Commit f06f6daa authored by Paul B Mahol's avatar Paul B Mahol Committed by Luca Barbato

mxf: Parse random index pack

Get the last partition offset and use it when footer partition
offset is missing.

Footer partition may not be present and even if present footer
partition offset may not be set in any partition except last one.
Signed-off-by: 's avatarLuca Barbato <lu_zero@gentoo.org>
parent 570af382
...@@ -206,6 +206,7 @@ typedef struct { ...@@ -206,6 +206,7 @@ typedef struct {
struct AVAES *aesc; struct AVAES *aesc;
uint8_t *local_tags; uint8_t *local_tags;
int local_tags_count; int local_tags_count;
uint64_t last_partition;
uint64_t footer_partition; uint64_t footer_partition;
KLVPacket current_klv_data; KLVPacket current_klv_data;
int current_klv_index; int current_klv_index;
...@@ -245,6 +246,7 @@ static const uint8_t mxf_klv_key[] = { 0x06,0x0e,0x2b,0x ...@@ -245,6 +246,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_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_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_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 }; 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))) #define IS_KLV_KEY(x, y) (!memcmp(x, y, sizeof(y)))
...@@ -1850,25 +1852,30 @@ static int mxf_parse_handle_essence(MXFContext *mxf) ...@@ -1850,25 +1852,30 @@ static int mxf_parse_handle_essence(MXFContext *mxf)
if (mxf->parsing_backward) { if (mxf->parsing_backward) {
return mxf_seek_to_previous_partition(mxf); return mxf_seek_to_previous_partition(mxf);
} else { } else {
if (!mxf->footer_partition) { uint64_t offset = mxf->footer_partition ? mxf->footer_partition
av_dlog(mxf->fc, "no footer\n"); : mxf->last_partition;
if (!offset) {
av_dlog(mxf->fc, "no last partition\n");
return 0; return 0;
} }
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 */ /* remember where we were so we don't end up seeking further back than this */
mxf->last_forward_tell = avio_tell(pb); mxf->last_forward_tell = avio_tell(pb);
if (!pb->seekable) { 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; return -1;
} }
/* seek to footer partition and parse backward */ /* seek to last partition and parse backward */
if ((ret = avio_seek(pb, mxf->run_in + mxf->footer_partition, SEEK_SET)) < 0) { if ((ret = avio_seek(pb, mxf->run_in + offset, SEEK_SET)) < 0) {
av_log(mxf->fc, AV_LOG_ERROR, "failed to seek to footer @ 0x%"PRIx64" (%"PRId64") - partial file?\n", av_log(mxf->fc, AV_LOG_ERROR,
mxf->run_in + mxf->footer_partition, ret); "failed to seek to last partition @ 0x%" PRIx64
" (%"PRId64") - partial file?\n",
mxf->run_in + offset, ret);
return ret; return ret;
} }
...@@ -1998,6 +2005,34 @@ static void mxf_handle_small_eubc(AVFormatContext *s) ...@@ -1998,6 +2005,34 @@ static void mxf_handle_small_eubc(AVFormatContext *s)
mxf->edit_units_per_packet = 1920; 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) static int mxf_read_header(AVFormatContext *s)
{ {
MXFContext *mxf = s->priv_data; MXFContext *mxf = s->priv_data;
...@@ -2016,7 +2051,10 @@ static int mxf_read_header(AVFormatContext *s) ...@@ -2016,7 +2051,10 @@ static int mxf_read_header(AVFormatContext *s)
mxf->fc = s; mxf->fc = s;
mxf->run_in = avio_tell(s->pb); mxf->run_in = avio_tell(s->pb);
mxf_read_random_index_pack(s);
while (!s->pb->eof_reached) { while (!s->pb->eof_reached) {
const MXFMetadataReadTableEntry *metadata; const MXFMetadataReadTableEntry *metadata;
if (klv_read_packet(&klv, s->pb) < 0) { if (klv_read_packet(&klv, s->pb) < 0) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment