vlc | branch: master | Steve Lhomme <[email protected]> | Tue Oct 4 16:15:49 2016 +0200| [75d656c77964f6df86cb744d8d88b1c4b90d582d] | committer: Jean-Baptiste Kempf
d3d11va: attempt to get the decoding buffer slices from the decoder pool Only works if the slice indices start from 0 which is not the case because of the reserved pictures in the pool Signed-off-by: Jean-Baptiste Kempf <[email protected]> > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=75d656c77964f6df86cb744d8d88b1c4b90d582d --- modules/codec/avcodec/d3d11va.c | 143 +++++++++++++++++++++++++++++++--------- 1 file changed, 112 insertions(+), 31 deletions(-) diff --git a/modules/codec/avcodec/d3d11va.c b/modules/codec/avcodec/d3d11va.c index d4ea55f..5831c6e 100644 --- a/modules/codec/avcodec/d3d11va.c +++ b/modules/codec/avcodec/d3d11va.c @@ -43,6 +43,7 @@ #include <vlc_charset.h> #include <vlc_filter.h> #include <vlc_modules.h> +#include <vlc_codec.h> #include "directx_va.h" @@ -118,6 +119,10 @@ struct vlc_va_sys_t ID3D11DeviceContext *d3dctx; HANDLE context_mutex; + /* pool */ + bool b_extern_pool; + picture_t *extern_pics[MAX_SURFACE_COUNT]; + /* Video decoder */ D3D11_VIDEO_DECODER_CONFIG cfg; @@ -454,6 +459,7 @@ static int Open(vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt, sys->d3dctx = p_sys->context; sys->d3dvidctx = d3dvidctx; + sys->b_extern_pool = true; assert(p_sys->texture != NULL); D3D11_TEXTURE2D_DESC dstDesc; @@ -957,45 +963,117 @@ static int DxCreateDecoderSurfaces(vlc_va_t *va, int codec_id, const video_forma ID3D10Multithread_Release(pMultithread); } - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = dx_sys->surface_width; - texDesc.Height = dx_sys->surface_height; - texDesc.MipLevels = 1; - texDesc.Format = sys->render; - texDesc.SampleDesc.Count = 1; - texDesc.MiscFlags = 0; - texDesc.ArraySize = dx_sys->surface_count; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_DECODER; - texDesc.CPUAccessFlags = 0; - - ID3D11Texture2D *p_texture; - hr = ID3D11Device_CreateTexture2D( (ID3D11Device*) dx_sys->d3ddev, &texDesc, NULL, &p_texture ); - if (FAILED(hr)) { - msg_Err(va, "CreateTexture2D %d failed. (hr=0x%0lx)", dx_sys->surface_count, hr); - dx_sys->surface_count = 0; - return VLC_EGENERIC; - } - D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC viewDesc; ZeroMemory(&viewDesc, sizeof(viewDesc)); viewDesc.DecodeProfile = dx_sys->input; viewDesc.ViewDimension = D3D11_VDOV_DIMENSION_TEXTURE2D; - int surface_count = dx_sys->surface_count; - for (dx_sys->surface_count = 0; dx_sys->surface_count < surface_count; dx_sys->surface_count++) { - viewDesc.Texture2D.ArraySlice = dx_sys->surface_count; + if (sys->b_extern_pool) + { + size_t surface_idx; + for (surface_idx = 0; surface_idx < dx_sys->surface_count; surface_idx++) { + picture_t *pic = decoder_NewPicture( (decoder_t*) va->obj.parent ); + sys->extern_pics[surface_idx] = pic; + dx_sys->hw_surface[surface_idx] = NULL; + if (pic==NULL) + { + msg_Warn(va, "not enough decoder pictures %d out of %d", surface_idx, dx_sys->surface_count); + sys->b_extern_pool = false; + break; + } - hr = ID3D11VideoDevice_CreateVideoDecoderOutputView( (ID3D11VideoDevice*) dx_sys->d3ddec, - (ID3D11Resource*) p_texture, - &viewDesc, - (ID3D11VideoDecoderOutputView**) &dx_sys->hw_surface[dx_sys->surface_count] ); + D3D11_TEXTURE2D_DESC texDesc; + ID3D11Texture2D_GetDesc(pic->p_sys->texture, &texDesc); + if (texDesc.ArraySize < dx_sys->surface_count) + { + msg_Warn(va, "not enough decoding slices in the texture (%d/%d)", + texDesc.ArraySize, dx_sys->surface_count); + sys->b_extern_pool = false; + break; + } + assert(texDesc.Format == sys->render); + assert(texDesc.BindFlags & D3D11_BIND_DECODER); + + if (pic->p_sys->slice_index != surface_idx) + { + msg_Warn(va, "d3d11va requires decoding slices to be the first in the texture (%d/%d)", + pic->p_sys->slice_index, surface_idx); + sys->b_extern_pool = false; + break; + } + + viewDesc.Texture2D.ArraySlice = pic->p_sys->slice_index; + hr = ID3D11VideoDevice_CreateVideoDecoderOutputView( (ID3D11VideoDevice*) dx_sys->d3ddec, + (ID3D11Resource*) pic->p_sys->texture, + &viewDesc, + &pic->p_sys->decoder ); + if (FAILED(hr)) { + msg_Warn(va, "CreateVideoDecoderOutputView %d failed. (hr=0x%0lx)", surface_idx, hr); + sys->b_extern_pool = false; + break; + } + sys->dx_sys.hw_surface[surface_idx] = pic->p_sys->decoder; + } + + if (!sys->b_extern_pool) + { + for (size_t i = 0; i < surface_idx; ++i) + { + if (dx_sys->hw_surface[i]) + { + ID3D11VideoDecoderOutputView_Release(dx_sys->hw_surface[i]); + dx_sys->hw_surface[i] = NULL; + } + if (sys->extern_pics[i]) + { + sys->extern_pics[i]->p_sys->decoder = NULL; + picture_Release(sys->extern_pics[i]); + sys->extern_pics[i] = NULL; + } + } + } + else + msg_Dbg(va, "using external surface pool"); + } + + if (!sys->b_extern_pool) + { + D3D11_TEXTURE2D_DESC texDesc; + ZeroMemory(&texDesc, sizeof(texDesc)); + texDesc.Width = dx_sys->surface_width; + texDesc.Height = dx_sys->surface_height; + texDesc.MipLevels = 1; + texDesc.Format = sys->render; + texDesc.SampleDesc.Count = 1; + texDesc.MiscFlags = 0; + texDesc.ArraySize = dx_sys->surface_count; + texDesc.Usage = D3D11_USAGE_DEFAULT; + texDesc.BindFlags = D3D11_BIND_DECODER; + texDesc.CPUAccessFlags = 0; + + ID3D11Texture2D *p_texture; + hr = ID3D11Device_CreateTexture2D( (ID3D11Device*) dx_sys->d3ddev, &texDesc, NULL, &p_texture ); if (FAILED(hr)) { - msg_Err(va, "CreateVideoDecoderOutputView %d failed. (hr=0x%0lx)", dx_sys->surface_count, hr); - ID3D11Texture2D_Release(p_texture); + msg_Err(va, "CreateTexture2D %d failed. (hr=0x%0lx)", dx_sys->surface_count, hr); + dx_sys->surface_count = 0; return VLC_EGENERIC; } + + int surface_count = dx_sys->surface_count; + for (dx_sys->surface_count = 0; dx_sys->surface_count < surface_count; dx_sys->surface_count++) { + sys->extern_pics[dx_sys->surface_count] = NULL; + viewDesc.Texture2D.ArraySlice = dx_sys->surface_count; + + hr = ID3D11VideoDevice_CreateVideoDecoderOutputView( (ID3D11VideoDevice*) dx_sys->d3ddec, + (ID3D11Resource*) p_texture, + &viewDesc, + (ID3D11VideoDecoderOutputView**) &dx_sys->hw_surface[dx_sys->surface_count] ); + if (FAILED(hr)) { + msg_Err(va, "CreateVideoDecoderOutputView %d failed. (hr=0x%0lx)", dx_sys->surface_count, hr); + ID3D11Texture2D_Release(p_texture); + return VLC_EGENERIC; + } + } } msg_Dbg(va, "ID3D11VideoDecoderOutputView succeed with %d surfaces (%dx%d)", dx_sys->surface_count, dx_sys->surface_width, dx_sys->surface_height); @@ -1073,7 +1151,7 @@ static int DxCreateDecoderSurfaces(vlc_va_t *va, int codec_id, const video_forma static void DxDestroySurfaces(vlc_va_t *va) { directx_sys_t *dx_sys = &va->sys->dx_sys; - if (dx_sys->surface_count) { + if (dx_sys->surface_count && !va->sys->b_extern_pool) { ID3D11Resource *p_texture; ID3D11VideoDecoderOutputView_GetResource( (ID3D11VideoDecoderOutputView*) dx_sys->hw_surface[0], &p_texture ); ID3D11Resource_Release(p_texture); @@ -1095,6 +1173,9 @@ static void DestroyPicture(picture_t *picture) static picture_t *DxAllocPicture(vlc_va_t *va, const video_format_t *fmt, unsigned index) { vlc_va_sys_t *sys = va->sys; + if (sys->b_extern_pool) + return sys->extern_pics[index]; + video_format_t src_fmt = *fmt; src_fmt.i_chroma = sys->i_chroma; picture_sys_t *pic_sys = calloc(1, sizeof(*pic_sys)); _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
