[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