1/*
2 * Copyright (c) 2004-2010 Marcus Overhagen <marcus@overhagen.de>
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify,
8 * merge, publish, distribute, sublicense, and/or sell copies of
9 * the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25#include <media/MediaFormats.h>
26#include <media/MediaNode.h>
27#include <stdio.h>
28#include "MediaFormat.h"
29
30extern "C" {
31  #include "avcodec.h"
32
33#ifdef DEBUG
34  // Needed to fix debug build, otherwise the linker complains about
35  // "undefined reference to `ff_log2_tab'"
36  const uint8_t ff_log2_tab[256] = {0};
37#endif
38
39}  // extern "C"
40
41
42#if LIBAVCODEC_VERSION_INT <= ((54 << 16) | (50 << 8))
43#define AV_CODEC_ID_AC3 CODEC_ID_AC3
44#define AV_CODEC_ID_MP3 CODEC_ID_MP3
45#define AV_CODEC_ID_MPEG2VIDEO CODEC_ID_MPEG2VIDEO
46#endif
47
48
49void
50PrintFormat(const media_format &format)
51{
52	char s[200];
53	string_for_format(format, s, sizeof(s));
54	printf("%s\n", s);
55}
56
57
58void
59PrintFormat(const media_output &output)
60{
61	PrintFormat(output.format);
62}
63
64
65static status_t
66GetHeaderFormatAc3Audio(media_format *out_format, const uint8 *header, size_t size)
67{
68	printf("GetHeaderFormatAc3Audio\n");
69
70	status_t status;
71	media_format_description desc;
72//	desc.family = B_WAV_FORMAT_FAMILY;
73//	desc.u.wav.codec = 0x2000;
74	desc.family = B_MISC_FORMAT_FAMILY;
75	desc.u.misc.file_format = 'ffmp';
76	desc.u.misc.codec = AV_CODEC_ID_AC3;
77
78	BMediaFormats formats;
79	status = formats.InitCheck();
80	if (status) {
81		printf("formats.InitCheck failed, error %lu\n", status);
82		return status;
83	}
84
85	status = formats.GetFormatFor(desc, out_format);
86	if (status) {
87		printf("formats.GetFormatFor failed, error %lu\n", status);
88		return status;
89	}
90
91	return B_OK;
92}
93
94
95
96static status_t
97GetHeaderFormatDtsAudio(media_format *out_format, const uint8 *header, size_t size)
98{
99	printf("GetHeaderFormatDtsAudio: unsupported\n");
100	return B_ERROR;
101}
102
103
104static status_t
105GetHeaderFormatLpcmAudio(media_format *out_format, const uint8 *header, size_t size)
106{
107	printf("GetHeaderFormatLpcmAudio: unsupported\n");
108	return B_ERROR;
109}
110
111
112static status_t
113GetHeaderFormatPrivateStream(media_format *out_format, const uint8 *header, size_t size)
114{
115	printf("GetHeaderFormatPrivateStream: unsupported, assuming AC3\n");
116	return GetHeaderFormatAc3Audio(out_format, header, size);
117}
118
119
120static status_t
121GetHeaderFormatMpegAudio(media_format *out_format, const uint8 *header, size_t size)
122{
123	printf("GetHeaderFormatMpegAudio\n");
124
125	status_t status;
126	media_format_description desc;
127//	desc.family = B_MPEG_FORMAT_FAMILY;
128//	desc.u.mpeg.id = B_MPEG_2_AUDIO_LAYER_2;
129	desc.family = B_MISC_FORMAT_FAMILY;
130	desc.u.misc.file_format = 'ffmp';
131	desc.u.misc.codec = AV_CODEC_ID_MP3;
132
133
134	BMediaFormats formats;
135	status = formats.InitCheck();
136	if (status) {
137		printf("formats.InitCheck failed, error %lu\n", status);
138		return status;
139	}
140
141	status = formats.GetFormatFor(desc, out_format);
142	if (status) {
143		printf("formats.GetFormatFor failed, error %lu\n", status);
144		return status;
145	}
146
147	out_format->u.encoded_audio.output.frame_rate = 48000;
148	out_format->u.encoded_audio.output.channel_count = 2;
149	out_format->u.encoded_audio.output.buffer_size = 1024;
150	return B_OK;
151}
152
153
154static status_t
155GetHeaderFormatMpegVideo(media_format *out_format, const uint8 *header, size_t size)
156{
157	printf("GetHeaderFormatMpegVideo\n");
158
159	status_t status;
160	media_format_description desc;
161//	desc.family = B_MPEG_FORMAT_FAMILY;
162//	desc.u.mpeg.id = B_MPEG_2_VIDEO;
163	desc.family = B_MISC_FORMAT_FAMILY;
164	desc.u.misc.file_format = 'ffmp';
165	desc.u.misc.codec = AV_CODEC_ID_MPEG2VIDEO;
166
167	BMediaFormats formats;
168	status = formats.InitCheck();
169	if (status) {
170		printf("formats.InitCheck failed, error %lu\n", status);
171		return status;
172	}
173
174	status = formats.GetFormatFor(desc, out_format);
175	if (status) {
176		printf("formats.GetFormatFor failed, error %lu\n", status);
177		return status;
178	}
179
180	return B_OK;
181}
182
183
184status_t
185GetHeaderFormat(media_format *out_format, const void *header, size_t size, int stream_id)
186{
187	const uint8 *h = (const uint8 *)header;
188	status_t status;
189
190	printf("GetHeaderFormat: stream_id %02x\n", stream_id);
191	printf("inner frame header: "
192		   "%02x %02x %02x %02x %02x %02x %02x %02x "
193		   "%02x %02x %02x %02x %02x %02x %02x %02x\n",
194		   h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7],
195		   h[8], h[9], h[10], h[11], h[12], h[13], h[14], h[15]);
196
197	if (stream_id >= 0x80 && stream_id <= 0x87)
198		status = GetHeaderFormatAc3Audio(out_format, h, size);
199	else if (stream_id >= 0x88 && stream_id <= 0x8F)
200		status = GetHeaderFormatDtsAudio(out_format, h, size);
201	else if (stream_id >= 0xA0 && stream_id <= 0xA7)
202		status = GetHeaderFormatLpcmAudio(out_format, h, size);
203	else if (stream_id == 0xBD)
204		status = GetHeaderFormatPrivateStream(out_format, h, size);
205	else if (stream_id >= 0xC0 && stream_id <= 0xDF)
206		status = GetHeaderFormatMpegAudio(out_format, h, size);
207	else if (stream_id >= 0xE0 && stream_id <= 0xEF)
208		status = GetHeaderFormatMpegVideo(out_format, h, size);
209	else {
210		printf("GetHeaderFormat: don't know what this stream_id means\n");
211		status = B_ERROR;
212	}
213
214	if (status != B_OK) {
215		printf("GetHeaderFormat: failed!\n");
216	} else {
217		printf("GetHeaderFormat: out_format ");
218		PrintFormat(*out_format);
219	}
220	return status;
221}
222