From: Tomas Härdin <[email protected]>
This structs collects MXFIndexTableSegments belonging to one IndexSID and some
other bits of useful information.
---
libavformat/mxfdec.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 100 insertions(+), 0 deletions(-)
diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c
index c4e1336..bb0c8ec 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 {
@@ -1236,6 +1249,75 @@ 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_mallocz(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_mallocz(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;
@@ -1642,6 +1724,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;
@@ -1737,6 +1820,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);
}
@@ -1898,6 +1993,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;
}
--
1.7.8
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel