[FFmpeg-devel] [PATCH] lavfi: make ff_framequeue_skip_samples() more useful.
Nicolas George
george at nsup.org
Sun Jan 29 11:17:03 EET 2017
Instead of just updating statistics, have it actually do the work
instead of leaving that job to the call site.
Also: skip the samples by updating the frame data pointers
instead of moving the samples. More efficient and avoid writing
into shared frames.
Found-By: Muhammad Faiz <mfcc64 at gmail.com>
Signed-off-by: Nicolas George <george at nsup.org>
---
libavfilter/avfilter.c | 8 +-------
libavfilter/framequeue.c | 27 +++++++++++++++++++++++++++
libavfilter/framequeue.h | 11 +++++------
3 files changed, 33 insertions(+), 13 deletions(-)
diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
index c12d4912a8..b431990edc 100644
--- a/libavfilter/avfilter.c
+++ b/libavfilter/avfilter.c
@@ -1235,13 +1235,7 @@ static int take_samples(AVFilterLink *link, unsigned min, unsigned max,
frame = ff_framequeue_peek(&link->fifo, 0);
av_samples_copy(buf->extended_data, frame->extended_data, p, 0, n,
link->channels, link->format);
- frame->nb_samples -= n;
- av_samples_copy(frame->extended_data, frame->extended_data, 0, n,
- frame->nb_samples, link->channels, link->format);
- if (frame->pts != AV_NOPTS_VALUE)
- frame->pts += av_rescale_q(n, av_make_q(1, link->sample_rate), link->time_base);
- ff_framequeue_update_peeked(&link->fifo, 0);
- ff_framequeue_skip_samples(&link->fifo, n);
+ ff_framequeue_skip_samples(&link->fifo, n, link->time_base);
}
*rframe = buf;
diff --git a/libavfilter/framequeue.c b/libavfilter/framequeue.c
index a4ffa86c95..26bfa49967 100644
--- a/libavfilter/framequeue.c
+++ b/libavfilter/framequeue.c
@@ -121,3 +121,30 @@ AVFrame *ff_framequeue_peek(FFFrameQueue *fq, size_t idx)
check_consistency(fq);
return b->frame;
}
+
+void ff_framequeue_skip_samples(FFFrameQueue *fq, size_t samples, AVRational time_base)
+{
+ FFFrameBucket *b;
+ size_t bytes;
+ int planar, planes, i;
+
+ check_consistency(fq);
+ av_assert1(fq->queued);
+ b = bucket(fq, 0);
+ av_assert1(samples < b->frame->nb_samples);
+ planar = av_sample_fmt_is_planar(b->frame->format);
+ planes = planar ? b->frame->channels : 1;
+ bytes = samples * av_get_bytes_per_sample(b->frame->format);
+ if (!planar)
+ bytes *= b->frame->channels;
+ if (b->frame->pts != AV_NOPTS_VALUE)
+ b->frame->pts += av_rescale_q(samples, av_make_q(1, b->frame->sample_rate), time_base);
+ b->frame->nb_samples -= samples;
+ b->frame->linesize[0] -= bytes;
+ for (i = 0; i < planes; i++)
+ b->frame->extended_data[i] += bytes;
+ for (i = 0; i < planes && i < AV_NUM_DATA_POINTERS; i++)
+ b->frame->data[i] = b->frame->extended_data[i];
+ fq->total_samples_tail += samples;
+ ff_framequeue_update_peeked(fq, 0);
+}
diff --git a/libavfilter/framequeue.h b/libavfilter/framequeue.h
index f5ef744638..5aa2c725a7 100644
--- a/libavfilter/framequeue.h
+++ b/libavfilter/framequeue.h
@@ -161,14 +161,13 @@ static inline void ff_framequeue_update_peeked(FFFrameQueue *fq, size_t idx)
}
/**
- * Update the sample count in the queue.
+ * Skip samples from the first frame in the queue.
*
* This function must be used when the first frame was accessed using
- * ff_framequeue_peek() and samples were removed from it.
+ * ff_framequeue_peek() and samples were consumed from it.
+ * It adapts the data pointers and timestamps of the head frame to account
+ * for the skipped samples.
*/
-static inline void ff_framequeue_skip_samples(FFFrameQueue *fq, size_t n)
-{
- fq->total_samples_tail += n;
-}
+void ff_framequeue_skip_samples(FFFrameQueue *fq, size_t samples, AVRational time_base);
#endif /* AVFILTER_FRAMEQUEUE_H */
--
2.11.0
More information about the ffmpeg-devel
mailing list