xref: /haiku/src/kits/media/MediaDefs.cpp (revision 6eafb4b041ad79cb936b2041fdb9c56b1209cc10)
1 /*
2  * Copyright 2004, 2006, Jérôme Duval.
3  * Copyright 2003-2004, Andrew Bachmann.
4  * Copyright 2002-2004, 2006 Marcus Overhagen.
5  * Copyright 2002, Eric Jaessler.
6  * All rights reserved. Distributed under the terms of the MIT license.
7  */
8 
9 
10 #include <inttypes.h>
11 #include <stdio.h>
12 #include <string.h>
13 
14 #include <MediaDefs.h>
15 #include <MediaNode.h>
16 #include <Roster.h>
17 
18 #include "debug.h"
19 
20 #include "AddOnManager.h"
21 #include "DataExchange.h"
22 #include "MediaMisc.h"
23 
24 
25 #define META_DATA_MAX_SIZE			(16 << 20)
26 #define META_DATA_AREA_MIN_SIZE		32000
27 
28 
29 // #pragma mark - media_destination
30 
31 
32 media_destination::media_destination(port_id port, int32 id)
33 	:
34 	port(port),
35 	id(id)
36 {
37 }
38 
39 
40 media_destination::media_destination(const media_destination& clone)
41 	:
42 	port(clone.port),
43 	id(clone.id)
44 {
45 }
46 
47 
48 media_destination&
49 media_destination::operator=(const media_destination& clone)
50 {
51 	port = clone.port;
52 	id = clone.id;
53 	return *this;
54 }
55 
56 
57 media_destination::media_destination()
58 	:
59 	port(-1),
60 	id(-1)
61 {
62 }
63 
64 
65 media_destination::~media_destination()
66 {
67 }
68 
69 
70 media_destination media_destination::null(-1, -1);
71 
72 
73 // #pragma mark - media_source
74 
75 
76 media_source::media_source(port_id port,
77 						   int32 id)
78 	:
79 	port(port),
80 	id(id)
81 {
82 }
83 
84 
85 media_source::media_source(const media_source& clone)
86 	:
87 	port(clone.port),
88 	id(clone.id)
89 {
90 }
91 
92 
93 media_source&
94 media_source::operator=(const media_source& clone)
95 {
96 	port = clone.port;
97 	id = clone.id;
98 	return *this;
99 }
100 
101 
102 media_source::media_source()
103 	:
104 	port(-1),
105 	id(-1)
106 {
107 }
108 
109 
110 media_source::~media_source()
111 {
112 }
113 
114 
115 media_source media_source::null(-1, -1);
116 
117 
118 // #pragma mark -
119 
120 
121 bool
122 operator==(const media_destination& a, const media_destination& b)
123 {
124 	return a.port == b.port && a.id == b.id;
125 }
126 
127 
128 bool
129 operator!=(const media_destination& a, const media_destination& b)
130 {
131 	return a.port != b.port || a.id != b.id;
132 }
133 
134 
135 bool
136 operator<(const media_destination& a, const media_destination& b)
137 {
138 	UNIMPLEMENTED();
139 	return false;
140 }
141 
142 
143 bool
144 operator==(const media_source& a, const media_source& b)
145 {
146 	return a.port == b.port && a.id == b.id;
147 }
148 
149 
150 bool
151 operator!=(const media_source& a, const media_source& b)
152 {
153 	return a.port != b.port || a.id != b.id;
154 }
155 
156 
157 bool
158 operator<(const media_source& a, const media_source& b)
159 {
160 	UNIMPLEMENTED();
161 	return false;
162 }
163 
164 
165 bool
166 operator==(const media_node& a, const media_node& b)
167 {
168 	return a.node == b.node && a.port == b.port && a.kind == b.kind;
169 }
170 
171 
172 bool
173 operator!=(const media_node& a, const media_node& b)
174 {
175 	return a.node != b.node || a.port != b.port || a.kind != b.kind;
176 }
177 
178 
179 bool
180 operator<(const media_node& a, const media_node& b)
181 {
182 	UNIMPLEMENTED();
183 	return false;
184 }
185 
186 
187 // #pragma mark -
188 
189 
190 media_multi_audio_format media_raw_audio_format::wildcard;
191 
192 media_multi_audio_format media_multi_audio_format::wildcard;
193 
194 media_encoded_audio_format media_encoded_audio_format::wildcard = {{0}};
195 
196 media_video_display_info media_video_display_info::wildcard = {(color_space)0};
197 
198 media_raw_video_format media_raw_video_format::wildcard = {0};
199 
200 media_encoded_video_format media_encoded_video_format::wildcard = {{0}};
201 
202 media_multistream_format media_multistream_format::wildcard = {0};
203 
204 
205 // #pragma mark - media_format::Matches() support
206 
207 
208 static bool
209 raw_audio_format_matches(const media_raw_audio_format& a,
210 	const media_raw_audio_format& b)
211 {
212 	if (a.frame_rate != 0 && b.frame_rate != 0 && a.frame_rate != b.frame_rate)
213 		return false;
214 	if (a.channel_count != 0 && b.channel_count != 0
215 		&& a.channel_count != b.channel_count) {
216 		return false;
217 	}
218 	if (a.format != 0 && b.format != 0 && a.format != b.format)
219 		return false;
220 	if (a.byte_order != 0 && b.byte_order != 0 && a.byte_order != b.byte_order)
221 		return false;
222 	if (a.buffer_size != 0 && b.buffer_size != 0
223 		&& a.buffer_size != b.buffer_size) {
224 		return false;
225 	}
226 	if (a.frame_rate != 0 && b.frame_rate != 0 && a.frame_rate != b.frame_rate)
227 		return false;
228 	return true;
229 }
230 
231 
232 static bool
233 multi_audio_info_matches(const media_multi_audio_info& a,
234 	const media_multi_audio_info& b)
235 {
236 	if (a.channel_mask != 0 && b.channel_mask != 0
237 		&& a.channel_mask != b.channel_mask) {
238 		return false;
239 	}
240 	if (a.valid_bits != 0 && b.valid_bits != 0 && a.valid_bits != b.valid_bits)
241 		return false;
242 	if (a.matrix_mask != 0 && b.matrix_mask != 0
243 		&& a.matrix_mask != b.matrix_mask) {
244 		return false;
245 	}
246 	return true;
247 }
248 
249 
250 static bool
251 multi_audio_format_matches(const media_multi_audio_format& a,
252 	const media_multi_audio_format& b)
253 {
254 	return raw_audio_format_matches(a, b) && multi_audio_info_matches(a, b);
255 }
256 
257 
258 static bool
259 raw_video_format_matches(const media_raw_video_format& a,
260 	const media_raw_video_format& b)
261 {
262 	if (a.field_rate != 0 && b.field_rate != 0
263 		&& a.field_rate != b.field_rate) {
264 		return false;
265 	}
266 	if (a.interlace != 0 && b.interlace != 0
267 		&& a.interlace != b.interlace) {
268 		return false;
269 	}
270 	if (a.first_active != 0 && b.first_active != 0
271 		&& a.first_active != b.first_active) {
272 		return false;
273 	}
274 	if (a.last_active != 0 && b.last_active != 0
275 		&& a.last_active != b.last_active) {
276 		return false;
277 	}
278 	if (a.orientation != 0 && b.orientation != 0
279 		&& a.orientation != b.orientation) {
280 		return false;
281 	}
282 	if (a.pixel_width_aspect != 0 && b.pixel_width_aspect != 0
283 		&& a.pixel_width_aspect != b.pixel_width_aspect) {
284 		return false;
285 	}
286 	if (a.pixel_height_aspect != 0 && b.pixel_height_aspect != 0
287 		&& a.pixel_height_aspect != b.pixel_height_aspect) {
288 		return false;
289 	}
290 	if (a.display.format != 0 && b.display.format != 0
291 		&& a.display.format != b.display.format) {
292 		return false;
293 	}
294 	if (a.display.line_width != 0 && b.display.line_width != 0
295 		&& a.display.line_width != b.display.line_width) {
296 		return false;
297 	}
298 	if (a.display.line_count != 0 && b.display.line_count != 0
299 		&& a.display.line_count != b.display.line_count) {
300 		return false;
301 	}
302 	if (a.display.bytes_per_row != 0 && b.display.bytes_per_row != 0
303 		&& a.display.bytes_per_row != b.display.bytes_per_row) {
304 		return false;
305 	}
306 	if (a.display.pixel_offset != 0 && b.display.pixel_offset != 0
307 		&& a.display.pixel_offset != b.display.pixel_offset) {
308 		return false;
309 	}
310 	if (a.display.line_offset != 0 && b.display.line_offset != 0
311 		&& a.display.line_offset != b.display.line_offset) {
312 		return false;
313 	}
314 	if (a.display.flags != 0 && b.display.flags != 0
315 		&& a.display.flags != b.display.flags) {
316 		return false;
317 	}
318 
319 	return true;
320 }
321 
322 
323 static bool
324 multistream_format_matches(const media_multistream_format& a,
325 	const media_multistream_format& b)
326 {
327 	if (a.avg_bit_rate != 0 && b.avg_bit_rate != 0
328 		&& a.avg_bit_rate != b.avg_bit_rate) {
329 		return false;
330 	}
331 	if (a.max_bit_rate != 0 && b.max_bit_rate != 0
332 		&& a.max_bit_rate != b.max_bit_rate) {
333 		return false;
334 	}
335 	if (a.avg_chunk_size != 0 && b.avg_chunk_size != 0
336 		&& a.avg_chunk_size != b.avg_chunk_size) {
337 		return false;
338 	}
339 	if (a.max_chunk_size != 0 && b.max_chunk_size != 0
340 		&& a.max_chunk_size != b.max_chunk_size) {
341 		return false;
342 	}
343 	if (a.flags != 0 && b.flags != 0 && a.flags != b.flags)
344 		return false;
345 	if (a.format != 0 && b.format != 0 && a.format != b.format)
346 		return false;
347 
348 	if (a.format == 0 && b.format == 0) {
349 		// TODO: How do we compare two formats with no type?
350 		return true;
351 	}
352 
353 	switch ((a.format != 0) ? a.format : b.format) {
354 		default:
355 			return true; // TODO: really?
356 
357 		case media_multistream_format::B_VID:
358 			if (a.u.vid.frame_rate != 0 && b.u.vid.frame_rate != 0
359 				&& a.u.vid.frame_rate != b.u.vid.frame_rate) {
360 				return false;
361 			}
362 			if (a.u.vid.width != 0 && b.u.vid.width != 0
363 				&& a.u.vid.width != b.u.vid.width) {
364 				return false;
365 			}
366 			if (a.u.vid.height != 0 && b.u.vid.height != 0
367 				&& a.u.vid.height != b.u.vid.height) {
368 				return false;
369 			}
370 			if (a.u.vid.space != 0 && b.u.vid.space != 0
371 				&& a.u.vid.space != b.u.vid.space) {
372 				return false;
373 			}
374 			if (a.u.vid.sampling_rate != 0 && b.u.vid.sampling_rate != 0
375 				&& a.u.vid.sampling_rate != b.u.vid.sampling_rate) {
376 				return false;
377 			}
378 			if (a.u.vid.sample_format != 0 && b.u.vid.sample_format != 0
379 				&& a.u.vid.sample_format != b.u.vid.sample_format) {
380 				return false;
381 			}
382 			if (a.u.vid.byte_order != 0 && b.u.vid.byte_order != 0
383 				&& a.u.vid.byte_order != b.u.vid.byte_order) {
384 				return false;
385 			}
386 			if (a.u.vid.channel_count != 0 && b.u.vid.channel_count != 0
387 				&& a.u.vid.channel_count != b.u.vid.channel_count) {
388 				return false;
389 			}
390 			return true;
391 
392 		case media_multistream_format::B_AVI:
393 			if (a.u.avi.us_per_frame != 0 && b.u.avi.us_per_frame != 0
394 				&& a.u.avi.us_per_frame != b.u.avi.us_per_frame) {
395 				return false;
396 			}
397 			if (a.u.avi.width != 0 && b.u.avi.width != 0
398 				&& a.u.avi.width != b.u.avi.width) {
399 				return false;
400 			}
401 			if (a.u.avi.height != 0 && b.u.avi.height != 0
402 				&& a.u.avi.height != b.u.avi.height) {
403 				return false;
404 			}
405 			if (a.u.avi.type_count != 0 && b.u.avi.type_count != 0
406 				&& a.u.avi.type_count != b.u.avi.type_count) {
407 				return false;
408 			}
409 			if (a.u.avi.types[0] != 0 && b.u.avi.types[0] != 0
410 				&& a.u.avi.types[0] != b.u.avi.types[0]) {
411 				return false;
412 			}
413 			if (a.u.avi.types[1] != 0 && b.u.avi.types[1] != 0
414 				&& a.u.avi.types[1] != b.u.avi.types[1]) {
415 				return false;
416 			}
417 			if (a.u.avi.types[2] != 0 && b.u.avi.types[2] != 0
418 				&& a.u.avi.types[2] != b.u.avi.types[2]) {
419 				return false;
420 			}
421 			if (a.u.avi.types[3] != 0 && b.u.avi.types[3] != 0
422 				&& a.u.avi.types[3] != b.u.avi.types[3]) {
423 				return false;
424 			}
425 			if (a.u.avi.types[4] != 0 && b.u.avi.types[4] != 0
426 				&& a.u.avi.types[4] != b.u.avi.types[4]) {
427 				return false;
428 			}
429 			return true;
430 	}
431 }
432 
433 
434 static bool
435 encoded_audio_format_matches(const media_encoded_audio_format& a,
436 	const media_encoded_audio_format& b)
437 {
438 	if (!raw_audio_format_matches(a.output, b.output))
439 		return false;
440 	if (a.encoding != 0 && b.encoding != 0 && a.encoding != b.encoding)
441 		return false;
442 	if (a.bit_rate != 0 && b.bit_rate != 0 && a.bit_rate != b.bit_rate)
443 		return false;
444 	if (a.frame_size != 0 && b.frame_size != 0 && a.frame_size != b.frame_size)
445 		return false;
446 	if (!multi_audio_info_matches(a.multi_info, b.multi_info))
447 		return false;
448 
449 	if (a.encoding == 0 && b.encoding == 0)
450 		return true; // can't compare
451 
452 	switch((a.encoding != 0) ? a.encoding : b.encoding) {
453 		case media_encoded_audio_format::B_ANY:
454 		default:
455 			return true;
456 	}
457 }
458 
459 
460 static bool
461 encoded_video_format_matches(const media_encoded_video_format& a,
462 	const media_encoded_video_format& b)
463 {
464 	if (!raw_video_format_matches(a.output, b.output))
465 		return false;
466 	if (a.encoding != 0 && b.encoding != 0 && a.encoding != b.encoding)
467 		return false;
468 
469 	if (a.avg_bit_rate != 0 && b.avg_bit_rate != 0
470 		&& a.avg_bit_rate != b.avg_bit_rate) {
471 		return false;
472 	}
473 	if (a.max_bit_rate != 0 && b.max_bit_rate != 0
474 		&& a.max_bit_rate != b.max_bit_rate) {
475 		return false;
476 	}
477 	if (a.frame_size != 0 && b.frame_size != 0
478 		&& a.frame_size != b.frame_size) {
479 		return false;
480 	}
481 	if (a.forward_history != 0 && b.forward_history != 0
482 		&& a.forward_history != b.forward_history) {
483 		return false;
484 	}
485 	if (a.backward_history != 0 && b.backward_history != 0
486 		&& a.backward_history != b.backward_history) {
487 		return false;
488 	}
489 
490 	if (a.encoding == 0 && b.encoding == 0)
491 		return true; // can't compare
492 
493 	switch((a.encoding != 0) ? a.encoding : b.encoding) {
494 		case media_encoded_video_format::B_ANY:
495 		default:
496 			return true;
497 	}
498 }
499 
500 
501 // #pragma mark - media_format::SpecializeTo() support
502 
503 
504 static void
505 raw_audio_format_specialize(media_raw_audio_format* format,
506 	const media_raw_audio_format* other)
507 {
508 	if (format->frame_rate == 0)
509 		format->frame_rate = other->frame_rate;
510 	if (format->channel_count == 0)
511 		format->channel_count = other->channel_count;
512 	if (format->format == 0)
513 		format->format = other->format;
514 	if (format->byte_order == 0)
515 		format->byte_order = other->byte_order;
516 	if (format->buffer_size == 0)
517 		format->buffer_size = other->buffer_size;
518 	if (format->frame_rate == 0)
519 		format->frame_rate = other->frame_rate;
520 }
521 
522 
523 static void
524 multi_audio_info_specialize(media_multi_audio_info* format,
525 	const media_multi_audio_info* other)
526 {
527 	if (format->channel_mask == 0)
528 		format->channel_mask = other->channel_mask;
529 	if (format->valid_bits == 0)
530 		format->valid_bits = other->valid_bits;
531 	if (format->matrix_mask == 0)
532 		format->matrix_mask = other->matrix_mask;
533 }
534 
535 
536 static void
537 multi_audio_format_specialize(media_multi_audio_format* format,
538 	const media_multi_audio_format* other)
539 {
540 	raw_audio_format_specialize(format, other);
541 	multi_audio_info_specialize(format, other);
542 }
543 
544 
545 static void
546 raw_video_format_specialize(media_raw_video_format* format,
547 	const media_raw_video_format* other)
548 {
549 	if (format->field_rate == 0)
550 		format->field_rate = other->field_rate;
551 	if (format->interlace == 0)
552 		format->interlace = other->interlace;
553 	if (format->first_active == 0)
554 		format->first_active = other->first_active;
555 	if (format->last_active == 0)
556 		format->last_active = other->last_active;
557 	if (format->orientation == 0)
558 		format->orientation = other->orientation;
559 	if (format->pixel_width_aspect == 0)
560 		format->pixel_width_aspect = other->pixel_width_aspect;
561 	if (format->pixel_height_aspect == 0)
562 		format->pixel_height_aspect = other->pixel_height_aspect;
563 	if (format->display.format == 0)
564 		format->display.format = other->display.format;
565 	if (format->display.line_width == 0)
566 		format->display.line_width = other->display.line_width;
567 	if (format->display.line_count == 0)
568 		format->display.line_count = other->display.line_count;
569 	if (format->display.bytes_per_row == 0)
570 		format->display.bytes_per_row = other->display.bytes_per_row;
571 	if (format->display.pixel_offset == 0)
572 		format->display.pixel_offset = other->display.pixel_offset;
573 	if (format->display.line_offset == 0)
574 		format->display.line_offset = other->display.line_offset;
575 	if (format->display.flags == 0)
576 		format->display.flags = other->display.flags;
577 }
578 
579 
580 static void
581 multistream_format_specialize(media_multistream_format* format,
582 	const media_multistream_format* other)
583 {
584 	if (format->avg_bit_rate == 0)
585 		format->avg_bit_rate = other->avg_bit_rate;
586 	if (format->max_bit_rate == 0)
587 		format->max_bit_rate = other->max_bit_rate;
588 	if (format->avg_chunk_size == 0)
589 		format->avg_chunk_size = other->avg_chunk_size;
590 	if (format->max_chunk_size == 0)
591 		format->max_chunk_size = other->max_chunk_size;
592 	if (format->flags == 0)
593 		format->flags = other->flags;
594 	if (format->format == 0)
595 		format->format = other->format;
596 
597 	switch (format->format) {
598 		case media_multistream_format::B_VID:
599 			if (format->u.vid.frame_rate == 0)
600 				format->u.vid.frame_rate = other->u.vid.frame_rate;
601 			if (format->u.vid.width == 0)
602 				format->u.vid.width = other->u.vid.width;
603 			if (format->u.vid.height == 0)
604 				format->u.vid.height = other->u.vid.height;
605 			if (format->u.vid.space == 0)
606 				format->u.vid.space = other->u.vid.space;
607 			if (format->u.vid.sampling_rate == 0)
608 				format->u.vid.sampling_rate = other->u.vid.sampling_rate;
609 			if (format->u.vid.sample_format == 0)
610 				format->u.vid.sample_format = other->u.vid.sample_format;
611 			if (format->u.vid.byte_order == 0)
612 				format->u.vid.byte_order = other->u.vid.byte_order;
613 			if (format->u.vid.channel_count == 0)
614 				format->u.vid.channel_count = other->u.vid.channel_count;
615 			break;
616 
617 		case media_multistream_format::B_AVI:
618 			if (format->u.avi.us_per_frame == 0)
619 				format->u.avi.us_per_frame = other->u.avi.us_per_frame;
620 			if (format->u.avi.width == 0)
621 				format->u.avi.width = other->u.avi.width;
622 			if (format->u.avi.height == 0)
623 				format->u.avi.height = other->u.avi.height;
624 			if (format->u.avi.type_count == 0)
625 				format->u.avi.type_count = other->u.avi.type_count;
626 			if (format->u.avi.types[0] == 0)
627 				format->u.avi.types[0] = other->u.avi.types[0];
628 			if (format->u.avi.types[1] == 0)
629 				format->u.avi.types[1] = other->u.avi.types[1];
630 			if (format->u.avi.types[2] == 0)
631 				format->u.avi.types[2] = other->u.avi.types[2];
632 			if (format->u.avi.types[3] == 0)
633 				format->u.avi.types[3] = other->u.avi.types[3];
634 			if (format->u.avi.types[4] == 0)
635 				format->u.avi.types[4] = other->u.avi.types[4];
636 			break;
637 
638 		default:
639 			ERROR("media_format::SpecializeTo can't specialize "
640 				"media_multistream_format of format %" B_PRId32 "\n",
641 				format->format);
642 	}
643 }
644 
645 
646 static void
647 encoded_audio_format_specialize(media_encoded_audio_format* format,
648 	const media_encoded_audio_format* other)
649 {
650 	raw_audio_format_specialize(&format->output, &other->output);
651 	if (format->encoding == 0)
652 		format->encoding = other->encoding;
653 	if (format->bit_rate == 0)
654 		format->bit_rate = other->bit_rate;
655 	if (format->frame_size == 0)
656 		format->frame_size = other->frame_size;
657 	multi_audio_info_specialize(&format->multi_info, &other->multi_info);
658 }
659 
660 
661 static void
662 encoded_video_format_specialize(media_encoded_video_format* format,
663 	const media_encoded_video_format* other)
664 {
665 	raw_video_format_specialize(&format->output, &other->output);
666 	if (format->avg_bit_rate == 0)
667 		format->avg_bit_rate = other->avg_bit_rate;
668 	if (format->max_bit_rate == 0)
669 		format->max_bit_rate = other->max_bit_rate;
670 	if (format->encoding == 0)
671 		format->encoding = other->encoding;
672 	if (format->frame_size == 0)
673 		format->frame_size = other->frame_size;
674 	if (format->forward_history == 0)
675 		format->forward_history = other->forward_history;
676 	if (format->backward_history == 0)
677 		format->backward_history = other->backward_history;
678 }
679 
680 
681 // #pragma mark - media_format
682 
683 
684 bool
685 media_format::Matches(const media_format* other) const
686 {
687 	CALLED();
688 
689 	if (type == 0 && other->type == 0) {
690 		// TODO: How do we compare two formats with no type?
691 		return true;
692 	}
693 
694 	if (type != 0 && other->type != 0 && type != other->type)
695 		return false;
696 
697 	switch ((type != 0) ? type : other->type) {
698 		case B_MEDIA_RAW_AUDIO:
699 			return multi_audio_format_matches(u.raw_audio, other->u.raw_audio);
700 
701 		case B_MEDIA_RAW_VIDEO:
702 			return raw_video_format_matches(u.raw_video, other->u.raw_video);
703 
704 		case B_MEDIA_MULTISTREAM:
705 			return multistream_format_matches(u.multistream,
706 				other->u.multistream);
707 
708 		case B_MEDIA_ENCODED_AUDIO:
709 			return encoded_audio_format_matches(u.encoded_audio,
710 				other->u.encoded_audio);
711 
712 		case B_MEDIA_ENCODED_VIDEO:
713 			return encoded_video_format_matches(u.encoded_video,
714 				other->u.encoded_video);
715 
716 		default:
717 			return true; // TODO: really?
718 	}
719 }
720 
721 
722 void
723 media_format::SpecializeTo(const media_format* otherFormat)
724 {
725 	CALLED();
726 
727 	if (type == 0 && otherFormat->type == 0) {
728 		ERROR("media_format::SpecializeTo can't specialize wildcard to other "
729 			"wildcard format\n");
730 		return;
731 	}
732 
733 	if (type == 0)
734 		type = otherFormat->type;
735 
736 	switch (type) {
737 		case B_MEDIA_RAW_AUDIO:
738 			multi_audio_format_specialize(&u.raw_audio,
739 				&otherFormat->u.raw_audio);
740 			return;
741 
742 		case B_MEDIA_RAW_VIDEO:
743 			raw_video_format_specialize(&u.raw_video,
744 				&otherFormat->u.raw_video);
745 			return;
746 
747 		case B_MEDIA_MULTISTREAM:
748 			multistream_format_specialize(&u.multistream,
749 				&otherFormat->u.multistream);
750 			return;
751 
752 		case B_MEDIA_ENCODED_AUDIO:
753 			encoded_audio_format_specialize(&u.encoded_audio,
754 				&otherFormat->u.encoded_audio);
755 			return;
756 
757 		case B_MEDIA_ENCODED_VIDEO:
758 			encoded_video_format_specialize(&u.encoded_video,
759 				&otherFormat->u.encoded_video);
760 			return;
761 
762 		default:
763 			ERROR("media_format::SpecializeTo can't specialize format "
764 				"type %d\n", type);
765 	}
766 }
767 
768 
769 status_t
770 media_format::SetMetaData(const void* data, size_t size)
771 {
772 	if (!data || size < 0 || size > META_DATA_MAX_SIZE)
773 		return B_BAD_VALUE;
774 
775 	void* new_addr;
776 	area_id new_area;
777 	if (size < META_DATA_AREA_MIN_SIZE) {
778 		new_area = B_BAD_VALUE;
779 		new_addr = malloc(size);
780 		if (!new_addr)
781 			return B_NO_MEMORY;
782 	} else {
783 		new_area = create_area("meta_data_area", &new_addr, B_ANY_ADDRESS,
784 			ROUND_UP_TO_PAGE(size), B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
785 		if (new_area < 0)
786 			return (status_t)new_area;
787 	}
788 
789 	if (meta_data_area > 0)
790 		delete_area(meta_data_area);
791 	else
792 		free(meta_data);
793 
794 	meta_data = new_addr;
795 	meta_data_size = size;
796 	meta_data_area = new_area;
797 
798 	memcpy(meta_data, data, size);
799 
800 	if (meta_data_area > 0)
801 		set_area_protection(meta_data_area, B_READ_AREA);
802 
803 	return B_OK;
804 }
805 
806 
807 const void*
808 media_format::MetaData() const
809 {
810 	return meta_data;
811 }
812 
813 
814 int32
815 media_format::MetaDataSize() const
816 {
817 	return meta_data_size;
818 }
819 
820 
821 media_format::media_format()
822 {
823 	memset(this, 0x00, sizeof(*this));
824 	meta_data_area = B_BAD_VALUE;
825 }
826 
827 
828 media_format::media_format(const media_format& other)
829 {
830 	memset(this, 0x00, sizeof(*this));
831 	meta_data_area = B_BAD_VALUE;
832 	*this = other;
833 }
834 
835 
836 media_format::~media_format()
837 {
838 	if (meta_data_area > 0)
839 		delete_area(meta_data_area);
840 	else
841 		free(meta_data);
842 }
843 
844 
845 // final
846 media_format&
847 media_format::operator=(const media_format& clone)
848 {
849 	// get rid of this format's meta data
850 	this->~media_format();
851 		// danger: using only ~media_format() would call the constructor
852 
853 	// make a binary copy
854 	memcpy(this, &clone, sizeof(*this));
855 	// some binary copies are invalid:
856 	meta_data = NULL;
857 	meta_data_area = B_BAD_VALUE;
858 
859 	// clone or copy the meta data
860 	if (clone.meta_data) {
861 		if (clone.meta_data_area != B_BAD_VALUE) {
862 			meta_data_area = clone_area("meta_data_clone_area", &meta_data,
863 				B_ANY_ADDRESS, B_READ_AREA, clone.meta_data_area);
864 			if (meta_data_area < 0) {
865 				// whoops, we just lost our meta data
866 				meta_data = NULL;
867 				meta_data_size = 0;
868 			}
869 		} else {
870 			meta_data = malloc(meta_data_size);
871 			if (meta_data) {
872 				memcpy(meta_data, clone.meta_data, meta_data_size);
873 			} else {
874 				// whoops, we just lost our meta data
875 				meta_data_size = 0;
876 			}
877 		}
878 	}
879 	return *this;
880 }
881 
882 
883 // #pragma mark -
884 
885 
886 bool
887 operator==(const media_raw_audio_format& a, const media_raw_audio_format& b)
888 {
889 	return a.frame_rate == b.frame_rate
890 		&& a.channel_count == b.channel_count
891 		&& a.format == b.format
892 		&& a.byte_order == b.byte_order
893 		&& a.buffer_size == b.buffer_size;
894 }
895 
896 
897 bool
898 operator==(const media_multi_audio_info& a, const media_multi_audio_info& b)
899 {
900 	return a.channel_mask == b.channel_mask
901 		&& a.valid_bits == b.valid_bits
902 		&& a.matrix_mask == b.matrix_mask;
903 }
904 
905 
906 bool
907 operator==(const media_multi_audio_format& a,
908 	const media_multi_audio_format& b)
909 {
910 	return (media_raw_audio_format)a == (media_raw_audio_format)b
911 		&& (media_multi_audio_info)a == (media_multi_audio_info)b;
912 }
913 
914 
915 bool
916 operator==(const media_encoded_audio_format& a,
917 	const media_encoded_audio_format& b)
918 {
919 	return a.output == b.output
920 		&& a.encoding == b.encoding
921 		&& a.bit_rate == b.bit_rate
922 		&& a.frame_size == b.frame_size
923 		&& a.multi_info == b.multi_info;
924 }
925 
926 
927 bool
928 operator==(const media_video_display_info& a,
929 	const media_video_display_info& b)
930 {
931 	return a.format == b.format
932 		&& a.line_width == b.line_width
933 		&& a.line_count == b.line_count
934 		&& a.bytes_per_row == b.bytes_per_row
935 		&& a.pixel_offset == b.pixel_offset
936 		&& a.line_offset == b.line_offset
937 		&& a.flags == b.flags;
938 }
939 
940 
941 bool
942 operator==(const media_raw_video_format& a, const media_raw_video_format& b)
943 {
944 	return a.field_rate == b.field_rate
945 		&& a.interlace == b.interlace
946 		&& a.first_active == b.first_active
947 		&& a.last_active == b.last_active
948 		&& a.orientation == b.orientation
949 		&& a.pixel_width_aspect == b.pixel_width_aspect
950 		&& a.pixel_height_aspect == b.pixel_height_aspect
951 		&& a.display == b.display;
952 }
953 
954 
955 bool
956 operator==(const media_encoded_video_format& a,
957 	const media_encoded_video_format& b)
958 {
959 	return a.output == b.output
960 		&& a.avg_bit_rate == b.avg_bit_rate
961 		&& a.max_bit_rate == b.max_bit_rate
962 		&& a.encoding == b.encoding
963 		&& a.frame_size == b.frame_size
964 		&& a.forward_history == b.forward_history
965 		&& a.backward_history == b.backward_history;
966 }
967 
968 
969 bool
970 operator==(const media_multistream_format::vid_info& a,
971 	const media_multistream_format::vid_info& b)
972 {
973 	return a.frame_rate == b.frame_rate
974 		&& a.width == b.width
975 		&& a.height == b.height
976 		&& a.space == b.space
977 		&& a.sampling_rate == b.sampling_rate
978 		&& a.sample_format == b.sample_format
979 		&& a.byte_order == b.byte_order
980 		&& a.channel_count == b.channel_count;
981 }
982 
983 
984 bool
985 operator==(const media_multistream_format::avi_info& a,
986 	const media_multistream_format::avi_info& b)
987 {
988 	return a.us_per_frame == b.us_per_frame
989 		&& a.width == b.width
990 		&& a.height == b.height
991 		&& a.type_count == b.type_count
992 		&& a.types[0] == b.types[0]
993 		&& a.types[1] == b.types[1]
994 		&& a.types[2] == b.types[2]
995 		&& a.types[3] == b.types[3]
996 		&& a.types[4] == b.types[4];
997 }
998 
999 
1000 bool
1001 operator==(const media_multistream_format& a,
1002 	const media_multistream_format& b)
1003 {
1004 	if (a.avg_bit_rate != b.avg_bit_rate
1005 		|| a.max_bit_rate != b.max_bit_rate
1006 		|| a.avg_chunk_size != b.avg_chunk_size
1007 		|| a.max_chunk_size != b.max_chunk_size
1008 		|| a.format != b.format
1009 		|| a.flags != b.flags) {
1010 		return false;
1011 	}
1012 
1013 	switch (a.format) {
1014 		case media_multistream_format::B_VID:
1015 			return a.u.vid == b.u.vid;
1016 
1017 		case media_multistream_format::B_AVI:
1018 			return a.u.avi == b.u.avi;
1019 
1020 		default:
1021 			return true; // TODO: really?
1022 	}
1023 }
1024 
1025 
1026 bool
1027 operator==(const media_format& a, const media_format& b)
1028 {
1029 	if (a.type != b.type
1030 		|| a.user_data_type != b.user_data_type
1031 		// TODO: compare user_data[48] ?
1032 		|| a.require_flags != b.require_flags
1033 		|| a.deny_flags != b.deny_flags) {
1034 		return false;
1035 	}
1036 
1037 	switch (a.type) {
1038 		case B_MEDIA_RAW_AUDIO:
1039 			return a.u.raw_audio == b.u.raw_audio;
1040 
1041 		case B_MEDIA_RAW_VIDEO:
1042 			return a.u.raw_video == b.u.raw_video;
1043 
1044 		case B_MEDIA_MULTISTREAM:
1045 			return a.u.multistream == b.u.multistream;
1046 
1047 		case B_MEDIA_ENCODED_AUDIO:
1048 			return a.u.encoded_audio == b.u.encoded_audio;
1049 
1050 		case B_MEDIA_ENCODED_VIDEO:
1051 			return a.u.encoded_video == b.u.encoded_video;
1052 
1053 		default:
1054 			return true; // TODO: really?
1055 	}
1056 }
1057 
1058 
1059 // #pragma mark -
1060 
1061 
1062 /*! return \c true if a and b are compatible (accounting for wildcards)
1063 	a is the format you want to feed to something accepting b
1064 */
1065 bool
1066 format_is_compatible(const media_format& a, const media_format& b)
1067 {
1068 	return a.Matches(&b);
1069 }
1070 
1071 
1072 bool
1073 string_for_format(const media_format& f, char* buf, size_t size)
1074 {
1075 	char encoding[10]; /* maybe Be wanted to use some 4CCs ? */
1076 	const char* videoOrientation = "0"; /* I'd use "NC", R5 uses 0. */
1077 
1078 	if (buf == NULL)
1079 		return false;
1080 	switch (f.type) {
1081 	case B_MEDIA_RAW_AUDIO:
1082 		snprintf(buf, size,
1083 			"raw_audio;%g;%" B_PRIu32 ";0x%" B_PRIx32 ";%" B_PRIu32 ";0x%"
1084 				B_PRIxSIZE ";0x%#" B_PRIx32 ";%d;0x%04x",
1085 			f.u.raw_audio.frame_rate,
1086 			f.u.raw_audio.channel_count,
1087 			f.u.raw_audio.format,
1088 			f.u.raw_audio.byte_order,
1089 			f.u.raw_audio.buffer_size,
1090 			f.u.raw_audio.channel_mask,
1091 			f.u.raw_audio.valid_bits,
1092 			f.u.raw_audio.matrix_mask);
1093 		return true;
1094 	case B_MEDIA_RAW_VIDEO:
1095 		if (f.u.raw_video.orientation == B_VIDEO_TOP_LEFT_RIGHT)
1096 			videoOrientation = "TopLR";
1097 		else if (f.u.raw_video.orientation == B_VIDEO_BOTTOM_LEFT_RIGHT)
1098 			videoOrientation = "BotLR";
1099 		snprintf(buf, size, "raw_video;%g;0x%x;%" B_PRIu32 ";%" B_PRIu32 ";%"
1100 				B_PRIu32 ";%" B_PRIu32 ";%s;%d;%d",
1101 			f.u.raw_video.field_rate,
1102 			f.u.raw_video.display.format,
1103 			f.u.raw_video.interlace,
1104 			f.u.raw_video.display.line_width,
1105 			f.u.raw_video.display.line_count,
1106 			f.u.raw_video.first_active,
1107 			videoOrientation,
1108 			f.u.raw_video.pixel_width_aspect,
1109 			f.u.raw_video.pixel_height_aspect);
1110 		return true;
1111 	case B_MEDIA_ENCODED_AUDIO:
1112 		snprintf(encoding, 10, "%d", f.u.encoded_audio.encoding);
1113 		snprintf(buf, size,
1114 			"caudio;%s;%g;%ld;(%g;%" B_PRIu32 ";0x%" B_PRIx32 ";%" B_PRIu32
1115 				";0x%" B_PRIxSIZE ";0x%08" B_PRIx32 ";%d;0x%04x)",
1116 			encoding,
1117 			f.u.encoded_audio.bit_rate,
1118 			f.u.encoded_audio.frame_size,
1119 			f.u.encoded_audio.output.frame_rate,
1120 			f.u.encoded_audio.output.channel_count,
1121 			f.u.encoded_audio.output.format,
1122 			f.u.encoded_audio.output.byte_order,
1123 			f.u.encoded_audio.output.buffer_size,
1124 			f.u.encoded_audio.multi_info.channel_mask,
1125 			f.u.encoded_audio.multi_info.valid_bits,
1126 			f.u.encoded_audio.multi_info.matrix_mask);
1127 		return true;
1128 	case B_MEDIA_ENCODED_VIDEO:
1129 		snprintf(encoding, 10, "%d", f.u.encoded_video.encoding);
1130 		if (f.u.encoded_video.output.orientation == B_VIDEO_TOP_LEFT_RIGHT)
1131 			videoOrientation = "TopLR";
1132 		else if (f.u.encoded_video.output.orientation == B_VIDEO_BOTTOM_LEFT_RIGHT)
1133 			videoOrientation = "BotLR";
1134 		snprintf(buf, size,
1135 			"cvideo;%s;%g;%g;%" B_PRIuSIZE ";(%g;0x%x;%" B_PRIu32 ";%" B_PRIu32
1136 				";%" B_PRIu32 ";%" B_PRIu32 ";%s;%d;%d)",
1137 			encoding,
1138 			f.u.encoded_video.avg_bit_rate,
1139 			f.u.encoded_video.max_bit_rate,
1140 			f.u.encoded_video.frame_size,
1141 			f.u.encoded_video.output.field_rate,
1142 			f.u.encoded_video.output.display.format,
1143 			f.u.encoded_video.output.interlace,
1144 			f.u.encoded_video.output.display.line_width,
1145 			f.u.encoded_video.output.display.line_count,
1146 			f.u.encoded_video.output.first_active,
1147 			videoOrientation,
1148 			f.u.encoded_video.output.pixel_width_aspect,
1149 			f.u.encoded_video.output.pixel_height_aspect);
1150 		return true;
1151 	default:
1152 		snprintf(buf, size, "%d-", f.type);
1153 		unsigned char* p = (unsigned char*)&(f.u);
1154 		size -= strlen(buf);
1155 		buf += strlen(buf);
1156 		for (int i = 0; (size > 2) && (i < 96); i++) {
1157 			snprintf(buf, 3, "%2.2x", *(p + i));
1158 			buf+=2;
1159 			size-=2;
1160 		}
1161 		return true; // ?
1162 	}
1163 	return false;
1164 }
1165 
1166 
1167 // #pragma mark -
1168 
1169 
1170 bool
1171 operator==(const media_file_format_id& a, const media_file_format_id& b)
1172 {
1173 	return a.node == b.node && a.device == b.device
1174 		&& a.internal_id == b.internal_id;
1175 }
1176 
1177 
1178 bool
1179 operator<(const media_file_format_id& a, const media_file_format_id& b)
1180 {
1181 	return a.internal_id < b.internal_id;
1182 }
1183 
1184 
1185 // #pragma mark -
1186 
1187 
1188 //! Use this function to iterate through available file format writers.
1189 status_t
1190 get_next_file_format(int32* cookie, media_file_format* mff)
1191 {
1192 	if (cookie == NULL || mff == NULL)
1193 		return B_BAD_VALUE;
1194 
1195 	status_t ret = AddOnManager::GetInstance()->GetFileFormat(mff, *cookie);
1196 	if (ret != B_OK)
1197 		return ret;
1198 
1199 	*cookie = *cookie + 1;
1200 
1201 	return B_OK;
1202 }
1203 
1204 
1205 // #pragma mark -
1206 
1207 
1208 // final & verified
1209 const char* B_MEDIA_SERVER_SIGNATURE = "application/x-vnd.Be.media-server";
1210 const char* B_MEDIA_ADDON_SERVER_SIGNATURE = "application/x-vnd.Be.addon-host";
1211 
1212 const type_code B_CODEC_TYPE_INFO = 0x040807b2;
1213 
1214 
1215 // #pragma mark -
1216 
1217 
1218 // shutdown_media_server() and launch_media_server()
1219 // are provided by libbe.so in BeOS R5
1220 
1221 status_t
1222 shutdown_media_server(bigtime_t timeout,
1223 	bool (*progress)(int stage, const char* message, void* cookie),
1224 	void* cookie)
1225 {
1226 	BMessage msg(B_QUIT_REQUESTED);
1227 	BMessage reply;
1228 	status_t err;
1229 
1230 	if ((err = msg.AddBool("be:_user_request", true)) != B_OK)
1231 		return err;
1232 
1233 	if (be_roster->IsRunning(B_MEDIA_SERVER_SIGNATURE)) {
1234 		BMessenger messenger(B_MEDIA_SERVER_SIGNATURE);
1235 		progress(10, "Telling media_server to quit.", cookie);
1236 
1237 		err = messenger.SendMessage(&msg, &reply, 2000000, 2000000);
1238 		if (err != B_OK)
1239 			return err;
1240 
1241 		int32 rv;
1242 		if (reply.FindInt32("error", &rv) == B_OK && rv != B_OK)
1243 			return rv;
1244 	}
1245 
1246 	if (be_roster->IsRunning(B_MEDIA_ADDON_SERVER_SIGNATURE)) {
1247 		BMessenger messenger(B_MEDIA_ADDON_SERVER_SIGNATURE);
1248 		progress(20, "Telling media_addon_server to quit.", cookie);
1249 
1250 		err = messenger.SendMessage(&msg, &reply, 2000000, 2000000);
1251 		if (err != B_OK)
1252 			return err;
1253 
1254 		int32 rv;
1255 		if (reply.FindInt32("error", &rv) == B_OK && rv != B_OK)
1256 			return rv;
1257 	}
1258 
1259 	if (be_roster->IsRunning(B_MEDIA_SERVER_SIGNATURE)) {
1260 		progress(40, "Waiting for media_server to quit.", cookie);
1261 		snooze(200000);
1262 	}
1263 
1264 	if (be_roster->IsRunning(B_MEDIA_ADDON_SERVER_SIGNATURE)) {
1265 		progress(50, "Waiting for media_addon_server to quit.", cookie);
1266 		snooze(200000);
1267 	}
1268 
1269 	progress(70, "Cleaning Up.", cookie);
1270 	snooze(1000000);
1271 
1272 	if (be_roster->IsRunning(B_MEDIA_SERVER_SIGNATURE)) {
1273 		kill_team(be_roster->TeamFor(B_MEDIA_SERVER_SIGNATURE));
1274 	}
1275 
1276 	if (be_roster->IsRunning(B_MEDIA_ADDON_SERVER_SIGNATURE)) {
1277 		kill_team(be_roster->TeamFor(B_MEDIA_ADDON_SERVER_SIGNATURE));
1278 	}
1279 
1280 	progress(100, "Done Shutting Down.", cookie);
1281 	snooze(1000000);
1282 
1283 	return B_OK;
1284 }
1285 
1286 
1287 status_t
1288 launch_media_server(uint32 flags)
1289 {
1290 	status_t err;
1291 
1292 	if (be_roster->IsRunning(B_MEDIA_SERVER_SIGNATURE))
1293 		return B_ALREADY_RUNNING;
1294 
1295 	if (be_roster->IsRunning(B_MEDIA_ADDON_SERVER_SIGNATURE)) {
1296 		kill_team(be_roster->TeamFor(B_MEDIA_ADDON_SERVER_SIGNATURE));
1297 		snooze(1000000);
1298 	}
1299 
1300 	err = be_roster->Launch(B_MEDIA_SERVER_SIGNATURE);
1301 	if (err != B_OK)
1302 		return err;
1303 
1304 	err = B_MEDIA_SYSTEM_FAILURE;
1305 	for (int i = 0; i < 15; i++) {
1306 		snooze(2000000);
1307 
1308 		BMessage msg(1); // this is a hack
1309 		BMessage reply;
1310 		BMessenger messenger(B_MEDIA_ADDON_SERVER_SIGNATURE);
1311 
1312 		if (messenger.IsValid()) {
1313 			messenger.SendMessage(&msg, &reply, 2000000, 2000000);
1314 			err = B_OK;
1315 			break;
1316 		}
1317 	}
1318 
1319 	return err;
1320 }
1321 
1322 
1323 // #pragma mark -
1324 
1325 
1326 //	Given an image_id, prepare that image_id for realtime media
1327 //	If the kind of media indicated by "flags" is not enabled for real-time,
1328 //	B_MEDIA_REALTIME_DISABLED is returned.
1329 //	If there are not enough system resources to enable real-time performance,
1330 //	B_MEDIA_REALTIME_UNAVAILABLE is returned.
1331 status_t
1332 media_realtime_init_image(image_id image, uint32 flags)
1333 {
1334 	UNIMPLEMENTED();
1335 	return B_OK;
1336 }
1337 
1338 //	Given a thread ID, and an optional indication of what the thread is
1339 //	doing in "flags", prepare the thread for real-time media performance.
1340 //	Currently, this means locking the thread stack, up to size_used bytes,
1341 //	or all of it if 0 is passed. Typically, you will not be using all
1342 //	256 kB of the stack, so you should pass some smaller value you determine
1343 //	from profiling the thread; typically in the 32-64kB range.
1344 //	Return values are the same as for media_prepare_realtime_image().
1345 status_t
1346 media_realtime_init_thread(thread_id thread, size_t stack_used, uint32 flags)
1347 {
1348 	UNIMPLEMENTED();
1349 	return B_OK;
1350 }
1351 
1352 
1353 // #pragma mark - media_encode_info
1354 
1355 
1356 media_encode_info::media_encode_info()
1357 {
1358 	flags = 0;
1359 	used_data_size = 0;
1360 	start_time = 0;
1361 	time_to_encode = INT64_MAX;
1362 	file_format_data = NULL;
1363 	file_format_data_size = 0;
1364 	codec_data = NULL;
1365 	codec_data_size = 0;
1366 }
1367 
1368 
1369 media_decode_info::media_decode_info()
1370 {
1371 	time_to_decode = INT64_MAX;
1372 	file_format_data = NULL;
1373 	file_format_data_size = 0;
1374 	codec_data = NULL;
1375 	codec_data_size = 0;
1376 }
1377 
1378 
1379