xref: /haiku/src/kits/media/MediaDefs.cpp (revision f2b4344867e97c3f4e742a1b4a15e6879644601a)
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 %ld\n", format->format);
640 	}
641 }
642 
643 
644 static void
645 encoded_audio_format_specialize(media_encoded_audio_format* format,
646 	const media_encoded_audio_format* other)
647 {
648 	raw_audio_format_specialize(&format->output, &other->output);
649 	if (format->encoding == 0)
650 		format->encoding = other->encoding;
651 	if (format->bit_rate == 0)
652 		format->bit_rate = other->bit_rate;
653 	if (format->frame_size == 0)
654 		format->frame_size = other->frame_size;
655 	multi_audio_info_specialize(&format->multi_info, &other->multi_info);
656 }
657 
658 
659 static void
660 encoded_video_format_specialize(media_encoded_video_format* format,
661 	const media_encoded_video_format* other)
662 {
663 	raw_video_format_specialize(&format->output, &other->output);
664 	if (format->avg_bit_rate == 0)
665 		format->avg_bit_rate = other->avg_bit_rate;
666 	if (format->max_bit_rate == 0)
667 		format->max_bit_rate = other->max_bit_rate;
668 	if (format->encoding == 0)
669 		format->encoding = other->encoding;
670 	if (format->frame_size == 0)
671 		format->frame_size = other->frame_size;
672 	if (format->forward_history == 0)
673 		format->forward_history = other->forward_history;
674 	if (format->backward_history == 0)
675 		format->backward_history = other->backward_history;
676 }
677 
678 
679 // #pragma mark - media_format
680 
681 
682 bool
683 media_format::Matches(const media_format* other) const
684 {
685 	CALLED();
686 
687 	if (type == 0 && other->type == 0) {
688 		// TODO: How do we compare two formats with no type?
689 		return true;
690 	}
691 
692 	if (type != 0 && other->type != 0 && type != other->type)
693 		return false;
694 
695 	switch ((type != 0) ? type : other->type) {
696 		case B_MEDIA_RAW_AUDIO:
697 			return multi_audio_format_matches(u.raw_audio, other->u.raw_audio);
698 
699 		case B_MEDIA_RAW_VIDEO:
700 			return raw_video_format_matches(u.raw_video, other->u.raw_video);
701 
702 		case B_MEDIA_MULTISTREAM:
703 			return multistream_format_matches(u.multistream,
704 				other->u.multistream);
705 
706 		case B_MEDIA_ENCODED_AUDIO:
707 			return encoded_audio_format_matches(u.encoded_audio,
708 				other->u.encoded_audio);
709 
710 		case B_MEDIA_ENCODED_VIDEO:
711 			return encoded_video_format_matches(u.encoded_video,
712 				other->u.encoded_video);
713 
714 		default:
715 			return true; // TODO: really?
716 	}
717 }
718 
719 
720 void
721 media_format::SpecializeTo(const media_format* otherFormat)
722 {
723 	CALLED();
724 
725 	if (type == 0 && otherFormat->type == 0) {
726 		ERROR("media_format::SpecializeTo can't specialize wildcard to other "
727 			"wildcard format\n");
728 		return;
729 	}
730 
731 	if (type == 0)
732 		type = otherFormat->type;
733 
734 	switch (type) {
735 		case B_MEDIA_RAW_AUDIO:
736 			multi_audio_format_specialize(&u.raw_audio,
737 				&otherFormat->u.raw_audio);
738 			return;
739 
740 		case B_MEDIA_RAW_VIDEO:
741 			raw_video_format_specialize(&u.raw_video,
742 				&otherFormat->u.raw_video);
743 			return;
744 
745 		case B_MEDIA_MULTISTREAM:
746 			multistream_format_specialize(&u.multistream,
747 				&otherFormat->u.multistream);
748 			return;
749 
750 		case B_MEDIA_ENCODED_AUDIO:
751 			encoded_audio_format_specialize(&u.encoded_audio,
752 				&otherFormat->u.encoded_audio);
753 			return;
754 
755 		case B_MEDIA_ENCODED_VIDEO:
756 			encoded_video_format_specialize(&u.encoded_video,
757 				&otherFormat->u.encoded_video);
758 			return;
759 
760 		default:
761 			ERROR("media_format::SpecializeTo can't specialize format "
762 				"type %d\n", type);
763 	}
764 }
765 
766 
767 status_t
768 media_format::SetMetaData(const void* data, size_t size)
769 {
770 	if (!data || size < 0 || size > META_DATA_MAX_SIZE)
771 		return B_BAD_VALUE;
772 
773 	void* new_addr;
774 	area_id new_area;
775 	if (size < META_DATA_AREA_MIN_SIZE) {
776 		new_area = B_BAD_VALUE;
777 		new_addr = malloc(size);
778 		if (!new_addr)
779 			return B_NO_MEMORY;
780 	} else {
781 		new_area = create_area("meta_data_area", &new_addr, B_ANY_ADDRESS,
782 			ROUND_UP_TO_PAGE(size), B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
783 		if (new_area < 0)
784 			return (status_t)new_area;
785 	}
786 
787 	if (meta_data_area > 0)
788 		delete_area(meta_data_area);
789 	else
790 		free(meta_data);
791 
792 	meta_data = new_addr;
793 	meta_data_size = size;
794 	meta_data_area = new_area;
795 
796 	memcpy(meta_data, data, size);
797 
798 	if (meta_data_area > 0)
799 		set_area_protection(meta_data_area, B_READ_AREA);
800 
801 	return B_OK;
802 }
803 
804 
805 const void*
806 media_format::MetaData() const
807 {
808 	return meta_data;
809 }
810 
811 
812 int32
813 media_format::MetaDataSize() const
814 {
815 	return meta_data_size;
816 }
817 
818 
819 media_format::media_format()
820 {
821 	memset(this, 0x00, sizeof(*this));
822 	meta_data_area = B_BAD_VALUE;
823 }
824 
825 
826 media_format::media_format(const media_format& other)
827 {
828 	memset(this, 0x00, sizeof(*this));
829 	meta_data_area = B_BAD_VALUE;
830 	*this = other;
831 }
832 
833 
834 media_format::~media_format()
835 {
836 	if (meta_data_area > 0)
837 		delete_area(meta_data_area);
838 	else
839 		free(meta_data);
840 }
841 
842 
843 // final
844 media_format&
845 media_format::operator=(const media_format& clone)
846 {
847 	// get rid of this format's meta data
848 	this->~media_format();
849 		// danger: using only ~media_format() would call the constructor
850 
851 	// make a binary copy
852 	memcpy(this, &clone, sizeof(*this));
853 	// some binary copies are invalid:
854 	meta_data = NULL;
855 	meta_data_area = B_BAD_VALUE;
856 
857 	// clone or copy the meta data
858 	if (clone.meta_data) {
859 		if (clone.meta_data_area != B_BAD_VALUE) {
860 			meta_data_area = clone_area("meta_data_clone_area", &meta_data,
861 				B_ANY_ADDRESS, B_READ_AREA, clone.meta_data_area);
862 			if (meta_data_area < 0) {
863 				// whoops, we just lost our meta data
864 				meta_data = NULL;
865 				meta_data_size = 0;
866 			}
867 		} else {
868 			meta_data = malloc(meta_data_size);
869 			if (meta_data) {
870 				memcpy(meta_data, clone.meta_data, meta_data_size);
871 			} else {
872 				// whoops, we just lost our meta data
873 				meta_data_size = 0;
874 			}
875 		}
876 	}
877 	return *this;
878 }
879 
880 
881 // #pragma mark -
882 
883 
884 bool
885 operator==(const media_raw_audio_format& a, const media_raw_audio_format& b)
886 {
887 	return a.frame_rate == b.frame_rate
888 		&& a.channel_count == b.channel_count
889 		&& a.format == b.format
890 		&& a.byte_order == b.byte_order
891 		&& a.buffer_size == b.buffer_size;
892 }
893 
894 
895 bool
896 operator==(const media_multi_audio_info& a, const media_multi_audio_info& b)
897 {
898 	return a.channel_mask == b.channel_mask
899 		&& a.valid_bits == b.valid_bits
900 		&& a.matrix_mask == b.matrix_mask;
901 }
902 
903 
904 bool
905 operator==(const media_multi_audio_format& a,
906 	const media_multi_audio_format& b)
907 {
908 	return (media_raw_audio_format)a == (media_raw_audio_format)b
909 		&& (media_multi_audio_info)a == (media_multi_audio_info)b;
910 }
911 
912 
913 bool
914 operator==(const media_encoded_audio_format& a,
915 	const media_encoded_audio_format& b)
916 {
917 	return a.output == b.output
918 		&& a.encoding == b.encoding
919 		&& a.bit_rate == b.bit_rate
920 		&& a.frame_size == b.frame_size
921 		&& a.multi_info == b.multi_info;
922 }
923 
924 
925 bool
926 operator==(const media_video_display_info& a,
927 	const media_video_display_info& b)
928 {
929 	return a.format == b.format
930 		&& a.line_width == b.line_width
931 		&& a.line_count == b.line_count
932 		&& a.bytes_per_row == b.bytes_per_row
933 		&& a.pixel_offset == b.pixel_offset
934 		&& a.line_offset == b.line_offset
935 		&& a.flags == b.flags;
936 }
937 
938 
939 bool
940 operator==(const media_raw_video_format& a, const media_raw_video_format& b)
941 {
942 	return a.field_rate == b.field_rate
943 		&& a.interlace == b.interlace
944 		&& a.first_active == b.first_active
945 		&& a.last_active == b.last_active
946 		&& a.orientation == b.orientation
947 		&& a.pixel_width_aspect == b.pixel_width_aspect
948 		&& a.pixel_height_aspect == b.pixel_height_aspect
949 		&& a.display == b.display;
950 }
951 
952 
953 bool
954 operator==(const media_encoded_video_format& a,
955 	const media_encoded_video_format& b)
956 {
957 	return a.output == b.output
958 		&& a.avg_bit_rate == b.avg_bit_rate
959 		&& a.max_bit_rate == b.max_bit_rate
960 		&& a.encoding == b.encoding
961 		&& a.frame_size == b.frame_size
962 		&& a.forward_history == b.forward_history
963 		&& a.backward_history == b.backward_history;
964 }
965 
966 
967 bool
968 operator==(const media_multistream_format::vid_info& a,
969 	const media_multistream_format::vid_info& b)
970 {
971 	return a.frame_rate == b.frame_rate
972 		&& a.width == b.width
973 		&& a.height == b.height
974 		&& a.space == b.space
975 		&& a.sampling_rate == b.sampling_rate
976 		&& a.sample_format == b.sample_format
977 		&& a.byte_order == b.byte_order
978 		&& a.channel_count == b.channel_count;
979 }
980 
981 
982 bool
983 operator==(const media_multistream_format::avi_info& a,
984 	const media_multistream_format::avi_info& b)
985 {
986 	return a.us_per_frame == b.us_per_frame
987 		&& a.width == b.width
988 		&& a.height == b.height
989 		&& a.type_count == b.type_count
990 		&& a.types[0] == b.types[0]
991 		&& a.types[1] == b.types[1]
992 		&& a.types[2] == b.types[2]
993 		&& a.types[3] == b.types[3]
994 		&& a.types[4] == b.types[4];
995 }
996 
997 
998 bool
999 operator==(const media_multistream_format& a,
1000 	const media_multistream_format& b)
1001 {
1002 	if (a.avg_bit_rate != b.avg_bit_rate
1003 		|| a.max_bit_rate != b.max_bit_rate
1004 		|| a.avg_chunk_size != b.avg_chunk_size
1005 		|| a.max_chunk_size != b.max_chunk_size
1006 		|| a.format != b.format
1007 		|| a.flags != b.flags) {
1008 		return false;
1009 	}
1010 
1011 	switch (a.format) {
1012 		case media_multistream_format::B_VID:
1013 			return a.u.vid == b.u.vid;
1014 
1015 		case media_multistream_format::B_AVI:
1016 			return a.u.avi == b.u.avi;
1017 
1018 		default:
1019 			return true; // TODO: really?
1020 	}
1021 }
1022 
1023 
1024 bool
1025 operator==(const media_format& a, const media_format& b)
1026 {
1027 	if (a.type != b.type
1028 		|| a.user_data_type != b.user_data_type
1029 		// TODO: compare user_data[48] ?
1030 		|| a.require_flags != b.require_flags
1031 		|| a.deny_flags != b.deny_flags) {
1032 		return false;
1033 	}
1034 
1035 	switch (a.type) {
1036 		case B_MEDIA_RAW_AUDIO:
1037 			return a.u.raw_audio == b.u.raw_audio;
1038 
1039 		case B_MEDIA_RAW_VIDEO:
1040 			return a.u.raw_video == b.u.raw_video;
1041 
1042 		case B_MEDIA_MULTISTREAM:
1043 			return a.u.multistream == b.u.multistream;
1044 
1045 		case B_MEDIA_ENCODED_AUDIO:
1046 			return a.u.encoded_audio == b.u.encoded_audio;
1047 
1048 		case B_MEDIA_ENCODED_VIDEO:
1049 			return a.u.encoded_video == b.u.encoded_video;
1050 
1051 		default:
1052 			return true; // TODO: really?
1053 	}
1054 }
1055 
1056 
1057 // #pragma mark -
1058 
1059 
1060 /*! return \c true if a and b are compatible (accounting for wildcards)
1061 	a is the format you want to feed to something accepting b
1062 */
1063 bool
1064 format_is_compatible(const media_format& a, const media_format& b)
1065 {
1066 	return a.Matches(&b);
1067 }
1068 
1069 
1070 bool
1071 string_for_format(const media_format& f, char* buf, size_t size)
1072 {
1073 	char encoding[10]; /* maybe Be wanted to use some 4CCs ? */
1074 	const char* videoOrientation = "0"; /* I'd use "NC", R5 uses 0. */
1075 
1076 	if (buf == NULL)
1077 		return false;
1078 	switch (f.type) {
1079 	case B_MEDIA_RAW_AUDIO:
1080 		snprintf(buf, size,
1081 			"raw_audio;%g;%ld;0x%lx;%ld;0x%lx;0x%08lx;%d;0x%04x",
1082 			f.u.raw_audio.frame_rate,
1083 			f.u.raw_audio.channel_count,
1084 			f.u.raw_audio.format,
1085 			f.u.raw_audio.byte_order,
1086 			f.u.raw_audio.buffer_size,
1087 			f.u.raw_audio.channel_mask,
1088 			f.u.raw_audio.valid_bits,
1089 			f.u.raw_audio.matrix_mask);
1090 		return true;
1091 	case B_MEDIA_RAW_VIDEO:
1092 		if (f.u.raw_video.orientation == B_VIDEO_TOP_LEFT_RIGHT)
1093 			videoOrientation = "TopLR";
1094 		else if (f.u.raw_video.orientation == B_VIDEO_BOTTOM_LEFT_RIGHT)
1095 			videoOrientation = "BotLR";
1096 //		snprintf(buf, size, "raw_video;%g;%ld;%ld;%ld;%s;%d;%d;%d;%d;%d;%d;"
1097 //			"%d;%d",
1098 		snprintf(buf, size, "raw_video;%g;0x%x;%ld;%ld;%ld;%ld;%s;%d;%d",
1099 			f.u.raw_video.field_rate,
1100 			f.u.raw_video.display.format,
1101 			f.u.raw_video.interlace,
1102 			f.u.raw_video.display.line_width,
1103 			f.u.raw_video.display.line_count,
1104 			f.u.raw_video.first_active,
1105 			videoOrientation,
1106 			f.u.raw_video.pixel_width_aspect,
1107 			f.u.raw_video.pixel_height_aspect);
1108 		return true;
1109 	case B_MEDIA_ENCODED_AUDIO:
1110 		snprintf(encoding, 10, "%d", f.u.encoded_audio.encoding);
1111 		snprintf(buf, size,
1112 			"caudio;%s;%g;%ld;(%g;%ld;0x%lx;%ld;0x%lx;0x%08lx;%d;0x%04x)",
1113 			encoding, // f.u.encoded_audio.encoding,
1114 			f.u.encoded_audio.bit_rate,
1115 			f.u.encoded_audio.frame_size,
1116 			// (
1117 			f.u.encoded_audio.output.frame_rate,
1118 			f.u.encoded_audio.output.channel_count,
1119 			f.u.encoded_audio.output.format,
1120 			f.u.encoded_audio.output.byte_order,
1121 			f.u.encoded_audio.output.buffer_size,
1122 			f.u.encoded_audio.multi_info.channel_mask,
1123 			f.u.encoded_audio.multi_info.valid_bits,
1124 			f.u.encoded_audio.multi_info.matrix_mask);
1125 			// )
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;%ld;(%g;0x%x;%ld;%ld;%ld;%ld;%s;%d;%d)",
1135 			encoding,
1136 			f.u.encoded_video.avg_bit_rate,
1137 			f.u.encoded_video.max_bit_rate,
1138 			f.u.encoded_video.frame_size,
1139 			// (
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 			// )
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 	// get list of available readers from the server
1196 	server_get_file_format_request request;
1197 	request.cookie = *cookie;
1198 	server_get_file_format_reply reply;
1199 	status_t ret = QueryServer(SERVER_GET_FILE_FORMAT_FOR_COOKIE, &request,
1200 		sizeof(request), &reply, sizeof(reply));
1201 	if (ret != B_OK)
1202 		return ret;
1203 
1204 	*cookie = *cookie + 1;
1205 	*mff = reply.file_format;
1206 
1207 	return B_OK;
1208 }
1209 
1210 
1211 // #pragma mark -
1212 
1213 
1214 // final & verified
1215 const char* B_MEDIA_SERVER_SIGNATURE = "application/x-vnd.Be.media-server";
1216 const char* B_MEDIA_ADDON_SERVER_SIGNATURE = "application/x-vnd.Be.addon-host";
1217 
1218 const type_code B_CODEC_TYPE_INFO = 0x040807b2;
1219 
1220 
1221 // #pragma mark -
1222 
1223 
1224 // shutdown_media_server() and launch_media_server()
1225 // are provided by libbe.so in BeOS R5
1226 
1227 status_t
1228 shutdown_media_server(bigtime_t timeout,
1229 	bool (*progress)(int stage, const char* message, void* cookie),
1230 	void* cookie)
1231 {
1232 	BMessage msg(B_QUIT_REQUESTED);
1233 	BMessage reply;
1234 	status_t err;
1235 
1236 	if ((err = msg.AddBool("be:_user_request", true)) != B_OK)
1237 		return err;
1238 
1239 	if (be_roster->IsRunning(B_MEDIA_SERVER_SIGNATURE)) {
1240 		BMessenger messenger(B_MEDIA_SERVER_SIGNATURE);
1241 		progress(10, "Telling media_server to quit.", cookie);
1242 
1243 		err = messenger.SendMessage(&msg, &reply, 2000000, 2000000);
1244 		if (err != B_OK)
1245 			return err;
1246 
1247 		int32 rv;
1248 		if (reply.FindInt32("error", &rv) == B_OK && rv != B_OK)
1249 			return rv;
1250 	}
1251 
1252 	if (be_roster->IsRunning(B_MEDIA_ADDON_SERVER_SIGNATURE)) {
1253 		BMessenger messenger(B_MEDIA_ADDON_SERVER_SIGNATURE);
1254 		progress(20, "Telling media_addon_server to quit.", cookie);
1255 
1256 		err = messenger.SendMessage(&msg, &reply, 2000000, 2000000);
1257 		if (err != B_OK)
1258 			return err;
1259 
1260 		int32 rv;
1261 		if (reply.FindInt32("error", &rv) == B_OK && rv != B_OK)
1262 			return rv;
1263 	}
1264 
1265 	if (be_roster->IsRunning(B_MEDIA_SERVER_SIGNATURE)) {
1266 		progress(40, "Waiting for media_server to quit.", cookie);
1267 		snooze(200000);
1268 	}
1269 
1270 	if (be_roster->IsRunning(B_MEDIA_ADDON_SERVER_SIGNATURE)) {
1271 		progress(50, "Waiting for media_addon_server to quit.", cookie);
1272 		snooze(200000);
1273 	}
1274 
1275 	progress(70, "Cleaning Up.", cookie);
1276 	snooze(1000000);
1277 
1278 	if (be_roster->IsRunning(B_MEDIA_SERVER_SIGNATURE)) {
1279 		kill_team(be_roster->TeamFor(B_MEDIA_SERVER_SIGNATURE));
1280 	}
1281 
1282 	if (be_roster->IsRunning(B_MEDIA_ADDON_SERVER_SIGNATURE)) {
1283 		kill_team(be_roster->TeamFor(B_MEDIA_ADDON_SERVER_SIGNATURE));
1284 	}
1285 
1286 	progress(100, "Done Shutting Down.", cookie);
1287 	snooze(1000000);
1288 
1289 	return B_OK;
1290 }
1291 
1292 
1293 status_t
1294 launch_media_server(uint32 flags)
1295 {
1296 	status_t err;
1297 
1298 	if (be_roster->IsRunning(B_MEDIA_SERVER_SIGNATURE))
1299 		return B_ALREADY_RUNNING;
1300 
1301 	if (be_roster->IsRunning(B_MEDIA_ADDON_SERVER_SIGNATURE)) {
1302 		kill_team(be_roster->TeamFor(B_MEDIA_ADDON_SERVER_SIGNATURE));
1303 		snooze(1000000);
1304 	}
1305 
1306 	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