summaryrefslogtreecommitdiff
path: root/libavformat
diff options
context:
space:
mode:
authorTomas Härdin <tomas.hardin@codemill.se>2011-12-09 16:46:38 +0100
committerMichael Niedermayer <michaelni@gmx.at>2011-12-12 18:34:37 +0100
commit1e14bfc117fbac5cd7940cc061c0a014668450b5 (patch)
tree0fc29ce68f8497bf7957d3fda700d3496ade94a6 /libavformat
parent89cc8c17dfc2e49d2507eb72bfba10baba372d7f (diff)
mxfdec: Add support for Avid indexes
These indexes duplicate every entry and have the total size of the essence container as the last entry. This patch also computes the size of the packets when unknown. Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavformat')
-rw-r--r--libavformat/mxfdec.c68
1 files changed, 56 insertions, 12 deletions
diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c
index 2b2eb98a0c..cfe1474061 100644
--- a/libavformat/mxfdec.c
+++ b/libavformat/mxfdec.c
@@ -1078,10 +1078,33 @@ static int mxf_absolute_bodysid_offset(MXFContext *mxf, int body_sid, int64_t of
return AVERROR_INVALIDDATA;
}
+/**
+ * Returns the length of the essence container with given BodySID, or zero if unknown
+ */
+static int64_t mxf_essence_container_length(MXFContext *mxf, int body_sid)
+{
+ int x;
+ int64_t ret = 0;
+
+ for (x = 0; x < mxf->partitions_count; x++) {
+ MXFPartition *p = &mxf->partitions[x];
+
+ if (p->body_sid != body_sid)
+ continue;
+
+ if (!p->essence_length)
+ return 0;
+
+ ret += p->essence_length;
+ }
+
+ return ret;
+}
+
static int mxf_parse_index(MXFContext *mxf, int track_id, AVStream *st)
{
int64_t accumulated_offset = 0;
- int j, k, ret, nb_sorted_segments;
+ int j, k, l, ret, nb_sorted_segments;
MXFIndexTableSegment **sorted_segments = NULL;
int n_delta = track_id - 1; /* TrackID = 1-based stream index */
@@ -1104,11 +1127,18 @@ static int mxf_parse_index(MXFContext *mxf, int track_id, AVStream *st)
int duration, sample_duration = 1, last_sample_size = 0;
int64_t segment_size;
MXFIndexTableSegment *tableseg = sorted_segments[j];
+ int index_delta = 1, last_size_unknown = 0;
+ int64_t last_pos = 0;
/* reset accumulated_offset on BodySID change */
if (j > 0 && tableseg->body_sid != sorted_segments[j-1]->body_sid)
accumulated_offset = 0;
+ if (tableseg->nb_index_entries == 2 * tableseg->index_duration + 1) {
+ /* Avid index - duplicate entries and total size as last entry */
+ index_delta = 2;
+ }
+
if (n_delta >= tableseg->nb_delta_entries && st->index != 0)
continue;
duration = tableseg->index_duration > 0 ? tableseg->index_duration :
@@ -1132,33 +1162,33 @@ static int mxf_parse_index(MXFContext *mxf, int track_id, AVStream *st)
goto err_out;
}
- for (k = 0; k < duration; k++) {
+ for (k = l = 0; k < duration; k++, l += index_delta) {
int64_t pos;
int size, flags = 0;
- if (k < tableseg->nb_index_entries) {
- pos = tableseg->stream_offset_entries[k];
+ if (l < tableseg->nb_index_entries) {
+ pos = tableseg->stream_offset_entries[l];
if (n_delta < tableseg->nb_delta_entries) {
if (n_delta < tableseg->nb_delta_entries - 1) {
size =
- tableseg->slice_offset_entries[k][tableseg->slice[n_delta+1]-1] +
+ tableseg->slice_offset_entries[l][tableseg->slice[n_delta+1]-1] +
tableseg->element_delta[n_delta+1] -
tableseg->element_delta[n_delta];
if (tableseg->slice[n_delta] > 0)
- size -= tableseg->slice_offset_entries[k][tableseg->slice[n_delta]-1];
- } else if (k < duration - 1) {
- size = tableseg->stream_offset_entries[k+1] -
- tableseg->stream_offset_entries[k] -
- tableseg->slice_offset_entries[k][tableseg->slice[tableseg->nb_delta_entries-1]-1] -
+ size -= tableseg->slice_offset_entries[l][tableseg->slice[n_delta]-1];
+ } else if (l < tableseg->nb_index_entries - 1) {
+ size = tableseg->stream_offset_entries[l+1] -
+ tableseg->stream_offset_entries[l] -
+ tableseg->slice_offset_entries[l][tableseg->slice[tableseg->nb_delta_entries-1]-1] -
tableseg->element_delta[tableseg->nb_delta_entries-1];
} else
size = 0;
if (tableseg->slice[n_delta] > 0)
- pos += tableseg->slice_offset_entries[k][tableseg->slice[n_delta]-1];
+ pos += tableseg->slice_offset_entries[l][tableseg->slice[n_delta]-1];
pos += tableseg->element_delta[n_delta];
} else
size = 0;
- flags = !(tableseg->flag_entries[k] & 0x30) ? AVINDEX_KEYFRAME : 0;
+ flags = !(tableseg->flag_entries[l] & 0x30) ? AVINDEX_KEYFRAME : 0;
} else {
pos = (int64_t)k * tableseg->edit_unit_byte_count + accumulated_offset;
if (n_delta < tableseg->nb_delta_entries - 1)
@@ -1177,6 +1207,12 @@ static int mxf_parse_index(MXFContext *mxf, int track_id, AVStream *st)
flags = AVINDEX_KEYFRAME;
}
+ if (last_size_unknown)
+ st->index_entries[st->nb_index_entries-1].size = pos - last_pos;
+
+ last_size_unknown = size == 0;
+ last_pos = pos;
+
if (mxf_absolute_bodysid_offset(mxf, tableseg->body_sid, pos, &pos) < 0) {
/* probably partial file - no point going further for this stream */
break;
@@ -1188,6 +1224,14 @@ static int mxf_parse_index(MXFContext *mxf, int track_id, AVStream *st)
if ((ret = av_add_index_entry(st, pos, sample_duration * st->nb_index_entries, size, 0, flags)) < 0)
return ret;
}
+
+ if (last_size_unknown) {
+ int64_t ecl = mxf_essence_container_length(mxf, tableseg->body_sid);
+
+ if (ecl > 0)
+ st->index_entries[st->nb_index_entries-1].size = ecl - last_pos;
+ }
+
accumulated_offset += segment_size;
}