[vlc-devel] [PATCH 4/4] avcodec: pass the number of threads used by avcodec to the HW acceleration back-ends

Felix Abecassis felix.abecassis at gmail.com
Tue Mar 4 15:22:03 CET 2014


The number of threads impacts the number of surfaces that should be
allocated by the HW acceleration backend. If not enough surfaces are
allocated, the VAAPI and DXVA modules returned the oldest surface
currently in used. This technique can cause many visual glitches with
some samples. The number of allocated surfaces now scales with the
number of threads used by avcodec.

Fix #9887
---
 modules/codec/avcodec/dxva2.c | 10 +++++++---
 modules/codec/avcodec/va.c    |  9 +++++----
 modules/codec/avcodec/va.h    |  3 ++-
 modules/codec/avcodec/vaapi.c | 12 ++++++------
 modules/codec/avcodec/video.c |  2 +-
 modules/hw/vdpau/avcodec.c    |  6 ++++--
 6 files changed, 25 insertions(+), 17 deletions(-)

diff --git a/modules/codec/avcodec/dxva2.c b/modules/codec/avcodec/dxva2.c
index c1d1a4a..b78c9d1 100644
--- a/modules/codec/avcodec/dxva2.c
+++ b/modules/codec/avcodec/dxva2.c
@@ -51,7 +51,7 @@
 #include "va.h"
 #include "../../video_chroma/copy.h"
 
-static int Open(vlc_va_t *, int, const es_format_t *);
+static int Open(vlc_va_t *, int, const es_format_t *, int);
 static void Close(vlc_va_t *);
 
 vlc_module_begin()
@@ -283,6 +283,8 @@ struct vlc_va_sys_t
     int          surface_height;
     vlc_fourcc_t surface_chroma;
 
+    int          thread_count;
+
     vlc_va_surface_t surface[VA_DXVA2_MAX_SURFACE_COUNT];
     LPDIRECT3DSURFACE9 hw_surface[VA_DXVA2_MAX_SURFACE_COUNT];
 };
@@ -492,7 +494,7 @@ static void Close(vlc_va_t *external)
     free(va);
 }
 
-static int Open(vlc_va_t *external, int codec_id, const es_format_t *fmt)
+static int Open(vlc_va_t *external, int codec_id, const es_format_t *fmt, int thread_count)
 {
     vlc_va_dxva2_t *va = calloc(1, sizeof(*va));
     if (!va)
@@ -540,6 +542,8 @@ static int Open(vlc_va_t *external, int codec_id, const es_format_t *fmt)
         goto error;
     }
 
+    va->thread_count = thread_count;
+
     /* TODO print the hardware name/vendor for debugging purposes */
     external->description = DxDescribe(va);
     external->pix_fmt = PIX_FMT_DXVA2_VLD;
@@ -858,7 +862,7 @@ static int DxCreateVideoDecoder(vlc_va_dxva2_t *va,
     int surface_count;
     switch (codec_id) {
     case AV_CODEC_ID_H264:
-        surface_count = 16 + 1;
+        surface_count = 16 + va->thread_count + 2;
         break;
     default:
         surface_count = 2 + 1;
diff --git a/modules/codec/avcodec/va.c b/modules/codec/avcodec/va.c
index 94abb36..36d46ea 100644
--- a/modules/codec/avcodec/va.c
+++ b/modules/codec/avcodec/va.c
@@ -33,9 +33,10 @@ static int vlc_va_Start(void *func, va_list ap)
     vlc_va_t *va = va_arg(ap, vlc_va_t *);
     int codec = va_arg(ap, int);
     const es_format_t *fmt = va_arg(ap, const es_format_t *);
-    int (*open)(vlc_va_t *, int, const es_format_t *) = func;
+    int thread_count = va_arg(ap, int);
+    int (*open)(vlc_va_t *, int, const es_format_t *, int) = func;
 
-    return open(va, codec, fmt);
+    return open(va, codec, fmt, thread_count);
 }
 
 static void vlc_va_Stop(void *func, va_list ap)
@@ -46,14 +47,14 @@ static void vlc_va_Stop(void *func, va_list ap)
     close(va);
 }
 
-vlc_va_t *vlc_va_New(vlc_object_t *obj, int codec_id, const es_format_t *fmt)
+vlc_va_t *vlc_va_New(vlc_object_t *obj, int codec_id, const es_format_t *fmt, int thread_count)
 {
     vlc_va_t *va = vlc_object_create(obj, sizeof (*va));
     if (unlikely(va == NULL))
         return NULL;
 
     va->module = vlc_module_load(va, "hw decoder", "$avcodec-hw", true,
-                                 vlc_va_Start, va, codec_id, fmt);
+                                 vlc_va_Start, va, codec_id, fmt, thread_count);
     if (va->module == NULL)
     {
         vlc_object_release(va);
diff --git a/modules/codec/avcodec/va.h b/modules/codec/avcodec/va.h
index d4645dc..9c16ef7 100644
--- a/modules/codec/avcodec/va.h
+++ b/modules/codec/avcodec/va.h
@@ -47,9 +47,10 @@ struct vlc_va_t {
  * @param obj parent VLC object
  * @param codec_id libavcodec codec ID of the content to decode
  * @param fmt VLC format of the content to decode
+ * @param thread_count number of threads used by libavcodec
  * @return a new VLC object on success, NULL on error.
  */
-vlc_va_t *vlc_va_New(vlc_object_t *obj, int codec_id, const es_format_t *fmt);
+vlc_va_t *vlc_va_New(vlc_object_t *obj, int codec_id, const es_format_t *fmt, int thread_count);
 
 /**
  * Initializes the acceleration video decoding back-end for libavcodec.
diff --git a/modules/codec/avcodec/vaapi.c b/modules/codec/avcodec/vaapi.c
index 1a7b227..cb1e55f 100644
--- a/modules/codec/avcodec/vaapi.c
+++ b/modules/codec/avcodec/vaapi.c
@@ -46,7 +46,7 @@
     vaCreateSurfaces(d, w, h, f, ns, s)
 #endif
 
-static int Create( vlc_va_t *, int, const es_format_t * );
+static int Create( vlc_va_t *, int, const es_format_t *, int );
 static void Delete( vlc_va_t * );
 
 vlc_module_begin ()
@@ -96,7 +96,7 @@ struct vlc_va_sys_t
 };
 
 /* */
-static int Open( vlc_va_t *va, int i_codec_id )
+static int Open( vlc_va_t *va, int i_codec_id, int i_thread_count )
 {
     vlc_va_sys_t *sys = calloc( 1, sizeof(*sys) );
     if ( unlikely(sys == NULL) )
@@ -129,8 +129,8 @@ static int Open( vlc_va_t *va, int i_codec_id )
         break;
     case AV_CODEC_ID_H264:
         i_profile = VAProfileH264High;
-        i_surface_count = 16+1;
-        break;
+        i_surface_count = 16 + i_thread_count + 2;
+        break;;
     default:
         return VLC_EGENERIC;
     }
@@ -541,7 +541,7 @@ static void Delete( vlc_va_t *va )
     free( sys );
 }
 
-static int Create( vlc_va_t *p_va, int i_codec_id, const es_format_t *fmt )
+static int Create( vlc_va_t *p_va, int i_codec_id, const es_format_t *fmt, int i_thread_count )
 {
     if( !vlc_xlib_init( VLC_OBJECT(p_va) ) )
     {
@@ -551,7 +551,7 @@ static int Create( vlc_va_t *p_va, int i_codec_id, const es_format_t *fmt )
 
     (void) fmt;
 
-    int err = Open( p_va, i_codec_id );
+    int err = Open( p_va, i_codec_id, i_thread_count );
     if( err )
         return err;
 
diff --git a/modules/codec/avcodec/video.c b/modules/codec/avcodec/video.c
index b62ea93..f71482d 100644
--- a/modules/codec/avcodec/video.c
+++ b/modules/codec/avcodec/video.c
@@ -1328,7 +1328,7 @@ static enum PixelFormat ffmpeg_GetFormat( AVCodecContext *p_context,
     if( p_context->level != FF_LEVEL_UNKNOWN)
         p_dec->fmt_in.i_level = p_context->level;
 
-    p_va = vlc_va_New( VLC_OBJECT(p_dec), p_sys->i_codec_id, &p_dec->fmt_in );
+    p_va = vlc_va_New( VLC_OBJECT(p_dec), p_sys->i_codec_id, &p_dec->fmt_in, p_context->thread_count );
     if( p_va == NULL )
         goto end;
 
diff --git a/modules/hw/vdpau/avcodec.c b/modules/hw/vdpau/avcodec.c
index ad8c21b..bdc7f54 100644
--- a/modules/hw/vdpau/avcodec.c
+++ b/modules/hw/vdpau/avcodec.c
@@ -38,7 +38,7 @@
 #include "vlc_vdpau.h"
 #include "../../codec/avcodec/va.h"
 
-static int Open(vlc_va_t *, int, const es_format_t *);
+static int Open(vlc_va_t *, int, const es_format_t *, int);
 static void Close(vlc_va_t *);
 
 vlc_module_begin()
@@ -169,12 +169,14 @@ static int Setup(vlc_va_t *va, void **ctxp, vlc_fourcc_t *chromap,
     return Init(va, ctxp, chromap, width, height);
 }
 
-static int Open(vlc_va_t *va, int codec, const es_format_t *fmt)
+static int Open(vlc_va_t *va, int codec, const es_format_t *fmt, int thread_count)
 {
     VdpStatus err;
     VdpDecoderProfile profile;
     int level;
 
+    (void)thread_count;
+
     switch (codec)
     {
       case AV_CODEC_ID_MPEG1VIDEO:
-- 
1.8.3.2




More information about the vlc-devel mailing list