From: Tomas Härdin <[email protected]>
This replaces the old essence_offset code.
---
libavformat/mxfdec.c | 61 +++++++++++++++++++++++++++++++------------------
1 files changed, 38 insertions(+), 23 deletions(-)
diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c
index 124acae..67984c5 100644
--- a/libavformat/mxfdec.c
+++ b/libavformat/mxfdec.c
@@ -190,9 +190,6 @@ typedef struct {
uint8_t *local_tags;
int local_tags_count;
uint64_t footer_partition;
- int64_t essence_offset;
- int first_essence_kl_length;
- int64_t first_essence_length;
KLVPacket current_klv_data;
int current_klv_index;
int run_in;
@@ -1010,9 +1007,36 @@ static int mxf_get_sorted_table_segments(MXFContext
*mxf, int *nb_sorted_segment
return 0;
}
+/**
+ * Computes the absolute file offset of the given essence container offset
+ */
+static int mxf_absolute_bodysid_offset(MXFContext *mxf, int body_sid, int64_t
offset, int64_t *offset_out)
+{
+ int x;
+ int64_t offset_in = offset; /* for logging */
+
+ for (x = 0; x < mxf->partitions_count; x++) {
+ MXFPartition *p = &mxf->partitions[x];
+
+ if (p->body_sid != body_sid)
+ continue;
+
+ if (offset < p->essence_length || !p->essence_length) {
+ *offset_out = p->essence_offset + offset;
+ return 0;
+ }
+
+ offset -= p->essence_length;
+ }
+
+ av_log(mxf->fc, AV_LOG_ERROR, "failed to find absolute offset of %lx in
BodySID %i - partial file?\n",
+ offset_in, body_sid);
+
+ return AVERROR_INVALIDDATA;
+}
+
static int mxf_parse_index(MXFContext *mxf, int track_id, AVStream *st)
{
- int64_t accumulated_offset = 0;
int j, k, ret, nb_sorted_segments;
MXFIndexTableSegment **sorted_segments;
int n_delta = track_id - 1; /* TrackID = 1-based stream index */
@@ -1030,10 +1054,6 @@ static int mxf_parse_index(MXFContext *mxf, int
track_id, AVStream *st)
int64_t segment_size;
MXFIndexTableSegment *tableseg = sorted_segments[j];
- /* reset accumulated_offset on BodySID change */
- if (j > 0 && tableseg->body_sid != sorted_segments[j-1]->body_sid)
- accumulated_offset = 0;
-
if (n_delta >= tableseg->nb_delta_entries && st->index != 0)
continue;
duration = tableseg->index_duration > 0 ? tableseg->index_duration :
@@ -1079,7 +1099,7 @@ static int mxf_parse_index(MXFContext *mxf, int track_id,
AVStream *st)
size = 0;
flags = !(tableseg->flag_entries[k] & 0x30) ? AVINDEX_KEYFRAME
: 0;
} else {
- pos = (int64_t)k * tableseg->edit_unit_byte_count +
accumulated_offset;
+ pos = (int64_t)(tableseg->index_start_position + k) *
tableseg->edit_unit_byte_count;
if (n_delta < tableseg->nb_delta_entries - 1)
size = tableseg->element_delta[n_delta+1] -
tableseg->element_delta[n_delta];
else {
@@ -1096,10 +1116,10 @@ static int mxf_parse_index(MXFContext *mxf, int
track_id, AVStream *st)
flags = AVINDEX_KEYFRAME;
}
- if (k > 0 && pos < mxf->first_essence_length && accumulated_offset
== 0)
- pos += mxf->first_essence_kl_length;
-
- pos += mxf->essence_offset;
+ if (mxf_absolute_bodysid_offset(mxf, tableseg->body_sid, pos,
&pos) < 0) {
+ /* probably partial file - no point going further for this
stream */
+ break;
+ }
av_dlog(mxf->fc, "Stream %d IndexEntry %d TrackID %d Offset
%"PRIx64" Timestamp %"PRId64"\n",
st->index, st->nb_index_entries, track_id, pos,
sample_duration * st->nb_index_entries);
@@ -1107,7 +1127,6 @@ 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;
}
- accumulated_offset += segment_size;
}
av_free(sorted_segments);
@@ -1499,6 +1518,7 @@ static int mxf_read_header(AVFormatContext *s,
AVFormatParameters *ap)
{
MXFContext *mxf = s->priv_data;
KLVPacket klv;
+ int64_t essence_offset = 0;
mxf->last_forward_tell = INT64_MAX;
@@ -1550,13 +1570,8 @@ static int mxf_read_header(AVFormatContext *s,
AVFormatParameters *ap)
}
}
- if (!mxf->essence_offset)
- mxf->essence_offset = klv.offset;
-
- if (!mxf->first_essence_kl_length && IS_KLV_KEY(klv.key,
mxf_essence_element_key)) {
- mxf->first_essence_kl_length = avio_tell(s->pb) - klv.offset;
- mxf->first_essence_length = klv.length;
- }
+ if (!essence_offset)
+ essence_offset = klv.offset;
/* seek to footer, previous partition or stop */
if (mxf_parse_handle_essence(mxf) <= 0)
@@ -1590,11 +1605,11 @@ static int mxf_read_header(AVFormatContext *s,
AVFormatParameters *ap)
avio_skip(s->pb, klv.length);
}
/* FIXME avoid seek */
- if (!mxf->essence_offset) {
+ if (!essence_offset) {
av_log(s, AV_LOG_ERROR, "no essence\n");
return AVERROR_INVALIDDATA;
}
- avio_seek(s->pb, mxf->essence_offset, SEEK_SET);
+ avio_seek(s->pb, essence_offset, SEEK_SET);
mxf_compute_essence_containers(mxf);
--
1.7.8
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel