2 * Copyright 2015, Dario Casalinuovo
3 * Copyright 2004, 2006, Jérôme Duval.
4 * Copyright 2003-2004, Andrew Bachmann.
5 * Copyright 2002-2004, 2006 Marcus Overhagen.
6 * Copyright 2002, Eric Jaessler.
7 * All rights reserved. Distributed under the terms of the MIT license.
11 #include <MediaDefs.h>
13 #include <Application.h>
16 #include <IconUtils.h>
18 #include <MediaNode.h>
19 #include <MediaRoster.h>
21 #include <Notification.h>
28 #include "AddOnManager.h"
29 #include "DataExchange.h"
31 #include "MediaMisc.h"
34 #define META_DATA_MAX_SIZE (16 << 20)
35 #define META_DATA_AREA_MIN_SIZE 32000
37 #undef B_TRANSLATION_CONTEXT
38 #define B_TRANSLATION_CONTEXT "MediaDefs"
41 // #pragma mark - media_destination
44 media_destination::media_destination(port_id port
, int32 id
)
52 media_destination::media_destination(const media_destination
& clone
)
61 media_destination::operator=(const media_destination
& clone
)
69 media_destination::media_destination()
77 media_destination::~media_destination()
82 media_destination
media_destination::null(-1, -1);
85 // #pragma mark - media_source
88 media_source::media_source(port_id port
,
97 media_source::media_source(const media_source
& clone
)
106 media_source::operator=(const media_source
& clone
)
114 media_source::media_source()
122 media_source::~media_source()
127 media_source
media_source::null(-1, -1);
134 operator==(const media_destination
& a
, const media_destination
& b
)
136 return a
.port
== b
.port
&& a
.id
== b
.id
;
141 operator!=(const media_destination
& a
, const media_destination
& b
)
143 return a
.port
!= b
.port
|| a
.id
!= b
.id
;
148 operator<(const media_destination
& a
, const media_destination
& b
)
156 operator==(const media_source
& a
, const media_source
& b
)
158 return a
.port
== b
.port
&& a
.id
== b
.id
;
163 operator!=(const media_source
& a
, const media_source
& b
)
165 return a
.port
!= b
.port
|| a
.id
!= b
.id
;
170 operator<(const media_source
& a
, const media_source
& b
)
178 operator==(const media_node
& a
, const media_node
& b
)
180 return a
.node
== b
.node
&& a
.port
== b
.port
&& a
.kind
== b
.kind
;
185 operator!=(const media_node
& a
, const media_node
& b
)
187 return a
.node
!= b
.node
|| a
.port
!= b
.port
|| a
.kind
!= b
.kind
;
192 operator<(const media_node
& a
, const media_node
& b
)
202 media_multi_audio_format
media_raw_audio_format::wildcard
;
204 media_multi_audio_format
media_multi_audio_format::wildcard
;
206 media_encoded_audio_format
media_encoded_audio_format::wildcard
= {{0}};
208 media_video_display_info
media_video_display_info::wildcard
= {(color_space
)0};
210 media_raw_video_format
media_raw_video_format::wildcard
= {0};
212 media_encoded_video_format
media_encoded_video_format::wildcard
= {{0}};
214 media_multistream_format
media_multistream_format::wildcard
= {0};
217 // #pragma mark - media_format::Matches() support
221 raw_audio_format_matches(const media_raw_audio_format
& a
,
222 const media_raw_audio_format
& b
)
224 if (a
.frame_rate
!= 0 && b
.frame_rate
!= 0 && a
.frame_rate
!= b
.frame_rate
)
226 if (a
.channel_count
!= 0 && b
.channel_count
!= 0
227 && a
.channel_count
!= b
.channel_count
) {
230 if (a
.format
!= 0 && b
.format
!= 0 && a
.format
!= b
.format
)
232 if (a
.byte_order
!= 0 && b
.byte_order
!= 0 && a
.byte_order
!= b
.byte_order
)
234 if (a
.buffer_size
!= 0 && b
.buffer_size
!= 0
235 && a
.buffer_size
!= b
.buffer_size
) {
238 if (a
.frame_rate
!= 0 && b
.frame_rate
!= 0 && a
.frame_rate
!= b
.frame_rate
)
245 multi_audio_info_matches(const media_multi_audio_info
& a
,
246 const media_multi_audio_info
& b
)
248 if (a
.channel_mask
!= 0 && b
.channel_mask
!= 0
249 && a
.channel_mask
!= b
.channel_mask
) {
252 if (a
.valid_bits
!= 0 && b
.valid_bits
!= 0 && a
.valid_bits
!= b
.valid_bits
)
254 if (a
.matrix_mask
!= 0 && b
.matrix_mask
!= 0
255 && a
.matrix_mask
!= b
.matrix_mask
) {
263 multi_audio_format_matches(const media_multi_audio_format
& a
,
264 const media_multi_audio_format
& b
)
266 return raw_audio_format_matches(a
, b
) && multi_audio_info_matches(a
, b
);
271 raw_video_format_matches(const media_raw_video_format
& a
,
272 const media_raw_video_format
& b
)
274 if (a
.field_rate
!= 0 && b
.field_rate
!= 0
275 && a
.field_rate
!= b
.field_rate
) {
278 if (a
.interlace
!= 0 && b
.interlace
!= 0
279 && a
.interlace
!= b
.interlace
) {
282 if (a
.first_active
!= 0 && b
.first_active
!= 0
283 && a
.first_active
!= b
.first_active
) {
286 if (a
.last_active
!= 0 && b
.last_active
!= 0
287 && a
.last_active
!= b
.last_active
) {
290 if (a
.orientation
!= 0 && b
.orientation
!= 0
291 && a
.orientation
!= b
.orientation
) {
294 if (a
.pixel_width_aspect
!= 0 && b
.pixel_width_aspect
!= 0
295 && a
.pixel_width_aspect
!= b
.pixel_width_aspect
) {
298 if (a
.pixel_height_aspect
!= 0 && b
.pixel_height_aspect
!= 0
299 && a
.pixel_height_aspect
!= b
.pixel_height_aspect
) {
302 if (a
.display
.format
!= 0 && b
.display
.format
!= 0
303 && a
.display
.format
!= b
.display
.format
) {
306 if (a
.display
.line_width
!= 0 && b
.display
.line_width
!= 0
307 && a
.display
.line_width
!= b
.display
.line_width
) {
310 if (a
.display
.line_count
!= 0 && b
.display
.line_count
!= 0
311 && a
.display
.line_count
!= b
.display
.line_count
) {
314 if (a
.display
.bytes_per_row
!= 0 && b
.display
.bytes_per_row
!= 0
315 && a
.display
.bytes_per_row
!= b
.display
.bytes_per_row
) {
318 if (a
.display
.pixel_offset
!= 0 && b
.display
.pixel_offset
!= 0
319 && a
.display
.pixel_offset
!= b
.display
.pixel_offset
) {
322 if (a
.display
.line_offset
!= 0 && b
.display
.line_offset
!= 0
323 && a
.display
.line_offset
!= b
.display
.line_offset
) {
326 if (a
.display
.flags
!= 0 && b
.display
.flags
!= 0
327 && a
.display
.flags
!= b
.display
.flags
) {
336 multistream_format_matches(const media_multistream_format
& a
,
337 const media_multistream_format
& b
)
339 if (a
.avg_bit_rate
!= 0 && b
.avg_bit_rate
!= 0
340 && a
.avg_bit_rate
!= b
.avg_bit_rate
) {
343 if (a
.max_bit_rate
!= 0 && b
.max_bit_rate
!= 0
344 && a
.max_bit_rate
!= b
.max_bit_rate
) {
347 if (a
.avg_chunk_size
!= 0 && b
.avg_chunk_size
!= 0
348 && a
.avg_chunk_size
!= b
.avg_chunk_size
) {
351 if (a
.max_chunk_size
!= 0 && b
.max_chunk_size
!= 0
352 && a
.max_chunk_size
!= b
.max_chunk_size
) {
355 if (a
.flags
!= 0 && b
.flags
!= 0 && a
.flags
!= b
.flags
)
357 if (a
.format
!= 0 && b
.format
!= 0 && a
.format
!= b
.format
)
360 if (a
.format
== 0 && b
.format
== 0) {
361 // TODO: How do we compare two formats with no type?
365 switch ((a
.format
!= 0) ? a
.format
: b
.format
) {
367 return true; // TODO: really?
369 case media_multistream_format::B_VID
:
370 if (a
.u
.vid
.frame_rate
!= 0 && b
.u
.vid
.frame_rate
!= 0
371 && a
.u
.vid
.frame_rate
!= b
.u
.vid
.frame_rate
) {
374 if (a
.u
.vid
.width
!= 0 && b
.u
.vid
.width
!= 0
375 && a
.u
.vid
.width
!= b
.u
.vid
.width
) {
378 if (a
.u
.vid
.height
!= 0 && b
.u
.vid
.height
!= 0
379 && a
.u
.vid
.height
!= b
.u
.vid
.height
) {
382 if (a
.u
.vid
.space
!= 0 && b
.u
.vid
.space
!= 0
383 && a
.u
.vid
.space
!= b
.u
.vid
.space
) {
386 if (a
.u
.vid
.sampling_rate
!= 0 && b
.u
.vid
.sampling_rate
!= 0
387 && a
.u
.vid
.sampling_rate
!= b
.u
.vid
.sampling_rate
) {
390 if (a
.u
.vid
.sample_format
!= 0 && b
.u
.vid
.sample_format
!= 0
391 && a
.u
.vid
.sample_format
!= b
.u
.vid
.sample_format
) {
394 if (a
.u
.vid
.byte_order
!= 0 && b
.u
.vid
.byte_order
!= 0
395 && a
.u
.vid
.byte_order
!= b
.u
.vid
.byte_order
) {
398 if (a
.u
.vid
.channel_count
!= 0 && b
.u
.vid
.channel_count
!= 0
399 && a
.u
.vid
.channel_count
!= b
.u
.vid
.channel_count
) {
404 case media_multistream_format::B_AVI
:
405 if (a
.u
.avi
.us_per_frame
!= 0 && b
.u
.avi
.us_per_frame
!= 0
406 && a
.u
.avi
.us_per_frame
!= b
.u
.avi
.us_per_frame
) {
409 if (a
.u
.avi
.width
!= 0 && b
.u
.avi
.width
!= 0
410 && a
.u
.avi
.width
!= b
.u
.avi
.width
) {
413 if (a
.u
.avi
.height
!= 0 && b
.u
.avi
.height
!= 0
414 && a
.u
.avi
.height
!= b
.u
.avi
.height
) {
417 if (a
.u
.avi
.type_count
!= 0 && b
.u
.avi
.type_count
!= 0
418 && a
.u
.avi
.type_count
!= b
.u
.avi
.type_count
) {
421 if (a
.u
.avi
.types
[0] != 0 && b
.u
.avi
.types
[0] != 0
422 && a
.u
.avi
.types
[0] != b
.u
.avi
.types
[0]) {
425 if (a
.u
.avi
.types
[1] != 0 && b
.u
.avi
.types
[1] != 0
426 && a
.u
.avi
.types
[1] != b
.u
.avi
.types
[1]) {
429 if (a
.u
.avi
.types
[2] != 0 && b
.u
.avi
.types
[2] != 0
430 && a
.u
.avi
.types
[2] != b
.u
.avi
.types
[2]) {
433 if (a
.u
.avi
.types
[3] != 0 && b
.u
.avi
.types
[3] != 0
434 && a
.u
.avi
.types
[3] != b
.u
.avi
.types
[3]) {
437 if (a
.u
.avi
.types
[4] != 0 && b
.u
.avi
.types
[4] != 0
438 && a
.u
.avi
.types
[4] != b
.u
.avi
.types
[4]) {
447 encoded_audio_format_matches(const media_encoded_audio_format
& a
,
448 const media_encoded_audio_format
& b
)
450 if (!raw_audio_format_matches(a
.output
, b
.output
))
452 if (a
.encoding
!= 0 && b
.encoding
!= 0 && a
.encoding
!= b
.encoding
)
454 if (a
.bit_rate
!= 0 && b
.bit_rate
!= 0 && a
.bit_rate
!= b
.bit_rate
)
456 if (a
.frame_size
!= 0 && b
.frame_size
!= 0 && a
.frame_size
!= b
.frame_size
)
458 if (!multi_audio_info_matches(a
.multi_info
, b
.multi_info
))
461 if (a
.encoding
== 0 && b
.encoding
== 0)
462 return true; // can't compare
464 switch((a
.encoding
!= 0) ? a
.encoding
: b
.encoding
) {
465 case media_encoded_audio_format::B_ANY
:
473 encoded_video_format_matches(const media_encoded_video_format
& a
,
474 const media_encoded_video_format
& b
)
476 if (!raw_video_format_matches(a
.output
, b
.output
))
478 if (a
.encoding
!= 0 && b
.encoding
!= 0 && a
.encoding
!= b
.encoding
)
481 if (a
.avg_bit_rate
!= 0 && b
.avg_bit_rate
!= 0
482 && a
.avg_bit_rate
!= b
.avg_bit_rate
) {
485 if (a
.max_bit_rate
!= 0 && b
.max_bit_rate
!= 0
486 && a
.max_bit_rate
!= b
.max_bit_rate
) {
489 if (a
.frame_size
!= 0 && b
.frame_size
!= 0
490 && a
.frame_size
!= b
.frame_size
) {
493 if (a
.forward_history
!= 0 && b
.forward_history
!= 0
494 && a
.forward_history
!= b
.forward_history
) {
497 if (a
.backward_history
!= 0 && b
.backward_history
!= 0
498 && a
.backward_history
!= b
.backward_history
) {
502 if (a
.encoding
== 0 && b
.encoding
== 0)
503 return true; // can't compare
505 switch((a
.encoding
!= 0) ? a
.encoding
: b
.encoding
) {
506 case media_encoded_video_format::B_ANY
:
513 // #pragma mark - media_format::SpecializeTo() support
517 raw_audio_format_specialize(media_raw_audio_format
* format
,
518 const media_raw_audio_format
* other
)
520 if (format
->frame_rate
== 0)
521 format
->frame_rate
= other
->frame_rate
;
522 if (format
->channel_count
== 0)
523 format
->channel_count
= other
->channel_count
;
524 if (format
->format
== 0)
525 format
->format
= other
->format
;
526 if (format
->byte_order
== 0)
527 format
->byte_order
= other
->byte_order
;
528 if (format
->buffer_size
== 0)
529 format
->buffer_size
= other
->buffer_size
;
530 if (format
->frame_rate
== 0)
531 format
->frame_rate
= other
->frame_rate
;
536 multi_audio_info_specialize(media_multi_audio_info
* format
,
537 const media_multi_audio_info
* other
)
539 if (format
->channel_mask
== 0)
540 format
->channel_mask
= other
->channel_mask
;
541 if (format
->valid_bits
== 0)
542 format
->valid_bits
= other
->valid_bits
;
543 if (format
->matrix_mask
== 0)
544 format
->matrix_mask
= other
->matrix_mask
;
549 multi_audio_format_specialize(media_multi_audio_format
* format
,
550 const media_multi_audio_format
* other
)
552 raw_audio_format_specialize(format
, other
);
553 multi_audio_info_specialize(format
, other
);
558 raw_video_format_specialize(media_raw_video_format
* format
,
559 const media_raw_video_format
* other
)
561 if (format
->field_rate
== 0)
562 format
->field_rate
= other
->field_rate
;
563 if (format
->interlace
== 0)
564 format
->interlace
= other
->interlace
;
565 if (format
->first_active
== 0)
566 format
->first_active
= other
->first_active
;
567 if (format
->last_active
== 0)
568 format
->last_active
= other
->last_active
;
569 if (format
->orientation
== 0)
570 format
->orientation
= other
->orientation
;
571 if (format
->pixel_width_aspect
== 0)
572 format
->pixel_width_aspect
= other
->pixel_width_aspect
;
573 if (format
->pixel_height_aspect
== 0)
574 format
->pixel_height_aspect
= other
->pixel_height_aspect
;
575 if (format
->display
.format
== 0)
576 format
->display
.format
= other
->display
.format
;
577 if (format
->display
.line_width
== 0)
578 format
->display
.line_width
= other
->display
.line_width
;
579 if (format
->display
.line_count
== 0)
580 format
->display
.line_count
= other
->display
.line_count
;
581 if (format
->display
.bytes_per_row
== 0)
582 format
->display
.bytes_per_row
= other
->display
.bytes_per_row
;
583 if (format
->display
.pixel_offset
== 0)
584 format
->display
.pixel_offset
= other
->display
.pixel_offset
;
585 if (format
->display
.line_offset
== 0)
586 format
->display
.line_offset
= other
->display
.line_offset
;
587 if (format
->display
.flags
== 0)
588 format
->display
.flags
= other
->display
.flags
;
593 multistream_format_specialize(media_multistream_format
* format
,
594 const media_multistream_format
* other
)
596 if (format
->avg_bit_rate
== 0)
597 format
->avg_bit_rate
= other
->avg_bit_rate
;
598 if (format
->max_bit_rate
== 0)
599 format
->max_bit_rate
= other
->max_bit_rate
;
600 if (format
->avg_chunk_size
== 0)
601 format
->avg_chunk_size
= other
->avg_chunk_size
;
602 if (format
->max_chunk_size
== 0)
603 format
->max_chunk_size
= other
->max_chunk_size
;
604 if (format
->flags
== 0)
605 format
->flags
= other
->flags
;
606 if (format
->format
== 0)
607 format
->format
= other
->format
;
609 switch (format
->format
) {
610 case media_multistream_format::B_VID
:
611 if (format
->u
.vid
.frame_rate
== 0)
612 format
->u
.vid
.frame_rate
= other
->u
.vid
.frame_rate
;
613 if (format
->u
.vid
.width
== 0)
614 format
->u
.vid
.width
= other
->u
.vid
.width
;
615 if (format
->u
.vid
.height
== 0)
616 format
->u
.vid
.height
= other
->u
.vid
.height
;
617 if (format
->u
.vid
.space
== 0)
618 format
->u
.vid
.space
= other
->u
.vid
.space
;
619 if (format
->u
.vid
.sampling_rate
== 0)
620 format
->u
.vid
.sampling_rate
= other
->u
.vid
.sampling_rate
;
621 if (format
->u
.vid
.sample_format
== 0)
622 format
->u
.vid
.sample_format
= other
->u
.vid
.sample_format
;
623 if (format
->u
.vid
.byte_order
== 0)
624 format
->u
.vid
.byte_order
= other
->u
.vid
.byte_order
;
625 if (format
->u
.vid
.channel_count
== 0)
626 format
->u
.vid
.channel_count
= other
->u
.vid
.channel_count
;
629 case media_multistream_format::B_AVI
:
630 if (format
->u
.avi
.us_per_frame
== 0)
631 format
->u
.avi
.us_per_frame
= other
->u
.avi
.us_per_frame
;
632 if (format
->u
.avi
.width
== 0)
633 format
->u
.avi
.width
= other
->u
.avi
.width
;
634 if (format
->u
.avi
.height
== 0)
635 format
->u
.avi
.height
= other
->u
.avi
.height
;
636 if (format
->u
.avi
.type_count
== 0)
637 format
->u
.avi
.type_count
= other
->u
.avi
.type_count
;
638 if (format
->u
.avi
.types
[0] == 0)
639 format
->u
.avi
.types
[0] = other
->u
.avi
.types
[0];
640 if (format
->u
.avi
.types
[1] == 0)
641 format
->u
.avi
.types
[1] = other
->u
.avi
.types
[1];
642 if (format
->u
.avi
.types
[2] == 0)
643 format
->u
.avi
.types
[2] = other
->u
.avi
.types
[2];
644 if (format
->u
.avi
.types
[3] == 0)
645 format
->u
.avi
.types
[3] = other
->u
.avi
.types
[3];
646 if (format
->u
.avi
.types
[4] == 0)
647 format
->u
.avi
.types
[4] = other
->u
.avi
.types
[4];
651 ERROR("media_format::SpecializeTo can't specialize "
652 "media_multistream_format of format %" B_PRId32
"\n",
659 encoded_audio_format_specialize(media_encoded_audio_format
* format
,
660 const media_encoded_audio_format
* other
)
662 raw_audio_format_specialize(&format
->output
, &other
->output
);
663 if (format
->encoding
== 0)
664 format
->encoding
= other
->encoding
;
665 if (format
->bit_rate
== 0)
666 format
->bit_rate
= other
->bit_rate
;
667 if (format
->frame_size
== 0)
668 format
->frame_size
= other
->frame_size
;
669 multi_audio_info_specialize(&format
->multi_info
, &other
->multi_info
);
674 encoded_video_format_specialize(media_encoded_video_format
* format
,
675 const media_encoded_video_format
* other
)
677 raw_video_format_specialize(&format
->output
, &other
->output
);
678 if (format
->avg_bit_rate
== 0)
679 format
->avg_bit_rate
= other
->avg_bit_rate
;
680 if (format
->max_bit_rate
== 0)
681 format
->max_bit_rate
= other
->max_bit_rate
;
682 if (format
->encoding
== 0)
683 format
->encoding
= other
->encoding
;
684 if (format
->frame_size
== 0)
685 format
->frame_size
= other
->frame_size
;
686 if (format
->forward_history
== 0)
687 format
->forward_history
= other
->forward_history
;
688 if (format
->backward_history
== 0)
689 format
->backward_history
= other
->backward_history
;
693 // #pragma mark - media_format
697 media_format::Matches(const media_format
* other
) const
701 if (type
== 0 && other
->type
== 0) {
702 // TODO: How do we compare two formats with no type?
706 if (type
!= 0 && other
->type
!= 0 && type
!= other
->type
)
709 switch ((type
!= 0) ? type
: other
->type
) {
710 case B_MEDIA_RAW_AUDIO
:
711 return multi_audio_format_matches(u
.raw_audio
, other
->u
.raw_audio
);
713 case B_MEDIA_RAW_VIDEO
:
714 return raw_video_format_matches(u
.raw_video
, other
->u
.raw_video
);
716 case B_MEDIA_MULTISTREAM
:
717 return multistream_format_matches(u
.multistream
,
718 other
->u
.multistream
);
720 case B_MEDIA_ENCODED_AUDIO
:
721 return encoded_audio_format_matches(u
.encoded_audio
,
722 other
->u
.encoded_audio
);
724 case B_MEDIA_ENCODED_VIDEO
:
725 return encoded_video_format_matches(u
.encoded_video
,
726 other
->u
.encoded_video
);
729 return true; // TODO: really?
735 media_format::SpecializeTo(const media_format
* otherFormat
)
739 if (type
== 0 && otherFormat
->type
== 0) {
740 ERROR("media_format::SpecializeTo can't specialize wildcard to other "
741 "wildcard format\n");
746 type
= otherFormat
->type
;
749 case B_MEDIA_RAW_AUDIO
:
750 multi_audio_format_specialize(&u
.raw_audio
,
751 &otherFormat
->u
.raw_audio
);
754 case B_MEDIA_RAW_VIDEO
:
755 raw_video_format_specialize(&u
.raw_video
,
756 &otherFormat
->u
.raw_video
);
759 case B_MEDIA_MULTISTREAM
:
760 multistream_format_specialize(&u
.multistream
,
761 &otherFormat
->u
.multistream
);
764 case B_MEDIA_ENCODED_AUDIO
:
765 encoded_audio_format_specialize(&u
.encoded_audio
,
766 &otherFormat
->u
.encoded_audio
);
769 case B_MEDIA_ENCODED_VIDEO
:
770 encoded_video_format_specialize(&u
.encoded_video
,
771 &otherFormat
->u
.encoded_video
);
775 ERROR("media_format::SpecializeTo can't specialize format "
782 media_format::SetMetaData(const void* data
, size_t size
)
784 if (!data
|| size
< 0 || size
> META_DATA_MAX_SIZE
)
789 if (size
< META_DATA_AREA_MIN_SIZE
) {
790 new_area
= B_BAD_VALUE
;
791 new_addr
= malloc(size
);
795 new_area
= create_area("meta_data_area", &new_addr
, B_ANY_ADDRESS
,
796 ROUND_UP_TO_PAGE(size
), B_NO_LOCK
, B_READ_AREA
| B_WRITE_AREA
);
798 return (status_t
)new_area
;
801 if (meta_data_area
> 0)
802 delete_area(meta_data_area
);
806 meta_data
= new_addr
;
807 meta_data_size
= size
;
808 meta_data_area
= new_area
;
810 memcpy(meta_data
, data
, size
);
812 if (meta_data_area
> 0)
813 set_area_protection(meta_data_area
, B_READ_AREA
);
820 media_format::MetaData() const
827 media_format::MetaDataSize() const
829 return meta_data_size
;
833 media_format::media_format()
835 memset(this, 0x00, sizeof(*this));
836 meta_data_area
= B_BAD_VALUE
;
840 media_format::media_format(const media_format
& other
)
842 memset(this, 0x00, sizeof(*this));
843 meta_data_area
= B_BAD_VALUE
;
848 media_format::~media_format()
850 if (meta_data_area
> 0)
851 delete_area(meta_data_area
);
859 media_format::operator=(const media_format
& clone
)
861 // get rid of this format's meta data
862 this->~media_format();
863 // danger: using only ~media_format() would call the constructor
865 // make a binary copy
866 memcpy(this, &clone
, sizeof(*this));
867 // some binary copies are invalid:
869 meta_data_area
= B_BAD_VALUE
;
871 // clone or copy the meta data
872 if (clone
.meta_data
) {
873 if (clone
.meta_data_area
!= B_BAD_VALUE
) {
874 meta_data_area
= clone_area("meta_data_clone_area", &meta_data
,
875 B_ANY_ADDRESS
, B_READ_AREA
, clone
.meta_data_area
);
876 if (meta_data_area
< 0) {
877 // whoops, we just lost our meta data
882 meta_data
= malloc(meta_data_size
);
884 memcpy(meta_data
, clone
.meta_data
, meta_data_size
);
886 // whoops, we just lost our meta data
899 operator==(const media_raw_audio_format
& a
, const media_raw_audio_format
& b
)
901 return a
.frame_rate
== b
.frame_rate
902 && a
.channel_count
== b
.channel_count
903 && a
.format
== b
.format
904 && a
.byte_order
== b
.byte_order
905 && a
.buffer_size
== b
.buffer_size
;
910 operator==(const media_multi_audio_info
& a
, const media_multi_audio_info
& b
)
912 return a
.channel_mask
== b
.channel_mask
913 && a
.valid_bits
== b
.valid_bits
914 && a
.matrix_mask
== b
.matrix_mask
;
919 operator==(const media_multi_audio_format
& a
,
920 const media_multi_audio_format
& b
)
922 return (media_raw_audio_format
)a
== (media_raw_audio_format
)b
923 && (media_multi_audio_info
)a
== (media_multi_audio_info
)b
;
928 operator==(const media_encoded_audio_format
& a
,
929 const media_encoded_audio_format
& b
)
931 return a
.output
== b
.output
932 && a
.encoding
== b
.encoding
933 && a
.bit_rate
== b
.bit_rate
934 && a
.frame_size
== b
.frame_size
935 && a
.multi_info
== b
.multi_info
;
940 operator==(const media_video_display_info
& a
,
941 const media_video_display_info
& b
)
943 return a
.format
== b
.format
944 && a
.line_width
== b
.line_width
945 && a
.line_count
== b
.line_count
946 && a
.bytes_per_row
== b
.bytes_per_row
947 && a
.pixel_offset
== b
.pixel_offset
948 && a
.line_offset
== b
.line_offset
949 && a
.flags
== b
.flags
;
954 operator==(const media_raw_video_format
& a
, const media_raw_video_format
& b
)
956 return a
.field_rate
== b
.field_rate
957 && a
.interlace
== b
.interlace
958 && a
.first_active
== b
.first_active
959 && a
.last_active
== b
.last_active
960 && a
.orientation
== b
.orientation
961 && a
.pixel_width_aspect
== b
.pixel_width_aspect
962 && a
.pixel_height_aspect
== b
.pixel_height_aspect
963 && a
.display
== b
.display
;
968 operator==(const media_encoded_video_format
& a
,
969 const media_encoded_video_format
& b
)
971 return a
.output
== b
.output
972 && a
.avg_bit_rate
== b
.avg_bit_rate
973 && a
.max_bit_rate
== b
.max_bit_rate
974 && a
.encoding
== b
.encoding
975 && a
.frame_size
== b
.frame_size
976 && a
.forward_history
== b
.forward_history
977 && a
.backward_history
== b
.backward_history
;
982 operator==(const media_multistream_format::vid_info
& a
,
983 const media_multistream_format::vid_info
& b
)
985 return a
.frame_rate
== b
.frame_rate
986 && a
.width
== b
.width
987 && a
.height
== b
.height
988 && a
.space
== b
.space
989 && a
.sampling_rate
== b
.sampling_rate
990 && a
.sample_format
== b
.sample_format
991 && a
.byte_order
== b
.byte_order
992 && a
.channel_count
== b
.channel_count
;
997 operator==(const media_multistream_format::avi_info
& a
,
998 const media_multistream_format::avi_info
& b
)
1000 return a
.us_per_frame
== b
.us_per_frame
1001 && a
.width
== b
.width
1002 && a
.height
== b
.height
1003 && a
.type_count
== b
.type_count
1004 && a
.types
[0] == b
.types
[0]
1005 && a
.types
[1] == b
.types
[1]
1006 && a
.types
[2] == b
.types
[2]
1007 && a
.types
[3] == b
.types
[3]
1008 && a
.types
[4] == b
.types
[4];
1013 operator==(const media_multistream_format
& a
,
1014 const media_multistream_format
& b
)
1016 if (a
.avg_bit_rate
!= b
.avg_bit_rate
1017 || a
.max_bit_rate
!= b
.max_bit_rate
1018 || a
.avg_chunk_size
!= b
.avg_chunk_size
1019 || a
.max_chunk_size
!= b
.max_chunk_size
1020 || a
.format
!= b
.format
1021 || a
.flags
!= b
.flags
) {
1026 case media_multistream_format::B_VID
:
1027 return a
.u
.vid
== b
.u
.vid
;
1029 case media_multistream_format::B_AVI
:
1030 return a
.u
.avi
== b
.u
.avi
;
1033 return true; // TODO: really?
1039 operator==(const media_format
& a
, const media_format
& b
)
1041 if (a
.type
!= b
.type
1042 || a
.user_data_type
!= b
.user_data_type
1043 // TODO: compare user_data[48] ?
1044 || a
.require_flags
!= b
.require_flags
1045 || a
.deny_flags
!= b
.deny_flags
) {
1050 case B_MEDIA_RAW_AUDIO
:
1051 return a
.u
.raw_audio
== b
.u
.raw_audio
;
1053 case B_MEDIA_RAW_VIDEO
:
1054 return a
.u
.raw_video
== b
.u
.raw_video
;
1056 case B_MEDIA_MULTISTREAM
:
1057 return a
.u
.multistream
== b
.u
.multistream
;
1059 case B_MEDIA_ENCODED_AUDIO
:
1060 return a
.u
.encoded_audio
== b
.u
.encoded_audio
;
1062 case B_MEDIA_ENCODED_VIDEO
:
1063 return a
.u
.encoded_video
== b
.u
.encoded_video
;
1066 return true; // TODO: really?
1074 /*! return \c true if a and b are compatible (accounting for wildcards)
1075 a is the format you want to feed to something accepting b
1078 format_is_compatible(const media_format
& a
, const media_format
& b
)
1080 return a
.Matches(&b
);
1085 string_for_format(const media_format
& f
, char* buf
, size_t size
)
1087 char encoding
[10]; /* maybe Be wanted to use some 4CCs ? */
1088 const char* videoOrientation
= "0"; /* I'd use "NC", R5 uses 0. */
1093 case B_MEDIA_RAW_AUDIO
:
1095 "raw_audio;%g;%" B_PRIu32
";0x%" B_PRIx32
";%" B_PRIu32
";0x%"
1096 B_PRIxSIZE
";0x%#" B_PRIx32
";%d;0x%04x",
1097 f
.u
.raw_audio
.frame_rate
,
1098 f
.u
.raw_audio
.channel_count
,
1099 f
.u
.raw_audio
.format
,
1100 f
.u
.raw_audio
.byte_order
,
1101 f
.u
.raw_audio
.buffer_size
,
1102 f
.u
.raw_audio
.channel_mask
,
1103 f
.u
.raw_audio
.valid_bits
,
1104 f
.u
.raw_audio
.matrix_mask
);
1106 case B_MEDIA_RAW_VIDEO
:
1107 if (f
.u
.raw_video
.orientation
== B_VIDEO_TOP_LEFT_RIGHT
)
1108 videoOrientation
= "TopLR";
1109 else if (f
.u
.raw_video
.orientation
== B_VIDEO_BOTTOM_LEFT_RIGHT
)
1110 videoOrientation
= "BotLR";
1111 snprintf(buf
, size
, "raw_video;%g;0x%x;%" B_PRIu32
";%" B_PRIu32
";%"
1112 B_PRIu32
";%" B_PRIu32
";%s;%d;%d",
1113 f
.u
.raw_video
.field_rate
,
1114 f
.u
.raw_video
.display
.format
,
1115 f
.u
.raw_video
.interlace
,
1116 f
.u
.raw_video
.display
.line_width
,
1117 f
.u
.raw_video
.display
.line_count
,
1118 f
.u
.raw_video
.first_active
,
1120 f
.u
.raw_video
.pixel_width_aspect
,
1121 f
.u
.raw_video
.pixel_height_aspect
);
1123 case B_MEDIA_ENCODED_AUDIO
:
1124 snprintf(encoding
, 10, "%d", f
.u
.encoded_audio
.encoding
);
1126 "caudio;%s;%g;%ld;(%g;%" B_PRIu32
";0x%" B_PRIx32
";%" B_PRIu32
1127 ";0x%" B_PRIxSIZE
";0x%08" B_PRIx32
";%d;0x%04x)",
1129 f
.u
.encoded_audio
.bit_rate
,
1130 f
.u
.encoded_audio
.frame_size
,
1131 f
.u
.encoded_audio
.output
.frame_rate
,
1132 f
.u
.encoded_audio
.output
.channel_count
,
1133 f
.u
.encoded_audio
.output
.format
,
1134 f
.u
.encoded_audio
.output
.byte_order
,
1135 f
.u
.encoded_audio
.output
.buffer_size
,
1136 f
.u
.encoded_audio
.multi_info
.channel_mask
,
1137 f
.u
.encoded_audio
.multi_info
.valid_bits
,
1138 f
.u
.encoded_audio
.multi_info
.matrix_mask
);
1140 case B_MEDIA_ENCODED_VIDEO
:
1141 snprintf(encoding
, 10, "%d", f
.u
.encoded_video
.encoding
);
1142 if (f
.u
.encoded_video
.output
.orientation
== B_VIDEO_TOP_LEFT_RIGHT
)
1143 videoOrientation
= "TopLR";
1144 else if (f
.u
.encoded_video
.output
.orientation
== B_VIDEO_BOTTOM_LEFT_RIGHT
)
1145 videoOrientation
= "BotLR";
1147 "cvideo;%s;%g;%g;%" B_PRIuSIZE
";(%g;0x%x;%" B_PRIu32
";%" B_PRIu32
1148 ";%" B_PRIu32
";%" B_PRIu32
";%s;%d;%d)",
1150 f
.u
.encoded_video
.avg_bit_rate
,
1151 f
.u
.encoded_video
.max_bit_rate
,
1152 f
.u
.encoded_video
.frame_size
,
1153 f
.u
.encoded_video
.output
.field_rate
,
1154 f
.u
.encoded_video
.output
.display
.format
,
1155 f
.u
.encoded_video
.output
.interlace
,
1156 f
.u
.encoded_video
.output
.display
.line_width
,
1157 f
.u
.encoded_video
.output
.display
.line_count
,
1158 f
.u
.encoded_video
.output
.first_active
,
1160 f
.u
.encoded_video
.output
.pixel_width_aspect
,
1161 f
.u
.encoded_video
.output
.pixel_height_aspect
);
1164 snprintf(buf
, size
, "%d-", f
.type
);
1165 unsigned char* p
= (unsigned char*)&(f
.u
);
1166 size
-= strlen(buf
);
1168 for (int i
= 0; (size
> 2) && (i
< 96); i
++) {
1169 snprintf(buf
, 3, "%2.2x", *(p
+ i
));
1183 operator==(const media_file_format_id
& a
, const media_file_format_id
& b
)
1185 return a
.node
== b
.node
&& a
.device
== b
.device
1186 && a
.internal_id
== b
.internal_id
;
1191 operator<(const media_file_format_id
& a
, const media_file_format_id
& b
)
1193 return a
.internal_id
< b
.internal_id
;
1200 //! Use this function to iterate through available file format writers.
1202 get_next_file_format(int32
* cookie
, media_file_format
* mff
)
1204 if (cookie
== NULL
|| mff
== NULL
)
1207 status_t ret
= AddOnManager::GetInstance()->GetFileFormat(mff
, *cookie
);
1211 *cookie
= *cookie
+ 1;
1221 const char* B_MEDIA_SERVER_SIGNATURE
= "application/x-vnd.Be.media-server";
1222 const char* B_MEDIA_ADDON_SERVER_SIGNATURE
= "application/x-vnd.Be.addon-host";
1224 const type_code B_CODEC_TYPE_INFO
= 0x040807b2;
1230 // shutdown_media_server() and launch_media_server()
1231 // are provided by libbe.so in BeOS R5
1233 #define MEDIA_SERVICE_NOTIFICATION_ID "MediaServiceNotificationID"
1237 notify_system(float progress
, const char* message
)
1239 BNotification
notification(B_PROGRESS_NOTIFICATION
);
1240 notification
.SetMessageID(MEDIA_SERVICE_NOTIFICATION_ID
);
1241 notification
.SetProgress(progress
);
1242 notification
.SetGroup(B_TRANSLATE("Media Service"));
1243 notification
.SetContent(message
);
1246 be_app
->GetAppInfo(&info
);
1247 BBitmap
icon(BRect(0, 0, 32, 32), B_RGBA32
);
1248 BNode
node(&info
.ref
);
1249 BIconUtils::GetVectorIcon(&node
, "BEOS:ICON", &icon
);
1250 notification
.SetIcon(&icon
);
1252 notification
.Send();
1257 progress_shutdown(int stage
,
1258 bool (*progress
)(int stage
, const char* message
, void* cookie
),
1261 // parameter "message" is no longer used. It is kept for compatibility with
1262 // BeOS as this is used as a shutdown_media_server callback.
1264 PRINT(("stage : %i\n", stage
));
1265 const char* string
= "Unknown stage";
1268 string
= B_TRANSLATE("Stopping media server" B_UTF8_ELLIPSIS
);
1271 string
= B_TRANSLATE("Telling media_addon_server to quit.");
1274 string
= B_TRANSLATE("Waiting for media_server to quit.");
1277 string
= B_TRANSLATE("Waiting for media_server to quit.");
1280 string
= B_TRANSLATE("Cleaning up.");
1283 string
= B_TRANSLATE("Done shutting down.");
1287 if (progress
== NULL
)
1288 notify_system(stage
, string
);
1290 progress(stage
, string
, cookie
);
1295 shutdown_media_server(bigtime_t timeout
,
1296 bool (*progress
)(int stage
, const char* message
, void* cookie
),
1299 BMessage
msg(B_QUIT_REQUESTED
);
1303 if ((err
= msg
.AddBool("be:_user_request", true)) != B_OK
)
1306 if (be_roster
->IsRunning(B_MEDIA_SERVER_SIGNATURE
)) {
1307 BMessenger
messenger(B_MEDIA_SERVER_SIGNATURE
);
1308 progress_shutdown(10, progress
, cookie
);
1310 err
= messenger
.SendMessage(&msg
, &reply
, 2000000, 2000000);
1315 if (reply
.FindInt32("error", &rv
) == B_OK
&& rv
!= B_OK
)
1319 if (be_roster
->IsRunning(B_MEDIA_ADDON_SERVER_SIGNATURE
)) {
1320 BMessenger
messenger(B_MEDIA_ADDON_SERVER_SIGNATURE
);
1321 progress_shutdown(20, progress
, cookie
);
1323 err
= messenger
.SendMessage(&msg
, &reply
, 2000000, 2000000);
1328 if (reply
.FindInt32("error", &rv
) == B_OK
&& rv
!= B_OK
)
1332 if (be_roster
->IsRunning(B_MEDIA_SERVER_SIGNATURE
)) {
1333 progress_shutdown(40, progress
, cookie
);
1337 if (be_roster
->IsRunning(B_MEDIA_ADDON_SERVER_SIGNATURE
)) {
1338 progress_shutdown(50, progress
, cookie
);
1342 progress_shutdown(70, progress
, cookie
);
1345 if (be_roster
->IsRunning(B_MEDIA_SERVER_SIGNATURE
)) {
1346 kill_team(be_roster
->TeamFor(B_MEDIA_SERVER_SIGNATURE
));
1349 if (be_roster
->IsRunning(B_MEDIA_ADDON_SERVER_SIGNATURE
)) {
1350 kill_team(be_roster
->TeamFor(B_MEDIA_ADDON_SERVER_SIGNATURE
));
1353 progress_shutdown(100, progress
, cookie
);
1361 progress_startup(int stage
,
1362 bool (*progress
)(int stage
, const char* message
, void* cookie
),
1365 // parameter "message" is no longer used. It is kept for compatibility with
1366 // BeOS as this is used as a shutdown_media_server callback.
1368 PRINT(("stage : %i\n", stage
));
1369 const char* string
= "Unknown stage";
1372 string
= B_TRANSLATE("Stopping media server" B_UTF8_ELLIPSIS
);
1375 string
= B_TRANSLATE("Telling media_addon_server to quit.");
1378 string
= B_TRANSLATE("Starting media_services.");
1381 string
= B_TRANSLATE("Error occurred starting media services.");
1384 string
= B_TRANSLATE("Ready for use.");
1388 if (progress
== NULL
)
1389 notify_system(stage
, string
);
1391 progress(stage
, string
, cookie
);
1396 launch_media_server(uint32 flags
)
1398 return launch_media_server(0, NULL
, NULL
, flags
);
1403 launch_media_server(bigtime_t timeout
,
1404 bool (*progress
)(int stage
, const char* message
, void* cookie
),
1405 void* cookie
, uint32 flags
)
1407 if (BMediaRoster::IsRunning())
1408 return B_ALREADY_RUNNING
;
1410 // The media_server crashed
1411 if (be_roster
->IsRunning(B_MEDIA_ADDON_SERVER_SIGNATURE
)) {
1412 progress_startup(10, progress
, cookie
);
1413 kill_team(be_roster
->TeamFor(B_MEDIA_ADDON_SERVER_SIGNATURE
));
1417 // The media_addon_server crashed
1418 if (be_roster
->IsRunning(B_MEDIA_SERVER_SIGNATURE
)) {
1419 progress_startup(20, progress
, cookie
);
1420 kill_team(be_roster
->TeamFor(B_MEDIA_SERVER_SIGNATURE
));
1424 progress_startup(50, progress
, cookie
);
1426 status_t err
= be_roster
->Launch(B_MEDIA_SERVER_SIGNATURE
);
1430 err
= B_MEDIA_SYSTEM_FAILURE
;
1431 for (int i
= 0; i
< 15; i
++) {
1434 BMessage
msg(1); // this is a hack
1436 BMessenger
messenger(B_MEDIA_ADDON_SERVER_SIGNATURE
);
1438 if (messenger
.IsValid()) {
1439 messenger
.SendMessage(&msg
, &reply
, 2000000, 2000000);
1441 progress_startup(100, progress
, cookie
);
1447 progress_startup(90, progress
, cookie
);
1456 // Given an image_id, prepare that image_id for realtime media
1457 // If the kind of media indicated by "flags" is not enabled for real-time,
1458 // B_MEDIA_REALTIME_DISABLED is returned.
1459 // If there are not enough system resources to enable real-time performance,
1460 // B_MEDIA_REALTIME_UNAVAILABLE is returned.
1462 media_realtime_init_image(image_id image
, uint32 flags
)
1468 // Given a thread ID, and an optional indication of what the thread is
1469 // doing in "flags", prepare the thread for real-time media performance.
1470 // Currently, this means locking the thread stack, up to size_used bytes,
1471 // or all of it if 0 is passed. Typically, you will not be using all
1472 // 256 kB of the stack, so you should pass some smaller value you determine
1473 // from profiling the thread; typically in the 32-64kB range.
1474 // Return values are the same as for media_prepare_realtime_image().
1476 media_realtime_init_thread(thread_id thread
, size_t stack_used
, uint32 flags
)
1483 // #pragma mark - media_encode_info
1486 media_encode_info::media_encode_info()
1491 time_to_encode
= INT64_MAX
;
1492 file_format_data
= NULL
;
1493 file_format_data_size
= 0;
1495 codec_data_size
= 0;
1499 media_decode_info::media_decode_info()
1501 time_to_decode
= INT64_MAX
;
1502 file_format_data
= NULL
;
1503 file_format_data_size
= 0;
1505 codec_data_size
= 0;