xref: /haiku/src/kits/media/MediaDefs.cpp (revision 67bce78b48ed6d01b5a8eef89f5694c372b7e0a1)
1 /***********************************************************************
2  * AUTHOR: Marcus Overhagen
3  *   FILE: MediaDefs.cpp
4  *  DESCR:
5  ***********************************************************************/
6 #include <MediaDefs.h>
7 #include <MediaNode.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <stdint.h>
11 #include "debug.h"
12 
13 /*************************************************************
14  * media_destination
15  *************************************************************/
16 
17 // final
18 media_destination::media_destination(port_id port,
19 									 int32 id)
20 	: port(port),
21 	id(id)
22 {
23 }
24 
25 // final
26 media_destination::media_destination(const media_destination &clone)
27 	: port(clone.port),
28 	id(clone.id)
29 {
30 }
31 
32 // final
33 media_destination &
34 media_destination::operator=(const media_destination &clone)
35 {
36 	port = clone.port;
37 	id = clone.id;
38 	return *this;
39 }
40 
41 // final & verfied
42 media_destination::media_destination()
43 	: port(-1),
44 	id(-1)
45 {
46 }
47 
48 // final
49 media_destination::~media_destination()
50 {
51 }
52 
53 // final & verfied
54 media_destination media_destination::null(-1,-1);
55 
56 /*************************************************************
57  * media_source
58  *************************************************************/
59 
60 // final
61 media_source::media_source(port_id port,
62 						   int32 id)
63 	: port(port),
64 	id(id)
65 {
66 }
67 
68 // final
69 media_source::media_source(const media_source &clone)
70 	: port(clone.port),
71 	id(clone.id)
72 {
73 }
74 
75 // final
76 media_source &
77 media_source::operator=(const media_source &clone)
78 {
79 	port = clone.port;
80 	id = clone.id;
81 	return *this;
82 }
83 
84 // final & verfied
85 media_source::media_source()
86 	: port(-1),
87 	id(-1)
88 {
89 }
90 
91 // final
92 media_source::~media_source()
93 {
94 }
95 
96 // final & verfied
97 media_source media_source::null(-1,-1);
98 
99 /*************************************************************
100  *
101  *************************************************************/
102 
103 // final
104 bool operator==(const media_destination & a, const media_destination & b)
105 {
106 	return (a.port == b.port) && (a.id == b.id);
107 }
108 
109 // final
110 bool operator!=(const media_destination & a, const media_destination & b)
111 {
112 	return (a.port != b.port) || (a.id != b.id);
113 }
114 
115 bool operator<(const media_destination & a, const media_destination & b)
116 {
117 	UNIMPLEMENTED();
118 	return false;
119 }
120 
121 // final
122 bool operator==(const media_source & a, const media_source & b)
123 {
124 	return (a.port == b.port) && (a.id == b.id);
125 }
126 
127 // final
128 bool operator!=(const media_source & a, const media_source & b)
129 {
130 	return (a.port != b.port) || (a.id != b.id);
131 }
132 
133 bool operator<(const media_source & a, const media_source & b)
134 {
135 	UNIMPLEMENTED();
136 	return false;
137 }
138 
139 // final
140 bool operator==(const media_node & a, const media_node & b)
141 {
142 	return (a.node == b.node) && (a.port == b.port) && (a.kind == b.kind);
143 }
144 
145 // final
146 bool operator!=(const media_node & a, const media_node & b)
147 {
148 	return (a.node != b.node) || (a.port != b.port) || (a.kind != b.kind);
149 }
150 
151 bool operator<(const media_node & a, const media_node & b)
152 {
153 	UNIMPLEMENTED();
154 	return false;
155 }
156 
157 
158 /*************************************************************
159  *
160  *************************************************************/
161 
162 media_multi_audio_format media_raw_audio_format::wildcard;
163 
164 media_multi_audio_format media_multi_audio_format::wildcard;
165 
166 media_encoded_audio_format media_encoded_audio_format::wildcard = {{0}};
167 
168 media_video_display_info media_video_display_info::wildcard = {(color_space)0};
169 
170 media_raw_video_format media_raw_video_format::wildcard = {0};
171 
172 media_encoded_video_format media_encoded_video_format::wildcard = {{0}};
173 
174 media_multistream_format media_multistream_format::wildcard = {0};
175 
176 /*************************************************************
177  * helper functions for media_format::Matches()
178  *************************************************************/
179 
180 static bool raw_audio_format_matches(const media_raw_audio_format &a, const media_raw_audio_format &b);
181 static bool multi_audio_info_matches(const media_multi_audio_info &a, const media_multi_audio_info &b);
182 static bool multi_audio_format_matches(const media_multi_audio_format &a, const media_multi_audio_format &b);
183 static bool raw_video_format_matches(const media_raw_video_format &a, const media_raw_video_format &b);
184 static bool multistream_format_matches(const media_multistream_format &a, const media_multistream_format &b);
185 static bool encoded_audio_format_matches(const media_encoded_audio_format &a, const media_encoded_audio_format &b);
186 static bool encoded_video_format_matches(const media_encoded_video_format &a, const media_encoded_video_format &b);
187 
188 static bool
189 raw_audio_format_matches(const media_raw_audio_format &a, const media_raw_audio_format &b)
190 {
191 	if (a.frame_rate != 0 && b.frame_rate != 0 && a.frame_rate != b.frame_rate)
192 		return false;
193 	if (a.channel_count != 0 && b.channel_count != 0 && a.channel_count != b.channel_count)
194 		return false;
195 	if (a.format != 0 && b.format != 0 && a.format != b.format)
196 		return false;
197 	if (a.byte_order != 0 && b.byte_order != 0 && a.byte_order != b.byte_order)
198 		return false;
199 	if (a.buffer_size != 0 && b.buffer_size != 0 && a.buffer_size != b.buffer_size)
200 		return false;
201 	if (a.frame_rate != 0 && b.frame_rate != 0 && a.frame_rate != b.frame_rate)
202 		return false;
203 	return true;
204 }
205 
206 static bool
207 multi_audio_info_matches(const media_multi_audio_info &a, const media_multi_audio_info &b)
208 {
209 	if (a.channel_mask != 0 && b.channel_mask != 0 && a.channel_mask != b.channel_mask)
210 		return false;
211 	if (a.valid_bits != 0 && b.valid_bits != 0 && a.valid_bits != b.valid_bits)
212 		return false;
213 	if (a.matrix_mask != 0 && b.matrix_mask != 0 && a.matrix_mask != b.matrix_mask)
214 		return false;
215 	return true;
216 }
217 
218 static bool
219 multi_audio_format_matches(const media_multi_audio_format &a, const media_multi_audio_format &b)
220 {
221 	return raw_audio_format_matches(a, b) && multi_audio_info_matches(a, b);
222 }
223 
224 static bool
225 raw_video_format_matches(const media_raw_video_format &a, const media_raw_video_format &b)
226 {
227 	if (a.field_rate != 0 && b.field_rate != 0 && a.field_rate != b.field_rate)
228 		return false;
229 	if (a.interlace != 0 && b.interlace != 0 && a.interlace != b.interlace)
230 		return false;
231 	if (a.first_active != 0 && b.first_active != 0 && a.first_active != b.first_active)
232 		return false;
233 	if (a.last_active != 0 && b.last_active != 0 && a.last_active != b.last_active)
234 		return false;
235 	if (a.orientation != 0 && b.orientation != 0 && a.orientation != b.orientation)
236 		return false;
237 	if (a.pixel_width_aspect != 0 && b.pixel_width_aspect != 0 && a.pixel_width_aspect != b.pixel_width_aspect)
238 		return false;
239 	if (a.pixel_height_aspect != 0 && b.pixel_height_aspect != 0 && a.pixel_height_aspect != b.pixel_height_aspect)
240 		return false;
241 	if (a.display.format != 0 && b.display.format != 0 && a.display.format != b.display.format)
242 		return false;
243 	if (a.display.line_width != 0 && b.display.line_width != 0 && a.display.line_width != b.display.line_width)
244 		return false;
245 	if (a.display.line_count != 0 && b.display.line_count != 0 && a.display.line_count != b.display.line_count)
246 		return false;
247 	if (a.display.bytes_per_row != 0 && b.display.bytes_per_row != 0 && a.display.bytes_per_row != b.display.bytes_per_row)
248 		return false;
249 	if (a.display.pixel_offset != 0 && b.display.pixel_offset != 0 && a.display.pixel_offset != b.display.pixel_offset)
250 		return false;
251 	if (a.display.line_offset != 0 && b.display.line_offset != 0 && a.display.line_offset != b.display.line_offset)
252 		return false;
253 	if (a.display.flags != 0 && b.display.flags != 0 && a.display.flags != b.display.flags)
254 		return false;
255 	return true;
256 }
257 
258 static bool
259 multistream_format_matches(const media_multistream_format &a, const media_multistream_format &b)
260 {
261 	if (a.avg_bit_rate != 0 && b.avg_bit_rate != 0 && a.avg_bit_rate != b.avg_bit_rate)
262 		return false;
263 	if (a.max_bit_rate != 0 && b.max_bit_rate != 0 && a.max_bit_rate != b.max_bit_rate)
264 		return false;
265 	if (a.avg_chunk_size != 0 && b.avg_chunk_size != 0 && a.avg_chunk_size != b.avg_chunk_size)
266 		return false;
267 	if (a.max_chunk_size != 0 && b.max_chunk_size != 0 && a.max_chunk_size != b.max_chunk_size)
268 		return false;
269 	if (a.flags != 0 && b.flags != 0 && a.flags != b.flags)
270 		return false;
271 	if (a.format != 0 && b.format != 0 && a.format != b.format)
272 		return false;
273 
274 	if (a.format == 0 && b.format == 0)
275 		return true; // XXX how do we compare two formats with no type?
276 
277 	switch ((a.format != 0) ? a.format : b.format) {
278 		default:
279 			return true; // XXX really?
280 
281 		case media_multistream_format::B_VID:
282 			if (a.u.vid.frame_rate != 0 && b.u.vid.frame_rate != 0 && a.u.vid.frame_rate != b.u.vid.frame_rate)
283 				return false;
284 			if (a.u.vid.width != 0 && b.u.vid.width != 0 && a.u.vid.width != b.u.vid.width)
285 				return false;
286 			if (a.u.vid.height != 0 && b.u.vid.height != 0 && a.u.vid.height != b.u.vid.height)
287 				return false;
288 			if (a.u.vid.space != 0 && b.u.vid.space != 0 && a.u.vid.space != b.u.vid.space)
289 				return false;
290 			if (a.u.vid.sampling_rate != 0 && b.u.vid.sampling_rate != 0 && a.u.vid.sampling_rate != b.u.vid.sampling_rate)
291 				return false;
292 			if (a.u.vid.sample_format != 0 && b.u.vid.sample_format != 0 && a.u.vid.sample_format != b.u.vid.sample_format)
293 				return false;
294 			if (a.u.vid.byte_order != 0 && b.u.vid.byte_order != 0 && a.u.vid.byte_order != b.u.vid.byte_order)
295 				return false;
296 			if (a.u.vid.channel_count != 0 && b.u.vid.channel_count != 0 && a.u.vid.channel_count != b.u.vid.channel_count)
297 				return false;
298 			return true;
299 
300 		case media_multistream_format::B_AVI:
301 			if (a.u.avi.us_per_frame != 0 && b.u.avi.us_per_frame != 0 && a.u.avi.us_per_frame != b.u.avi.us_per_frame)
302 				return false;
303 			if (a.u.avi.width != 0 && b.u.avi.width != 0 && a.u.avi.width != b.u.avi.width)
304 				return false;
305 			if (a.u.avi.height != 0 && b.u.avi.height != 0 && a.u.avi.height != b.u.avi.height)
306 				return false;
307 			if (a.u.avi.type_count != 0 && b.u.avi.type_count != 0 && a.u.avi.type_count != b.u.avi.type_count)
308 				return false;
309 			if (a.u.avi.types[0] != 0 && b.u.avi.types[0] != 0 && a.u.avi.types[0] != b.u.avi.types[0])
310 				return false;
311 			if (a.u.avi.types[1] != 0 && b.u.avi.types[1] != 0 && a.u.avi.types[1] != b.u.avi.types[1])
312 				return false;
313 			if (a.u.avi.types[2] != 0 && b.u.avi.types[2] != 0 && a.u.avi.types[2] != b.u.avi.types[2])
314 				return false;
315 			if (a.u.avi.types[3] != 0 && b.u.avi.types[3] != 0 && a.u.avi.types[3] != b.u.avi.types[3])
316 				return false;
317 			if (a.u.avi.types[4] != 0 && b.u.avi.types[4] != 0 && a.u.avi.types[4] != b.u.avi.types[4])
318 				return false;
319 			return true;
320 	}
321 }
322 
323 static bool
324 encoded_audio_format_matches(const media_encoded_audio_format &a, const media_encoded_audio_format &b)
325 {
326 	if (!raw_audio_format_matches(a.output, b.output))
327 		return false;
328 	if (a.encoding != 0 && b.encoding != 0 && a.encoding != b.encoding)
329 		return false;
330 	if (a.bit_rate != 0 && b.bit_rate != 0 && a.bit_rate != b.bit_rate)
331 		return false;
332 	if (a.frame_size != 0 && b.frame_size != 0 && a.frame_size != b.frame_size)
333 		return false;
334 	if (!multi_audio_info_matches(a.multi_info, b.multi_info))
335 		return false;
336 
337 	if (a.encoding == 0 && b.encoding == 0)
338 		return true; // can't compare
339 
340 	switch((a.encoding != 0) ? a.encoding : b.encoding) {
341 		case media_encoded_audio_format::B_ANY:
342 		default:
343 			return true;
344 	}
345 }
346 
347 static bool
348 encoded_video_format_matches(const media_encoded_video_format &a, const media_encoded_video_format &b)
349 {
350 	if (!raw_video_format_matches(a.output, b.output))
351 		return false;
352 	if (a.encoding != 0 && b.encoding != 0 && a.encoding != b.encoding)
353 		return false;
354 
355 	if (a.avg_bit_rate != 0 && b.avg_bit_rate != 0 && a.avg_bit_rate != b.avg_bit_rate)
356 		return false;
357 	if (a.max_bit_rate != 0 && b.max_bit_rate != 0 && a.max_bit_rate != b.max_bit_rate)
358 		return false;
359 	if (a.frame_size != 0 && b.frame_size != 0 && a.frame_size != b.frame_size)
360 		return false;
361 	if (a.forward_history != 0 && b.forward_history != 0 && a.forward_history != b.forward_history)
362 		return false;
363 	if (a.backward_history != 0 && b.backward_history != 0 && a.backward_history != b.backward_history)
364 		return false;
365 
366 	if (a.encoding == 0 && b.encoding == 0)
367 		return true; // can't compare
368 
369 	switch((a.encoding != 0) ? a.encoding : b.encoding) {
370 		case media_encoded_video_format::B_ANY:
371 		default:
372 			return true;
373 	}
374 }
375 
376 /*************************************************************
377  * helper functions for media_format::SpecializeTo()
378  *************************************************************/
379 
380 static void raw_audio_format_specialize(media_raw_audio_format *format, const media_raw_audio_format *other);
381 static void multi_audio_info_specialize(media_multi_audio_info *format, const media_multi_audio_info *other);
382 static void multi_audio_format_specialize(media_multi_audio_format *format, const media_multi_audio_format *other);
383 static void raw_video_format_specialize(media_raw_video_format *format, const media_raw_video_format *other);
384 static void multistream_format_specialize(media_multistream_format *format, const media_multistream_format *other);
385 static void encoded_audio_format_specialize(media_encoded_audio_format *format, const media_encoded_audio_format *other);
386 static void encoded_video_format_specialize(media_encoded_video_format *format, const media_encoded_video_format *other);
387 
388 
389 static void
390 raw_audio_format_specialize(media_raw_audio_format *format, const media_raw_audio_format *other)
391 {
392 	if (format->frame_rate == 0)
393 		format->frame_rate = other->frame_rate;
394 	if (format->channel_count == 0)
395 		format->channel_count = other->channel_count;
396 	if (format->format == 0)
397 		format->format = other->format;
398 	if (format->byte_order == 0)
399 		format->byte_order = other->byte_order;
400 	if (format->buffer_size == 0)
401 		format->buffer_size = other->buffer_size;
402 	if (format->frame_rate == 0)
403 		format->frame_rate = other->frame_rate;
404 }
405 
406 static void
407 multi_audio_info_specialize(media_multi_audio_info *format, const media_multi_audio_info *other)
408 {
409 	if (format->channel_mask == 0)
410 		format->channel_mask = other->channel_mask;
411 	if (format->valid_bits == 0)
412 		format->valid_bits = other->valid_bits;
413 	if (format->matrix_mask == 0)
414 		format->matrix_mask = other->matrix_mask;
415 }
416 
417 static void
418 multi_audio_format_specialize(media_multi_audio_format *format, const media_multi_audio_format *other)
419 {
420 	raw_audio_format_specialize(format, other);
421 	multi_audio_info_specialize(format, other);
422 }
423 
424 static void
425 raw_video_format_specialize(media_raw_video_format *format, const media_raw_video_format *other)
426 {
427 	if (format->field_rate == 0)
428 		format->field_rate = other->field_rate;
429 	if (format->interlace == 0)
430 		format->interlace = other->interlace;
431 	if (format->first_active == 0)
432 		format->first_active = other->first_active;
433 	if (format->last_active == 0)
434 		format->last_active = other->last_active;
435 	if (format->orientation == 0)
436 		format->orientation = other->orientation;
437 	if (format->pixel_width_aspect == 0)
438 		format->pixel_width_aspect = other->pixel_width_aspect;
439 	if (format->pixel_height_aspect == 0)
440 		format->pixel_height_aspect = other->pixel_height_aspect;
441 	if (format->display.format == 0)
442 		format->display.format = other->display.format;
443 	if (format->display.line_width == 0)
444 		format->display.line_width = other->display.line_width;
445 	if (format->display.line_count == 0)
446 		format->display.line_count = other->display.line_count;
447 	if (format->display.bytes_per_row == 0)
448 		format->display.bytes_per_row = other->display.bytes_per_row;
449 	if (format->display.pixel_offset == 0)
450 		format->display.pixel_offset = other->display.pixel_offset;
451 	if (format->display.line_offset == 0)
452 		format->display.line_offset = other->display.line_offset;
453 	if (format->display.flags == 0)
454 		format->display.flags = other->display.flags;
455 }
456 
457 static void
458 multistream_format_specialize(media_multistream_format *format, const media_multistream_format *other)
459 {
460 	if (format->avg_bit_rate == 0)
461 		format->avg_bit_rate = other->avg_bit_rate;
462 	if (format->max_bit_rate == 0)
463 		format->max_bit_rate = other->max_bit_rate;
464 	if (format->avg_chunk_size == 0)
465 		format->avg_chunk_size = other->avg_chunk_size;
466 	if (format->max_chunk_size == 0)
467 		format->max_chunk_size = other->max_chunk_size;
468 	if (format->flags == 0)
469 		format->flags = other->flags;
470 	if (format->format == 0)
471 		format->format = other->format;
472 
473 	switch (format->format) {
474 		case media_multistream_format::B_VID:
475 			if (format->u.vid.frame_rate == 0)
476 				format->u.vid.frame_rate = other->u.vid.frame_rate;
477 			if (format->u.vid.width == 0)
478 				format->u.vid.width = other->u.vid.width;
479 			if (format->u.vid.height == 0)
480 				format->u.vid.height = other->u.vid.height;
481 			if (format->u.vid.space == 0)
482 				format->u.vid.space = other->u.vid.space;
483 			if (format->u.vid.sampling_rate == 0)
484 				format->u.vid.sampling_rate = other->u.vid.sampling_rate;
485 			if (format->u.vid.sample_format == 0)
486 				format->u.vid.sample_format = other->u.vid.sample_format;
487 			if (format->u.vid.byte_order == 0)
488 				format->u.vid.byte_order = other->u.vid.byte_order;
489 			if (format->u.vid.channel_count == 0)
490 				format->u.vid.channel_count = other->u.vid.channel_count;
491 			break;
492 
493 		case media_multistream_format::B_AVI:
494 			if (format->u.avi.us_per_frame == 0)
495 				format->u.avi.us_per_frame = other->u.avi.us_per_frame;
496 			if (format->u.avi.width == 0)
497 				format->u.avi.width = other->u.avi.width;
498 			if (format->u.avi.height == 0)
499 				format->u.avi.height = other->u.avi.height;
500 			if (format->u.avi.type_count == 0)
501 				format->u.avi.type_count = other->u.avi.type_count;
502 			if (format->u.avi.types[0] == 0)
503 				format->u.avi.types[0] = other->u.avi.types[0];
504 			if (format->u.avi.types[1] == 0)
505 				format->u.avi.types[1] = other->u.avi.types[1];
506 			if (format->u.avi.types[2] == 0)
507 				format->u.avi.types[2] = other->u.avi.types[2];
508 			if (format->u.avi.types[3] == 0)
509 				format->u.avi.types[3] = other->u.avi.types[3];
510 			if (format->u.avi.types[4] == 0)
511 				format->u.avi.types[4] = other->u.avi.types[4];
512 			break;
513 
514 		default:
515 			ERROR("media_format::SpecializeTo can't specialize media_multistream_format of format %d\n", format->format);
516 	}
517 }
518 
519 static void
520 encoded_audio_format_specialize(media_encoded_audio_format *format, const media_encoded_audio_format *other)
521 {
522 	raw_audio_format_specialize(&format->output, &other->output);
523 	if (format->encoding == 0)
524 		format->encoding = other->encoding;
525 	if (format->bit_rate == 0)
526 		format->bit_rate = other->bit_rate;
527 	if (format->frame_size == 0)
528 		format->frame_size = other->frame_size;
529 	multi_audio_info_specialize(&format->multi_info, &other->multi_info);
530 }
531 
532 static void
533 encoded_video_format_specialize(media_encoded_video_format *format, const media_encoded_video_format *other)
534 {
535 	raw_video_format_specialize(&format->output, &other->output);
536 	if (format->avg_bit_rate == 0)
537 		format->avg_bit_rate = other->avg_bit_rate;
538 	if (format->max_bit_rate == 0)
539 		format->max_bit_rate = other->max_bit_rate;
540 	if (format->encoding == 0)
541 		format->encoding = other->encoding;
542 	if (format->frame_size == 0)
543 		format->frame_size = other->frame_size;
544 	if (format->forward_history == 0)
545 		format->forward_history = other->forward_history;
546 	if (format->backward_history == 0)
547 		format->backward_history = other->backward_history;
548 }
549 
550 
551 /*************************************************************
552  * media_format
553  *************************************************************/
554 
555 bool
556 media_format::Matches(const media_format *other) const
557 {
558 	CALLED();
559 	if (type == 0 && other->type == 0)
560 		return true; // XXX how do we compare two formats with no type?
561 
562 	if (type != 0 && other->type != 0 && type != other->type)
563 		return false;
564 
565 	switch ((type != 0) ? type : other->type) {
566 		case B_MEDIA_RAW_AUDIO:
567 			return multi_audio_format_matches(u.raw_audio, other->u.raw_audio);
568 
569 		case B_MEDIA_RAW_VIDEO:
570 			return raw_video_format_matches(u.raw_video, other->u.raw_video);
571 
572 		case B_MEDIA_MULTISTREAM:
573 			return multistream_format_matches(u.multistream, other->u.multistream);
574 
575 		case B_MEDIA_ENCODED_AUDIO:
576 			return encoded_audio_format_matches(u.encoded_audio, other->u.encoded_audio);
577 
578 		case B_MEDIA_ENCODED_VIDEO:
579 			return encoded_video_format_matches(u.encoded_video, other->u.encoded_video);
580 
581 		default:
582 			return true; // XXX really?
583 	}
584 }
585 
586 void
587 media_format::SpecializeTo(const media_format *otherFormat)
588 {
589 	CALLED();
590 	if (type == 0 && otherFormat->type == 0) {
591 		ERROR("media_format::SpecializeTo can't specialize wildcard to other wildcard format\n");
592 		return;
593 	}
594 
595 	if (type == 0)
596 		type = otherFormat->type;
597 
598 	switch (type) {
599 		case B_MEDIA_RAW_AUDIO:
600 			multi_audio_format_specialize(&u.raw_audio, &otherFormat->u.raw_audio);
601 			return;
602 
603 		case B_MEDIA_RAW_VIDEO:
604 			raw_video_format_specialize(&u.raw_video, &otherFormat->u.raw_video);
605 			return;
606 
607 		case B_MEDIA_MULTISTREAM:
608 			multistream_format_specialize(&u.multistream, &otherFormat->u.multistream);
609 			return;
610 
611 		case B_MEDIA_ENCODED_AUDIO:
612 			encoded_audio_format_specialize(&u.encoded_audio, &otherFormat->u.encoded_audio);
613 			return;
614 
615 		case B_MEDIA_ENCODED_VIDEO:
616 			encoded_video_format_specialize(&u.encoded_video, &otherFormat->u.encoded_video);
617 			return;
618 
619 		default:
620 			ERROR("media_format::SpecializeTo can't specialize format type %d\n", type);
621 	}
622 }
623 
624 
625 status_t
626 media_format::SetMetaData(const void *data,
627 						  size_t size)
628 {
629 	// TODO: create_area / delete_area for this should be done by the media server?
630 	if (meta_data_area > 0) {
631 		delete_area(meta_data_area);
632 	}
633 	uchar * addr = 0;
634 	uint32 area_size = ((size - 1) / B_PAGE_SIZE + 1) * B_PAGE_SIZE ;
635 	area_id area = create_area("meta_data_area", (void**)&addr, B_ANY_ADDRESS, area_size,
636 	                           B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
637 	if (area < 0) {
638 		return area;
639 	}
640 	memcpy(addr, data, size);
641 	set_area_protection(area,B_READ_AREA);
642 	meta_data = addr;
643 	meta_data_size = size;
644 	meta_data_area = area;
645 	use_area = area;
646 	thread_id thread = find_thread(NULL);
647 	thread_info info;
648 	if (get_thread_info(thread, &info) == B_OK) {
649 		team = info.team;
650 	}
651 	thisPtr = this;
652 	return B_OK;
653 }
654 
655 
656 const void *
657 media_format::MetaData() const
658 {
659 	return meta_data;
660 }
661 
662 
663 int32
664 media_format::MetaDataSize() const
665 {
666 	return meta_data_size;
667 }
668 
669 // final
670 media_format::media_format()
671 {
672 	memset(this, 0x00, sizeof(*this));
673 	meta_data_area = B_BAD_VALUE;
674 	use_area = B_BAD_VALUE;
675 	team = B_BAD_VALUE;
676 	//meta_data, meta_data_size, meta_data_area, use_area,
677 	//team, and thisPtr are currently only used by decoders
678 	//when communicating with the file reader; they're not
679 	//currently for public use.
680 
681 	//If any field is 0, it's treated as a wildcard
682 }
683 
684 
685 // final
686 media_format::media_format(const media_format &other)
687 {
688 	*this = other;
689 }
690 
691 // final
692 media_format::~media_format()
693 {
694 }
695 
696 
697 // final
698 media_format &
699 media_format::operator=(const media_format &clone)
700 {
701 	memcpy(this, &clone, sizeof(*this));
702 	// these things only happen when a meta_data_area is defined:
703 	if (meta_data_area > 0) {
704 		thread_id thread = find_thread(NULL);
705 		thread_info info;
706 		if (get_thread_info(thread,&info) == B_OK) {
707 			team = info.team;
708 		}
709 		thisPtr = this;
710 		// TODO: start _Media_Roster_
711 		// TODO: request the _Media_Roster_ to give us the
712 		// use_area for this team, or to create a
713 		// clone for our team if our team doesn't have one yet
714 		// TODO: set meta_data to point to the clone's address
715 		UNIMPLEMENTED();
716 	}
717 	return *this;
718 }
719 
720 /*************************************************************
721  *
722  *************************************************************/
723 
724 
725 bool operator==(const media_raw_audio_format & a, const media_raw_audio_format & b)
726 {
727 	return (   a.frame_rate == b.frame_rate
728 			&& a.channel_count == b.channel_count
729 			&& a.format == b.format
730 			&& a.byte_order == b.byte_order
731 			&& a.buffer_size == b.buffer_size);
732 }
733 
734 bool operator==(const media_multi_audio_info & a, const media_multi_audio_info & b)
735 {
736 	return (   a.channel_mask == b.channel_mask
737 			&& a.valid_bits == b.valid_bits
738 			&& a.matrix_mask == b.matrix_mask);
739 }
740 
741 bool operator==(const media_multi_audio_format & a, const media_multi_audio_format & b)
742 {
743 	return (   (media_raw_audio_format)a == (media_raw_audio_format)b
744 			&& (media_multi_audio_info)a == (media_multi_audio_info)b);
745 }
746 
747 bool operator==(const media_encoded_audio_format & a, const media_encoded_audio_format & b)
748 {
749 	return (   a.output == b.output
750 			&& a.encoding == b.encoding
751 			&& a.bit_rate == b.bit_rate
752 			&& a.frame_size == b.frame_size
753 			&& a.multi_info == b.multi_info);
754 }
755 
756 bool operator==(const media_video_display_info & a, const media_video_display_info & b)
757 {
758 	return (   a.format == b.format
759 			&& a.line_width == b.line_width
760 			&& a.line_count == b.line_count
761 			&& a.bytes_per_row == b.bytes_per_row
762 			&& a.pixel_offset == b.pixel_offset
763 			&& a.line_offset == b.line_offset
764 			&& a.flags == b.flags);
765 }
766 
767 bool operator==(const media_raw_video_format & a, const media_raw_video_format & b)
768 {
769 	return (   a.field_rate == b.field_rate
770 			&& a.interlace == b.interlace
771 			&& a.first_active == b.first_active
772 			&& a.last_active == b.last_active
773 			&& a.orientation == b.orientation
774 			&& a.pixel_width_aspect == b.pixel_width_aspect
775 			&& a.pixel_height_aspect == b.pixel_height_aspect
776 			&& a.display == b.display);
777 }
778 
779 bool operator==(const media_encoded_video_format & a, const media_encoded_video_format & b)
780 {
781 	return (   a.output == b.output
782 			&& a.avg_bit_rate == b.avg_bit_rate
783 			&& a.max_bit_rate == b.max_bit_rate
784 			&& a.encoding == b.encoding
785 			&& a.frame_size == b.frame_size
786 			&& a.forward_history == b.forward_history
787 			&& a.backward_history == b.backward_history);
788 }
789 
790 bool operator==(const media_multistream_format::vid_info & a, const media_multistream_format::vid_info & b)
791 {
792 	return (   a.frame_rate == b.frame_rate
793 			&& a.width == b.width
794 			&& a.height == b.height
795 			&& a.space == b.space
796 			&& a.sampling_rate == b.sampling_rate
797 			&& a.sample_format == b.sample_format
798 			&& a.byte_order == b.byte_order
799 			&& a.channel_count == b.channel_count);
800 }
801 
802 bool operator==(const media_multistream_format::avi_info & a, const media_multistream_format::avi_info & b)
803 {
804 	return (   a.us_per_frame == b.us_per_frame
805 			&& a.width == b.width
806 			&& a.height == b.height
807 			&& a.type_count == b.type_count
808 			&& a.types[0] == b.types[0]
809 			&& a.types[1] == b.types[1]
810 			&& a.types[2] == b.types[2]
811 			&& a.types[3] == b.types[3]
812 			&& a.types[4] == b.types[4]);
813 }
814 
815 bool operator==(const media_multistream_format & a, const media_multistream_format & b)
816 {
817 	if (a.avg_bit_rate != b.avg_bit_rate
818 		|| a.max_bit_rate != b.max_bit_rate
819 		|| a.avg_chunk_size != b.avg_chunk_size
820 		|| a.max_chunk_size != b.max_chunk_size
821 		|| a.format != b.format
822 		|| a.flags != b.flags)
823 		return false;
824 
825 	switch (a.format) {
826 		case media_multistream_format::B_VID:
827 			return a.u.vid == b.u.vid;
828 
829 		case media_multistream_format::B_AVI:
830 			return a.u.avi == b.u.avi;
831 
832 		default:
833 			return true; // XXX really?
834 	}
835 }
836 
837 bool operator==(const media_format & a, const media_format & b)
838 {
839 	if (a.type != b.type
840 		|| a.user_data_type != b.user_data_type
841 		// XXX compare user_data[48] ?
842 		|| a.require_flags != b.require_flags
843 		|| a.deny_flags != b.deny_flags)
844 		return false;
845 
846 	switch (a.type) {
847 		case B_MEDIA_RAW_AUDIO:
848 			return a.u.raw_audio == b.u.raw_audio;
849 
850 		case B_MEDIA_RAW_VIDEO:
851 			return a.u.raw_video == b.u.raw_video;
852 
853 		case B_MEDIA_MULTISTREAM:
854 			return a.u.multistream == b.u.multistream;
855 
856 		case B_MEDIA_ENCODED_AUDIO:
857 			return a.u.encoded_audio == b.u.encoded_audio;
858 
859 		case B_MEDIA_ENCODED_VIDEO:
860 			return a.u.encoded_video == b.u.encoded_video;
861 
862 		default:
863 			return true; // XXX really?
864 	}
865 }
866 
867 /*************************************************************
868  *
869  *************************************************************/
870 
871 /* return true if a and b are compatible (accounting for wildcards) */
872 bool format_is_compatible(const media_format & a, const media_format & b)	/* a is the format you want to feed to something accepting b */
873 {
874 	return a.Matches(&b);
875 }
876 
877 bool string_for_format(const media_format & f, char * buf, size_t size)
878 {
879 	char encoding[10]; /* maybe Be wanted to use some 4CCs ? */
880 	const char *video_orientation = "0"; /* I'd use "NC", R5 uses 0. */
881 
882 	if (buf == NULL)
883 		return false;
884 	switch (f.type) {
885 	case B_MEDIA_RAW_AUDIO:
886 		snprintf(buf, size,
887 				"raw_audio;%g;%ld;0x%lx;%ld;0x%lx;0x%08lx;%d;0x%04x",
888 				f.u.raw_audio.frame_rate,
889 				f.u.raw_audio.channel_count,
890 				f.u.raw_audio.format,
891 				f.u.raw_audio.byte_order,
892 				f.u.raw_audio.buffer_size,
893 				f.u.raw_audio.channel_mask,
894 				f.u.raw_audio.valid_bits,
895 				f.u.raw_audio.matrix_mask);
896 		return true;
897 	case B_MEDIA_RAW_VIDEO:
898 		if (f.u.raw_video.orientation == B_VIDEO_TOP_LEFT_RIGHT)
899 			video_orientation = "TopLR";
900 		else if (f.u.raw_video.orientation == B_VIDEO_BOTTOM_LEFT_RIGHT)
901 			video_orientation = "BotLR";
902 		//snprintf(buf, size, "raw_video;%g;%ld;%ld;%ld;%s;%d;%d;%d;%d;%d;%d;%d;%d",
903 		snprintf(buf, size, "raw_video;%g;0x%x;%ld;%ld;%ld;%ld;%s;%d;%d",
904 				f.u.raw_video.field_rate,
905 				f.u.raw_video.display.format,
906 				f.u.raw_video.interlace,
907 				f.u.raw_video.display.line_width,
908 				f.u.raw_video.display.line_count,
909 				f.u.raw_video.first_active,
910 				video_orientation,
911 				f.u.raw_video.pixel_width_aspect,
912 				f.u.raw_video.pixel_height_aspect);
913 		return true;
914 	case B_MEDIA_ENCODED_AUDIO:
915 		snprintf(encoding, 10, "%d", f.u.encoded_audio.encoding);
916 		snprintf(buf, size,
917 				"caudio;%s;%g;%ld;(%g;%ld;0x%lx;%ld;0x%lx;0x%08lx;%d;0x%04x)",
918 				encoding, // f.u.encoded_audio.encoding,
919 				f.u.encoded_audio.bit_rate,
920 				f.u.encoded_audio.frame_size,
921 				// (
922 				f.u.encoded_audio.output.frame_rate,
923 				f.u.encoded_audio.output.channel_count,
924 				f.u.encoded_audio.output.format,
925 				f.u.encoded_audio.output.byte_order,
926 				f.u.encoded_audio.output.buffer_size,
927 				f.u.encoded_audio.multi_info.channel_mask,
928 				f.u.encoded_audio.multi_info.valid_bits,
929 				f.u.encoded_audio.multi_info.matrix_mask);
930 				// )
931 		return true;
932 	case B_MEDIA_ENCODED_VIDEO:
933 		snprintf(encoding, 10, "%d", f.u.encoded_video.encoding);
934 		if (f.u.encoded_video.output.orientation == B_VIDEO_TOP_LEFT_RIGHT)
935 			video_orientation = "TopLR";
936 		else if (f.u.encoded_video.output.orientation == B_VIDEO_BOTTOM_LEFT_RIGHT)
937 			video_orientation = "BotLR";
938 		snprintf(buf, size,
939 				"cvideo;%s;%g;%g;%ld;(%g;0x%x;%ld;%ld;%ld;%ld;%s;%d;%d)",
940 				encoding,
941 				f.u.encoded_video.avg_bit_rate,
942 				f.u.encoded_video.max_bit_rate,
943 				f.u.encoded_video.frame_size,
944 				// (
945 				f.u.encoded_video.output.field_rate,
946 				f.u.encoded_video.output.display.format,
947 				f.u.encoded_video.output.interlace,
948 				f.u.encoded_video.output.display.line_width,
949 				f.u.encoded_video.output.display.line_count,
950 				f.u.encoded_video.output.first_active,
951 				video_orientation,
952 				f.u.encoded_video.output.pixel_width_aspect,
953 				f.u.encoded_video.output.pixel_height_aspect);
954 				// )
955 		return true;
956 	default:
957 		snprintf(buf, size, "%d-", f.type);
958 		unsigned char *p = (unsigned char *)&(f.u);
959 		size -= strlen(buf);
960 		buf += strlen(buf);
961 		for (int i = 0; (size > 2) && (i < 96); i++) {
962 			snprintf(buf, 3, "%2.2x", *(p + i));
963 			buf+=2;
964 			size-=2;
965 		}
966 		return true; // ?
967 	}
968 	return false;
969 }
970 
971 /*************************************************************
972  *
973  *************************************************************/
974 
975 bool operator==(const media_file_format_id & a, const media_file_format_id & b)
976 {
977 	UNIMPLEMENTED();
978 	return false;
979 }
980 
981 bool operator<(const media_file_format_id & a, const media_file_format_id & b)
982 {
983 	UNIMPLEMENTED();
984 	return false;
985 }
986 
987 /*************************************************************
988  *
989  *************************************************************/
990 
991 //
992 // Use this function iterate through available file format writers
993 //
994 status_t get_next_file_format(int32 *cookie, media_file_format *mfi)
995 {
996 	UNIMPLEMENTED();
997 	return B_ERROR;
998 }
999 
1000 
1001 /*************************************************************
1002  *
1003  *************************************************************/
1004 
1005 // final & verified
1006 const char * B_MEDIA_SERVER_SIGNATURE = "application/x-vnd.Be.media-server";
1007 
1008 const type_code B_CODEC_TYPE_INFO = 0x040807b2;
1009 
1010 /*************************************************************
1011  *
1012  *************************************************************/
1013 
1014 struct dormant_node_info
1015 {
1016 };
1017 
1018 struct buffer_clone_info
1019 {
1020 };
1021 
1022 /*************************************************************
1023  *
1024  *************************************************************/
1025 
1026 
1027 //	If you for some reason need to get rid of the media_server (and friends)
1028 //	use these functions, rather than sending messages yourself.
1029 //	The callback will be called for various stages of the process, with 100 meaning completely done
1030 //	The callback should always return TRUE for the time being.
1031 status_t shutdown_media_server(bigtime_t timeout = B_INFINITE_TIMEOUT, bool (*progress)(int stage, const char * message, void * cookie) = NULL, void * cookie = NULL)
1032 {
1033 	UNIMPLEMENTED();
1034 	return B_OK;
1035 }
1036 
1037 status_t launch_media_server(uint32 flags = 0)
1038 {
1039 	UNIMPLEMENTED();
1040 	return B_OK;
1041 }
1042 
1043 //	Given an image_id, prepare that image_id for realtime media
1044 //	If the kind of media indicated by "flags" is not enabled for real-time,
1045 //	B_MEDIA_REALTIME_DISABLED is returned.
1046 //	If there are not enough system resources to enable real-time performance,
1047 //	B_MEDIA_REALTIME_UNAVAILABLE is returned.
1048 status_t media_realtime_init_image(image_id image, uint32 flags)
1049 {
1050 	UNIMPLEMENTED();
1051 	return B_OK;
1052 }
1053 
1054 //	Given a thread ID, and an optional indication of what the thread is
1055 //	doing in "flags", prepare the thread for real-time media performance.
1056 //	Currently, this means locking the thread stack, up to size_used bytes,
1057 //	or all of it if 0 is passed. Typically, you will not be using all
1058 //	256 kB of the stack, so you should pass some smaller value you determine
1059 //	from profiling the thread; typically in the 32-64kB range.
1060 //	Return values are the same as for media_prepare_realtime_image().
1061 status_t media_realtime_init_thread(thread_id thread, size_t stack_used, uint32 flags)
1062 {
1063 	UNIMPLEMENTED();
1064 	return B_OK;
1065 }
1066 
1067 /*************************************************************
1068  * media_encode_info
1069  *************************************************************/
1070 
1071 
1072 media_encode_info::media_encode_info()
1073 {
1074 	flags = 0;
1075 	used_data_size = 0;
1076 	start_time = 0;
1077 	time_to_encode = INT64_MAX;
1078 	file_format_data = NULL;
1079 	file_format_data_size = 0;
1080 	codec_data = NULL;
1081 	codec_data_size = 0;
1082 }
1083 
1084 
1085 media_decode_info::media_decode_info()
1086 {
1087 	time_to_decode = INT64_MAX;
1088 	file_format_data = NULL;
1089 	file_format_data_size = 0;
1090 	codec_data = NULL;
1091 	codec_data_size = 0;
1092 }
1093 
1094 
1095