|
@@ -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 { |
|
@@ -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) |
|
|
static int mxf_read_header(AVFormatContext *s) |
|
|
{ |
|
|
{ |
|
|
MXFContext *mxf = s->priv_data; |
|
|
MXFContext *mxf = s->priv_data; |
|
@@ -1691,6 +1728,7 @@ static int mxf_read_header(AVFormatContext *s) |
|
|
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"); |
|
@@ -1796,6 +1834,8 @@ static int mxf_read_header(AVFormatContext *s) |
|
|
return AVERROR_INVALIDDATA; |
|
|
return AVERROR_INVALIDDATA; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
mxf_handle_small_eubc(s); |
|
|
|
|
|
|
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@@ -1897,6 +1937,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); |
|
@@ -1909,12 +1950,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; |
|
@@ -1938,7 +1981,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; |
|
|
} |
|
|
} |
|
|