]> git.sesse.net Git - vlc/commitdiff
avcodec: move hardware decoding into dedicated plugins (fixes #7220)
authorRémi Denis-Courmont <remi@remlab.net>
Fri, 12 Oct 2012 17:59:50 +0000 (20:59 +0300)
committerRémi Denis-Courmont <remi@remlab.net>
Fri, 12 Oct 2012 18:54:02 +0000 (21:54 +0300)
modules/codec/Modules.am
modules/codec/avcodec/avcodec.c
modules/codec/avcodec/dxva2.c
modules/codec/avcodec/va.h
modules/codec/avcodec/vaapi.c
modules/codec/avcodec/vda.c
modules/codec/avcodec/video.c

index fcf987ef4f03b990411e5b49bb991d4a8dda698e..d2e7541ec257e5ca8b2d2fc05eaac07f339cdf95 100644 (file)
@@ -94,7 +94,6 @@ libavcodec_plugin_la_SOURCES = \
        avcodec/deinterlace.c \
        avcodec/fourcc.c \
        avcodec/chroma.c avcodec/chroma.h \
-       avcodec/copy.c avcodec/copy.h \
        avcodec/va.h \
        avcodec/avcodec.c avcodec/avcodec.h
 if ENABLE_SOUT
@@ -104,21 +103,7 @@ endif
 libavcodec_plugin_la_CFLAGS = $(AM_CFLAGS) $(CFLAGS_avcodec)
 libavcodec_plugin_la_LIBADD = $(AM_LIBADD) $(LIBS_avcodec)
 libavcodec_plugin_la_LDFLAGS = $(AM_LDFLAGS) $(LDFLAGS_avcodec)
-if HAVE_AVCODEC_VAAPI
-libavcodec_plugin_la_SOURCES += avcodec/vaapi.c
-libavcodec_plugin_la_CFLAGS += $(LIBVA_CFLAGS) $(X_CFLAGS) -DHAVE_AVCODEC_VAAPI
-libavcodec_plugin_la_LIBADD += $(LIBVA_LIBS) $(X_LIBS) $(X_PRE_LIBS) -lX11
-endif
-if HAVE_AVCODEC_DXVA2
-libavcodec_plugin_la_SOURCES += avcodec/dxva2.c
-libavcodec_plugin_la_CFLAGS += -DHAVE_AVCODEC_DXVA2
-libavcodec_plugin_la_LIBADD += -lole32 -lshlwapi -luuid
-endif
-if HAVE_AVCODEC_VDA
-libavcodec_plugin_la_SOURCES += avcodec/vda.c
-libavcodec_plugin_la_CFLAGS += -DHAVE_AVCODEC_VDA
-libavcodec_plugin_la_LDFLAGS += -Wl,-framework,CoreFoundation,-framework,VideoDecodeAcceleration,-framework,QuartzCore
-endif
+
 if MERGE_FFMPEG
 libavcodec_plugin_la_SOURCES += \
        ../demux/avformat/demux.c \
@@ -135,6 +120,34 @@ libvlc_LTLIBRARIES += \
 EXTRA_LTLIBRARIES += \
        libavcodec_plugin.la
 
+### avcodec hardware acceleration ###
+
+libvaapi_plugin_la_SOURCES = \
+       avcodec/copy.c avcodec/copy.h \
+       avcodec/vaapi.c
+libvaapi_plugin_la_CFLAGS = $(AM_CFLAGS) $(LIBVA_CFLAGS) $(X_CFLAGS)
+libvaapi_plugin_la_LIBADD = $(AM_LIBADD) $(LIBVA_LIBS) \
+                            $(X_LIBS) $(X_PRE_LIBS) -lX11
+if HAVE_AVCODEC_VAAPI
+libvlc_LTLIBRARIES += libvaapi_plugin.la
+endif
+
+libdxva2_plugin_la_SOURCES = \
+       avcodec/copy.c avcodec/copy.h \
+       avcodec/dxva2.c
+libdxva2_plugin_la_LIBADD = $(AM_LIBADD) -lole32 -lshlwapi -luuid
+if HAVE_AVCODEC_DXVA2
+libvlc_LTLIBRARIES += libdxva2_plugin.la
+endif
+
+libvda_plugin_la_SOURCES = \
+       avcodec/copy.c avcodec/copy.h \
+       avcodec/vda.c
+libvda_plugin_la_LDFLAGS = -Wl,-framework,CoreFoundation,-framework,VideoDecodeAcceleration,-framework,QuartzCore
+if HAVE_AVCODEC_VDA
+libvlc_LTLIBRARIES += libvda_plugin.la
+endif
+
 ### OpenMAX ###
 noinst_HEADERS += \
        omxil/OMX_Component.h \
index 2cd356e73c4ea4bdba708d9bcee86524ecec92c2..6d81f66bada8c86c42eae3d2394dbfd9edbe75c5 100644 (file)
@@ -65,12 +65,6 @@ static const int  nloopf_list[] = { 0, 1, 2, 3, 4 };
 static const char *const nloopf_list_text[] =
   { N_("None"), N_("Non-ref"), N_("Bidir"), N_("Non-key"), N_("All") };
 
-#if defined(HAVE_AVCODEC_VDA)
-static const int  nvda_pix_fmt_list[] = { 0, 1 };
-static const char *const nvda_pix_fmt_list_text[] =
-  { N_("420YpCbCr8Planar"), N_("422YpCbCr8") };
-#endif
-
 #ifdef ENABLE_SOUT
 static const char *const enc_hq_list[] = { "rd", "bits", "simple" };
 static const char *const enc_hq_list_text[] = {
@@ -141,22 +135,8 @@ vlc_module_begin ()
                  true )
     add_obsolete_string( "ffmpeg-codec" ) /* removed since 2.1.0 */
     add_string( "avcodec-codec", NULL, CODEC_TEXT, CODEC_LONGTEXT, true )
-#if defined(HAVE_AVCODEC_VAAPI) || defined(HAVE_AVCODEC_DXVA2) || defined(HAVE_AVCODEC_VDA)
     add_obsolete_bool( "ffmpeg-hw" ) /* removed since 2.1.0 */
-    add_bool( "avcodec-hw",
-#if !defined(HAVE_AVCODEC_VDA)
-    false
-#else
-    true
-#endif
-    , HW_TEXT, HW_LONGTEXT, false )
-#if defined(HAVE_AVCODEC_VDA)
-    add_integer ( "avcodec-vda-pix-fmt", 0, VDA_PIX_FMT_TEXT,
-                  VDA_PIX_FMT_LONGTEXT, false)
-        change_safe ()
-        change_integer_list( nvda_pix_fmt_list, nvda_pix_fmt_list_text )
-#endif
-#endif
+    add_module( "avcodec-hw", "hw decoder", "none", HW_TEXT, HW_LONGTEXT, false )
 #if defined(FF_THREAD_FRAME)
     add_obsolete_integer( "ffmpeg-threads" ) /* removed since 2.1.0 */
     add_integer( "avcodec-threads", 1, THREADS_TEXT, THREADS_LONGTEXT, true );
index 354b61be0e8474a372f61ad2b7b609313e753528..26c7fb1d81518e690d67e9a4005caf076b318575 100644 (file)
 #  define _WIN32_WINNT 0x600
 # endif
 
+#include <assert.h>
+
 #include <vlc_common.h>
 #include <vlc_picture.h>
 #include <vlc_fourcc.h>
 #include <vlc_cpu.h>
-#include <assert.h>
+#include <vlc_plugin.h>
 
 #include <libavcodec/avcodec.h>
 #    define DXVA2API_USE_BITFIELDS
 #include "va.h"
 #include "copy.h"
 
+static int Open(vlc_va_t *, int, int, const es_format_t *);
+static void Close(vlc_va_t *);
+
+vlc_module_begin()
+    set_description(N_("DirectX Video Acceleration (DXVA) 2.0"))
+    set_capability("hw decoder", 50)
+    set_category(CAT_INPUT)
+    set_subcategory(SUBCAT_INPUT_VCODEC)
+    set_callbacks(Open, Close)
+vlc_module_end()
+
 #include <windows.h>
 #include <windowsx.h>
 #include <ole2.h>
@@ -488,8 +501,8 @@ static void Close(vlc_va_t *external)
     free(va);
 }
 
-int vlc_va_New(vlc_va_t *log, int pixfmt, int codec_id,
-               const es_format_t *fmt)
+static int Open(vlc_va_t *log, int pixfmt, int codec_id,
+                const es_format_t *fmt)
 {
     if( pixfmt != PIX_FMT_DXVA2_VLD )
         return NULL;
index 6e44dd90e5f38ed809c1fe41195b8b8e3cc54b32..f0a27c780daed8c81689b55f4a5c811ae4bb8b23 100644 (file)
@@ -31,6 +31,7 @@ struct vlc_va_t {
     VLC_COMMON_MEMBERS
 
     vlc_va_sys_t *sys;
+    module_t *module;
     char *description;
 
     int  (*setup)(vlc_va_t *, void **hw, vlc_fourcc_t *output,
@@ -38,7 +39,6 @@ struct vlc_va_t {
     int  (*get)(vlc_va_t *, AVFrame *frame);
     void (*release)(vlc_va_t *, AVFrame *frame);
     int  (*extract)(vlc_va_t *, picture_t *dst, AVFrame *src);
-    void (*close)(vlc_va_t *);
 };
 
 static inline int vlc_va_Setup(vlc_va_t *va, void **hw, vlc_fourcc_t *output,
@@ -58,12 +58,8 @@ static inline int vlc_va_Extract(vlc_va_t *va, picture_t *dst, AVFrame *src)
 {
     return va->extract(va, dst, src);
 }
-static inline void vlc_va_Delete(vlc_va_t *va)
-{
-    va->close(va);
-    vlc_object_release(va);
-}
 
-int vlc_va_New(vlc_va_t *, int pix, int codec, const es_format_t *);
+static vlc_va_t *vlc_va_New(vlc_object_t *, int, int, const es_format_t *);
+static void vlc_va_Delete(vlc_va_t *va);
 
 #endif
index e8f0e6ad397a08368438588fa8c7134a189cb354..38e8e684cbfe0e67a3e0df66693f919b61b040d6 100644 (file)
 # include "config.h"
 #endif
 
+#include <assert.h>
+
 #include <vlc_common.h>
+#include <vlc_plugin.h>
 #include <vlc_fourcc.h>
-#include <assert.h>
+#include <vlc_xlib.h>
 
 #include <libavcodec/avcodec.h>
+#include <libavcodec/vaapi.h>
+#include <X11/Xlib.h>
+#include <va/va_x11.h>
 
 #include "avcodec.h"
 #include "va.h"
 #include "copy.h"
 
-#include <vlc_xlib.h>
+static int Create( vlc_va_t *, int, int, const es_format_t * );
+static void Delete( vlc_va_t * );
 
-#include <libavcodec/vaapi.h>
-
-#include <X11/Xlib.h>
-#include <va/va_x11.h>
+vlc_module_begin ()
+    set_description( N_("Video Acceleration (VA) API") )
+    set_capability( "hw decoder", 50 )
+    set_category( CAT_INPUT )
+    set_subcategory( SUBCAT_INPUT_VCODEC )
+    set_callbacks( Create, Delete )
+vlc_module_end ()
 
 typedef struct
 {
@@ -490,6 +500,7 @@ static void Close( vlc_va_sys_t *p_va )
     if( p_va->p_display_x11 )
         XCloseDisplay( p_va->p_display_x11 );
 }
+
 static void Delete( vlc_va_t *p_external )
 {
     vlc_va_sys_t *p_va = p_external->sys;
@@ -498,8 +509,7 @@ static void Delete( vlc_va_t *p_external )
     free( p_va );
 }
 
-/* */
-int vlc_va_New( vlc_va_t *p_va, int pixfmt, int i_codec_id,
+static int Create( vlc_va_t *p_va, int pixfmt, int i_codec_id,
                 const es_format_t *fmt )
 {
     /* Only VLD supported */
@@ -523,6 +533,5 @@ int vlc_va_New( vlc_va_t *p_va, int pixfmt, int i_codec_id,
     p_va->get = Get;
     p_va->release = Release;
     p_va->extract = Extract;
-    p_va->close = Delete;
     return VLC_SUCCESS;
 }
index 035db0a98e7c180a0a9a52cb2dba7549bd08c3d5..1d0c9a7d0bdf1428e308c48ca7dabae30886616f 100644 (file)
 # include "config.h"
 #endif
 
+#include <assert.h>
+
 #include <vlc_common.h>
 #include <vlc_vout.h>
-#include <assert.h>
+#include <vlc_plugin.h>
 
 #include <libavcodec/avcodec.h>
 
 #include <libavcodec/vda.h>
 #include <VideoDecodeAcceleration/VDADecoder.h>
 
+static int Open( vlc_va_t *, int, int, const es_format_t * );
+static void Close( vlc_va_t * );
+
+static const int  nvda_pix_fmt_list[] = { 0, 1 };
+static const char *const nvda_pix_fmt_list_text[] =
+  { N_("420YpCbCr8Planar"), N_("422YpCbCr8") };
+
+vlc_module_begin ()
+    set_description( N_("Video Decode Acceleration Framework (VDA)") )
+    set_capability( "hw decoder", 50 )
+    set_category( CAT_INPUT )
+    set_subcategory( SUBCAT_INPUT_VCODEC )
+    set_callbacks( Open, Close )
+    add_integer ( "avcodec-vda-pix-fmt", 0, VDA_PIX_FMT_TEXT,
+                  VDA_PIX_FMT_LONGTEXT, false)
+        change_integer_list( nvda_pix_fmt_list, nvda_pix_fmt_list_text )
+vlc_module_end ()
+
 struct vlc_va_sys_t
 {
     struct vda_context  hw_ctx;
@@ -241,15 +261,15 @@ static void Close( vlc_va_t *p_external )
     free( p_va );
 }
 
-int vlc_va_New( vlc_va_t *external, int pixfmt, int i_codec_id,
-                const es_format_t *fmt )
+static int Open( vlc_va_t *external, int pixfmt, int i_codec_id,
+                  const es_format_t *fmt )
 {
     if( pixfmt != PIX_FMT_VDA_VLD || i_codec_id != CODEC_ID_H264 )
         return NULL;
 
     if( fmt->p_extra == NULL || fmt->i_extra < 7 )
     {
-        msg_Warn( p_log, "VDA requires extradata." );
+        msg_Warn( external, "VDA requires extradata." );
         return NULL;
     }
 
@@ -267,7 +287,6 @@ int vlc_va_New( vlc_va_t *external, int pixfmt, int i_codec_id,
     external->get = Get;
     external->release = Release;
     external->extract = Extract;
-    external->close = Close;
 
     return VLC_SUCCESS;
 }
index 9fb9c1539d15d5ecddc061e56c0cc78862d618e7..95f8b652c8cb4b6f6ef137ddc5f38d002c12732d 100644 (file)
 #include <vlc_codec.h>
 #include <vlc_avcodec.h>
 #include <vlc_cpu.h>
+#include <vlc_modules.h>
 #include <assert.h>
 
 #include <libavcodec/avcodec.h>
 #include <libavutil/mem.h>
+#include <libavutil/pixdesc.h>
 
 #include "avcodec.h"
 #include "va.h"
-#if defined(HAVE_AVCODEC_VAAPI) || defined(HAVE_AVCODEC_DXVA2) || defined(HAVE_AVCODEC_VDA)
-#   define HAVE_AVCODEC_VA
-#   include <libavutil/pixdesc.h>
-#endif
 
 /*****************************************************************************
  * decoder_sys_t : decoder descriptor
@@ -108,11 +106,8 @@ static void ffmpeg_CopyPicture    ( decoder_t *, picture_t *, AVFrame * );
 static int  ffmpeg_GetFrameBuf    ( struct AVCodecContext *, AVFrame * );
 static int  ffmpeg_ReGetFrameBuf( struct AVCodecContext *, AVFrame * );
 static void ffmpeg_ReleaseFrameBuf( struct AVCodecContext *, AVFrame * );
-
-#ifdef HAVE_AVCODEC_VA
 static enum PixelFormat ffmpeg_GetFormat( AVCodecContext *,
                                           const enum PixelFormat * );
-#endif
 
 static uint32_t ffmpeg_CodecTag( vlc_fourcc_t fcc )
 {
@@ -345,9 +340,8 @@ int InitVideoDec( decoder_t *p_dec, AVCodecContext *p_context,
     p_sys->p_context->thread_count = i_thread_count;
 #endif
 
-#ifdef HAVE_AVCODEC_VA
-    const bool b_use_hw = var_CreateGetBool( p_dec, "avcodec-hw" );
-    if( b_use_hw &&
+    char *hw = var_CreateGetString( p_dec, "avcodec-hw" ); /* FIXME */
+    if( (hw == NULL || strcasecmp( hw, "none" )) &&
         (i_codec_id == CODEC_ID_MPEG1VIDEO || i_codec_id == CODEC_ID_MPEG2VIDEO ||
          i_codec_id == CODEC_ID_MPEG4 ||
          i_codec_id == CODEC_ID_H264 ||
@@ -368,7 +362,7 @@ int InitVideoDec( decoder_t *p_dec, AVCodecContext *p_context,
 #endif
         p_sys->p_context->get_format = ffmpeg_GetFormat;
     }
-#endif
+    free( hw );
 #ifdef HAVE_AVCODEC_MT
     if( p_sys->p_context->thread_type & FF_THREAD_FRAME )
         p_dec->i_extra_picture_buffers = 2 * p_sys->p_context->thread_count;
@@ -963,7 +957,7 @@ static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context,
 
     if( p_sys->p_va )
     {
-#ifdef HAVE_AVCODEC_VA
+#if 1 // LIBAVCODEC_VERSION_MAJOR >= ? FIXME
         /* hwaccel_context is not present in old ffmpeg version */
         if( vlc_va_Setup( p_sys->p_va,
                           &p_context->hwaccel_context, &p_dec->fmt_out.video.i_chroma,
@@ -1124,7 +1118,49 @@ static void ffmpeg_ReleaseFrameBuf( struct AVCodecContext *p_context,
         p_ff_pic->data[i] = NULL;
 }
 
-#ifdef HAVE_AVCODEC_VA
+static int ffmpeg_va_Start( void *func, va_list ap )
+{
+    vlc_va_t *va = va_arg( ap, vlc_va_t * );
+    int pix = va_arg( ap, int );
+    int codec = va_arg( ap, int );
+    const es_format_t *fmt = va_arg( ap, const es_format_t * );
+    int (*open)( vlc_va_t *, int, int, const es_format_t * ) = func;
+
+    return open( va, pix, codec, fmt );
+}
+
+static vlc_va_t *vlc_va_New( vlc_object_t *parent, int pixfmt, int codec_id,
+                             const es_format_t *fmt )
+{
+    vlc_va_t *p_va = vlc_object_create( parent, sizeof( *p_va ) );
+    if( unlikely(p_va == NULL) )
+        return NULL;
+
+    p_va->module = vlc_module_load( p_va, "hw decoder", "$avcodec-hw",
+                                    true, ffmpeg_va_Start, p_va, pixfmt,
+                                    codec_id, fmt );
+    if( p_va->module == NULL )
+    {
+        vlc_object_release( p_va );
+        p_va = NULL;
+    }
+    return p_va;
+}
+
+static void ffmpeg_va_Stop( void *func, va_list ap )
+{
+    vlc_va_t *va = va_arg( ap, vlc_va_t * );
+    void (*close)( vlc_va_t * ) = func;
+
+    close( va );
+}
+
+static void vlc_va_Delete( vlc_va_t *va )
+{
+    vlc_module_unload( va->module, ffmpeg_va_Stop, va );
+    vlc_object_release( va );
+}
+
 static enum PixelFormat ffmpeg_GetFormat( AVCodecContext *p_context,
                                           const enum PixelFormat *pi_fmt )
 {
@@ -1144,12 +1180,10 @@ static enum PixelFormat ffmpeg_GetFormat( AVCodecContext *p_context,
         msg_Dbg( p_dec, "Available decoder output format %d (%s)", pi_fmt[i],
                  name ? name : "unknown" );
 
-        vlc_va_t *p_va = vlc_object_create( p_dec, sizeof( *p_va ) );
-        if( unlikely(p_va == NULL) )
-            continue;
-        if( vlc_va_New( p_va, pi_fmt[i], p_sys->i_codec_id, &p_dec->fmt_in ) )
+        vlc_va_t *p_va = vlc_va_New( VLC_OBJECT(p_dec), pi_fmt[i],
+                                     p_sys->i_codec_id, &p_dec->fmt_in );
+        if( p_va == NULL )
         {
-            vlc_object_release( p_va );
             msg_Dbg( p_dec, "acceleration not available" );
             continue;
         }
@@ -1183,5 +1217,3 @@ static enum PixelFormat ffmpeg_GetFormat( AVCodecContext *p_context,
     /* Fallback to default behaviour */
     return avcodec_default_get_format( p_context, pi_fmt );
 }
-#endif
-