--- 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 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel