[FFmpeg-devel] [PATCH 1/5] avformat/mov: export edit list as stream side data

Clément Bœsch u at pkh.me
Tue Jan 6 18:09:57 CET 2015


From: Clément Bœsch <clement at 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



More information about the ffmpeg-devel mailing list