[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