39#define AMF_AV_FRAME_REF L"av_frame_ref"
40#define PTS_PROP L"PtsProp"
52#define FFMPEG_AMF_WRITER_ID L"ffmpeg_amf"
92 if(!
ctx->pts_property_name)
97 if(!
ctx->av_frame_property_name)
133 ctx->submitted_frame = 0;
134 ctx->encoded_frame = 0;
145 ctx->encoder->pVtbl->Terminate(
ctx->encoder);
146 ctx->encoder->pVtbl->Release(
ctx->encoder);
153 if (
ctx->output_list) {
173 uint8_t *dst_data[4] = {0};
174 int dst_linesize[4] = {0};
178 planes = (int)surface->pVtbl->GetPlanesCount(surface);
182 plane = surface->pVtbl->GetPlaneAt(surface,
i);
183 dst_data[
i] = plane->pVtbl->GetNative(plane);
184 dst_linesize[
i] = plane->pVtbl->GetHPitch(plane);
197 AMFVariantStruct var = {0};
210 buffer->pVtbl->GetProperty(
buffer, AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE, &var);
211 pkt->flags |=
AV_PKT_FLAG_KEY * (var.int64Value == AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_IDR);
212 pict_type = var.int64Value == AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_IDR ?
AV_PICTURE_TYPE_I :
218 if ((
buffer->pVtbl->GetProperty(
buffer, AMF_VIDEO_ENCODER_STATISTIC_AVERAGE_QP, &var)) == AMF_OK) {
219 average_qp =
FFMAX((
int)var.int64Value, -1);
223 buffer->pVtbl->GetProperty(
buffer, AMF_VIDEO_ENCODER_HEVC_OUTPUT_DATA_TYPE, &var);
224 pkt->flags |=
AV_PKT_FLAG_KEY * (var.int64Value == AMF_VIDEO_ENCODER_HEVC_OUTPUT_DATA_TYPE_IDR);
225 pict_type = var.int64Value == AMF_VIDEO_ENCODER_HEVC_OUTPUT_DATA_TYPE_IDR ?
AV_PICTURE_TYPE_I :
226 var.int64Value == AMF_VIDEO_ENCODER_HEVC_OUTPUT_DATA_TYPE_I ?
AV_PICTURE_TYPE_I :
227 var.int64Value == AMF_VIDEO_ENCODER_HEVC_OUTPUT_DATA_TYPE_P ?
AV_PICTURE_TYPE_P : 0;
230 if ((
buffer->pVtbl->GetProperty(
buffer, AMF_VIDEO_ENCODER_HEVC_STATISTIC_AVERAGE_QP, &var)) == AMF_OK) {
231 average_qp =
FFMAX((
int)var.int64Value, -1);
235 buffer->pVtbl->GetProperty(
buffer, AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE, &var);
236 pkt->flags |=
AV_PKT_FLAG_KEY * (var.int64Value == AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE_KEY);
237 pict_type = var.int64Value == AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE_KEY ?
AV_PICTURE_TYPE_I :
238 var.int64Value == AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE_INTRA_ONLY ?
AV_PICTURE_TYPE_I :
239 var.int64Value == AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE_INTER ?
AV_PICTURE_TYPE_P : 0;
242 if ((
buffer->pVtbl->GetProperty(
buffer, AMF_VIDEO_ENCODER_AV1_STATISTIC_AVERAGE_Q_INDEX, &var)) == AMF_OK) {
243 average_qp =
FFMAX((
int)var.int64Value, -1);
244 if (average_qp >= 0) {
245 average_qp = (average_qp > 244) ? (average_qp <= 249 ? 62 : 63) : (average_qp + 3) >> 2;
253 if (average_qp >= 0) {
259 pkt->pts = var.int64Value;
265 if ((
ctx->max_b_frames > 0 || ((
ctx->pa_adaptive_mini_gop == 1) ?
true :
false)) &&
ctx->dts_delay == 0) {
270 "timestamp_list is empty while max_b_frames = %d\n", avctx->
max_b_frames);
275 ctx->dts_delay = timestamp_last - timestamp;
277 pkt->dts = timestamp -
ctx->dts_delay;
291 if (!
ctx->timestamp_list) {
295 if (!
ctx->output_list)
300 ctx->hwsurfaces_in_queue = 0;
329 if (
ctx->pa_lookahead_buffer_depth >=
ctx->hwsurfaces_in_queue_max) {
331 "async_depth (%d) too small for lookahead (%d), increasing to (%d)\n",
332 ctx->hwsurfaces_in_queue_max,
333 ctx->pa_lookahead_buffer_depth,
334 ctx->pa_lookahead_buffer_depth + 1);
335 ctx->hwsurfaces_in_queue_max =
ctx->pa_lookahead_buffer_depth + 1;
349 AMFVariantStruct var;
350 res = AMFVariantInit(&var);
352 AMFGuid guid_AMFInterface = IID_AMFInterface();
353 AMFInterface *amf_interface;
354 res =
val->pVtbl->QueryInterface(
val, &guid_AMFInterface, (
void**)&amf_interface);
357 res = AMFVariantAssignInterface(&var, amf_interface);
358 amf_interface->pVtbl->Release(amf_interface);
361 res =
object->pVtbl->SetProperty(
object,
name, var);
363 AMFVariantClear(&var);
370 AMF_RESULT res = AMF_FAIL;
375 AMF_ASSIGN_PROPERTY_INT64(res, surface,
ctx->av_frame_property_name,
data);
382 AMFVariantStruct var = {0};
383 AMF_RESULT res =
buffer->pVtbl->GetProperty(
buffer,
ctx->av_frame_property_name, &var);
384 if(res == AMF_OK && var.int64Value){
404 switch (
frame->format) {
408 static const GUID AMFTextureArrayIndexGUID = { 0x28115527, 0xe7c3, 0x4b66, { 0x99, 0xd3, 0x4f, 0x2a, 0xe6, 0xb4, 0x7f, 0xaf } };
409 ID3D11Texture2D *texture = (ID3D11Texture2D*)
frame->data[0];
413 texture->lpVtbl->SetPrivateData(texture, &AMFTextureArrayIndexGUID,
sizeof(
index), &
index);
414 res = amf_device_ctx->
context->pVtbl->CreateSurfaceFromDX11Native(amf_device_ctx->
context, texture, &surface,
NULL);
423 IDirect3DSurface9 *texture = (IDirect3DSurface9 *)
frame->data[3];
424 res = amf_device_ctx->
context->pVtbl->CreateSurfaceFromDX9Native(amf_device_ctx->
context, texture, &surface,
NULL);
432 surface = (AMFSurface*)
frame->data[0];
433 surface->pVtbl->Acquire(surface);
439 res = amf_device_ctx->
context->pVtbl->AllocSurface(amf_device_ctx->
context, AMF_MEMORY_HOST,
ctx->format, avctx->
width, avctx->
height, &surface);
447 ctx->hwsurfaces_in_queue++;
449 surface->pVtbl->SetCrop(surface, 0, 0,
frame->width,
frame->height);
453 AMFBuffer * hdrmeta_buffer =
NULL;
454 res = amf_device_ctx->
context->pVtbl->AllocBuffer(amf_device_ctx->
context, AMF_MEMORY_HOST,
sizeof(AMFHDRMetadata), &hdrmeta_buffer);
456 AMFHDRMetadata * hdrmeta = (AMFHDRMetadata*)hdrmeta_buffer->pVtbl->GetNative(hdrmeta_buffer);
460 AMF_ASSIGN_PROPERTY_INTERFACE(res,
ctx->encoder, AMF_VIDEO_ENCODER_INPUT_HDR_METADATA, hdrmeta_buffer);
break;
462 AMF_ASSIGN_PROPERTY_INTERFACE(res,
ctx->encoder, AMF_VIDEO_ENCODER_HEVC_INPUT_HDR_METADATA, hdrmeta_buffer);
break;
464 AMF_ASSIGN_PROPERTY_INTERFACE(res,
ctx->encoder, AMF_VIDEO_ENCODER_AV1_INPUT_HDR_METADATA, hdrmeta_buffer);
break;
469 hdrmeta_buffer->pVtbl->Release(hdrmeta_buffer);
472 surface->pVtbl->SetPts(surface,
frame->pts);
474 AMF_ASSIGN_PROPERTY_INT64(res, surface,
ctx->pts_property_name,
frame->pts);
478 AMF_ASSIGN_PROPERTY_BOOL(res, surface, AMF_VIDEO_ENCODER_STATISTICS_FEEDBACK, 1);
479 AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_INSERT_AUD, !!
ctx->aud);
480 switch (
frame->pict_type) {
482 if (
ctx->forced_idr) {
483 AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_INSERT_SPS, 1);
484 AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_INSERT_PPS, 1);
485 AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_FORCE_PICTURE_TYPE, AMF_VIDEO_ENCODER_PICTURE_TYPE_IDR);
487 AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_FORCE_PICTURE_TYPE, AMF_VIDEO_ENCODER_PICTURE_TYPE_I);
491 AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_FORCE_PICTURE_TYPE, AMF_VIDEO_ENCODER_PICTURE_TYPE_P);
494 AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_FORCE_PICTURE_TYPE, AMF_VIDEO_ENCODER_PICTURE_TYPE_B);
499 AMF_ASSIGN_PROPERTY_BOOL(res, surface, AMF_VIDEO_ENCODER_HEVC_STATISTICS_FEEDBACK, 1);
500 AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_HEVC_INSERT_AUD, !!
ctx->aud);
501 switch (
frame->pict_type) {
503 if (
ctx->forced_idr) {
504 AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_HEVC_INSERT_HEADER, 1);
505 AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_HEVC_FORCE_PICTURE_TYPE, AMF_VIDEO_ENCODER_HEVC_PICTURE_TYPE_IDR);
507 AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_HEVC_FORCE_PICTURE_TYPE, AMF_VIDEO_ENCODER_HEVC_PICTURE_TYPE_I);
511 AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_HEVC_FORCE_PICTURE_TYPE, AMF_VIDEO_ENCODER_HEVC_PICTURE_TYPE_P);
516 AMF_ASSIGN_PROPERTY_BOOL(res, surface, AMF_VIDEO_ENCODER_AV1_STATISTICS_FEEDBACK, 1);
518 if (
ctx->forced_idr) {
519 AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_AV1_FORCE_INSERT_SEQUENCE_HEADER, 1);
520 AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE, AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE_KEY);
522 AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE, AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE_INTRA_ONLY);
530 res =
ctx->encoder->pVtbl->SubmitInput(
ctx->encoder, (AMFData*)surface);
531 if (res == AMF_INPUT_FULL) {
533 *surface_resubmit = surface;
535 surface->pVtbl->Release(surface);
537 ctx->submitted_frame++;
541 if(
ctx->submitted_frame <=
ctx->encoded_frame + output_delay)
554 if (amf_device_ctx->
lock)
557 if (amf_device_ctx->
unlock)
566 AMF_RESULT ret =
ctx->encoder->pVtbl->QueryOutput(
ctx->encoder, &
data);
569 AMFGuid guid = IID_AMFBuffer();
573 ctx->hwsurfaces_in_queue--;
574 ctx->encoded_frame++;
582 AMFSurface *surface =
NULL;
585 AMF_RESULT res_query;
609 if(
ctx->submitted_frame <=
ctx->encoded_frame + output_delay)
615 if (!
frame->buf[0]) {
617 if(!
ctx->delayed_drain) {
618 res =
ctx->encoder->pVtbl->Drain(
ctx->encoder);
619 if (res == AMF_INPUT_FULL) {
620 ctx->delayed_drain = 1;
650 if (
ctx->delayed_drain) {
651 res =
ctx->encoder->pVtbl->Drain(
ctx->encoder);
652 if (res != AMF_INPUT_FULL) {
653 ctx->delayed_drain = 0;
657 av_log(avctx,
AV_LOG_WARNING,
"Data acquired but delayed drain submission got AMF_INPUT_FULL- should not happen\n");
660 }
else if (
ctx->delayed_drain || (
ctx->eof && res_query != AMF_EOF) || (
ctx->hwsurfaces_in_queue >=
ctx->hwsurfaces_in_queue_max) || surface) {
664 if (!
ctx->query_timeout_supported || avpkt->
data || avpkt->
buf) {
668 }
while (block_and_wait);
670 if (res_query == AMF_EOF) {
678 res =
ctx->encoder->pVtbl->SubmitInput(
ctx->encoder, (AMFData*)surface);
679 if (res != AMF_INPUT_FULL)
682 if (!
ctx->query_timeout_supported)
693 }
while(res == AMF_INPUT_FULL);
695 surface->pVtbl->Release(surface);
696 if (res == AMF_INPUT_FULL) {
697 av_log(avctx,
AV_LOG_WARNING,
"Data acquired but delayed SubmitInput returned AMF_INPUT_FULL- should not happen\n");
703 ctx->submitted_frame++;
static double val(void *priv, double ch)
static int amf_submit_frame_locked(AVCodecContext *avctx, AVFrame *frame, AMFSurface **surface_resubmit)
int ff_amf_encode_init(AVCodecContext *avctx)
Common encoder initization function.
static AMF_RESULT amf_query_output(AVCodecContext *avctx, AMFBuffer **buffer)
const AVCodecHWConfigInternal *const ff_amfenc_hw_configs[]
static AMF_RESULT amf_release_attached_frame_ref(AMFEncoderContext *ctx, AMFBuffer *buffer)
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 int amf_submit_frame(AVCodecContext *avctx, AVFrame *frame, AMFSurface **surface_resubmit)
static int amf_copy_surface(AVCodecContext *avctx, const AVFrame *frame, AMFSurface *surface)
static int amf_init_encoder(AVCodecContext *avctx)
static int64_t next_encoder_index
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 AMF_RESULT amf_store_attached_frame_ref(AMFEncoderContext *ctx, const AVFrame *frame, AMFSurface *surface)
#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.
#define i(width, name, range_min, range_max)
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.
int ff_encode_add_stats_side_data(AVPacket *pkt, int quality, const int64_t error[], int error_count, enum AVPictureType pict_type)
#define AV_CODEC_FLAG_LOW_DELAY
Force low delay.
#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(const AVBufferRef *buf)
Create a new reference to an AVBuffer.
#define FF_QP2LAMBDA
factor to convert from H.263 QP to lambda
#define AVERROR_ENCODER_NOT_FOUND
Encoder not found.
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
#define AVERROR_EOF
End of file.
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
AVFifo * av_fifo_alloc2(size_t nb_elems, size_t elem_size, unsigned int flags)
Allocate and initialize an AVFifo with a given element size.
void av_fifo_freep2(AVFifo **f)
Free an AVFifo and reset pointer to NULL.
#define AV_FIFO_FLAG_AUTO_GROW
Automatically resize the FIFO on writes, so that the data fits.
size_t av_fifo_can_read(const AVFifo *f)
int av_fifo_peek(const AVFifo *f, void *buf, size_t nb_elems, size_t offset)
Read data from a FIFO without modifying FIFO state.
int av_fifo_write(AVFifo *f, const void *buf, size_t nb_elems)
Write data into a FIFO.
int av_fifo_read(AVFifo *f, void *buf, size_t nb_elems)
Read data from a FIFO.
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.
AVFrame * av_frame_clone(const AVFrame *src)
Create a new frame that references the same data as src.
#define AV_LOG_WARNING
Something somehow does not look correct.
void * av_memdup(const void *p, size_t size)
Duplicate a buffer with av_malloc().
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 ...
@ AV_PICTURE_TYPE_I
Intra.
@ AV_PICTURE_TYPE_P
Predicted.
@ AV_PICTURE_TYPE_B
Bi-dir predicted.
#define AV_NOPTS_VALUE
Undefined timestamp value.
static AVBufferRef * hw_device_ctx
#define HW_CONFIG_ENCODER_DEVICE(format, device_type_)
#define HW_CONFIG_ENCODER_FRAMES(format, device_type_)
int av_hwdevice_ctx_create(AVBufferRef **pdevice_ref, enum AVHWDeviceType type, const char *device, AVDictionary *opts, int flags)
Open a device of the specified type and create an AVHWDeviceContext for it.
int av_hwdevice_ctx_create_derived(AVBufferRef **dst_ref_ptr, enum AVHWDeviceType type, AVBufferRef *src_ref, int flags)
Create a new device of the specified type from an existing device.
enum AMF_SURFACE_FORMAT av_av_to_amf_format(enum AVPixelFormat fmt)
int av_amf_extract_hdr_metadata(const AVFrame *frame, AMFHDRMetadata *hdrmeta)
An API-specific header for AV_HWDEVICE_TYPE_D3D11VA.
An API-specific header for AV_HWDEVICE_TYPE_DXVA2.
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
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_ARGB
packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
@ 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_AMF_SURFACE
HW acceleration through AMF.
#define AV_PIX_FMT_X2BGR10
@ AVCOL_TRC_SMPTE2084
SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems.
#define FF_ARRAY_ELEMS(a)
This struct is allocated as AVHWDeviceContext.hwctx.
void(* lock)(void *lock_ctx)
void(* unlock)(void *lock_ctx)
int64_t version
version of AMF runtime
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
int flags
AV_CODEC_FLAG_*.
AVBufferRef * hw_device_ctx
A reference to the AVHWDeviceContext describing the device which will be used by a hardware encoder/d...
This structure describes decoded (raw) audio or video data.
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
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 format
The pixel format identifying the underlying HW surface type.
AVBufferRef * device_ref
A reference to the parent AVHWDeviceContext.
This structure stores compressed data.
AVBufferRef * buf
A reference to the reference-counted buffer where the packet data is stored.
static int frame_ref(AVFrame *dst, const AVFrame *src, const int plane_copy[4])
static AVFormatContext * ctx
int av_usleep(unsigned usec)
Sleep for a period of time.