[FFmpeg-devel] [PATCH] avformat/mxfdec; parse random index pack to get last partition offset and use it when footer partition offset is missing
Paul B Mahol
onemda at gmail.com
Fri Oct 18 15:13:59 CEST 2013
Footer partition may not be present and even if present it may not be set
in any partition except last one.
Signed-off-by: Paul B Mahol <onemda at gmail.com>
---
libavformat/mxfdec.c | 56 +++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 45 insertions(+), 11 deletions(-)
diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c
index 72faf4c..d0cbeea 100644
--- a/libavformat/mxfdec.c
+++ b/libavformat/mxfdec.c
@@ -213,6 +213,7 @@ typedef struct {
struct AVAES *aesc;
uint8_t *local_tags;
int local_tags_count;
+ uint64_t last_partition;
uint64_t footer_partition;
KLVPacket current_klv_data;
int current_klv_index;
@@ -254,6 +255,7 @@ static const uint8_t mxf_klv_key[] = { 0x06,0x0e,0x2b,0x
static const uint8_t mxf_crypto_source_container_ul[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x09,0x06,0x01,0x01,0x02,0x02,0x00,0x00,0x00 };
static const uint8_t mxf_encrypted_triplet_key[] = { 0x06,0x0e,0x2b,0x34,0x02,0x04,0x01,0x07,0x0d,0x01,0x03,0x01,0x02,0x7e,0x01,0x00 };
static const uint8_t mxf_encrypted_essence_container[] = { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x07,0x0d,0x01,0x03,0x01,0x02,0x0b,0x01,0x00 };
+static const uint8_t mxf_random_index_pack_key[] = { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0D,0x01,0x02,0x01,0x01,0x11,0x01,0x00 };
static const uint8_t mxf_sony_mpeg4_extradata[] = { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0e,0x06,0x06,0x02,0x02,0x01,0x00,0x00 };
#define IS_KLV_KEY(x, y) (!memcmp(x, y, sizeof(y)))
@@ -1852,31 +1854,33 @@ static int mxf_parse_handle_essence(MXFContext *mxf)
if (mxf->parsing_backward) {
return mxf_seek_to_previous_partition(mxf);
- } else {
- if (!mxf->footer_partition) {
- av_dlog(mxf->fc, "no footer\n");
- return 0;
- }
+ } else if (mxf->footer_partition || mxf->last_partition){
+ uint64_t offset;
+
+ offset = mxf->footer_partition ? mxf->footer_partition : mxf->last_partition;
- av_dlog(mxf->fc, "seeking to footer\n");
+ av_dlog(mxf->fc, "seeking to last partition\n");
/* remember where we were so we don't end up seeking further back than this */
mxf->last_forward_tell = avio_tell(pb);
if (!pb->seekable) {
- av_log(mxf->fc, AV_LOG_INFO, "file is not seekable - not parsing footer\n");
+ av_log(mxf->fc, AV_LOG_INFO, "file is not seekable - not parsing last partition\n");
return -1;
}
- /* seek to footer partition and parse backward */
- if ((ret = avio_seek(pb, mxf->run_in + mxf->footer_partition, SEEK_SET)) < 0) {
- av_log(mxf->fc, AV_LOG_ERROR, "failed to seek to footer @ 0x%"PRIx64" (%"PRId64") - partial file?\n",
- mxf->run_in + mxf->footer_partition, ret);
+ /* seek to last partition and parse backward */
+ if ((ret = avio_seek(pb, mxf->run_in + offset, SEEK_SET)) < 0) {
+ av_log(mxf->fc, AV_LOG_ERROR, "failed to seek to last partition @ 0x%"PRIx64" (%"PRId64") - partial file?\n",
+ mxf->run_in + offset, ret);
return ret;
}
mxf->current_partition = NULL;
mxf->parsing_backward = 1;
+ } else {
+ av_dlog(mxf->fc, "can't find last partition\n");
+ return 0;
}
return 1;
@@ -1968,6 +1972,34 @@ static void mxf_handle_small_eubc(AVFormatContext *s)
mxf->edit_units_per_packet = 1920;
}
+static void mxf_read_random_index_pack(AVFormatContext *s)
+{
+ MXFContext *mxf = s->priv_data;
+ uint32_t length;
+ int64_t file_size;
+ KLVPacket klv;
+
+ if (!s->pb->seekable)
+ return;
+
+ file_size = avio_size(s->pb);
+ avio_seek(s->pb, file_size - 4, SEEK_SET);
+ length = avio_rb32(s->pb);
+ if (length <= 32 || length >= FFMIN(file_size, INT_MAX))
+ 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)
+ goto end;
+
+ avio_skip(s->pb, klv.length - 12);
+ mxf->last_partition = avio_rb64(s->pb);
+
+end:
+ avio_seek(s->pb, mxf->run_in, SEEK_SET);
+}
+
static int mxf_read_header(AVFormatContext *s)
{
MXFContext *mxf = s->priv_data;
@@ -1986,6 +2018,8 @@ static int mxf_read_header(AVFormatContext *s)
mxf->fc = s;
mxf->run_in = avio_tell(s->pb);
+ mxf_read_random_index_pack(s);
+
while (!url_feof(s->pb)) {
const MXFMetadataReadTableEntry *metadata;
--
1.7.11.2
More information about the ffmpeg-devel
mailing list