[FFmpeg-devel] [PATCH] avformat/mxfdec; parse random index pack to get last partition offset and use it when footer partition offset is missing
Robert Krüger
krueger at lesspain.de
Fri Oct 18 16:05:00 CEST 2013
On Fri, Oct 18, 2013 at 3:13 PM, Paul B Mahol <onemda at gmail.com> wrote:
> 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
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Verified to fix broken packet timestamps returned for a file created
using the Sony XDCAM Transfer Tool export plugin from Final Cut 7.
More information about the ffmpeg-devel
mailing list