[FFmpeg-devel] [PATCH 1/2] avfilter: add ff_inlink_peek_samples and ff_inlink_skip samples
Paul B Mahol
onemda at gmail.com
Sat Apr 18 14:59:30 EEST 2020
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;
+}
+
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.
--
2.17.1
More information about the ffmpeg-devel
mailing list