32#include <AMF/core/Surface.h>
33#include <AMF/core/Trace.h>
53#define FFMPEG_AMF_WRITER_ID L"ffmpeg_amf"
72 const wchar_t *scope,
const wchar_t *
message)
91 writer->
avctx = avctx;
111typedef struct AVAMFFormatMap {
141 return AMF_SURFACE_UNKNOWN;
157 switch (color_space) {
160 return AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_601;
162 return AMF_VIDEO_CONVERTER_COLOR_PROFILE_601;
167 return AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_709;
169 return AMF_VIDEO_CONVERTER_COLOR_PROFILE_709;
175 return AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_2020;
177 return AMF_VIDEO_CONVERTER_COLOR_PROFILE_2020;
182 return AMF_VIDEO_CONVERTER_COLOR_PROFILE_UNKNOWN;
188 if (!display_meta || !hdrmeta)
192 const unsigned int luma_den = 10000;
193 hdrmeta->maxMasteringLuminance =
195 hdrmeta->minMasteringLuminance =
200 const unsigned int chroma_den = 50000;
201 hdrmeta->redPrimary[0] =
203 hdrmeta->redPrimary[1] =
205 hdrmeta->greenPrimary[0] =
207 hdrmeta->greenPrimary[1] =
209 hdrmeta->bluePrimary[0] =
211 hdrmeta->bluePrimary[1] =
213 hdrmeta->whitePoint[0] =
215 hdrmeta->whitePoint[1] =
224 if (!light_meta || !hdrmeta)
227 hdrmeta->maxContentLightLevel = (amf_uint16)light_meta->
MaxCLL;
228 hdrmeta->maxFrameAverageLightLevel = (amf_uint16)light_meta->
MaxFALL;
239 if (!
frame || !hdrmeta)
246 mastering_display =
NULL;
253 content_light =
NULL;
256 if (!mastering_display && !content_light)
263 if (!hdrmeta || !
frame)
268 const int chroma_den = 50000;
269 const int luma_den = 10000;
275 av_make_q(hdrmeta->redPrimary[0], chroma_den);
277 av_make_q(hdrmeta->redPrimary[1], chroma_den);
280 av_make_q(hdrmeta->greenPrimary[0], chroma_den);
282 av_make_q(hdrmeta->greenPrimary[1], chroma_den);
285 av_make_q(hdrmeta->bluePrimary[0], chroma_den);
287 av_make_q(hdrmeta->bluePrimary[1], chroma_den);
293 av_make_q(hdrmeta->maxMasteringLuminance, luma_den);
295 av_make_q(hdrmeta->maxMasteringLuminance, luma_den);
299 if (hdrmeta->maxContentLightLevel) {
306 light->
MaxCLL = hdrmeta->maxContentLightLevel;
307 light->
MaxFALL = hdrmeta->maxFrameAverageLightLevel;
341 const void *hwconfig,
439 AMFSurface *surface = (AMFSurface*)(
data);
440 surface->pVtbl->Release(surface);
447 AMFSurface* surface = (AMFSurface*)
dst->data[0];
449 uint8_t *dst_data[4];
457 if (
dst->hw_frames_ctx->data != (uint8_t *)
ctx ||
src->format !=
ctx->sw_format)
464 res = amf_device_ctx->
context->pVtbl->AllocSurface(amf_device_ctx->
context, AMF_MEMORY_HOST,
format,
dst->width,
dst->height, &surface);
466 dst->data[0] = (uint8_t *)surface;
474 planes = (int)surface->pVtbl->GetPlanesCount(surface);
478 plane = surface->pVtbl->GetPlaneAt(surface,
i);
479 dst_data[
i] = plane->pVtbl->GetNative(plane);
480 dst_linesize[
i] = plane->pVtbl->GetHPitch(plane);
492 AMFSurface* surface = (AMFSurface*)
src->data[0];
494 uint8_t *src_data[4];
502 if (
src->hw_frames_ctx->data != (uint8_t *)
ctx ||
dst->format !=
ctx->sw_format)
505 ret = surface->pVtbl->Convert(surface, AMF_MEMORY_HOST);
508 planes = (int)surface->pVtbl->GetPlanesCount(surface);
512 plane = surface->pVtbl->GetPlaneAt(surface,
i);
513 src_data[
i] = plane->pVtbl->GetNative(plane);
514 src_linesize[
i] = plane->pVtbl->GetHPitch(plane);
517 src_data, src_linesize,
dst->format,
527 AMF_RESULT res = AMF_NOT_INITIALIZED;
537 res = amf_ctx->
factory->pVtbl->GetTrace(amf_ctx->
factory, &trace);
563 AMFContext *context = amf_ctx->
context;
564 AMFContext1 *context1 =
NULL;
565 AMFGuid guid1 = IID_AMFContext1();
568 return AMF_MEMORY_UNKNOWN;
572 return AMF_MEMORY_DX11;
575 return AMF_MEMORY_DX9;
578 if (
AMF_IFACE_CALL(context, QueryInterface, &guid1, (
void**)&context1) != AMF_OK)
579 return AMF_MEMORY_UNKNOWN;
582 context1->pVtbl->Release(context1);
583 return AMF_MEMORY_VULKAN;
586 return AMF_MEMORY_UNKNOWN;
592 AMFContext *context = amf_ctx->
context;
593 AMFContext1 *context1 =
NULL;
594 AMFGuid guid1 = IID_AMFContext1();
597 if (!amf_ctx->
lock) {
625 av_log(
ctx,
AV_LOG_WARNING,
"AMF failed to initialize with any of supported versions of DirectX, trying Vulkan instead...\n");
628 res =
AMF_IFACE_CALL(context, QueryInterface, &guid1, (
void**)&context1);
637 if (res == AMF_NOT_SUPPORTED)
651 AMFQueryVersion_Fn version_fun;
654 amf_ctx->
library = dlopen(AMF_DLL_NAMEA, RTLD_NOW | RTLD_LOCAL);
658 init_fun = (AMFInit_Fn)dlsym(amf_ctx->
library, AMF_INIT_FUNCTION_NAME);
661 version_fun = (AMFQueryVersion_Fn)dlsym(amf_ctx->
library, AMF_QUERY_VERSION_FUNCTION_NAME);
668 res = init_fun(AMF_FULL_VERSION, &amf_ctx->
factory);
681 ret =
ctx->factory->pVtbl->GetTrace(
ctx->factory, &trace);
684 int level_amf = AMF_TRACE_TRACE;
685 amf_bool enable_log =
true;
689 level_amf = AMF_TRACE_ERROR;
695 level_amf = AMF_TRACE_ERROR;
699 level_amf = AMF_TRACE_WARNING;
702 level_amf = AMF_TRACE_INFO;
705 level_amf = AMF_TRACE_DEBUG;
708 level_amf = AMF_TRACE_TRACE;
711 if(
ctx->version == AMF_MAKE_FULL_VERSION(1, 4, 35, 0)){
712 level_amf = AMF_TRACE_WARNING;
715 trace->pVtbl->EnableWriter(trace, AMF_TRACE_WRITER_CONSOLE, 0);
716 trace->pVtbl->SetGlobalLevel(trace, level_amf);
723 trace->pVtbl->SetWriterLevel(trace, AMF_TRACE_WRITER_DEBUG_OUTPUT, level_amf);
724 trace->pVtbl->EnableWriter(trace, AMF_TRACE_WRITER_DEBUG_OUTPUT, enable_log);
728 ret =
ctx->factory->pVtbl->CreateContext(
ctx->factory, &
ctx->context);
730 AMF_ASSIGN_PROPERTY_INT64(ret,
ctx->context,
L"DeviceSurfaceCacheSize", 50 );
743 IDirect3DDevice9 *device;
744 HANDLE device_handle;
749 hr = IDirect3DDeviceManager9_OpenDeviceHandle(hwctx->
devmgr, &device_handle);
751 av_log(child_device_ctx,
AV_LOG_ERROR,
"Failed to open device handle for Direct3D9 device: %lx.\n", (
unsigned long)hr);
755 hr = IDirect3DDeviceManager9_LockDevice(hwctx->
devmgr, device_handle, &device, FALSE);
757 IDirect3DDeviceManager9_UnlockDevice(hwctx->
devmgr, device_handle, FALSE);
760 av_log(child_device_ctx,
AV_LOG_ERROR,
"Failed to lock device handle for Direct3D9 device: %lx.\n", (
unsigned long)hr);
765 IDirect3DDeviceManager9_CloseDeviceHandle(hwctx->
devmgr, device_handle);
772 IDirect3DDevice9_Release(device);
774 if (res != AMF_OK && res != AMF_ALREADY_INITIALIZED) {
775 if (res == AMF_NOT_SUPPORTED)
776 av_log(child_device_ctx,
AV_LOG_ERROR,
"AMF via D3D9 is not supported on the given device.\n");
778 av_log(child_device_ctx,
AV_LOG_ERROR,
"AMF failed to initialise on given D3D9 device: %d.\n", res);
792 if (res != AMF_OK && res != AMF_ALREADY_INITIALIZED) {
793 if (res == AMF_NOT_SUPPORTED)
794 av_log(child_device_ctx,
AV_LOG_ERROR,
"AMF via D3D11 is not supported on the given device.\n");
796 av_log(child_device_ctx,
AV_LOG_ERROR,
"AMF failed to initialise on the given D3D11 device: %d.\n", res);
809 AMFContext2 *context2 =
NULL;
810 AMFGuid guid = IID_AMFContext2();
811 res = amf_ctx->
context->pVtbl->QueryInterface(amf_ctx->
context, &guid, (
void**)&context2);
813 res = context2->pVtbl->InitDX12(context2, hwctx->
device, AMF_DX12);
814 context2->pVtbl->Release(context2);
815 if (res != AMF_OK && res != AMF_ALREADY_INITIALIZED) {
816 if (res == AMF_NOT_SUPPORTED)
817 av_log(child_device_ctx,
AV_LOG_ERROR,
"AMF via D3D12 is not supported on the given device.\n");
819 av_log(child_device_ctx,
AV_LOG_ERROR,
"AMF failed to initialise on the given D3D12 device: %d.\n", res);
832#if CONFIG_DXVA2 || CONFIG_D3D11VA
841 switch (child_device_ctx->
type) {
844 return amf_init_from_dxva2_device(amf_ctx, child_device_ctx);
848 return amf_init_from_d3d11_device(amf_ctx, child_device_ctx);
852 return amf_init_from_d3d12_device(amf_ctx, child_device_ctx);
855 av_log(child_device_ctx,
AV_LOG_ERROR,
"AMF initialisation from a %s device is not supported.\n",
863 AMFSurface1 *surface1 = hwmap->
priv;
870 AMFSurface *surface = (AMFSurface *)
src->data[0];
871 AMFSurface1 *surface1 =
NULL;
872 size_t *linesizes =
NULL;
874 int amf_mem_flags = AMF_MEMORY_CPU_NONE;
875 const AMFGuid guid = IID_AMFSurface1();
876 AMF_RESULT res = AMF_FAIL;
877 size_t plane_count = 0;
882 res =
AMF_IFACE_CALL(surface, QueryInterface, &guid, (
void**)&surface1);
886 amf_mem_flags |= AMF_MEMORY_CPU_READ;
889 amf_mem_flags |= AMF_MEMORY_CPU_WRITE;
900 res =
AMF_IFACE_CALL(surface1, Map, amf_mem_flags, plane_count, linesizes, (
void**)
map);
907 dst->height =
src->height;
913 for (
int plane = 0; plane < plane_count; ++plane)
915 dst->data[plane] =
map[plane];
916 dst->linesize[plane] = linesizes[plane];
926 if (ret < 0 && surface1 !=
NULL)
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
static const char *const format[]
static void amf_free_amfsurface(void *opaque, uint8_t *data)
#define FFMPEG_AMF_WRITER_ID
#define AMF_RETURN_IF_FALSE(avctx, exp, ret_value,...)
Error handling helper.
static AVFormatContext * ctx
static AVDictionary * opts
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert0(cond)
assert() equivalent, that is always enabled.
refcounted data buffer API
#define flags(name, subs,...)
#define i(width, name, range_min, range_max)
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
#define AV_BUFFER_FLAG_READONLY
Always treat the buffer as read-only, even when it has only one reference.
AVBufferRef * av_buffer_create(uint8_t *data, size_t size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
AVBufferRef * av_buffer_pool_get(AVBufferPool *pool)
Allocate a new AVBuffer, reusing an old buffer from the pool when available.
AVBufferPool * av_buffer_pool_init2(size_t size, void *opaque, AVBufferRef *(*alloc)(void *opaque, size_t size), void(*pool_free)(void *opaque))
Allocate and initialize a buffer pool with a more complex allocator.
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
#define AVERROR_EXTERNAL
Generic error in an external library.
AVFrameSideData * av_frame_get_side_data(const AVFrame *frame, enum AVFrameSideDataType type)
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
@ AV_FRAME_DATA_CONTENT_LIGHT_LEVEL
Content light level (based on CTA-861.3).
@ AV_FRAME_DATA_MASTERING_DISPLAY_METADATA
Mastering display metadata associated with a video frame.
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
#define AV_LOG_PANIC
Something went really wrong and we will crash now.
#define AV_LOG_QUIET
Print no output.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
#define AV_LOG_WARNING
Something somehow does not look correct.
#define AV_LOG_FATAL
Something went wrong and recovery is not possible.
#define AV_LOG_VERBOSE
Detailed information.
#define AV_LOG_INFO
Standard information.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
int av_log_get_level(void)
Get the current log level.
static AVRational av_make_q(int num, int den)
Create an AVRational.
static double av_q2d(AVRational a)
Convert an AVRational to a double.
static void av_image_copy2(uint8_t *const dst_data[4], const int dst_linesizes[4], uint8_t *const src_data[4], const int src_linesizes[4], enum AVPixelFormat pix_fmt, int width, int height)
Wrapper around av_image_copy() to workaround the limitation that the conversion from uint8_t * const ...
const char * av_hwdevice_get_type_name(enum AVHWDeviceType type)
Get the string name of an AVHWDeviceType.
int ff_hwframe_map_create(AVBufferRef *hwframe_ref, AVFrame *dst, const AVFrame *src, void(*unmap)(AVHWFramesContext *ctx, HWMapDescriptor *hwmap), void *priv)
@ AV_HWFRAME_MAP_READ
The mapping must be readable.
@ AV_HWFRAME_MAP_WRITE
The mapping must be writeable.
AVHWFrameTransferDirection
@ AV_HWDEVICE_TYPE_D3D11VA
@ AV_HWDEVICE_TYPE_D3D12VA
int av_amf_display_mastering_meta_to_hdrmeta(const AVMasteringDisplayMetadata *display_meta, AMFHDRMetadata *hdrmeta)
static int amf_device_create(AVHWDeviceContext *device_ctx, const char *device, AVDictionary *opts, int flags)
static void amf_unmap_frame(av_unused AVHWFramesContext *unused, HWMapDescriptor *hwmap)
static int amf_device_init(AVHWDeviceContext *ctx)
static void amf_unlock_default(void *opaque)
static int amf_load_library(AVAMFDeviceContext *amf_ctx, void *avcl)
enum AMF_MEMORY_TYPE av_amf_get_memory_type(AVAMFDeviceContext *amf_ctx)
static int amf_map_frame(AVHWFramesContext *device_ctx, AVFrame *dst, const AVFrame *src, int flags)
int av_amf_attach_hdr_metadata(AVFrame *frame, const AMFHDRMetadata *hdrmeta)
static void AMF_CDECL_CALL AMFTraceWriter_Write(AMFTraceWriter *pThis, const wchar_t *scope, const wchar_t *message)
static int amf_transfer_data_from(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src)
static int amf_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src)
const FormatMap format_map[]
const HWContextType ff_hwcontext_type_amf
int av_amf_light_metadata_to_hdrmeta(const AVContentLightMetadata *light_meta, AMFHDRMetadata *hdrmeta)
static void amf_device_uninit(AVHWDeviceContext *device_ctx)
static int amf_frames_init(AVHWFramesContext *ctx)
enum AMF_SURFACE_FORMAT av_av_to_amf_format(enum AVPixelFormat fmt)
static void amf_writer_free(void *opaque)
static enum AVPixelFormat supported_transfer_formats[]
static AmfTraceWriter * amf_writer_alloc(void *avctx)
static int amf_device_derive(AVHWDeviceContext *device_ctx, AVHWDeviceContext *child_device_ctx, AVDictionary *opts, int flags)
static int amf_get_buffer(AVHWFramesContext *ctx, AVFrame *frame)
static void amf_free_amfsurface(void *opaque, uint8_t *data)
int av_amf_extract_hdr_metadata(const AVFrame *frame, AMFHDRMetadata *hdrmeta)
enum AVPixelFormat av_amf_to_av_format(enum AMF_SURFACE_FORMAT fmt)
static void amf_lock_default(void *opaque)
static int amf_transfer_get_formats(AVHWFramesContext *ctx, enum AVHWFrameTransferDirection dir, enum AVPixelFormat **formats)
static void amf_dummy_free(void *opaque, uint8_t *data)
enum AMF_VIDEO_CONVERTER_COLOR_PROFILE_ENUM av_amf_get_color_profile(enum AVColorRange color_range, enum AVColorSpace color_space)
static int amf_frames_get_constraints(AVHWDeviceContext *ctx, const void *hwconfig, AVHWFramesConstraints *constraints)
static AVBufferRef * amf_pool_alloc(void *opaque, size_t size)
static void AMF_CDECL_CALL AMFTraceWriter_Flush(AMFTraceWriter *pThis)
#define AMF_GOTO_FAIL_IF_FALSE(avctx, exp, ret_value,...)
#define AMF_IFACE_CALL(this, function,...)
An API-specific header for AV_HWDEVICE_TYPE_D3D11VA.
An API-specific header for AV_HWDEVICE_TYPE_D3D12VA.
An API-specific header for AV_HWDEVICE_TYPE_DXVA2.
static FFHWFramesContext * ffhwframesctx(AVHWFramesContext *ctx)
const VDPAUPixFmtMap * map
API-specific header for AV_HWDEVICE_TYPE_VULKAN.
static int ff_mutex_unlock(AVMutex *mutex)
static int ff_mutex_lock(AVMutex *mutex)
static int ff_mutex_destroy(AVMutex *mutex)
static int ff_mutex_init(AVMutex *mutex, const void *attr)
static const struct @257111027162314367033347246032313251342043035002 planes[]
Memory handling functions.
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
#define AV_PIX_FMT_RGBAF16
AVColorRange
Visual content value range.
@ AVCOL_RANGE_JPEG
Full range content.
AVPixelFormat
Pixel format.
@ AV_PIX_FMT_NV12
planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
@ AV_PIX_FMT_BGR0
packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
@ AV_PIX_FMT_D3D12
Hardware surfaces for Direct3D 12.
@ AV_PIX_FMT_DXVA2_VLD
HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer.
@ AV_PIX_FMT_ARGB
packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
@ AV_PIX_FMT_D3D11
Hardware surfaces for Direct3D11.
@ AV_PIX_FMT_RGB0
packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined
@ AV_PIX_FMT_YUYV422
packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
@ AV_PIX_FMT_AMF_SURFACE
HW acceleration through AMF.
#define AV_PIX_FMT_X2BGR10
AVColorSpace
YUV colorspace type.
@ AVCOL_SPC_BT709
also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / derived in SMPTE RP 177 Annex B
@ AVCOL_SPC_BT2020_CL
ITU-R BT2020 constant luminance system.
@ AVCOL_SPC_BT2020_NCL
ITU-R BT2020 non-constant luminance system.
@ AVCOL_SPC_SMPTE170M
also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC / functionally identical to above
#define FF_ARRAY_ELEMS(a)
We still need AVHWFramesContext to utilize our hardware memory otherwise, we will receive the error "...
This struct is allocated as AVHWDeviceContext.hwctx.
void(* lock)(void *lock_ctx)
void(* unlock)(void *lock_ctx)
int64_t version
version of AMF runtime
A reference to a data buffer.
Content light level needed by to transmit HDR over HDMI (CTA-861.3).
unsigned MaxFALL
Max average light level per frame (cd/m^2).
unsigned MaxCLL
Max content light level (cd/m^2).
This struct is allocated as AVHWDeviceContext.hwctx.
ID3D11Device * device
Device used for texture creation and access.
This struct is allocated as AVHWDeviceContext.hwctx.
ID3D12Device * device
Device used for objects creation and access.
This struct is allocated as AVHWDeviceContext.hwctx.
IDirect3DDeviceManager9 * devmgr
Structure to hold side data for an AVFrame.
This structure describes decoded (raw) audio or video data.
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
enum AVHWDeviceType type
This field identifies the underlying API used for hardware access.
This struct describes the constraints on hardware frames attached to a given device with a hardware-s...
enum AVPixelFormat * valid_hw_formats
A list of possible values for format in the hw_frames_ctx, terminated by AV_PIX_FMT_NONE.
enum AVPixelFormat * valid_sw_formats
A list of possible values for sw_format in the hw_frames_ctx, terminated by AV_PIX_FMT_NONE.
This struct describes a set or pool of "hardware" frames (i.e.
AMFTraceWriterVtbl * vtblp
AVBufferPool * pool_internal
void * priv
Hardware-specific private data associated with the mapping.
#define av_malloc_array(a, b)
static enum AVPixelFormat supported_formats[]