|
|
|
@@ -89,6 +89,7 @@ typedef struct { |
|
|
|
int64_t header_byte_count; |
|
|
|
int64_t index_byte_count; |
|
|
|
int pack_length; |
|
|
|
int64_t pack_ofs; ///< absolute offset of pack in file, including run-in |
|
|
|
} MXFPartition; |
|
|
|
|
|
|
|
typedef struct { |
|
|
|
@@ -472,6 +473,7 @@ static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size |
|
|
|
memset(partition, 0, sizeof(*partition)); |
|
|
|
mxf->partitions_count++; |
|
|
|
partition->pack_length = avio_tell(pb) - klv_offset + size; |
|
|
|
partition->pack_ofs = klv_offset; |
|
|
|
|
|
|
|
switch(uid[13]) { |
|
|
|
case 2: |
|
|
|
@@ -547,6 +549,7 @@ static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size |
|
|
|
partition->index_sid, partition->body_sid); |
|
|
|
|
|
|
|
/* sanity check PreviousPartition if set */ |
|
|
|
//NOTE: this isn't actually enough, see mxf_seek_to_previous_partition() |
|
|
|
if (partition->previous_partition && |
|
|
|
mxf->run_in + partition->previous_partition >= klv_offset) { |
|
|
|
av_log(mxf->fc, AV_LOG_ERROR, |
|
|
|
@@ -2076,23 +2079,53 @@ static int mxf_parse_klv(MXFContext *mxf, KLVPacket klv, MXFMetadataReadFunc *re |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Seeks to the previous partition, if possible |
|
|
|
* Seeks to the previous partition and parses it, if possible |
|
|
|
* @return <= 0 if we should stop parsing, > 0 if we should keep going |
|
|
|
*/ |
|
|
|
static int mxf_seek_to_previous_partition(MXFContext *mxf) |
|
|
|
{ |
|
|
|
AVIOContext *pb = mxf->fc->pb; |
|
|
|
KLVPacket klv; |
|
|
|
int64_t current_partition_ofs; |
|
|
|
int ret; |
|
|
|
|
|
|
|
if (!mxf->current_partition || |
|
|
|
mxf->run_in + mxf->current_partition->previous_partition <= mxf->last_forward_tell) |
|
|
|
return 0; /* we've parsed all partitions */ |
|
|
|
|
|
|
|
/* seek to previous partition */ |
|
|
|
current_partition_ofs = mxf->current_partition->pack_ofs; //includes run-in |
|
|
|
avio_seek(pb, mxf->run_in + mxf->current_partition->previous_partition, SEEK_SET); |
|
|
|
mxf->current_partition = NULL; |
|
|
|
|
|
|
|
av_dlog(mxf->fc, "seeking to previous partition\n"); |
|
|
|
|
|
|
|
/* Make sure this is actually a PartitionPack, and if so parse it. |
|
|
|
* See deadlock2.mxf |
|
|
|
*/ |
|
|
|
if ((ret = klv_read_packet(&klv, pb)) < 0) { |
|
|
|
av_log(mxf->fc, AV_LOG_ERROR, "failed to read PartitionPack KLV\n"); |
|
|
|
return ret; |
|
|
|
} |
|
|
|
|
|
|
|
if (!mxf_is_partition_pack_key(klv.key)) { |
|
|
|
av_log(mxf->fc, AV_LOG_ERROR, "PreviousPartition @ %" PRIx64 " isn't a PartitionPack\n", klv.offset); |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
|
|
|
|
/* We can't just check ofs >= current_partition_ofs because PreviousPartition |
|
|
|
* can point to just before the current partition, causing klv_read_packet() |
|
|
|
* to sync back up to it. See deadlock3.mxf |
|
|
|
*/ |
|
|
|
if (klv.offset >= current_partition_ofs) { |
|
|
|
av_log(mxf->fc, AV_LOG_ERROR, "PreviousPartition for PartitionPack @ %" |
|
|
|
PRIx64 " indirectly points to itself\n", current_partition_ofs); |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
|
|
|
|
if ((ret = mxf_parse_klv(mxf, klv, mxf_read_partition_pack, 0, 0)) < 0) |
|
|
|
return ret; |
|
|
|
|
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
|