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