[FFmpeg-cvslog] avcodec/nvenc: replace custom FIFOs with AVFifos

Andrey Turkin git at videolan.org
Wed May 25 12:53:14 CEST 2016


ffmpeg | branch: master | Andrey Turkin <andrey.turkin at gmail.com> | Fri May 20 19:13:20 2016 +0300| [cfb49fc6f797fb03fe9e02ebb58171a8d5e34437] | committer: Timo Rothenpieler

avcodec/nvenc: replace custom FIFOs with AVFifos

Signed-off-by: Timo Rothenpieler <timo at rothenpieler.org>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=cfb49fc6f797fb03fe9e02ebb58171a8d5e34437
---

 libavcodec/nvenc.c |  187 ++++++++++++++--------------------------------------
 1 file changed, 50 insertions(+), 137 deletions(-)

diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c
index 8624aac..5ba0171 100644
--- a/libavcodec/nvenc.c
+++ b/libavcodec/nvenc.c
@@ -27,6 +27,7 @@
 
 #include <nvEncodeAPI.h>
 
+#include "libavutil/fifo.h"
 #include "libavutil/internal.h"
 #include "libavutil/imgutils.h"
 #include "libavutil/avassert.h"
@@ -89,15 +90,6 @@ typedef struct NvencData
     } u;
 } NvencData;
 
-typedef struct NvencDataList
-{
-    NvencData* data;
-
-    uint32_t pos;
-    uint32_t count;
-    uint32_t size;
-} NvencDataList;
-
 typedef struct NvencDynLoadFunctions
 {
     PCUINIT cu_init;
@@ -141,9 +133,9 @@ typedef struct NvencContext
     int max_surface_count;
     NvencSurface *surfaces;
 
-    NvencDataList output_surface_queue;
-    NvencDataList output_surface_ready_queue;
-    NvencDataList timestamp_list;
+    AVFifoBuffer *output_surface_queue;
+    AVFifoBuffer *output_surface_ready_queue;
+    AVFifoBuffer *timestamp_list;
     int64_t last_dts;
 
     void *nvencoder;
@@ -279,105 +271,18 @@ static int input_string_to_uint32(AVCodecContext *avctx, const NvencValuePair *p
     return AVERROR(EINVAL);
 }
 
-static NvencData* data_queue_dequeue(NvencDataList* queue)
-{
-    uint32_t mask;
-    uint32_t read_pos;
-
-    av_assert0(queue);
-    av_assert0(queue->size);
-    av_assert0(queue->data);
-
-    if (!queue->count)
-        return NULL;
-
-    /* Size always is a multiple of two */
-    mask = queue->size - 1;
-    read_pos = (queue->pos - queue->count) & mask;
-    queue->count--;
-
-    return &queue->data[read_pos];
-}
-
-static int data_queue_enqueue(NvencDataList* queue, NvencData *data)
-{
-    NvencDataList new_queue;
-    NvencData* tmp_data;
-    uint32_t mask;
-
-    if (!queue->size) {
-        /* size always has to be a multiple of two */
-        queue->size = 4;
-        queue->pos = 0;
-        queue->count = 0;
-
-        queue->data = av_malloc(queue->size * sizeof(*(queue->data)));
-
-        if (!queue->data) {
-            queue->size = 0;
-            return AVERROR(ENOMEM);
-        }
-    }
-
-    if (queue->count == queue->size) {
-        new_queue.size = queue->size << 1;
-        new_queue.pos = 0;
-        new_queue.count = 0;
-        new_queue.data = av_malloc(new_queue.size * sizeof(*(queue->data)));
-
-        if (!new_queue.data)
-            return AVERROR(ENOMEM);
-
-        while (tmp_data = data_queue_dequeue(queue))
-            data_queue_enqueue(&new_queue, tmp_data);
-
-        av_free(queue->data);
-        *queue = new_queue;
-    }
-
-    mask = queue->size - 1;
-
-    queue->data[queue->pos] = *data;
-    queue->pos = (queue->pos + 1) & mask;
-    queue->count++;
-
-    return 0;
-}
-
-static int out_surf_queue_enqueue(NvencDataList* queue, NvencSurface* surface)
-{
-    NvencData data;
-    data.u.surface = surface;
-
-    return data_queue_enqueue(queue, &data);
-}
-
-static NvencSurface* out_surf_queue_dequeue(NvencDataList* queue)
+static void timestamp_queue_enqueue(AVFifoBuffer* queue, int64_t timestamp)
 {
-    NvencData* res = data_queue_dequeue(queue);
-
-    if (!res)
-        return NULL;
-
-    return res->u.surface;
+    av_fifo_generic_write(queue, &timestamp, sizeof(timestamp), NULL);
 }
 
-static int timestamp_queue_enqueue(NvencDataList* queue, int64_t timestamp)
+static int64_t timestamp_queue_dequeue(AVFifoBuffer* queue)
 {
-    NvencData data;
-    data.u.timestamp = timestamp;
+    int64_t timestamp = AV_NOPTS_VALUE;
+    if (av_fifo_size(queue) > 0)
+        av_fifo_generic_read(queue, &timestamp, sizeof(timestamp), NULL);
 
-    return data_queue_enqueue(queue, &data);
-}
-
-static int64_t timestamp_queue_dequeue(NvencDataList* queue)
-{
-    NvencData* res = data_queue_dequeue(queue);
-
-    if (!res)
-        return AV_NOPTS_VALUE;
-
-    return res->u.timestamp;
+    return timestamp;
 }
 
 #define CHECK_LOAD_FUNC(t, f, s) \
@@ -1218,6 +1123,16 @@ static av_cold int nvenc_setup_surfaces(AVCodecContext *avctx, int* surfaceCount
         return AVERROR(ENOMEM);
     }
 
+    ctx->timestamp_list = av_fifo_alloc(ctx->max_surface_count * sizeof(int64_t));
+    if (!ctx->timestamp_list)
+        return AVERROR(ENOMEM);
+    ctx->output_surface_queue = av_fifo_alloc(ctx->max_surface_count * sizeof(NvencSurface*));
+    if (!ctx->output_surface_queue)
+        return AVERROR(ENOMEM);
+    ctx->output_surface_ready_queue = av_fifo_alloc(ctx->max_surface_count * sizeof(NvencSurface*));
+    if (!ctx->output_surface_ready_queue)
+        return AVERROR(ENOMEM);
+
     for (*surfaceCount = 0; *surfaceCount < ctx->max_surface_count; ++*surfaceCount) {
         res = nvenc_alloc_surface(avctx, *surfaceCount);
         if (res)
@@ -1298,11 +1213,15 @@ static av_cold int nvenc_encode_init(AVCodecContext *avctx)
     return 0;
 
 error:
+    av_fifo_freep(&ctx->timestamp_list);
+    av_fifo_freep(&ctx->output_surface_ready_queue);
+    av_fifo_freep(&ctx->output_surface_queue);
 
     for (i = 0; i < surfaceCount; ++i) {
         p_nvenc->nvEncDestroyInputBuffer(ctx->nvencoder, ctx->surfaces[i].input_surface);
         p_nvenc->nvEncDestroyBitstreamBuffer(ctx->nvencoder, ctx->surfaces[i].output_surface);
     }
+    av_freep(&ctx->surfaces);
 
     if (ctx->nvencoder)
         p_nvenc->nvEncDestroyEncoder(ctx->nvencoder);
@@ -1325,14 +1244,15 @@ static av_cold int nvenc_encode_close(AVCodecContext *avctx)
     NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
     int i;
 
-    av_freep(&ctx->timestamp_list.data);
-    av_freep(&ctx->output_surface_ready_queue.data);
-    av_freep(&ctx->output_surface_queue.data);
+    av_fifo_freep(&ctx->timestamp_list);
+    av_fifo_freep(&ctx->output_surface_ready_queue);
+    av_fifo_freep(&ctx->output_surface_queue);
 
     for (i = 0; i < ctx->max_surface_count; ++i) {
         p_nvenc->nvEncDestroyInputBuffer(ctx->nvencoder, ctx->surfaces[i].input_surface);
         p_nvenc->nvEncDestroyBitstreamBuffer(ctx->nvencoder, ctx->surfaces[i].output_surface);
     }
+    av_freep(&ctx->surfaces);
     ctx->max_surface_count = 0;
 
     p_nvenc->nvEncDestroyEncoder(ctx->nvencoder);
@@ -1548,7 +1468,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
         (lock_params.frameAvgQP - 1) * FF_QP2LAMBDA, NULL, 0, pict_type);
 
     pkt->pts = lock_params.outputTimeStamp;
-    pkt->dts = timestamp_queue_dequeue(&ctx->timestamp_list);
+    pkt->dts = timestamp_queue_dequeue(ctx->timestamp_list);
 
     /* when there're b frame(s), set dts offset */
     if (ctx->encode_config.frameIntervalP >= 2)
@@ -1569,11 +1489,20 @@ FF_ENABLE_DEPRECATION_WARNINGS
 error:
 
     av_free(slice_offsets);
-    timestamp_queue_dequeue(&ctx->timestamp_list);
+    timestamp_queue_dequeue(ctx->timestamp_list);
 
     return res;
 }
 
+static int output_ready(NvencContext *ctx, int flush)
+{
+    int nb_ready, nb_pending;
+
+    nb_ready   = av_fifo_size(ctx->output_surface_ready_queue)   / sizeof(NvencSurface*);
+    nb_pending = av_fifo_size(ctx->output_surface_queue)         / sizeof(NvencSurface*);
+    return nb_ready > 0 && (flush || nb_ready + nb_pending >= ctx->buffer_delay);
+}
+
 static int nvenc_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
     const AVFrame *frame, int *got_packet)
 {
@@ -1621,48 +1550,32 @@ static int nvenc_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
 
         nvenc_codec_specific_pic_params(avctx, &pic_params);
 
-        res = timestamp_queue_enqueue(&ctx->timestamp_list, frame->pts);
-
-        if (res) {
-            inSurf->lockCount = 0;
-            return res;
-        }
+        timestamp_queue_enqueue(ctx->timestamp_list, frame->pts);
     } else {
         pic_params.encodePicFlags = NV_ENC_PIC_FLAG_EOS;
     }
 
     nv_status = p_nvenc->nvEncEncodePicture(ctx->nvencoder, &pic_params);
 
-    if (frame && nv_status == NV_ENC_ERR_NEED_MORE_INPUT) {
-        res = out_surf_queue_enqueue(&ctx->output_surface_queue, inSurf);
-
-        if (res)
-            return res;
-    }
+    if (frame && nv_status == NV_ENC_ERR_NEED_MORE_INPUT)
+        av_fifo_generic_write(ctx->output_surface_queue, &inSurf, sizeof(inSurf), NULL);
 
     if (nv_status != NV_ENC_SUCCESS && nv_status != NV_ENC_ERR_NEED_MORE_INPUT) {
         return nvenc_print_error(avctx, nv_status, "EncodePicture failed!");
     }
 
     if (nv_status != NV_ENC_ERR_NEED_MORE_INPUT) {
-        while (ctx->output_surface_queue.count) {
-            tmpoutsurf = out_surf_queue_dequeue(&ctx->output_surface_queue);
-            res = out_surf_queue_enqueue(&ctx->output_surface_ready_queue, tmpoutsurf);
-
-            if (res)
-                return res;
+        while (av_fifo_size(ctx->output_surface_queue) > 0) {
+            av_fifo_generic_read(ctx->output_surface_queue, &tmpoutsurf, sizeof(tmpoutsurf), NULL);
+            av_fifo_generic_write(ctx->output_surface_ready_queue, &tmpoutsurf, sizeof(tmpoutsurf), NULL);
         }
 
-        if (frame) {
-            res = out_surf_queue_enqueue(&ctx->output_surface_ready_queue, inSurf);
-
-            if (res)
-                return res;
-        }
+        if (frame)
+            av_fifo_generic_write(ctx->output_surface_ready_queue, &inSurf, sizeof(inSurf), NULL);
     }
 
-    if (ctx->output_surface_ready_queue.count && (!frame || ctx->output_surface_ready_queue.count + ctx->output_surface_queue.count >= ctx->buffer_delay)) {
-        tmpoutsurf = out_surf_queue_dequeue(&ctx->output_surface_ready_queue);
+    if (output_ready(ctx, !frame)) {
+        av_fifo_generic_read(ctx->output_surface_ready_queue, &tmpoutsurf, sizeof(tmpoutsurf), NULL);
 
         res = process_output_surface(avctx, pkt, tmpoutsurf);
 



More information about the ffmpeg-cvslog mailing list