summaryrefslogtreecommitdiff
path: root/libavformat
diff options
context:
space:
mode:
authorTomas Härdin <tomas.hardin@codemill.se>2011-12-15 16:47:49 +0100
committerTomas Härdin <tomas.hardin@codemill.se>2011-12-16 11:32:52 +0100
commit8ce41721a4a29711211f8dad0c86502caf86f4d3 (patch)
tree5ee4ea45d2eeef9bd7e62cba8b7ef71c95eaeb11 /libavformat
parent31029e30fa99d3d44403901850a00ce8e69b42dd (diff)
mxfdec: Add MXFIndexTables
This structs collects MXFIndexTableSegments belonging to one IndexSID and some other bits of useful information.
Diffstat (limited to 'libavformat')
-rw-r--r--libavformat/mxfdec.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c
index 8447da5d2b..88eb4c4927 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;
}