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
31media_destination::media_destination(port_id port, int32 id)
32	:
33	port(port),
34	id(id)
35{
36}
37
38
39media_destination::media_destination(const media_destination& clone)
40	:
41	port(clone.port),
42	id(clone.id)
43{
44}
45
46
47media_destination&
48media_destination::operator=(const media_destination& clone)
49{
50	port = clone.port;
51	id = clone.id;
52	return *this;
53}
54
55
56media_destination::media_destination()
57	:
58	port(-1),
59	id(-1)
60{
61}
62
63
64media_destination::~media_destination()
65{
66}
67
68
69media_destination media_destination::null(-1, -1);
70
71
72// #pragma mark - media_source
73
74
75media_source::media_source(port_id port,
76						   int32 id)
77	:
78	port(port),
79	id(id)
80{
81}
82
83
84media_source::media_source(const media_source& clone)
85	:
86	port(clone.port),
87	id(clone.id)
88{
89}
90
91
92media_source&
93media_source::operator=(const media_source& clone)
94{
95	port = clone.port;
96	id = clone.id;
97	return *this;
98}
99
100
101media_source::media_source()
102	:
103	port(-1),
104	id(-1)
105{
106}
107
108
109media_source::~media_source()
110{
111}
112
113
114media_source media_source::null(-1, -1);
115
116
117// #pragma mark -
118
119
120bool
121operator==(const media_destination& a, const media_destination& b)
122{
123	return a.port == b.port && a.id == b.id;
124}
125
126
127bool
128operator!=(const media_destination& a, const media_destination& b)
129{
130	return a.port != b.port || a.id != b.id;
131}
132
133
134bool
135operator<(const media_destination& a, const media_destination& b)
136{
137	UNIMPLEMENTED();
138	return false;
139}
140
141
142bool
143operator==(const media_source& a, const media_source& b)
144{
145	return a.port == b.port && a.id == b.id;
146}
147
148
149bool
150operator!=(const media_source& a, const media_source& b)
151{
152	return a.port != b.port || a.id != b.id;
153}
154
155
156bool
157operator<(const media_source& a, const media_source& b)
158{
159	UNIMPLEMENTED();
160	return false;
161}
162
163
164bool
165operator==(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
171bool
172operator!=(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
178bool
179operator<(const media_node& a, const media_node& b)
180{
181	UNIMPLEMENTED();
182	return false;
183}
184
185
186// #pragma mark -
187
188
189media_multi_audio_format media_raw_audio_format::wildcard;
190
191media_multi_audio_format media_multi_audio_format::wildcard;
192
193media_encoded_audio_format media_encoded_audio_format::wildcard = {{0}};
194
195media_video_display_info media_video_display_info::wildcard = {(color_space)0};
196
197media_raw_video_format media_raw_video_format::wildcard = {0};
198
199media_encoded_video_format media_encoded_video_format::wildcard = {{0}};
200
201media_multistream_format media_multistream_format::wildcard = {0};
202
203
204// #pragma mark - media_format::Matches() support
205
206
207static bool
208raw_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
231static bool
232multi_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
249static bool
250multi_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
257static bool
258raw_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
322static bool
323multistream_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
433static bool
434encoded_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
459static bool
460encoded_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
503static void
504raw_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
522static void
523multi_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
535static void
536multi_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
544static void
545raw_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
579static void
580multistream_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
645static void
646encoded_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
660static void
661encoded_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
683bool
684media_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
721void
722media_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
768status_t
769media_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
806const void*
807media_format::MetaData() const
808{
809	return meta_data;
810}
811
812
813int32
814media_format::MetaDataSize() const
815{
816	return meta_data_size;
817}
818
819
820media_format::media_format()
821{
822	memset(this, 0x00, sizeof(*this));
823	meta_data_area = B_BAD_VALUE;
824}
825
826
827media_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
835media_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
845media_format&
846media_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
885bool
886operator==(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
896bool
897operator==(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
905bool
906operator==(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
914bool
915operator==(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
926bool
927operator==(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
940bool
941operator==(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
954bool
955operator==(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
968bool
969operator==(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
983bool
984operator==(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
999bool
1000operator==(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
1025bool
1026operator==(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*/
1064bool
1065format_is_compatible(const media_format& a, const media_format& b)
1066{
1067	return a.Matches(&b);
1068}
1069
1070
1071bool
1072string_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
1169bool
1170operator==(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
1177bool
1178operator<(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.
1188status_t
1189get_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
1214const char* B_MEDIA_SERVER_SIGNATURE = "application/x-vnd.Be.media-server";
1215const char* B_MEDIA_ADDON_SERVER_SIGNATURE = "application/x-vnd.Be.addon-host";
1216
1217const 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
1226status_t
1227shutdown_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
1292status_t
1293launch_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.
1336status_t
1337media_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().
1350status_t
1351media_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
1361media_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
1374media_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