1 /*
2 * $Id$
3 * Copyright (c) 2010-2011, Matroska (non-profit organisation)
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Matroska assocation nor the
14 * names of its contributors may be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY the Matroska association ``AS IS'' AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL The Matroska Foundation BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28 #include "matroska/matroska.h"
29 #include "matroska/matroska_sem.h"
30 #include "matroska/matroska_internal.h"
31 #if defined(CONFIG_CODEC_HELPER)
32 #include "ivorbiscodec.h"
33 #include "codec_internal.h"
34 #include "misc.h"
35 #endif
36
37 static int A_MPEG_freq[4][4] =
38 {
39 // v2.5 * v2 v1
40 {11025, 0, 22050, 44100},
41 {12000, 0, 24000, 48000},
42 { 8000, 0, 16000, 32000},
43 { 0, 0, 0, 0}
44 };
45
46 static int A_MPEG_samples[4][4] =
47 {
48 // v2.5 * v2 v1
49 { 0, 0, 0, 0}, // unknown layer
50 { 576, 0, 576, 1152}, // layer III
51 {1152, 0, 1152, 1152}, // layer II
52 { 384, 0, 384, 384} // layer I
53 };
54
55 static const int A_AC3_freq[3][4] =
56 {
57 {48000, 44100, 32000, 0}, // EEEE<=8
58 {24000, 22050, 16000, 0}, // EEEE=9
59 {12000, 11025, 8000, 0}, // EEEE=10
60 };
61
62 static const int A_EAC3_freq[6] = { 48000, 44100, 32000, 24000, 22050, 16000 };
63 static const int A_EAC3_samples[4] = { 256, 512, 768, 1536 };
64
65 static const int A_DTS_freq[16] = {
66 0, 8000, 16000, 32000, 0, 0, 11025, 22050, 44100, 0, 0, 12000, 24000, 48000, 0, 0
67 };
68
69
MATROSKA_BlockProcessFrameDurations(matroska_block * Block,stream * Input)70 err_t MATROSKA_BlockProcessFrameDurations(matroska_block *Block, stream *Input)
71 {
72 ebml_master *Track=NULL;
73 ebml_element *Elt;
74 tchar_t CodecID[MAXPATH];
75 err_t Err;
76 bool_t ReadData;
77 uint8_t *Cursor;
78 size_t Frame;
79 int Version, Layer, SampleRate, Samples, fscod, fscod2;
80
81 Err = Node_GET(Block,MATROSKA_BLOCK_READ_TRACK,&Track);
82 if (Err==ERR_NONE)
83 {
84 assert(Track!=NULL);
85 Elt = EBML_MasterFindChild(Track,&MATROSKA_ContextTrackType);
86 if (!Elt || EBML_IntegerValue((ebml_integer*)Elt)!=TRACK_TYPE_AUDIO) // other track types not supported for now
87 Err = ERR_INVALID_DATA;
88 else
89 {
90 if (Block->FirstFrameLocation==0)
91 Err = ERR_READ;
92 else
93 {
94 Elt = EBML_MasterFindChild(Track,&MATROSKA_ContextCodecID);
95 if (!Elt) // missing codec ID
96 Err = ERR_INVALID_DATA;
97 else
98 {
99 EBML_StringGet((ebml_string*)Elt,CodecID,TSIZEOF(CodecID));
100 ReadData = 0;
101 if (!ArraySize(&Block->Data))
102 {
103 Err = MATROSKA_BlockReadData(Block,Input);
104 if (Err!=ERR_NONE)
105 goto exit;
106 ReadData = 1;
107 }
108
109 if (tcsisame_ascii(CodecID,T("A_MPEG/L3")) || tcsisame_ascii(CodecID,T("A_MPEG/L2")) || tcsisame_ascii(CodecID,T("A_MPEG/L1")))
110 {
111 Block->IsKeyframe = 1; // safety
112 ArrayResize(&Block->Durations,sizeof(timecode_t)*ARRAYCOUNT(Block->SizeList,int32_t),0);
113 Cursor = ARRAYBEGIN(Block->Data,uint8_t);
114 for (Frame=0;Frame<ARRAYCOUNT(Block->SizeList,int32_t);++Frame)
115 {
116 Version = (Cursor[1] >> 3) & 3;
117 Layer = (Cursor[1] >> 1) & 3;
118 SampleRate = (Cursor[2] >> 2) & 3;
119
120 Samples = A_MPEG_samples[Layer][Version];
121 SampleRate = A_MPEG_freq[SampleRate][Version];
122 if (SampleRate!=0 && Samples!=0)
123 ARRAYBEGIN(Block->Durations,timecode_t)[Frame] = Scale64(1000000000,Samples,SampleRate);
124 else
125 {
126 Err = ERR_INVALID_DATA;
127 ARRAYBEGIN(Block->Durations,timecode_t)[Frame] = INVALID_TIMECODE_T;
128 //goto exit;
129 }
130
131 Cursor += ARRAYBEGIN(Block->SizeList,int32_t)[Frame];
132 }
133 }
134 else if (tcsisame_ascii(CodecID,T("A_AC3")))
135 {
136 Block->IsKeyframe = 1; // safety
137 ArrayResize(&Block->Durations,sizeof(timecode_t)*ARRAYCOUNT(Block->SizeList,int32_t),0);
138 Cursor = ARRAYBEGIN(Block->Data,uint8_t);
139 for (Frame=0;Frame<ARRAYCOUNT(Block->SizeList,int32_t);++Frame)
140 {
141 fscod = Cursor[5] >> 3;
142 SampleRate = Cursor[4] >> 6;
143 if (fscod > 10 || fscod < 8)
144 {
145 Err = ERR_INVALID_DATA;
146 ARRAYBEGIN(Block->Durations,timecode_t)[Frame] = INVALID_TIMECODE_T;
147 //goto exit;
148 }
149 else
150 {
151 SampleRate = A_AC3_freq[fscod-8][SampleRate];
152 ARRAYBEGIN(Block->Durations,timecode_t)[Frame] = Scale64(1000000000,1536,SampleRate);
153 }
154 Cursor += ARRAYBEGIN(Block->SizeList,int32_t)[Frame];
155 }
156 }
157 else if (tcsisame_ascii(CodecID,T("A_EAC3")))
158 {
159 Block->IsKeyframe = 1; // safety
160 ArrayResize(&Block->Durations,sizeof(timecode_t)*ARRAYCOUNT(Block->SizeList,int32_t),0);
161 Cursor = ARRAYBEGIN(Block->Data,uint8_t);
162 for (Frame=0;Frame<ARRAYCOUNT(Block->SizeList,int32_t);++Frame)
163 {
164 fscod = Cursor[4] >> 6;
165 fscod2 = (Cursor[4] >> 4) & 0x03;
166 if ((0x03 == fscod) && (0x03 == fscod2))
167 {
168 Err = ERR_INVALID_DATA;
169 ARRAYBEGIN(Block->Durations,timecode_t)[Frame] = INVALID_TIMECODE_T;
170 //goto exit;
171 }
172 else
173 {
174 SampleRate = A_EAC3_freq[0x03 == fscod ? 3 + fscod2 : fscod];
175 Samples = (0x03 == fscod) ? 1536 : A_EAC3_samples[fscod2];
176 ARRAYBEGIN(Block->Durations,timecode_t)[Frame] = Scale64(1000000000,Samples,SampleRate);
177 }
178 Cursor += ARRAYBEGIN(Block->SizeList,int32_t)[Frame];
179 }
180 }
181 else if (tcsisame_ascii(CodecID,T("A_DTS")))
182 {
183 Block->IsKeyframe = 1; // safety
184 ArrayResize(&Block->Durations,sizeof(timecode_t)*ARRAYCOUNT(Block->SizeList,int32_t),0);
185 Cursor = ARRAYBEGIN(Block->Data,uint8_t);
186 for (Frame=0;Frame<ARRAYCOUNT(Block->SizeList,int32_t);++Frame)
187 {
188 Samples = (((Cursor[4] & 1) << 7) + (Cursor[5] >> 2) + 1) * 32;
189 // TODO: handle the frame termination
190 SampleRate = A_DTS_freq[(Cursor[8] >> 2) & 0x0F];
191 if (Samples==0 || SampleRate==0)
192 {
193 Err = ERR_INVALID_DATA;
194 ARRAYBEGIN(Block->Durations,timecode_t)[Frame] = INVALID_TIMECODE_T;
195 //goto exit;
196 }
197 else
198 ARRAYBEGIN(Block->Durations,timecode_t)[Frame] = Scale64(1000000000,Samples,SampleRate);
199 Cursor += ARRAYBEGIN(Block->SizeList,int32_t)[Frame];
200 }
201 }
202 else if (tcsisame_ascii(CodecID,T("A_AAC")) || tcsncmp(CodecID,T("A_AAC/"),6)==0)
203 {
204 Block->IsKeyframe = 1; // safety
205 Elt = EBML_MasterFindChild(Track,&MATROSKA_ContextAudio);
206 if (Elt)
207 {
208 Elt = EBML_MasterFindChild((ebml_master*)Elt,&MATROSKA_ContextSamplingFrequency);
209 if (Elt)
210 {
211 ArrayResize(&Block->Durations,sizeof(timecode_t)*ARRAYCOUNT(Block->SizeList,int32_t),0);
212 Samples = 1024;
213 SampleRate = (int)((ebml_float*)Elt)->Value;
214 for (Frame=0;Frame<ARRAYCOUNT(Block->SizeList,int32_t);++Frame)
215 ARRAYBEGIN(Block->Durations,timecode_t)[Frame] = Scale64(1000000000,Samples,SampleRate);
216 }
217 }
218 }
219 #if defined(CONFIG_CODEC_HELPER)
220 else if (tcsisame_ascii(CodecID,T("A_VORBIS")))
221 {
222 Block->IsKeyframe = 1; // safety
223 Elt = EBML_MasterFindChild(Track,&MATROSKA_ContextCodecPrivate);
224 if (Elt)
225 {
226 vorbis_info vi;
227 vorbis_comment vc;
228 ogg_packet OggPacket;
229 ogg_reference OggRef;
230 ogg_buffer OggBuffer;
231 int n,i,j;
232 codec_setup_info *ci;
233
234 vorbis_info_init(&vi);
235 vorbis_comment_init(&vc);
236 memset(&OggPacket,0,sizeof(ogg_packet));
237
238 OggBuffer.data = (uint8_t*)EBML_BinaryGetData((ebml_binary*)Elt);
239 OggBuffer.size = (long)Elt->DataSize;
240 OggBuffer.refcount = 1;
241
242 memset(&OggRef,0,sizeof(OggRef));
243 OggRef.buffer = &OggBuffer;
244 OggRef.next = NULL;
245
246 OggPacket.packet = &OggRef;
247 OggPacket.packetno = -1;
248
249 n = OggBuffer.data[0];
250 i = 1+n;
251 j = 1;
252
253 while (OggPacket.packetno < 3 && n>=j)
254 {
255 OggRef.begin = i;
256 OggRef.length = 0;
257 do
258 {
259 OggRef.length += OggBuffer.data[j];
260 }
261 while (OggBuffer.data[j++] == 255 && n>=j);
262 i += OggRef.length;
263
264 if (i > OggBuffer.size)
265 return ERR_INVALID_DATA;
266
267 ++OggPacket.packetno;
268 OggPacket.b_o_s = OggPacket.packetno == 0;
269 OggPacket.bytes = OggPacket.packet->length;
270 if (!(vorbis_synthesis_headerin(&vi,&vc,&OggPacket) >= 0) && OggPacket.packetno==0)
271 return ERR_INVALID_DATA;
272 }
273
274 if (OggPacket.packetno < 3)
275 {
276 OggRef.begin = i;
277 OggRef.length = OggBuffer.size - i;
278
279 ++OggPacket.packetno;
280 OggPacket.b_o_s = OggPacket.packetno == 0;
281 OggPacket.bytes = OggPacket.packet->length;
282
283 if (!(vorbis_synthesis_headerin(&vi,&vc,&OggPacket) >= 0) && OggPacket.packetno==0)
284 return ERR_INVALID_DATA;
285 }
286
287 SampleRate = vi.rate;
288 ArrayResize(&Block->Durations,sizeof(timecode_t)*ARRAYCOUNT(Block->SizeList,int32_t),0);
289 Cursor = ARRAYBEGIN(Block->Data,uint8_t);
290 ci = vi.codec_setup;
291 for (Frame=0;Frame<ARRAYCOUNT(Block->SizeList,int32_t);++Frame)
292 {
293 fscod = _ilog(ci->modes-1);
294 fscod = (Cursor[0] & 0x7F) >> (7-fscod);
295 if (fscod > ci->modes)
296 {
297 Err = ERR_INVALID_DATA;
298 ARRAYBEGIN(Block->Durations,timecode_t)[Frame] = INVALID_TIMECODE_T;
299 //goto exit;
300 }
301 else
302 {
303 Samples = ci->blocksizes[ci->mode_param[fscod]->blockflag];
304 ARRAYBEGIN(Block->Durations,timecode_t)[Frame] = Scale64(1000000000,Samples,SampleRate);
305 }
306 Cursor += ARRAYBEGIN(Block->SizeList,int32_t)[Frame];
307 }
308 vorbis_comment_clear(&vc);
309 vorbis_info_clear(&vi);
310 }
311 }
312 #endif
313
314 if (ReadData)
315 {
316 ArrayClear(&Block->Data);
317 Block->Base.Base.bValueIsSet = 0;
318 }
319 }
320 }
321 }
322 }
323 exit:
324 return Err;
325 }
326
MATROSKA_BlockGetFrameCount(const matroska_block * Block)327 size_t MATROSKA_BlockGetFrameCount(const matroska_block *Block)
328 {
329 return ARRAYCOUNT(Block->SizeList,int32_t);
330 }
331
MATROSKA_BlockGetLength(const matroska_block * Block,size_t FrameNum)332 size_t MATROSKA_BlockGetLength(const matroska_block *Block, size_t FrameNum)
333 {
334 if (FrameNum >= ARRAYCOUNT(Block->SizeList,int32_t))
335 return 0;
336 return ARRAYBEGIN(Block->SizeList,int32_t)[FrameNum];
337 }
338
MATROSKA_BlockGetFrameDuration(const matroska_block * Block,size_t FrameNum)339 timecode_t MATROSKA_BlockGetFrameDuration(const matroska_block *Block, size_t FrameNum)
340 {
341 if (FrameNum >= ARRAYCOUNT(Block->Durations,timecode_t))
342 return INVALID_TIMECODE_T;
343 return ARRAYBEGIN(Block->Durations,timecode_t)[FrameNum];
344 }
345
MATROSKA_BlockGetFrameStart(const matroska_block * Block,size_t FrameNum)346 timecode_t MATROSKA_BlockGetFrameStart(const matroska_block *Block, size_t FrameNum)
347 {
348 if (FrameNum >= ARRAYCOUNT(Block->Durations,timecode_t))
349 return INVALID_TIMECODE_T;
350 else
351 {
352 size_t i;
353 timecode_t Start = MATROSKA_BlockTimecode((matroska_block*)Block);
354 if (Start!=INVALID_TIMECODE_T)
355 {
356 for (i=0;i<FrameNum;++i)
357 {
358 if (ARRAYBEGIN(Block->Durations,timecode_t)[i]==INVALID_TIMECODE_T)
359 return INVALID_TIMECODE_T;
360 Start += ARRAYBEGIN(Block->Durations,timecode_t)[i];
361 }
362 }
363 return Start;
364 }
365 }
366
MATROSKA_BlockGetFrameEnd(const matroska_block * Block,size_t FrameNum)367 timecode_t MATROSKA_BlockGetFrameEnd(const matroska_block *Block, size_t FrameNum)
368 {
369 timecode_t Result = MATROSKA_BlockGetFrameStart(Block,FrameNum), a;
370 if (Result==INVALID_TIMECODE_T)
371 return INVALID_TIMECODE_T;
372 a = MATROSKA_BlockGetFrameDuration(Block,FrameNum);
373 if (a==INVALID_TIMECODE_T)
374 return INVALID_TIMECODE_T;
375 return Result + a;
376 }
377