[FFmpeg-devel] [PATCH 1/4] mxfdec: Index table based seeking

Tomas Härdin tomas.hardin at codemill.se
Thu Sep 29 10:04:55 CEST 2011


On Wed, 2011-09-28 at 21:59 +0200, Georg Lippitsch wrote:
> Am 27.09.2011, 11:08 Uhr, schrieb Tomas Härdin <tomas.hardin at codemill.se>:
> 
> > I took the liberty of refactoring and fixing a few bugs in your patch,
> > in addition to rebasing my partition parsing code on top of it and
> > adding some patches to support the V210 sample at
> > http://titan.codemill.se/~tomhar/samples/multiindex/
> 
> Here is a patch that makes the XDCAM HD files from your sample-directory
> seekable.
> 
> These files were indeed weird. They had every index entry doubled, and  
> therefore the nb_index_entries value was twice the index_duration. Even  
> mxfdump only parsed the indices for half of the file.

That's Avid for you.. IIRC there's actually 2*n+1 entries - the last
entry contains the length of the essence.

> I therefore added some code to remove double entries. Also, the sizes of  
> the index entries were not calculated if nb_delta_entries was 0, which  
> I've added now.

Yeah, I think they like the 64k limit of the local set coding. Neither
do I TBH.

> ...
> +    current = 0;
>      for (i = 0; i < segment->nb_index_entries; i++) {
> +        int flag_entry;
> +        uint64_t stream_offset_entry;
>          avio_rb16(pb);  /* TemporalOffset and KeyFrameOffset */
> -        segment->flag_entries[i] = avio_r8(pb);
> -        segment->stream_offset_entries[i] = avio_rb64(pb);
> -        if (segment->slice_count) {
> -            AV_MALLOC_ARR_OR_ENOMEM(segment->slice_offset_entries[i], segment->slice_count);
> -
> -            for (j = 0; j < segment->slice_count; j++) {
> -                segment->slice_offset_entries[i][j] = avio_rb32(pb);
> +        flag_entry = avio_r8(pb);
> +        stream_offset_entry = avio_rb64(pb);
> +        if (current == 0 || segment->stream_offset_entries[current-1] != stream_offset_entry)

Might want a comment above this "if" explaining why this is needed.
Something like /* handle Avid index tables with duplicate entries */

> +        {
> +            segment->flag_entries[current] = flag_entry;
> +            segment->stream_offset_entries[current] = stream_offset_entry;
> +            if (segment->slice_count) {
> +                AV_MALLOC_ARR_OR_ENOMEM(segment->slice_offset_entries[current],
> +                                        segment->slice_count);
> +                
> +                for (j = 0; j < segment->slice_count; j++) {
> +                    segment->slice_offset_entries[current][j] = avio_rb32(pb);
> +                }
> +            }
> +            current++;
> +        } else {
> +            if (segment->slice_count) {
> +                for (j = 0; j < segment->slice_count; j++)
> +                    avio_rb32(pb);

avio_skip(pb, 4*segment->slice_count);

>              }
>          }
>  
>          avio_skip(pb, length - 11 - 4 * segment->slice_count);
>      }
> +    segment->nb_unique_index_entries = current;

If my earlier memory was right, then we might want to do something like:

/* account for Avid's index tables having an extra entry for the size */
segment->nb_unique_index_entries = current ==
segment->nb_index_entries ? current : current - 1;

>      return 0;
>  }
>  
> @@ -982,7 +999,7 @@ static int mxf_parse_index(MXFContext *mxf, int i, AVStream *st)
>          st->index_entries = av_realloc(st->index_entries, st->index_entries_allocated_size);
>          for (k = 0; k < duration; k++) {
>              AVIndexEntry *e = &st->index_entries[st->nb_index_entries];
> -            if (k < tableseg->nb_index_entries) {
> +            if (k < tableseg->nb_unique_index_entries) {
>                  e->pos = tableseg->stream_offset_entries[k];
>                  if (n_delta < tableseg->nb_delta_entries) {
>                      if (n_delta < tableseg->nb_delta_entries - 1) {
> @@ -1002,6 +1019,9 @@ static int mxf_parse_index(MXFContext *mxf, int i, AVStream *st)
>                      if (tableseg->slice[n_delta] > 0)
>                          e->pos += tableseg->slice_offset_entries[k][tableseg->slice[n_delta]-1];
>                      e->pos += tableseg->element_delta[n_delta];
> +                } else if (k < duration - 1) {
> +                    e->size = tableseg->stream_offset_entries[k+1] -
> +                        tableseg->stream_offset_entries[k];
>                  }
>                  e->flags = !(tableseg->flag_entries[k] & 0x30) ? AVINDEX_KEYFRAME : 0;
>              } else {
> @@ -1481,8 +1501,9 @@ static int mxf_read_close(AVFormatContext *s)
>              break;
>          case IndexTableSegment:
>              seg = (MXFIndexTableSegment *)mxf->metadata_sets[i];
> -            for (j = 0; j < seg->nb_index_entries; j++)
> -                av_freep(&seg->slice_offset_entries[j]);
> +            if (seg->slice_count)
> +                for (j = 0; j < seg->nb_index_entries; j++)
> +                    av_freep(&seg->slice_offset_entries[j]);

Unrelated? Also, aren't all of these NULL if !slice_count and thus av_freep() is OK?

/Tomas



More information about the ffmpeg-devel mailing list