Signed-off-by: Paul B Mahol <one...@gmail.com> --- 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; -- 2.17.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".