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>
17 #include <LaunchRoster.h>
19 #include <MediaNode.h>
20 #include <MediaRoster.h>
22 #include <Notification.h>
29 #include "AddOnManager.h"
30 #include "DataExchange.h"
32 #include "MediaMisc.h"
33 #include "MediaRosterEx.h"
36 #define META_DATA_MAX_SIZE (16 << 20)
37 #define META_DATA_AREA_MIN_SIZE 32000
39 #undef B_TRANSLATION_CONTEXT
40 #define B_TRANSLATION_CONTEXT "MediaDefs"
43 // #pragma mark - media_destination
46 media_destination::media_destination(port_id port
, int32 id
)
54 media_destination::media_destination(const media_destination
& clone
)
63 media_destination::operator=(const media_destination
& clone
)
71 media_destination::media_destination()
79 media_destination::~media_destination()
84 media_destination
media_destination::null(-1, -1);
87 // #pragma mark - media_source
90 media_source::media_source(port_id port
,
99 media_source::media_source(const media_source
& clone
)
108 media_source::operator=(const media_source
& clone
)
116 media_source::media_source()
124 media_source::~media_source()
129 media_source
media_source::null(-1, -1);
136 operator==(const media_destination
& a
, const media_destination
& b
)
138 return a
.port
== b
.port
&& a
.id
== b
.id
;
143 operator!=(const media_destination
& a
, const media_destination
& b
)
145 return a
.port
!= b
.port
|| a
.id
!= b
.id
;
150 operator<(const media_destination
& a
, const media_destination
& b
)
158 operator==(const media_source
& a
, const media_source
& b
)
160 return a
.port
== b
.port
&& a
.id
== b
.id
;
165 operator!=(const media_source
& a
, const media_source
& b
)
167 return a
.port
!= b
.port
|| a
.id
!= b
.id
;
172 operator<(const media_source
& a
, const media_source
& b
)
180 operator==(const media_node
& a
, const media_node
& b
)
182 return a
.node
== b
.node
&& a
.port
== b
.port
&& a
.kind
== b
.kind
;
187 operator!=(const media_node
& a
, const media_node
& b
)
189 return a
.node
!= b
.node
|| a
.port
!= b
.port
|| a
.kind
!= b
.kind
;
194 operator<(const media_node
& a
, const media_node
& b
)
204 media_multi_audio_format
media_raw_audio_format::wildcard
;
206 media_multi_audio_format
media_multi_audio_format::wildcard
;
208 media_encoded_audio_format
media_encoded_audio_format::wildcard
= {{0}};
210 media_video_display_info
media_video_display_info::wildcard
= {(color_space
)0};
212 media_raw_video_format
media_raw_video_format::wildcard
= {0};
214 media_encoded_video_format
media_encoded_video_format::wildcard
= {{0}};
216 media_multistream_format
media_multistream_format::wildcard
= {0};
219 // #pragma mark - media_format::Matches() support
223 raw_audio_format_matches(const media_raw_audio_format
& a
,
224 const media_raw_audio_format
& b
)
226 if (a
.frame_rate
!= 0 && b
.frame_rate
!= 0 && a
.frame_rate
!= b
.frame_rate
)
228 if (a
.channel_count
!= 0 && b
.channel_count
!= 0
229 && a
.channel_count
!= b
.channel_count
) {
232 if (a
.format
!= 0 && b
.format
!= 0 && a
.format
!= b
.format
)
234 if (a
.byte_order
!= 0 && b
.byte_order
!= 0 && a
.byte_order
!= b
.byte_order
)
236 if (a
.buffer_size
!= 0 && b
.buffer_size
!= 0
237 && a
.buffer_size
!= b
.buffer_size
) {
240 if (a
.frame_rate
!= 0 && b
.frame_rate
!= 0 && a
.frame_rate
!= b
.frame_rate
)
247 multi_audio_info_matches(const media_multi_audio_info
& a
,
248 const media_multi_audio_info
& b
)
250 if (a
.channel_mask
!= 0 && b
.channel_mask
!= 0
251 && a
.channel_mask
!= b
.channel_mask
) {
254 if (a
.valid_bits
!= 0 && b
.valid_bits
!= 0 && a
.valid_bits
!= b
.valid_bits
)
256 if (a
.matrix_mask
!= 0 && b
.matrix_mask
!= 0
257 && a
.matrix_mask
!= b
.matrix_mask
) {
265 multi_audio_format_matches(const media_multi_audio_format
& a
,
266 const media_multi_audio_format
& b
)
268 return raw_audio_format_matches(a
, b
) && multi_audio_info_matches(a
, b
);
273 raw_video_format_matches(const media_raw_video_format
& a
,
274 const media_raw_video_format
& b
)
276 if (a
.field_rate
!= 0 && b
.field_rate
!= 0
277 && a
.field_rate
!= b
.field_rate
) {
280 if (a
.interlace
!= 0 && b
.interlace
!= 0
281 && a
.interlace
!= b
.interlace
) {
284 if (a
.first_active
!= 0 && b
.first_active
!= 0
285 && a
.first_active
!= b
.first_active
) {
288 if (a
.last_active
!= 0 && b
.last_active
!= 0
289 && a
.last_active
!= b
.last_active
) {
292 if (a
.orientation
!= 0 && b
.orientation
!= 0
293 && a
.orientation
!= b
.orientation
) {
296 if (a
.pixel_width_aspect
!= 0 && b
.pixel_width_aspect
!= 0
297 && a
.pixel_width_aspect
!= b
.pixel_width_aspect
) {
300 if (a
.pixel_height_aspect
!= 0 && b
.pixel_height_aspect
!= 0
301 && a
.pixel_height_aspect
!= b
.pixel_height_aspect
) {
304 if (a
.display
.format
!= 0 && b
.display
.format
!= 0
305 && a
.display
.format
!= b
.display
.format
) {
308 if (a
.display
.line_width
!= 0 && b
.display
.line_width
!= 0
309 && a
.display
.line_width
!= b
.display
.line_width
) {
312 if (a
.display
.line_count
!= 0 && b
.display
.line_count
!= 0
313 && a
.display
.line_count
!= b
.display
.line_count
) {
316 if (a
.display
.bytes_per_row
!= 0 && b
.display
.bytes_per_row
!= 0
317 && a
.display
.bytes_per_row
!= b
.display
.bytes_per_row
) {
320 if (a
.display
.pixel_offset
!= 0 && b
.display
.pixel_offset
!= 0
321 && a
.display
.pixel_offset
!= b
.display
.pixel_offset
) {
324 if (a
.display
.line_offset
!= 0 && b
.display
.line_offset
!= 0
325 && a
.display
.line_offset
!= b
.display
.line_offset
) {
328 if (a
.display
.flags
!= 0 && b
.display
.flags
!= 0
329 && a
.display
.flags
!= b
.display
.flags
) {
338 multistream_format_matches(const media_multistream_format
& a
,
339 const media_multistream_format
& b
)
341 if (a
.avg_bit_rate
!= 0 && b
.avg_bit_rate
!= 0
342 && a
.avg_bit_rate
!= b
.avg_bit_rate
) {
345 if (a
.max_bit_rate
!= 0 && b
.max_bit_rate
!= 0
346 && a
.max_bit_rate
!= b
.max_bit_rate
) {
349 if (a
.avg_chunk_size
!= 0 && b
.avg_chunk_size
!= 0
350 && a
.avg_chunk_size
!= b
.avg_chunk_size
) {
353 if (a
.max_chunk_size
!= 0 && b
.max_chunk_size
!= 0
354 && a
.max_chunk_size
!= b
.max_chunk_size
) {
357 if (a
.flags
!= 0 && b
.flags
!= 0 && a
.flags
!= b
.flags
)
359 if (a
.format
!= 0 && b
.format
!= 0 && a
.format
!= b
.format
)
362 if (a
.format
== 0 && b
.format
== 0) {
363 // TODO: How do we compare two formats with no type?
367 switch ((a
.format
!= 0) ? a
.format
: b
.format
) {
369 return true; // TODO: really?
371 case media_multistream_format::B_VID
:
372 if (a
.u
.vid
.frame_rate
!= 0 && b
.u
.vid
.frame_rate
!= 0
373 && a
.u
.vid
.frame_rate
!= b
.u
.vid
.frame_rate
) {
376 if (a
.u
.vid
.width
!= 0 && b
.u
.vid
.width
!= 0
377 && a
.u
.vid
.width
!= b
.u
.vid
.width
) {
380 if (a
.u
.vid
.height
!= 0 && b
.u
.vid
.height
!= 0
381 && a
.u
.vid
.height
!= b
.u
.vid
.height
) {
384 if (a
.u
.vid
.space
!= 0 && b
.u
.vid
.space
!= 0
385 && a
.u
.vid
.space
!= b
.u
.vid
.space
) {
388 if (a
.u
.vid
.sampling_rate
!= 0 && b
.u
.vid
.sampling_rate
!= 0
389 && a
.u
.vid
.sampling_rate
!= b
.u
.vid
.sampling_rate
) {
392 if (a
.u
.vid
.sample_format
!= 0 && b
.u
.vid
.sample_format
!= 0
393 && a
.u
.vid
.sample_format
!= b
.u
.vid
.sample_format
) {
396 if (a
.u
.vid
.byte_order
!= 0 && b
.u
.vid
.byte_order
!= 0
397 && a
.u
.vid
.byte_order
!= b
.u
.vid
.byte_order
) {
400 if (a
.u
.vid
.channel_count
!= 0 && b
.u
.vid
.channel_count
!= 0
401 && a
.u
.vid
.channel_count
!= b
.u
.vid
.channel_count
) {
406 case media_multistream_format::B_AVI
:
407 if (a
.u
.avi
.us_per_frame
!= 0 && b
.u
.avi
.us_per_frame
!= 0
408 && a
.u
.avi
.us_per_frame
!= b
.u
.avi
.us_per_frame
) {
411 if (a
.u
.avi
.width
!= 0 && b
.u
.avi
.width
!= 0
412 && a
.u
.avi
.width
!= b
.u
.avi
.width
) {
415 if (a
.u
.avi
.height
!= 0 && b
.u
.avi
.height
!= 0
416 && a
.u
.avi
.height
!= b
.u
.avi
.height
) {
419 if (a
.u
.avi
.type_count
!= 0 && b
.u
.avi
.type_count
!= 0
420 && a
.u
.avi
.type_count
!= b
.u
.avi
.type_count
) {
423 if (a
.u
.avi
.types
[0] != 0 && b
.u
.avi
.types
[0] != 0
424 && a
.u
.avi
.types
[0] != b
.u
.avi
.types
[0]) {
427 if (a
.u
.avi
.types
[1] != 0 && b
.u
.avi
.types
[1] != 0
428 && a
.u
.avi
.types
[1] != b
.u
.avi
.types
[1]) {
431 if (a
.u
.avi
.types
[2] != 0 && b
.u
.avi
.types
[2] != 0
432 && a
.u
.avi
.types
[2] != b
.u
.avi
.types
[2]) {
435 if (a
.u
.avi
.types
[3] != 0 && b
.u
.avi
.types
[3] != 0
436 && a
.u
.avi
.types
[3] != b
.u
.avi
.types
[3]) {
439 if (a
.u
.avi
.types
[4] != 0 && b
.u
.avi
.types
[4] != 0
440 && a
.u
.avi
.types
[4] != b
.u
.avi
.types
[4]) {
449 encoded_audio_format_matches(const media_encoded_audio_format
& a
,
450 const media_encoded_audio_format
& b
)
452 if (!raw_audio_format_matches(a
.output
, b
.output
))
454 if (a
.encoding
!= 0 && b
.encoding
!= 0 && a
.encoding
!= b
.encoding
)
456 if (a
.bit_rate
!= 0 && b
.bit_rate
!= 0 && a
.bit_rate
!= b
.bit_rate
)
458 if (a
.frame_size
!= 0 && b
.frame_size
!= 0 && a
.frame_size
!= b
.frame_size
)
460 if (!multi_audio_info_matches(a
.multi_info
, b
.multi_info
))
463 if (a
.encoding
== 0 && b
.encoding
== 0)
464 return true; // can't compare
466 switch((a
.encoding
!= 0) ? a
.encoding
: b
.encoding
) {
467 case media_encoded_audio_format::B_ANY
:
475 encoded_video_format_matches(const media_encoded_video_format
& a
,
476 const media_encoded_video_format
& b
)
478 if (!raw_video_format_matches(a
.output
, b
.output
))
480 if (a
.encoding
!= 0 && b
.encoding
!= 0 && a
.encoding
!= b
.encoding
)
483 if (a
.avg_bit_rate
!= 0 && b
.avg_bit_rate
!= 0
484 && a
.avg_bit_rate
!= b
.avg_bit_rate
) {
487 if (a
.max_bit_rate
!= 0 && b
.max_bit_rate
!= 0
488 && a
.max_bit_rate
!= b
.max_bit_rate
) {
491 if (a
.frame_size
!= 0 && b
.frame_size
!= 0
492 && a
.frame_size
!= b
.frame_size
) {
495 if (a
.forward_history
!= 0 && b
.forward_history
!= 0
496 && a
.forward_history
!= b
.forward_history
) {
499 if (a
.backward_history
!= 0 && b
.backward_history
!= 0
500 && a
.backward_history
!= b
.backward_history
) {
504 if (a
.encoding
== 0 && b
.encoding
== 0)
505 return true; // can't compare
507 switch((a
.encoding
!= 0) ? a
.encoding
: b
.encoding
) {
508 case media_encoded_video_format::B_ANY
:
515 // #pragma mark - media_format::SpecializeTo() support
519 raw_audio_format_specialize(media_raw_audio_format
* format
,
520 const media_raw_audio_format
* other
)
522 if (format
->frame_rate
== 0)
523 format
->frame_rate
= other
->frame_rate
;
524 if (format
->channel_count
== 0)
525 format
->channel_count
= other
->channel_count
;
526 if (format
->format
== 0)
527 format
->format
= other
->format
;
528 if (format
->byte_order
== 0)
529 format
->byte_order
= other
->byte_order
;
530 if (format
->buffer_size
== 0)
531 format
->buffer_size
= other
->buffer_size
;
532 if (format
->frame_rate
== 0)
533 format
->frame_rate
= other
->frame_rate
;
538 multi_audio_info_specialize(media_multi_audio_info
* format
,
539 const media_multi_audio_info
* other
)
541 if (format
->channel_mask
== 0)
542 format
->channel_mask
= other
->channel_mask
;
543 if (format
->valid_bits
== 0)
544 format
->valid_bits
= other
->valid_bits
;
545 if (format
->matrix_mask
== 0)
546 format
->matrix_mask
= other
->matrix_mask
;
551 multi_audio_format_specialize(media_multi_audio_format
* format
,
552 const media_multi_audio_format
* other
)
554 raw_audio_format_specialize(format
, other
);
555 multi_audio_info_specialize(format
, other
);
560 raw_video_format_specialize(media_raw_video_format
* format
,
561 const media_raw_video_format
* other
)
563 if (format
->field_rate
== 0)
564 format
->field_rate
= other
->field_rate
;
565 if (format
->interlace
== 0)
566 format
->interlace
= other
->interlace
;
567 if (format
->first_active
== 0)
568 format
->first_active
= other
->first_active
;
569 if (format
->last_active
== 0)
570 format
->last_active
= other
->last_active
;
571 if (format
->orientation
== 0)
572 format
->orientation
= other
->orientation
;
573 if (format
->pixel_width_aspect
== 0)
574 format
->pixel_width_aspect
= other
->pixel_width_aspect
;
575 if (format
->pixel_height_aspect
== 0)
576 format
->pixel_height_aspect
= other
->pixel_height_aspect
;
577 if (format
->display
.format
== 0)
578 format
->display
.format
= other
->display
.format
;
579 if (format
->display
.line_width
== 0)
580 format
->display
.line_width
= other
->display
.line_width
;
581 if (format
->display
.line_count
== 0)
582 format
->display
.line_count
= other
->display
.line_count
;
583 if (format
->display
.bytes_per_row
== 0)
584 format
->display
.bytes_per_row
= other
->display
.bytes_per_row
;
585 if (format
->display
.pixel_offset
== 0)
586 format
->display
.pixel_offset
= other
->display
.pixel_offset
;
587 if (format
->display
.line_offset
== 0)
588 format
->display
.line_offset
= other
->display
.line_offset
;
589 if (format
->display
.flags
== 0)
590 format
->display
.flags
= other
->display
.flags
;
595 multistream_format_specialize(media_multistream_format
* format
,
596 const media_multistream_format
* other
)
598 if (format
->avg_bit_rate
== 0)
599 format
->avg_bit_rate
= other
->avg_bit_rate
;
600 if (format
->max_bit_rate
== 0)
601 format
->max_bit_rate
= other
->max_bit_rate
;
602 if (format
->avg_chunk_size
== 0)
603 format
->avg_chunk_size
= other
->avg_chunk_size
;
604 if (format
->max_chunk_size
== 0)
605 format
->max_chunk_size
= other
->max_chunk_size
;
606 if (format
->flags
== 0)
607 format
->flags
= other
->flags
;
608 if (format
->format
== 0)
609 format
->format
= other
->format
;
611 switch (format
->format
) {
612 case media_multistream_format::B_VID
:
613 if (format
->u
.vid
.frame_rate
== 0)
614 format
->u
.vid
.frame_rate
= other
->u
.vid
.frame_rate
;
615 if (format
->u
.vid
.width
== 0)
616 format
->u
.vid
.width
= other
->u
.vid
.width
;
617 if (format
->u
.vid
.height
== 0)
618 format
->u
.vid
.height
= other
->u
.vid
.height
;
619 if (format
->u
.vid
.space
== 0)
620 format
->u
.vid
.space
= other
->u
.vid
.space
;
621 if (format
->u
.vid
.sampling_rate
== 0)
622 format
->u
.vid
.sampling_rate
= other
->u
.vid
.sampling_rate
;
623 if (format
->u
.vid
.sample_format
== 0)
624 format
->u
.vid
.sample_format
= other
->u
.vid
.sample_format
;
625 if (format
->u
.vid
.byte_order
== 0)
626 format
->u
.vid
.byte_order
= other
->u
.vid
.byte_order
;
627 if (format
->u
.vid
.channel_count
== 0)
628 format
->u
.vid
.channel_count
= other
->u
.vid
.channel_count
;
631 case media_multistream_format::B_AVI
:
632 if (format
->u
.avi
.us_per_frame
== 0)
633 format
->u
.avi
.us_per_frame
= other
->u
.avi
.us_per_frame
;
634 if (format
->u
.avi
.width
== 0)
635 format
->u
.avi
.width
= other
->u
.avi
.width
;
636 if (format
->u
.avi
.height
== 0)
637 format
->u
.avi
.height
= other
->u
.avi
.height
;
638 if (format
->u
.avi
.type_count
== 0)
639 format
->u
.avi
.type_count
= other
->u
.avi
.type_count
;
640 if (format
->u
.avi
.types
[0] == 0)
641 format
->u
.avi
.types
[0] = other
->u
.avi
.types
[0];
642 if (format
->u
.avi
.types
[1] == 0)
643 format
->u
.avi
.types
[1] = other
->u
.avi
.types
[1];
644 if (format
->u
.avi
.types
[2] == 0)
645 format
->u
.avi
.types
[2] = other
->u
.avi
.types
[2];
646 if (format
->u
.avi
.types
[3] == 0)
647 format
->u
.avi
.types
[3] = other
->u
.avi
.types
[3];
648 if (format
->u
.avi
.types
[4] == 0)
649 format
->u
.avi
.types
[4] = other
->u
.avi
.types
[4];
653 ERROR("media_format::SpecializeTo can't specialize "
654 "media_multistream_format of format %" B_PRId32
"\n",
661 encoded_audio_format_specialize(media_encoded_audio_format
* format
,
662 const media_encoded_audio_format
* other
)
664 raw_audio_format_specialize(&format
->output
, &other
->output
);
665 if (format
->encoding
== 0)
666 format
->encoding
= other
->encoding
;
667 if (format
->bit_rate
== 0)
668 format
->bit_rate
= other
->bit_rate
;
669 if (format
->frame_size
== 0)
670 format
->frame_size
= other
->frame_size
;
671 multi_audio_info_specialize(&format
->multi_info
, &other
->multi_info
);
676 encoded_video_format_specialize(media_encoded_video_format
* format
,
677 const media_encoded_video_format
* other
)
679 raw_video_format_specialize(&format
->output
, &other
->output
);
680 if (format
->avg_bit_rate
== 0)
681 format
->avg_bit_rate
= other
->avg_bit_rate
;
682 if (format
->max_bit_rate
== 0)
683 format
->max_bit_rate
= other
->max_bit_rate
;
684 if (format
->encoding
== 0)
685 format
->encoding
= other
->encoding
;
686 if (format
->frame_size
== 0)
687 format
->frame_size
= other
->frame_size
;
688 if (format
->forward_history
== 0)
689 format
->forward_history
= other
->forward_history
;
690 if (format
->backward_history
== 0)
691 format
->backward_history
= other
->backward_history
;
695 // #pragma mark - media_format
699 media_format::Matches(const media_format
* other
) const
703 if (type
== 0 && other
->type
== 0) {
704 // TODO: How do we compare two formats with no type?
708 if (type
!= 0 && other
->type
!= 0 && type
!= other
->type
)
711 switch ((type
!= 0) ? type
: other
->type
) {
712 case B_MEDIA_RAW_AUDIO
:
713 return multi_audio_format_matches(u
.raw_audio
, other
->u
.raw_audio
);
715 case B_MEDIA_RAW_VIDEO
:
716 return raw_video_format_matches(u
.raw_video
, other
->u
.raw_video
);
718 case B_MEDIA_MULTISTREAM
:
719 return multistream_format_matches(u
.multistream
,
720 other
->u
.multistream
);
722 case B_MEDIA_ENCODED_AUDIO
:
723 return encoded_audio_format_matches(u
.encoded_audio
,
724 other
->u
.encoded_audio
);
726 case B_MEDIA_ENCODED_VIDEO
:
727 return encoded_video_format_matches(u
.encoded_video
,
728 other
->u
.encoded_video
);
731 return true; // TODO: really?
737 media_format::SpecializeTo(const media_format
* otherFormat
)
741 if (type
== 0 && otherFormat
->type
== 0) {
742 ERROR("media_format::SpecializeTo can't specialize wildcard to other "
743 "wildcard format\n");
748 type
= otherFormat
->type
;
751 case B_MEDIA_RAW_AUDIO
:
752 multi_audio_format_specialize(&u
.raw_audio
,
753 &otherFormat
->u
.raw_audio
);
756 case B_MEDIA_RAW_VIDEO
:
757 raw_video_format_specialize(&u
.raw_video
,
758 &otherFormat
->u
.raw_video
);
761 case B_MEDIA_MULTISTREAM
:
762 multistream_format_specialize(&u
.multistream
,
763 &otherFormat
->u
.multistream
);
766 case B_MEDIA_ENCODED_AUDIO
:
767 encoded_audio_format_specialize(&u
.encoded_audio
,
768 &otherFormat
->u
.encoded_audio
);
771 case B_MEDIA_ENCODED_VIDEO
:
772 encoded_video_format_specialize(&u
.encoded_video
,
773 &otherFormat
->u
.encoded_video
);
777 ERROR("media_format::SpecializeTo can't specialize format "
784 media_format::SetMetaData(const void* data
, size_t size
)
786 if (!data
|| size
< 0 || size
> META_DATA_MAX_SIZE
)
791 if (size
< META_DATA_AREA_MIN_SIZE
) {
792 new_area
= B_BAD_VALUE
;
793 new_addr
= malloc(size
);
797 new_area
= create_area("meta_data_area", &new_addr
, B_ANY_ADDRESS
,
798 ROUND_UP_TO_PAGE(size
), B_NO_LOCK
, B_READ_AREA
| B_WRITE_AREA
);
800 return (status_t
)new_area
;
803 if (meta_data_area
> 0)
804 delete_area(meta_data_area
);
808 meta_data
= new_addr
;
809 meta_data_size
= size
;
810 meta_data_area
= new_area
;
812 memcpy(meta_data
, data
, size
);
814 if (meta_data_area
> 0)
815 set_area_protection(meta_data_area
, B_READ_AREA
);
822 media_format::MetaData() const
829 media_format::MetaDataSize() const
831 return meta_data_size
;
835 media_format::media_format()
837 memset(this, 0x00, sizeof(*this));
838 meta_data_area
= B_BAD_VALUE
;
842 media_format::media_format(const media_format
& other
)
844 memset(this, 0x00, sizeof(*this));
845 meta_data_area
= B_BAD_VALUE
;
850 media_format::~media_format()
852 if (meta_data_area
> 0)
853 delete_area(meta_data_area
);
861 media_format::operator=(const media_format
& clone
)
863 // get rid of this format's meta data
864 this->~media_format();
865 // danger: using only ~media_format() would call the constructor
867 // make a binary copy
868 memcpy(this, &clone
, sizeof(*this));
869 // some binary copies are invalid:
871 meta_data_area
= B_BAD_VALUE
;
873 // clone or copy the meta data
874 if (clone
.meta_data
) {
875 if (clone
.meta_data_area
!= B_BAD_VALUE
) {
876 meta_data_area
= clone_area("meta_data_clone_area", &meta_data
,
877 B_ANY_ADDRESS
, B_READ_AREA
, clone
.meta_data_area
);
878 if (meta_data_area
< 0) {
879 // whoops, we just lost our meta data
884 meta_data
= malloc(meta_data_size
);
886 memcpy(meta_data
, clone
.meta_data
, meta_data_size
);
888 // whoops, we just lost our meta data
901 operator==(const media_raw_audio_format
& a
, const media_raw_audio_format
& b
)
903 return a
.frame_rate
== b
.frame_rate
904 && a
.channel_count
== b
.channel_count
905 && a
.format
== b
.format
906 && a
.byte_order
== b
.byte_order
907 && a
.buffer_size
== b
.buffer_size
;
912 operator==(const media_multi_audio_info
& a
, const media_multi_audio_info
& b
)
914 return a
.channel_mask
== b
.channel_mask
915 && a
.valid_bits
== b
.valid_bits
916 && a
.matrix_mask
== b
.matrix_mask
;
921 operator==(const media_multi_audio_format
& a
,
922 const media_multi_audio_format
& b
)
924 return (media_raw_audio_format
)a
== (media_raw_audio_format
)b
925 && (media_multi_audio_info
)a
== (media_multi_audio_info
)b
;
930 operator==(const media_encoded_audio_format
& a
,
931 const media_encoded_audio_format
& b
)
933 return a
.output
== b
.output
934 && a
.encoding
== b
.encoding
935 && a
.bit_rate
== b
.bit_rate
936 && a
.frame_size
== b
.frame_size
937 && a
.multi_info
== b
.multi_info
;
942 operator==(const media_video_display_info
& a
,
943 const media_video_display_info
& b
)
945 return a
.format
== b
.format
946 && a
.line_width
== b
.line_width
947 && a
.line_count
== b
.line_count
948 && a
.bytes_per_row
== b
.bytes_per_row
949 && a
.pixel_offset
== b
.pixel_offset
950 && a
.line_offset
== b
.line_offset
951 && a
.flags
== b
.flags
;
956 operator==(const media_raw_video_format
& a
, const media_raw_video_format
& b
)
958 return a
.field_rate
== b
.field_rate
959 && a
.interlace
== b
.interlace
960 && a
.first_active
== b
.first_active
961 && a
.last_active
== b
.last_active
962 && a
.orientation
== b
.orientation
963 && a
.pixel_width_aspect
== b
.pixel_width_aspect
964 && a
.pixel_height_aspect
== b
.pixel_height_aspect
965 && a
.display
== b
.display
;
970 operator==(const media_encoded_video_format
& a
,
971 const media_encoded_video_format
& b
)
973 return a
.output
== b
.output
974 && a
.avg_bit_rate
== b
.avg_bit_rate
975 && a
.max_bit_rate
== b
.max_bit_rate
976 && a
.encoding
== b
.encoding
977 && a
.frame_size
== b
.frame_size
978 && a
.forward_history
== b
.forward_history
979 && a
.backward_history
== b
.backward_history
;
984 operator==(const media_multistream_format::vid_info
& a
,
985 const media_multistream_format::vid_info
& b
)
987 return a
.frame_rate
== b
.frame_rate
988 && a
.width
== b
.width
989 && a
.height
== b
.height
990 && a
.space
== b
.space
991 && a
.sampling_rate
== b
.sampling_rate
992 && a
.sample_format
== b
.sample_format
993 && a
.byte_order
== b
.byte_order
994 && a
.channel_count
== b
.channel_count
;
999 operator==(const media_multistream_format::avi_info
& a
,
1000 const media_multistream_format::avi_info
& b
)
1002 return a
.us_per_frame
== b
.us_per_frame
1003 && a
.width
== b
.width
1004 && a
.height
== b
.height
1005 && a
.type_count
== b
.type_count
1006 && a
.types
[0] == b
.types
[0]
1007 && a
.types
[1] == b
.types
[1]
1008 && a
.types
[2] == b
.types
[2]
1009 && a
.types
[3] == b
.types
[3]
1010 && a
.types
[4] == b
.types
[4];
1015 operator==(const media_multistream_format
& a
,
1016 const media_multistream_format
& b
)
1018 if (a
.avg_bit_rate
!= b
.avg_bit_rate
1019 || a
.max_bit_rate
!= b
.max_bit_rate
1020 || a
.avg_chunk_size
!= b
.avg_chunk_size
1021 || a
.max_chunk_size
!= b
.max_chunk_size
1022 || a
.format
!= b
.format
1023 || a
.flags
!= b
.flags
) {
1028 case media_multistream_format::B_VID
:
1029 return a
.u
.vid
== b
.u
.vid
;
1031 case media_multistream_format::B_AVI
:
1032 return a
.u
.avi
== b
.u
.avi
;
1035 return true; // TODO: really?
1041 operator==(const media_format
& a
, const media_format
& b
)
1043 if (a
.type
!= b
.type
1044 || a
.user_data_type
!= b
.user_data_type
1045 // TODO: compare user_data[48] ?
1046 || a
.require_flags
!= b
.require_flags
1047 || a
.deny_flags
!= b
.deny_flags
) {
1052 case B_MEDIA_RAW_AUDIO
:
1053 return a
.u
.raw_audio
== b
.u
.raw_audio
;
1055 case B_MEDIA_RAW_VIDEO
:
1056 return a
.u
.raw_video
== b
.u
.raw_video
;
1058 case B_MEDIA_MULTISTREAM
:
1059 return a
.u
.multistream
== b
.u
.multistream
;
1061 case B_MEDIA_ENCODED_AUDIO
:
1062 return a
.u
.encoded_audio
== b
.u
.encoded_audio
;
1064 case B_MEDIA_ENCODED_VIDEO
:
1065 return a
.u
.encoded_video
== b
.u
.encoded_video
;
1068 return true; // TODO: really?
1076 /*! return \c true if a and b are compatible (accounting for wildcards)
1077 a is the format you want to feed to something accepting b
1080 format_is_compatible(const media_format
& a
, const media_format
& b
)
1082 return a
.Matches(&b
);
1087 string_for_format(const media_format
& f
, char* buf
, size_t size
)
1089 char encoding
[10]; /* maybe Be wanted to use some 4CCs ? */
1090 const char* videoOrientation
= "0"; /* I'd use "NC", R5 uses 0. */
1095 case B_MEDIA_RAW_AUDIO
:
1097 "raw_audio;%g;%" B_PRIu32
";0x%" B_PRIx32
";%" B_PRIu32
";0x%"
1098 B_PRIxSIZE
";0x%#" B_PRIx32
";%d;0x%04x",
1099 f
.u
.raw_audio
.frame_rate
,
1100 f
.u
.raw_audio
.channel_count
,
1101 f
.u
.raw_audio
.format
,
1102 f
.u
.raw_audio
.byte_order
,
1103 f
.u
.raw_audio
.buffer_size
,
1104 f
.u
.raw_audio
.channel_mask
,
1105 f
.u
.raw_audio
.valid_bits
,
1106 f
.u
.raw_audio
.matrix_mask
);
1108 case B_MEDIA_RAW_VIDEO
:
1109 if (f
.u
.raw_video
.orientation
== B_VIDEO_TOP_LEFT_RIGHT
)
1110 videoOrientation
= "TopLR";
1111 else if (f
.u
.raw_video
.orientation
== B_VIDEO_BOTTOM_LEFT_RIGHT
)
1112 videoOrientation
= "BotLR";
1113 snprintf(buf
, size
, "raw_video;%g;0x%x;%" B_PRIu32
";%" B_PRIu32
";%"
1114 B_PRIu32
";%" B_PRIu32
";%s;%d;%d",
1115 f
.u
.raw_video
.field_rate
,
1116 f
.u
.raw_video
.display
.format
,
1117 f
.u
.raw_video
.interlace
,
1118 f
.u
.raw_video
.display
.line_width
,
1119 f
.u
.raw_video
.display
.line_count
,
1120 f
.u
.raw_video
.first_active
,
1122 f
.u
.raw_video
.pixel_width_aspect
,
1123 f
.u
.raw_video
.pixel_height_aspect
);
1125 case B_MEDIA_ENCODED_AUDIO
:
1126 snprintf(encoding
, 10, "%d", f
.u
.encoded_audio
.encoding
);
1128 "caudio;%s;%g;%ld;(%g;%" B_PRIu32
";0x%" B_PRIx32
";%" B_PRIu32
1129 ";0x%" B_PRIxSIZE
";0x%08" B_PRIx32
";%d;0x%04x)",
1131 f
.u
.encoded_audio
.bit_rate
,
1132 f
.u
.encoded_audio
.frame_size
,
1133 f
.u
.encoded_audio
.output
.frame_rate
,
1134 f
.u
.encoded_audio
.output
.channel_count
,
1135 f
.u
.encoded_audio
.output
.format
,
1136 f
.u
.encoded_audio
.output
.byte_order
,
1137 f
.u
.encoded_audio
.output
.buffer_size
,
1138 f
.u
.encoded_audio
.multi_info
.channel_mask
,
1139 f
.u
.encoded_audio
.multi_info
.valid_bits
,
1140 f
.u
.encoded_audio
.multi_info
.matrix_mask
);
1142 case B_MEDIA_ENCODED_VIDEO
:
1143 snprintf(encoding
, 10, "%d", f
.u
.encoded_video
.encoding
);
1144 if (f
.u
.encoded_video
.output
.orientation
== B_VIDEO_TOP_LEFT_RIGHT
)
1145 videoOrientation
= "TopLR";
1146 else if (f
.u
.encoded_video
.output
.orientation
== B_VIDEO_BOTTOM_LEFT_RIGHT
)
1147 videoOrientation
= "BotLR";
1149 "cvideo;%s;%g;%g;%" B_PRIuSIZE
";(%g;0x%x;%" B_PRIu32
";%" B_PRIu32
1150 ";%" B_PRIu32
";%" B_PRIu32
";%s;%d;%d)",
1152 f
.u
.encoded_video
.avg_bit_rate
,
1153 f
.u
.encoded_video
.max_bit_rate
,
1154 f
.u
.encoded_video
.frame_size
,
1155 f
.u
.encoded_video
.output
.field_rate
,
1156 f
.u
.encoded_video
.output
.display
.format
,
1157 f
.u
.encoded_video
.output
.interlace
,
1158 f
.u
.encoded_video
.output
.display
.line_width
,
1159 f
.u
.encoded_video
.output
.display
.line_count
,
1160 f
.u
.encoded_video
.output
.first_active
,
1162 f
.u
.encoded_video
.output
.pixel_width_aspect
,
1163 f
.u
.encoded_video
.output
.pixel_height_aspect
);
1166 snprintf(buf
, size
, "%d-", f
.type
);
1167 unsigned char* p
= (unsigned char*)&(f
.u
);
1168 size
-= strlen(buf
);
1170 for (int i
= 0; (size
> 2) && (i
< 96); i
++) {
1171 snprintf(buf
, 3, "%2.2x", *(p
+ i
));
1185 operator==(const media_file_format_id
& a
, const media_file_format_id
& b
)
1187 return a
.node
== b
.node
&& a
.device
== b
.device
1188 && a
.internal_id
== b
.internal_id
;
1193 operator<(const media_file_format_id
& a
, const media_file_format_id
& b
)
1195 return a
.internal_id
< b
.internal_id
;
1202 //! Use this function to iterate through available file format writers.
1204 get_next_file_format(int32
* cookie
, media_file_format
* mff
)
1206 if (cookie
== NULL
|| mff
== NULL
)
1209 status_t ret
= AddOnManager::GetInstance()->GetFileFormat(mff
, *cookie
);
1213 *cookie
= *cookie
+ 1;
1223 const char* B_MEDIA_SERVER_SIGNATURE
= "application/x-vnd.Be.media-server";
1224 const char* B_MEDIA_ADDON_SERVER_SIGNATURE
= "application/x-vnd.Be.addon-host";
1226 const type_code B_CODEC_TYPE_INFO
= 0x040807b2;
1232 // shutdown_media_server() and launch_media_server()
1233 // are provided by libbe.so in BeOS R5
1235 #define MEDIA_SERVICE_NOTIFICATION_ID "MediaServiceNotificationID"
1239 notify_system(float progress
, const char* message
)
1241 BNotification
notification(B_PROGRESS_NOTIFICATION
);
1242 notification
.SetMessageID(MEDIA_SERVICE_NOTIFICATION_ID
);
1243 notification
.SetProgress(progress
);
1244 notification
.SetGroup(B_TRANSLATE("Media Service"));
1245 notification
.SetContent(message
);
1248 be_app
->GetAppInfo(&info
);
1249 BBitmap
icon(BRect(0, 0, 32, 32), B_RGBA32
);
1250 BNode
node(&info
.ref
);
1251 BIconUtils::GetVectorIcon(&node
, "BEOS:ICON", &icon
);
1252 notification
.SetIcon(&icon
);
1254 notification
.Send();
1259 progress_shutdown(int stage
,
1260 bool (*progress
)(int stage
, const char* message
, void* cookie
),
1263 // parameter "message" is no longer used. It is kept for compatibility with
1264 // BeOS as this is used as a shutdown_media_server callback.
1266 TRACE("stage: %i\n", stage
);
1267 const char* string
= "Unknown stage";
1270 string
= B_TRANSLATE("Stopping media server" B_UTF8_ELLIPSIS
);
1273 string
= B_TRANSLATE("Waiting for media_server to quit.");
1276 string
= B_TRANSLATE("Telling media_addon_server to quit.");
1279 string
= B_TRANSLATE("Waiting for media_addon_server to quit.");
1282 string
= B_TRANSLATE("Cleaning up.");
1285 string
= B_TRANSLATE("Done shutting down.");
1289 if (progress
== NULL
)
1290 notify_system(stage
/ 100.0f
, string
);
1292 progress(stage
, string
, cookie
);
1297 shutdown_media_server(bigtime_t timeout
,
1298 bool (*progress
)(int stage
, const char* message
, void* cookie
),
1301 BMessage
msg(B_QUIT_REQUESTED
);
1302 status_t err
= B_MEDIA_SYSTEM_FAILURE
;
1303 bool shutdown
= false;
1305 BMediaRoster
* roster
= BMediaRoster::Roster(&err
);
1306 if (roster
== NULL
|| err
!= B_OK
)
1309 if (progress
== NULL
&& roster
->Lock()) {
1310 MediaRosterEx(roster
)->EnableLaunchNotification(true, true);
1314 if ((err
= msg
.AddBool("be:_user_request", true)) != B_OK
)
1317 team_id mediaServer
= be_roster
->TeamFor(B_MEDIA_SERVER_SIGNATURE
);
1318 team_id addOnServer
= be_roster
->TeamFor(B_MEDIA_ADDON_SERVER_SIGNATURE
);
1320 if (mediaServer
!= B_ERROR
) {
1322 BMessenger
messenger(B_MEDIA_SERVER_SIGNATURE
, mediaServer
);
1323 progress_shutdown(10, progress
, cookie
);
1325 err
= messenger
.SendMessage(&msg
, &reply
, 2000000, 2000000);
1326 reply
.FindBool("_shutdown", &shutdown
);
1327 if (err
== B_TIMED_OUT
|| shutdown
== false) {
1328 if (messenger
.IsValid())
1329 kill_team(mediaServer
);
1330 } else if (err
!= B_OK
)
1333 progress_shutdown(20, progress
, cookie
);
1336 if (reply
.FindInt32("error", &rv
) == B_OK
&& rv
!= B_OK
)
1340 if (addOnServer
!= B_ERROR
) {
1343 BMessenger
messenger(B_MEDIA_ADDON_SERVER_SIGNATURE
, addOnServer
);
1344 progress_shutdown(40, progress
, cookie
);
1346 // The media_server usually shutdown the media_addon_server,
1347 // if not let's do something.
1348 if (messenger
.IsValid()) {
1349 err
= messenger
.SendMessage(&msg
, &reply
, 2000000, 2000000);
1350 reply
.FindBool("_shutdown", &shutdown
);
1351 if (err
== B_TIMED_OUT
|| shutdown
== false) {
1352 if (messenger
.IsValid())
1353 kill_team(addOnServer
);
1354 } else if (err
!= B_OK
)
1357 progress_shutdown(50, progress
, cookie
);
1360 if (reply
.FindInt32("error", &rv
) == B_OK
&& rv
!= B_OK
)
1365 progress_shutdown(100, progress
, cookie
);
1371 progress_startup(int stage
,
1372 bool (*progress
)(int stage
, const char* message
, void* cookie
),
1375 // parameter "message" is no longer used. It is kept for compatibility with
1376 // BeOS as this is used as a shutdown_media_server callback.
1378 TRACE("stage: %i\n", stage
);
1379 const char* string
= "Unknown stage";
1382 string
= B_TRANSLATE("Stopping media server" B_UTF8_ELLIPSIS
);
1385 string
= B_TRANSLATE("Stopping media_addon_server.");
1388 string
= B_TRANSLATE("Starting media_services.");
1391 string
= B_TRANSLATE("Error occurred starting media services.");
1394 string
= B_TRANSLATE("Ready for use.");
1398 if (progress
== NULL
)
1399 notify_system(stage
/ 100.0f
, string
);
1401 progress(stage
, string
, cookie
);
1406 launch_media_server(bigtime_t timeout
,
1407 bool (*progress
)(int stage
, const char* message
, void* cookie
),
1408 void* cookie
, uint32 flags
)
1410 if (BMediaRoster::IsRunning())
1411 return B_ALREADY_RUNNING
;
1413 status_t err
= B_MEDIA_SYSTEM_FAILURE
;
1414 BMediaRoster
* roster
= BMediaRoster::Roster(&err
);
1415 if (roster
== NULL
|| err
!= B_OK
)
1418 if (progress
== NULL
&& roster
->Lock()) {
1419 MediaRosterEx(roster
)->EnableLaunchNotification(true, true);
1423 // The media_server crashed
1424 if (be_roster
->IsRunning(B_MEDIA_ADDON_SERVER_SIGNATURE
)) {
1425 progress_startup(10, progress
, cookie
);
1426 kill_team(be_roster
->TeamFor(B_MEDIA_ADDON_SERVER_SIGNATURE
));
1429 // The media_addon_server crashed
1430 if (be_roster
->IsRunning(B_MEDIA_SERVER_SIGNATURE
)) {
1431 progress_startup(20, progress
, cookie
);
1432 kill_team(be_roster
->TeamFor(B_MEDIA_SERVER_SIGNATURE
));
1435 progress_startup(50, progress
, cookie
);
1437 err
= BLaunchRoster().Start(B_MEDIA_SERVER_SIGNATURE
);
1440 progress_startup(90, progress
, cookie
);
1441 else if (progress
!= NULL
) {
1442 progress_startup(100, progress
, cookie
);
1450 // #pragma mark - media_encode_info
1453 media_encode_info::media_encode_info()
1458 time_to_encode
= INT64_MAX
;
1459 file_format_data
= NULL
;
1460 file_format_data_size
= 0;
1462 codec_data_size
= 0;
1466 media_decode_info::media_decode_info()
1468 time_to_decode
= INT64_MAX
;
1469 file_format_data
= NULL
;
1470 file_format_data_size
= 0;
1472 codec_data_size
= 0;