diff --git a/avidemux_plugins/ADM_demuxers/Mp4/ADM_mp4.cpp b/avidemux_plugins/ADM_demuxers/Mp4/ADM_mp4.cpp index 3588b93757..bc289ba2e6 100644 --- a/avidemux_plugins/ADM_demuxers/Mp4/ADM_mp4.cpp +++ b/avidemux_plugins/ADM_demuxers/Mp4/ADM_mp4.cpp @@ -265,6 +265,7 @@ MP4Header::MP4Header(void) _currentAudioTrack=0; _reordered=0; _videoScale=1; + _defaultDurationEx=0; _videoFound=0; delayRelativeToVideo=0; _flavor=Mp4Regular; @@ -333,7 +334,7 @@ uint8_t MP4Header::getExtraHeaderData(uint32_t *len, uint8_t **data) //______________________________________ uint8_t MP4Header::open(const char *name) { - printf("** opening 3gpp files **"); + printf("** opening 3gpp files **\n"); _fd=ADM_fopen(name,"rb"); if(!_fd) { diff --git a/avidemux_plugins/ADM_demuxers/Mp4/ADM_mp4.h b/avidemux_plugins/ADM_demuxers/Mp4/ADM_mp4.h index 8ada7e7f91..1c452642d3 100644 --- a/avidemux_plugins/ADM_demuxers/Mp4/ADM_mp4.h +++ b/avidemux_plugins/ADM_demuxers/Mp4/ADM_mp4.h @@ -186,6 +186,7 @@ class MP4Header :public vidHeader uint64_t delayRelativeToVideo; uint8_t lookupMainAtoms(void *tom); void parseMvhd(void *tom); + uint8_t parseTrex(void *ztom); uint8_t parseTrack(void *ztom); uint8_t parseElst(void *tom,int64_t *delay,int64_t *skip); bool parseMoof(adm_atom &son); @@ -204,6 +205,7 @@ class MP4Header :public vidHeader bool adjustElstDelay(void); uint32_t _videoScale; uint32_t _movieScale; + uint32_t _defaultDurationEx; // dts increment in ticks _videoScale int64_t _movieDuration; // in ms uint32_t _videoFound; bool processAudio( MP4Track *track, uint32_t trackScale, diff --git a/avidemux_plugins/ADM_demuxers/Mp4/ADM_mp4Analyzer.cpp b/avidemux_plugins/ADM_demuxers/Mp4/ADM_mp4Analyzer.cpp index 999440a9a1..2c40c8ec04 100644 --- a/avidemux_plugins/ADM_demuxers/Mp4/ADM_mp4Analyzer.cpp +++ b/avidemux_plugins/ADM_demuxers/Mp4/ADM_mp4Analyzer.cpp @@ -118,6 +118,12 @@ uint8_t MP4Header::lookupMainAtoms(void *ztom) switch(id) { case ADM_MP4_MVHD: parseMvhd(&son);break; + case ADM_MP4_MVEX: + { + ADM_info("Found mvex at position %u of size %u\n",son.getStartPos(),son.getRemainingSize()); + parseTrex(&son); + } + break; case ADM_MP4_TRACK: if(!parseTrack(&son)) { @@ -199,8 +205,45 @@ void MP4Header::parseMvhd(void *ztom) } /** - \fn parseMvhd - \brief Parse mvhd header + \fn parseTrex + \brief Some iso5 files specify dts increment via trex box only. We ignore other trex data for now. +*/ +uint8_t MP4Header::parseTrex(void *ztom) +{ + if(_defaultDurationEx) + { + ADM_warning("Multiple trex boxes not handled!\n"); + return 0; + } + adm_atom *tom=(adm_atom *)ztom; + ADMAtoms id; + uint32_t container; + uint32_t trackId=0; + while(!tom->isDone()) + { + adm_atom son(tom); + if(!ADM_mp4SearchAtomName(son.getFCC(),&id,&container)) + { + aprintf("[parseTrex] Unknown atom %s\n",fourCC::tostringBE(son.getFCC())); + son.skipAtom(); + continue; + } + if(id!=ADM_MP4_TREX) continue; + ADM_info("Found trex, assuming it is for the video track, reading it.\n"); + son.skipBytes(4); // version and flags + trackId=son.read32(); + son.skipBytes(4); // stsd id + _defaultDurationEx=tom->read32(); + ADM_info("Default duration from trex for track id %u: %u\n",trackId,_defaultDurationEx); + son.skipAtom(); + return 1; + } + ADM_info("trex box not found.\n"); + return 0; +} +/** + \fn parseTrack + \brief Parse track header */ uint8_t MP4Header::parseTrack(void *ztom) { @@ -922,7 +965,12 @@ uint8_t MP4Header::parseStbl(void *ztom,uint32_t trackType,uint32_t trackScale) mixDump(VDEO.extraData+offset,len); // Verify width and height, the values from the container may be wrong. ADM_SPSInfo sps; - if(extractSPSInfo(VDEO.extraData,VDEO.extraDataSize,&sps) && sps.width && sps.height) + if(false==extractSPSInfo(VDEO.extraData,VDEO.extraDataSize,&sps)) + { + ADM_warning("Could not decode H.264 extradata.\n"); + break; + } + if(sps.width && sps.height) { if(lw && lw!=sps.width) ADM_warning("Width mismatch, container says %u, codec %u, trusting codec\n",lw,sps.width); @@ -931,7 +979,24 @@ uint8_t MP4Header::parseStbl(void *ztom,uint32_t trackType,uint32_t trackScale) ADM_warning("Height mismatch, container says %u, codec %u, trusting codec\n",lh,sps.height); _video_bih.biHeight=_mainaviheader.dwHeight=sps.height; }else - ADM_warning("Could not decode H.264 extradata to verify video width and height.\n"); + ADM_warning("Got invalid dimensions from SPS, cannot verify video width and height.\n"); + // Prefill time base from fps1000 value we got from SPS, we handle only standard cases here. + switch(sps.fps1000) + { + case 23976: + _videostream.dwScale=1001; + _videostream.dwRate=24000; + break; + case 29970: + _videostream.dwScale=1001; + _videostream.dwRate=30000; + break; + case 24000: case 25000: case 30000: case 50000: case 60000: + _videostream.dwScale=1000; + _videostream.dwRate=sps.fps1000; + break; + default:break; + } break; } // while son.skipAtom(); diff --git a/avidemux_plugins/ADM_demuxers/Mp4/ADM_mp4Fragments.cpp b/avidemux_plugins/ADM_demuxers/Mp4/ADM_mp4Fragments.cpp index 2dd152ec4f..250b1c52b4 100644 --- a/avidemux_plugins/ADM_demuxers/Mp4/ADM_mp4Fragments.cpp +++ b/avidemux_plugins/ADM_demuxers/Mp4/ADM_mp4Fragments.cpp @@ -121,6 +121,8 @@ bool MP4Header::parseTraf(adm_atom &tom,uint64_t moofStart) TRAF_INFO(0x20,defaultFlags,32); if(trafFlags&0x10000) {aprintf("Empty duration\n");info.emptyDuration=true;} + if(!info.emptyDuration && !info.defaultDuration && _defaultDurationEx) + info.defaultDuration=_defaultDurationEx; // from trex if(trafFlags&0x20000) { diff --git a/avidemux_plugins/ADM_demuxers/Mp4/ADM_mp4Leaf.h b/avidemux_plugins/ADM_demuxers/Mp4/ADM_mp4Leaf.h index 58e86926ac..2b83642c2a 100644 --- a/avidemux_plugins/ADM_demuxers/Mp4/ADM_mp4Leaf.h +++ b/avidemux_plugins/ADM_demuxers/Mp4/ADM_mp4Leaf.h @@ -18,6 +18,7 @@ /* Container atom */ MKMP4LEAF('moov',MOOV,1), MKMP4LEAF('moof',MOOF,1), +MKMP4LEAF('mvex',MVEX,1), MKMP4LEAF('trak',TRACK,1), MKMP4LEAF('mdia',MDIA,1), MKMP4LEAF('minf',MINF,1), @@ -31,6 +32,7 @@ MKMP4LEAF('trun',TRUN,0), MKMP4LEAF('mfhd',MFHD,0), MKMP4LEAF('mvhd',MVHD,0), MKMP4LEAF('tkhd',TKHD,0), +MKMP4LEAF('trex',TREX,0), MKMP4LEAF('mdhd',MDHD,0), MKMP4LEAF('hdlr',HDLR,0),