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; if (img->imgfmt != IMGFMT_D3D11VA) return img; ID3D11Texture2D *texture = (void *)img->planes[1]; int subindex = (intptr_t)img->planes[2]; if (!texture) { 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 ID3D11DeviceContext_CopySubresourceRegion( p->device_ctx, (ID3D11Resource *)staging, 0, 0, 0, 0, (ID3D11Resource *)texture, subindex, 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; }
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; }
static struct mp_image *dxva2_retrieve_image(struct lavc_ctx *s, struct mp_image *img) { HRESULT hr; struct priv *p = s->hwdec_priv; IDirect3DSurface9 *surface = img->imgfmt == IMGFMT_DXVA2 ? (IDirect3DSurface9 *)img->planes[3] : NULL; if (!surface) { MP_ERR(p, "Failed to get Direct3D surface from mp_image\n"); return img; } D3DSURFACE_DESC surface_desc; IDirect3DSurface9_GetDesc(surface, &surface_desc); if (surface_desc.Width < img->w || surface_desc.Height < img->h) { MP_ERR(p, "Direct3D11 texture smaller than mp_image dimensions\n"); return img; } struct mp_image *sw_img = mp_image_pool_get(p->sw_pool, p->mpfmt_decoded, surface_desc.Width, surface_desc.Height); if (!sw_img) { MP_ERR(p, "Failed to get %s surface from CPU pool\n", mp_imgfmt_to_name(p->mpfmt_decoded)); return img; } D3DLOCKED_RECT lock; hr = IDirect3DSurface9_LockRect(surface, &lock, NULL, D3DLOCK_READONLY); if (FAILED(hr)) { MP_ERR(p, "Unable to lock DXVA2 surface: %s\n", mp_HRESULT_to_str(hr)); talloc_free(sw_img); return img; } copy_nv12(sw_img, lock.pBits, lock.Pitch, surface_desc.Height); IDirect3DSurface9_UnlockRect(surface); mp_image_set_size(sw_img, img->w, img->h); mp_image_copy_attributes(sw_img, img); talloc_free(img); return sw_img; }
static struct mp_image *dxva2_retrieve_image(struct lavc_ctx *s, struct mp_image *img) { DXVA2Context *ctx = s->hwdec_priv; LPDIRECT3DSURFACE9 surface = (LPDIRECT3DSURFACE9)img->planes[3]; D3DSURFACE_DESC surfaceDesc; D3DLOCKED_RECT LockedRect; HRESULT hr; IDirect3DSurface9_GetDesc(surface, &surfaceDesc); if (surfaceDesc.Width < img->w || surfaceDesc.Height < img->h) return img; struct mp_image *sw_img = mp_image_pool_get(ctx->sw_pool, IMGFMT_NV12, surfaceDesc.Width, surfaceDesc.Height); if (!sw_img) return img; hr = IDirect3DSurface9_LockRect(surface, &LockedRect, NULL, D3DLOCK_READONLY); if (FAILED(hr)) { MP_ERR(ctx, "Unable to lock DXVA2 surface\n"); talloc_free(sw_img); return img; } copy_nv12(sw_img, LockedRect.pBits, LockedRect.Pitch, surfaceDesc.Height); mp_image_set_size(sw_img, img->w, img->h); mp_image_copy_attributes(sw_img, img); IDirect3DSurface9_UnlockRect(surface); talloc_free(img); return sw_img; }