[FFmpeg-cvslog] mxfdec: Add MXFIndexTables

Tomas Härdin git at videolan.org
Sun Dec 18 23:30:43 CET 2011


ffmpeg | branch: master | Tomas Härdin <tomas.hardin at codemill.se> | Thu Dec 15 16:47:49 2011 +0100| [8ce41721a4a29711211f8dad0c86502caf86f4d3] | committer: Tomas Härdin

mxfdec: Add MXFIndexTables

This structs collects MXFIndexTableSegments belonging to one IndexSID and some
other bits of useful information.

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=8ce41721a4a29711211f8dad0c86502caf86f4d3
---

 libavformat/mxfdec.c |   97 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 97 insertions(+), 0 deletions(-)

diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c
index 8447da5..88eb4c4 100644
--- a/libavformat/mxfdec.c
+++ b/libavformat/mxfdec.c
@@ -177,6 +177,17 @@ typedef struct {
     enum MXFMetadataSetType type;
 } MXFMetadataSet;
 
+/* decoded index table */
+typedef struct {
+    int index_sid;
+    int body_sid;
+    int nb_ptses;               /* number of PTSes or total duration of index */
+    int64_t first_dts;          /* DTS = EditUnit + first_dts */
+    int64_t *ptses;             /* maps EditUnit -> PTS */
+    int nb_segments;
+    MXFIndexTableSegment **segments;    /* sorted by IndexStartPosition */
+} MXFIndexTable;
+
 typedef struct {
     MXFPartition *partitions;
     unsigned partitions_count;
@@ -204,6 +215,8 @@ typedef struct {
     int64_t first_dts;          /* DTS = EditUnit + first_dts */
     int64_t *ptses;             /* maps EditUnit -> PTS */
     int nb_ptses;
+    int nb_index_tables;
+    MXFIndexTable *index_tables;
 } MXFContext;
 
 enum MXFWrappingScheme {
@@ -1211,6 +1224,72 @@ static int mxf_compute_ptses(MXFContext *mxf, MXFIndexTableSegment **sorted_segm
     return 0;
 }
 
+/**
+ * Sorts and collects index table segments into index tables.
+ * Also computes PTSes if possible.
+ */
+static int mxf_compute_index_tables(MXFContext *mxf)
+{
+    int i, j, ret, nb_sorted_segments;
+    MXFIndexTableSegment **sorted_segments = NULL;
+
+    if ((ret = mxf_get_sorted_table_segments(mxf, &nb_sorted_segments, &sorted_segments)) ||
+        nb_sorted_segments <= 0) {
+        av_log(mxf->fc, AV_LOG_WARNING, "broken or empty index\n");
+        return 0;
+    }
+
+    /* sanity check and count unique BodySIDs/IndexSIDs */
+    for (i = 0; i < nb_sorted_segments; i++) {
+        if (i == 0 || sorted_segments[i-1]->index_sid != sorted_segments[i]->index_sid)
+            mxf->nb_index_tables++;
+        else if (sorted_segments[i-1]->body_sid != sorted_segments[i]->body_sid) {
+            av_log(mxf->fc, AV_LOG_ERROR, "found inconsistent BodySID\n");
+            ret = AVERROR_INVALIDDATA;
+            goto finish_decoding_index;
+        }
+    }
+
+    if (!(mxf->index_tables = av_calloc(mxf->nb_index_tables, sizeof(MXFIndexTable)))) {
+        av_log(mxf->fc, AV_LOG_ERROR, "failed to allocate index tables\n");
+        ret = AVERROR(ENOMEM);
+        goto finish_decoding_index;
+    }
+
+    /* distribute sorted segments to index tables */
+    for (i = j = 0; i < nb_sorted_segments; i++) {
+        if (i != 0 && sorted_segments[i-1]->index_sid != sorted_segments[i]->index_sid) {
+            /* next IndexSID */
+            j++;
+        }
+
+        mxf->index_tables[j].nb_segments++;
+    }
+
+    for (i = j = 0; j < mxf->nb_index_tables; i += mxf->index_tables[j++].nb_segments) {
+        MXFIndexTable *t = &mxf->index_tables[j];
+
+        if (!(t->segments = av_calloc(t->nb_segments, sizeof(MXFIndexTableSegment*)))) {
+            av_log(mxf->fc, AV_LOG_ERROR, "failed to allocate IndexTableSegment pointer array\n");
+            ret = AVERROR(ENOMEM);
+            goto finish_decoding_index;
+        }
+
+        if (sorted_segments[i]->index_start_position)
+            av_log(mxf->fc, AV_LOG_WARNING, "IndexSID %i starts at EditUnit %"PRId64" - seeking may not work as expected\n",
+                   sorted_segments[i]->index_sid, sorted_segments[i]->index_start_position);
+
+        memcpy(t->segments, &sorted_segments[i], t->nb_segments * sizeof(MXFIndexTableSegment*));
+        t->index_sid = sorted_segments[i]->index_sid;
+        t->body_sid = sorted_segments[i]->body_sid;
+    }
+
+    ret = 0;
+finish_decoding_index:
+    av_free(sorted_segments);
+    return ret;
+}
+
 static int mxf_parse_structural_metadata(MXFContext *mxf)
 {
     MXFPackage *material_package = NULL;
@@ -1617,6 +1696,7 @@ static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap)
     MXFContext *mxf = s->priv_data;
     KLVPacket klv;
     int64_t essence_offset = 0;
+    int ret;
 
     mxf->last_forward_tell = INT64_MAX;
 
@@ -1712,6 +1792,18 @@ static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap)
 
     mxf_compute_essence_containers(mxf);
 
+    if ((ret = mxf_compute_index_tables(mxf)) < 0)
+        return ret;
+
+    if (mxf->nb_index_tables > 1) {
+        /* TODO: look up which IndexSID to use via EssenceContainerData */
+        av_log(mxf->fc, AV_LOG_INFO, "got %i index tables - only the first one (IndexSID %i) will be used\n",
+               mxf->nb_index_tables, mxf->index_tables[0].index_sid);
+    } else if (mxf->nb_index_tables == 0 && mxf->op == OPAtom) {
+        av_log(mxf->fc, AV_LOG_ERROR, "cannot demux OPAtom without an index\n");
+        return AVERROR_INVALIDDATA;
+    }
+
     return mxf_parse_structural_metadata(mxf);
 }
 
@@ -1871,6 +1963,11 @@ static int mxf_read_close(AVFormatContext *s)
     av_freep(&mxf->aesc);
     av_freep(&mxf->local_tags);
     av_freep(&mxf->ptses);
+
+    for (i = 0; i < mxf->nb_index_tables; i++)
+        av_freep(&mxf->index_tables[i].segments);
+    av_freep(&mxf->index_tables);
+
     return 0;
 }
 



More information about the ffmpeg-cvslog mailing list