[FFmpeg-devel] [PATCH] avcodec/amfenc: adapt to the new internal encode API

James Almer jamrial at gmail.com
Sat Apr 4 01:19:01 EEST 2020


Signed-off-by: James Almer <jamrial at gmail.com>
---
 libavcodec/amfenc.c      | 45 ++++++++++++++++++++--------------------
 libavcodec/amfenc.h      |  2 ++
 libavcodec/amfenc_h264.c |  1 -
 libavcodec/amfenc_hevc.c |  1 -
 4 files changed, 25 insertions(+), 24 deletions(-)

diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c
index 876fddd2b6..d318c21978 100644
--- a/libavcodec/amfenc.c
+++ b/libavcodec/amfenc.c
@@ -33,6 +33,7 @@
 #include "libavutil/time.h"
 
 #include "amfenc.h"
+#include "encode.h"
 #include "internal.h"
 
 #if CONFIG_D3D11VA
@@ -112,6 +113,10 @@ static int amf_load_library(AVCodecContext *avctx)
     AMFQueryVersion_Fn version_fun;
     AMF_RESULT         res;
 
+    ctx->frame = av_frame_alloc();
+    if (!ctx->frame) {
+        return AVERROR(ENOMEM);
+    }
     ctx->delayed_frame = av_frame_alloc();
     if (!ctx->delayed_frame) {
         return AVERROR(ENOMEM);
@@ -401,6 +406,7 @@ int av_cold ff_amf_encode_close(AVCodecContext *avctx)
     ctx->factory = NULL;
     ctx->version = 0;
     ctx->delayed_drain = 0;
+    av_frame_free(&ctx->frame);
     av_frame_free(&ctx->delayed_frame);
     av_fifo_freep(&ctx->timestamp_list);
 
@@ -588,17 +594,27 @@ static void amf_release_buffer_with_frame_ref(AMFBuffer *frame_ref_storage_buffe
     frame_ref_storage_buffer->pVtbl->Release(frame_ref_storage_buffer);
 }
 
-int ff_amf_send_frame(AVCodecContext *avctx, const AVFrame *frame)
+int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
 {
     AmfContext *ctx = avctx->priv_data;
     AMFSurface *surface;
     AMF_RESULT  res;
     int         ret;
+    AMF_RESULT  res_query;
+    AMFData    *data = NULL;
+    AVFrame    *frame = ctx->frame;
+    int         block_and_wait;
 
     if (!ctx->encoder)
         return AVERROR(EINVAL);
 
-    if (!frame) { // submit drain
+    if (!frame->buf[0]) {
+        ret = ff_encode_get_frame(avctx, frame);
+        if (ret < 0 && ret != AVERROR_EOF)
+            return ret;
+    }
+
+    if (!frame->buf[0]) { // submit drain
         if (!ctx->eof) { // submit drain one time only
             if (ctx->delayed_surface != NULL) {
                 ctx->delayed_drain = 1; // input queue is full: resubmit Drain() in ff_amf_receive_packet
@@ -613,15 +629,10 @@ int ff_amf_send_frame(AVCodecContext *avctx, const AVFrame *frame)
                     AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "Drain() failed with error %d\n", res);
                 }
             }
-        } else{
-            return AVERROR_EOF;
         }
-    } else { // submit frame
+    } else if (!ctx->delayed_surface) { // submit frame
         int hw_surface = 0;
 
-        if (ctx->delayed_surface != NULL) {
-            return AVERROR(EAGAIN); // should not happen when called from ffmpeg, other clients may resubmit
-        }
         // prepare surface from frame
         switch (frame->format) {
 #if CONFIG_D3D11VA
@@ -693,38 +704,28 @@ int ff_amf_send_frame(AVCodecContext *avctx, const AVFrame *frame)
             break;
         }
 
-
         // submit surface
         res = ctx->encoder->pVtbl->SubmitInput(ctx->encoder, (AMFData*)surface);
         if (res == AMF_INPUT_FULL) { // handle full queue
             //store surface for later submission
             ctx->delayed_surface = surface;
             if (surface->pVtbl->GetMemoryType(surface) == AMF_MEMORY_DX11) {
-                av_frame_ref(ctx->delayed_frame, frame);
+                av_frame_move_ref(ctx->delayed_frame, frame);
             }
         } else {
             surface->pVtbl->Release(surface);
             AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "SubmitInput() failed with error %d\n", res);
 
             if ((ret = timestamp_queue_enqueue(avctx, frame->pts)) < 0) {
+                av_frame_unref(frame);
                 return ret;
             }
 
         }
+
+        av_frame_unref(frame);
     }
-    return 0;
-}
-int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
-{
-    int             ret;
-    AMF_RESULT      res;
-    AMF_RESULT      res_query;
-    AmfContext     *ctx = avctx->priv_data;
-    AMFData        *data = NULL;
-    int             block_and_wait;
 
-    if (!ctx->encoder)
-        return AVERROR(EINVAL);
 
     do {
         block_and_wait = 0;
diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h
index b1361842bd..39cbdc881c 100644
--- a/libavcodec/amfenc.h
+++ b/libavcodec/amfenc.h
@@ -65,6 +65,8 @@ typedef struct AmfContext {
     int                 hwsurfaces_in_queue;
     int                 hwsurfaces_in_queue_max;
 
+    AVFrame            *frame;
+
     // helpers to handle async calls
     int                 delayed_drain;
     AMFSurface         *delayed_surface;
diff --git a/libavcodec/amfenc_h264.c b/libavcodec/amfenc_h264.c
index 7f2817f115..7a8029f3b7 100644
--- a/libavcodec/amfenc_h264.c
+++ b/libavcodec/amfenc_h264.c
@@ -383,7 +383,6 @@ AVCodec ff_h264_amf_encoder = {
     .type           = AVMEDIA_TYPE_VIDEO,
     .id             = AV_CODEC_ID_H264,
     .init           = amf_encode_init_h264,
-    .send_frame     = ff_amf_send_frame,
     .receive_packet = ff_amf_receive_packet,
     .close          = ff_amf_encode_close,
     .priv_data_size = sizeof(AmfContext),
diff --git a/libavcodec/amfenc_hevc.c b/libavcodec/amfenc_hevc.c
index 77e57d2461..8b2302f2af 100644
--- a/libavcodec/amfenc_hevc.c
+++ b/libavcodec/amfenc_hevc.c
@@ -313,7 +313,6 @@ AVCodec ff_hevc_amf_encoder = {
     .type           = AVMEDIA_TYPE_VIDEO,
     .id             = AV_CODEC_ID_HEVC,
     .init           = amf_encode_init_hevc,
-    .send_frame     = ff_amf_send_frame,
     .receive_packet = ff_amf_receive_packet,
     .close          = ff_amf_encode_close,
     .priv_data_size = sizeof(AmfContext),
-- 
2.26.0



More information about the ffmpeg-devel mailing list