History

acvodec/amfenc: Enable use of AMF Surface in multiple encoders

Fixes the behavior of AMF encoders when the same AMF surface is passed to multiple encoder objects. for example when using -filter_complex

Dmitrii Ovchinnikov committed 1 year ago

Commit 64fce721 parent b2c0d373 files · +291 −167Browse files

Unified · Split

3 files
  1. libavcodec/amfenc.c +287 −166
  2. libavcodec/amfenc.h +2 −0
  3. libavutil/hwcontext_amf.h +2 −1
libavcodec/amfenc.c+287−166
@@ -40,7 +40,8 @@ · 39 unmodified lines
4040 #include "internal.h"
4141 #include "libavutil/mastering_display_metadata.h"
4242
43−#define AMF_AV_FRAME_REF L"av_frame_ref"
43+#define AMF_AV_FRAME_REF L"av_frame_ref"
44+#define PTS_PROP L"PtsProp"
4445
4546 static int amf_save_hdr_metadata(AVCodecContext *avctx, const AVFrame *frame, AMFHDRMetadata *hdrmeta)
4647 {
@@ -104,7 +105,6 @@ static int amf_save_hdr_metadata(AVCodecContext *avctx, const AVFrame *frame, AM · 57 unmodified lines
104105
105106 #define FFMPEG_AMF_WRITER_ID L"ffmpeg_amf"
106107
107−#define PTS_PROP L"PtsProp"
108108
109109 const enum AVPixelFormat ff_amf_pix_fmts[] = {
110110 AV_PIX_FMT_NV12,
@@ -127,6 +127,8 @@ const enum AVPixelFormat ff_amf_pix_fmts[] = { · 16 unmodified lines
127127 AV_PIX_FMT_NONE
128128 };
129129
130+static int64_t next_encoder_index = 0;
131+
130132 static int amf_init_encoder(AVCodecContext *avctx)
131133 {
132134 AMFEncoderContext *ctx = avctx->priv_data;
@@ -135,6 +137,21 @@ static int amf_init_encoder(AVCodecContext *avctx) · 2 unmodified lines
135137 enum AVPixelFormat pix_fmt;
136138 AVHWDeviceContext *hw_device_ctx = (AVHWDeviceContext*)ctx->device_ctx_ref->data;
137139 AVAMFDeviceContext *amf_device_ctx = (AVAMFDeviceContext *)hw_device_ctx->hwctx;
140+ int alloc_size;
141+ wchar_t name[512];
142+
143+
144+ alloc_size = swprintf(name, amf_countof(name), L"%s%lld",PTS_PROP, next_encoder_index) + 1;
145+ ctx->pts_property_name = av_memdup(name, alloc_size * sizeof(wchar_t));
146+ if(!ctx->pts_property_name)
147+ return AVERROR(ENOMEM);
148+
149+ alloc_size = swprintf(name, amf_countof(name), L"%s%lld",AMF_AV_FRAME_REF, next_encoder_index) + 1;
150+ ctx->av_frame_property_name = av_memdup(name, alloc_size * sizeof(wchar_t));
151+ if(!ctx->av_frame_property_name)
152+ return AVERROR(ENOMEM);
153+
154+ next_encoder_index++;
138155
139156 switch (avctx->codec->id) {
140157 case AV_CODEC_ID_H264:
@@ -187,6 +204,9 @@ int av_cold ff_amf_encode_close(AVCodecContext *avctx) · 46 unmodified lines
187204 av_buffer_unref(&ctx->device_ctx_ref);
188205 av_fifo_freep2(&ctx->timestamp_list);
189206
207+ av_freep(&ctx->pts_property_name);
208+ av_freep(&ctx->av_frame_property_name);
209+
190210 return 0;
191211 }
192212
@@ -249,7 +269,7 @@ static int amf_copy_buffer(AVCodecContext *avctx, AVPacket *pkt, AMFBuffer *buff · 56 unmodified lines
249269 break;
250270 }
251271
252− buffer->pVtbl->GetProperty(buffer, PTS_PROP, &var);
272+ buffer->pVtbl->GetProperty(buffer, ctx->pts_property_name, &var);
253273
254274 pkt->pts = var.int64Value; // original pts
255275
@@ -298,7 +318,7 @@ int ff_amf_encode_init(AVCodecContext *avctx) · 42 unmodified lines
298318 }
299319 else {
300320 ret = av_hwdevice_ctx_create_derived(&ctx->device_ctx_ref, AV_HWDEVICE_TYPE_AMF, avctx->hw_device_ctx, 0);
301− AMF_RETURN_IF_FALSE(avctx, ret == 0, ret, "Failed to create derived AMF device context: %s\n", av_err2str(ret));
321+ AMF_RETURN_IF_FALSE(ctx, ret == 0, ret, "Failed to create derived AMF device context: %s\n", av_err2str(ret));
302322 }
303323 } else if (avctx->hw_frames_ctx) {
304324 AVHWFramesContext *frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
@@ -308,13 +328,13 @@ int ff_amf_encode_init(AVCodecContext *avctx) · 3 unmodified lines
308328 }
309329 else {
310330 ret = av_hwdevice_ctx_create_derived(&ctx->device_ctx_ref, AV_HWDEVICE_TYPE_AMF, frames_ctx->device_ref, 0);
311− AMF_RETURN_IF_FALSE(avctx, ret == 0, ret, "Failed to create derived AMF device context: %s\n", av_err2str(ret));
331+ AMF_RETURN_IF_FALSE(ctx, ret == 0, ret, "Failed to create derived AMF device context: %s\n", av_err2str(ret));
312332 }
313333 }
314334 }
315335 else {
316336 ret = av_hwdevice_ctx_create(&ctx->device_ctx_ref, AV_HWDEVICE_TYPE_AMF, NULL, NULL, 0);
317− AMF_RETURN_IF_FALSE(avctx, ret == 0, ret, "Failed to create hardware device context (AMF) : %s\n", av_err2str(ret));
337+ AMF_RETURN_IF_FALSE(ctx, ret == 0, ret, "Failed to create hardware device context (AMF) : %s\n", av_err2str(ret));
318338 }
319339
320340 if ((ret = amf_init_encoder(avctx)) == 0) {
@@ -347,22 +367,105 @@ static AMF_RESULT amf_set_property_buffer(AMFSurface *object, const wchar_t *nam · 26 unmodified lines
347367 return res;
348368 }
349369
350−static AMF_RESULT amf_store_attached_frame_ref(const AVFrame *frame, AMFSurface *surface)
370+static AMF_RESULT amf_lock_context(AVCodecContext *avctx)
371+{
372+ AMFEncoderContext *ctx = avctx->priv_data;
373+ AVHWDeviceContext *hw_device_ctx = (AVHWDeviceContext*)ctx->device_ctx_ref->data;
374+ AVAMFDeviceContext *amf_device_ctx = (AVAMFDeviceContext *)hw_device_ctx->hwctx;
375+ AMF_RESULT res;
376+
377+ switch(amf_device_ctx->memory_type) {
378+ case AMF_MEMORY_DX11:
379+ res = amf_device_ctx->context->pVtbl->LockDX11(amf_device_ctx->context);
380+ AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "LockDX11() failed with error %d\n", res);
381+ break;
382+ case AMF_MEMORY_DX12:
383+ {
384+ AMFContext2 *context2 = NULL;
385+ AMFGuid guid = IID_AMFContext2();
386+ res = amf_device_ctx->context->pVtbl->QueryInterface(amf_device_ctx->context, &guid, (void**)&context2);
387+ AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "QueryInterface for AMFContext2 failed with error %d\n", res);
388+ res = context2->pVtbl->LockDX12(context2);
389+ AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "LockDX12() failed with error %d\n", res);
390+ context2->pVtbl->Release(context2);
391+ }
392+ break;
393+ case AMF_MEMORY_DX9:
394+ res = amf_device_ctx->context->pVtbl->LockDX9(amf_device_ctx->context);
395+ AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "LockDX9() failed with error %d\n", res);
396+
397+ case AMF_MEMORY_VULKAN:
398+ {
399+ AMFContext2 *context2 = NULL;
400+ AMFGuid guid = IID_AMFContext2();
401+ res = amf_device_ctx->context->pVtbl->QueryInterface(amf_device_ctx->context, &guid, (void**)&context2);
402+ AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "QueryInterface for AMFContext2 failed with error %d\n", res);
403+ res = context2->pVtbl->LockVulkan(context2);
404+ AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "LockVulkan() failed with error %d\n", res);
405+ context2->pVtbl->Release(context2);
406+ }
407+ break;
408+ }
409+ return AMF_OK;
410+}
411+static AMF_RESULT amf_unlock_context(AVCodecContext *avctx)
412+{
413+ AMFEncoderContext *ctx = avctx->priv_data;
414+ AVHWDeviceContext *hw_device_ctx = (AVHWDeviceContext*)ctx->device_ctx_ref->data;
415+ AVAMFDeviceContext *amf_device_ctx = (AVAMFDeviceContext *)hw_device_ctx->hwctx;
416+ AMF_RESULT res;
417+
418+ switch(amf_device_ctx->memory_type) {
419+ case AMF_MEMORY_DX11:
420+ res = amf_device_ctx->context->pVtbl->UnlockDX11(amf_device_ctx->context);
421+ AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "LockDX11() failed with error %d\n", res);
422+ break;
423+ case AMF_MEMORY_DX12:
424+ {
425+ AMFContext2 *context2 = NULL;
426+ AMFGuid guid = IID_AMFContext2();
427+ res = amf_device_ctx->context->pVtbl->QueryInterface(amf_device_ctx->context, &guid, (void**)&context2);
428+ AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "QueryInterface for AMFContext2 failed with error %d\n", res);
429+ res = context2->pVtbl->UnlockDX12(context2);
430+ AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "LockDX12() failed with error %d\n", res);
431+ context2->pVtbl->Release(context2);
432+ }
433+ break;
434+ case AMF_MEMORY_DX9:
435+ res = amf_device_ctx->context->pVtbl->UnlockDX9(amf_device_ctx->context);
436+ AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "LockDX9() failed with error %d\n", res);
437+
438+ case AMF_MEMORY_VULKAN:
439+ {
440+ AMFContext2 *context2 = NULL;
441+ AMFGuid guid = IID_AMFContext2();
442+ res = amf_device_ctx->context->pVtbl->QueryInterface(amf_device_ctx->context, &guid, (void**)&context2);
443+ AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "QueryInterface for AMFContext2 failed with error %d\n", res);
444+ res = context2->pVtbl->UnlockVulkan(context2);
445+ AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "LockVulkan() failed with error %d\n", res);
446+ context2->pVtbl->Release(context2);
447+ }
448+ break;
449+ }
450+ return AMF_OK;
451+}
452+
453+static AMF_RESULT amf_store_attached_frame_ref(AMFEncoderContext *ctx, const AVFrame *frame, AMFSurface *surface)
351454 {
352455 AMF_RESULT res = AMF_FAIL;
353456 int64_t data;
354457 AVFrame *frame_ref = av_frame_clone(frame);
355458 if (frame_ref) {
356459 memcpy(&data, &frame_ref, sizeof(frame_ref)); // store pointer in 8 bytes
357− AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_AV_FRAME_REF, data);
460+ AMF_ASSIGN_PROPERTY_INT64(res, surface, ctx->av_frame_property_name, data);
358461 }
359462 return res;
360463 }
361464
362−static AMF_RESULT amf_release_attached_frame_ref(AMFBuffer *buffer)
465+static AMF_RESULT amf_release_attached_frame_ref(AMFEncoderContext *ctx, AMFBuffer *buffer)
363466 {
364467 AMFVariantStruct var = {0};
365− AMF_RESULT res = buffer->pVtbl->GetProperty(buffer, AMF_AV_FRAME_REF, &var);
468+ AMF_RESULT res = buffer->pVtbl->GetProperty(buffer, ctx->av_frame_property_name, &var);
366469 if(res == AMF_OK && var.int64Value){
367470 AVFrame *frame_ref;
368471 memcpy(&frame_ref, &var.int64Value, sizeof(frame_ref));
@@ -371,20 +474,184 @@ static AMF_RESULT amf_release_attached_frame_ref(AMFBuffer *buffer) · 2 unmodified lines
371474 return res;
372475 }
373476
477+static int amf_submit_frame(AVCodecContext *avctx, AVFrame *frame, AMFSurface **surface_resubmit)
478+{
479+ AMFEncoderContext *ctx = avctx->priv_data;
480+ AVHWDeviceContext *hw_device_ctx = (AVHWDeviceContext*)ctx->device_ctx_ref->data;
481+ AVAMFDeviceContext *amf_device_ctx = (AVAMFDeviceContext *)hw_device_ctx->hwctx;
482+ AMFSurface *surface;
483+ AMF_RESULT res;
484+ int ret;
485+ int hw_surface = 0;
486+ int max_b_frames = ctx->max_b_frames < 0 ? 0 : ctx->max_b_frames;
487+
488+// prepare surface from frame
489+ switch (frame->format) {
490+#if CONFIG_D3D11VA
491+ case AV_PIX_FMT_D3D11:
492+ {
493+ static const GUID AMFTextureArrayIndexGUID = { 0x28115527, 0xe7c3, 0x4b66, { 0x99, 0xd3, 0x4f, 0x2a, 0xe6, 0xb4, 0x7f, 0xaf } };
494+ ID3D11Texture2D *texture = (ID3D11Texture2D*)frame->data[0]; // actual texture
495+ int index = (intptr_t)frame->data[1]; // index is a slice in texture array is - set to tell AMF which slice to use
496+ av_assert0(frame->hw_frames_ctx && avctx->hw_frames_ctx &&
497+ frame->hw_frames_ctx->data == avctx->hw_frames_ctx->data);
498+ texture->lpVtbl->SetPrivateData(texture, &AMFTextureArrayIndexGUID, sizeof(index), &index);
499+ res = amf_device_ctx->context->pVtbl->CreateSurfaceFromDX11Native(amf_device_ctx->context, texture, &surface, NULL); // wrap to AMF surface
500+ AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "CreateSurfaceFromDX11Native() failed with error %d\n", res);
501+ hw_surface = 1;
502+ }
503+ break;
504+#endif
505+#if CONFIG_DXVA2
506+ case AV_PIX_FMT_DXVA2_VLD:
507+ {
508+ IDirect3DSurface9 *texture = (IDirect3DSurface9 *)frame->data[3]; // actual texture
509+ res = amf_device_ctx->context->pVtbl->CreateSurfaceFromDX9Native(amf_device_ctx->context, texture, &surface, NULL); // wrap to AMF surface
510+ AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "CreateSurfaceFromDX9Native() failed with error %d\n", res);
511+ hw_surface = 1;
512+ }
513+ break;
514+#endif
515+ case AV_PIX_FMT_AMF_SURFACE:
516+ {
517+ surface = (AMFSurface*)frame->data[0];
518+ surface->pVtbl->Acquire(surface);
519+ hw_surface = 1;
520+ }
521+ break;
522+ default:
523+ {
524+ res = amf_device_ctx->context->pVtbl->AllocSurface(amf_device_ctx->context, AMF_MEMORY_HOST, ctx->format, avctx->width, avctx->height, &surface);
525+ AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "AllocSurface() failed with error %d\n", res);
526+ amf_copy_surface(avctx, frame, surface);
527+ }
528+ break;
529+ }
530+ if (hw_surface) {
531+ amf_store_attached_frame_ref(ctx, frame, surface);
532+ ctx->hwsurfaces_in_queue++;
533+ // input HW surfaces can be vertically aligned by 16; tell AMF the real size
534+ surface->pVtbl->SetCrop(surface, 0, 0, frame->width, frame->height);
535+ }
536+ // HDR10 metadata
537+ if (frame->color_trc == AVCOL_TRC_SMPTE2084) {
538+ AMFBuffer * hdrmeta_buffer = NULL;
539+ res = amf_device_ctx->context->pVtbl->AllocBuffer(amf_device_ctx->context, AMF_MEMORY_HOST, sizeof(AMFHDRMetadata), &hdrmeta_buffer);
540+ if (res == AMF_OK) {
541+ AMFHDRMetadata * hdrmeta = (AMFHDRMetadata*)hdrmeta_buffer->pVtbl->GetNative(hdrmeta_buffer);
542+ if (amf_save_hdr_metadata(avctx, frame, hdrmeta) == 0) {
543+ switch (avctx->codec->id) {
544+ case AV_CODEC_ID_H264:
545+ AMF_ASSIGN_PROPERTY_INTERFACE(res, ctx->encoder, AMF_VIDEO_ENCODER_INPUT_HDR_METADATA, hdrmeta_buffer); break;
546+ case AV_CODEC_ID_HEVC:
547+ AMF_ASSIGN_PROPERTY_INTERFACE(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_INPUT_HDR_METADATA, hdrmeta_buffer); break;
548+ case AV_CODEC_ID_AV1:
549+ AMF_ASSIGN_PROPERTY_INTERFACE(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_INPUT_HDR_METADATA, hdrmeta_buffer); break;
550+ }
551+ res = amf_set_property_buffer(surface, L"av_frame_hdrmeta", hdrmeta_buffer);
552+ AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "SetProperty failed for \"av_frame_hdrmeta\" with error %d\n", res);
553+ }
554+ hdrmeta_buffer->pVtbl->Release(hdrmeta_buffer);
555+ }
556+ }
557+ surface->pVtbl->SetPts(surface, frame->pts);
558+
559+ AMF_ASSIGN_PROPERTY_INT64(res, surface, ctx->pts_property_name, frame->pts);
560+
561+ switch (avctx->codec->id) {
562+ case AV_CODEC_ID_H264:
563+ AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_INSERT_AUD, !!ctx->aud);
564+ switch (frame->pict_type) {
565+ case AV_PICTURE_TYPE_I:
566+ if (ctx->forced_idr) {
567+ AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_INSERT_SPS, 1);
568+ AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_INSERT_PPS, 1);
569+ AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_FORCE_PICTURE_TYPE, AMF_VIDEO_ENCODER_PICTURE_TYPE_IDR);
570+ } else {
571+ AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_FORCE_PICTURE_TYPE, AMF_VIDEO_ENCODER_PICTURE_TYPE_I);
572+ }
573+ break;
574+ case AV_PICTURE_TYPE_P:
575+ AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_FORCE_PICTURE_TYPE, AMF_VIDEO_ENCODER_PICTURE_TYPE_P);
576+ break;
577+ case AV_PICTURE_TYPE_B:
578+ AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_FORCE_PICTURE_TYPE, AMF_VIDEO_ENCODER_PICTURE_TYPE_B);
579+ break;
580+ }
581+ break;
582+ case AV_CODEC_ID_HEVC:
583+ AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_HEVC_INSERT_AUD, !!ctx->aud);
584+ switch (frame->pict_type) {
585+ case AV_PICTURE_TYPE_I:
586+ if (ctx->forced_idr) {
587+ AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_HEVC_INSERT_HEADER, 1);
588+ AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_HEVC_FORCE_PICTURE_TYPE, AMF_VIDEO_ENCODER_HEVC_PICTURE_TYPE_IDR);
589+ } else {
590+ AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_HEVC_FORCE_PICTURE_TYPE, AMF_VIDEO_ENCODER_HEVC_PICTURE_TYPE_I);
591+ }
592+ break;
593+ case AV_PICTURE_TYPE_P:
594+ AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_HEVC_FORCE_PICTURE_TYPE, AMF_VIDEO_ENCODER_HEVC_PICTURE_TYPE_P);
595+ break;
596+ }
597+ break;
598+ case AV_CODEC_ID_AV1:
599+ if (frame->pict_type == AV_PICTURE_TYPE_I) {
600+ if (ctx->forced_idr) {
601+ AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_AV1_FORCE_INSERT_SEQUENCE_HEADER, 1);
602+ AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE, AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE_KEY);
603+ } else {
604+ AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE, AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE_INTRA_ONLY);
605+ }
606+ }
607+ break;
608+ default:
609+ break;
610+ }
611+ // submit surface
612+ res = ctx->encoder->pVtbl->SubmitInput(ctx->encoder, (AMFData*)surface);
613+ if (res == AMF_INPUT_FULL) { // handle full queue
614+ //store surface for later submission
615+ *surface_resubmit = surface;
616+ } else {
617+ surface->pVtbl->Release(surface);
618+ AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "SubmitInput() failed with error %d\n", res);
619+ ctx->submitted_frame++;
620+ ret = av_fifo_write(ctx->timestamp_list, &frame->pts, 1);
621+ if (ret < 0)
622+ return ret;
623+ if(ctx->submitted_frame <= ctx->encoded_frame + max_b_frames + 1)
624+ return AVERROR(EAGAIN); // if frame just submiited - don't poll or wait
625+ }
626+ return 0;
627+}
628+
629+static int amf_submit_frame_locked(AVCodecContext *avctx, AVFrame *frame, AMFSurface **surface_resubmit)
630+{
631+ int ret;
632+ int locked = amf_lock_context(avctx);
633+ if(locked != AMF_OK)
634+ av_log(avctx, AV_LOG_WARNING, "amf_lock_context() failed with %d - should not happen\n", locked);
635+
636+ ret = amf_submit_frame(avctx, frame, surface_resubmit);
637+
638+ if(locked == AMF_OK)
639+ amf_unlock_context(avctx);
640+ return ret;
641+}
642+
374643 int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
375644 {
376645 AMFEncoderContext *ctx = avctx->priv_data;
377646 AVHWDeviceContext *hw_device_ctx = (AVHWDeviceContext*)ctx->device_ctx_ref->data;
378647 AVAMFDeviceContext *amf_device_ctx = (AVAMFDeviceContext *)hw_device_ctx->hwctx;
379− AMFSurface *surface;
648+ AMFSurface *surface = NULL;
380649 AMF_RESULT res;
381650 int ret;
382651 AMF_RESULT res_query;
383652 AMFData *data = NULL;
384653 AVFrame *frame = av_frame_alloc();
385654 int block_and_wait;
386− int input_full = 0;
387− int hw_surface = 0;
388655 int64_t pts = 0;
389656 int max_b_frames = ctx->max_b_frames < 0 ? 0 : ctx->max_b_frames;
390657
@@ -418,158 +685,12 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) · 27 unmodified lines
418685 }
419686 }
420687 } else { // submit frame
421−
422− // prepare surface from frame
423− switch (frame->format) {
424− #if CONFIG_D3D11VA
425− case AV_PIX_FMT_D3D11:
426− {
427− static const GUID AMFTextureArrayIndexGUID = { 0x28115527, 0xe7c3, 0x4b66, { 0x99, 0xd3, 0x4f, 0x2a, 0xe6, 0xb4, 0x7f, 0xaf } };
428− ID3D11Texture2D *texture = (ID3D11Texture2D*)frame->data[0]; // actual texture
429− int index = (intptr_t)frame->data[1]; // index is a slice in texture array is - set to tell AMF which slice to use
430−
431− av_assert0(frame->hw_frames_ctx && avctx->hw_frames_ctx &&
432− frame->hw_frames_ctx->data == avctx->hw_frames_ctx->data);
433−
434− texture->lpVtbl->SetPrivateData(texture, &AMFTextureArrayIndexGUID, sizeof(index), &index);
435−
436− res = amf_device_ctx->context->pVtbl->CreateSurfaceFromDX11Native(amf_device_ctx->context, texture, &surface, NULL); // wrap to AMF surface
437− AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "CreateSurfaceFromDX11Native() failed with error %d\n", res);
438−
439− hw_surface = 1;
440− }
441− break;
442− #endif
443− #if CONFIG_DXVA2
444− case AV_PIX_FMT_DXVA2_VLD:
445− {
446− IDirect3DSurface9 *texture = (IDirect3DSurface9 *)frame->data[3]; // actual texture
447−
448− res = amf_device_ctx->context->pVtbl->CreateSurfaceFromDX9Native(amf_device_ctx->context, texture, &surface, NULL); // wrap to AMF surface
449− AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "CreateSurfaceFromDX9Native() failed with error %d\n", res);
450−
451− hw_surface = 1;
452− }
453− break;
454− #endif
455− case AV_PIX_FMT_AMF_SURFACE:
456− {
457− surface = (AMFSurface*)frame->data[0];
458− surface->pVtbl->Acquire(surface);
459− hw_surface = 1;
460− }
461− break;
462− default:
463− {
464− res = amf_device_ctx->context->pVtbl->AllocSurface(amf_device_ctx->context, AMF_MEMORY_HOST, ctx->format, avctx->width, avctx->height, &surface);
465− AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "AllocSurface() failed with error %d\n", res);
466− amf_copy_surface(avctx, frame, surface);
467− }
468− break;
469− }
470−
471− if (hw_surface) {
472− amf_store_attached_frame_ref(frame, surface);
473− ctx->hwsurfaces_in_queue++;
474− // input HW surfaces can be vertically aligned by 16; tell AMF the real size
475− surface->pVtbl->SetCrop(surface, 0, 0, frame->width, frame->height);
476− }
477−
478− // HDR10 metadata
479− if (frame->color_trc == AVCOL_TRC_SMPTE2084) {
480− AMFBuffer * hdrmeta_buffer = NULL;
481− res = amf_device_ctx->context->pVtbl->AllocBuffer(amf_device_ctx->context, AMF_MEMORY_HOST, sizeof(AMFHDRMetadata), &hdrmeta_buffer);
482− if (res == AMF_OK) {
483− AMFHDRMetadata * hdrmeta = (AMFHDRMetadata*)hdrmeta_buffer->pVtbl->GetNative(hdrmeta_buffer);
484− if (amf_save_hdr_metadata(avctx, frame, hdrmeta) == 0) {
485− switch (avctx->codec->id) {
486− case AV_CODEC_ID_H264:
487− AMF_ASSIGN_PROPERTY_INTERFACE(res, ctx->encoder, AMF_VIDEO_ENCODER_INPUT_HDR_METADATA, hdrmeta_buffer); break;
488− case AV_CODEC_ID_HEVC:
489− AMF_ASSIGN_PROPERTY_INTERFACE(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_INPUT_HDR_METADATA, hdrmeta_buffer); break;
490− case AV_CODEC_ID_AV1:
491− AMF_ASSIGN_PROPERTY_INTERFACE(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_INPUT_HDR_METADATA, hdrmeta_buffer); break;
492− }
493− res = amf_set_property_buffer(surface, L"av_frame_hdrmeta", hdrmeta_buffer);
494− AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, "SetProperty failed for \"av_frame_hdrmeta\" with error %d\n", res);
495− }
496− hdrmeta_buffer->pVtbl->Release(hdrmeta_buffer);
497− }
498− }
499−
500− surface->pVtbl->SetPts(surface, frame->pts);
501− AMF_ASSIGN_PROPERTY_INT64(res, surface, PTS_PROP, frame->pts);
502−
503− switch (avctx->codec->id) {
504− case AV_CODEC_ID_H264:
505− AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_INSERT_AUD, !!ctx->aud);
506− switch (frame->pict_type) {
507− case AV_PICTURE_TYPE_I:
508− if (ctx->forced_idr) {
509− AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_INSERT_SPS, 1);
510− AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_INSERT_PPS, 1);
511− AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_FORCE_PICTURE_TYPE, AMF_VIDEO_ENCODER_PICTURE_TYPE_IDR);
512− } else {
513− AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_FORCE_PICTURE_TYPE, AMF_VIDEO_ENCODER_PICTURE_TYPE_I);
514− }
515− break;
516− case AV_PICTURE_TYPE_P:
517− AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_FORCE_PICTURE_TYPE, AMF_VIDEO_ENCODER_PICTURE_TYPE_P);
518− break;
519− case AV_PICTURE_TYPE_B:
520− AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_FORCE_PICTURE_TYPE, AMF_VIDEO_ENCODER_PICTURE_TYPE_B);
521− break;
522− }
523− break;
524− case AV_CODEC_ID_HEVC:
525− AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_HEVC_INSERT_AUD, !!ctx->aud);
526− switch (frame->pict_type) {
527− case AV_PICTURE_TYPE_I:
528− if (ctx->forced_idr) {
529− AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_HEVC_INSERT_HEADER, 1);
530− AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_HEVC_FORCE_PICTURE_TYPE, AMF_VIDEO_ENCODER_HEVC_PICTURE_TYPE_IDR);
531− } else {
532− AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_HEVC_FORCE_PICTURE_TYPE, AMF_VIDEO_ENCODER_HEVC_PICTURE_TYPE_I);
533− }
534− break;
535− case AV_PICTURE_TYPE_P:
536− AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_HEVC_FORCE_PICTURE_TYPE, AMF_VIDEO_ENCODER_HEVC_PICTURE_TYPE_P);
537− break;
538− }
539− break;
540− case AV_CODEC_ID_AV1:
541− if (frame->pict_type == AV_PICTURE_TYPE_I) {
542− if (ctx->forced_idr) {
543− AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_AV1_FORCE_INSERT_SEQUENCE_HEADER, 1);
544− AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE, AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE_KEY);
545− } else {
546− AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE, AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE_INTRA_ONLY);
547− }
548− }
549− break;
550− default:
551− break;
688+ ret = amf_submit_frame_locked(avctx, frame, &surface);
689+ if(ret < 0){
690+ av_frame_free(&frame);
691+ return ret;
552692 }
553693 pts = frame->pts;
554− // submit surface
555− res = ctx->encoder->pVtbl->SubmitInput(ctx->encoder, (AMFData*)surface);
556− av_frame_free(&frame);
557−
558− if (res == AMF_INPUT_FULL) { // handle full queue
559− //store surface for later submission
560− input_full = 1;
561− } else {
562− surface->pVtbl->Release(surface);
563− AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "SubmitInput() failed with error %d\n", res);
564−
565− ctx->submitted_frame++;
566− ret = av_fifo_write(ctx->timestamp_list, &pts, 1);
567−
568− if (ret < 0)
569− return ret;
570− if(ctx->submitted_frame <= ctx->encoded_frame + max_b_frames + 1)
571− return AVERROR(EAGAIN); // if frame just submiited - don't poll or wait
572− }
573694 }
574695 }
575696 av_frame_free(&frame);
@@ -585,7 +706,7 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) · 9 unmodified lines
585706 AMFGuid guid = IID_AMFBuffer();
586707 data->pVtbl->QueryInterface(data, &guid, (void**)&buffer); // query for buffer interface
587708 ret = amf_copy_buffer(avctx, avpkt, buffer);
588− if (amf_release_attached_frame_ref(buffer) == AMF_OK) {
709+ if (amf_release_attached_frame_ref(ctx, buffer) == AMF_OK) {
589710 ctx->hwsurfaces_in_queue--;
590711 }
591712 ctx->encoded_frame++;
@@ -604,7 +725,7 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) · 12 unmodified lines
604725 av_log(avctx, AV_LOG_WARNING, "Data acquired but delayed drain submission got AMF_INPUT_FULL- should not happen\n");
605726 }
606727 }
607− } else if (ctx->delayed_drain || (ctx->eof && res_query != AMF_EOF) || (ctx->hwsurfaces_in_queue >= ctx->hwsurfaces_in_queue_max) || input_full) {
728+ } else if (ctx->delayed_drain || (ctx->eof && res_query != AMF_EOF) || (ctx->hwsurfaces_in_queue >= ctx->hwsurfaces_in_queue_max) || surface) {
608729 block_and_wait = 1;
609730 // Only sleep if the driver doesn't support waiting in QueryOutput()
610731 // or if we already have output data so we will skip calling it.
@@ -619,7 +740,7 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) · 8 unmodified lines
619740 } else if (data == NULL) {
620741 ret = AVERROR(EAGAIN);
621742 } else {
622− if(input_full) {
743+ if(surface) {
623744 // resubmit surface
624745 res = ctx->encoder->pVtbl->SubmitInput(ctx->encoder, (AMFData*)surface);
625746 surface->pVtbl->Release(surface);
libavcodec/amfenc.h+2−0
@@ -46,6 +46,8 @@ typedef struct AMFEncoderContext { · 45 unmodified lines
4646 AMFComponent *encoder; ///< AMF encoder object
4747 amf_bool eof; ///< flag indicating EOF happened
4848 AMF_SURFACE_FORMAT format; ///< AMF surface format
49+ wchar_t *pts_property_name;
50+ wchar_t *av_frame_property_name;
4951
5052 int hwsurfaces_in_queue;
5153 int hwsurfaces_in_queue_max;
libavutil/hwcontext_amf.h+2−1
@@ -35,8 +35,9 @@ typedef struct AVAMFDeviceContext { · 34 unmodified lines
3535 AMFFactory *factory;
3636 void *trace_writer;
3737
38− int64_t version; ///< version of AMF runtime
38+ int64_t version; ///< version of AMF runtime
3939 AMFContext *context;
40+ AMF_MEMORY_TYPE memory_type;
4041 } AVAMFDeviceContext;
4142
4243 enum AMF_SURFACE_FORMAT av_av_to_amf_format(enum AVPixelFormat fmt);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t