static struct mp_image *d3d11va_new_ref(ID3D11VideoDecoderOutputView *view, int w, int h) { if (!view) return NULL; struct d3d11va_surface *surface = talloc_zero(NULL, struct d3d11va_surface); surface->surface = view; ID3D11VideoDecoderOutputView_AddRef(surface->surface); ID3D11VideoDecoderOutputView_GetResource( surface->surface, (ID3D11Resource **)&surface->texture); D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC surface_desc; ID3D11VideoDecoderOutputView_GetDesc(surface->surface, &surface_desc); surface->subindex = surface_desc.Texture2D.ArraySlice; struct mp_image *mpi = mp_image_new_custom_ref(NULL, surface, d3d11va_release_img); if (!mpi) abort(); mp_image_setfmt(mpi, IMGFMT_D3D11VA); mp_image_set_size(mpi, w, h); mpi->planes[0] = NULL; mpi->planes[1] = (void *)surface->texture; mpi->planes[2] = (void *)(intptr_t)surface->subindex; mpi->planes[3] = (void *)surface->surface; return mpi; }
static int Extract(vlc_va_t *va, picture_t *output, uint8_t *data) { vlc_va_sys_t *sys = va->sys; ID3D11VideoDecoderOutputView *src = (ID3D11VideoDecoderOutputView*)(uintptr_t)data; vlc_va_surface_t *surface = output->context; if (output->format.i_chroma == VLC_CODEC_D3D11_OPAQUE) { /* copy decoder slice to surface */ D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC viewDesc; picture_sys_t *p_sys_out = output->p_sys; picture_sys_t *p_sys_in = surface->p_pic->p_sys; assert(p_sys_out->texture != NULL); assert(p_sys_in->decoder == src); ID3D11VideoDecoderOutputView_GetDesc( src, &viewDesc ); ID3D11DeviceContext_CopySubresourceRegion(sys->d3dctx, (ID3D11Resource*) p_sys_out->texture, 0, 0, 0, 0, (ID3D11Resource*) p_sys_in->texture, viewDesc.Texture2D.ArraySlice, NULL); } else if (output->format.i_chroma == VLC_CODEC_YV12) { va->sys->filter->owner.sys = output; picture_Hold( surface->p_pic ); va->sys->filter->pf_video_filter( va->sys->filter, surface->p_pic ); } else { msg_Err(va, "Unsupported output picture format %08X", output->format.i_chroma ); return VLC_EGENERIC; } return VLC_SUCCESS; }
static struct mp_image *d3d11va_retrieve_image(struct lavc_ctx *s, struct mp_image *img) { HRESULT hr; struct priv *p = s->hwdec_priv; ID3D11Texture2D *staging = p->decoder->staging; ID3D11Texture2D *texture = d3d11_texture_in_mp_image(img); ID3D11VideoDecoderOutputView *surface = d3d11_surface_in_mp_image(img); if (!texture || !surface) { MP_ERR(p, "Failed to get Direct3D texture and surface from mp_image\n"); return img; } D3D11_TEXTURE2D_DESC texture_desc; ID3D11Texture2D_GetDesc(texture, &texture_desc); if (texture_desc.Width < img->w || texture_desc.Height < img->h) { MP_ERR(p, "Direct3D11 texture smaller than mp_image dimensions\n"); return img; } // copy to the staging texture D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC surface_desc; ID3D11VideoDecoderOutputView_GetDesc(surface, &surface_desc); ID3D11DeviceContext_CopySubresourceRegion( p->device_ctx, (ID3D11Resource *)staging, 0, 0, 0, 0, (ID3D11Resource *)texture, surface_desc.Texture2D.ArraySlice, NULL); struct mp_image *sw_img = mp_image_pool_get(p->sw_pool, p->decoder->mpfmt_decoded, texture_desc.Width, texture_desc.Height); if (!sw_img) { MP_ERR(p, "Failed to get %s surface from CPU pool\n", mp_imgfmt_to_name(p->decoder->mpfmt_decoded)); return img; } // copy staging texture to the cpu mp_image D3D11_MAPPED_SUBRESOURCE lock; hr = ID3D11DeviceContext_Map(p->device_ctx, (ID3D11Resource *)staging, 0, D3D11_MAP_READ, 0, &lock); if (FAILED(hr)) { MP_ERR(p, "Failed to map D3D11 surface: %s\n", mp_HRESULT_to_str(hr)); talloc_free(sw_img); return img; } copy_nv12(sw_img, lock.pData, lock.RowPitch, texture_desc.Height); ID3D11DeviceContext_Unmap(p->device_ctx, (ID3D11Resource *)staging, 0); mp_image_set_size(sw_img, img->w, img->h); mp_image_copy_attributes(sw_img, img); talloc_free(img); return sw_img; }
unsigned ff_dxva2_get_surface_index(const AVCodecContext *avctx, const AVDXVAContext *ctx, const AVFrame *frame) { void *surface = ff_dxva2_get_surface(frame); unsigned i; for (i = 0; i < DXVA_CONTEXT_COUNT(avctx, ctx); i++) #if CONFIG_D3D11VA if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD && ctx->d3d11va.surface[i] == surface) { D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC viewDesc; ID3D11VideoDecoderOutputView_GetDesc(ctx->d3d11va.surface[i], &viewDesc); return viewDesc.Texture2D.ArraySlice; } #endif #if CONFIG_DXVA2 if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD && ctx->dxva2.surface[i] == surface) return i; #endif assert(0); return 0; }