[vlc-devel] [PATCH] DXA9: add a converter from DXVA2/D3D9 GPU surfaces to YUV planes

Steve Lhomme robUx4 at videolabs.io
Wed Apr 29 09:36:24 CEST 2015


---
 modules/video_chroma/Makefile.am |  10 ++
 modules/video_chroma/dxa9.c      | 211 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 221 insertions(+)
 create mode 100644 modules/video_chroma/dxa9.c

diff --git a/modules/video_chroma/Makefile.am b/modules/video_chroma/Makefile.am
index 3aa874c..078ff56 100644
--- a/modules/video_chroma/Makefile.am
+++ b/modules/video_chroma/Makefile.am
@@ -97,3 +97,13 @@ chroma_LTLIBRARIES += \
 	libi420_yuy2_sse2_plugin.la \
 	libi422_yuy2_sse2_plugin.la
 endif
+
+# DXVA2
+libdxa9_plugin_la_SOURCES = video_chroma/dxa9.c \
+	video_chroma/copy.c video_chroma/copy.h
+
+if HAVE_AVCODEC_DXVA2
+chroma_LTLIBRARIES += \
+	libdxa9_plugin.la
+endif
+
diff --git a/modules/video_chroma/dxa9.c b/modules/video_chroma/dxa9.c
new file mode 100644
index 0000000..9c386c1
--- /dev/null
+++ b/modules/video_chroma/dxa9.c
@@ -0,0 +1,211 @@
+/*****************************************************************************
+ * dxa9.c : DXVA2 GPU surface conversion module for vlc
+ *****************************************************************************
+ * Copyright (C) 2009 Geoffroy Couprie
+ * Copyright (C) 2009 Laurent Aimar
+ * Copyright (C) 2015 VLC authors and VideoLAN
+ * $Id$
+ *
+ * Authors: Geoffroy Couprie <geal at videolan.org>
+ *          Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
+ *          Steve Lhomme <robux4 at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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>
+
+#include "copy.h"
+
+static int  OpenConverter( vlc_object_t * );
+static void CloseConverter( vlc_object_t * );
+
+/*****************************************************************************
+ * Module descriptor.
+ *****************************************************************************/
+vlc_module_begin ()
+    set_description( N_("Conversions from DXA9 to I420,YV12,NV12") )
+    set_capability( "video filter2", 10 )
+    set_callbacks( OpenConverter, CloseConverter )
+vlc_module_end ()
+
+#include <windows.h>
+#include <d3d9.h>
+
+struct picture_sys_t
+{
+    LPDIRECT3DSURFACE9 surface;
+};
+
+static bool GetLock(filter_t *p_filter, LPDIRECT3DSURFACE9 d3d,
+                    D3DLOCKED_RECT *p_lock, D3DSURFACE_DESC *p_desc)
+{
+    if (FAILED( IDirect3DSurface9_GetDesc(d3d, p_desc)))
+        return false;
+
+    /* */
+    if (FAILED(IDirect3DSurface9_LockRect(d3d, p_lock, NULL, D3DLOCK_READONLY))) {
+        msg_Err(p_filter, "Failed to lock surface");
+        return false;
+    }
+
+    return true;
+}
+
+static void DXA9_YV12(filter_t *p_filter, picture_t *src, picture_t *dst)
+{
+    copy_cache_t *p_copy_cache = (copy_cache_t*) p_filter->p_sys;
+
+    D3DSURFACE_DESC desc;
+    D3DLOCKED_RECT lock;
+    if (!GetLock(p_filter, src->p_sys->surface, &lock, &desc))
+        return;
+
+    if (dst->format.i_chroma == VLC_CODEC_I420) {
+        uint8_t *tmp = dst->p[1].p_pixels;
+        dst->p[1].p_pixels = dst->p[2].p_pixels;
+        dst->p[2].p_pixels = tmp;
+    }
+
+    if (desc.Format == MAKEFOURCC('Y','V','1','2') ||
+        desc.Format == MAKEFOURCC('I','M','C','3')) {
+        bool imc3 = desc.Format == MAKEFOURCC('I','M','C','3');
+        size_t chroma_pitch = imc3 ? lock.Pitch : (lock.Pitch / 2);
+
+        size_t pitch[3] = {
+            lock.Pitch,
+            chroma_pitch,
+            chroma_pitch,
+        };
+
+        uint8_t *plane[3] = {
+            (uint8_t*)lock.pBits,
+            (uint8_t*)lock.pBits + pitch[0] * src->format.i_height,
+            (uint8_t*)lock.pBits + pitch[0] * src->format.i_height
+                                 + pitch[1] * src->format.i_height / 2,
+        };
+
+        if (imc3) {
+            uint8_t *V = plane[1];
+            plane[1] = plane[2];
+            plane[2] = V;
+        }
+        CopyFromYv12(dst, plane, pitch, src->format.i_width,
+                     src->format.i_visible_height, p_copy_cache);
+    } else if (desc.Format == MAKEFOURCC('N','V','1','2')) {
+        uint8_t *plane[2] = {
+            lock.pBits,
+            (uint8_t*)lock.pBits + lock.Pitch * src->format.i_visible_height
+        };
+        size_t  pitch[2] = {
+            lock.Pitch,
+            lock.Pitch,
+        };
+        CopyFromNv12(dst, plane, pitch, src->format.i_width,
+                     src->format.i_visible_height, p_copy_cache);
+    } else {
+        msg_Err(p_filter, "Unsupported DXA9 conversion from 0x%08X to YV12", desc.Format);
+    }
+
+    if (dst->format.i_chroma == VLC_CODEC_I420) {
+        uint8_t *tmp = dst->p[1].p_pixels;
+        dst->p[1].p_pixels = dst->p[2].p_pixels;
+        dst->p[2].p_pixels = tmp;
+    }
+
+    /* */
+    IDirect3DSurface9_UnlockRect(src->p_sys->surface);
+}
+
+static void DXA9_NV12(filter_t *p_filter, picture_t *src, picture_t *dst)
+{
+    copy_cache_t *p_copy_cache = (copy_cache_t*) p_filter->p_sys;
+
+    D3DSURFACE_DESC desc;
+    D3DLOCKED_RECT lock;
+    if (!GetLock(p_filter, src->p_sys->surface, &lock, &desc))
+        return;
+
+    if (desc.Format == MAKEFOURCC('N','V','1','2')) {
+        uint8_t *plane[2] = {
+            lock.pBits,
+            (uint8_t*)lock.pBits + lock.Pitch * src->format.i_visible_height
+        };
+        size_t  pitch[2] = {
+            lock.Pitch,
+            lock.Pitch,
+        };
+        CopyFromNv12ToNv12(dst, plane, pitch, src->format.i_width,
+                           src->format.i_visible_height, p_copy_cache);
+    } else {
+        msg_Err(p_filter, "Unsupported DXA9 conversion from 0x%08X to NV12", desc.Format);
+    }
+
+    /* */
+    IDirect3DSurface9_UnlockRect(src->p_sys->surface);
+}
+
+VIDEO_FILTER_WRAPPER (DXA9_YV12)
+VIDEO_FILTER_WRAPPER (DXA9_NV12)
+
+static int OpenConverter( vlc_object_t *obj )
+{
+    filter_t *p_filter = (filter_t *)obj;
+    if ( p_filter->fmt_in.video.i_chroma != VLC_CODEC_D3D9_OPAQUE )
+        return VLC_EGENERIC;
+
+    if ( p_filter->fmt_in.video.i_height != p_filter->fmt_out.video.i_height
+         || p_filter->fmt_in.video.i_width != p_filter->fmt_out.video.i_width )
+        return VLC_EGENERIC;
+
+    switch( p_filter->fmt_out.video.i_chroma ) {
+    case VLC_CODEC_I420:
+    case VLC_CODEC_YV12:
+        p_filter->pf_video_filter = DXA9_YV12_Filter;
+        break;
+    case VLC_CODEC_NV12:
+        p_filter->pf_video_filter = DXA9_NV12_Filter;
+        break;
+    default:
+        return VLC_EGENERIC;
+    }
+
+    copy_cache_t *p_copy_cache = calloc(1, sizeof(*p_copy_cache));
+    if (!p_copy_cache)
+         return VLC_ENOMEM;
+    CopyInitCache(p_copy_cache, p_filter->fmt_in.video.i_width );
+    p_filter->p_sys = (filter_sys_t*) p_copy_cache;
+
+    return VLC_SUCCESS;
+}
+
+static void CloseConverter( vlc_object_t *obj )
+{
+    filter_t *p_filter = (filter_t *)obj;
+    copy_cache_t *p_copy_cache = (copy_cache_t*) p_filter->p_sys;
+    CopyCleanCache(p_copy_cache);
+    free( p_copy_cache );
+    p_filter->p_sys = NULL;
+}
-- 
2.3.2




More information about the vlc-devel mailing list