[vlc-devel] [PATCH 3/3] New video chroma converter to enable transcoding of VAAPI decoded images

Etienne Membrives etienne at membrives.fr
Wed Aug 5 13:17:07 CEST 2009


These three patches create a new picture type (fourcc 'VAAP'), a new video output and a chroma converter that use the Video Acceleration API (VAAPI) hardware acceleration to decode, display or help transcoding compressed videos. Due to the lack of implementation of subpicture blending in current VAAPI drivers, no OSD is available for the new video output.
---
 modules/video_chroma/Modules.am   |    4 +
 modules/video_chroma/vaapi_i420.c |  184 +++++++++++++++++++++++++++++++++++++
 2 files changed, 188 insertions(+), 0 deletions(-)
 create mode 100644 modules/video_chroma/vaapi_i420.c

diff --git a/modules/video_chroma/Modules.am b/modules/video_chroma/Modules.am
index f886bec..3744e6c 100644
--- a/modules/video_chroma/Modules.am
+++ b/modules/video_chroma/Modules.am
@@ -79,6 +79,10 @@ SOURCES_yuy2_i420 = \
 	yuy2_i420.c \
 	$(NULL)
 
+SOURCES_vaapi_i420 = \
+	vaapi_i420.c \
+	$(NULL)
+
 libvlc_LTLIBRARIES += \
 	libi420_rgb_plugin.la \
 	libgrey_yuv_plugin.la \
diff --git a/modules/video_chroma/vaapi_i420.c b/modules/video_chroma/vaapi_i420.c
new file mode 100644
index 0000000..bf0efd1
--- /dev/null
+++ b/modules/video_chroma/vaapi_i420.c
@@ -0,0 +1,184 @@
+/*****************************************************************************
+ * vaapi_i420.c : VAAPI to Planar YUV conversion module for vlc
+ *****************************************************************************
+ * Copyright (C) 2009 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Etienne Membrives <etienne at membrives.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+#include <vlc_filter.h>
+
+#ifdef HAVE_AVCODEC_VAAPI
+#   include <va/va_x11.h>
+#   include <va/va.h>
+#   include "../codec/avcodec/vaapi.h"
+#endif
+
+#define SRC_FOURCC "VAAP"
+#define DEST_FOURCC  "I420"
+
+/*****************************************************************************
+ * Local and extern prototypes.
+ *****************************************************************************/
+static int  Activate ( vlc_object_t * );
+
+static void VAAP_I420           ( filter_t *, picture_t *, picture_t * );
+
+static picture_t *VAAP_I420_Filter    ( filter_t *, picture_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin ()
+    set_description( N_("Conversions from " SRC_FOURCC " to " DEST_FOURCC) )
+    set_capability( "video filter2", 80 )
+    set_callbacks( Activate, NULL )
+vlc_module_end ()
+
+/*****************************************************************************
+ * Activate: allocate a chroma function
+ *****************************************************************************
+ * This function allocates and initializes a chroma function
+ *****************************************************************************/
+static int Activate( vlc_object_t *p_this )
+{
+    filter_t *p_filter = (filter_t *)p_this;
+
+    if( p_filter->fmt_in.video.i_width & 1
+     || p_filter->fmt_in.video.i_height & 1 )
+    {
+        return -1;
+    }
+
+    if( p_filter->fmt_in.video.i_width != p_filter->fmt_out.video.i_width
+     || p_filter->fmt_in.video.i_height != p_filter->fmt_out.video.i_height )
+        return -1;
+
+    switch( p_filter->fmt_out.video.i_chroma )
+    {
+        case VLC_CODEC_I420:
+            switch( p_filter->fmt_in.video.i_chroma )
+            {
+                case VLC_CODEC_VAAPI:
+                    p_filter->pf_video_filter = VAAP_I420_Filter;
+                    break;
+
+                default:
+                    return -1;
+            }
+            break;
+
+        default:
+            return -1;
+    }
+
+    return VLC_SUCCESS;
+}
+
+/* Following functions are local */
+VIDEO_FILTER_WRAPPER( VAAP_I420 )
+
+int StatusCheck( filter_t* p_this, VAStatus status, const char *msg )
+{
+    if ( status != VA_STATUS_SUCCESS )
+    {
+        msg_Err( p_this, "[chroma_filter vaap_i420] %s: %s\n", msg, vaErrorStr( status ) );
+        return VLC_EGENERIC;
+    }
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * VAAP_I420: hw accelerated VAAPI to planar YUV 4:2:0
+ *****************************************************************************/
+static void VAAP_I420( filter_t *p_filter, picture_t *p_source,
+                                           picture_t *p_dest )
+{
+    vlc_va_t* p_va;    VASurfaceID surface;
+    VAStatus status;    VAImage va_image;
+
+    p_va=*((vlc_va_t**)p_source->p_data);
+    memcpy(&surface,p_source->p_data+sizeof(vlc_va_t*),sizeof(VASurfaceID));
+
+    /* Sync surface with its content */
+    status = vaSyncSurface( p_va->p_display, p_va->i_context_id, surface );
+
+    if( StatusCheck( p_filter, status, "vaSyncSurface" ) )
+        return VLC_EGENERIC;
+
+
+    /* Load data into the image (created by avcodec) */
+    status = vaGetImage( p_va->p_display, surface,
+                         0, 0, p_va->i_surface_width, p_va->i_surface_height,
+                         p_va->image.image_id);
+
+    if( StatusCheck( p_filter, status, "vaGetImage" ) )
+        return VLC_EGENERIC;
+
+    void *p_base;
+
+    /* Allocates system memory */
+    status = vaMapBuffer( p_va->p_display, p_va->image.buf, &p_base );
+    if( StatusCheck( p_filter, status, "vaMapBuffer" ) )
+        return VLC_EGENERIC;
+
+    /* Copy data into a real I420 picture_t */
+    for( int i_plane = 0; i_plane < p_dest->i_planes; i_plane++ )
+    {
+        const int i_src_plane = ((p_va->image.format.fourcc == VA_FOURCC('Y','V','1','2' )) && i_plane != 0) ?  (3 - i_plane) : i_plane;
+        const uint8_t *p_src = (uint8_t*)p_base + p_va->image.offsets[i_src_plane];
+        const int i_src_stride = p_va->image.pitches[i_src_plane];
+
+        uint8_t *p_dst = p_dest->p[i_plane].p_pixels;
+        const int i_dst_stride = p_dest->p[i_plane].i_pitch;
+
+        msg_Dbg( p_filter, "New plane" );
+
+        if( i_src_stride != i_dst_stride )
+        {
+            for( int i = 0; i < p_dest->p[i_plane].i_visible_lines; i++ )
+            {
+                vlc_memcpy( p_dst, p_src, __MIN( i_src_stride, i_dst_stride ) );
+                p_src += i_src_stride;
+                p_dst += i_dst_stride;
+            }
+        }
+        else
+        {
+            vlc_memcpy( p_dst, p_src, p_dest->p[i_plane].i_visible_lines * i_src_stride );
+        }
+    }
+
+    /* Unallocates system memory */
+    status = vaUnmapBuffer( p_va->p_display, p_va->image.buf );
+    if( StatusCheck( p_filter, status, "vaUnmapBuffer") )
+        return VLC_EGENERIC;
+
+    return VLC_SUCCESS;
+}
+
-- 
1.6.3.3




More information about the vlc-devel mailing list