49 #define FFMPEG_AMF_WRITER_ID L"ffmpeg_amf"
51 #define PTS_PROP L"PtsProp"
89 return AMF_SURFACE_UNKNOWN;
93 const wchar_t *scope,
const wchar_t *
message)
113 AMFQueryVersion_Fn version_fun;
117 if (!
ctx->delayed_frame) {
122 if (!
ctx->timestamp_list) {
128 ctx->library = dlopen(AMF_DLL_NAMEA, RTLD_NOW | RTLD_LOCAL);
132 init_fun = (AMFInit_Fn)dlsym(
ctx->library, AMF_INIT_FUNCTION_NAME);
135 version_fun = (AMFQueryVersion_Fn)dlsym(
ctx->library, AMF_QUERY_VERSION_FUNCTION_NAME);
138 res = version_fun(&
ctx->version);
140 res = init_fun(AMF_FULL_VERSION, &
ctx->factory);
142 res =
ctx->factory->pVtbl->GetTrace(
ctx->factory, &
ctx->trace);
155 res =
ctx->context->pVtbl->InitDX11(
ctx->context, hwctx->
device, AMF_DX11_1);
157 if (res == AMF_NOT_SUPPORTED)
160 av_log(avctx,
AV_LOG_ERROR,
"AMF failed to initialise on the given D3D11 device: %d.\n", res);
172 HANDLE device_handle;
173 IDirect3DDevice9 *device;
178 hr = IDirect3DDeviceManager9_OpenDeviceHandle(hwctx->
devmgr, &device_handle);
180 av_log(avctx,
AV_LOG_ERROR,
"Failed to open device handle for Direct3D9 device: %lx.\n", (
unsigned long)hr);
184 hr = IDirect3DDeviceManager9_LockDevice(hwctx->
devmgr, device_handle, &device, FALSE);
186 IDirect3DDeviceManager9_UnlockDevice(hwctx->
devmgr, device_handle, FALSE);
189 av_log(avctx,
AV_LOG_ERROR,
"Failed to lock device handle for Direct3D9 device: %lx.\n", (
unsigned long)hr);
193 IDirect3DDeviceManager9_CloseDeviceHandle(hwctx->
devmgr, device_handle);
198 res =
ctx->context->pVtbl->InitDX9(
ctx->context, device);
200 IDirect3DDevice9_Release(device);
203 if (res == AMF_NOT_SUPPORTED)
206 av_log(avctx,
AV_LOG_ERROR,
"AMF failed to initialise on given D3D9 device: %d.\n", res);
217 AMFContext1 *context1 =
NULL;
221 ctx->hwsurfaces_in_queue = 0;
222 ctx->hwsurfaces_in_queue_max = 16;
226 ctx->trace->pVtbl->EnableWriter(
ctx->trace, AMF_TRACE_WRITER_DEBUG_OUTPUT,
ctx->log_to_dbg != 0 );
228 ctx->trace->pVtbl->SetWriterLevel(
ctx->trace, AMF_TRACE_WRITER_DEBUG_OUTPUT, AMF_TRACE_TRACE);
229 ctx->trace->pVtbl->EnableWriter(
ctx->trace, AMF_TRACE_WRITER_CONSOLE, 0);
230 ctx->trace->pVtbl->SetGlobalLevel(
ctx->trace, AMF_TRACE_TRACE);
234 ctx->tracer.avctx = avctx;
238 res =
ctx->factory->pVtbl->CreateContext(
ctx->factory, &
ctx->context);
246 av_log(avctx,
AV_LOG_ERROR,
"Format of input frames context (%s) is not supported by AMF.\n",
254 ret = amf_init_from_d3d11_device(avctx, frames_ctx->
device_ctx->
hwctx);
261 ret = amf_init_from_dxva2_device(avctx, frames_ctx->
device_ctx->
hwctx);
267 av_log(avctx,
AV_LOG_ERROR,
"AMF initialisation from a %s frames context is not supported.\n",
273 if (!
ctx->hw_frames_ctx)
282 switch (device_ctx->
type) {
285 ret = amf_init_from_d3d11_device(avctx, device_ctx->
hwctx);
292 ret = amf_init_from_dxva2_device(avctx, device_ctx->
hwctx);
298 av_log(avctx,
AV_LOG_ERROR,
"AMF initialisation from a %s device is not supported.\n",
304 if (!
ctx->hw_device_ctx)
308 res =
ctx->context->pVtbl->InitDX11(
ctx->context,
NULL, AMF_DX11_1);
312 res =
ctx->context->pVtbl->InitDX9(
ctx->context,
NULL);
316 AMFGuid guid = IID_AMFContext1();
317 res =
ctx->context->pVtbl->QueryInterface(
ctx->context, &guid, (
void**)&context1);
320 res = context1->pVtbl->InitVulkan(context1,
NULL);
321 context1->pVtbl->Release(context1);
323 if (res == AMF_NOT_SUPPORTED)
324 av_log(avctx,
AV_LOG_ERROR,
"AMF via Vulkan is not supported on the given device.\n");
326 av_log(avctx,
AV_LOG_ERROR,
"AMF failed to initialise on the given Vulkan device: %d.\n", res);
355 if (
ctx->hw_frames_ctx)
364 res =
ctx->factory->pVtbl->CreateComponent(
ctx->factory,
ctx->context,
codec_id, &
ctx->encoder);
374 if (
ctx->delayed_surface) {
375 ctx->delayed_surface->pVtbl->Release(
ctx->delayed_surface);
380 ctx->encoder->pVtbl->Terminate(
ctx->encoder);
381 ctx->encoder->pVtbl->Release(
ctx->encoder);
386 ctx->context->pVtbl->Terminate(
ctx->context);
387 ctx->context->pVtbl->Release(
ctx->context);
397 dlclose(
ctx->library);
404 ctx->delayed_drain = 0;
420 planes = surface->pVtbl->GetPlanesCount(surface);
424 plane = surface->pVtbl->GetPlaneAt(surface,
i);
425 dst_data[
i] = plane->pVtbl->GetNative(plane);
426 dst_linesize[
i] = plane->pVtbl->GetHPitch(plane);
451 AMFVariantStruct var = {0};
462 buffer->pVtbl->GetProperty(
buffer, AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE, &var);
463 if(var.int64Value == AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_IDR) {
468 buffer->pVtbl->GetProperty(
buffer, AMF_VIDEO_ENCODER_HEVC_OUTPUT_DATA_TYPE, &var);
469 if (var.int64Value == AMF_VIDEO_ENCODER_HEVC_OUTPUT_DATA_TYPE_IDR) {
479 pkt->
pts = var.int64Value;
490 "timestamp_list is empty while max_b_frames = %d\n", avctx->
max_b_frames);
494 (
av_fifo_size(
ctx->timestamp_list) /
sizeof(timestamp) - 1) *
sizeof(timestamp_last),
495 sizeof(timestamp_last),
500 ctx->dts_delay = timestamp_last - timestamp;
525 AMFVariantStruct var;
526 res = AMFVariantInit(&var);
528 AMFGuid guid_AMFInterface = IID_AMFInterface();
529 AMFInterface *amf_interface;
530 res =
val->pVtbl->QueryInterface(
val, &guid_AMFInterface, (
void**)&amf_interface);
533 res = AMFVariantAssignInterface(&var, amf_interface);
534 amf_interface->pVtbl->Release(amf_interface);
537 res =
object->pVtbl->SetProperty(
object,
name, var);
539 AMFVariantClear(&var);
547 AMFVariantStruct var;
548 res = AMFVariantInit(&var);
550 res =
object->pVtbl->GetProperty(
object,
name, &var);
552 if (var.type == AMF_VARIANT_INTERFACE) {
553 AMFGuid guid_AMFBuffer = IID_AMFBuffer();
554 AMFInterface *amf_interface = AMFVariantInterface(&var);
555 res = amf_interface->pVtbl->QueryInterface(amf_interface, &guid_AMFBuffer, (
void**)
val);
557 res = AMF_INVALID_DATA_TYPE;
560 AMFVariantClear(&var);
568 AMFBuffer *frame_ref_storage_buffer =
NULL;
571 res = context->pVtbl->AllocBuffer(context, AMF_MEMORY_HOST,
sizeof(frame_ref), &frame_ref_storage_buffer);
575 memcpy(frame_ref_storage_buffer->pVtbl->GetNative(frame_ref_storage_buffer), &frame_ref,
sizeof(frame_ref));
577 frame_ref_storage_buffer->pVtbl->Release(frame_ref_storage_buffer);
578 frame_ref_storage_buffer =
NULL;
581 return frame_ref_storage_buffer;
587 memcpy(&frame_ref, frame_ref_storage_buffer->pVtbl->GetNative(frame_ref_storage_buffer),
sizeof(frame_ref));
589 frame_ref_storage_buffer->pVtbl->Release(frame_ref_storage_buffer);
598 AMF_RESULT res_query;
614 if (
ctx->delayed_surface !=
NULL) {
615 ctx->delayed_drain = 1;
616 }
else if(!
ctx->delayed_drain) {
617 res =
ctx->encoder->pVtbl->Drain(
ctx->encoder);
618 if (res == AMF_INPUT_FULL) {
619 ctx->delayed_drain = 1;
628 }
else if (!
ctx->delayed_surface) {
636 static const GUID AMFTextureArrayIndexGUID = { 0x28115527, 0xe7c3, 0x4b66, { 0x99, 0xd3, 0x4f, 0x2a, 0xe6, 0xb4, 0x7f, 0xaf } };
637 ID3D11Texture2D *texture = (ID3D11Texture2D*)
frame->
data[0];
643 texture->lpVtbl->SetPrivateData(texture, &AMFTextureArrayIndexGUID,
sizeof(
index), &
index);
645 res =
ctx->context->pVtbl->CreateSurfaceFromDX11Native(
ctx->context, texture, &surface,
NULL);
655 IDirect3DSurface9 *texture = (IDirect3DSurface9 *)
frame->
data[3];
657 res =
ctx->context->pVtbl->CreateSurfaceFromDX9Native(
ctx->context, texture, &surface,
NULL);
666 res =
ctx->context->pVtbl->AllocSurface(
ctx->context, AMF_MEMORY_HOST,
ctx->format, avctx->
width, avctx->
height, &surface);
674 AMFBuffer *frame_ref_storage_buffer;
684 ctx->hwsurfaces_in_queue++;
685 frame_ref_storage_buffer->pVtbl->Release(frame_ref_storage_buffer);
688 surface->pVtbl->SetPts(surface,
frame->
pts);
693 AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_INSERT_AUD, !!
ctx->aud);
696 AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_HEVC_INSERT_AUD, !!
ctx->aud);
703 res =
ctx->encoder->pVtbl->SubmitInput(
ctx->encoder, (AMFData*)surface);
704 if (res == AMF_INPUT_FULL) {
706 ctx->delayed_surface = surface;
709 surface->pVtbl->Release(surface);
723 res_query =
ctx->encoder->pVtbl->QueryOutput(
ctx->encoder, &
data);
727 AMFGuid guid = IID_AMFBuffer();
733 if (
data->pVtbl->HasProperty(
data,
L"av_frame_ref")) {
734 AMFBuffer *frame_ref_storage_buffer;
738 ctx->hwsurfaces_in_queue--;
745 if (
ctx->delayed_surface !=
NULL) {
746 res =
ctx->encoder->pVtbl->SubmitInput(
ctx->encoder, (AMFData*)
ctx->delayed_surface);
747 if (res != AMF_INPUT_FULL) {
748 int64_t
pts =
ctx->delayed_surface->pVtbl->GetPts(
ctx->delayed_surface);
749 ctx->delayed_surface->pVtbl->Release(
ctx->delayed_surface);
758 av_log(avctx,
AV_LOG_WARNING,
"Data acquired but delayed frame submission got AMF_INPUT_FULL- should not happen\n");
760 }
else if (
ctx->delayed_drain) {
761 res =
ctx->encoder->pVtbl->Drain(
ctx->encoder);
762 if (res != AMF_INPUT_FULL) {
763 ctx->delayed_drain = 0;
767 av_log(avctx,
AV_LOG_WARNING,
"Data acquired but delayed drain submission got AMF_INPUT_FULL- should not happen\n");
770 }
else if (
ctx->delayed_surface !=
NULL ||
ctx->delayed_drain || (
ctx->eof && res_query != AMF_EOF) || (
ctx->hwsurfaces_in_queue >=
ctx->hwsurfaces_in_queue_max)) {
774 }
while (block_and_wait);
776 if (res_query == AMF_EOF) {
static double val(void *priv, double ch)
int ff_amf_encode_init(AVCodecContext *avctx)
Common encoder initization function.
static int amf_init_context(AVCodecContext *avctx)
static void AMF_CDECL_CALL AMFTraceWriter_Write(AMFTraceWriter *pThis, const wchar_t *scope, const wchar_t *message)
static AMFTraceWriterVtbl tracer_vtbl
static const FormatMap format_map[]
static enum AMF_SURFACE_FORMAT amf_av_to_amf_format(enum AVPixelFormat fmt)
const AVCodecHWConfigInternal *const ff_amfenc_hw_configs[]
static int amf_load_library(AVCodecContext *avctx)
static int timestamp_queue_enqueue(AVCodecContext *avctx, int64_t timestamp)
static AMF_RESULT amf_set_property_buffer(AMFSurface *object, const wchar_t *name, AMFBuffer *val)
static int amf_copy_buffer(AVCodecContext *avctx, AVPacket *pkt, AMFBuffer *buffer)
int av_cold ff_amf_encode_close(AVCodecContext *avctx)
Common encoder termination function.
static AMFBuffer * amf_create_buffer_with_frame_ref(const AVFrame *frame, AMFContext *context)
#define FFMPEG_AMF_WRITER_ID
static int amf_copy_surface(AVCodecContext *avctx, const AVFrame *frame, AMFSurface *surface)
static int amf_init_encoder(AVCodecContext *avctx)
int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
Ecoding one frame - common function for all AMF encoders.
enum AVPixelFormat ff_amf_pix_fmts[]
Supported formats.
static void amf_release_buffer_with_frame_ref(AMFBuffer *frame_ref_storage_buffer)
static AMF_RESULT amf_get_property_buffer(AMFData *object, const wchar_t *name, AMFBuffer **val)
static void AMF_CDECL_CALL AMFTraceWriter_Flush(AMFTraceWriter *pThis)
#define AMF_RETURN_IF_FALSE(avctx, exp, ret_value,...)
Error handling helper.
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert0(cond)
assert() equivalent, that is always enabled.
static enum AVPixelFormat pix_fmt
int ff_get_encode_buffer(AVCodecContext *avctx, AVPacket *avpkt, int64_t size, int flags)
Get a buffer for a packet.
int ff_encode_get_frame(AVCodecContext *avctx, AVFrame *frame)
Called by encoders to get the next frame for encoding.
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
AVBufferRef * av_buffer_ref(AVBufferRef *buf)
Create a new reference to an AVBuffer.
#define AVERROR_ENCODER_NOT_FOUND
Encoder not found.
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
#define AVERROR_EXTERNAL
Generic error in an external library.
#define AVERROR_EOF
End of file.
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
AVFrame * av_frame_clone(const AVFrame *src)
Create a new frame that references the same data as src.
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
#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_VERBOSE
Detailed information.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
void av_image_copy(uint8_t *dst_data[4], int dst_linesizes[4], const uint8_t *src_data[4], const int src_linesizes[4], enum AVPixelFormat pix_fmt, int width, int height)
Copy image in src_data to dst_data.
#define AV_NOPTS_VALUE
Undefined timestamp value.
#define HW_CONFIG_ENCODER_DEVICE(format, device_type_)
#define HW_CONFIG_ENCODER_FRAMES(format, device_type_)
const char * av_hwdevice_get_type_name(enum AVHWDeviceType type)
Get the string name of an AVHWDeviceType.
@ AV_HWDEVICE_TYPE_D3D11VA
An API-specific header for AV_HWDEVICE_TYPE_D3D11VA.
An API-specific header for AV_HWDEVICE_TYPE_DXVA2.
void av_fifo_freep(AVFifoBuffer **f)
Free an AVFifoBuffer and reset pointer to NULL.
int av_fifo_size(const AVFifoBuffer *f)
Return the amount of data in bytes in the AVFifoBuffer, that is the amount of data you can read from ...
int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size, void(*func)(void *, void *, int))
Feed data from an AVFifoBuffer to a user-supplied callback.
int av_fifo_space(const AVFifoBuffer *f)
Return the amount of space in bytes in the AVFifoBuffer, that is the amount of data you can write int...
AVFifoBuffer * av_fifo_alloc(unsigned int size)
Initialize an AVFifoBuffer.
int av_fifo_generic_peek_at(AVFifoBuffer *f, void *dest, int offset, int buf_size, void(*func)(void *, void *, int))
Feed data at specific position from an AVFifoBuffer to a user-supplied callback.
int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size, int(*func)(void *, void *, int))
Feed data from a user-supplied callback to an AVFifoBuffer.
int av_fifo_grow(AVFifoBuffer *f, unsigned int size)
Enlarge an AVFifoBuffer.
common internal API header
static const struct @322 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.
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_DXVA2_VLD
HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer.
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
@ 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
#define FF_ARRAY_ELEMS(a)
uint8_t * data
The data buffer.
main external API structure.
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
int width
picture width / height.
AVBufferRef * hw_frames_ctx
A reference to the AVHWFramesContext describing the input (for encoding) or output (decoding) frames.
int max_b_frames
maximum number of B-frames between non-B-frames Note: The output will be delayed by max_b_frames+1 re...
const struct AVCodec * codec
AVBufferRef * hw_device_ctx
A reference to the AVHWDeviceContext describing the device which will be used by a hardware encoder/d...
This struct is allocated as AVHWDeviceContext.hwctx.
ID3D11Device * device
Device used for texture creation and access.
This struct is allocated as AVHWDeviceContext.hwctx.
IDirect3DDeviceManager9 * devmgr
int debug
Flags to enable debugging.
This structure describes decoded (raw) audio or video data.
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
AVBufferRef * hw_frames_ctx
For hwaccel-format frames, this should be a reference to the AVHWFramesContext describing the frame.
AVBufferRef * buf[AV_NUM_DATA_POINTERS]
AVBuffer references backing the data for this frame.
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames,...
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 a set or pool of "hardware" frames (i.e.
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
int initial_pool_size
Initial size of the frame pool.
AVHWDeviceContext * device_ctx
The parent AVHWDeviceContext.
This structure stores compressed data.
int flags
A combination of AV_PKT_FLAG values.
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed.
AMF trace writer callback class Used to capture all AMF logging.
int av_usleep(unsigned usec)
Sleep for a period of time.