Quoting Martin Storsjö (2014-11-04 15:38:11)
> 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.
> ---
> libavformat/movenc.c | 33 ++++++++++++++++++++++++++++++++-
> libavformat/movenc.h | 2 ++
> 2 files changed, 34 insertions(+), 1 deletion(-)
>
> diff --git a/libavformat/movenc.c b/libavformat/movenc.c
> index 80a44cf..7d37b15 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 e905627..8349a18 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)
> --
> 1.9.3 (Apple Git-50)
>
Don't know much about mov, but looks sane enough from what I can tell.
Perhaps Yusuke has an opinion. Otherwise feel free to push.
--
Anton Khirnov
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel