|
|
|
@@ -1829,48 +1829,50 @@ static int mxf_read_header(AVFormatContext *s) |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Computes DTS and PTS for the given video packet based on its offset. |
|
|
|
* Sets mxf->current_edit_unit based on what offset we're currently at. |
|
|
|
* @return next_ofs if OK, <0 on error |
|
|
|
*/ |
|
|
|
static void mxf_packet_timestamps(MXFContext *mxf, AVPacket *pkt) |
|
|
|
static int64_t mxf_set_current_edit_unit(MXFContext *mxf, int64_t current_offset) |
|
|
|
{ |
|
|
|
int64_t last_ofs = -1, next_ofs; |
|
|
|
int64_t last_ofs = -1, next_ofs = -1; |
|
|
|
MXFIndexTable *t = &mxf->index_tables[0]; |
|
|
|
|
|
|
|
/* this is called from the OP1a demuxing logic, which means there |
|
|
|
* may be no index tables */ |
|
|
|
if (mxf->nb_index_tables <= 0) |
|
|
|
return; |
|
|
|
return -1; |
|
|
|
|
|
|
|
/* find mxf->current_edit_unit so that the next edit unit starts ahead of pkt->pos */ |
|
|
|
/* find mxf->current_edit_unit so that the next edit unit starts ahead of current_offset */ |
|
|
|
while (mxf->current_edit_unit >= 0) { |
|
|
|
if (mxf_edit_unit_absolute_offset(mxf, t, mxf->current_edit_unit + 1, NULL, &next_ofs, 0) < 0) |
|
|
|
break; |
|
|
|
return -1; |
|
|
|
|
|
|
|
if (next_ofs <= last_ofs) { |
|
|
|
/* large next_ofs didn't change or current_edit_unit wrapped |
|
|
|
* around this fixes the infinite loop on zzuf3.mxf */ |
|
|
|
av_log(mxf->fc, AV_LOG_ERROR, |
|
|
|
"next_ofs didn't change. not deriving packet timestamps\n"); |
|
|
|
return; |
|
|
|
return - 1; |
|
|
|
} |
|
|
|
|
|
|
|
if (next_ofs > pkt->pos) |
|
|
|
if (next_ofs > current_offset) |
|
|
|
break; |
|
|
|
|
|
|
|
last_ofs = next_ofs; |
|
|
|
mxf->current_edit_unit++; |
|
|
|
} |
|
|
|
|
|
|
|
if (mxf->current_edit_unit < 0 || mxf->current_edit_unit >= t->nb_ptses) |
|
|
|
return; |
|
|
|
/* not checking mxf->current_edit_unit >= t->nb_ptses here since CBR files may lack IndexEntryArrays */ |
|
|
|
if (mxf->current_edit_unit < 0) |
|
|
|
return -1; |
|
|
|
|
|
|
|
pkt->dts = mxf->current_edit_unit + t->first_dts; |
|
|
|
pkt->pts = t->ptses[mxf->current_edit_unit]; |
|
|
|
return next_ofs; |
|
|
|
} |
|
|
|
|
|
|
|
static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt) |
|
|
|
{ |
|
|
|
KLVPacket klv; |
|
|
|
MXFContext *mxf = s->priv_data; |
|
|
|
|
|
|
|
while (!url_feof(s->pb)) { |
|
|
|
int ret; |
|
|
|
@@ -1889,12 +1891,27 @@ static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt) |
|
|
|
if (IS_KLV_KEY(klv.key, mxf_essence_element_key) || |
|
|
|
IS_KLV_KEY(klv.key, mxf_avid_essence_element_key)) { |
|
|
|
int index = mxf_get_stream_index(s, &klv); |
|
|
|
int64_t next_ofs, next_klv; |
|
|
|
|
|
|
|
if (index < 0) { |
|
|
|
av_log(s, AV_LOG_ERROR, "error getting stream index %d\n", AV_RB32(klv.key+12)); |
|
|
|
goto skip; |
|
|
|
} |
|
|
|
if (s->streams[index]->discard == AVDISCARD_ALL) |
|
|
|
goto skip; |
|
|
|
|
|
|
|
next_klv = avio_tell(s->pb) + klv.length; |
|
|
|
next_ofs = mxf_set_current_edit_unit(mxf, klv.offset); |
|
|
|
|
|
|
|
if (next_ofs >= 0 && next_klv > next_ofs) { |
|
|
|
/* if this check is hit then it's possible OPAtom was treated as OP1a |
|
|
|
* truncate the packet since it's probably very large (>2 GiB is common) */ |
|
|
|
av_log_ask_for_sample(s, |
|
|
|
"KLV for edit unit %i extends into next edit unit - OPAtom misinterpreted as OP1a?\n", |
|
|
|
mxf->current_edit_unit); |
|
|
|
klv.length = next_ofs - avio_tell(s->pb); |
|
|
|
} |
|
|
|
|
|
|
|
/* check for 8 channels AES3 element */ |
|
|
|
if (klv.key[12] == 0x06 && klv.key[13] == 0x01 && klv.key[14] == 0x10) { |
|
|
|
if (mxf_get_d10_aes3_packet(s->pb, s->streams[index], pkt, klv.length) < 0) { |
|
|
|
@@ -1909,8 +1926,18 @@ static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt) |
|
|
|
pkt->stream_index = index; |
|
|
|
pkt->pos = klv.offset; |
|
|
|
|
|
|
|
if (s->streams[index]->codec->codec_type == AVMEDIA_TYPE_VIDEO) |
|
|
|
mxf_packet_timestamps(s->priv_data, pkt); /* offset -> EditUnit -> DTS/PTS */ |
|
|
|
if (s->streams[index]->codec->codec_type == AVMEDIA_TYPE_VIDEO && next_ofs >= 0) { |
|
|
|
/* mxf->current_edit_unit good - see if we have an index table to derive timestamps from */ |
|
|
|
MXFIndexTable *t = &mxf->index_tables[0]; |
|
|
|
|
|
|
|
if (mxf->nb_index_tables >= 1 && mxf->current_edit_unit < t->nb_ptses) { |
|
|
|
pkt->dts = mxf->current_edit_unit + t->first_dts; |
|
|
|
pkt->pts = t->ptses[mxf->current_edit_unit]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* seek for truncated packets */ |
|
|
|
avio_seek(s->pb, next_klv, SEEK_SET); |
|
|
|
|
|
|
|
return 0; |
|
|
|
} else |
|
|
|
|