[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