[FFmpeg-devel] [PATCH 08/35] lavu/fifo: add new FIFO read/peek functions
Anton Khirnov
anton at khirnov.net
Tue Jan 11 22:45:43 EET 2022
As for writing, use separate functions for reading to a buffer and a
callback. Allow the callbacks to limit the amount of data read,
similarly to what is done for writing.
Consistently use size_t for sizes.
---
doc/APIchanges | 3 ++-
libavutil/fifo.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++
libavutil/fifo.h | 60 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 130 insertions(+), 1 deletion(-)
diff --git a/doc/APIchanges b/doc/APIchanges
index 0b179c30e5..f64759d69d 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -19,7 +19,8 @@ API changes, most recent first:
Operations on FIFOs created with this function on these elements
rather than bytes.
Add av_fifo_elem_size(), av_fifo_can_read(), av_fifo_can_write(),
- av_fifo_grow2(), av_fifo_drain2(), av_fifo_write(), av_fifo_write_from_cb().
+ av_fifo_grow2(), av_fifo_drain2(), av_fifo_write(), av_fifo_write_from_cb(),
+ av_fifo_read(), av_fifo_read_to_cb(), av_fifo_peek(), av_fifo_peek_to_cb().
2022-01-xx - xxxxxxxxxx - lavu fifo.h
Access to all AVFifoBuffer members is deprecated. The struct will
diff --git a/libavutil/fifo.c b/libavutil/fifo.c
index 1d94fff457..ea944bc936 100644
--- a/libavutil/fifo.c
+++ b/libavutil/fifo.c
@@ -265,6 +265,74 @@ int av_fifo_write_from_cb(AVFifoBuffer *f, AVFifoCB read_cb,
return fifo_write_common(f, NULL, nb_elems, read_cb, opaque);
}
+static int fifo_peek_common(const AVFifoBuffer *f, uint8_t *buf, size_t *nb_elems,
+ size_t offset, AVFifoCB write_cb, void *opaque)
+{
+ const FifoBuffer *fb = (FifoBuffer*)f;
+ size_t to_read = *nb_elems;
+ size_t offset_r = fb->offset_r;
+ int ret = 0;
+
+ if (offset > av_fifo_can_read(f) ||
+ to_read > av_fifo_can_read(f) - offset) {
+ *nb_elems = 0;
+ return AVERROR(EINVAL);
+ }
+
+ if (offset_r >= fb->nb_elems - offset)
+ offset_r -= fb->nb_elems - offset;
+ else
+ offset_r += offset;
+
+ do {
+ size_t len = FFMIN(fb->nb_elems - offset_r, to_read);
+ uint8_t *rptr = f->buffer + offset_r * fb->elem_size;
+
+ if (write_cb) {
+ ret = write_cb(opaque, rptr, &len);
+ if (ret < 0 || len == 0)
+ break;
+ } else {
+ memcpy(buf, rptr, len * fb->elem_size);
+ buf += len * fb->elem_size;
+ }
+ offset_r += len;
+ if (offset_r >= fb->nb_elems)
+ offset_r = 0;
+ to_read -= len;
+ } while (to_read > 0);
+
+ *nb_elems -= to_read;
+
+ return ret;
+}
+
+int av_fifo_read(AVFifoBuffer *f, void *buf, size_t nb_elems)
+{
+ int ret = fifo_peek_common(f, buf, &nb_elems, 0, NULL, NULL);
+ av_fifo_drain2(f, nb_elems);
+ return ret;
+}
+
+int av_fifo_read_to_cb(AVFifoBuffer *f, AVFifoCB write_cb,
+ void *opaque, size_t *nb_elems)
+{
+ int ret = fifo_peek_common(f, NULL, nb_elems, 0, write_cb, opaque);
+ av_fifo_drain2(f, *nb_elems);
+ return ret;
+}
+
+int av_fifo_peek(AVFifoBuffer *f, void *buf, size_t nb_elems, size_t offset)
+{
+ return fifo_peek_common(f, buf, &nb_elems, offset, NULL, NULL);
+}
+
+int av_fifo_peek_to_cb(AVFifoBuffer *f, AVFifoCB write_cb, void *opaque,
+ size_t *nb_elems, size_t offset)
+{
+ return fifo_peek_common(f, NULL, nb_elems, offset, write_cb, opaque);
+}
+
int av_fifo_realloc2(AVFifoBuffer *f, unsigned int new_size)
{
FifoBuffer *fb = (FifoBuffer*)f;
diff --git a/libavutil/fifo.h b/libavutil/fifo.h
index ac1245ff39..c7be5e8f7d 100644
--- a/libavutil/fifo.h
+++ b/libavutil/fifo.h
@@ -189,6 +189,66 @@ int av_fifo_write(AVFifoBuffer *f, const void *buf, size_t nb_elems);
int av_fifo_write_from_cb(AVFifoBuffer *f, AVFifoCB read_cb,
void *opaque, size_t *nb_elems);
+/**
+ * Read data from a FIFO.
+ *
+ * @param f the FIFO buffer
+ * @param buf Buffer to store the data. nb_elems * av_fifo_elem_size(f) bytes
+ * will be written into buf.
+ * @param nb_elems number of elements to read from FIFO
+ *
+ * @return a non-negative number on success, a negative error code on failure
+ */
+int av_fifo_read(AVFifoBuffer *f, void *buf, size_t nb_elems);
+
+/**
+ * Feed data from a FIFO into a user-provided callback.
+ *
+ * @param f the FIFO buffer
+ * @param write_cb Callback the data will be supplied to. May be called
+ * multiple times.
+ * @param opaque opaque user data to be provided to write_cb
+ * @param nb_elems Should point to the maximum number of elements that can be
+ * read. Will be updated to contain the total number of elements
+ * actually sent to the callback.
+ *
+ * @return non-negative number on success, a negative error code on failure
+ */
+int av_fifo_read_to_cb(AVFifoBuffer *f, AVFifoCB write_cb,
+ void *opaque, size_t *nb_elems);
+
+/**
+ * Read data from a FIFO without modifying FIFO state.
+ *
+ * @param f the FIFO buffer
+ * @param buf Buffer to store the data. nb_elems * av_fifo_elem_size(f) bytes
+ * will be written into buf.
+ * @param nb_elems number of elements to read from FIFO
+ * @param offset number of initial elements to skip; offset + nb_elems must not
+ * be larger than av_fifo_can_read(f).
+ *
+ * @return a non-negative number on success, a negative error code on failure
+ */
+int av_fifo_peek(AVFifoBuffer *f, void *buf, size_t nb_elems, size_t offset);
+
+/**
+ * Feed data from a FIFO into a user-provided callback.
+ *
+ * @param f the FIFO buffer
+ * @param write_cb Callback the data will be supplied to. May be called
+ * multiple times.
+ * @param opaque opaque user data to be provided to write_cb
+ * @param nb_elems Should point to the maximum number of elements that can be
+ * read. Will be updated to contain the total number of elements
+ * actually sent to the callback.
+ * @param offset number of initial elements to skip; offset + *nb_elems must not
+ * be larger than av_fifo_can_read(f).
+ *
+ * @return a non-negative number on success, a negative error code on failure
+ */
+int av_fifo_peek_to_cb(AVFifoBuffer *f, AVFifoCB write_cb, void *opaque,
+ size_t *nb_elems, size_t offset);
+
/**
* Discard the specified amount of data from an AVFifoBuffer.
* @param size number of elements to discard, MUST NOT be larger than
--
2.33.0
More information about the ffmpeg-devel
mailing list