[libav-devel] [v5] qsvvpp: Fix to perform full init only when needed

Rogozhkin, Dmitry V dmitry.v.rogozhkin at intel.com
Wed Jul 25 02:56:59 CEST 2018


On Wed, 2018-07-18 at 14:07 +0200, Maxym Dmytrychenko wrote:
> Not used VPP sessions, like for hwupload/hwdownload handling,
> can increase CPU utilization and this patch fixes it.
> thank you,Joe, for the contribution.
> 
> Signed-off-by: Maxym Dmytrychenko <maxim.d33 at gmail.com>
> ---
>  libavutil/hwcontext_qsv.c | 72
> +++++++++++++++++++++++++++++++++++++++++------
>  1 file changed, 64 insertions(+), 8 deletions(-)
> 
> diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c
> index b3eb4a3ea..6bc2a38ff 100644
> --- a/libavutil/hwcontext_qsv.c
> +++ b/libavutil/hwcontext_qsv.c
> @@ -23,6 +23,10 @@
>  
>  #include "config.h"
>  
> +#if HAVE_PTHREADS
> +#include <pthread.h>
> +#endif
> +
>  #if CONFIG_VAAPI
>  #include "hwcontext_vaapi.h"
>  #endif
> @@ -56,7 +60,13 @@ typedef struct QSVDeviceContext {
>  
>  typedef struct QSVFramesContext {
>      mfxSession session_download;
> +    int session_download_init;
>      mfxSession session_upload;
> +    int session_upload_init;
> +#if HAVE_PTHREADS
> +    pthread_mutex_t session_lock;
> +    pthread_cond_t session_cond;
> +#endif
>  
>      AVBufferRef *child_frames_ref;
>      mfxFrameSurface1 *surfaces_internal;
> @@ -146,13 +156,20 @@ static void qsv_frames_uninit(AVHWFramesContext
> *ctx)
>          MFXVideoVPP_Close(s->session_download);
>          MFXClose(s->session_download);
>      }
> -    s->session_download = NULL;
> +    s->session_download      = NULL;
> +    s->session_download_init = 0;
>  
>      if (s->session_upload) {
>          MFXVideoVPP_Close(s->session_upload);
>          MFXClose(s->session_upload);
>      }
> -    s->session_upload = NULL;
> +    s->session_upload      = NULL;
> +    s->session_upload_init = 0;
> +
> +#if HAVE_PTHREADS
> +    pthread_mutex_destroy(&s->session_lock);
> +    pthread_cond_destroy(&s->session_cond);
> +#endif
>  
>      av_freep(&s->mem_ids);
>      av_freep(&s->surface_ptrs);
> @@ -535,13 +552,16 @@ static int qsv_frames_init(AVHWFramesContext
> *ctx)
>              s->mem_ids[i] = frames_hwctx->surfaces[i].Data.MemId;
>      }
>  
> -    ret = qsv_init_internal_session(ctx, &s->session_download, 0);
> -    if (ret < 0)
> -        return ret;
> +    s->session_download = NULL;
> +    s->session_upload   = NULL;
>  
> -    ret = qsv_init_internal_session(ctx, &s->session_upload, 1);
> -    if (ret < 0)
> -        return ret;
> +    s->session_download_init = 0;
> +    s->session_upload_init   = 0;
> +
> +#if HAVE_PTHREADS
> +    pthread_mutex_init(&s->session_lock, NULL);
> +    pthread_cond_init(&s->session_cond, NULL);
> +#endif
>  
>      return 0;
>  }
> @@ -741,6 +761,24 @@ static int
> qsv_transfer_data_from(AVHWFramesContext *ctx, AVFrame *dst,
>      mfxSyncPoint sync = NULL;
>      mfxStatus err;
>  
> +    while (!s->session_download_init && !s->session_download) {
> +#if HAVE_PTHREADS
> +        if (pthread_mutex_trylock(&s->session_lock) == 0) {
> +#endif
> +            qsv_init_internal_session(ctx, &s->session_download, 0);
> +            s->session_download_init = 1;
> +#if HAVE_PTHREADS
> +            pthread_cond_signal(&s->session_cond);
You don't need to signal under the mutex. More efficiently is to do
that without.
> +            pthread_mutex_unlock(&s->session_lock);
> +        }
> +        else {
> +            pthread_mutex_lock(&s->session_lock);
> +            pthread_cond_wait(&s->session_cond, &s->session_lock);
This is incorrect usage of condition variables. Look into example in
'man 3 pthread_cond_wait': you should check predicate under the mutex.
> +            pthread_mutex_unlock(&s->session_lock);
> +        }
> +#endif
> +    }
> +
As I said the above code is an example of incorrect usage of condition
variables. I believe this should be written in this way:

#if HAVE_PTHREADS
    if (pthread_mutex_trylock(&s->session_lock) == 0) {
#endif
        qsv_init_internal_session(ctx, &s->session_download, 0);
        s->session_download_init = 1;
#if HAVE_PTHREADS
        pthread_mutex_unlock(&s->session_lock);
        pthread_cond_signal(&s->session_cond);
    } else {
        pthread_mutex_lock(&s->session_lock);
        while (!s->session_download_init && !s->session_download) {
            pthread_cond_wait(&s->session_cond, &s->session_lock);
        }
        pthread_mutex_unlock(&s->session_lock);
    }
#endif

> 
>      if (!s->session_download) {
>          if (s->child_frames_ref)
>              return qsv_transfer_data_child(ctx, dst, src);
> @@ -788,6 +826,24 @@ static int
> qsv_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst,
>      mfxSyncPoint sync = NULL;
>      mfxStatus err;
>  
> +    while (!s->session_upload_init && !s->session_upload) {
> +#if HAVE_PTHREADS
> +        if (pthread_mutex_trylock(&s->session_lock) == 0) {
> +#endif
> +            qsv_init_internal_session(ctx, &s->session_upload, 1);
> +            s->session_upload_init = 1;
> +#if HAVE_PTHREADS
> +            pthread_cond_signal(&s->session_cond);
> +            pthread_mutex_unlock(&s->session_lock);
> +        }
> +        else {
> +            pthread_mutex_lock(&s->session_lock);
> +            pthread_cond_wait(&s->session_cond, &s->session_lock);
> +            pthread_mutex_unlock(&s->session_lock);
> +        }
> +#endif
> +    }
> +
Same comment as above. Correct code would be:

#if HAVE_PTHREADS
    if (pthread_mutex_trylock(&s->session_lock) == 0) {
#endif
        qsv_init_internal_session(ctx, &s->session_upload, 0);
        s->session_upload_init = 1;
#if HAVE_PTHREADS
        pthread_mutex_unlock(&s->session_lock);
        pthread_cond_signal(&s->session_cond);
    } else {
        pthread_mutex_lock(&s->session_lock);
        while (!s->session_upload_init && !s->session_upload) {
            pthread_cond_wait(&s->session_cond, &s->session_lock);
        }
        pthread_mutex_unlock(&s->session_lock);
    }
#endif

>      if (!s->session_upload) {
>          if (s->child_frames_ref)
>              return qsv_transfer_data_child(ctx, dst, src);


More information about the libav-devel mailing list