These are common with audio atoms. Without this the demuxer would read two
bytes at a time for a mono 16-bit file.
---
 libavformat/mxfdec.c |   43 +++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c
index cf9751a..d385a7e 100644
--- a/libavformat/mxfdec.c
+++ b/libavformat/mxfdec.c
@@ -207,6 +207,7 @@ typedef struct {
     int current_edit_unit;
     int nb_index_tables;
     MXFIndexTable *index_tables;
+    int edit_units_per_packet;      ///< how many edit units to read at a time 
(PCM, OPAtom)
 } MXFContext;
 
 enum MXFWrappingScheme {
@@ -1678,6 +1679,38 @@ static inline void 
compute_partition_essence_offset(AVFormatContext *s,
     }
 }
 
+static int is_pcm(enum CodecID codec_id)
+{
+    /* we only care about "normal" PCM codecs until we get samples */
+    return codec_id >= CODEC_ID_PCM_S16LE && codec_id < CODEC_ID_PCM_S24DAUD;
+}
+
+/**
+ * Deals with the case where for some audio atoms EditUnitByteCount is very 
small (2, 4..).
+ * In those cases we should read more than one sample per call to 
mxf_read_packet().
+ */
+static void mxf_handle_small_eubc(AVFormatContext *s)
+{
+    MXFContext *mxf = s->priv_data;
+
+    /* assuming non-OPAtom == frame wrapped
+     * no sane writer would wrap 2 byte PCM packets with 20 byte headers.. */
+    if (mxf->op != OPAtom)
+        return;
+
+    /* expect PCM with exactly one index table segment and a small (< 32) EUBC 
*/
+    if (s->nb_streams != 1 || s->streams[0]->codec->codec_type != 
AVMEDIA_TYPE_AUDIO ||
+        !is_pcm(s->streams[0]->codec->codec_id) || mxf->nb_index_tables != 1 ||
+        mxf->index_tables[0].nb_segments != 1 ||
+        mxf->index_tables[0].segments[0]->edit_unit_byte_count >= 32)
+        return;
+
+    /* arbitrarily default to 48 kHz PAL audio frame size */
+    /* TODO: we could compute this from the ratio between the audio and video 
edit rates
+     *       for 48 kHz NTSC we could use the 1802-1802-1802-1802-1801 pattern 
*/
+    mxf->edit_units_per_packet = 1920;
+}
+
 static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap)
 {
     MXFContext *mxf = s->priv_data;
@@ -1686,6 +1719,7 @@ static int mxf_read_header(AVFormatContext *s, 
AVFormatParameters *ap)
     int ret;
 
     mxf->last_forward_tell = INT64_MAX;
+    mxf->edit_units_per_packet = 1;
 
     if (!mxf_read_sync(s->pb, mxf_header_partition_pack_key, 14)) {
         av_log(s, AV_LOG_ERROR, "could not find header partition pack key\n");
@@ -1790,6 +1824,8 @@ static int mxf_read_header(AVFormatContext *s, 
AVFormatParameters *ap)
         return AVERROR_INVALIDDATA;
     }
 
+    mxf_handle_small_eubc(s);
+
     return 0;
 }
 
@@ -1889,6 +1925,7 @@ static int mxf_read_packet(AVFormatContext *s, AVPacket 
*pkt)
     int64_t ret64, pos, next_pos;
     AVStream *st;
     MXFIndexTable *t;
+    int edit_units;
 
     if (mxf->op != OPAtom)
         return mxf_read_packet_old(s, pkt);
@@ -1901,12 +1938,14 @@ static int mxf_read_packet(AVFormatContext *s, AVPacket 
*pkt)
     if (mxf->current_edit_unit >= st->duration)
         return AVERROR_EOF;
 
+    edit_units = FFMIN(mxf->edit_units_per_packet, st->duration - 
mxf->current_edit_unit);
+
     if ((ret = mxf_edit_unit_absolute_offset(mxf, t, mxf->current_edit_unit, 
NULL, &pos, 1)) < 0)
         return ret;
 
     /* compute size by finding the next edit unit or the end of the essence 
container
      * not pretty, but it works */
-    if ((ret = mxf_edit_unit_absolute_offset(mxf, t, mxf->current_edit_unit + 
1, NULL, &next_pos, 0)) < 0 &&
+    if ((ret = mxf_edit_unit_absolute_offset(mxf, t, mxf->current_edit_unit + 
edit_units, NULL, &next_pos, 0)) < 0 &&
         (next_pos = mxf_essence_container_end(mxf, t->body_sid)) <= 0) {
         av_log(s, AV_LOG_ERROR, "unable to compute the size of the last 
packet\n");
         return AVERROR_INVALIDDATA;
@@ -1930,7 +1969,7 @@ static int mxf_read_packet(AVFormatContext *s, AVPacket 
*pkt)
     }
 
     pkt->stream_index = 0;
-    mxf->current_edit_unit++;
+    mxf->current_edit_unit += edit_units;
 
     return 0;
 }
-- 
1.7.5.4

_______________________________________________
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to