return s->nb_streams == 1 && s->streams[0]->priv_data ? 0 : -1;
}
-static int find_body_sid_by_offset(MXFContext *mxf, int64_t offset)
+static int find_body_sid_by_absolute_offset(MXFContext *mxf, int64_t offset)
{
// we look for partition where the offset is placed
int a, b, m;
- int64_t this_partition;
+ int64_t pack_ofs;
a = -1;
b = mxf->partitions_count;
while (b - a > 1) {
- m = (a + b) >> 1;
- this_partition = mxf->partitions[m].this_partition;
- if (this_partition <= offset)
+ m = (a + b) >> 1;
+ pack_ofs = mxf->partitions[m].pack_ofs;
+ if (pack_ofs <= offset)
a = m;
else
b = m;
if (!IS_KLV_KEY(klv, mxf_essence_element_key))
return AVERROR_INVALIDDATA;
- body_sid = find_body_sid_by_offset(mxf, klv->offset);
+ body_sid = find_body_sid_by_absolute_offset(mxf, klv->offset);
index = mxf_get_stream_index(s, klv, body_sid);
if (index < 0)
return AVERROR_INVALIDDATA;
static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
{
MXFContext *mxf = arg;
+ AVFormatContext *s = mxf->fc;
MXFPartition *partition, *tmp_part;
UID op;
uint64_t footer_partition;
}
nb_essence_containers = avio_rb32(pb);
+ if (partition->type == Header) {
+ char str[36];
+ snprintf(str, sizeof(str), "%08x.%08x.%08x.%08x", AV_RB32(&op[0]), AV_RB32(&op[4]), AV_RB32(&op[8]), AV_RB32(&op[12]));
+ av_dict_set(&s->metadata, "operational_pattern_ul", str, 0);
+ }
+
if (partition->this_partition &&
partition->previous_partition == partition->this_partition) {
av_log(mxf->fc, AV_LOG_ERROR,
{ { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x05,0x00,0x00 }, 14, AV_CODEC_ID_RAWVIDEO, NULL, 15, RawVWrap }, /* uncompressed picture */
{ { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0a,0x0e,0x0f,0x03,0x01,0x02,0x20,0x01,0x01 }, 15, AV_CODEC_ID_HQ_HQA },
{ { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0a,0x0e,0x0f,0x03,0x01,0x02,0x20,0x02,0x01 }, 15, AV_CODEC_ID_HQX },
+ { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0a,0x0e,0x15,0x00,0x04,0x02,0x10,0x00,0x01 }, 16, AV_CODEC_ID_HEVC, NULL, 15 }, /* Canon XF-HEVC */
{ { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0xff,0x4b,0x46,0x41,0x41,0x00,0x0d,0x4d,0x4f }, 14, AV_CODEC_ID_RAWVIDEO }, /* Legacy ?? Uncompressed Picture */
{ { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_CODEC_ID_NONE },
};
*/
static int64_t mxf_essence_container_end(MXFContext *mxf, int body_sid)
{
- int x;
- int64_t ret = 0;
-
- for (x = 0; x < mxf->partitions_count; x++) {
+ for (int x = mxf->partitions_count - 1; x >= 0; x--) {
MXFPartition *p = &mxf->partitions[x];
if (p->body_sid != body_sid)
if (!p->essence_length)
return 0;
- ret = p->essence_offset + p->essence_length;
+ return p->essence_offset + p->essence_length;
}
- return ret;
+ return 0;
}
/* EditUnit -> absolute offset */
}
}
+ for (int i = 0; i < mxf->fc->nb_streams; i++) {
+ MXFTrack *track1 = mxf->fc->streams[i]->priv_data;
+ if (track1 && track1->body_sid) {
+ for (int j = i + 1; j < mxf->fc->nb_streams; j++) {
+ MXFTrack *track2 = mxf->fc->streams[j]->priv_data;
+ if (track2 && track1->body_sid == track2->body_sid && track1->wrapping != track2->wrapping) {
+ if (track1->wrapping == UnknownWrapped)
+ track1->wrapping = track2->wrapping;
+ else if (track2->wrapping == UnknownWrapped)
+ track2->wrapping = track1->wrapping;
+ else
+ av_log(mxf->fc, AV_LOG_ERROR, "stream %d and stream %d have the same BodySID (%d) "
+ "with different wrapping\n", i, j, track1->body_sid);
+ }
+ }
+ }
+ }
+
ret = 0;
fail_and_free:
return ret;
goto end;
avio_seek(s->pb, file_size - length, SEEK_SET);
if (klv_read_packet(&klv, s->pb) < 0 ||
- !IS_KLV_KEY(klv.key, mxf_random_index_pack_key) ||
- klv.length != length - 20)
+ !IS_KLV_KEY(klv.key, mxf_random_index_pack_key))
+ goto end;
+ if (klv.next_klv != file_size || klv.length <= 4 || (klv.length - 4) % 12) {
+ av_log(s, AV_LOG_WARNING, "Invalid RIP KLV length\n");
goto end;
+ }
avio_skip(s->pb, klv.length - 12);
mxf->footer_partition = avio_rb64(s->pb);
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");
+ //goto fail should not be needed as no metadata sets will have been parsed yet
return AVERROR_INVALIDDATA;
}
avio_seek(s->pb, -14, SEEK_CUR);
if (!mxf->current_partition) {
av_log(mxf->fc, AV_LOG_ERROR, "found essence prior to first PartitionPack\n");
- return AVERROR_INVALIDDATA;
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
}
if (!mxf->current_partition->first_essence_klv.offset)
if (IS_KLV_KEY(klv.key, mxf_essence_element_key) ||
IS_KLV_KEY(klv.key, mxf_canopus_essence_element_key) ||
IS_KLV_KEY(klv.key, mxf_avid_essence_element_key)) {
- int body_sid = find_body_sid_by_offset(mxf, klv.offset);
+ int body_sid = find_body_sid_by_absolute_offset(mxf, klv.offset);
int index = mxf_get_stream_index(s, &klv, body_sid);
int64_t next_ofs;
AVStream *st;
} else {
if ((size = next_ofs - pos) <= 0) {
av_log(s, AV_LOG_ERROR, "bad size: %"PRId64"\n", size);
- ret = AVERROR_INVALIDDATA;
- goto skip;
+ mxf->current_klv_data = (KLVPacket){{0}};
+ return AVERROR_INVALIDDATA;
}
// We must not overread, because the next edit unit might be in another KLV
if (size > max_data_size)
for (i = 0; i < mxf->metadata_sets_count; i++) {
mxf_free_metadataset(mxf->metadata_sets + i, 1);
}
+ mxf->metadata_sets_count = 0;
av_freep(&mxf->partitions);
av_freep(&mxf->metadata_sets);
av_freep(&mxf->aesc);
return 0;
}
-static int mxf_probe(AVProbeData *p) {
+static int mxf_probe(const AVProbeData *p) {
const uint8_t *bufp = p->buf;
const uint8_t *end = p->buf + p->buf_size;