Commit f1721fbc authored by Michael Niedermayer's avatar Michael Niedermayer

Merge remote-tracking branch 'tjoppen/mxf_fixes_20120124'

* tjoppen/mxf_fixes_20120124:
  mxfdec: Fix files > 2 GiB
  mxfdec: Handle small EditUnitByteCount
Merged-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parents 62d2a75b b720915b
...@@ -207,6 +207,7 @@ typedef struct { ...@@ -207,6 +207,7 @@ typedef struct {
int current_edit_unit; int current_edit_unit;
int nb_index_tables; int nb_index_tables;
MXFIndexTable *index_tables; MXFIndexTable *index_tables;
int edit_units_per_packet; ///< how many edit units to read at a time (PCM, OPAtom)
} MXFContext; } MXFContext;
enum MXFWrappingScheme { enum MXFWrappingScheme {
...@@ -991,7 +992,7 @@ static int64_t mxf_essence_container_end(MXFContext *mxf, int body_sid) ...@@ -991,7 +992,7 @@ static int64_t mxf_essence_container_end(MXFContext *mxf, int body_sid)
static int mxf_edit_unit_absolute_offset(MXFContext *mxf, MXFIndexTable *index_table, int64_t edit_unit, int64_t *edit_unit_out, int64_t *offset_out, int nag) static int mxf_edit_unit_absolute_offset(MXFContext *mxf, MXFIndexTable *index_table, int64_t edit_unit, int64_t *edit_unit_out, int64_t *offset_out, int nag)
{ {
int i; int i;
int offset_temp = 0; int64_t offset_temp = 0;
for (i = 0; i < index_table->nb_segments; i++) { for (i = 0; i < index_table->nb_segments; i++) {
MXFIndexTableSegment *s = index_table->segments[i]; MXFIndexTableSegment *s = index_table->segments[i];
...@@ -1615,6 +1616,38 @@ static int64_t round_to_kag(int64_t position, int kag_size) ...@@ -1615,6 +1616,38 @@ static int64_t round_to_kag(int64_t position, int kag_size)
return ret == position ? ret : ret + kag_size; return ret == position ? ret : ret + kag_size;
} }
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) static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap)
{ {
MXFContext *mxf = s->priv_data; MXFContext *mxf = s->priv_data;
...@@ -1623,6 +1656,7 @@ static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap) ...@@ -1623,6 +1656,7 @@ static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap)
int ret; int ret;
mxf->last_forward_tell = INT64_MAX; mxf->last_forward_tell = INT64_MAX;
mxf->edit_units_per_packet = 1;
if (!mxf_read_sync(s->pb, mxf_header_partition_pack_key, 14)) { 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"); av_log(s, AV_LOG_ERROR, "could not find header partition pack key\n");
...@@ -1747,6 +1781,8 @@ static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap) ...@@ -1747,6 +1781,8 @@ static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap)
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
} }
mxf_handle_small_eubc(s);
return 0; return 0;
} }
...@@ -1847,6 +1883,7 @@ static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt) ...@@ -1847,6 +1883,7 @@ static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt)
int64_t ret64, pos, next_pos; int64_t ret64, pos, next_pos;
AVStream *st; AVStream *st;
MXFIndexTable *t; MXFIndexTable *t;
int edit_units;
if (mxf->op != OPAtom) if (mxf->op != OPAtom)
return mxf_read_packet_old(s, pkt); return mxf_read_packet_old(s, pkt);
...@@ -1859,12 +1896,14 @@ static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt) ...@@ -1859,12 +1896,14 @@ static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt)
if (mxf->current_edit_unit >= st->duration) if (mxf->current_edit_unit >= st->duration)
return AVERROR_EOF; 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) if ((ret = mxf_edit_unit_absolute_offset(mxf, t, mxf->current_edit_unit, NULL, &pos, 1)) < 0)
return ret; return ret;
/* compute size by finding the next edit unit or the end of the essence container /* compute size by finding the next edit unit or the end of the essence container
* not pretty, but it works */ * 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) { (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"); av_log(s, AV_LOG_ERROR, "unable to compute the size of the last packet\n");
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
...@@ -1888,7 +1927,7 @@ static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt) ...@@ -1888,7 +1927,7 @@ static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt)
} }
pkt->stream_index = 0; pkt->stream_index = 0;
mxf->current_edit_unit++; mxf->current_edit_unit += edit_units;
return 0; return 0;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment