[FFmpeg-devel] [PATCH] libavformat/mxfdec.c: support demuxing opatom audio without index
Mark Reid
mindmark at gmail.com
Mon Dec 22 02:46:48 CET 2014
---
libavformat/mxfdec.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 63 insertions(+), 3 deletions(-)
diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c
index 4715169..92c864f 100644
--- a/libavformat/mxfdec.c
+++ b/libavformat/mxfdec.c
@@ -152,6 +152,8 @@ typedef struct {
int intra_only;
uint64_t sample_count;
int64_t original_duration; /* st->duration in SampleRate/EditRate units */
+ int64_t essence_offset;
+ int64_t essence_length;
} MXFTrack;
typedef struct {
@@ -2422,6 +2424,28 @@ static void mxf_handle_small_eubc(AVFormatContext *s)
mxf->edit_units_per_packet = 1920;
}
+static int mxf_handle_opatom_missing_index(AVFormatContext *s)
+{
+ KLVPacket klv;
+ MXFTrack *track = NULL;
+
+ /* TODO: support raw video without a index if they exist */
+ if (s->nb_streams != 1 || s->streams[0]->codec->codec_type != AVMEDIA_TYPE_AUDIO || !is_pcm(s->streams[0]->codec->codec_id))
+ return AVERROR_INVALIDDATA;
+
+ if (klv_read_packet(&klv, s->pb) != 0)
+ return AVERROR_INVALIDDATA;
+
+ if (!(IS_KLV_KEY(klv.key, mxf_essence_element_key) || IS_KLV_KEY(klv.key, mxf_avid_essence_element_key)))
+ return AVERROR_INVALIDDATA;
+
+ track = s->streams[0]->priv_data;
+ track->essence_offset = avio_tell(s->pb);
+ track->essence_length = klv.length;
+
+ return 0;
+}
+
static void mxf_read_random_index_pack(AVFormatContext *s)
{
MXFContext *mxf = s->priv_data;
@@ -2592,9 +2616,11 @@ static int mxf_read_header(AVFormatContext *s)
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");
- ret = AVERROR_INVALIDDATA;
- goto fail;
+ if (mxf_handle_opatom_missing_index(s) != 0) {
+ av_log(mxf->fc, AV_LOG_ERROR, "cannot demux OPAtom without an index\n");
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
}
mxf_handle_small_eubc(s);
@@ -2807,6 +2833,37 @@ static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt)
return avio_feof(s->pb) ? AVERROR_EOF : ret;
}
+#define RAW_SAMPLES 1024
+static int mxf_read_raw_opatom_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ AVStream *st = s->streams[0];
+ MXFTrack *track = st->priv_data;
+ int64_t pos, packet_size, sample_size;
+ int ret;
+
+ pos = avio_tell(s->pb) - track->essence_offset;
+ sample_size = (av_get_bits_per_sample(st->codec->codec_id) * st->codec->channels) >> 3;
+ packet_size = RAW_SAMPLES * sample_size;
+
+ if (pos >= track->essence_length)
+ return AVERROR_EOF;
+
+ if(pos < 0 || pos % packet_size){
+ /* align to nearest packet position */
+ pos = FFMAX(0, pos - (pos % packet_size));
+ if ((ret = avio_seek(s->pb, track->essence_offset + pos, SEEK_SET)) < 0)
+ return ret;
+ }
+
+ ret = av_get_packet(s->pb, pkt, FFMIN(packet_size, track->essence_length - pos));
+ pkt->pts = pkt->dts = pos / sample_size;
+ pkt->stream_index = 0;
+
+ if (ret < 0)
+ return ret;
+ return 0;
+}
+
static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt)
{
MXFContext *mxf = s->priv_data;
@@ -2819,6 +2876,9 @@ static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt)
if (mxf->op != OPAtom)
return mxf_read_packet_old(s, pkt);
+ if (mxf->nb_index_tables <= 0)
+ return mxf_read_raw_opatom_packet(s, pkt);
+
/* OPAtom - clip wrapped demuxing */
/* NOTE: mxf_read_header() makes sure nb_index_tables > 0 for OPAtom */
st = s->streams[0];
--
2.0.0
More information about the ffmpeg-devel
mailing list