[vlc-devel] [PATCH 2/5] dxva2: extract the pixel into YV12 planes when DR is not possible
Steve Lhomme
robux4 at gmail.com
Mon Jun 1 15:58:05 CEST 2015
---
modules/codec/Makefile.am | 3 +-
modules/codec/avcodec/dxva2.c | 105 +++++++++++++++++++++++++++++++++++-------
modules/codec/avcodec/va.c | 3 ++
3 files changed, 93 insertions(+), 18 deletions(-)
diff --git a/modules/codec/Makefile.am b/modules/codec/Makefile.am
index b3f3649..d176178 100644
--- a/modules/codec/Makefile.am
+++ b/modules/codec/Makefile.am
@@ -345,7 +345,8 @@ endif
libdxva2_plugin_la_SOURCES = \
codec/avcodec/dxva2.c codec/avcodec/directx_va.c codec/avcodec/directx_va.h \
- packetizer/h264_nal.c packetizer/h264_nal.h
+ packetizer/h264_nal.c packetizer/h264_nal.h \
+ video_chroma/copy.c video_chroma/copy.h
libdxva2_plugin_la_LIBADD = -lole32 -lshlwapi -luuid
if HAVE_AVCODEC_DXVA2
codec_LTLIBRARIES += libdxva2_plugin.la
diff --git a/modules/codec/avcodec/dxva2.c b/modules/codec/avcodec/dxva2.c
index 3db903f..20b03d2 100644
--- a/modules/codec/avcodec/dxva2.c
+++ b/modules/codec/avcodec/dxva2.c
@@ -38,6 +38,7 @@
#define DXVA2API_USE_BITFIELDS
#define COBJMACROS
#include <libavcodec/dxva2.h>
+#include "../../video_chroma/copy.h"
static int Open(vlc_va_t *, AVCodecContext *, enum PixelFormat,
const es_format_t *, picture_sys_t *p_sys);
@@ -124,6 +125,9 @@ struct vlc_va_sys_t
/* Video decoder */
DXVA2_ConfigPictureDecode cfg;
+ /* Option conversion */
+ copy_cache_t surface_cache;
+
/* avcodec internals */
struct dxva_context hw;
};
@@ -160,7 +164,10 @@ static int Setup(vlc_va_t *va, AVCodecContext *avctx, vlc_fourcc_t *chroma, bool
return VLC_EGENERIC;
avctx->hwaccel_context = &sys->hw;
- *chroma = VLC_CODEC_D3D9_OPAQUE;
+ if (b_opaque)
+ *chroma = VLC_CODEC_D3D9_OPAQUE;
+ else
+ *chroma = VLC_CODEC_YV12;
return VLC_SUCCESS;
}
@@ -183,26 +190,86 @@ static int Extract(vlc_va_t *va, picture_t *picture, uint8_t *data)
{
directx_sys_t *dx_sys = &va->sys->dx_sys;
LPDIRECT3DSURFACE9 d3d = (LPDIRECT3DSURFACE9)(uintptr_t)data;
- picture_sys_t *p_sys = picture->p_sys;
- LPDIRECT3DSURFACE9 output = p_sys->surface;
+ if (picture->format.i_chroma == VLC_CODEC_D3D9_OPAQUE)
+ {
+ picture_sys_t *p_sys = picture->p_sys;
+ LPDIRECT3DSURFACE9 output = p_sys->surface;
- assert(d3d != output);
+ assert(d3d != output);
#ifndef NDEBUG
- LPDIRECT3DDEVICE9 srcDevice, dstDevice;
- IDirect3DSurface9_GetDevice(d3d, &srcDevice);
- IDirect3DSurface9_GetDevice(output, &dstDevice);
- assert(srcDevice == dstDevice);
+ LPDIRECT3DDEVICE9 srcDevice, dstDevice;
+ IDirect3DSurface9_GetDevice(d3d, &srcDevice);
+ IDirect3DSurface9_GetDevice(output, &dstDevice);
+ assert(srcDevice == dstDevice);
#endif
- HRESULT hr;
- RECT visibleSource;
- visibleSource.left = 0;
- visibleSource.top = 0;
- visibleSource.right = picture->format.i_visible_width;
- visibleSource.bottom = picture->format.i_visible_height;
- hr = IDirect3DDevice9_StretchRect( (IDirect3DDevice9*) dx_sys->d3ddev, d3d, &visibleSource, output, &visibleSource, D3DTEXF_NONE);
- if (FAILED(hr)) {
- msg_Err(va, "Failed to copy the hw surface to the decoder surface (hr=0x%0lx)", hr );
+ HRESULT hr;
+ RECT visibleSource;
+ visibleSource.left = 0;
+ visibleSource.top = 0;
+ visibleSource.right = picture->format.i_visible_width;
+ visibleSource.bottom = picture->format.i_visible_height;
+ hr = IDirect3DDevice9_StretchRect( (IDirect3DDevice9*) dx_sys->d3ddev, d3d, &visibleSource, output, &visibleSource, D3DTEXF_NONE);
+ if (FAILED(hr)) {
+ msg_Err(va, "Failed to copy the hw surface to the decoder surface (hr=0x%0lx)", hr );
+ return VLC_EGENERIC;
+ }
+ }
+ else if (picture->format.i_chroma == VLC_CODEC_YV12) {
+ D3DSURFACE_DESC desc;
+ D3DLOCKED_RECT lock;
+ if (FAILED( IDirect3DSurface9_GetDesc(d3d, &desc)))
+ return VLC_EGENERIC;
+
+ /* */
+ if (FAILED(IDirect3DSurface9_LockRect(d3d, &lock, NULL, D3DLOCK_READONLY))) {
+ msg_Err(va, "Failed to lock surface");
+ return VLC_EGENERIC;
+ }
+
+ 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] * dx_sys->surface_height,
+ (uint8_t*)lock.pBits + pitch[0] * dx_sys->surface_height
+ + pitch[1] * dx_sys->surface_height / 2,
+ };
+
+ if (imc3) {
+ uint8_t *V = plane[1];
+ plane[1] = plane[2];
+ plane[2] = V;
+ }
+ CopyFromYv12(picture, plane, pitch, dx_sys->width, dx_sys->height,
+ &va->sys->surface_cache);
+ } else {
+ assert(desc.Format == MAKEFOURCC('N','V','1','2'));
+ uint8_t *plane[2] = {
+ lock.pBits,
+ (uint8_t*)lock.pBits + lock.Pitch * dx_sys->surface_height
+ };
+ size_t pitch[2] = {
+ lock.Pitch,
+ lock.Pitch,
+ };
+ CopyFromNv12(picture, plane, pitch, dx_sys->width, dx_sys->height,
+ &va->sys->surface_cache);
+ }
+
+ /* */
+ IDirect3DSurface9_UnlockRect(d3d);
+ } else {
+ msg_Err(va, "Unsupported output picture format %08X", picture->format.i_chroma );
return VLC_EGENERIC;
}
@@ -236,6 +303,8 @@ static void Close(vlc_va_t *va, AVCodecContext *ctx)
(void) ctx;
+ CopyCleanCache(&sys->surface_cache);
+
directx_va_Close(va, &sys->dx_sys);
if (sys->hd3d9_dll)
@@ -260,6 +329,8 @@ static int Open(vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt,
if (unlikely(sys == NULL))
return VLC_ENOMEM;
+ CopyInitCache( &sys->surface_cache, fmt->video.i_width );
+
/* Load dll*/
sys->hd3d9_dll = LoadLibrary(TEXT("D3D9.DLL"));
if (!sys->hd3d9_dll) {
diff --git a/modules/codec/avcodec/va.c b/modules/codec/avcodec/va.c
index 413574d..95b3f7a 100644
--- a/modules/codec/avcodec/va.c
+++ b/modules/codec/avcodec/va.c
@@ -41,6 +41,9 @@ vlc_fourcc_t vlc_va_GetChroma(enum PixelFormat hwfmt, enum PixelFormat swfmt)
return VLC_CODEC_YV12;
case AV_PIX_FMT_DXVA2_VLD:
+ if (swfmt == AV_PIX_FMT_DXVA2_VLD)
+ return VLC_CODEC_D3D9_OPAQUE;
+ else
return VLC_CODEC_YV12;
#if (LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(53, 14, 0))
case AV_PIX_FMT_VDA_VLD:
--
2.4.0
More information about the vlc-devel
mailing list