From: Tomas Härdin <[email protected]>
This adds OPAtom support and proper seeking.
D-10 and non-seekable OP1a streams still use the old demuxing/seeking code.
---
libavformat/mxfdec.c | 101 +++++++++++++++++++++++++++++++++++++++++++++--
tests/ref/seek/lavf_mxf | 41 ++++++++-----------
2 files changed, 115 insertions(+), 27 deletions(-)
diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c
index 67984c5..d4195fb 100644
--- a/libavformat/mxfdec.c
+++ b/libavformat/mxfdec.c
@@ -197,6 +197,9 @@ typedef struct {
int parsing_backward;
int64_t last_forward_tell;
int last_forward_partition;
+ int current_edit_unit;
+ int current_stream;
+ int d10;
} MXFContext;
enum MXFWrappingScheme {
@@ -372,7 +375,7 @@ static int mxf_decrypt_triplet(AVFormatContext *s, AVPacket
*pkt, KLVPacket *klv
return 0;
}
-static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt)
+static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt)
{
KLVPacket klv;
@@ -418,6 +421,65 @@ static int mxf_read_packet(AVFormatContext *s, AVPacket
*pkt)
return AVERROR_EOF;
}
+static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ MXFContext *mxf = s->priv_data;
+ AVIndexEntry *e;
+ int ret;
+ int64_t ret64;
+ KLVPacket klv;
+ AVStream *st;
+
+ /* TODO: better logic for this?
+ * only files that lack all index segments prior to the essence need this
*/
+ if (!s->pb->seekable && mxf->op != OPAtom || mxf->d10)
+ return mxf_read_packet_old(s, pkt);
+
+ if (mxf->current_stream >= s->nb_streams) {
+ mxf->current_edit_unit++;
+ mxf->current_stream = 0;
+ }
+
+ st = s->streams[mxf->current_stream];
+
+ if (mxf->current_edit_unit >= st->nb_index_entries)
+ return AVERROR_EOF;
+
+ e = &st->index_entries[mxf->current_edit_unit];
+
+ if ((ret64 = avio_seek(s->pb, e->pos, SEEK_SET)) < 0)
+ return ret64;
+
+ if (mxf->op == OPAtom) {
+ /* OPAtom - no KL, just essence */
+ if ((ret = av_get_packet(s->pb, pkt, e->size)) != e->size)
+ return ret < 0 ? ret : AVERROR_EOF;
+ } else {
+ /* read KL, read L bytes of essence */
+ if ((ret = klv_read_packet(&klv, s->pb)) < 0)
+ return ret;
+
+ /* untested, but looks OK */
+ if (IS_KLV_KEY(klv.key, mxf_encrypted_triplet_key)) {
+ int res = mxf_decrypt_triplet(s, pkt, &klv);
+ if (res < 0) {
+ av_log(s, AV_LOG_ERROR, "invalid encoded triplet\n");
+ return -1;
+ }
+ return 0;
+ }
+
+ if ((ret = av_get_packet(s->pb, pkt, klv.length)) != klv.length)
+ return ret < 0 ? ret : AVERROR_EOF;
+
+ pkt->pos = e->pos;
+ }
+
+ pkt->stream_index = mxf->current_stream++;
+
+ return 0;
+}
+
static int mxf_read_primer_pack(void *arg, AVIOContext *pb, int tag, int size,
UID uid, int64_t klv_offset)
{
MXFContext *mxf = arg;
@@ -948,6 +1010,8 @@ static const MXFCodecUL mxf_essence_container_uls[] = {
{ {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
}, 0, CODEC_ID_NONE },
};
+static UID mxf_d10_ul = {
0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x01,0x01
};
+
static int mxf_get_sorted_table_segments(MXFContext *mxf, int
*nb_sorted_segments, MXFIndexTableSegment ***sorted_segments)
{
int i, j, nb_segments = 0;
@@ -1277,6 +1341,11 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
}
}
}
+
+ /* HACK: revert to the old demuxing/seeking scode for D-10 for now */
+ if (mxf_match_uid(essence_container_ul, mxf_d10_ul, 14))
+ mxf->d10 = 1;
+
/* TODO: drop PictureEssenceCoding and SoundEssenceCompression, only
check EssenceContainer */
codec_ul = mxf_get_codec_ul(ff_mxf_codec_uls,
&descriptor->essence_codec_ul);
st->codec->codec_id = codec_ul->id;
@@ -1316,8 +1385,8 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
}
}
if (st->codec->codec_type != AVMEDIA_TYPE_DATA &&
(*essence_container_ul)[15] > 0x01) {
- av_log(mxf->fc, AV_LOG_WARNING, "only frame wrapped mappings are
correctly supported\n");
- st->need_parsing = AVSTREAM_PARSE_FULL;
+ /* TODO: decode timestamps */
+ st->need_parsing = AVSTREAM_PARSE_TIMESTAMPS;
}
if ((ret = mxf_parse_index(mxf, material_track->track_id, st)))
@@ -1684,8 +1753,11 @@ static int mxf_read_seek(AVFormatContext *s, int
stream_index, int64_t sample_ti
{
AVStream *st = s->streams[stream_index];
int64_t seconds;
- int ret;
+ MXFContext* mxf = s->priv_data;
+ int64_t seekpos;
+ int index, ret;
+ if (mxf->d10) {
if (!s->bit_rate)
return -1;
if (sample_time < 0)
@@ -1695,6 +1767,27 @@ static int mxf_read_seek(AVFormatContext *s, int
stream_index, int64_t sample_ti
if ((ret = avio_seek(s->pb, (s->bit_rate * seconds) >> 3, SEEK_SET)) < 0)
return ret;
ff_update_cur_dts(s, st, sample_time);
+ } else {
+ if (st->nb_index_entries <= 0)
+ return -1;
+
+ index = av_index_search_timestamp(st, sample_time, flags);
+
+ av_dlog(s, "stream %d, timestamp %"PRId64", sample %d\n", st->index,
sample_time, index);
+
+ if (index < 0) {
+ if (sample_time < st->index_entries[0].timestamp)
+ index = 0;
+ else
+ return -1;
+ }
+
+ seekpos = st->index_entries[index].pos;
+ ff_update_cur_dts(s, st, st->index_entries[index].timestamp);
+ mxf->current_edit_unit = st->index_entries[index].timestamp;
+ mxf->current_stream = 0;
+ avio_seek(s->pb, seekpos, SEEK_SET);
+ }
return 0;
}
diff --git a/tests/ref/seek/lavf_mxf b/tests/ref/seek/lavf_mxf
index 4c1aecc..00dea3d 100644
--- a/tests/ref/seek/lavf_mxf
+++ b/tests/ref/seek/lavf_mxf
@@ -2,52 +2,47 @@ ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos:
6144 size: 24801
ret: 0 st:-1 flags:0 ts:-1.000000
ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size:
24801
ret: 0 st:-1 flags:1 ts: 1.894167
-ret:-1
+ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 460800 size:
24712
ret: 0 st: 0 flags:0 ts: 0.800000
-ret:-1
+ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 460800 size:
24712
ret: 0 st: 0 flags:1 ts:-0.320000
ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size:
24801
-ret: 0 st: 1 flags:0 ts: 2.560000
-ret:-1
+ret:-1 st: 1 flags:0 ts: 2.560000
ret: 0 st: 1 flags:1 ts: 1.480000
-ret:-1
+ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 460800 size:
24712
ret: 0 st:-1 flags:0 ts: 0.365002
-ret: 0 st: 0 flags:1 dts: 0.360000 pts: NOPTS pos: 6144 size:
24801
+ret: 0 st: 0 flags:1 dts: 0.400000 pts: NOPTS pos: 211968 size:
24787
ret: 0 st:-1 flags:1 ts:-0.740831
ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size:
24801
-ret: 0 st: 0 flags:0 ts: 2.160000
-ret:-1
+ret:-1 st: 0 flags:0 ts: 2.160000
ret: 0 st: 0 flags:1 ts: 1.040000
-ret:-1
+ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 460800 size:
24712
ret: 0 st: 1 flags:0 ts:-0.040000
ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size:
24801
ret: 0 st: 1 flags:1 ts: 2.840000
-ret:-1
-ret: 0 st:-1 flags:0 ts: 1.730004
-ret:-1
+ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 460800 size:
24712
+ret:-1 st:-1 flags:0 ts: 1.730004
ret: 0 st:-1 flags:1 ts: 0.624171
-ret:-1
+ret: 0 st: 0 flags:1 dts: 0.400000 pts: NOPTS pos: 211968 size:
24787
ret: 0 st: 0 flags:0 ts:-0.480000
ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size:
24801
ret: 0 st: 0 flags:1 ts: 2.400000
-ret:-1
-ret: 0 st: 1 flags:0 ts: 1.320000
-ret:-1
+ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 460800 size:
24712
+ret:-1 st: 1 flags:0 ts: 1.320000
ret: 0 st: 1 flags:1 ts: 0.200000
-ret: 0 st: 0 flags:1 dts: 0.200000 pts: NOPTS pos: 6144 size:
24801
+ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size:
24801
ret: 0 st:-1 flags:0 ts:-0.904994
ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size:
24801
ret: 0 st:-1 flags:1 ts: 1.989173
-ret:-1
+ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 460800 size:
24712
ret: 0 st: 0 flags:0 ts: 0.880000
-ret:-1
+ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 460800 size:
24712
ret: 0 st: 0 flags:1 ts:-0.240000
ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size:
24801
-ret: 0 st: 1 flags:0 ts: 2.680000
-ret:-1
+ret:-1 st: 1 flags:0 ts: 2.680000
ret: 0 st: 1 flags:1 ts: 1.560000
-ret:-1
+ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 460800 size:
24712
ret: 0 st:-1 flags:0 ts: 0.460008
-ret: 0 st: 0 flags:1 dts: 0.480000 pts: NOPTS pos: 6144 size:
24801
+ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 460800 size:
24712
ret: 0 st:-1 flags:1 ts:-0.645825
ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 6144 size:
24801
--
1.7.8
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel