Skip to content

Commit

Permalink
[demuxers/Mp4] Support fragmented mp4 with default dts increment spec…
Browse files Browse the repository at this point in the history
…ified in trex box only, prefill time base for H.264 streams from SPS

It is assumed that only one trex box exists and the track id matches the video track.
  • Loading branch information
eumagga0x2a committed Mar 13, 2020
1 parent 8b8ec79 commit 3581d6a
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 5 deletions.
3 changes: 2 additions & 1 deletion avidemux_plugins/ADM_demuxers/Mp4/ADM_mp4.cpp
Expand Up @@ -265,6 +265,7 @@ MP4Header::MP4Header(void)
_currentAudioTrack=0;
_reordered=0;
_videoScale=1;
_defaultDurationEx=0;
_videoFound=0;
delayRelativeToVideo=0;
_flavor=Mp4Regular;
Expand Down Expand Up @@ -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)
{
Expand Down
2 changes: 2 additions & 0 deletions avidemux_plugins/ADM_demuxers/Mp4/ADM_mp4.h
Expand Up @@ -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);
Expand All @@ -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,
Expand Down
73 changes: 69 additions & 4 deletions avidemux_plugins/ADM_demuxers/Mp4/ADM_mp4Analyzer.cpp
Expand Up @@ -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))
{
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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);
Expand All @@ -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();
Expand Down
2 changes: 2 additions & 0 deletions avidemux_plugins/ADM_demuxers/Mp4/ADM_mp4Fragments.cpp
Expand Up @@ -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)
{

Expand Down
2 changes: 2 additions & 0 deletions avidemux_plugins/ADM_demuxers/Mp4/ADM_mp4Leaf.h
Expand Up @@ -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),
Expand All @@ -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),

Expand Down

0 comments on commit 3581d6a

Please sign in to comment.