From patchwork Tue Oct 8 14:53:12 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul B Mahol X-Patchwork-Id: 15577 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id A466B44A37B for ; Tue, 8 Oct 2019 17:53:27 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 7EDEF687F52; Tue, 8 Oct 2019 17:53:27 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wm1-f68.google.com (mail-wm1-f68.google.com [209.85.128.68]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 2950B680373 for ; Tue, 8 Oct 2019 17:53:21 +0300 (EEST) Received: by mail-wm1-f68.google.com with SMTP id i16so3503079wmd.3 for ; Tue, 08 Oct 2019 07:53:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id; bh=GKO4pnL9bc1GdvHa3mKukWsouTgwYd9cvs3tkHF0OxE=; b=WJ/dLa3bzFBFeZf11BYlq2Mq+G7Xfu8zPfYhuHCza1Z5MytUTC660mNc8mZ2AMLRe+ HLqgWaVCobLOmeVE68Z2biGxvL0zaXFNS7QiHaSIOrnZNmTNl/q1LH/8UCKUvGRRP514 fxot/87VLEY9j5VX/cg22zu1s4SW9oC4y6LJzQMl8l95R6PPI9c0SmPE5P9DfRLTCuK2 M+BGNLaqNA9JQY3s064M5ZBFzOQHXaMAJPVTPDmMBgFn97XW1grhxWtQfVZBiKXp/P2T Cj+KEXMU0GvG066mux/IscBg4+WE+EwlqJl4hLQWF8vWolxs8cUo/jfvaExxDrHy2IcH qNmA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id; bh=GKO4pnL9bc1GdvHa3mKukWsouTgwYd9cvs3tkHF0OxE=; b=CmmcnXtIKR8HueNtS5Oa2qM4uPD3NLVfaXz+LlmgGKBnRNnHo/lmtWsMB8IdMGJeW6 hN1U9Q+d5Vc0aHPFSugol5iSW6U1YZ7ZQmyOibDHmQvbUI2D9li0wNpRSPnJngCsEDAh 1QcbC0ux0oHHPcjWQeyX6p7pbZV3GNDcb4mcZcFpHrZ/c9p4auq7heV98WlqKKf2j7VI 3WeeZ3Ghl8cZ/YgPOPM0e0QqXHiTqxgQCoEVS7bA4KdfOMRJ/mKIUCY2odeWDuWiLp+b HB7H4L2BR/ByqCY0DtmSPtyfxEwBd38hwzDijYnPUOOxxISAVJfecYXaPOaor8r87AaI bSrg== X-Gm-Message-State: APjAAAURTCHXoRsBCZM+HVX4qnn6ytVApI8e/xAhUmrkHGucnQHzwRlc pJUcqMDLKHlz2+r8fMxXjui9DGqQ X-Google-Smtp-Source: APXvYqyu43dxlaDk5MFmCG5Rq6CAzl01uzACflNtDkH3mKt1XI7BXf5ULs5Uiw5kf+/2wGRHNkfc6g== X-Received: by 2002:a1c:4d0d:: with SMTP id o13mr792853wmh.19.1570546400210; Tue, 08 Oct 2019 07:53:20 -0700 (PDT) Received: from localhost.localdomain ([37.244.240.27]) by smtp.gmail.com with ESMTPSA id o19sm4797531wmh.27.2019.10.08.07.53.18 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 08 Oct 2019 07:53:19 -0700 (PDT) From: Paul B Mahol To: ffmpeg-devel@ffmpeg.org Date: Tue, 8 Oct 2019 16:53:12 +0200 Message-Id: <20191008145312.22000-1-onemda@gmail.com> X-Mailer: git-send-email 2.17.1 Subject: [FFmpeg-devel] [PATCH] avfilter/avf_showwaves: make output frame rate actually follow user supplied value X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Signed-off-by: Paul B Mahol --- libavfilter/avf_showwaves.c | 77 ++++++++++++++++++++++++++++--------- 1 file changed, 58 insertions(+), 19 deletions(-) diff --git a/libavfilter/avf_showwaves.c b/libavfilter/avf_showwaves.c index afe05fb504..532a75b684 100644 --- a/libavfilter/avf_showwaves.c +++ b/libavfilter/avf_showwaves.c @@ -23,6 +23,7 @@ * audio to video multimedia filter */ +#include "libavutil/audio_fifo.h" #include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/channel_layout.h" @@ -70,6 +71,7 @@ typedef struct ShowWavesContext { int buf_idx; int16_t *buf_idy; /* y coordinate of previous sample for each channel */ AVFrame *outpicref; + AVFrame *tmp; int n; int pixstep; int sample_count_mod; @@ -89,6 +91,11 @@ typedef struct ShowWavesContext { struct frame_node *last_frame; int64_t total_samples; int64_t *sum; /* abs sum of the samples per channel */ + int hop_size; + int64_t pts; + int64_t samples_in; + int64_t samples_out; + AVAudioFifo *fifo; } ShowWavesContext; #define OFFSET(x) offsetof(ShowWavesContext, x) @@ -124,6 +131,7 @@ static av_cold void uninit(AVFilterContext *ctx) { ShowWavesContext *showwaves = ctx->priv; + av_frame_free(&showwaves->tmp); av_frame_free(&showwaves->outpicref); av_freep(&showwaves->buf_idy); av_freep(&showwaves->fg); @@ -139,6 +147,8 @@ static av_cold void uninit(AVFilterContext *ctx) } av_freep(&showwaves->sum); showwaves->last_frame = NULL; + } else { + av_audio_fifo_free(showwaves->fifo); } } @@ -413,11 +423,22 @@ static int config_output(AVFilterLink *outlink) uint8_t x; int ch; - if (showwaves->single_pic) + if (showwaves->single_pic) { showwaves->n = 1; + } else { + showwaves->fifo = av_audio_fifo_alloc(inlink->format, inlink->channels, 1024); + if (!showwaves->fifo) + return AVERROR(ENOMEM); + } if (!showwaves->n) showwaves->n = FFMAX(1, av_rescale_q(inlink->sample_rate, av_make_q(1, showwaves->w), showwaves->rate)); + showwaves->hop_size = FFMIN(showwaves->n * showwaves->w, av_rescale(inlink->sample_rate, showwaves->rate.den, showwaves->rate.num)); + if (!showwaves->single_pic) { + showwaves->tmp = ff_get_audio_buffer(inlink, showwaves->n * showwaves->w); + if (!showwaves->tmp) + return AVERROR(ENOMEM); + } showwaves->buf_idx = 0; if (!(showwaves->buf_idy = av_mallocz_array(nb_channels, sizeof(*showwaves->buf_idy)))) { @@ -428,11 +449,12 @@ static int config_output(AVFilterLink *outlink) outlink->h = showwaves->h; outlink->sample_aspect_ratio = (AVRational){1,1}; - outlink->frame_rate = av_div_q((AVRational){inlink->sample_rate,showwaves->n}, - (AVRational){showwaves->w,1}); + outlink->frame_rate = showwaves->rate; + outlink->time_base = inlink->time_base; - av_log(ctx, AV_LOG_VERBOSE, "s:%dx%d r:%f n:%d\n", - showwaves->w, showwaves->h, av_q2d(outlink->frame_rate), showwaves->n); + av_log(ctx, AV_LOG_VERBOSE, "s:%dx%d r:%f n:%d hop:%d tb:%d/%d\n", + showwaves->w, showwaves->h, av_q2d(outlink->frame_rate), showwaves->n, + showwaves->hop_size, outlink->time_base.num, outlink->time_base.den); switch (outlink->format) { case AV_PIX_FMT_GRAY8: @@ -635,7 +657,7 @@ static int request_frame(AVFilterLink *outlink) static int alloc_out_frame(ShowWavesContext *showwaves, const int16_t *p, const AVFilterLink *inlink, AVFilterLink *outlink, - const AVFrame *in) + const AVFrame *in, int64_t pts) { if (!showwaves->outpicref) { int j; @@ -645,9 +667,9 @@ static int alloc_out_frame(ShowWavesContext *showwaves, const int16_t *p, return AVERROR(ENOMEM); out->width = outlink->w; out->height = outlink->h; - out->pts = in->pts + av_rescale_q((p - (int16_t *)in->data[0]) / inlink->channels, - av_make_q(1, inlink->sample_rate), - outlink->time_base); + out->pts = pts + av_rescale_q(showwaves->samples_out + showwaves->n * showwaves->w - showwaves->samples_in, + av_make_q(1, inlink->sample_rate), + outlink->time_base); for (j = 0; j < outlink->h; j++) memset(out->data[0] + j*out->linesize[0], 0, outlink->w * showwaves->pixstep); } @@ -668,7 +690,7 @@ static av_cold int init(AVFilterContext *ctx) #if CONFIG_SHOWWAVES_FILTER -static int showwaves_filter_frame(AVFilterLink *inlink, AVFrame *insamples) +static int showwaves_filter_frame(AVFilterLink *inlink, AVFrame *insamples, int64_t pts) { AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; @@ -685,7 +707,7 @@ static int showwaves_filter_frame(AVFilterLink *inlink, AVFrame *insamples) /* draw data in the buffer */ for (i = 0; i < nb_samples; i++) { - ret = alloc_out_frame(showwaves, p, inlink, outlink, insamples); + ret = alloc_out_frame(showwaves, p, inlink, outlink, insamples, pts); if (ret < 0) goto end; outpicref = showwaves->outpicref; @@ -708,14 +730,16 @@ static int showwaves_filter_frame(AVFilterLink *inlink, AVFrame *insamples) showwaves->buf_idx++; } if (showwaves->buf_idx == showwaves->w || - (ff_outlink_get_status(inlink) && i == nb_samples - 1)) + av_audio_fifo_size(showwaves->fifo) <= 0) { + av_audio_fifo_drain(showwaves->fifo, showwaves->hop_size); + showwaves->samples_out += showwaves->hop_size; if ((ret = push_frame(outlink)) < 0) break; + } outpicref = showwaves->outpicref; } end: - av_frame_free(&insamples); return ret; } @@ -730,11 +754,26 @@ static int activate(AVFilterContext *ctx) FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); - ret = ff_inlink_consume_samples(inlink, nb_samples, nb_samples, &in); - if (ret < 0) - return ret; - if (ret > 0) - return showwaves_filter_frame(inlink, in); + if (av_audio_fifo_size(showwaves->fifo) < nb_samples) { + ret = ff_inlink_consume_samples(inlink, nb_samples, nb_samples, &in); + if (ret < 0) + return ret; + if (ret > 0) { + showwaves->pts = in->pts; + ret = av_audio_fifo_write(showwaves->fifo, (void **)in->extended_data, + in->nb_samples); + showwaves->samples_in += in->nb_samples; + av_frame_free(&in); + if (ret < 0) + return ret; + } + } + if (av_audio_fifo_size(showwaves->fifo) >= nb_samples) { + ret = av_audio_fifo_peek(showwaves->fifo, (void **)showwaves->tmp->extended_data, nb_samples); + if (ret < 0) + return ret; + return showwaves_filter_frame(inlink, showwaves->tmp, showwaves->pts); + } FF_FILTER_FORWARD_STATUS(inlink, outlink); FF_FILTER_FORWARD_WANTED(outlink, inlink); @@ -822,7 +861,7 @@ static int showwavespic_filter_frame(AVFilterLink *inlink, AVFrame *insamples) if (showwaves->single_pic) { struct frame_node *f; - ret = alloc_out_frame(showwaves, p, inlink, outlink, insamples); + ret = alloc_out_frame(showwaves, p, inlink, outlink, insamples, 0); if (ret < 0) goto end;