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