[FFmpeg-devel] [PATCH 1/2] avfilter: add ff_inlink_peek_samples and ff_inlink_skip samples
Nicolas George
george at nsup.org
Mon Apr 20 12:25:10 EEST 2020
Paul B Mahol (12020-04-18):
> Signed-off-by: Paul B Mahol <onemda at gmail.com>
> ---
> libavfilter/avfilter.c | 96 ++++++++++++++++++++++++++++++++++++++++++
> libavfilter/filters.h | 17 ++++++++
> 2 files changed, 113 insertions(+)
>
> diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
> index 394811916d..90c73fb64b 100644
> --- a/libavfilter/avfilter.c
> +++ b/libavfilter/avfilter.c
> @@ -1190,6 +1190,61 @@ static int take_samples(AVFilterLink *link, unsigned min, unsigned max,
> return 0;
> }
>
> +static int peek_samples(AVFilterLink *link, unsigned peek_samples,
> + AVFrame **rframe)
> +{
> + AVFrame *frame0, *frame, *buf;
> + unsigned nb_samples, nb_frames, i, p;
> + int ret;
> +
> + /* Note: this function relies on no format changes and must only be
> + called with enough samples. */
> + av_assert1(samples_ready(link, link->min_samples));
> + frame0 = frame = ff_framequeue_peek(&link->fifo, 0);
> + if (!link->fifo.samples_skipped && frame->nb_samples == peek_samples) {
> + *rframe = av_frame_clone(frame);
> + return 0;
> + }
> + nb_frames = 0;
> + nb_samples = 0;
> + while (1) {
> + if (nb_samples + frame->nb_samples >= peek_samples)
> + break;
> + nb_samples += frame->nb_samples;
> + nb_frames++;
> + if (nb_frames == ff_framequeue_queued_frames(&link->fifo))
> + break;
> + frame = ff_framequeue_peek(&link->fifo, nb_frames);
> + }
> +
> + buf = ff_get_audio_buffer(link, peek_samples);
> + if (!buf)
> + return AVERROR(ENOMEM);
> + ret = av_frame_copy_props(buf, frame0);
> + if (ret < 0) {
> + av_frame_free(&buf);
> + return ret;
> + }
> + buf->pts = frame0->pts;
> +
> + p = 0;
> + for (i = 0; i < nb_frames; i++) {
> + frame = ff_framequeue_peek(&link->fifo, i);
> + av_samples_copy(buf->extended_data, frame->extended_data, p, 0,
> + frame->nb_samples, link->channels, link->format);
> + p += frame->nb_samples;
> + }
> + if (p < peek_samples) {
> + unsigned n = peek_samples - p;
> + frame = ff_framequeue_peek(&link->fifo, i);
> + av_samples_copy(buf->extended_data, frame->extended_data, p, 0, n,
> + link->channels, link->format);
> + }
> +
> + *rframe = buf;
> + return 0;
> +}
This is a copy-paste of take_samples() with only minimal changes. Please
make more effort to share the code.
> +
> static int ff_filter_frame_to_filter(AVFilterLink *link)
> {
> AVFrame *frame = NULL;
> @@ -1512,6 +1567,47 @@ int ff_inlink_consume_samples(AVFilterLink *link, unsigned min, unsigned max,
> return 1;
> }
>
> +int ff_inlink_peek_samples(AVFilterLink *link, unsigned nb_samples,
> + AVFrame **rframe)
> +{
> + AVFrame *frame;
> + int ret;
> +
> + av_assert1(nb_samples);
> + *rframe = NULL;
> + if (!ff_inlink_check_available_samples(link, nb_samples))
> + return 0;
> + if (link->status_in)
> + nb_samples = FFMIN(nb_samples, ff_framequeue_queued_samples(&link->fifo));
> + ret = peek_samples(link, nb_samples, &frame);
> + if (ret < 0)
> + return ret;
> + *rframe = frame;
> + return !!frame;
> +}
> +
> +void ff_inlink_skip_samples(AVFilterLink *link, unsigned skip_samples)
> +{
> + while (skip_samples > 0) {
> + AVFrame *frame = ff_inlink_peek_frame(link, 0);
> + if (skip_samples >= frame->nb_samples) {
> + frame = ff_framequeue_take(&link->fifo);
> + skip_samples -= frame->nb_samples;
> + av_frame_free(&frame);
> + } else {
> + break;
> + }
> + }
> +
> + if (skip_samples)
> + ff_framequeue_skip_samples(&link->fifo, skip_samples, link->time_base);
> +
> + if (ff_inlink_queued_frames(link)) {
> + AVFrame *frame = ff_inlink_peek_frame(link, 0);
> + consume_update(link, frame);
> + }
> +}
> +
> AVFrame *ff_inlink_peek_frame(AVFilterLink *link, size_t idx)
> {
> return ff_framequeue_peek(&link->fifo, idx);
> diff --git a/libavfilter/filters.h b/libavfilter/filters.h
> index 1157755403..7dc0b35981 100644
> --- a/libavfilter/filters.h
> +++ b/libavfilter/filters.h
> @@ -115,6 +115,23 @@ int ff_inlink_consume_frame(AVFilterLink *link, AVFrame **rframe);
> int ff_inlink_consume_samples(AVFilterLink *link, unsigned min, unsigned max,
> AVFrame **rframe);
>
> +/**
> + * Peek samples from the link's FIFO.
> + *
> + * @return >0 if a samples are available,
> + * 0 and set rframe to NULL if no samples are available,
> + * or AVERROR code
> + */
> +int ff_inlink_peek_samples(AVFilterLink *link, unsigned nb_samples,
> + AVFrame **rframe);
> +
> +/**
> + * Skip samples from the link's FIFO.
> + *
> + * @note May trigger process_command() and/or update is_disabled.
> + */
> +void ff_inlink_skip_samples(AVFilterLink *link, unsigned skip);
> +
> /**
> * Access a frame in the link fifo without consuming it.
> * The first frame is numbered 0; the designated frame must exist.
Regards,
--
Nicolas George
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <https://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20200420/a966c091/attachment.sig>
More information about the ffmpeg-devel
mailing list