1 /***************************************************************************
2                           ADMMP4p.cpp  -  description
3                              -------------------
4 
5 		Read quicktime/mpeg4 file format found in 3gpp file.
6 		They are limited to SQCIF/QCIF video size and can
7 		only contains
8 			video : h263 or mpeg4
9 			audio : AMR or AAC
10 
11 
12 		For the mpeg4, the VOL headers are stored in esds atom
13 		and not in the first image
14 		Idem for MJPG and SVQ3
15 
16 		The usual tree structure of a 3gp file is
17 
18 		- ftyp
19 		- mdat
20 		- moov
21 			xxx
22 			trak
23 				tkhd (duration / ...)
24 			mdia
25 				hdlr (type)
26 				minf
27 					stsd header for audio/video
28 					stbl index to datas
29 
30 	We ignore other chunk as they are not vital for our aim
31 	and just keep moov/mdia/minf/stsd/stbl stuff
32 
33 Generic
34 *********
35 http://developer.apple.com/documentation/QuickTime/QTFF/QTFFChap2/chapter_3_section_5.html#//apple_ref/doc/uid/DontLinkBookID_69-CH204-BBCJEIIA
36 
37 version 2 media descriptor :
38 ****************************** http://developer.apple.com/documentation/QuickTime/Conceptual/QT7Win_Update_Guide/Chapter03/chapter_3_section_1.html#//apple_ref/doc/uid/TP40002476-CH314-BBCDGGBB
39 
40 
41 
42     begin                : Tue Jul  2003
43     copyright            : (C) 2003/2006 by mean
44     email                : fixounet@free.fr
45  ***************************************************************************/
46 
47 /***************************************************************************
48  *                                                                         *
49  *   This program is free software; you can redistribute it and/or modify  *
50  *   it under the terms of the GNU General Public License as published by  *
51  *   the Free Software Foundation; either version 2 of the License, or     *
52  *   (at your option) any later version.                                   *
53  *                                                                         *
54  ***************************************************************************/
55 
56 
57 #include <string.h>
58 #include <math.h>
59 
60 #include "ADM_default.h"
61 #include "ADM_Video.h"
62 
63 #include "fourcc.h"
64 #include "ADM_mp4.h"
65 
66 #include "ADM_vidMisc.h"
67 #include "DIA_processing.h"
68 
69 #include "ADM_videoInfoExtractor.h"
70 #include "ADM_codecType.h"
71 #include "ADM_a52info.h"
72 #include "ADM_mp3info.h"
73 #include "ADM_audioXiphUtils.h"
74 
75 #if 1
76 #define aprintf(...) {}
77 #else
78 #define aprintf printf
79 #endif
80 
81 //#define MP4_VERBOSE
82 #define MAX_CHUNK_SIZE (3*1024)
83 
84 uint32_t ADM_UsecFromFps1000(uint32_t fps1000);
85 //****************************************************
MP4Track(void)86 MP4Track::MP4Track(void)
87 {
88     extraDataSize=0;
89     extraData=NULL;
90     index=NULL;
91     nbIndex=0;
92     id=0;
93     memset(&_rdWav,0,sizeof(_rdWav));
94     delay=0;
95     totalDataSize=0;
96 }
~MP4Track()97 MP4Track::~MP4Track()
98 {
99     if(extraData) delete [] extraData;
100     if(index)   delete [] index;
101 
102     index=NULL;
103     extraData=NULL;
104 
105 }
106 //****************************************************
setFlag(uint32_t frame,uint32_t flags)107 uint8_t MP4Header::setFlag(uint32_t frame,uint32_t flags)
108 {
109     UNUSED_ARG(frame);
110     UNUSED_ARG(flags);
111 
112     VDEO.index[frame].intra=flags;
113     return 0;
114 }
115 
getFlags(uint32_t frame,uint32_t * flags)116 uint32_t MP4Header::getFlags(uint32_t frame,uint32_t *flags)
117 {
118         if(frame>= (uint32_t)_videostream.dwLength) return 0;
119         *flags=VDEO.index[frame].intra;
120 
121         return 1;
122 }
123 /**
124     \fn getTime
125 */
getTime(uint32_t frameNum)126 uint64_t                   MP4Header::getTime(uint32_t frameNum)
127 {
128     ADM_assert(frameNum<VDEO.nbIndex);
129     // Assume if not PTS, PTS=DTS (non mpeg4/non h264 streams)
130     if(VDEO.index[frameNum].pts==ADM_COMPRESSED_NO_PTS) return VDEO.index[frameNum].dts;
131     return VDEO.index[frameNum].pts;
132 }
133 /**
134     \fn getVideoDuration
135 */
getVideoDuration(void)136 uint64_t                   MP4Header::getVideoDuration(void)
137 {
138     return _movieDuration*1000LL; //VDEO.index[VDEO.nbIndex-1].time;
139 
140 }
141 
142 #ifdef DERIVE_TB_FROM_MINIMUM_DELTA
143 /**
144  * \fn compute the minimum us delta = maximum fps
145  * \brief average fps is not good enough, it might be too high
146  * @return
147  */
refineFps(void)148 bool MP4Header::refineFps(void)
149 {
150     int n=VDEO.nbIndex;
151     uint64_t minDelta=60*1000*1000;
152     for(int i=0;i<n-1;i++)
153     {
154         MP4Index *dex=&(_tracks[0].index[i]);
155         MP4Index *next=&(_tracks[0].index[i+1]);
156         if(dex->dts==ADM_NO_PTS) continue;
157         if(next->dts==ADM_NO_PTS) continue;
158         uint64_t delta=next->dts-dex->dts;
159         if(delta<minDelta) minDelta=delta;
160     }
161     if(minDelta>1000)
162     {
163         double f=1000000./(double)minDelta;
164         f*=1000.;
165         uint32_t fps1000=floor(f+0.49);
166         ADM_info("MinDelta=%d us\n",(int)minDelta);
167         ADM_info("Computed fps1000=%d\n",fps1000);
168         if(fps1000 == _videostream.dwRate)
169         {
170             ADM_info("Computed fps1000 matches the average one.\n");
171             return true;
172         }
173         int score=0;
174         uint64_t avgDelta=_mainaviheader.dwMicroSecPerFrame;
175         int64_t halfway=avgDelta-minDelta+1;
176         halfway/=2;
177         halfway+=minDelta;
178         for(int i=0;i<n-1;i++)
179         {
180             MP4Index *dex=&(_tracks[0].index[i]);
181             MP4Index *next=&(_tracks[0].index[i+1]);
182             if(dex->dts==ADM_NO_PTS) continue;
183             if(next->dts==ADM_NO_PTS) continue;
184             uint64_t delta=next->dts-dex->dts;
185             if(delta==minDelta) score++;
186             if(delta<halfway) score++;
187         }
188         float weighted=score*1000.;
189         weighted/=n;
190         ADM_info("Original fps1000 = %d, score = %d, weighted score = %d\n",_videostream.dwRate,score,(int)weighted);
191         // require that at least 10% of video better or 5% perfectly matches max fps
192         if(fps1000 > _videostream.dwRate && (int)weighted > 100)
193         {
194             ADM_info("Adjusting fps, the computed is higher than average, dropped frames ?\n");
195            _videostream.dwRate=fps1000;
196            _mainaviheader.dwMicroSecPerFrame=ADM_UsecFromFps1000(_videostream.dwRate);
197         }
198     }
199     return true;
200 
201 }
202 #endif
203 
getFrame(uint32_t framenum,ADMCompressedImage * img)204 uint8_t  MP4Header::getFrame(uint32_t framenum,ADMCompressedImage *img)
205 {
206     aprintf("[MP4] frame %d requested (nbFrame=%d)\n",framenum,VDEO.nbIndex);
207     if(framenum>=VDEO.nbIndex)
208     {
209       return 0;
210     }
211 
212 MP4Index *idx=&(VDEO.index[framenum]);
213 
214     uint64_t offset=idx->offset; //+_mdatOffset;
215 
216 
217     if(fseeko(_fd,offset,SEEK_SET))
218     {
219         ADM_error("Seeking past the end of the file! Broken index?\n");
220         return 0;
221     }
222     if(!fread(img->data, (size_t)idx->size, 1, _fd))
223     {
224         ADM_error("Incomplete frame %" PRIu32". Broken index?\n",framenum);
225         return 0;
226     }
227     img->dataLength=idx->size;
228 	img->flags = idx->intra;
229 
230     img->demuxerDts=idx->dts;
231     img->demuxerPts=idx->pts;
232     aprintf("[MP4] Pts=%s\n",ADM_us2plain(idx->pts));
233     aprintf("[MP4] Dts=%s\n",ADM_us2plain(idx->dts));
234     /*
235     if(img->demuxerPts==ADM_COMPRESSED_NO_PTS)
236         img->demuxerPts=img->demuxerDts;
237     */
238     return 1;
239 }
~MP4Header()240 MP4Header::~MP4Header()
241 {
242     close();
243 
244     for(int audio = 0; audio < nbAudioTrack; audio++)
245     {
246         delete audioStream[audio];
247         delete audioAccess[audio];
248     }
249     for(int i = 0; i < nbTrex; i++)
250     {
251         delete _trexData[i];
252         _trexData[i] = NULL;
253     }
254 }
close(void)255 uint8_t    MP4Header::close( void )
256 {
257       if(_fd)
258               {
259               fclose(_fd);
260               }
261             _fd=NULL;
262       return 1;
263 }
264 //
265 //	Set default save value
266 //
267 
MP4Header(void)268 MP4Header::MP4Header(void)
269 {
270         _fd=NULL;
271         nbAudioTrack=0;
272         _currentAudioTrack=0;
273         _reordered=0;
274         _videoScale=1;
275         _videoFound=0;
276         delayRelativeToVideo=0;
277         _flavor=Mp4Regular;
278         nbTrex=0;
279         for(int i=0;i<_3GP_MAX_TRACKS;i++)
280             _trexData[i]=NULL;
281 }
282 /**
283     \fn getAudioInfo
284     \brief
285 */
getAudioInfo(uint32_t i)286 WAVHeader    *MP4Header::getAudioInfo(uint32_t i )
287 {
288     if(nbAudioTrack)
289     {
290         ADM_assert(i<nbAudioTrack);
291         return &(_tracks[i+1]._rdWav);
292     }
293 
294     return NULL;
295 
296 }
297 /**
298     \fn getAudioStream
299 */
300 
getAudioStream(uint32_t i,ADM_audioStream ** audio)301 uint8_t      MP4Header::getAudioStream(uint32_t i,ADM_audioStream  **audio)
302 {
303     if(nbAudioTrack)
304     {
305         ADM_assert(i<nbAudioTrack);
306         *audio=audioStream[i];
307     }  else
308         *audio=NULL;
309     return 1;
310 }
311 /**
312     \fn getNbAudioStreams
313 */
getNbAudioStreams(void)314 uint8_t      MP4Header::getNbAudioStreams(void)
315 {
316     return nbAudioTrack;
317 
318 }
319 
320 
getExtraHeaderData(uint32_t * len,uint8_t ** data)321 uint8_t   MP4Header::getExtraHeaderData(uint32_t *len, uint8_t **data)
322 {
323         *len=0;*data=NULL;
324         if(_tracks[0].extraDataSize)
325         {
326             *len= VDEO.extraDataSize;
327             *data=VDEO.extraData;
328         }
329         return 1;
330 }
331 //______________________________________
332 //
333 // Open and recursively read the atoms
334 // until we got the information we want
335 // i.e. :
336 //	index for audio and video track
337 //	esds for mpeg4
338 //	size / codec used
339 //
340 // We don't care about sync atom and all
341 // other stuff which are pretty useless on
342 // 3gp file anyway.
343 //______________________________________
open(const char * name)344 uint8_t    MP4Header::open(const char *name)
345 {
346         printf("** opening 3gpp files **\n");
347         _fd=ADM_fopen(name,"rb");
348         if(!_fd)
349         {
350                 printf("\n cannot open %s \n",name);
351                 return 0;
352         }
353 #define CLR(x)              memset(& x,0,sizeof(  x));
354 
355         CLR( _videostream);
356         CLR(  _mainaviheader);
357 
358         _videostream.dwScale=1000;
359         _videostream.dwRate=10000;
360         _mainaviheader.dwMicroSecPerFrame=100000;;     // 10 fps hard coded
361 
362         adm_atom *atom=new adm_atom(_fd);
363         // Some mp4/mov files have the data at the end but do start properly
364         // detect and workaround...
365         // Check it is not mdat start(ADM_memcpy_0)
366         uint8_t check[4];
367         uint64_t fileSize;
368         fseeko(_fd,0,SEEK_END);
369         fileSize=ftello(_fd);
370         fseeko(_fd,4,SEEK_SET);
371         fread(check,4,1,_fd);
372         fseeko(_fd,0,SEEK_SET);
373         if(check[0]=='m' && check[1]=='d' &&check[2]=='a' && check[3]=='t')
374         {
375                         uint64_t of;
376                         uint64_t hi,lo;
377                                         printf("Data first, header later...\n");
378                                         of=atom->read32();
379                                         if(of==1)
380                                         {
381                                           atom->read32();	// size
382                                           atom->read32();	// fcc
383                                           hi=atom->read32();
384                                           lo=atom->read32();
385                                           of=(hi<<32)+lo;
386                                           if(of>fileSize) of=hi;
387                                         }
388                                         fseeko(_fd,of,SEEK_SET);
389                                         printf("Header starts at %" PRIx64"\n",of);
390                                         delete atom;
391                                         atom=new adm_atom(_fd);
392         }
393         //**************
394 
395         if(!lookupMainAtoms((void*) atom))
396         {
397           printf("Cannot find needed atom\n");
398           if(!_tracks[0].fragments.size() || !indexVideoFragments(0))
399           {
400             fclose(_fd);
401             _fd=NULL;
402             delete atom;
403             return 0;
404           }else
405           { // do other tracks as well
406               for(int i=1;i<=nbAudioTrack;i++)
407               {
408                   if(_tracks[i].fragments.size())
409                       indexAudioFragments(i);
410                   if(_tracks[i].index==NULL)
411                       nbAudioTrack--;
412               }
413           }
414         }
415 
416         delete atom;
417 
418         _isvideopresent=1;
419         _isaudiopresent=0;
420 
421         _videostream.fccType=fourCC::get((uint8_t *)"vids");
422         _video_bih.biBitCount=24;
423         _videostream.dwInitialFrames= 0;
424         _videostream.dwStart= 0;
425 
426 	printf("\n");
427 
428 
429         if(!VDEO.index)
430         {
431                 printf("No index!\n");
432                 return 0;
433         }
434 
435         // If it is mpeg4 and we have extra data
436         // Decode vol header to get the real width/height
437         // The mpeg4/3GP/Mov header is often misleading
438 
439         if(fourCC::check(_videostream.fccHandler,(uint8_t *)"DIVX"))
440         {
441             if(VDEO.extraDataSize)
442             {
443                 uint32_t w,h,ti;
444                 if(extractMpeg4Info(VDEO.extraData,VDEO.extraDataSize,&w,&h,&ti))
445                 {
446                     printf("MP4 Corrected size : %" PRIu32" x %" PRIu32"\n",w,h);
447                     _video_bih.biWidth=_mainaviheader.dwWidth=w ;
448                     _video_bih.biHeight=_mainaviheader.dwHeight=h;
449                 }
450             }else { printf("No extradata to probe\n");}
451 
452         }else if(fourCC::check(_videostream.fccHandler,(uint8_t *)"H263"))
453         { // Same story for H263 : Analyze 1st frame to get the real width/height
454             uint32_t w,h,sz;
455             uint8_t *bfer=NULL;
456             sz=VDEO.index[0].size;
457             if(sz)
458             {
459                 bfer=new uint8_t[sz];
460                 ADMCompressedImage img;
461                 img.data=bfer;
462                 if(getFrame(0,&img))
463                 {
464                     if(extractH263Info(bfer,sz,&w,&h))
465                     {
466                         printf("H263 Corrected size : %" PRIu32" x %" PRIu32"\n",w,h);
467                         _video_bih.biWidth=_mainaviheader.dwWidth=w ;
468                         _video_bih.biHeight=_mainaviheader.dwHeight=h;
469                     }else
470                     {
471                         printf("H263 COULD NOT EXTRACT SIZE, using : %" PRIu32" x %" PRIu32"\n",
472                         _video_bih.biWidth,  _video_bih.biHeight);
473                     }
474                 }
475                 delete [] bfer;
476             }
477         }else if(isH264Compatible(_videostream.fccHandler) && VDEO.extraDataSize)
478         { // Get frame type from H.264 slice headers, this is essential for handling of field encoded streams
479             ADM_SPSInfo info;
480             if(extractSPSInfo_mp4Header(VDEO.extraData,VDEO.extraDataSize,&info))
481             {
482                 uint32_t nalSize = ADM_getNalSizeH264(VDEO.extraData,VDEO.extraDataSize);
483                 uint32_t prevSpsLen=0;
484                 uint8_t *prevSps=NULL, *curSps=NULL;
485 #define MAX_SPS_SIZE 1024
486 #define MAX_FRAME_LENGTH (1920*1080*3) // ~7 MiB, should be enough even for 4K
487                 uint8_t *bfer=new uint8_t[MAX_FRAME_LENGTH];
488                 ADMCompressedImage img;
489                 img.data=bfer;
490                 uint32_t i,fields=0,nb=VDEO.nbIndex;
491                 uint64_t processed=0;
492                 DIA_processingBase *work=createProcessing(QT_TRANSLATE_NOOP("mp4demuxer","Decoding frame type"),nb);
493                 for(i=0;i<nb;i++)
494                 {
495                     if(work && work->update(1,processed++))
496                         break; // cancelling frame type decoding is non-fatal
497                     if(!getFrame(i,&img))
498                     {
499                         ADM_warning("Could not get frame %u while decoding H.264 frame type.\n",i);
500                         continue;
501                     }
502                     if(img.flags & AVI_KEY_FRAME)
503                     {
504                         // Check for presence of SPS in the stream. If it changes on-the-fly, we are in trouble.
505                         if(!curSps)
506                             curSps=new uint8_t[MAX_SPS_SIZE];
507                         memset(curSps,0,MAX_SPS_SIZE);
508                         uint32_t curSpsLen = getRawH264SPS(img.data, img.dataLength, nalSize, curSps, MAX_SPS_SIZE);
509                         bool match=true;
510                         if(curSpsLen)
511                         {
512                             if(prevSps)
513                             {
514                                 if(prevSpsLen)
515                                     match=!memcmp(prevSps,curSps,(prevSpsLen>curSpsLen)? curSpsLen : prevSpsLen);
516                             }else
517                             {
518                                 prevSps=new uint8_t[MAX_SPS_SIZE];
519                             }
520                             if(!match)
521                             {
522                                 ADM_warning("Codec parameters change at frame %u.\n",i);
523                                 printf("\nOld SPS:\n");
524                                 mixDump(prevSps,prevSpsLen);
525                                 printf("\nNew SPS:\n");
526                                 mixDump(curSps,curSpsLen);
527                             }
528                             prevSpsLen=curSpsLen;
529                             memset(prevSps,0,MAX_SPS_SIZE);
530                             memcpy(prevSps,curSps,prevSpsLen);
531                         }
532                         if(!match && curSps)
533                         {
534                             ADM_info("SPS mismatch? Checking deeper...\n");
535                             ADM_SPSInfo info2;
536                             if(extractSPSInfoFromData(curSps,curSpsLen,&info2))
537                             { // check only fields we actually use
538 #define MATCH(x) if(info.x != info2.x) { ADM_warning("%s value does not match.\n",#x); info.x = info2.x; match=false; }
539                                 match=true;
540                                 // FIXME: dimensions mismatch should be fatal
541                                 MATCH(CpbDpbToSkip)
542                                 MATCH(hasPocInfo)
543                                 MATCH(log2MaxFrameNum)
544                                 MATCH(log2MaxPocLsb)
545                                 MATCH(frameMbsOnlyFlag)
546                                 MATCH(refFrames)
547                                 if(!match)
548                                     ADM_warning("Codec parameters change on the fly, expect problems.\n");
549                             }
550                         }
551                     }
552                     uint32_t flags;
553                     if(extractH264FrameType(img.data,img.dataLength,nalSize,&flags,NULL,&info))
554                     {
555                         if(flags & AVI_FIELD_STRUCTURE)
556                         {
557                             if(!fields)
558                                 printf("First field at frame %u\n",i);
559                             fields++;
560                         }else if(fields==1)
561                         { // discard a single field immediately followed by a frame, probably damaged stream
562                             printf("Resetting fields counter at frame %u\n",i);
563                             fields=0;
564                         }
565                         setFlag(i,flags);
566                     }
567                 }
568                 if(work) delete work;
569                 work=NULL;
570                 delete [] bfer;
571                 bfer=NULL;
572                 if(curSps) delete [] curSps;
573                 curSps=NULL;
574                 if(prevSps) delete [] prevSps;
575                 prevSps=NULL;
576                 if(fields)
577                     ADM_info("Field encoded H.264 stream detected, # fields: %u\n",fields);
578                 else
579                     ADM_info("Probably a frame encoded H.264 stream.\n");
580             }
581         }
582         /*
583          * Veryfy DTS<=PTS
584          */
585         int nb=(int)_tracks[0].nbIndex;
586         uint64_t delta,maxDelta=0;
587         for(int i=0;i<nb;i++)
588         {
589             uint64_t pts,dts;
590             dts=VDEO.index[i].dts;
591             pts=VDEO.index[i].pts;
592             if(pts==ADM_COMPRESSED_NO_PTS || dts==ADM_COMPRESSED_NO_PTS) continue;
593             if(dts>=pts)
594             {
595                 uint64_t delta=(uint64_t)(dts-pts);
596                 if(delta>maxDelta) maxDelta=delta;
597             }
598         }
599         if(maxDelta)
600         {
601             shiftTimeBy(maxDelta);
602              _movieDuration+=(maxDelta+999)/1000;
603         }
604         /*
605                 Now build audio tracks
606         */
607         if(nbAudioTrack) _isaudiopresent=1; // Still needed ?
608 
609         adjustElstDelay();
610 
611         //
612         for(int audio=0;audio<nbAudioTrack;audio++)
613         {
614             switch(_tracks[1+audio]._rdWav.encoding)
615             {
616 
617             // Lookup if AAC is lying about # of channels
618             case WAV_AAC:
619                 {
620                     if(_tracks[1+audio].extraDataSize==2)
621                     {
622                         // Channels
623                         uint32_t word=(_tracks[1+audio].extraData[0]<<8)+_tracks[1+audio].extraData[1];
624                         uint32_t chan=(word>>3)&0xf;
625                         uint32_t fqIndex=(word>>7)&0xf;
626                         printf("0x%x word, Channel : %d, fqIndex=%d\n",word,chan,fqIndex);
627                     }
628                 }
629                 break;
630             case WAV_AC3: // same for ac3
631             {
632                  // read First chunk
633 
634                 MP4Index *dex=_tracks[1+audio].index;
635                 int size=dex[0].size;
636                 uint8_t *buffer=new uint8_t[size];
637                   fseeko(_fd,dex[0].offset,SEEK_SET);
638                   if(fread(buffer,1,size,_fd))
639                   {
640                       uint32_t fq,  br,  chan, syncoff;
641                       if(ADM_AC3GetInfo(buffer,size, &fq, &br, &chan,&syncoff))
642                       {
643                           ADM_info("Updating AC3 info : Fq=%d, br=%d, chan=%d\n",fq,br,chan);
644                           _tracks[1+audio]._rdWav.channels=chan;
645                           _tracks[1+audio]._rdWav.byterate=br;
646                       }
647                   }
648                   delete [] buffer;
649                   break;
650             }
651             case WAV_MP3: // same for mp3
652             {
653                 MP4Index *dex=_tracks[1+audio].index;
654                 int size=dex[0].size;
655                 uint8_t *buffer=new uint8_t[size];
656                 fseeko(_fd,dex[0].offset,SEEK_SET);
657                 if(fread(buffer,1,size,_fd))
658                 {
659                     uint32_t off;
660                     MpegAudioInfo mpeg;
661                     if(getMpegFrameInfo(buffer, size, &mpeg, NULL, &off) && size >= off+mpeg.size)
662                     {
663                         if(mpeg.mode == 3 && _tracks[1+audio]._rdWav.channels!=1)
664                         {
665                             uint32_t fq=mpeg.samplerate;
666                             uint32_t br=(mpeg.bitrate*1000)>>3; //
667                             ADM_info("Updating MP3 info : Fq=%u, br=%u, chan=%u\n",fq,br,1);
668                             _tracks[1+audio]._rdWav.channels=1;
669                             _tracks[1+audio]._rdWav.frequency=fq;
670                             _tracks[1+audio]._rdWav.byterate=br;
671                         }
672                     }else
673                     {
674                         ADM_warning("Cannot get MP3 info from the first sample.\n");
675                     }
676                 }
677                 delete [] buffer;
678                 break;
679             }
680             case WAV_OGG_VORBIS:
681             {
682                 ADM_info("[MP4] Reformatting vorbis header for track %u\n",1+audio);
683                 uint8_t *newExtra=NULL;
684                 int newExtraSize=0;
685                 if(false==ADMXiph::xiphExtraData2Adm(_tracks[1+audio].extraData, _tracks[1+audio].extraDataSize, &newExtra, &newExtraSize))
686                 {
687                     ADM_warning("Cannot reformat vorbis extra data, faking audio format to avoid crash.\n");
688                     _tracks[1+audio]._rdWav.encoding=WAV_UNKNOWN;
689                 }
690                 // Destroy old extradata
691                 delete [] _tracks[1+audio].extraData;
692                 _tracks[1+audio].extraData=newExtra;
693                 _tracks[1+audio].extraDataSize=newExtraSize;
694             }
695                 break;
696             default:
697                 break;
698             }
699             audioAccess[audio]=new ADM_mp4AudioAccess(name,&(_tracks[1+audio]));
700             audioStream[audio]=ADM_audioCreateStream(&(_tracks[1+audio]._rdWav), audioAccess[audio]);
701         }
702         fseeko(_fd,0,SEEK_SET);
703         uint64_t duration1=_movieDuration*1000LL;
704         uint64_t duration2=0;
705         uint32_t lastFrame=0;
706         for(int i=nb-32;i<nb;i++)
707         {
708             if(i<0) continue;
709             if(_tracks[0].index[i].pts==ADM_NO_PTS) continue;
710             if(duration2<_tracks[0].index[i].pts)
711             {
712                 duration2=_tracks[0].index[i].pts;
713                 lastFrame=i;
714             }
715         }
716         int64_t increment=_mainaviheader.dwMicroSecPerFrame;
717         if(!increment) // perfectly regular stream
718         {
719             ADM_assert(_videostream.dwRate);
720             double f=_videostream.dwScale;
721             f*=1000.*1000.;
722             f/=_videostream.dwRate;
723             f+=0.49;
724             increment=(int64_t)f;
725         }
726         duration2+=increment;
727         ADM_info("3gp/mov file successfully read..\n");
728         if(duration2!=ADM_NO_PTS && duration2>=duration1)
729         { // video duration must be > max PTS, otherwise we drop the last frame
730             ADM_warning("Last PTS is at or after movie duration, increasing movie duration\n");
731             _movieDuration=(duration2+499)/1000;
732 #ifdef DERIVE_TB_FROM_MINIMUM_DELTA
733             // adjust calculated average FPS and time increment
734             double f=_movieDuration;
735             f=1000.*_tracks[0].nbIndex/f;
736             f*=1000.;
737             _videostream.dwRate=(uint32_t)floor(f+0.49);
738             _mainaviheader.dwMicroSecPerFrame=ADM_UsecFromFps1000(_videostream.dwRate);
739             ADM_info("Adjusted fps1000: %d = %" PRIu64" us per frame.\n",_videostream.dwRate,_mainaviheader.dwMicroSecPerFrame);
740 #endif
741         }
742 #ifdef DERIVE_TB_FROM_MINIMUM_DELTA
743         refineFps();
744 #endif
745         if(nb>1 && !lastFrame)
746             lastFrame=nb-1;
747         ADM_info("Nb images       : %d\n",nb);
748         ADM_info("Movie duration  : %s\n",ADM_us2plain(_movieDuration*1000LL));
749         ADM_info("Last video PTS  : %s\n",ADM_us2plain(_tracks[0].index[lastFrame].pts));
750         ADM_info("Last video DTS  : %s\n",ADM_us2plain(_tracks[0].index[nb-1].dts));
751 
752         checkDuplicatedPts();
753 
754         return 1;
755 }
checkDuplicatedPts(void)756 bool MP4Header::checkDuplicatedPts(void)
757 {
758         int nb=(int)_tracks[0].nbIndex;
759         for(int i=0;i<nb;i++)
760         {
761             int mn,mx;
762             mn=i-10;
763             if(mn<0) mn=0;
764             mx=i+10;
765             if(mx>=nb-1) mx=nb-1;
766             for(int j=mn;j<mx;j++)
767             {
768                 if(j==i) continue;
769                 if(_tracks[0].index[i].pts==_tracks[0].index[j].pts)
770                 {
771                     ADM_warning("Duplicate pts %s at %d and %d\n",ADM_us2plain(_tracks[0].index[i].pts),i,j);
772                     _tracks[0].index[j].pts+=1000; // add 1 ms
773                 }
774             }
775 
776         }
777         return true;
778 }
779 /**
780  * \fn adjustElstDelay
781  * @return
782  */
adjustElstDelay(void)783 bool MP4Header::adjustElstDelay(void)
784 {
785     int xmin=10000000;
786     int xscaledDelay[_3GP_MAX_TRACKS];
787     for(int i=0;i<1+nbAudioTrack;i++)
788     {
789         double scaledDelay=_tracks[i].delay;
790         double scaledStartOffset=_tracks[i].startOffset;
791         scaledDelay/=_movieScale;
792         scaledStartOffset/=_tracks[i].scale;
793         scaledDelay*=1000000;
794         scaledStartOffset*=1000000;
795         ADM_info("Delay for track %d : raw = %d, scaled  = %d with scale = %d\n",i,_tracks[i].delay,(int)scaledDelay,_movieScale);
796         ADM_info("Start offset for track %d : raw = %d, scaled = %d with scale = %d\n",i,_tracks[i].startOffset,(int)scaledStartOffset,_tracks[i].scale);
797         scaledDelay-=scaledStartOffset;
798         xscaledDelay[i]=scaledDelay;
799         if(scaledDelay<xmin)
800             xmin=scaledDelay;
801     }
802     ADM_info("Elst minimum = %d us\n",xmin);
803     for(int i=0;i<1+nbAudioTrack;i++)
804     {
805         int d=xscaledDelay[i]-xmin;
806         if(d)
807         {
808             ADM_info("    Shifting track %d by %s\n",i,ADM_us2plain(d));
809             shiftTrackByTime(i,d);
810         }
811     }
812     return true;
813 }
814 
815 
816 
817 /**
818  * \fn shiftTimeBy
819  * \brief increase pts by shift, fix some mp4 where dts is too low
820  * @param shift
821  * @return
822  */
shiftTimeBy(uint64_t shift)823 bool MP4Header::shiftTimeBy(uint64_t shift)
824 {
825 
826         ADM_warning("MP4, Must increase pts by %d us\n",(int)shift);
827         int nb=(int)_tracks[0].nbIndex;
828         for(int i=0;i<nb;i++)
829         {
830            uint64_t pts;
831             pts=VDEO.index[i].pts;
832             if(pts==ADM_COMPRESSED_NO_PTS) continue;
833             pts+=shift;
834             VDEO.index[i].pts=pts;
835         }
836         for(int i=1;i<nbAudioTrack;i++)
837             shiftTrackByTime(i,shift);
838         return true;
839 }
840 /**
841  *
842  * @param dex
843  * @param shift
844  * @return
845  */
shiftTrackByTime(int dex,uint64_t shift)846 bool MP4Header::shiftTrackByTime(int dex,uint64_t shift)
847 {
848     int nb=(int)_tracks[dex].nbIndex;
849     MP4Index *myIndex=_tracks[dex].index;
850     for(int i=0;i<nb;i++)
851     {
852              uint64_t dts,pts;
853                 dts=myIndex[i].dts;
854                 pts=myIndex[i].pts;
855                 if(dts!=ADM_COMPRESSED_NO_PTS)
856                 {
857                     dts+=shift;
858                 }
859                 if(pts!=ADM_COMPRESSED_NO_PTS)
860                 {
861                     pts+=shift;
862                 }
863                 myIndex[i].dts=dts;
864                 myIndex[i].pts=pts;
865      }
866 
867     return true;
868 }
869 
870 //
871 //	That tag are coded like this
872 //	Each 8 bits is in fact a 7 Bits part while b7=1
873 // 	So we concanate them while possible
readPackedLen(adm_atom * tom)874 uint32_t MP4Header::readPackedLen(adm_atom *tom )
875 {
876 	uint32_t len=0;
877 	uint8_t	 b=0;
878 
879 	do
880 	{
881 	b=tom->read();
882 	len=len<<7;
883 	len+=b&0x7f;
884 	}while(b&0x80);
885 	return len;
886 }
887 
getFrameSize(uint32_t frame,uint32_t * size)888 uint8_t MP4Header::getFrameSize (uint32_t frame, uint32_t * size){
889   if(frame >= _videostream.dwLength) return 0;
890   *size = VDEO.index[frame].size;
891   return 1;
892 }
changeAudioStream(uint32_t newstream)893   uint8_t   MP4Header::changeAudioStream(uint32_t newstream)
894 {
895         if(newstream>nbAudioTrack) return 0;
896         _currentAudioTrack=newstream;
897         return 1;
898 }
getCurrentAudioStreamNumber(void)899 uint32_t     MP4Header::getCurrentAudioStreamNumber(void)
900 {
901     return _currentAudioTrack;
902 }
903 
904 /**
905     \fn getPtsDts
906 */
getPtsDts(uint32_t frame,uint64_t * pts,uint64_t * dts)907 bool    MP4Header::getPtsDts(uint32_t frame,uint64_t *pts,uint64_t *dts)
908 {
909 
910     if(frame>=VDEO.nbIndex)
911     {
912       printf("[MP4] Frame %" PRIu32" exceeds # of frames %" PRIu32"\n",frame,VDEO.nbIndex);
913       return false;
914     }
915 
916     MP4Index *idx=&(VDEO.index[frame]);
917 
918     *dts=idx->dts; // FIXME
919     *pts=idx->pts;
920     return true;
921 }
922 /**
923         \fn setPtsDts
924 */
setPtsDts(uint32_t frame,uint64_t pts,uint64_t dts)925 bool    MP4Header::setPtsDts(uint32_t frame,uint64_t pts,uint64_t dts)
926 {
927     if(frame>=VDEO.nbIndex)
928     {
929       printf("[MP4] Frame %" PRIu32" exceeds # of frames %" PRIu32"\n",frame,VDEO.nbIndex);
930       return 0;
931     }
932 
933     MP4Index *idx=&(VDEO.index[frame]);
934 
935     idx->dts=dts; // FIXME
936     idx->pts=pts;
937     return true;
938 }
939 /**
940  * \fn unreliableBFramePts
941  * \brief with mp4+h264, bframe PTS are unreliable
942  * @return
943  */
unreliableBFramePts(void)944 bool         MP4Header::unreliableBFramePts (void)
945 {
946     if(isH264Compatible(_videostream.fccHandler))
947         return true;
948     return false;
949 }
950 //EOF
951