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