summaryrefslogtreecommitdiff
path: root/libavformat/mxfdec.c
diff options
context:
space:
mode:
authorTomas Härdin <tomas.hardin@codemill.se>2012-01-26 13:21:44 +0100
committerDiego Biurrun <diego@biurrun.de>2012-02-09 12:59:41 +0100
commitc65642d3513f1761b566d15ed9c937458f8c522c (patch)
tree3e810f39913ef50d23792a77be82aa3359b3614f /libavformat/mxfdec.c
parent240ddbce5646f0a152585e1ecad31c3e10b89b32 (diff)
mxfdec: Handle small EditUnitByteCount
These are common with audio atoms. Without this the demuxer would read two bytes at a time for a mono 16-bit file. Signed-off-by: Diego Biurrun <diego@biurrun.de>
Diffstat (limited to 'libavformat/mxfdec.c')
-rw-r--r--libavformat/mxfdec.c47
1 files changed, 45 insertions, 2 deletions
diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c
index e70bc21bd0..9a89469fd7 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 {
@@ -1683,6 +1684,42 @@ 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;
+}
+
+/**
+ * Deal 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)
{
MXFContext *mxf = s->priv_data;
@@ -1691,6 +1728,7 @@ static int mxf_read_header(AVFormatContext *s)
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");
@@ -1796,6 +1834,8 @@ static int mxf_read_header(AVFormatContext *s)
return AVERROR_INVALIDDATA;
}
+ mxf_handle_small_eubc(s);
+
return 0;
}
@@ -1897,6 +1937,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);
@@ -1909,12 +1950,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;
@@ -1938,7 +1981,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;
}