On Sun, 3 Mar 2013 17:26:53 +0100, Janne Grunau <[email protected]> wrote:
> On 2013-02-13 19:50:38 +0100, Anton Khirnov wrote:
> > ---
> >  doc/multithreading.txt |    5 ++
> >  libavcodec/internal.h  |   15 +++++
> >  libavcodec/pthread.c   |  169 
> > ++++++++++++++++++++++++------------------------
> >  libavcodec/thread.h    |   20 ++++--
> >  libavcodec/utils.c     |   19 ++++++
> >  5 files changed, 139 insertions(+), 89 deletions(-)
> > 
> > diff --git a/doc/multithreading.txt b/doc/multithreading.txt
> > index b72bc16..9b27b10 100644
> > --- a/doc/multithreading.txt
> > +++ b/doc/multithreading.txt
> > @@ -57,6 +57,11 @@ which re-allocates them for other threads.
> >  Add CODEC_CAP_FRAME_THREADS to the codec capabilities. There will be very 
> > little
> >  speed gain at this point but it should work.
> >  
> > +If there are inter-frame dependencies, so the codec calls
> > +ff_thread_report/await_progress(), set AVCodecInternal.allocate_progress. 
> > The
> > +frames must then be freed with ff_thread_release_buffer().
> > +Otherwise leave it at zero and decode directly into the user-supplied 
> > frames.
> > +
> >  Call ff_thread_report_progress() after some part of the current picture 
> > has decoded.
> >  A good place to put this is where draw_horiz_band() is called - add this 
> > if it isn't
> >  called anywhere, as it's useful too and the implementation is trivial when 
> > you're
> > diff --git a/libavcodec/internal.h b/libavcodec/internal.h
> > index 8e64640..594bd1e 100644
> > --- a/libavcodec/internal.h
> > +++ b/libavcodec/internal.h
> > @@ -61,6 +61,21 @@ typedef struct AVCodecInternal {
> >       */
> >      int is_copy;
> >  
> > +    /**
> > +     * Whether to allocate progress for frame threading.
> > +     *
> > +     * The codec must set it to 1 if it uses 
> > ff_thread_await/report_progress(),
> > +     * then progress will be allocated in ff_thread_get_buffer(). The 
> > frames
> > +     * then MUST be freed with ff_thread_release_buffer().
> > +     *
> > +     * If the codec does not need to call the progress functions (there 
> > are no
> > +     * dependencies between the frames), it should leave this at 0. Then 
> > it can
> > +     * decode straight to the user-provided frames (which the user will 
> > then
> > +     * free with av_frame_unref()), there is no need to call
> > +     * ff_thread_release_buffer().
> > +     */
> > +    int allocate_progress;
> > +
> >  #if FF_API_OLD_DECODE_AUDIO
> >      /**
> >       * Internal sample count used by avcodec_encode_audio() to fabricate 
> > pts.
> > diff --git a/libavcodec/pthread.c b/libavcodec/pthread.c
> > index 82df03c..c2be1a4 100644
> > --- a/libavcodec/pthread.c
> > +++ b/libavcodec/pthread.c
> > @@ -52,6 +52,7 @@
> >  #include "avcodec.h"
> >  #include "internal.h"
> >  #include "thread.h"
> > +#include "libavutil/avassert.h"
> >  #include "libavutil/common.h"
> >  
> >  #if HAVE_PTHREADS
> > @@ -80,9 +81,6 @@ typedef struct ThreadContext {
> >      int done;
> >  } ThreadContext;
> >  
> > -/// Max number of frame buffers that can be allocated when using frame 
> > threads.
> > -#define MAX_BUFFERS (32+1)
> > -
> >  /**
> >   * Context used by codec threads and stored in their AVCodecContext 
> > thread_opaque.
> >   */
> > @@ -122,16 +120,12 @@ typedef struct PerThreadContext {
> >       * Array of frames passed to ff_thread_release_buffer().
> >       * Frames are released after all threads referencing them are finished.
> >       */
> > -    AVFrame released_buffers[MAX_BUFFERS];
> > -    int     num_released_buffers;
> > -
> > -    /**
> > -     * Array of progress values used by ff_thread_get_buffer().
> > -     */
> > -    int     progress[MAX_BUFFERS][2];
> > -    uint8_t progress_used[MAX_BUFFERS];
> > +    AVFrame *released_buffers;
> > +    int  num_released_buffers;
> > +    int      released_buffers_allocated;
> >  
> >      AVFrame *requested_frame;       ///< AVFrame the codec passed to 
> > get_buffer()
> > +    int      requested_flags;       ///< flags passed to get_buffer() for 
> > requested_frame
> >  } PerThreadContext;
> >  
> >  /**
> > @@ -459,8 +453,11 @@ static int update_context_from_user(AVCodecContext 
> > *dst, AVCodecContext *src)
> >      dst->flags          = src->flags;
> >  
> >      dst->draw_horiz_band= src->draw_horiz_band;
> > +    dst->get_buffer2    = src->get_buffer2;
> > +#if FF_API_GET_BUFFER
> >      dst->get_buffer     = src->get_buffer;
> >      dst->release_buffer = src->release_buffer;
> > +#endif
> >  
> >      dst->opaque   = src->opaque;
> >      dst->debug    = src->debug;
> > @@ -492,28 +489,21 @@ static int update_context_from_user(AVCodecContext 
> > *dst, AVCodecContext *src)
> >  #undef copy_fields
> >  }
> >  
> > -static void free_progress(AVFrame *f)
> > -{
> > -    PerThreadContext *p = f->owner->thread_opaque;
> > -    int *progress = f->thread_opaque;
> > -
> > -    p->progress_used[(progress - p->progress[0]) / 2] = 0;
> > -}
> > -
> >  /// Releases the buffers that this decoding thread was the last user of.
> >  static void release_delayed_buffers(PerThreadContext *p)
> >  {
> >      FrameThreadContext *fctx = p->parent;
> > +    AVFrame *f;
> >  
> >      while (p->num_released_buffers > 0) {
> > -        AVFrame *f;
> > -
> 
> unnecessary change, I won't mind though
> 

Undid locally.
This was unintentional/related to some previous versions of this commit.

> >          pthread_mutex_lock(&fctx->buffer_mutex);
> > +
> > +        // fix extended data in case the caller screwed it up
> > +        av_assert0(p->avctx->codec_type == AVMEDIA_TYPE_VIDEO);
> >          f = &p->released_buffers[--p->num_released_buffers];
> > -        free_progress(f);
> > -        f->thread_opaque = NULL;
> > +        f->extended_data = f->data;
> > +        av_frame_unref(f);
> >  
> > -        f->owner->release_buffer(f->owner, f);
> >          pthread_mutex_unlock(&fctx->buffer_mutex);
> >      }
> >  }
> > @@ -567,15 +557,18 @@ static int submit_packet(PerThreadContext *p, 
> > AVPacket *avpkt)
> >       * and it calls back to the client here.
> >       */
> >  
> > -    if (!p->avctx->thread_safe_callbacks &&
> > -         p->avctx->get_buffer != avcodec_default_get_buffer) {
> > +    if (!p->avctx->thread_safe_callbacks && (
> > +#if FF_API_GET_BUFFER
> > +         p->avctx->get_buffer ||
> > +#endif
> > +         p->avctx->get_buffer2 != avcodec_default_get_buffer2)) {
> >          while (p->state != STATE_SETUP_FINISHED && p->state != 
> > STATE_INPUT_READY) {
> >              pthread_mutex_lock(&p->progress_mutex);
> >              while (p->state == STATE_SETTING_UP)
> >                  pthread_cond_wait(&p->progress_cond, &p->progress_mutex);
> >  
> >              if (p->state == STATE_GET_BUFFER) {
> > -                p->result = ff_get_buffer(p->avctx, p->requested_frame);
> > +                p->result = ff_get_buffer(p->avctx, p->requested_frame, 
> > p->requested_flags);
> >                  p->state  = STATE_SETTING_UP;
> >                  pthread_cond_signal(&p->progress_cond);
> >              }
> > @@ -637,7 +630,7 @@ int ff_thread_decode_frame(AVCodecContext *avctx,
> >              pthread_mutex_unlock(&p->progress_mutex);
> >          }
> >  
> > -        *picture = p->frame;
> > +        av_frame_move_ref(picture, &p->frame);
> >          *got_picture_ptr = p->got_frame;
> >          picture->pkt_dts = p->avpkt.dts;
> >  
> > @@ -662,10 +655,10 @@ int ff_thread_decode_frame(AVCodecContext *avctx,
> >      return (p->result >= 0) ? avpkt->size : p->result;
> >  }
> >  
> > -void ff_thread_report_progress(AVFrame *f, int n, int field)
> > +void ff_thread_report_progress(ThreadFrame *f, int n, int field)
> >  {
> >      PerThreadContext *p;
> > -    int *progress = f->thread_opaque;
> > +    int *progress = f->progress ? (int*)f->progress->data : NULL;
> 
> the cast looks unecessary, please omit if that doesn't adds a warning.
> same for all following handling of progress

It is necessary, AVBufferRef.data is uint8_t* so it needs and explicit cast.

> 
> >      if (!progress || progress[field] >= n) return;
> >  
> > @@ -680,10 +673,10 @@ void ff_thread_report_progress(AVFrame *f, int n, int 
> > field)
> >      pthread_mutex_unlock(&p->progress_mutex);
> >  }
> >  
> > -void ff_thread_await_progress(AVFrame *f, int n, int field)
> > +void ff_thread_await_progress(ThreadFrame *f, int n, int field)
> >  {
> >      PerThreadContext *p;
> > -    int *progress = f->thread_opaque;
> > +    int *progress = f->progress ? (int*)f->progress->data : NULL;
> >  
> >      if (!progress || progress[field] >= n) return;
> >  
> > @@ -730,7 +723,7 @@ static void frame_thread_free(AVCodecContext *avctx, 
> > int thread_count)
> >  {
> >      FrameThreadContext *fctx = avctx->thread_opaque;
> >      const AVCodec *codec = avctx->codec;
> > -    int i;
> > +    int i, j;
> 
> unused variable j

Removed locally.

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

Reply via email to