[FFmpeg-devel] [PATCH 5/5] movenc: add max_av_duration and max_trackID to MOVMuxContext

Jean First jeanfirst at gmail.com
Sat Jan 14 14:10:21 CET 2012


movenc: add max_av_duration and max_trackID to MOVMuxContext

this patch adds max_av_duration and max_trackID to the MOVMuxContext and
moves the code fetching these values to a central place.

until now maxTrackLen was only used in mov_write_mvhd_tag. The maxTrackLen
was the maximum track lenght from all streams. It is replaced with
max_av_duration will be the maximum length of all video and audio
tracks. Forthermore it will be used for all data tracks, because they
were set to some default value.

fate still passes with these changes.

Signed-off-by: Jean First <jeanfirst at gmail.com>
---
 libavformat/movenc.c |   79 +++++++++++++++++++++++++++++--------------------
 libavformat/movenc.h |    3 ++
 2 files changed, 50 insertions(+), 32 deletions(-)

diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index c304291..7698911 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -1185,7 +1185,7 @@ static int mov_write_minf_tag(AVIOContext *pb, MOVTrack *track)
     else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
         mov_write_smhd_tag(pb);
     else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE) {
-        if (track->tag == MKTAG('t','e','x','t')) mov_write_gmhd_tag(pb);
+        if (track->tag == MKTAG('t','e','x','t')) mov_write_gmhd_tag(pb, track);
         else                                      mov_write_nmhd_tag(pb);
     } else if (track->tag == MKTAG('r','t','p',' ')) {
         mov_write_hmhd_tag(pb);
@@ -1238,10 +1238,18 @@ static int mov_write_mdia_tag(AVIOContext *pb, MOVTrack *track)
     return updateSize(pb, pos);
 }
 
-static int mov_write_tkhd_tag(AVIOContext *pb, MOVTrack *track, AVStream *st)
+static int mov_write_tkhd_tag(AVIOContext *pb, MOVMuxContext *mov, int i, AVStream *st)
 {
-    int64_t duration = av_rescale_rnd(track->trackDuration, MOV_TIMESCALE,
-                                      track->timescale, AV_ROUND_UP);
+    int64_t duration;
+    MOVTrack *track = &(mov->tracks[i]);
+
+    if(track->enc->codec_type == AVMEDIA_TYPE_DATA && mov->max_av_duration){
+        duration = mov->max_av_duration;
+    } else {
+        duration = av_rescale_rnd(track->trackDuration, MOV_TIMESCALE,
+                                  track->timescale, AV_ROUND_UP);
+    }
+
     int version = duration < INT32_MAX ? 0 : 1;
 
     (version == 1) ? avio_wb32(pb, 104) : avio_wb32(pb, 92); /* size */
@@ -1328,10 +1336,18 @@ static int mov_write_tapt_tag(AVIOContext *pb, MOVTrack *track)
 }
 
 // This box seems important for the psp playback ... without it the movie seems to hang
-static int mov_write_edts_tag(AVIOContext *pb, MOVTrack *track)
+static int mov_write_edts_tag(AVIOContext *pb, MOVMuxContext *mov, int i)
 {
-    int64_t duration = av_rescale_rnd(track->trackDuration, MOV_TIMESCALE,
-                                      track->timescale, AV_ROUND_UP);
+    int64_t duration;
+    MOVTrack *track = &(mov->tracks[i]);
+
+    if(track->enc->codec_type == AVMEDIA_TYPE_DATA && mov->max_av_duration){
+        duration = mov->max_av_duration;
+    } else {
+        duration = av_rescale_rnd(track->trackDuration, MOV_TIMESCALE,
+                                  track->timescale, AV_ROUND_UP);
+    }
+
     int version = duration < INT32_MAX ? 0 : 1;
     int entry_size, entry_count, size;
     int64_t delay, start_ct = track->cluster[0].cts;
@@ -1423,14 +1439,15 @@ static int mov_write_udta_sdp(AVIOContext *pb, AVFormatContext *ctx, int index)
     return len + 24;
 }
 
-static int mov_write_trak_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track, AVStream *st)
+static int mov_write_trak_tag(AVIOContext *pb, MOVMuxContext *mov, int i, AVStream *st)
 {
     int64_t pos = avio_tell(pb);
+    MOVTrack *track = &(mov->tracks[i]);
     avio_wb32(pb, 0); /* size */
     ffio_wfourcc(pb, "trak");
-    mov_write_tkhd_tag(pb, track, st);
+    mov_write_tkhd_tag(pb, mov, i, st);
     if(!mov->fragments) // EDTS with fragments is tricky as we dont know the duration when its written
-        mov_write_edts_tag(pb, track);  // PSP Movies and several other cases require edts box
+        mov_write_edts_tag(pb, mov, i);  // PSP Movies and several other cases require edts box
     if (track->tref_tag)
         mov_write_tref_tag(pb, track);
     mov_write_mdia_tag(pb, track);
@@ -1543,24 +1560,7 @@ static int mov_write_iods_tag(AVIOContext *pb, MOVMuxContext *mov)
 
 static int mov_write_mvhd_tag(AVIOContext *pb, MOVMuxContext *mov)
 {
-    int maxTrackID = 1, i;
-    int64_t maxTrackLenTemp, maxTrackLen = 0;
-    int version;
-
-    for (i=0; i<mov->nb_streams; i++) {
-        if(mov->tracks[i].entry > 0) {
-            maxTrackLenTemp = av_rescale_rnd(mov->tracks[i].trackDuration,
-                                             MOV_TIMESCALE,
-                                             mov->tracks[i].timescale,
-                                             AV_ROUND_UP);
-            if(maxTrackLen < maxTrackLenTemp)
-                maxTrackLen = maxTrackLenTemp;
-            if(maxTrackID < mov->tracks[i].trackID)
-                maxTrackID = mov->tracks[i].trackID;
-        }
-    }
-
-    version = maxTrackLen < UINT32_MAX ? 0 : 1;
+    int version = mov->max_av_duration < UINT32_MAX ? 0 : 1;
     (version == 1) ? avio_wb32(pb, 120) : avio_wb32(pb, 108); /* size */
     ffio_wfourcc(pb, "mvhd");
     avio_w8(pb, version);
@@ -1573,7 +1573,8 @@ static int mov_write_mvhd_tag(AVIOContext *pb, MOVMuxContext *mov)
         avio_wb32(pb, mov->time); /* modification time */
     }
     avio_wb32(pb, MOV_TIMESCALE);
-    (version == 1) ? avio_wb64(pb, maxTrackLen) : avio_wb32(pb, maxTrackLen); /* duration of longest track */
+    (version == 1) ? avio_wb64(pb, mov->max_av_duration) :
+                     avio_wb32(pb, mov->max_av_duration); /* duration of longest track */
 
     avio_wb32(pb, 0x00010000); /* reserved (preferred rate) 1.0 = normal */
     avio_wb16(pb, 0x0100); /* reserved (preferred volume) 1.0 = normal */
@@ -1598,7 +1599,7 @@ static int mov_write_mvhd_tag(AVIOContext *pb, MOVMuxContext *mov)
     avio_wb32(pb, 0); /* reserved (selection time) */
     avio_wb32(pb, 0); /* reserved (selection duration) */
     avio_wb32(pb, 0); /* reserved (current time) */
-    avio_wb32(pb, maxTrackID+1); /* Next track id */
+    avio_wb32(pb, mov->max_trackID+1); /* Next track id */
     return 0x6c;
 }
 
@@ -1977,7 +1978,7 @@ static int mov_write_moov_tag(AVIOContext *pb, MOVMuxContext *mov,
                               AVFormatContext *s)
 {
     int i;
-    int64_t pos = avio_tell(pb);
+    int64_t pos = avio_tell(pb), temp_duration = 0;
     avio_wb32(pb, 0); /* size placeholder*/
     ffio_wfourcc(pb, "moov");
 
@@ -1986,8 +1987,22 @@ static int mov_write_moov_tag(AVIOContext *pb, MOVMuxContext *mov,
 
         mov->tracks[i].time = mov->time;
         mov->tracks[i].trackID = i+1;
+        mov->max_trackID       = i+1;
 
         build_chunks(&mov->tracks[i]);
+
+        /* data tracks should only be as long as the longest audio or video track */
+        if (mov->tracks[i].enc->codec_type == AVMEDIA_TYPE_VIDEO ||
+            mov->tracks[i].enc->codec_type == AVMEDIA_TYPE_AUDIO) {
+
+            temp_duration = av_rescale_rnd(mov->tracks[i].trackDuration,
+                                             MOV_TIMESCALE,
+                                             mov->tracks[i].timescale,
+                                             AV_ROUND_UP);
+            if (temp_duration > mov->max_av_duration){
+                mov->max_av_duration = temp_duration;
+            }
+        }
     }
 
     if (mov->chapter_track)
@@ -2008,7 +2023,7 @@ static int mov_write_moov_tag(AVIOContext *pb, MOVMuxContext *mov,
         mov_write_iods_tag(pb, mov);
     for (i=0; i<mov->nb_streams; i++) {
         if(mov->tracks[i].entry > 0) {
-            mov_write_trak_tag(pb, mov, &(mov->tracks[i]), i < s->nb_streams ? s->streams[i] : NULL);
+            mov_write_trak_tag(pb, mov, i, i < s->nb_streams ? s->streams[i] : NULL);
         }
     }
 
diff --git a/libavformat/movenc.h b/libavformat/movenc.h
index f6c95ad..496fc57 100644
--- a/libavformat/movenc.h
+++ b/libavformat/movenc.h
@@ -126,6 +126,9 @@ typedef struct MOVMuxContext {
     int max_fragment_duration;
     int max_fragment_size;
 
+    int64_t max_av_duration;
+    int     max_trackID;
+
     int iods_skip;
     int iods_video_profile;
     int iods_audio_profile;
-- 
1.7.8.3



More information about the ffmpeg-devel mailing list