vfs: check userland buffers before reading them.
[haiku.git] / src / kits / media / MediaDefs.cpp
blob1eb4803cb95ee8a446b0ed9beb58031aea4bf9f8
1 /*
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.
8 */
11 #include <MediaDefs.h>
13 #include <Application.h>
14 #include <Bitmap.h>
15 #include <Catalog.h>
16 #include <IconUtils.h>
17 #include <LaunchRoster.h>
18 #include <Locale.h>
19 #include <MediaNode.h>
20 #include <MediaRoster.h>
21 #include <Node.h>
22 #include <Notification.h>
23 #include <Roster.h>
25 #include <inttypes.h>
26 #include <stdio.h>
27 #include <string.h>
29 #include "AddOnManager.h"
30 #include "DataExchange.h"
31 #include "debug.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)
48 port(port),
49 id(id)
54 media_destination::media_destination(const media_destination& clone)
56 port(clone.port),
57 id(clone.id)
62 media_destination&
63 media_destination::operator=(const media_destination& clone)
65 port = clone.port;
66 id = clone.id;
67 return *this;
71 media_destination::media_destination()
73 port(-1),
74 id(-1)
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,
91 int32 id)
93 port(port),
94 id(id)
99 media_source::media_source(const media_source& clone)
101 port(clone.port),
102 id(clone.id)
107 media_source&
108 media_source::operator=(const media_source& clone)
110 port = clone.port;
111 id = clone.id;
112 return *this;
116 media_source::media_source()
118 port(-1),
119 id(-1)
124 media_source::~media_source()
129 media_source media_source::null(-1, -1);
132 // #pragma mark -
135 bool
136 operator==(const media_destination& a, const media_destination& b)
138 return a.port == b.port && a.id == b.id;
142 bool
143 operator!=(const media_destination& a, const media_destination& b)
145 return a.port != b.port || a.id != b.id;
149 bool
150 operator<(const media_destination& a, const media_destination& b)
152 UNIMPLEMENTED();
153 return false;
157 bool
158 operator==(const media_source& a, const media_source& b)
160 return a.port == b.port && a.id == b.id;
164 bool
165 operator!=(const media_source& a, const media_source& b)
167 return a.port != b.port || a.id != b.id;
171 bool
172 operator<(const media_source& a, const media_source& b)
174 UNIMPLEMENTED();
175 return false;
179 bool
180 operator==(const media_node& a, const media_node& b)
182 return a.node == b.node && a.port == b.port && a.kind == b.kind;
186 bool
187 operator!=(const media_node& a, const media_node& b)
189 return a.node != b.node || a.port != b.port || a.kind != b.kind;
193 bool
194 operator<(const media_node& a, const media_node& b)
196 UNIMPLEMENTED();
197 return false;
201 // #pragma mark -
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
222 static bool
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)
227 return false;
228 if (a.channel_count != 0 && b.channel_count != 0
229 && a.channel_count != b.channel_count) {
230 return false;
232 if (a.format != 0 && b.format != 0 && a.format != b.format)
233 return false;
234 if (a.byte_order != 0 && b.byte_order != 0 && a.byte_order != b.byte_order)
235 return false;
236 if (a.buffer_size != 0 && b.buffer_size != 0
237 && a.buffer_size != b.buffer_size) {
238 return false;
240 if (a.frame_rate != 0 && b.frame_rate != 0 && a.frame_rate != b.frame_rate)
241 return false;
242 return true;
246 static bool
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) {
252 return false;
254 if (a.valid_bits != 0 && b.valid_bits != 0 && a.valid_bits != b.valid_bits)
255 return false;
256 if (a.matrix_mask != 0 && b.matrix_mask != 0
257 && a.matrix_mask != b.matrix_mask) {
258 return false;
260 return true;
264 static bool
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);
272 static bool
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) {
278 return false;
280 if (a.interlace != 0 && b.interlace != 0
281 && a.interlace != b.interlace) {
282 return false;
284 if (a.first_active != 0 && b.first_active != 0
285 && a.first_active != b.first_active) {
286 return false;
288 if (a.last_active != 0 && b.last_active != 0
289 && a.last_active != b.last_active) {
290 return false;
292 if (a.orientation != 0 && b.orientation != 0
293 && a.orientation != b.orientation) {
294 return false;
296 if (a.pixel_width_aspect != 0 && b.pixel_width_aspect != 0
297 && a.pixel_width_aspect != b.pixel_width_aspect) {
298 return false;
300 if (a.pixel_height_aspect != 0 && b.pixel_height_aspect != 0
301 && a.pixel_height_aspect != b.pixel_height_aspect) {
302 return false;
304 if (a.display.format != 0 && b.display.format != 0
305 && a.display.format != b.display.format) {
306 return false;
308 if (a.display.line_width != 0 && b.display.line_width != 0
309 && a.display.line_width != b.display.line_width) {
310 return false;
312 if (a.display.line_count != 0 && b.display.line_count != 0
313 && a.display.line_count != b.display.line_count) {
314 return false;
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) {
318 return false;
320 if (a.display.pixel_offset != 0 && b.display.pixel_offset != 0
321 && a.display.pixel_offset != b.display.pixel_offset) {
322 return false;
324 if (a.display.line_offset != 0 && b.display.line_offset != 0
325 && a.display.line_offset != b.display.line_offset) {
326 return false;
328 if (a.display.flags != 0 && b.display.flags != 0
329 && a.display.flags != b.display.flags) {
330 return false;
333 return true;
337 static bool
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) {
343 return false;
345 if (a.max_bit_rate != 0 && b.max_bit_rate != 0
346 && a.max_bit_rate != b.max_bit_rate) {
347 return false;
349 if (a.avg_chunk_size != 0 && b.avg_chunk_size != 0
350 && a.avg_chunk_size != b.avg_chunk_size) {
351 return false;
353 if (a.max_chunk_size != 0 && b.max_chunk_size != 0
354 && a.max_chunk_size != b.max_chunk_size) {
355 return false;
357 if (a.flags != 0 && b.flags != 0 && a.flags != b.flags)
358 return false;
359 if (a.format != 0 && b.format != 0 && a.format != b.format)
360 return false;
362 if (a.format == 0 && b.format == 0) {
363 // TODO: How do we compare two formats with no type?
364 return true;
367 switch ((a.format != 0) ? a.format : b.format) {
368 default:
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) {
374 return false;
376 if (a.u.vid.width != 0 && b.u.vid.width != 0
377 && a.u.vid.width != b.u.vid.width) {
378 return false;
380 if (a.u.vid.height != 0 && b.u.vid.height != 0
381 && a.u.vid.height != b.u.vid.height) {
382 return false;
384 if (a.u.vid.space != 0 && b.u.vid.space != 0
385 && a.u.vid.space != b.u.vid.space) {
386 return false;
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) {
390 return false;
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) {
394 return false;
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) {
398 return false;
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) {
402 return false;
404 return true;
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) {
409 return false;
411 if (a.u.avi.width != 0 && b.u.avi.width != 0
412 && a.u.avi.width != b.u.avi.width) {
413 return false;
415 if (a.u.avi.height != 0 && b.u.avi.height != 0
416 && a.u.avi.height != b.u.avi.height) {
417 return false;
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) {
421 return false;
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]) {
425 return false;
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]) {
429 return false;
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]) {
433 return false;
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]) {
437 return false;
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]) {
441 return false;
443 return true;
448 static bool
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))
453 return false;
454 if (a.encoding != 0 && b.encoding != 0 && a.encoding != b.encoding)
455 return false;
456 if (a.bit_rate != 0 && b.bit_rate != 0 && a.bit_rate != b.bit_rate)
457 return false;
458 if (a.frame_size != 0 && b.frame_size != 0 && a.frame_size != b.frame_size)
459 return false;
460 if (!multi_audio_info_matches(a.multi_info, b.multi_info))
461 return false;
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:
468 default:
469 return true;
474 static bool
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))
479 return false;
480 if (a.encoding != 0 && b.encoding != 0 && a.encoding != b.encoding)
481 return false;
483 if (a.avg_bit_rate != 0 && b.avg_bit_rate != 0
484 && a.avg_bit_rate != b.avg_bit_rate) {
485 return false;
487 if (a.max_bit_rate != 0 && b.max_bit_rate != 0
488 && a.max_bit_rate != b.max_bit_rate) {
489 return false;
491 if (a.frame_size != 0 && b.frame_size != 0
492 && a.frame_size != b.frame_size) {
493 return false;
495 if (a.forward_history != 0 && b.forward_history != 0
496 && a.forward_history != b.forward_history) {
497 return false;
499 if (a.backward_history != 0 && b.backward_history != 0
500 && a.backward_history != b.backward_history) {
501 return false;
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:
509 default:
510 return true;
515 // #pragma mark - media_format::SpecializeTo() support
518 static void
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;
537 static void
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;
550 static void
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);
559 static void
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;
594 static void
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;
629 break;
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];
650 break;
652 default:
653 ERROR("media_format::SpecializeTo can't specialize "
654 "media_multistream_format of format %" B_PRId32 "\n",
655 format->format);
660 static void
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);
675 static void
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
698 bool
699 media_format::Matches(const media_format* other) const
701 CALLED();
703 if (type == 0 && other->type == 0) {
704 // TODO: How do we compare two formats with no type?
705 return true;
708 if (type != 0 && other->type != 0 && type != other->type)
709 return false;
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);
730 default:
731 return true; // TODO: really?
736 void
737 media_format::SpecializeTo(const media_format* otherFormat)
739 CALLED();
741 if (type == 0 && otherFormat->type == 0) {
742 ERROR("media_format::SpecializeTo can't specialize wildcard to other "
743 "wildcard format\n");
744 return;
747 if (type == 0)
748 type = otherFormat->type;
750 switch (type) {
751 case B_MEDIA_RAW_AUDIO:
752 multi_audio_format_specialize(&u.raw_audio,
753 &otherFormat->u.raw_audio);
754 return;
756 case B_MEDIA_RAW_VIDEO:
757 raw_video_format_specialize(&u.raw_video,
758 &otherFormat->u.raw_video);
759 return;
761 case B_MEDIA_MULTISTREAM:
762 multistream_format_specialize(&u.multistream,
763 &otherFormat->u.multistream);
764 return;
766 case B_MEDIA_ENCODED_AUDIO:
767 encoded_audio_format_specialize(&u.encoded_audio,
768 &otherFormat->u.encoded_audio);
769 return;
771 case B_MEDIA_ENCODED_VIDEO:
772 encoded_video_format_specialize(&u.encoded_video,
773 &otherFormat->u.encoded_video);
774 return;
776 default:
777 ERROR("media_format::SpecializeTo can't specialize format "
778 "type %d\n", type);
783 status_t
784 media_format::SetMetaData(const void* data, size_t size)
786 if (!data || size < 0 || size > META_DATA_MAX_SIZE)
787 return B_BAD_VALUE;
789 void* new_addr;
790 area_id new_area;
791 if (size < META_DATA_AREA_MIN_SIZE) {
792 new_area = B_BAD_VALUE;
793 new_addr = malloc(size);
794 if (!new_addr)
795 return B_NO_MEMORY;
796 } else {
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);
799 if (new_area < 0)
800 return (status_t)new_area;
803 if (meta_data_area > 0)
804 delete_area(meta_data_area);
805 else
806 free(meta_data);
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);
817 return B_OK;
821 const void*
822 media_format::MetaData() const
824 return meta_data;
828 int32
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;
846 *this = other;
850 media_format::~media_format()
852 if (meta_data_area > 0)
853 delete_area(meta_data_area);
854 else
855 free(meta_data);
859 // final
860 media_format&
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:
870 meta_data = NULL;
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
880 meta_data = NULL;
881 meta_data_size = 0;
883 } else {
884 meta_data = malloc(meta_data_size);
885 if (meta_data) {
886 memcpy(meta_data, clone.meta_data, meta_data_size);
887 } else {
888 // whoops, we just lost our meta data
889 meta_data_size = 0;
893 return *this;
897 // #pragma mark -
900 bool
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;
911 bool
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;
920 bool
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;
929 bool
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;
941 bool
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;
955 bool
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;
969 bool
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;
983 bool
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;
998 bool
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];
1014 bool
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) {
1024 return false;
1027 switch (a.format) {
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;
1034 default:
1035 return true; // TODO: really?
1040 bool
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) {
1048 return false;
1051 switch (a.type) {
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;
1067 default:
1068 return true; // TODO: really?
1073 // #pragma mark -
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
1079 bool
1080 format_is_compatible(const media_format& a, const media_format& b)
1082 return a.Matches(&b);
1086 bool
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. */
1092 if (buf == NULL)
1093 return false;
1094 switch (f.type) {
1095 case B_MEDIA_RAW_AUDIO:
1096 snprintf(buf, size,
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);
1107 return true;
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,
1121 videoOrientation,
1122 f.u.raw_video.pixel_width_aspect,
1123 f.u.raw_video.pixel_height_aspect);
1124 return true;
1125 case B_MEDIA_ENCODED_AUDIO:
1126 snprintf(encoding, 10, "%d", f.u.encoded_audio.encoding);
1127 snprintf(buf, size,
1128 "caudio;%s;%g;%ld;(%g;%" B_PRIu32 ";0x%" B_PRIx32 ";%" B_PRIu32
1129 ";0x%" B_PRIxSIZE ";0x%08" B_PRIx32 ";%d;0x%04x)",
1130 encoding,
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);
1141 return true;
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";
1148 snprintf(buf, size,
1149 "cvideo;%s;%g;%g;%" B_PRIuSIZE ";(%g;0x%x;%" B_PRIu32 ";%" B_PRIu32
1150 ";%" B_PRIu32 ";%" B_PRIu32 ";%s;%d;%d)",
1151 encoding,
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,
1161 videoOrientation,
1162 f.u.encoded_video.output.pixel_width_aspect,
1163 f.u.encoded_video.output.pixel_height_aspect);
1164 return true;
1165 default:
1166 snprintf(buf, size, "%d-", f.type);
1167 unsigned char* p = (unsigned char*)&(f.u);
1168 size -= strlen(buf);
1169 buf += strlen(buf);
1170 for (int i = 0; (size > 2) && (i < 96); i++) {
1171 snprintf(buf, 3, "%2.2x", *(p + i));
1172 buf+=2;
1173 size-=2;
1175 return true; // ?
1177 return false;
1181 // #pragma mark -
1184 bool
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;
1192 bool
1193 operator<(const media_file_format_id& a, const media_file_format_id& b)
1195 return a.internal_id < b.internal_id;
1199 // #pragma mark -
1202 //! Use this function to iterate through available file format writers.
1203 status_t
1204 get_next_file_format(int32* cookie, media_file_format* mff)
1206 if (cookie == NULL || mff == NULL)
1207 return B_BAD_VALUE;
1209 status_t ret = AddOnManager::GetInstance()->GetFileFormat(mff, *cookie);
1210 if (ret != B_OK)
1211 return ret;
1213 *cookie = *cookie + 1;
1215 return B_OK;
1219 // #pragma mark -
1222 // final & verified
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;
1229 // #pragma mark -
1232 // shutdown_media_server() and launch_media_server()
1233 // are provided by libbe.so in BeOS R5
1235 #define MEDIA_SERVICE_NOTIFICATION_ID "MediaServiceNotificationID"
1238 void
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);
1247 app_info info;
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();
1258 void
1259 progress_shutdown(int stage,
1260 bool (*progress)(int stage, const char* message, void* cookie),
1261 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";
1268 switch (stage) {
1269 case 10:
1270 string = B_TRANSLATE("Stopping media server" B_UTF8_ELLIPSIS);
1271 break;
1272 case 20:
1273 string = B_TRANSLATE("Waiting for media_server to quit.");
1274 break;
1275 case 40:
1276 string = B_TRANSLATE("Telling media_addon_server to quit.");
1277 break;
1278 case 50:
1279 string = B_TRANSLATE("Waiting for media_addon_server to quit.");
1280 break;
1281 case 70:
1282 string = B_TRANSLATE("Cleaning up.");
1283 break;
1284 case 100:
1285 string = B_TRANSLATE("Done shutting down.");
1286 break;
1289 if (progress == NULL)
1290 notify_system(stage / 100.0f, string);
1291 else
1292 progress(stage, string, cookie);
1296 status_t
1297 shutdown_media_server(bigtime_t timeout,
1298 bool (*progress)(int stage, const char* message, void* cookie),
1299 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)
1307 return err;
1309 if (progress == NULL && roster->Lock()) {
1310 MediaRosterEx(roster)->EnableLaunchNotification(true, true);
1311 roster->Unlock();
1314 if ((err = msg.AddBool("be:_user_request", true)) != B_OK)
1315 return err;
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) {
1321 BMessage reply;
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)
1331 return err;
1333 progress_shutdown(20, progress, cookie);
1335 int32 rv;
1336 if (reply.FindInt32("error", &rv) == B_OK && rv != B_OK)
1337 return rv;
1340 if (addOnServer != B_ERROR) {
1341 shutdown = false;
1342 BMessage reply;
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)
1355 return err;
1357 progress_shutdown(50, progress, cookie);
1359 int32 rv;
1360 if (reply.FindInt32("error", &rv) == B_OK && rv != B_OK)
1361 return rv;
1365 progress_shutdown(100, progress, cookie);
1366 return B_OK;
1370 void
1371 progress_startup(int stage,
1372 bool (*progress)(int stage, const char* message, void* cookie),
1373 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";
1380 switch (stage) {
1381 case 10:
1382 string = B_TRANSLATE("Stopping media server" B_UTF8_ELLIPSIS);
1383 break;
1384 case 20:
1385 string = B_TRANSLATE("Stopping media_addon_server.");
1386 break;
1387 case 50:
1388 string = B_TRANSLATE("Starting media_services.");
1389 break;
1390 case 90:
1391 string = B_TRANSLATE("Error occurred starting media services.");
1392 break;
1393 case 100:
1394 string = B_TRANSLATE("Ready for use.");
1395 break;
1398 if (progress == NULL)
1399 notify_system(stage / 100.0f, string);
1400 else
1401 progress(stage, string, cookie);
1405 status_t
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)
1416 return err;
1418 if (progress == NULL && roster->Lock()) {
1419 MediaRosterEx(roster)->EnableLaunchNotification(true, true);
1420 roster->Unlock();
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);
1439 if (err != B_OK)
1440 progress_startup(90, progress, cookie);
1441 else if (progress != NULL) {
1442 progress_startup(100, progress, cookie);
1443 err = B_OK;
1446 return err;
1450 // #pragma mark - media_encode_info
1453 media_encode_info::media_encode_info()
1455 flags = 0;
1456 used_data_size = 0;
1457 start_time = 0;
1458 time_to_encode = INT64_MAX;
1459 file_format_data = NULL;
1460 file_format_data_size = 0;
1461 codec_data = NULL;
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;
1471 codec_data = NULL;
1472 codec_data_size = 0;