On Sun, 3 Mar 2013 21:04:55 +0100, Janne Grunau <[email protected]> wrote:
> On 2013-02-13 19:51:19 +0100, Anton Khirnov wrote:
> > ---
> >  libavcodec/h264.c        |  310 
> > +++++++++++++++++++++++++++++-----------------
> >  libavcodec/h264.h        |    5 +
> >  libavcodec/h264_direct.c |    2 +-
> >  libavcodec/h264_refs.c   |   32 +++--
> >  4 files changed, 225 insertions(+), 124 deletions(-)
> > 
> > diff --git a/libavcodec/h264.c b/libavcodec/h264.c
> > index 339aecd..6f9263a 100644
> > --- a/libavcodec/h264.c
> > +++ b/libavcodec/h264.c
> > @@ -112,28 +112,25 @@ void ff_h264_draw_horiz_band(H264Context *h, int y, 
> > int height)
> >                         h->low_delay, h->mb_height * 16, h->mb_width * 16);
> >  }
> >  
> > -static void free_frame_buffer(H264Context *h, Picture *pic)
> > -{
> > -    ff_thread_release_buffer(h->avctx, &pic->f);
> > -    av_freep(&pic->f.hwaccel_picture_private);
> > -}
> > -
> > -static void free_picture(H264Context *h, Picture *pic)
> > +static void unref_picture(H264Context *h, Picture *pic)
> >  {
> > +    int off = offsetof(Picture, tf) + sizeof(pic->tf);
> 
> that's nicer than the offsetof use in mpegvideo
> 

??
It's exactly the same, no?

> >      int i;
> >  
> > -    if (pic->f.data[0])
> > -        free_frame_buffer(h, pic);
> > +    if (!pic->f.data[0])
> > +        return;
> > +
> > +    ff_thread_release_buffer(h->avctx, &pic->tf);
> > +    av_buffer_unref(&pic->hwaccel_priv_buf);
> >  
> > -    av_freep(&pic->qscale_table_base);
> > -    pic->qscale_table = NULL;
> > -    av_freep(&pic->mb_type_base);
> > -    pic->mb_type = NULL;
> > +    av_buffer_unref(&pic->qscale_table_buf);
> > +    av_buffer_unref(&pic->mb_type_buf);
> >      for (i = 0; i < 2; i++) {
> > -        av_freep(&pic->motion_val_base[i]);
> > -        av_freep(&pic->ref_index[i]);
> > -        pic->motion_val[i] = NULL;
> > +        av_buffer_unref(&pic->motion_val_buf[i]);
> > +        av_buffer_unref(&pic->ref_index_buf[i]);
> >      }
> > +
> > +    memset((uint8_t*)pic + off, 0, sizeof(*pic) - off);
> >  }
> >  
> >  static void release_unused_pictures(H264Context *h, int remove_current)
> > @@ -143,13 +140,72 @@ static void release_unused_pictures(H264Context *h, 
> > int remove_current)
> >      /* release non reference frames */
> >      for (i = 0; i < h->picture_count; i++) {
> >          if (h->DPB[i].f.data[0] && !h->DPB[i].reference &&
> > -            (!h->DPB[i].owner2 || h->DPB[i].owner2 == h) &&
> >              (remove_current || &h->DPB[i] != h->cur_pic_ptr)) {
> > -            free_frame_buffer(h, &h->DPB[i]);
> > +            unref_picture(h, &h->DPB[i]);
> >          }
> >      }
> >  }
> >  
> > +static int ref_picture(H264Context *h, Picture *dst, Picture *src)
> > +{
> > +    int ret, i;
> > +
> > +    av_assert0(!dst->f.buf[0]);
> > +    av_assert0(src->f.buf[0]);
> > +
> > +    src->tf.f = &src->f;
> 
> modifying the source picture here looks strange but I guess ok if it's
> too hard to guarantee src->tf.f == &src->f
> 
> > +    dst->tf.f = &dst->f;
> > +    ret = ff_thread_ref_frame(&dst->tf, &src->tf);
> > +    if (ret < 0)
> > +        goto fail;
> > +
> > +
> > +    dst->qscale_table_buf = av_buffer_ref(src->qscale_table_buf);
> > +    dst->mb_type_buf      = av_buffer_ref(src->mb_type_buf);
> > +    if (!dst->qscale_table_buf || !dst->mb_type_buf)
> > +        goto fail;
> > +    dst->qscale_table = src->qscale_table;
> > +    dst->mb_type      = src->mb_type;
> > +
> > +    for (i = 0; i < 2; i ++) {
> > +        dst->motion_val_buf[i] = av_buffer_ref(src->motion_val_buf[i]);
> > +        dst->ref_index_buf[i]  = av_buffer_ref(src->ref_index_buf[i]);
> > +        if (!dst->motion_val_buf[i] || !dst->ref_index_buf[i])
> > +            goto fail;
> > +        dst->motion_val[i] = src->motion_val[i];
> > +        dst->ref_index[i]  = src->ref_index[i];
> > +    }
> > +
> > +    if (src->hwaccel_picture_private) {
> > +        dst->hwaccel_priv_buf = av_buffer_ref(src->hwaccel_priv_buf);
> > +        if (!dst->hwaccel_priv_buf)
> > +            goto fail;
> > +        dst->hwaccel_picture_private = dst->hwaccel_priv_buf->data;
> > +    }
> > +
> > +    for (i = 0; i < 2; i++)
> > +        dst->field_poc[i] = src->field_poc[i];
> > +
> > +    memcpy(dst->ref_poc,   src->ref_poc,   sizeof(src->ref_poc));
> > +    memcpy(dst->ref_count, src->ref_count, sizeof(src->ref_count));
> > +
> > +    dst->poc                     = src->poc;
> > +    dst->frame_num               = src->frame_num;
> > +    dst->mmco_reset              = src->mmco_reset;
> > +    dst->pic_id                  = src->pic_id;
> > +    dst->long_ref                = src->long_ref;
> > +    dst->mbaff                   = src->mbaff;
> > +    dst->field_picture           = src->field_picture;
> > +    dst->needs_realloc           = src->needs_realloc;
> 
> We should be able to get rid of needs_realloc with refcounted frames but
> that can be done afterwards
> 
> > +    dst->reference               = src->reference;
> > +
> > +    return 0;
> > +fail:
> > +    unref_picture(h, dst);
> > +    return ret;
> > +}
> > +
> > +
> >  static int alloc_scratch_buffers(H264Context *h, int linesize)
> >  {
> >      int alloc_size = FFALIGN(FFABS(linesize) + 32, 32);
> > @@ -171,60 +227,86 @@ static int alloc_scratch_buffers(H264Context *h, int 
> > linesize)
> >      return 0;
> >  }
> >  
> > -static int alloc_picture(H264Context *h, Picture *pic)
> > +static int init_table_pools(H264Context *h)
> >  {
> >      const int big_mb_num    = h->mb_stride * (h->mb_height + 1) + 1;
> >      const int mb_array_size = h->mb_stride * h->mb_height;
> >      const int b4_stride     = h->mb_width * 4 + 1;
> >      const int b4_array_size = b4_stride * h->mb_height * 4;
> > +
> > +    h->qscale_table_pool = av_buffer_pool_init(big_mb_num + h->mb_stride,
> > +                                               av_buffer_allocz);
> > +    h->mb_type_pool      = av_buffer_pool_init((big_mb_num + h->mb_stride) 
> > *
> > +                                               sizeof(uint32_t), 
> > av_buffer_allocz);
> > +    h->motion_val_pool = av_buffer_pool_init(2 * (b4_array_size + 4) *
> > +                                             sizeof(int16_t), 
> > av_buffer_allocz);
> > +    h->ref_index_pool  = av_buffer_pool_init(4 * mb_array_size, 
> > av_buffer_allocz);
> > +
> > +    if (!h->qscale_table_pool || !h->mb_type_pool || !h->motion_val_pool ||
> > +        !h->ref_index_pool) {
> > +        av_buffer_pool_uninit(&h->qscale_table_pool);
> > +        av_buffer_pool_uninit(&h->mb_type_pool);
> > +        av_buffer_pool_uninit(&h->motion_val_pool);
> > +        av_buffer_pool_uninit(&h->ref_index_pool);
> > +        return AVERROR(ENOMEM);
> > +    }
> > +
> > +    return 0;
> > +}
> > +
> > +static int alloc_picture(H264Context *h, Picture *pic)
> > +{
> >      int i, ret = 0;
> >  
> >      av_assert0(!pic->f.data[0]);
> >  
> >      if (h->avctx->hwaccel) {
> >          const AVHWAccel *hwaccel = h->avctx->hwaccel;
> > -        av_assert0(!pic->f.hwaccel_picture_private);
> > +        av_assert0(!pic->hwaccel_picture_private);
> >          if (hwaccel->priv_data_size) {
> > -            pic->f.hwaccel_picture_private = 
> > av_mallocz(hwaccel->priv_data_size);
> > -            if (!pic->f.hwaccel_picture_private)
> > +            pic->hwaccel_priv_buf = 
> > av_buffer_allocz(hwaccel->priv_data_size);
> > +            if (!pic->hwaccel_priv_buf)
> >                  return AVERROR(ENOMEM);
> > +            pic->hwaccel_picture_private = pic->hwaccel_priv_buf->data;
> >          }
> >      }
> > -    ret = ff_thread_get_buffer(h->avctx, &pic->f);
> > +    pic->tf.f = &pic->f;
> > +    ret = ff_thread_get_buffer(h->avctx, &pic->tf, pic->reference ?
> > +                                                   AV_GET_BUFFER_FLAG_REF 
> > : 0);
> >      if (ret < 0)
> >          goto fail;
> >  
> >      h->linesize   = pic->f.linesize[0];
> >      h->uvlinesize = pic->f.linesize[1];
> >  
> > -    if (pic->qscale_table == NULL) {
> > -        FF_ALLOCZ_OR_GOTO(h->avctx, pic->qscale_table_base,
> > -                          (big_mb_num + h->mb_stride) * sizeof(uint8_t),
> > -                          fail)
> > -        FF_ALLOCZ_OR_GOTO(h->avctx, pic->mb_type_base,
> > -                          (big_mb_num + h->mb_stride) * sizeof(uint32_t),
> > -                          fail)
> > -        pic->mb_type = pic->mb_type_base + 2 * h->mb_stride + 1;
> > -        pic->qscale_table = pic->qscale_table_base + 2 * h->mb_stride + 1;
> > +    if (!h->qscale_table_pool) {
> > +        ret = init_table_pools(h);
> > +        if (ret < 0)
> > +            goto fail;
> > +    }
> >  
> > -        for (i = 0; i < 2; i++) {
> > -            FF_ALLOCZ_OR_GOTO(h->avctx, pic->motion_val_base[i],
> > -                              2 * (b4_array_size + 4) * sizeof(int16_t),
> > -                              fail)
> > -            pic->motion_val[i] = pic->motion_val_base[i] + 4;
> > -            FF_ALLOCZ_OR_GOTO(h->avctx, pic->ref_index[i],
> > -                              4 * mb_array_size * sizeof(uint8_t), fail)
> > -        }
> > -        pic->f.motion_subsample_log2 = 2;
> > +    pic->qscale_table_buf = av_buffer_alloc_pool(h->qscale_table_pool);
> > +    pic->mb_type_buf      = av_buffer_alloc_pool(h->mb_type_pool);
> > +    if (!pic->qscale_table_buf || !pic->mb_type_buf)
> > +        goto fail;
> >  
> > -        pic->f.qstride = h->mb_stride;
> > -    }
> > +    pic->mb_type      = (uint32_t*)pic->mb_type_buf->data + 2 * 
> > h->mb_stride + 1;
> > +    pic->qscale_table = pic->qscale_table_buf->data + 2 * h->mb_stride + 1;
> >  
> > -    pic->owner2 = h;
> > +    for (i = 0; i < 2; i++) {
> > +        pic->motion_val_buf[i] = av_buffer_alloc_pool(h->motion_val_pool);
> > +        pic->ref_index_buf[i]  = av_buffer_alloc_pool(h->ref_index_pool);
> > +        if (!pic->motion_val_buf[i] || !pic->ref_index_buf[i])
> > +            goto fail;
> > +
> > +        pic->motion_val[i] = (int16_t (*)[2])pic->motion_val_buf[i]->data 
> > + 4;
> > +        pic->ref_index[i]  = pic->ref_index_buf[i]->data;
> > +    }
> > +    pic->f.motion_subsample_log2 = 2;
> >  
> >      return 0;
> >  fail:
> > -    free_frame_buffer(h, pic);
> > +    unref_picture(h, pic);
> >      return (ret < 0) ? ret : AVERROR(ENOMEM);
> >  }
> >  
> > @@ -233,8 +315,7 @@ static inline int pic_is_unused(H264Context *h, Picture 
> > *pic)
> >      if (pic->f.data[0] == NULL)
> >          return 1;
> >      if (pic->needs_realloc && !(pic->reference & DELAYED_PIC_REF))
> > -        if (!pic->owner2 || pic->owner2 == h)
> > -            return 1;
> > +        return 1;
> >      return 0;
> >  }
> >  
> > @@ -242,17 +323,14 @@ static int find_unused_picture(H264Context *h)
> >  {
> >      int i;
> >  
> > -    for (i = h->picture_range_start; i < h->picture_range_end; i++) {
> > +    for (i = 0; i < h->picture_count; i++) {
> >          if (pic_is_unused(h, &h->DPB[i]))
> >              break;
> >      }
> > -    if (i == h->picture_range_end)
> > -        return AVERROR_INVALIDDATA;
> 
> Are you sure it's impossible that the loop doesn't break?

No I'm not, not sure why I removed that part.
Restored locally.

> 
> >      if (h->DPB[i].needs_realloc) {
> >          h->DPB[i].needs_realloc = 0;
> > -        free_picture(h, &h->DPB[i]);
> > -        avcodec_get_frame_defaults(&h->DPB[i].f);
> > +        unref_picture(h, &h->DPB[i]);
> >      }
> >  
> >      return i;
> > @@ -503,7 +581,7 @@ static inline void get_lowest_part_y(H264Context *h, 
> > int refs[2][48], int n,
> >          // Error resilience puts the current picture in the ref list.
> >          // Don't try to wait on these as it will cause a deadlock.
> >          // Fields can wait on each other, though.
> > -        if (ref->f.thread_opaque   != h->cur_pic.f.thread_opaque ||
> > +        if (ref->tf.progress->data   != h->cur_pic.tf.progress->data ||
> 
> it gets even uglier, I'll look if there's a proper fix for this
> 
> >              (ref->reference & 3) != h->picture_structure) {
> >              my = get_lowest_part_list_y(h, ref, n, height, y_offset, 0);
> >              if (refs[0][ref_n] < 0)
> > @@ -516,7 +594,7 @@ static inline void get_lowest_part_y(H264Context *h, 
> > int refs[2][48], int n,
> >          int ref_n    = h->ref_cache[1][scan8[n]];
> >          Picture *ref = &h->ref_list[1][ref_n];
> >  
> > -        if (ref->f.thread_opaque   != h->cur_pic.f.thread_opaque ||
> > +        if (ref->tf.progress->data != h->cur_pic.tf.progress->data ||
> >              (ref->reference & 3) != h->picture_structure) {
> >              my = get_lowest_part_list_y(h, ref, n, height, y_offset, 1);
> >              if (refs[1][ref_n] < 0)
> > @@ -614,24 +692,24 @@ static void await_references(H264Context *h)
> >                  nrefs[list]--;
> >  
> >                  if (!FIELD_PICTURE && ref_field_picture) { // frame 
> > referencing two fields
> > -                    ff_thread_await_progress(&ref_pic->f,
> > +                    ff_thread_await_progress(&ref_pic->tf,
> >                                               FFMIN((row >> 1) - !(row & 1),
> >                                                     pic_height - 1),
> >                                               1);
> > -                    ff_thread_await_progress(&ref_pic->f,
> > +                    ff_thread_await_progress(&ref_pic->tf,
> >                                               FFMIN((row >> 1), pic_height 
> > - 1),
> >                                               0);
> >                  } else if (FIELD_PICTURE && !ref_field_picture) { // field 
> > referencing one field of a frame
> > -                    ff_thread_await_progress(&ref_pic->f,
> > +                    ff_thread_await_progress(&ref_pic->tf,
> >                                               FFMIN(row * 2 + ref_field,
> >                                                     pic_height - 1),
> >                                               0);
> >                  } else if (FIELD_PICTURE) {
> > -                    ff_thread_await_progress(&ref_pic->f,
> > +                    ff_thread_await_progress(&ref_pic->tf,
> >                                               FFMIN(row, pic_height - 1),
> >                                               ref_field);
> >                  } else {
> > -                    ff_thread_await_progress(&ref_pic->f,
> > +                    ff_thread_await_progress(&ref_pic->tf,
> >                                               FFMIN(row, pic_height - 1),
> >                                               0);
> >                  }
> > @@ -951,9 +1029,14 @@ static void free_tables(H264Context *h, int free_rbsp)
> >      av_freep(&h->mb2b_xy);
> >      av_freep(&h->mb2br_xy);
> >  
> > +    av_buffer_pool_uninit(&h->qscale_table_pool);
> > +    av_buffer_pool_uninit(&h->mb_type_pool);
> > +    av_buffer_pool_uninit(&h->motion_val_pool);
> > +    av_buffer_pool_uninit(&h->ref_index_pool);
> > +
> >      if (free_rbsp) {
> > -        for (i = 0; i < h->picture_count && !h->avctx->internal->is_copy; 
> > i++)
> > -            free_picture(h, &h->DPB[i]);
> > +        for (i = 0; i < h->picture_count; i++)
> > +            unref_picture(h, &h->DPB[i]);
> >          av_freep(&h->DPB);
> >          h->picture_count = 0;
> >      } else if (h->DPB) {
> > @@ -1106,7 +1189,7 @@ int ff_h264_alloc_tables(H264Context *h)
> >          init_dequant_tables(h);
> >  
> >      if (!h->DPB) {
> > -        h->picture_count = MAX_PICTURE_COUNT * FFMAX(1, 
> > h->avctx->thread_count);
> > +        h->picture_count = MAX_PICTURE_COUNT;
> 
> we can get rid picture_count if it's a constant

Right, replaced it with MAX_PICTURE_COUNT everywhere.

> 
> >          h->DPB = av_mallocz_array(h->picture_count, sizeof(*h->DPB));
> >          if (!h->DPB)
> >              return AVERROR(ENOMEM);
> > @@ -1306,8 +1389,6 @@ av_cold int ff_h264_decode_init(AVCodecContext *avctx)
> >      common_init(h);
> >  
> >      h->picture_structure   = PICT_FRAME;
> > -    h->picture_range_start = 0;
> > -    h->picture_range_end   = MAX_PICTURE_COUNT;
> >      h->slice_context_count = 1;
> >      h->workaround_bugs     = avctx->workaround_bugs;
> >      h->flags               = avctx->flags;
> > @@ -1347,6 +1428,8 @@ av_cold int ff_h264_decode_init(AVCodecContext *avctx)
> >          h->low_delay           = 0;
> >      }
> >  
> > +    avctx->internal->allocate_progress = 1;
> > +
> >      return 0;
> >  }
> >  
> > @@ -1398,6 +1481,8 @@ static int decode_init_thread_copy(AVCodecContext 
> > *avctx)
> >  
> >      h->context_initialized = 0;
> >  
> > +    avctx->internal->allocate_progress = 1;
> > +
> 
> unnecessary
> 

Removed

> >      return 0;
> >  }
> >  
> > @@ -1414,7 +1499,7 @@ static int 
> > decode_update_thread_context(AVCodecContext *dst,
> >  {
> >      H264Context *h = dst->priv_data, *h1 = src->priv_data;
> >      int inited = h->context_initialized, err = 0;
> > -    int i;
> > +    int i, ret;
> >  
> >      if (dst == src || !h1->context_initialized)
> >          return 0;
> > @@ -1468,12 +1553,16 @@ static int 
> > decode_update_thread_context(AVCodecContext *dst,
> >          memset(&h->me, 0, sizeof(h->me));
> >          h->context_initialized = 0;
> >  
> > -        h->picture_range_start  += MAX_PICTURE_COUNT;
> > -        h->picture_range_end    += MAX_PICTURE_COUNT;
> > +        memset(&h->cur_pic, 0, sizeof(h->cur_pic));
> > +        avcodec_get_frame_defaults(&h->cur_pic.f);
> > +        h->cur_pic.tf.f = &h->cur_pic.f;
> >  
> >          h->avctx = dst;
> >          h->DPB   = NULL;
> > -        h->cur_pic.f.extended_data = h->cur_pic.f.data;
> > +        h->qscale_table_pool = NULL;
> > +        h->mb_type_pool = NULL;
> > +        h->ref_index_pool = NULL;
> > +        h->motion_val_pool = NULL;
> >  
> >          if (ff_h264_alloc_tables(h) < 0) {
> >              av_log(dst, AV_LOG_ERROR, "Could not allocate memory for 
> > h264\n");
> > @@ -1507,15 +1596,17 @@ static int 
> > decode_update_thread_context(AVCodecContext *dst,
> >      h->data_partitioning    = h1->data_partitioning;
> >      h->low_delay            = h1->low_delay;
> >  
> > -    memcpy(h->DPB, h1->DPB, h1->picture_count * sizeof(*h1->DPB));
> > -
> > -    // reset s->picture[].f.extended_data to s->picture[].f.data
> > -    for (i = 0; i < h->picture_count; i++)
> > -        h->DPB[i].f.extended_data = h->DPB[i].f.data;
> > +    for (i = 0; i < h->picture_count; i++) {
> > +        unref_picture(h, &h->DPB[i]);
> > +        if (h1->DPB[i].f.data[0] &&
> > +            (ret = ref_picture(h, &h->DPB[i], &h1->DPB[i])) < 0)
> > +            return ret;
> > +    }
> >  
> >      h->cur_pic_ptr     = REBASE_PICTURE(h1->cur_pic_ptr, h, h1);
> > -    h->cur_pic = h1->cur_pic;
> > -    h->cur_pic.f.extended_data = h->cur_pic.f.data;
> > +    unref_picture(h, &h->cur_pic);
> > +    if ((ret = ref_picture(h, &h->cur_pic, &h1->cur_pic)) < 0)
> > +        return ret;
> >  
> >      h->workaround_bugs = h1->workaround_bugs;
> >      h->low_delay       = h1->low_delay;
> > @@ -1613,8 +1704,9 @@ int ff_h264_frame_start(H264Context *h)
> >          return ret;
> >  
> >      h->cur_pic_ptr = pic;
> > -    h->cur_pic     = *h->cur_pic_ptr;
> > -    h->cur_pic.f.extended_data = h->cur_pic.f.data;
> > +    unref_picture(h, &h->cur_pic);
> > +    if ((ret = ref_picture(h, &h->cur_pic, h->cur_pic_ptr)) < 0)
> > +        return ret;
> >  
> >      ff_er_frame_start(&h->er);
> >  
> > @@ -1681,7 +1773,6 @@ static void decode_postinit(H264Context *h, int 
> > setup_finished)
> >      int i, pics, out_of_order, out_idx;
> >      int invalid = 0, cnt = 0;
> >  
> > -    h->cur_pic_ptr->f.qscale_type = FF_QSCALE_TYPE_H264;
> >      h->cur_pic_ptr->f.pict_type   = h->pict_type;
> >  
> >      if (h->next_output_pic)
> > @@ -1854,7 +1945,6 @@ static void decode_postinit(H264Context *h, int 
> > setup_finished)
> >          out->reference &= ~DELAYED_PIC_REF;
> >          // for frame threading, the owner must be the second field's 
> > thread or
> >          // else the first thread can release the picture and reuse it 
> > unsafely
> > -        out->owner2       = h;
> >          for (i = out_idx; h->delayed_pic[i]; i++)
> >              h->delayed_pic[i] = h->delayed_pic[i + 1];
> >      }
> > @@ -2477,11 +2567,10 @@ static void flush_dpb(AVCodecContext *avctx)
> >  
> >      flush_change(h);
> >  
> > -    for (i = 0; i < h->picture_count; i++) {
> > -        if (h->DPB[i].f.data[0])
> > -            free_frame_buffer(h, &h->DPB[i]);
> > -    }
> > +    for (i = 0; i < h->picture_count; i++)
> > +        unref_picture(h, &h->DPB[i]);
> >      h->cur_pic_ptr = NULL;
> > +    unref_picture(h, &h->cur_pic);
> >  
> >      h->mb_x = h->mb_y = 0;
> >  
> > @@ -2614,7 +2703,7 @@ static int field_end(H264Context *h, int in_setup)
> >      h->mb_y = 0;
> >  
> >      if (!in_setup && !h->droppable)
> > -        ff_thread_report_progress(&h->cur_pic_ptr->f, INT_MAX,
> > +        ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX,
> >                                    h->picture_structure == 
> > PICT_BOTTOM_FIELD);
> >  
> >      if (CONFIG_H264_VDPAU_DECODER &&
> > @@ -2974,9 +3063,8 @@ static int decode_slice_header(H264Context *h, 
> > H264Context *h0)
> >  
> >          h0->current_slice = 0;
> >          if (!h0->first_field) {
> > -            if (h->cur_pic_ptr && !h->droppable &&
> > -                h->cur_pic_ptr->owner2 == h) {
> > -                ff_thread_report_progress(&h->cur_pic_ptr->f, INT_MAX,
> > +            if (h->cur_pic_ptr && !h->droppable) {
> > +                ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX,
> >                                            h->picture_structure == 
> > PICT_BOTTOM_FIELD);
> >              }
> >              h->cur_pic_ptr = NULL;
> > @@ -3201,8 +3289,8 @@ static int decode_slice_header(H264Context *h, 
> > H264Context *h0)
> >              assert(h0->cur_pic_ptr->reference != DELAYED_PIC_REF);
> >  
> >              /* Mark old field/frame as completed */
> > -            if (!last_pic_droppable && h0->cur_pic_ptr->owner2 == h0) {
> > -                ff_thread_report_progress(&h0->cur_pic_ptr->f, INT_MAX,
> > +            if (!last_pic_droppable) {
> > +                ff_thread_report_progress(&h0->cur_pic_ptr->tf, INT_MAX,
> >                                            last_pic_structure == 
> > PICT_BOTTOM_FIELD);
> >              }
> >  
> > @@ -3211,7 +3299,7 @@ static int decode_slice_header(H264Context *h, 
> > H264Context *h0)
> >                  /* Previous field is unmatched. Don't display it, but let 
> > it
> >                   * remain for reference if marked as such. */
> >                  if (!last_pic_droppable && last_pic_structure != 
> > PICT_FRAME) {
> > -                    ff_thread_report_progress(&h0->cur_pic_ptr->f, INT_MAX,
> > +                    ff_thread_report_progress(&h0->cur_pic_ptr->tf, 
> > INT_MAX,
> >                                                last_pic_structure == 
> > PICT_TOP_FIELD);
> >                  }
> >              } else {
> > @@ -3221,7 +3309,7 @@ static int decode_slice_header(H264Context *h, 
> > H264Context *h0)
> >                       * pair. Throw away previous field except for reference
> >                       * purposes. */
> >                      if (!last_pic_droppable && last_pic_structure != 
> > PICT_FRAME) {
> > -                        ff_thread_report_progress(&h0->cur_pic_ptr->f, 
> > INT_MAX,
> > +                        ff_thread_report_progress(&h0->cur_pic_ptr->tf, 
> > INT_MAX,
> >                                                    last_pic_structure == 
> > PICT_TOP_FIELD);
> >                      }
> >                  } else {
> > @@ -3244,14 +3332,6 @@ static int decode_slice_header(H264Context *h, 
> > H264Context *h0)
> >                          h->droppable         = last_pic_droppable;
> >                          return AVERROR_PATCHWELCOME;
> >                      }
> > -
> > -                    /* Take ownership of this buffer. Note that if another 
> > thread owned
> > -                     * the first field of this buffer, we're not operating 
> > on that pointer,
> > -                     * so the original thread is still responsible for 
> > reporting progress
> > -                     * on that first field (or if that was us, we just did 
> > that above).
> > -                     * By taking ownership, we assign responsibility to 
> > ourselves to
> > -                     * report progress on the second field. */
> > -                    h0->cur_pic_ptr->owner2 = h0;
> >                  }
> >              }
> >          }
> > @@ -3266,8 +3346,8 @@ static int decode_slice_header(H264Context *h, 
> > H264Context *h0)
> >              h->prev_frame_num++;
> >              h->prev_frame_num %= 1 << h->sps.log2_max_frame_num;
> >              h->cur_pic_ptr->frame_num = h->prev_frame_num;
> > -            ff_thread_report_progress(&h->cur_pic_ptr->f, INT_MAX, 0);
> > -            ff_thread_report_progress(&h->cur_pic_ptr->f, INT_MAX, 1);
> > +            ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, 0);
> > +            ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, 1);
> >              if ((ret = ff_generate_sliding_window_mmcos(h, 1)) < 0 &&
> >                  h->avctx->err_recognition & AV_EF_EXPLODE)
> >                  return ret;
> > @@ -3561,16 +3641,16 @@ static int decode_slice_header(H264Context *h, 
> > H264Context *h0)
> >          int *ref2frm = h->ref2frm[h->slice_num & (MAX_SLICES - 1)][j];
> >          for (i = 0; i < 16; i++) {
> >              id_list[i] = 60;
> > -            if (h->ref_list[j][i].f.data[0]) {
> > +            if (i < h->ref_count[j] && h->ref_list[j][i].f.buf[0]) {
> >                  int k;
> > -                uint8_t *base = h->ref_list[j][i].f.base[0];
> > +                AVBuffer *buf = h->ref_list[j][i].f.buf[0]->buffer;
> >                  for (k = 0; k < h->short_ref_count; k++)
> > -                    if (h->short_ref[k]->f.base[0] == base) {
> > +                    if (h->short_ref[k]->f.buf[0]->buffer == buf) {
> 
> av_buffer_are_equal() to make it less ugly? or should the h264 decoder
> use something to keep track of pictures. something to fix later

I'm not convinced such a function would make it much prettier.
Maybe some other id for testing equality...?


-- 
Anton Khirnov
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to