#if CONFIG_D3D11VA
#include "libavutil/hwcontext_d3d11va.h"
#endif
+#if CONFIG_DXVA2
+#define COBJMACROS
+#include "libavutil/hwcontext_dxva2.h"
+#endif
#include "libavutil/mem.h"
#include "libavutil/pixdesc.h"
#include "libavutil/time.h"
AV_PIX_FMT_YUV420P,
#if CONFIG_D3D11VA
AV_PIX_FMT_D3D11,
+#endif
+#if CONFIG_DXVA2
+ AV_PIX_FMT_DXVA2_VLD,
#endif
AV_PIX_FMT_NONE
};
static int amf_load_library(AVCodecContext *avctx)
{
- AmfContext *ctx = avctx->priv_data;
- AMFInit_Fn init_fun = NULL;
- AMFQueryVersion_Fn version_fun = NULL;
- AMF_RESULT res = AMF_OK;
+ AmfContext *ctx = avctx->priv_data;
+ AMFInit_Fn init_fun;
+ AMFQueryVersion_Fn version_fun;
+ AMF_RESULT res;
- ctx->eof = 0;
- ctx->delayed_drain = 0;
- ctx->hw_frames_ctx = NULL;
- ctx->hw_device_ctx = NULL;
- ctx->delayed_surface = NULL;
ctx->delayed_frame = av_frame_alloc();
if (!ctx->delayed_frame) {
return AVERROR(ENOMEM);
}
#endif
+#if CONFIG_DXVA2
+static int amf_init_from_dxva2_device(AVCodecContext *avctx, AVDXVA2DeviceContext *hwctx)
+{
+ AmfContext *ctx = avctx->priv_data;
+ HANDLE device_handle;
+ IDirect3DDevice9 *device;
+ HRESULT hr;
+ AMF_RESULT res;
+ int ret;
+
+ hr = IDirect3DDeviceManager9_OpenDeviceHandle(hwctx->devmgr, &device_handle);
+ if (FAILED(hr)) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to open device handle for Direct3D9 device: %lx.\n", (unsigned long)hr);
+ return AVERROR_EXTERNAL;
+ }
+
+ hr = IDirect3DDeviceManager9_LockDevice(hwctx->devmgr, device_handle, &device, FALSE);
+ if (SUCCEEDED(hr)) {
+ IDirect3DDeviceManager9_UnlockDevice(hwctx->devmgr, device_handle, FALSE);
+ ret = 0;
+ } else {
+ av_log(avctx, AV_LOG_ERROR, "Failed to lock device handle for Direct3D9 device: %lx.\n", (unsigned long)hr);
+ ret = AVERROR_EXTERNAL;
+ }
+
+ IDirect3DDeviceManager9_CloseDeviceHandle(hwctx->devmgr, device_handle);
+
+ if (ret < 0)
+ return ret;
+
+ res = ctx->context->pVtbl->InitDX9(ctx->context, device);
+
+ IDirect3DDevice9_Release(device);
+
+ if (res != AMF_OK) {
+ if (res == AMF_NOT_SUPPORTED)
+ av_log(avctx, AV_LOG_ERROR, "AMF via D3D9 is not supported on the given device.\n");
+ else
+ av_log(avctx, AV_LOG_ERROR, "AMF failed to initialise on given D3D9 device: %d.\n", res);
+ return AVERROR(ENODEV);
+ }
+
+ return 0;
+}
+#endif
+
static int amf_init_context(AVCodecContext *avctx)
{
AmfContext *ctx = avctx->priv_data;
if (ret < 0)
return ret;
break;
+#endif
+#if CONFIG_DXVA2
+ case AV_HWDEVICE_TYPE_DXVA2:
+ ret = amf_init_from_dxva2_device(avctx, frames_ctx->device_ctx->hwctx);
+ if (ret < 0)
+ return ret;
+ break;
#endif
default:
av_log(avctx, AV_LOG_ERROR, "AMF initialisation from a %s frames context is not supported.\n",
if (ret < 0)
return ret;
break;
+#endif
+#if CONFIG_DXVA2
+ case AV_HWDEVICE_TYPE_DXVA2:
+ ret = amf_init_from_dxva2_device(avctx, device_ctx->hwctx);
+ if (ret < 0)
+ return ret;
+ break;
#endif
default:
av_log(avctx, AV_LOG_ERROR, "AMF initialisation from a %s device is not supported.\n",
static int amf_init_encoder(AVCodecContext *avctx)
{
- AmfContext *ctx = avctx->priv_data;
- const wchar_t *codec_id = NULL;
- AMF_RESULT res = AMF_OK;
- enum AVPixelFormat pix_fmt;
+ AmfContext *ctx = avctx->priv_data;
+ const wchar_t *codec_id = NULL;
+ AMF_RESULT res;
+ enum AVPixelFormat pix_fmt;
switch (avctx->codec->id) {
case AV_CODEC_ID_H264:
int av_cold ff_amf_encode_close(AVCodecContext *avctx)
{
- AmfContext *ctx = avctx->priv_data;
- if (ctx->delayed_surface)
- {
+ AmfContext *ctx = avctx->priv_data;
+
+ if (ctx->delayed_surface) {
ctx->delayed_surface->pVtbl->Release(ctx->delayed_surface);
ctx->delayed_surface = NULL;
}
static int amf_copy_surface(AVCodecContext *avctx, const AVFrame *frame,
AMFSurface* surface)
{
- AMFPlane *plane = NULL;
- uint8_t *dst_data[4];
- int dst_linesize[4];
- int planes;
- int i;
+ AMFPlane *plane;
+ uint8_t *dst_data[4];
+ int dst_linesize[4];
+ int planes;
+ int i;
planes = surface->pVtbl->GetPlanesCount(surface);
av_assert0(planes < FF_ARRAY_ELEMS(dst_data));
static int amf_copy_buffer(AVCodecContext *avctx, AVPacket *pkt, AMFBuffer *buffer)
{
- AmfContext *ctx = avctx->priv_data;
- int ret;
- AMFVariantStruct var = {0};
- int64_t timestamp = AV_NOPTS_VALUE;
- int64_t size = buffer->pVtbl->GetSize(buffer);
+ AmfContext *ctx = avctx->priv_data;
+ int ret;
+ AMFVariantStruct var = {0};
+ int64_t timestamp = AV_NOPTS_VALUE;
+ int64_t size = buffer->pVtbl->GetSize(buffer);
if ((ret = ff_alloc_packet2(avctx, pkt, size, 0)) < 0) {
return ret;
// amfenc API implementation
int ff_amf_encode_init(AVCodecContext *avctx)
{
- AmfContext *ctx = avctx->priv_data;
- int ret;
-
- ctx->factory = NULL;
- ctx->debug = NULL;
- ctx->trace = NULL;
- ctx->context = NULL;
- ctx->encoder = NULL;
- ctx->library = NULL;
- ctx->version = 0;
- ctx->eof = 0;
- ctx->format = 0;
- ctx->tracer.vtbl = NULL;
- ctx->tracer.avctx = NULL;
+ int ret;
if ((ret = amf_load_library(avctx)) == 0) {
if ((ret = amf_init_context(avctx)) == 0) {
static void amf_release_buffer_with_frame_ref(AMFBuffer *frame_ref_storage_buffer)
{
- AVFrame *av_frame_ref;
- memcpy(&av_frame_ref, frame_ref_storage_buffer->pVtbl->GetNative(frame_ref_storage_buffer), sizeof(av_frame_ref));
- av_frame_free(&av_frame_ref);
+ AVFrame *frame_ref;
+ memcpy(&frame_ref, frame_ref_storage_buffer->pVtbl->GetNative(frame_ref_storage_buffer), sizeof(frame_ref));
+ av_frame_free(&frame_ref);
frame_ref_storage_buffer->pVtbl->Release(frame_ref_storage_buffer);
}
int ff_amf_send_frame(AVCodecContext *avctx, const AVFrame *frame)
{
- AMF_RESULT res = AMF_OK;
- AmfContext *ctx = avctx->priv_data;
- AMFSurface *surface = NULL;
- int ret;
+ AmfContext *ctx = avctx->priv_data;
+ AMFSurface *surface;
+ AMF_RESULT res;
+ int ret;
if (!ctx->encoder)
return AVERROR(EINVAL);
hw_surface = 1;
}
break;
+#endif
+#if CONFIG_DXVA2
+ case AV_PIX_FMT_DXVA2_VLD:
+ {
+ IDirect3DSurface9 *texture = (IDirect3DSurface9 *)frame->data[3]; // actual texture
+
+ res = ctx->context->pVtbl->CreateSurfaceFromDX9Native(ctx->context, texture, &surface, NULL); // wrap to AMF surface
+ AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "CreateSurfaceFromDX9Native() failed with error %d\n", res);
+
+ hw_surface = 1;
+ }
+ break;
#endif
default:
{