From 1d8a0c1b43e58332a3a15c67d4adc161713cade8 Mon Sep 17 00:00:00 2001 From: Martin Storsjö Date: Tue, 4 Nov 2014 16:28:48 +0200 Subject: movenc: Allow to request not to use edit lists MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In this case, shift tracks to start from zero instead (potentially stretching the first sample in tracks that start later than the first one). Some software does not support edit lists at all, the adobe flash player seems to be one of these. This results in AV sync errors when edit lists are used to adjust AV sync. Some players, such as QuickTime, don't respect the duration for audio packets, so if an audio track starts later than the video track and the first audio sample gets a duration longer than the actual amount of data in it, the result will be out of sync. Based on patches by Michael Niedermayer. Signed-off-by: Martin Storsjö --- libavformat/movenc.c | 33 ++++++++++++++++++++++++++++++++- libavformat/movenc.h | 2 ++ 2 files changed, 34 insertions(+), 1 deletion(-) (limited to 'libavformat') diff --git a/libavformat/movenc.c b/libavformat/movenc.c index c6c683fe33..7a0d9f1150 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -68,6 +68,7 @@ static const AVOption options[] = { { "frag_size", "Maximum fragment size", offsetof(MOVMuxContext, max_fragment_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM}, { "ism_lookahead", "Number of lookahead entries for ISM files", offsetof(MOVMuxContext, ism_lookahead), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM}, { "brand", "Override major brand", offsetof(MOVMuxContext, major_brand), AV_OPT_TYPE_STRING, {.str = NULL}, .flags = AV_OPT_FLAG_ENCODING_PARAM }, + { "use_editlist", "use edit list", offsetof(MOVMuxContext, use_editlist), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM}, { NULL }, }; @@ -1773,7 +1774,11 @@ static int mov_write_trak_tag(AVIOContext *pb, MOVMuxContext *mov, if (track->mode == MODE_PSP || track->flags & MOV_TRACK_CTTS || (track->entry && track->cluster[0].dts) || is_clcp_track(track)) { - mov_write_edts_tag(pb, mov, track); // PSP Movies require edts box + if (mov->use_editlist) + mov_write_edts_tag(pb, mov, track); // PSP Movies require edts box + else if ((track->entry && track->cluster[0].dts) || track->mode == MODE_PSP || is_clcp_track(track)) + av_log(mov->fc, AV_LOG_WARNING, + "Not writing any edit list even though one would have been required\n"); } if (track->tref_tag) mov_write_tref_tag(pb, track); @@ -3148,6 +3153,15 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) * of this packet to be what the previous packets duration implies. */ trk->cluster[trk->entry].dts = trk->start_dts + trk->track_duration; } + if (!trk->entry && trk->start_dts == AV_NOPTS_VALUE && !mov->use_editlist && + s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO) { + /* Not using edit lists and shifting the first track to start from zero. + * If the other streams start from a later timestamp, we won't be able + * to signal the difference in starting time without an edit list. + * Thus move the timestamp for this first sample to 0, increasing + * its duration instead. */ + trk->cluster[trk->entry].dts = trk->start_dts = 0; + } if (trk->start_dts == AV_NOPTS_VALUE) { trk->start_dts = pkt->dts; if (pkt->dts && mov->flags & FF_MOV_FLAG_EMPTY_MOOV) @@ -3462,6 +3476,23 @@ static int mov_write_header(AVFormatContext *s) } } + if (mov->use_editlist < 0) { + mov->use_editlist = 1; + if (mov->flags & FF_MOV_FLAG_FRAGMENT) { + // If we can avoid needing an edit list by shifting the + // tracks, prefer that over (trying to) write edit lists + // in fragmented output. + if (s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO || + s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO) + mov->use_editlist = 0; + } + } + if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV && mov->use_editlist) + av_log(s, AV_LOG_WARNING, "No meaningful edit list will be written when using empty_moov\n"); + + if (!mov->use_editlist && s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO) + s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_ZERO; + /* Non-seekable output is ok if using fragmentation. If ism_lookahead * is enabled, we don't support non-seekable output at all. */ if (!s->pb->seekable && diff --git a/libavformat/movenc.h b/libavformat/movenc.h index e9056275ef..8349a18c1d 100644 --- a/libavformat/movenc.h +++ b/libavformat/movenc.h @@ -166,6 +166,8 @@ typedef struct MOVMuxContext { int per_stream_grouping; AVFormatContext *fc; + + int use_editlist; } MOVMuxContext; #define FF_MOV_FLAG_RTP_HINT (1 << 0) -- cgit v1.2.3