1 /***************************************************************************
2 copyright : (C) 2006 by mean
3 email : fixounet@free.fr
4 ***************************************************************************/
5
6 /***************************************************************************
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 ***************************************************************************/
14 #include "ADM_cpp.h"
15 #include "ADM_default.h"
16 #include "math.h"
17 #include "ADM_Video.h"
18
19 #include "ADM_mkv.h"
20 #include "ADM_a52info.h"
21 #include "ADM_eac3info.h"
22 #include "ADM_dcainfo.h"
23
24 #include "ADM_vidMisc.h"
25 #if 0
26 #define vprintf printf
27 #else
28 #define vprintf(...) {}
29 #endif
30
31 /**
32 \fn mkvAccess
33 \brief constructor
34
35 */
mkvAccess(const char * name,mkvTrak * track)36 mkvAccess::mkvAccess(const char *name,mkvTrak *track)
37 {
38 uint8_t ac3Buffer[20000];
39 uint32_t len,sample;
40 uint64_t timecode;
41
42 _parser=new ADM_ebml_file();
43 ADM_assert(_parser->open(name));
44 _track=track;
45 ADM_assert(_track);
46 _currentBlock=0;
47 _currentLace=_maxLace=0;
48 goToBlock(0);
49
50 if(track->duration && !track->wavHeader.byterate)
51 track->wavHeader.byterate=(uint32_t)(track->_sizeInBytes*1000000LL/track->duration);
52
53 /* Check that it is really EAC3 */
54 if(_track->wavHeader.encoding==WAV_EAC3)
55 {
56 if(getPacket(ac3Buffer, &len, 20000, &timecode))
57 {
58 uint32_t syncoff;
59 ADM_EAC3_INFO efo;
60 if(ADM_EAC3GetInfo(ac3Buffer, len, &syncoff, &efo, false))
61 {
62 track->wavHeader.channels=efo.channels;
63 track->wavHeader.frequency=efo.frequency;
64 track->wavHeader.byterate=efo.byterate;
65 }else
66 {
67 track->wavHeader.encoding=WAV_AC3;
68 }
69 }
70 goToBlock(0);
71 }
72
73 /* In case of AC3, do not trust the header...*/
74 if(_track->wavHeader.encoding==WAV_AC3)
75 {
76 if( getPacket(ac3Buffer, &len, 20000,&timecode))
77 {
78 uint32_t fq,br,chan,syncoff;
79 if( ADM_AC3GetInfo(ac3Buffer, len, &fq, &br, &chan,&syncoff) )
80 {
81 track->wavHeader.channels=chan;
82 track->wavHeader.frequency=fq;
83 track->wavHeader.byterate=br;
84 }
85 }
86 goToBlock(0);
87 }
88
89 if(_track->wavHeader.encoding==WAV_DTS)
90 {
91 if( getPacket(ac3Buffer, &len, 20000,&timecode))
92 {
93 uint32_t syncoff,flags,nbsample;
94 ADM_DCA_INFO info;
95 if( true==ADM_DCAGetInfo(ac3Buffer, len,&info,&syncoff) )
96 {
97 track->wavHeader.channels=info.channels;
98 track->wavHeader.frequency=info.frequency;
99 track->wavHeader.byterate=info.bitrate/8;
100 }
101 }
102 goToBlock(0);
103 }
104
105
106 }
107 /**
108 \fn getExtraData
109 */
getExtraData(uint32_t * l,uint8_t ** d)110 bool mkvAccess::getExtraData(uint32_t *l, uint8_t **d)
111 {
112 *l=_track->extraDataLen;
113 *d=_track->extraData;
114 return true;
115 }
116 /**
117 \fn getDurationInUs
118 */
getDurationInUs(void)119 uint64_t mkvAccess::getDurationInUs(void)
120 {
121
122 uint32_t limit=_track->index.size();
123 if(!limit) return 0;
124 return _track->index[limit-1].Dts;
125 }
126 /**
127 \fn mkvAccess
128 \brief destructor
129 */
~mkvAccess()130 mkvAccess::~mkvAccess()
131 {
132 if(_parser) delete _parser;
133 _parser=NULL;
134 }
135 /**
136 \fn goToCluster
137 \brief Change the cluster parser...
138 */
goToBlock(uint32_t x)139 uint8_t mkvAccess::goToBlock(uint32_t x)
140 {
141 uint32_t limit=_track->index.size();
142 if(x>=limit)
143 {
144 ADM_warning("Exceeding max cluster : asked: %u max :%u\n",x,limit);
145 return 0; // FIXME
146 }
147
148 _parser->seek(_track->index[x].pos);
149 _currentLace=_maxLace=0;
150 _currentBlock=x;
151 return 1;
152 }
153 /**
154 \fn goToTime
155 */
goToTime(uint64_t timeUs)156 bool mkvAccess::goToTime(uint64_t timeUs)
157 {
158 uint64_t targetUs=timeUs;
159 int clus=-1;
160 uint32_t limit=_track->index.size();
161 if(!limit)
162 {
163 ADM_warning("No audio index, cannot seek\n");
164 return false;
165 }
166 mkvListOfIndex *dex=&(_track->index);
167 // First identify the cluster...
168
169 if(timeUs<(*dex)[0].Dts)
170 {
171 clus=0;
172 }else
173 {
174 for(int i=0;i<limit-1;i++)
175 {
176 if(targetUs>=(*dex)[i].Dts && targetUs<(*dex)[i+1].Dts)
177 {
178 clus=i;
179 break;
180 }
181 }
182 }
183 if(clus==-1) clus=limit-1; // Hopefully in the last one
184 ADM_info("[MKVAUDIO] Asked for %s , go to block %d\n",ADM_us2plain(timeUs),clus);
185 ADM_info("[MKVAUDIO] This block starts at %s\n",ADM_us2plain((*dex)[clus].Dts));
186 targetUs-=(*dex)[clus].Dts; // now the time is relative
187 ADM_info("[MKVAUDIO] Offset=%" PRId64" us\n",(int64_t)targetUs);
188 goToBlock(clus);
189
190
191 // Now seek more finely
192 // will be off by one frame
193 #if 0
194 #define MAX_SEEK_BUFFER 20000
195 uint8_t buffer[MAX_SEEK_BUFFER];
196 uint32_t len,samples;
197 uint64_t timecode;
198 while(getPacket(buffer, &len, MAX_SEEK_BUFFER,&timecode))
199 {
200 uint64_t curTime=_clusters[_currentCluster].Dts;
201 vprintf("Wanted: %lu us clusTime : %lu Timecode:%lu us\n",timeUs,_curTimeCodeUs,timecode);
202 ADM_assert(len<MAX_SEEK_BUFFER);
203
204 if(timecode>=(timeUs))
205 {
206 printf("[MKV audio] fine seek to %u \n",timecode);
207 return 1;
208 }
209 }
210 printf("Failed to seek to %u mstime\n");
211 return 0;
212 #else
213 return 1;
214 #endif
215 return 1;
216
217 }
218 /**
219 \fn initLaces
220 \brief start a bunch of lace, compute the missing DTSs
221 */
initLaces(uint32_t nbLaces,uint64_t time)222 bool mkvAccess::initLaces(uint32_t nbLaces,uint64_t time)
223 {
224 _maxLace=nbLaces;
225 _currentLace=1;
226 _lastDtsBase=time;
227 _currentBlock++;
228 if(_currentBlock<_track->index.size()) // is it not the last block
229 {
230 uint64_t deltaTime=_track->index[_currentBlock].Dts;
231 deltaTime-=time;
232 _laceIncrementUs=deltaTime/nbLaces;
233 vprintf("***************DeltaTime : %" PRIu64" inc:%" PRIu64"\n",deltaTime,_laceIncrementUs);
234 } // else keep lastIncrement, which is as good as a random value
235 return true;
236 }
237 /**
238 \fn getPacket
239 */
getPacket(uint8_t * dest,uint32_t * packlen,uint32_t maxSize,uint64_t * timecode)240 bool mkvAccess::getPacket(uint8_t *dest, uint32_t *packlen, uint32_t maxSize,uint64_t *timecode)
241 {
242 uint64_t fileSize,len,bsize,pos;
243 uint32_t alen,vlen;
244 uint64_t id;
245 ADM_MKV_TYPE type;
246 const char *ss;
247
248 // vprintf("Enter: Currently at :%llx\n",_clusterParser->tell());
249
250 // Have we still lace to go ?
251 if(_currentLace<_maxLace)
252 {
253 *packlen= readAndRepeat(dest, _Laces[_currentLace],maxSize);
254 ADM_assert(*packlen<maxSize);
255 vprintf("Continuing lacing : %u bytes, lacing %u/%u\n",*packlen,_currentLace,_maxLace);
256 *timecode=_lastDtsBase+_laceIncrementUs*_currentLace;
257 vprintf(">>>>>>>>> %" PRIu64" \n",*timecode);
258 _currentLace++;
259 return true;
260 }
261 if(_currentBlock>=_track->index.size()) return false;
262 // Else we start a new lace (or no lacing at all)
263 goToBlock(_currentBlock);
264 mkvIndex *dex=&(_track->index[_currentBlock]);
265 uint64_t size=dex->size-3;
266 uint64_t time=dex->Dts;
267 if(!time && _currentBlock) time=ADM_AUDIO_NO_DTS;
268 vprintf("[MKV] Time :%lu block:%u\n",time,_currentBlock);
269 // Read headers & flags
270 int16_t dummyTime=_parser->readSignedInt(2);
271 //if(!track) printf("TC: %d\n",timecode);
272 uint8_t flags=_parser->readu8();
273 int lacing=((flags>>1)&3);
274 vprintf("[MKV] Lacing : %u\n",lacing);
275 *timecode=time;
276 switch(lacing)
277 {
278 case 0 : // no lacing
279
280 vprintf("No lacing :%d bytes\n",(int)size);
281 *packlen= readAndRepeat(dest,size,maxSize);
282 _currentLace=_maxLace=0;
283 _currentBlock++;
284 return 1;
285 case 1: //Xiph lacing
286 {
287 int nbLaces=_parser->readu8()+1;
288 size--;
289 ADM_assert(nbLaces<MKV_MAX_LACES);
290 for(int i=0;i<nbLaces-1;i++)
291 {
292 int v=0;
293 int lce=0;
294 while( (v=_parser->readu8())==0xff)
295 {
296 lce+=v;
297 size-=(1+0xff);
298 }
299 lce+=v;
300 size--;
301 size-=v;
302 _Laces[i]=lce;
303 }
304
305 // The first one has Dts
306 *packlen= readAndRepeat(dest, _Laces[0],maxSize);
307 _Laces[nbLaces-1]=size;
308
309 initLaces(nbLaces,time);
310 return 1;
311 }
312
313 break;
314 case 2 : // constant size lacing
315 {
316 int nbLaces=_parser->readu8()+1;
317 size--;
318 int bsize=size/nbLaces;
319 vprintf("NbLaces :%u lacesize:%u\n",nbLaces,bsize);
320 ADM_assert(nbLaces<MKV_MAX_LACES);
321 for(int i=0;i<nbLaces;i++)
322 {
323 _Laces[i]=bsize;
324 }
325 *packlen= readAndRepeat(dest, bsize,maxSize);
326 // The first one has Dts
327 initLaces(nbLaces,time);
328
329 return 1;
330 }
331 break;
332
333 case 3: // Ebml lacing
334 {
335 uint64_t head=_parser->tell();
336 int nbLaces=_parser->readu8()+1;
337 int32_t curSize=_parser->readEBMCode();
338 int32_t delta;
339 uint32_t sum;
340
341
342 vprintf("Ebml nbLaces :%u lacesize(0):%u\n",nbLaces,curSize);
343
344 _Laces[0]=curSize;
345 sum=curSize;
346 ADM_assert(nbLaces<MKV_MAX_LACES);
347 for(int i=1;i<nbLaces-1;i++)
348 {
349 delta=_parser->readEBMCode_Signed();
350 vprintf("Ebml delta :%d lacesize[%d]->:%d\n",delta,i,curSize+delta);
351 curSize+=delta;
352 ADM_assert(curSize>0);
353 _Laces[i]=curSize;
354 sum+=curSize;
355
356 }
357 uint64_t tail=_parser->tell();
358 uint64_t consumed=head+size-tail;
359
360 _Laces[nbLaces-1]=consumed-sum;
361
362 // Take the 1st laces, it has timestamp
363 *packlen= readAndRepeat(dest, _Laces[0],maxSize);
364 ADM_assert(*packlen<maxSize);
365 vprintf("Continuing lacing : dts : %lu %u bytes, lacing %u/%u\n",time,*packlen,_currentLace,_maxLace);
366 initLaces(nbLaces,time);
367 return 1;
368 }
369 break;
370 default:
371 printf("Unsupported lacing %u\n",lacing);
372 goToBlock(0);
373 }
374
375 return false;
376 }
377 //EOF
378