From: Clément Bœsch <clem...@stupeflix.com> Add a AV_PKT_DATA_MOV_TIMELINE stream side data which will be used by the MOV/MP4 demuxer when "ignore_editlist" option is set to "export" (or -1, not the default).
Note: exporting the timeline as side data inhibits current demuxer heuristics. TODO: bump micro --- libavcodec/avcodec.h | 7 +++++++ libavformat/dump.c | 3 +++ libavformat/mov.c | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 99467bb..0b761b4 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1094,6 +1094,13 @@ enum AVPacketSideDataType { * side data includes updated metadata which appeared in the stream. */ AV_PKT_DATA_METADATA_UPDATE, + + /** + * MOV/MP4 elst atom, with additionnal 4 bytes at the beginning containing + * the presentation time scale to be used as a unit for the values in the + * table. + */ + AV_PKT_DATA_MOV_TIMELINE, }; typedef struct AVPacketSideData { diff --git a/libavformat/dump.c b/libavformat/dump.c index 56b37ff..6436521 100644 --- a/libavformat/dump.c +++ b/libavformat/dump.c @@ -328,6 +328,9 @@ static void dump_sidedata(void *ctx, AVStream *st, const char *indent) av_log(ctx, AV_LOG_INFO, "stereo3d: "); dump_stereo3d(ctx, &sd); break; + case AV_PKT_DATA_MOV_TIMELINE: + av_log(ctx, AV_LOG_INFO, "mov edit list"); + break; default: av_log(ctx, AV_LOG_WARNING, "unknown side data type %d (%d bytes)", sd.type, sd.size); diff --git a/libavformat/mov.c b/libavformat/mov.c index 248faf7..27e0232 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -3209,14 +3209,54 @@ free_and_return: #endif } +static int export_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom) +{ + int n; + uint8_t *buf; + AVPacketSideData *sd, *tmp; + AVStream *st = c->fc->streams[c->fc->nb_streams-1]; + int64_t start = avio_tell(pb); + + buf = av_malloc(atom.size + 4); + if (!buf) + return AVERROR(ENOMEM); + + AV_WB32(buf, c->time_scale); + + n = avio_read(pb, buf + 4, atom.size); + if (n != atom.size) { + av_log(c->fc, AV_LOG_ERROR, "Unexpected read error in ELST\n"); + return AVERROR_INVALIDDATA; + } + + tmp = av_realloc_array(st->side_data, st->nb_side_data + 1, sizeof(*tmp)); + if (!tmp) { + av_freep(&buf); + return AVERROR(ENOMEM); + } + st->side_data = tmp; + st->nb_side_data++; + + sd = &st->side_data[st->nb_side_data - 1]; + sd->type = AV_PKT_DATA_MOV_TIMELINE; + sd->data = buf; + sd->size = atom.size + 4; + + return avio_seek(pb, start, SEEK_SET); +} + /* edit list atom */ static int mov_read_elst(MOVContext *c, AVIOContext *pb, MOVAtom atom) { MOVStreamContext *sc; int i, edit_count, version; - if (c->fc->nb_streams < 1 || c->ignore_editlist) + if (c->fc->nb_streams < 1 || c->ignore_editlist == 1) return 0; + + if (c->ignore_editlist == -1) + return export_elst(c, pb, atom); + sc = c->fc->streams[c->fc->nb_streams-1]->priv_data; version = avio_r8(pb); /* version */ @@ -4261,7 +4301,9 @@ static const AVOption mov_options[] = { OFFSET(use_absolute_path), FF_OPT_TYPE_INT, {.i64 = 0}, 0, 1, FLAGS}, {"ignore_editlist", "", OFFSET(ignore_editlist), FF_OPT_TYPE_INT, {.i64 = 0}, - 0, 1, FLAGS}, + -1, 1, FLAGS, "editlist_mode"}, + {"export", "ignore edit list and export is as side data", + 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, FLAGS, "editlist_mode" }, {"use_mfra_for", "use mfra for fragment timestamps", OFFSET(use_mfra_for), FF_OPT_TYPE_INT, {.i64 = FF_MOV_FLAG_MFRA_AUTO}, -- 2.2.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel