[FFmpeg-devel] [PATCH] avfilter/avf_showcqt: fix frame management

Muhammad Faiz mfcc64 at gmail.com
Tue Oct 13 07:18:58 CEST 2015


-------------- next part --------------
From 893d4068adb9d3d2c118186bdc5645056f0ef172 Mon Sep 17 00:00:00 2001
From: Muhammad Faiz <mfcc64 at gmail.com>
Date: Tue, 13 Oct 2015 12:06:37 +0700
Subject: [PATCH] avfilter/avf_showcqt: fix frame management

follow frame writability rule
reuse buffer
---
 libavfilter/avf_showcqt.c | 61 +++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 51 insertions(+), 10 deletions(-)

diff --git a/libavfilter/avf_showcqt.c b/libavfilter/avf_showcqt.c
index e939d8f..5d5fa6c 100644
--- a/libavfilter/avf_showcqt.c
+++ b/libavfilter/avf_showcqt.c
@@ -60,9 +60,12 @@ typedef struct {
     int start, len;
 } Coeffs;
 
+#define NB_OUTPICREF_MAX 16
+
 typedef struct {
     const AVClass *class;
-    AVFrame *outpicref;
+    AVFrame *outpicref[NB_OUTPICREF_MAX];
+    int nb_outpicref;
     FFTContext *fft_context;
     FFTComplex *fft_data;
     FFTComplex *fft_result;
@@ -123,7 +126,8 @@ static av_cold void uninit(AVFilterContext *ctx)
     av_freep(&s->fft_result);
     av_freep(&s->spectogram);
     av_freep(&s->font_alpha);
-    av_frame_free(&s->outpicref);
+    for (k = 0; k < s->nb_outpicref; k++)
+        av_frame_free(&s->outpicref[k]);
 }
 
 static int query_formats(AVFilterContext *ctx)
@@ -428,11 +432,12 @@ static int config_output(AVFilterLink *outlink)
     s->remaining_fill = fft_len >> 1;
     memset(s->fft_data, 0, fft_len * sizeof(*s->fft_data));
 
-    s->outpicref = ff_get_video_buffer(outlink, outlink->w, outlink->h);
-    if (!s->outpicref)
+    s->outpicref[0] = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+    if (!s->outpicref[0])
         return AVERROR(ENOMEM);
+    s->nb_outpicref = 1;
 
-    s->spectogram = av_calloc(spectogram_height, s->outpicref->linesize[0]);
+    s->spectogram = av_calloc(spectogram_height, s->outpicref[0]->linesize[0]);
     if (!s->spectogram)
         return AVERROR(ENOMEM);
 
@@ -456,7 +461,7 @@ static int plot_cqt(AVFilterLink *inlink)
     int fft_len = 1 << s->fft_bits;
     FFTSample result[VIDEO_WIDTH][4];
     int x, y, ret = 0;
-    int linesize = s->outpicref->linesize[0];
+    int linesize = s->outpicref[0]->linesize[0];
     int video_scale = s->fullhd ? 2 : 1;
     int video_width = (VIDEO_WIDTH/2) * video_scale;
     int spectogram_height = (SPECTOGRAM_HEIGHT/2) * video_scale;
@@ -549,10 +554,46 @@ static int plot_cqt(AVFilterLink *inlink)
 
     /* drawing */
     if (!s->spectogram_count) {
-        uint8_t *data = (uint8_t*) s->outpicref->data[0];
+        AVFrame *outpic = NULL;
+        uint8_t *data;
         float rcp_result[VIDEO_WIDTH];
         int total_length = linesize * spectogram_height;
         int back_length = linesize * s->spectogram_index;
+        int pic_idx;
+
+        /* reuse buffer if it is available */
+        /* faster, but not writable to next filters */
+        /* become slower if next filters need writable frame */
+        for (pic_idx = 0; pic_idx < s->nb_outpicref; pic_idx++) {
+            if (av_frame_is_writable(s->outpicref[pic_idx])) {
+                outpic = av_frame_clone(s->outpicref[pic_idx]);
+                break;
+            }
+        }
+
+        /* allocate buffer and make it reusable if it is possible */
+        if (pic_idx == s->nb_outpicref) {
+            if (s->nb_outpicref < NB_OUTPICREF_MAX) {
+                s->nb_outpicref++;
+                av_log(ctx, AV_LOG_DEBUG, "allocating reusable buffer (nb_outpicref = %d) "
+                       "at frame %"PRId64"\n", s->nb_outpicref, s->frame_count);
+                s->outpicref[pic_idx] = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+                if (!s->outpicref[pic_idx])
+                    return AVERROR(ENOMEM);
+                outpic = av_frame_clone(s->outpicref[pic_idx]);
+            } else {
+                av_log(ctx, AV_LOG_DEBUG, "allocating buffer at frame %"PRId64"\n",
+                       s->frame_count);
+                outpic = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+            }
+        }
+
+        if (!outpic)
+            return AVERROR(ENOMEM);
+        data = outpic->data[0];
+        /* linesize should be consistent accross different call to ff_get_video_buffer */
+        /* needed for drawing sonogram */
+        av_assert0(outpic->linesize[0] == linesize);
 
         for (x = 0; x < video_width; x++)
             rcp_result[x] = 1.0f / (result[x][3]+0.0001f);
@@ -645,8 +686,8 @@ static int plot_cqt(AVFilterLink *inlink)
         if (back_length)
             memcpy(data, s->spectogram, back_length);
 
-        s->outpicref->pts = s->frame_count;
-        ret = ff_filter_frame(outlink, av_frame_clone(s->outpicref));
+        outpic->pts = s->frame_count;
+        ret = ff_filter_frame(outlink, outpic);
         s->frame_count++;
     }
     s->spectogram_count = (s->spectogram_count + 1) % s->count;
@@ -721,7 +762,7 @@ static int request_frame(AVFilterLink *outlink)
     int ret;
 
     ret = ff_request_frame(inlink);
-    if (ret == AVERROR_EOF && s->outpicref)
+    if (ret == AVERROR_EOF && s->outpicref[0])
         filter_frame(inlink, NULL);
     return ret;
 }
-- 
1.8.3.1



More information about the ffmpeg-devel mailing list