[FFmpeg-devel] [PATCH] AMF Encoder: fix issue with frame corruption if encoder connected directly to decoder

2018-03-23 Thread Kravchenko, Alexander
Hello,
I am collaborating with AMD to integrate and support AMF integration FFmpeg

This patch solves issue with frame corruption if encoder connected directly to 
decoder
Solution: storing frame reference while it is used during encoding

From 0fae3679bae8e121ed7b997d7eabd533deb113fb Mon Sep 17 00:00:00 2001
From: Alexander Kravchenko 
Date: Fri, 23 Mar 2018 12:50:21 +0300
Subject: [PATCH] AMF Encoder: fix issue with frame corruption if encoder
 connected directly to decoder. Solution: storing frame reference while it is 
used during encoding

---
 libavcodec/amfenc.c | 64 ++---
 1 file changed, 61 insertions(+), 3 deletions(-)

diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c
index 89a10ff253..9ffc52b0b0 100644
--- a/libavcodec/amfenc.c
+++ b/libavcodec/amfenc.c
@@ -443,6 +443,41 @@ int ff_amf_encode_init(AVCodecContext *avctx)
 return ret;
 }

+#define AV_AMF_QUERY_INTERFACE(res, from, InterfaceType, to ) \
+{ \
+AMFGuid guid_##InterfaceType = IID_##InterfaceType(); \
+res = from->pVtbl->QueryInterface(from, &guid_##InterfaceType, 
(void**)&to); \
+}
+
+#define AV_AMF_ASSIGN_PROPERTY_INTERFACE(res, pThis, name, val ) \
+{ \
+AMFInterface *amf_interface; \
+AV_AMF_QUERY_INTERFACE(res, val, AMFInterface, amf_interface)\
+if(res == AMF_OK) { \
+AMFVariantStruct var; \
+AMFVariantInit(&var); \
+AMFVariantAssignInterface(&var, amf_interface); \
+amf_interface->pVtbl->Release(amf_interface); \
+res = pThis->pVtbl->SetProperty(pThis, name, var); \
+AMFVariantClear(&var); \
+} \
+}
+
+#define AV_AMF_GET_PROPERTY_INTERFACE(res, pThis, name, target_type, val) \
+{ \
+AMFVariantStruct var; \
+AMFVariantInit(&var); \
+res = pThis->pVtbl->GetProperty(pThis, name, &var); \
+if(res == AMF_OK) { \
+if(var.type == AMF_VARIANT_INTERFACE && var.pInterface) { \
+AMFGuid guid = IID_##target_type(); \
+res = var.pInterface->pVtbl->QueryInterface(var.pInterface, 
&guid, (void**)&val); \
+} else { \
+res = AMF_INVALID_DATA_TYPE; \
+} \
+AMFVariantClear(&var); \
+} \
+}

 int ff_amf_send_frame(AVCodecContext *avctx, const AVFrame *frame)
 {
@@ -484,6 +519,8 @@ int ff_amf_send_frame(AVCodecContext *avctx, const AVFrame 
*frame)
 (ctx->hw_device_ctx && 
((AVHWFramesContext*)frame->hw_frames_ctx->data)->device_ctx ==
 (AVHWDeviceContext*)ctx->hw_device_ctx->data)
 )) {
+AVFrame* frame_ref = av_frame_clone(frame);
+AMFBuffer* frame_ref_storage_buffer;
 #if CONFIG_D3D11VA
 static const GUID AMFTextureArrayIndexGUID = { 0x28115527, 0xe7c3, 
0x4b66, { 0x99, 0xd3, 0x4f, 0x2a, 0xe6, 0xb4, 0x7f, 0xaf } };
 ID3D11Texture2D *texture = (ID3D11Texture2D*)frame->data[0]; // 
actual texture
@@ -496,6 +533,12 @@ int ff_amf_send_frame(AVCodecContext *avctx, const AVFrame 
*frame)
 // input HW surfaces can be vertically aligned by 16; tell AMF the 
real size
 surface->pVtbl->SetCrop(surface, 0, 0, frame->width, 
frame->height);
 #endif
+res = ctx->context->pVtbl->AllocBuffer(ctx->context, 
AMF_MEMORY_HOST, sizeof(frame_ref), &frame_ref_storage_buffer);
+AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), 
"AllocBuffer() failed  with error %d\n", res);
+
memcpy(frame_ref_storage_buffer->pVtbl->GetNative(frame_ref_storage_buffer), 
&frame_ref, sizeof(frame_ref));
+
+AV_AMF_ASSIGN_PROPERTY_INTERFACE(res, surface, L"av_frame_ref", 
frame_ref_storage_buffer);
+frame_ref_storage_buffer->pVtbl->Release(frame_ref_storage_buffer);
 } else {
 res = ctx->context->pVtbl->AllocSurface(ctx->context, 
AMF_MEMORY_HOST, ctx->format, avctx->width, avctx->height, &surface);
 AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), 
"AllocSurface() failed  with error %d\n", res);
@@ -555,11 +598,26 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket 
*avpkt)
 if (data) {
 // copy data to packet
 AMFBuffer* buffer;
-AMFGuid guid = IID_AMFBuffer();
-data->pVtbl->QueryInterface(data, &guid, (void**)&buffer); // 
query for buffer interface
+AV_AMF_QUERY_INTERFACE(res, data, AMFBuffer, buffer);
+AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "Invalid 
data type from encoder->QueryOutput, should be AMFBuffer, error %d\n", res);
 ret = amf_copy_buffer(avctx, avpkt, buffer);
-
 buffer->pVtbl->Release(buffer);
+
+//try to get attached av_frame_ref and unref
+if(data->pVtbl->HasProperty(data, L"av_frame_ref")) {
+AMFBuffer *frame_ref_storage_buffer = NULL;
+AVFrame *av_fr

Re: [FFmpeg-devel] [PATCH] AMF Encoder: fix issue with frame corruption if encoder connected directly to decoder

2018-03-23 Thread Carl Eugen Hoyos
2018-03-23 11:20 GMT+01:00, Kravchenko, Alexander :

> Subject: [PATCH] AMF Encoder: fix issue with frame corruption if encoder
>  connected directly to decoder. Solution: storing frame reference while it
> is used during encoding

The commit message should start with something similar to "lavc/amfenc: "
and should have a first line ~70 characters followed by two CR/LFs
followed by more information if useful.

[...]

> This e-mail and any attachment(s) are intended only for the recipient(s)
> named above and others who have been specifically authorized to receive
> them. They may contain confidential information.

Please remove this from mails sent to the public mailing list of an
open-source project.

Carl Eugen
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel