Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
* [FFmpeg-devel] [PATCH 1/7] lavc/flac_parser: use a custom FIFO implementation
@ 2021-12-31 10:53 Anton Khirnov
  2021-12-31 10:53 ` [FFmpeg-devel] [PATCH 2/7] lavf/dvenc: replace av_fifo_peek2() with av_fifo_generic_peek_at() Anton Khirnov
                   ` (6 more replies)
  0 siblings, 7 replies; 10+ messages in thread
From: Anton Khirnov @ 2021-12-31 10:53 UTC (permalink / raw)
  To: ffmpeg-devel

FLAC parser currently uses AVFifoBuffer in a highly non-trivial manner,
modifying its "internals" (the whole struct is currently public, but no
other code touches its contents directly). E.g. it does not use any
av_fifo functions for reading the FIFO contents, but implements its own.

Reimplement the needed parts of the AVFifoBuffer API in the FLAC parser,
making it completely self-contained. This will allow us to make
AVFifoBuffer private.
---
 libavcodec/flac_parser.c | 191 +++++++++++++++++++++++++++++++--------
 1 file changed, 153 insertions(+), 38 deletions(-)

diff --git a/libavcodec/flac_parser.c b/libavcodec/flac_parser.c
index 3b27b152fc..d6af5ce836 100644
--- a/libavcodec/flac_parser.c
+++ b/libavcodec/flac_parser.c
@@ -34,7 +34,6 @@
 
 #include "libavutil/attributes.h"
 #include "libavutil/crc.h"
-#include "libavutil/fifo.h"
 #include "bytestream.h"
 #include "parser.h"
 #include "flac.h"
@@ -57,6 +56,15 @@
 #define MAX_FRAME_HEADER_SIZE 16
 #define MAX_FRAME_VERIFY_SIZE (MAX_FRAME_HEADER_SIZE + 1)
 
+typedef struct FifoBuffer {
+    uint8_t *buffer;
+    uint8_t *end;
+    uint8_t *rptr;
+    uint8_t *wptr;
+    size_t rndx;
+    size_t wndx;
+} FifoBuffer;
+
 typedef struct FLACHeaderMarker {
     int offset;       /**< byte offset from start of FLACParseContext->buffer */
     int link_penalty[FLAC_MAX_SEQUENTIAL_HEADERS]; /**< array of local scores
@@ -84,7 +92,7 @@ typedef struct FLACParseContext {
     int nb_headers_buffered;       /**< number of headers that are buffered   */
     int best_header_valid;         /**< flag set when the parser returns junk;
                                         if set return best_header next time   */
-    AVFifoBuffer *fifo_buf;        /**< buffer to store all data until headers
+    FifoBuffer fifo_buf;           /**< buffer to store all data until headers
                                         can be verified                       */
     int end_padded;                /**< specifies if fifo_buf's end is padded */
     uint8_t *wrap_buf;             /**< general fifo read buffer when wrapped */
@@ -127,6 +135,17 @@ static int frame_header_is_valid(AVCodecContext *avctx, const uint8_t *buf,
     return 1;
 }
 
+static size_t flac_fifo_size(FifoBuffer *f)
+{
+    av_assert0(f->wndx >= f->rndx);
+    return f->wndx - f->rndx;
+}
+
+static size_t flac_fifo_space(FifoBuffer *f)
+{
+    return f->end - f->buffer - flac_fifo_size(f);
+}
+
 /**
  * Non-destructive fast fifo pointer fetching
  * Returns a pointer from the specified offset.
@@ -143,7 +162,7 @@ static int frame_header_is_valid(AVCodecContext *avctx, const uint8_t *buf,
 static uint8_t *flac_fifo_read_wrap(FLACParseContext *fpc, int offset, int len,
                                     uint8_t **wrap_buf, int *allocated_size)
 {
-    AVFifoBuffer *f   = fpc->fifo_buf;
+    FifoBuffer   *f   = &fpc->fifo_buf;
     uint8_t *start    = f->rptr + offset;
     uint8_t *tmp_buf;
 
@@ -180,9 +199,8 @@ static uint8_t *flac_fifo_read_wrap(FLACParseContext *fpc, int offset, int len,
  * A second call to flac_fifo_read (with new offset and len) should be called
  * to get the post-wrap buf if the returned len is less than the requested.
  **/
-static uint8_t *flac_fifo_read(FLACParseContext *fpc, int offset, int *len)
+static uint8_t *flac_fifo_read(FifoBuffer *f, int offset, int *len)
 {
-    AVFifoBuffer *f   = fpc->fifo_buf;
     uint8_t *start    = f->rptr + offset;
 
     if (start >= f->end)
@@ -191,6 +209,106 @@ static uint8_t *flac_fifo_read(FLACParseContext *fpc, int offset, int *len)
     return start;
 }
 
+static int flac_fifo_grow(FifoBuffer *f, size_t inc)
+{
+    size_t size_old = f->end - f->buffer;
+    size_t offset_r = f->rptr - f->buffer;
+    size_t offset_w = f->wptr - f->buffer;
+    size_t size_new;
+
+    uint8_t *tmp;
+
+    if (size_old > SIZE_MAX - inc)
+        return AVERROR(EINVAL);
+    size_new = size_old + inc;
+
+    tmp = av_realloc(f->buffer, size_new);
+    if (!tmp)
+        return AVERROR(ENOMEM);
+
+    // move the data from the beginning of the ring buffer
+    // to the newly allocated space
+    // the second condition distinguishes full vs empty fifo
+    if (offset_w <= offset_r && flac_fifo_size(f)) {
+        const size_t copy = FFMIN(inc, offset_w);
+        memcpy(tmp + size_old, tmp, copy);
+        if (copy < offset_w) {
+            memmove(tmp, tmp + copy, offset_w - copy);
+            offset_w -= copy;
+        } else
+            offset_w = size_old + copy;
+    }
+
+    f->buffer = tmp;
+    f->end    = f->buffer + size_new;
+    f->rptr   = f->buffer + offset_r;
+    f->wptr   = f->buffer + offset_w;
+
+    return 0;
+}
+
+static int flac_fifo_write(FifoBuffer *f, const uint8_t *src, size_t size)
+{
+    uint32_t wndx = f->wndx;
+    uint8_t *wptr;
+
+    if (flac_fifo_space(f) < size) {
+        int ret = flac_fifo_grow(f, FFMAX(flac_fifo_size(f), size));
+        if (ret < 0)
+            return ret;
+    }
+
+    wptr = f->wptr;
+    do {
+        size_t len = FFMIN(f->end - wptr, size);
+        memcpy(wptr, src, len);
+        src  += len;
+        wptr += len;
+        if (wptr >= f->end)
+            wptr = f->buffer;
+        wndx    += len;
+        size    -= len;
+    } while (size > 0);
+
+    f->wndx = wndx;
+    f->wptr = wptr;
+
+    return 0;
+}
+
+static void flac_fifo_drain(FifoBuffer *f, size_t size)
+{
+    av_assert0(flac_fifo_size(f) >= size);
+    f->rptr += size;
+    if (f->rptr >= f->end)
+        f->rptr -= f->end - f->buffer;
+    f->rndx += size;
+}
+
+static int flac_fifo_alloc(FifoBuffer *f, size_t size)
+{
+    memset(f, 0, sizeof(*f));
+
+    f->buffer = av_realloc(NULL, size);
+    if (!f->buffer)
+        return AVERROR(ENOMEM);
+
+    f->wptr = f->buffer;
+    f->rptr = f->buffer;
+    f->end  = f->buffer + size;
+
+    f->rndx = 0;
+    f->wndx = 0;
+
+    return 0;
+}
+
+static void flac_fifo_free(FifoBuffer *f)
+{
+    av_freep(&f->buffer);
+    memset(f, 0, sizeof(*f));
+}
+
 static int find_headers_search_validate(FLACParseContext *fpc, int offset)
 {
     FLACFrameInfo fi;
@@ -263,9 +381,9 @@ static int find_new_headers(FLACParseContext *fpc, int search_start)
     fpc->nb_headers_found = 0;
 
     /* Search for a new header of at most 16 bytes. */
-    search_end = av_fifo_size(fpc->fifo_buf) - (MAX_FRAME_HEADER_SIZE - 1);
+    search_end = flac_fifo_size(&fpc->fifo_buf) - (MAX_FRAME_HEADER_SIZE - 1);
     read_len   = search_end - search_start + 1;
-    buf        = flac_fifo_read(fpc, search_start, &read_len);
+    buf        = flac_fifo_read(&fpc->fifo_buf, search_start, &read_len);
     size       = find_headers_search(fpc, buf, read_len, search_start);
     search_start += read_len - 1;
 
@@ -277,7 +395,7 @@ static int find_new_headers(FLACParseContext *fpc, int search_start)
         /* search_start + 1 is the post-wrap offset in the fifo. */
         read_len = search_end - (search_start + 1) + 1;
 
-        buf      = flac_fifo_read(fpc, search_start + 1, &read_len);
+        buf      = flac_fifo_read(&fpc->fifo_buf, search_start + 1, &read_len);
         wrap[1]  = buf[0];
 
         if ((AV_RB16(wrap) & 0xFFFE) == 0xFFF8) {
@@ -406,12 +524,12 @@ static int check_header_mismatch(FLACParseContext  *fpc,
             }
 
             read_len = end->offset - start->offset;
-            buf      = flac_fifo_read(fpc, start->offset, &read_len);
+            buf      = flac_fifo_read(&fpc->fifo_buf, start->offset, &read_len);
             crc      = av_crc(av_crc_get_table(AV_CRC_16_ANSI), 0, buf, read_len);
             read_len = (end->offset - start->offset) - read_len;
 
             if (read_len) {
-                buf = flac_fifo_read(fpc, end->offset - read_len, &read_len);
+                buf = flac_fifo_read(&fpc->fifo_buf, end->offset - read_len, &read_len);
                 crc = av_crc(av_crc_get_table(AV_CRC_16_ANSI), crc, buf, read_len);
             }
         }
@@ -500,7 +618,7 @@ static int get_best_header(FLACParseContext *fpc, const uint8_t **poutbuf,
     FLACHeaderMarker *header = fpc->best_header;
     FLACHeaderMarker *child  = header->best_child;
     if (!child) {
-        *poutbuf_size = av_fifo_size(fpc->fifo_buf) - header->offset;
+        *poutbuf_size = flac_fifo_size(&fpc->fifo_buf) - header->offset;
     } else {
         *poutbuf_size = child->offset - header->offset;
 
@@ -519,7 +637,6 @@ static int get_best_header(FLACParseContext *fpc, const uint8_t **poutbuf,
                                         &fpc->wrap_buf,
                                         &fpc->wrap_buf_allocated_size);
 
-
     if (fpc->pc->flags & PARSER_FLAG_USE_CODEC_TS) {
         if (header->fi.is_var_size)
           fpc->pc->pts = header->fi.frame_or_sample_num;
@@ -534,7 +651,7 @@ static int get_best_header(FLACParseContext *fpc, const uint8_t **poutbuf,
     /* Return the negative overread index so the client can compute pos.
        This should be the amount overread to the beginning of the child */
     if (child)
-        return child->offset - av_fifo_size(fpc->fifo_buf);
+        return child->offset - flac_fifo_size(&fpc->fifo_buf);
     return 0;
 }
 
@@ -586,7 +703,7 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx,
             fpc->nb_headers_buffered--;
         }
         /* Release returned data from ring buffer. */
-        av_fifo_drain(fpc->fifo_buf, best_child->offset);
+        flac_fifo_drain(&fpc->fifo_buf, best_child->offset);
 
         /* Fix the offset for the headers remaining to match the new buffer. */
         for (curr = best_child->next; curr; curr = curr->next)
@@ -620,7 +737,7 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx,
     while ((buf_size && read_end < buf + buf_size &&
             fpc->nb_headers_buffered < FLAC_MIN_HEADERS)
            || (!buf_size && !fpc->end_padded)) {
-        int start_offset;
+        int start_offset, ret;
 
         /* Pad the end once if EOF, to check the final region for headers. */
         if (!buf_size) {
@@ -634,8 +751,8 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx,
                                               nb_desired * FLAC_AVG_FRAME_SIZE);
         }
 
-        if (!av_fifo_space(fpc->fifo_buf) &&
-            av_fifo_size(fpc->fifo_buf) / FLAC_AVG_FRAME_SIZE >
+        if (!flac_fifo_space(&fpc->fifo_buf) &&
+            flac_fifo_size(&fpc->fifo_buf) / FLAC_AVG_FRAME_SIZE >
             fpc->nb_headers_buffered * 20) {
             /* There is less than one valid flac header buffered for 20 headers
              * buffered. Therefore the fifo is most likely filled with invalid
@@ -644,24 +761,20 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx,
         }
 
         /* Fill the buffer. */
-        if (   av_fifo_space(fpc->fifo_buf) < read_end - read_start
-            && av_fifo_realloc2(fpc->fifo_buf, (read_end - read_start) + 2*av_fifo_size(fpc->fifo_buf)) < 0) {
-            av_log(avctx, AV_LOG_ERROR,
-                   "couldn't reallocate buffer of size %"PTRDIFF_SPECIFIER"\n",
-                   (read_end - read_start) + av_fifo_size(fpc->fifo_buf));
-            goto handle_error;
-        }
-
         if (buf_size) {
-            av_fifo_generic_write(fpc->fifo_buf, (void*) read_start,
-                                  read_end - read_start, NULL);
+            ret = flac_fifo_write(&fpc->fifo_buf, read_start,
+                                  read_end - read_start);
         } else {
             int8_t pad[MAX_FRAME_HEADER_SIZE] = { 0 };
-            av_fifo_generic_write(fpc->fifo_buf, pad, sizeof(pad), NULL);
+            ret = flac_fifo_write(&fpc->fifo_buf, pad, sizeof(pad));
+        }
+        if (ret < 0) {
+            av_log(avctx, AV_LOG_ERROR, "Error buffering data\n");
+            goto handle_error;
         }
 
         /* Tag headers and update sequences. */
-        start_offset = av_fifo_size(fpc->fifo_buf) -
+        start_offset = flac_fifo_size(&fpc->fifo_buf) -
                        ((read_end - read_start) + (MAX_FRAME_HEADER_SIZE - 1));
         start_offset = FFMAX(0, start_offset);
         nb_headers   = find_new_headers(fpc, start_offset);
@@ -689,13 +802,13 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx,
 
         /* restore the state pre-padding */
         if (fpc->end_padded) {
-            int warp = fpc->fifo_buf->wptr - fpc->fifo_buf->buffer < MAX_FRAME_HEADER_SIZE;
+            int warp = fpc->fifo_buf.wptr - fpc->fifo_buf.buffer < MAX_FRAME_HEADER_SIZE;
             /* HACK: drain the tail of the fifo */
-            fpc->fifo_buf->wptr -= MAX_FRAME_HEADER_SIZE;
-            fpc->fifo_buf->wndx -= MAX_FRAME_HEADER_SIZE;
+            fpc->fifo_buf.wptr -= MAX_FRAME_HEADER_SIZE;
+            fpc->fifo_buf.wndx -= MAX_FRAME_HEADER_SIZE;
             if (warp) {
-                fpc->fifo_buf->wptr += fpc->fifo_buf->end -
-                    fpc->fifo_buf->buffer;
+                fpc->fifo_buf.wptr += fpc->fifo_buf.end -
+                    fpc->fifo_buf.buffer;
             }
             read_start = read_end = NULL;
         }
@@ -727,7 +840,7 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx,
                                                 &fpc->wrap_buf,
                                                 &fpc->wrap_buf_allocated_size);
             return buf_size ? (read_end - buf) : (fpc->best_header->offset -
-                                                  av_fifo_size(fpc->fifo_buf));
+                                                  flac_fifo_size(&fpc->fifo_buf));
         }
         if (!buf_size)
             return get_best_header(fpc, poutbuf, poutbuf_size);
@@ -742,11 +855,13 @@ handle_error:
 static av_cold int flac_parse_init(AVCodecParserContext *c)
 {
     FLACParseContext *fpc = c->priv_data;
+    int ret;
+
     fpc->pc = c;
     /* There will generally be FLAC_MIN_HEADERS buffered in the fifo before
        it drains.  This is allocated early to avoid slow reallocation. */
-    fpc->fifo_buf = av_fifo_alloc_array(FLAC_MIN_HEADERS + 3, FLAC_AVG_FRAME_SIZE);
-    if (!fpc->fifo_buf) {
+    ret = flac_fifo_alloc(&fpc->fifo_buf, (FLAC_MIN_HEADERS + 3) * FLAC_AVG_FRAME_SIZE);
+    if (ret < 0) {
         av_log(fpc->avctx, AV_LOG_ERROR,
                 "couldn't allocate fifo_buf\n");
         return AVERROR(ENOMEM);
@@ -765,7 +880,7 @@ static void flac_parse_close(AVCodecParserContext *c)
         curr = temp;
     }
     fpc->headers = NULL;
-    av_fifo_freep(&fpc->fifo_buf);
+    flac_fifo_free(&fpc->fifo_buf);
     av_freep(&fpc->wrap_buf);
 }
 
-- 
2.33.0

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [FFmpeg-devel] [PATCH 2/7] lavf/dvenc: replace av_fifo_peek2() with av_fifo_generic_peek_at()
  2021-12-31 10:53 [FFmpeg-devel] [PATCH 1/7] lavc/flac_parser: use a custom FIFO implementation Anton Khirnov
@ 2021-12-31 10:53 ` Anton Khirnov
  2021-12-31 10:53 ` [FFmpeg-devel] [PATCH 3/7] lavu/fifo: deprecate av_fifo_peek2() Anton Khirnov
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Anton Khirnov @ 2021-12-31 10:53 UTC (permalink / raw)
  To: ffmpeg-devel

This is the only remaining caller of av_fifo_peek2(), which will be
deprecated.
---
 libavformat/dvenc.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/libavformat/dvenc.c b/libavformat/dvenc.c
index 9a853ba7ce..b76539b59f 100644
--- a/libavformat/dvenc.c
+++ b/libavformat/dvenc.c
@@ -201,8 +201,9 @@ static void dv_inject_audio(DVMuxContext *c, int channel, uint8_t* frame_ptr)
                 if (of*2 >= size)
                     continue;
 
-                frame_ptr[d]   = *av_fifo_peek2(c->audio_data[channel], of*2+1); // FIXME: maybe we have to admit
-                frame_ptr[d+1] = *av_fifo_peek2(c->audio_data[channel], of*2);   //        that DV is a big-endian PCM
+                // FIXME: maybe we have to admit that DV is a big-endian PCM
+                av_fifo_generic_peek_at(c->audio_data[channel], frame_ptr + d, of * 2, 2, NULL);
+                FFSWAP(uint8_t, frame_ptr[d], frame_ptr[d + 1]);
             }
             frame_ptr += 16 * 80; /* 15 Video DIFs + 1 Audio DIF */
         }
-- 
2.33.0

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [FFmpeg-devel] [PATCH 3/7] lavu/fifo: deprecate av_fifo_peek2()
  2021-12-31 10:53 [FFmpeg-devel] [PATCH 1/7] lavc/flac_parser: use a custom FIFO implementation Anton Khirnov
  2021-12-31 10:53 ` [FFmpeg-devel] [PATCH 2/7] lavf/dvenc: replace av_fifo_peek2() with av_fifo_generic_peek_at() Anton Khirnov
@ 2021-12-31 10:53 ` Anton Khirnov
  2021-12-31 10:53 ` [FFmpeg-devel] [PATCH 4/7] lavu/fifo: simplify av_fifo_alloc() Anton Khirnov
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Anton Khirnov @ 2021-12-31 10:53 UTC (permalink / raw)
  To: ffmpeg-devel

It returns a pointer inside the fifo's buffer, which cannot be safely
used without accessing AVFifoBuffer internals. It is easier and safer to
use av_fifo_generic_peek_at().
---
 libavutil/fifo.h       |  4 ++++
 libavutil/tests/fifo.c |  8 --------
 libavutil/version.h    |  1 +
 tests/ref/fate/fifo    | 26 --------------------------
 4 files changed, 5 insertions(+), 34 deletions(-)

diff --git a/libavutil/fifo.h b/libavutil/fifo.h
index dc7bc6f0dd..37da9f14c2 100644
--- a/libavutil/fifo.h
+++ b/libavutil/fifo.h
@@ -156,6 +156,7 @@ int av_fifo_grow(AVFifoBuffer *f, unsigned int additional_space);
  */
 void av_fifo_drain(AVFifoBuffer *f, int size);
 
+#if FF_API_OLD_FIFO
 /**
  * Return a pointer to the data stored in a FIFO buffer at a certain offset.
  * The FIFO buffer is not modified.
@@ -165,7 +166,9 @@ void av_fifo_drain(AVFifoBuffer *f, int size);
  *             than the used buffer size or the returned pointer will
  *             point outside to the buffer data.
  *             The used buffer size can be checked with av_fifo_size().
+ * @deprecated use av_fifo_generic_peek_at()
  */
+attribute_deprecated
 static inline uint8_t *av_fifo_peek2(const AVFifoBuffer *f, int offs)
 {
     uint8_t *ptr = f->rptr + offs;
@@ -175,5 +178,6 @@ static inline uint8_t *av_fifo_peek2(const AVFifoBuffer *f, int offs)
         ptr = f->end - (f->buffer - ptr);
     return ptr;
 }
+#endif
 
 #endif /* AVUTIL_FIFO_H */
diff --git a/libavutil/tests/fifo.c b/libavutil/tests/fifo.c
index 8a550e088b..a17d913233 100644
--- a/libavutil/tests/fifo.c
+++ b/libavutil/tests/fifo.c
@@ -30,14 +30,6 @@ int main(void)
     for (i = 0; av_fifo_space(fifo) >= sizeof(int); i++)
         av_fifo_generic_write(fifo, &i, sizeof(int), NULL);
 
-    /* peek at FIFO */
-    n = av_fifo_size(fifo) / sizeof(int);
-    for (i = -n + 1; i < n; i++) {
-        int *v = (int *)av_fifo_peek2(fifo, i * sizeof(int));
-        printf("%d: %d\n", i, *v);
-    }
-    printf("\n");
-
     /* peek_at at FIFO */
     n = av_fifo_size(fifo) / sizeof(int);
     for (i = 0; i < n; i++) {
diff --git a/libavutil/version.h b/libavutil/version.h
index 3cac09cb96..0ba8f2d2d0 100644
--- a/libavutil/version.h
+++ b/libavutil/version.h
@@ -109,6 +109,7 @@
 #define FF_API_DECLARE_ALIGNED          (LIBAVUTIL_VERSION_MAJOR < 58)
 #define FF_API_COLORSPACE_NAME          (LIBAVUTIL_VERSION_MAJOR < 58)
 #define FF_API_AV_MALLOCZ_ARRAY         (LIBAVUTIL_VERSION_MAJOR < 58)
+#define FF_API_OLD_FIFO                 (LIBAVUTIL_VERSION_MAJOR < 58)
 
 /**
  * @}
diff --git a/tests/ref/fate/fifo b/tests/ref/fate/fifo
index 2b18ed5ffc..1b0e005412 100644
--- a/tests/ref/fate/fifo
+++ b/tests/ref/fate/fifo
@@ -1,29 +1,3 @@
--12: 1
--11: 2
--10: 3
--9: 4
--8: 5
--7: 6
--6: 7
--5: 8
--4: 9
--3: 10
--2: 11
--1: 12
-0: 0
-1: 1
-2: 2
-3: 3
-4: 4
-5: 5
-6: 6
-7: 7
-8: 8
-9: 9
-10: 10
-11: 11
-12: 12
-
 0: 0
 1: 1
 2: 2
-- 
2.33.0

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [FFmpeg-devel] [PATCH 4/7] lavu/fifo: simplify av_fifo_alloc()
  2021-12-31 10:53 [FFmpeg-devel] [PATCH 1/7] lavc/flac_parser: use a custom FIFO implementation Anton Khirnov
  2021-12-31 10:53 ` [FFmpeg-devel] [PATCH 2/7] lavf/dvenc: replace av_fifo_peek2() with av_fifo_generic_peek_at() Anton Khirnov
  2021-12-31 10:53 ` [FFmpeg-devel] [PATCH 3/7] lavu/fifo: deprecate av_fifo_peek2() Anton Khirnov
@ 2021-12-31 10:53 ` Anton Khirnov
  2021-12-31 10:53 ` [FFmpeg-devel] [PATCH 5/7] lavu/fifo: do not copy the whole fifo when reallocating Anton Khirnov
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Anton Khirnov @ 2021-12-31 10:53 UTC (permalink / raw)
  To: ffmpeg-devel

Turn it into a wrapper around av_fifo_alloc_array().
---
 libavutil/fifo.c | 14 ++++----------
 1 file changed, 4 insertions(+), 10 deletions(-)

diff --git a/libavutil/fifo.c b/libavutil/fifo.c
index 1060aedf13..5eee18a8c8 100644
--- a/libavutil/fifo.c
+++ b/libavutil/fifo.c
@@ -24,9 +24,10 @@
 #include "common.h"
 #include "fifo.h"
 
-static AVFifoBuffer *fifo_alloc_common(void *buffer, size_t size)
+AVFifoBuffer *av_fifo_alloc_array(size_t nmemb, size_t size)
 {
     AVFifoBuffer *f;
+    void *buffer = av_malloc_array(nmemb, size);
     if (!buffer)
         return NULL;
     f = av_mallocz(sizeof(AVFifoBuffer));
@@ -35,21 +36,14 @@ static AVFifoBuffer *fifo_alloc_common(void *buffer, size_t size)
         return NULL;
     }
     f->buffer = buffer;
-    f->end    = f->buffer + size;
+    f->end    = f->buffer + nmemb * size;
     av_fifo_reset(f);
     return f;
 }
 
 AVFifoBuffer *av_fifo_alloc(unsigned int size)
 {
-    void *buffer = av_malloc(size);
-    return fifo_alloc_common(buffer, size);
-}
-
-AVFifoBuffer *av_fifo_alloc_array(size_t nmemb, size_t size)
-{
-    void *buffer = av_malloc_array(nmemb, size);
-    return fifo_alloc_common(buffer, nmemb * size);
+    return av_fifo_alloc_array(size, 1);
 }
 
 void av_fifo_free(AVFifoBuffer *f)
-- 
2.33.0

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [FFmpeg-devel] [PATCH 5/7] lavu/fifo: do not copy the whole fifo when reallocating
  2021-12-31 10:53 [FFmpeg-devel] [PATCH 1/7] lavc/flac_parser: use a custom FIFO implementation Anton Khirnov
                   ` (2 preceding siblings ...)
  2021-12-31 10:53 ` [FFmpeg-devel] [PATCH 4/7] lavu/fifo: simplify av_fifo_alloc() Anton Khirnov
@ 2021-12-31 10:53 ` Anton Khirnov
  2021-12-31 10:53 ` [FFmpeg-devel] [PATCH 6/7] lavu/fifo: drop useless comments Anton Khirnov
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Anton Khirnov @ 2021-12-31 10:53 UTC (permalink / raw)
  To: ffmpeg-devel

av_realloc() the buffer and only move the part of the ring buffer that
needs it. Also avoids allocating a temporary fifo.
---
 libavutil/fifo.c | 34 ++++++++++++++++++++++++----------
 1 file changed, 24 insertions(+), 10 deletions(-)

diff --git a/libavutil/fifo.c b/libavutil/fifo.c
index 5eee18a8c8..171c1aa9cd 100644
--- a/libavutil/fifo.c
+++ b/libavutil/fifo.c
@@ -27,7 +27,7 @@
 AVFifoBuffer *av_fifo_alloc_array(size_t nmemb, size_t size)
 {
     AVFifoBuffer *f;
-    void *buffer = av_malloc_array(nmemb, size);
+    void *buffer = av_realloc_array(NULL, nmemb, size);
     if (!buffer)
         return NULL;
     f = av_mallocz(sizeof(AVFifoBuffer));
@@ -83,17 +83,31 @@ int av_fifo_realloc2(AVFifoBuffer *f, unsigned int new_size)
     unsigned int old_size = f->end - f->buffer;
 
     if (old_size < new_size) {
-        int len          = av_fifo_size(f);
-        AVFifoBuffer *f2 = av_fifo_alloc(new_size);
+        size_t offset_r = f->rptr - f->buffer;
+        size_t offset_w = f->wptr - f->buffer;
+        uint8_t *tmp;
 
-        if (!f2)
+        tmp = av_realloc(f->buffer, new_size);
+        if (!tmp)
             return AVERROR(ENOMEM);
-        av_fifo_generic_read(f, f2->buffer, len, NULL);
-        f2->wptr += len;
-        f2->wndx += len;
-        av_free(f->buffer);
-        *f = *f2;
-        av_free(f2);
+
+        // move the data from the beginning of the ring buffer
+        // to the newly allocated space
+        // the second condition distinguishes full vs empty fifo
+        if (offset_w <= offset_r && av_fifo_size(f)) {
+            const size_t copy = FFMIN(new_size - old_size, offset_w);
+            memcpy(tmp + old_size, tmp, copy);
+            if (copy < offset_w) {
+                memmove(tmp, tmp + copy , offset_w - copy);
+                offset_w -= copy;
+            } else
+                offset_w = old_size + copy;
+        }
+
+        f->buffer = tmp;
+        f->end    = f->buffer + new_size;
+        f->rptr   = f->buffer + offset_r;
+        f->wptr   = f->buffer + offset_w;
     }
     return 0;
 }
-- 
2.33.0

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [FFmpeg-devel] [PATCH 6/7] lavu/fifo: drop useless comments
  2021-12-31 10:53 [FFmpeg-devel] [PATCH 1/7] lavc/flac_parser: use a custom FIFO implementation Anton Khirnov
                   ` (3 preceding siblings ...)
  2021-12-31 10:53 ` [FFmpeg-devel] [PATCH 5/7] lavu/fifo: do not copy the whole fifo when reallocating Anton Khirnov
@ 2021-12-31 10:53 ` Anton Khirnov
  2021-12-31 11:47   ` Andreas Rheinhardt
  2021-12-31 10:53 ` [FFmpeg-devel] [PATCH 7/7] lavu/fifo: return errors on trying to read/write too much Anton Khirnov
  2021-12-31 11:30 ` [FFmpeg-devel] [PATCH 1/7] lavc/flac_parser: use a custom FIFO implementation Andreas Rheinhardt
  6 siblings, 1 reply; 10+ messages in thread
From: Anton Khirnov @ 2021-12-31 10:53 UTC (permalink / raw)
  To: ffmpeg-devel

This object was never intended to be thread-safe, so these carry no
useful information.
---
 libavutil/fifo.c | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/libavutil/fifo.c b/libavutil/fifo.c
index 171c1aa9cd..f38e8ff089 100644
--- a/libavutil/fifo.c
+++ b/libavutil/fifo.c
@@ -144,7 +144,6 @@ int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size,
             memcpy(wptr, src, len);
             src = (uint8_t *)src + len;
         }
-// Write memory barrier needed for SMP here in theory
         wptr += len;
         if (wptr >= f->end)
             wptr = f->buffer;
@@ -197,7 +196,6 @@ int av_fifo_generic_peek_at(AVFifoBuffer *f, void *dest, int offset, int buf_siz
 int av_fifo_generic_peek(AVFifoBuffer *f, void *dest, int buf_size,
                          void (*func)(void *, void *, int))
 {
-// Read memory barrier needed for SMP here in theory
     uint8_t *rptr = f->rptr;
 
     do {
@@ -208,7 +206,6 @@ int av_fifo_generic_peek(AVFifoBuffer *f, void *dest, int buf_size,
             memcpy(dest, rptr, len);
             dest = (uint8_t *)dest + len;
         }
-// memory barrier needed for SMP here in theory
         rptr += len;
         if (rptr >= f->end)
             rptr -= f->end - f->buffer;
@@ -221,7 +218,6 @@ int av_fifo_generic_peek(AVFifoBuffer *f, void *dest, int buf_size,
 int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size,
                          void (*func)(void *, void *, int))
 {
-// Read memory barrier needed for SMP here in theory
     do {
         int len = FFMIN(f->end - f->rptr, buf_size);
         if (func)
@@ -230,7 +226,6 @@ int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size,
             memcpy(dest, f->rptr, len);
             dest = (uint8_t *)dest + len;
         }
-// memory barrier needed for SMP here in theory
         av_fifo_drain(f, len);
         buf_size -= len;
     } while (buf_size > 0);
-- 
2.33.0

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [FFmpeg-devel] [PATCH 7/7] lavu/fifo: return errors on trying to read/write too much
  2021-12-31 10:53 [FFmpeg-devel] [PATCH 1/7] lavc/flac_parser: use a custom FIFO implementation Anton Khirnov
                   ` (4 preceding siblings ...)
  2021-12-31 10:53 ` [FFmpeg-devel] [PATCH 6/7] lavu/fifo: drop useless comments Anton Khirnov
@ 2021-12-31 10:53 ` Anton Khirnov
  2021-12-31 11:30 ` [FFmpeg-devel] [PATCH 1/7] lavc/flac_parser: use a custom FIFO implementation Andreas Rheinhardt
  6 siblings, 0 replies; 10+ messages in thread
From: Anton Khirnov @ 2021-12-31 10:53 UTC (permalink / raw)
  To: ffmpeg-devel

Trying to write too much will currently overwrite previous data. Trying
to read too much will either av_assert2() in av_fifo_drain() or return
old data. Trying to peek too much will either av_assert2() in
av_fifo_generic_peek_at() or return old data.

Return an error code in all these cases, which is safer and more
consistent.
---
 libavutil/fifo.c | 18 +++++++++++-------
 libavutil/fifo.h |  8 +++++++-
 2 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/libavutil/fifo.c b/libavutil/fifo.c
index f38e8ff089..d741bdd395 100644
--- a/libavutil/fifo.c
+++ b/libavutil/fifo.c
@@ -134,6 +134,9 @@ int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size,
     uint32_t wndx= f->wndx;
     uint8_t *wptr= f->wptr;
 
+    if (size > av_fifo_space(f))
+        return AVERROR(ENOSPC);
+
     do {
         int len = FFMIN(f->end - wptr, size);
         if (func) {
@@ -159,13 +162,8 @@ int av_fifo_generic_peek_at(AVFifoBuffer *f, void *dest, int offset, int buf_siz
 {
     uint8_t *rptr = f->rptr;
 
-    av_assert2(offset >= 0);
-
-    /*
-     * *ndx are indexes modulo 2^32, they are intended to overflow,
-     * to handle *ndx greater than 4gb.
-     */
-    av_assert2(buf_size + (unsigned)offset <= f->wndx - f->rndx);
+    if (offset < 0 || buf_size > av_fifo_size(f) - offset)
+        return AVERROR(EINVAL);
 
     if (offset >= f->end - rptr)
         rptr += offset - (f->end - f->buffer);
@@ -198,6 +196,9 @@ int av_fifo_generic_peek(AVFifoBuffer *f, void *dest, int buf_size,
 {
     uint8_t *rptr = f->rptr;
 
+    if (buf_size > av_fifo_size(f))
+        return AVERROR(EINVAL);
+
     do {
         int len = FFMIN(f->end - rptr, buf_size);
         if (func)
@@ -218,6 +219,9 @@ int av_fifo_generic_peek(AVFifoBuffer *f, void *dest, int buf_size,
 int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size,
                          void (*func)(void *, void *, int))
 {
+    if (buf_size > av_fifo_size(f))
+        return AVERROR(EINVAL);
+
     do {
         int len = FFMIN(f->end - f->rptr, buf_size);
         if (func)
diff --git a/libavutil/fifo.h b/libavutil/fifo.h
index 37da9f14c2..53b668aa17 100644
--- a/libavutil/fifo.h
+++ b/libavutil/fifo.h
@@ -91,6 +91,8 @@ int av_fifo_space(const AVFifoBuffer *f);
  * @param buf_size number of bytes to read
  * @param func generic read function
  * @param dest data destination
+ *
+ * @return a non-negative number on success, a negative error code on failure
  */
 int av_fifo_generic_peek_at(AVFifoBuffer *f, void *dest, int offset, int buf_size, void (*func)(void*, void*, int));
 
@@ -101,6 +103,8 @@ int av_fifo_generic_peek_at(AVFifoBuffer *f, void *dest, int offset, int buf_siz
  * @param buf_size number of bytes to read
  * @param func generic read function
  * @param dest data destination
+ *
+ * @return a non-negative number on success, a negative error code on failure
  */
 int av_fifo_generic_peek(AVFifoBuffer *f, void *dest, int buf_size, void (*func)(void*, void*, int));
 
@@ -110,6 +114,8 @@ int av_fifo_generic_peek(AVFifoBuffer *f, void *dest, int buf_size, void (*func)
  * @param buf_size number of bytes to read
  * @param func generic read function
  * @param dest data destination
+ *
+ * @return a non-negative number on success, a negative error code on failure
  */
 int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size, void (*func)(void*, void*, int));
 
@@ -124,7 +130,7 @@ int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size, void (*func)
  * func must return the number of bytes written to dest_buf, or <= 0 to
  * indicate no more data available to write.
  * If func is NULL, src is interpreted as a simple byte array for source data.
- * @return the number of bytes written to the FIFO
+ * @return the number of bytes written to the FIFO or a negative error code on failure
  */
 int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size, int (*func)(void*, void*, int));
 
-- 
2.33.0

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [FFmpeg-devel] [PATCH 1/7] lavc/flac_parser: use a custom FIFO implementation
  2021-12-31 10:53 [FFmpeg-devel] [PATCH 1/7] lavc/flac_parser: use a custom FIFO implementation Anton Khirnov
                   ` (5 preceding siblings ...)
  2021-12-31 10:53 ` [FFmpeg-devel] [PATCH 7/7] lavu/fifo: return errors on trying to read/write too much Anton Khirnov
@ 2021-12-31 11:30 ` Andreas Rheinhardt
  2022-01-02 14:24   ` [FFmpeg-devel] [PATCH] " Anton Khirnov
  6 siblings, 1 reply; 10+ messages in thread
From: Andreas Rheinhardt @ 2021-12-31 11:30 UTC (permalink / raw)
  To: ffmpeg-devel

Anton Khirnov:
> FLAC parser currently uses AVFifoBuffer in a highly non-trivial manner,
> modifying its "internals" (the whole struct is currently public, but no
> other code touches its contents directly). E.g. it does not use any
> av_fifo functions for reading the FIFO contents, but implements its own.
> 
> Reimplement the needed parts of the AVFifoBuffer API in the FLAC parser,
> making it completely self-contained. This will allow us to make
> AVFifoBuffer private.
> ---
>  libavcodec/flac_parser.c | 191 +++++++++++++++++++++++++++++++--------
>  1 file changed, 153 insertions(+), 38 deletions(-)
> 
> diff --git a/libavcodec/flac_parser.c b/libavcodec/flac_parser.c
> index 3b27b152fc..d6af5ce836 100644
> --- a/libavcodec/flac_parser.c
> +++ b/libavcodec/flac_parser.c
> @@ -34,7 +34,6 @@
>  
>  #include "libavutil/attributes.h"
>  #include "libavutil/crc.h"
> -#include "libavutil/fifo.h"
>  #include "bytestream.h"
>  #include "parser.h"
>  #include "flac.h"
> @@ -57,6 +56,15 @@
>  #define MAX_FRAME_HEADER_SIZE 16
>  #define MAX_FRAME_VERIFY_SIZE (MAX_FRAME_HEADER_SIZE + 1)
>  
> +typedef struct FifoBuffer {
> +    uint8_t *buffer;
> +    uint8_t *end;
> +    uint8_t *rptr;
> +    uint8_t *wptr;
> +    size_t rndx;
> +    size_t wndx;
> +} FifoBuffer;
> +
>  typedef struct FLACHeaderMarker {
>      int offset;       /**< byte offset from start of FLACParseContext->buffer */
>      int link_penalty[FLAC_MAX_SEQUENTIAL_HEADERS]; /**< array of local scores
> @@ -84,7 +92,7 @@ typedef struct FLACParseContext {
>      int nb_headers_buffered;       /**< number of headers that are buffered   */
>      int best_header_valid;         /**< flag set when the parser returns junk;
>                                          if set return best_header next time   */
> -    AVFifoBuffer *fifo_buf;        /**< buffer to store all data until headers
> +    FifoBuffer fifo_buf;           /**< buffer to store all data until headers
>                                          can be verified                       */
>      int end_padded;                /**< specifies if fifo_buf's end is padded */
>      uint8_t *wrap_buf;             /**< general fifo read buffer when wrapped */
> @@ -127,6 +135,17 @@ static int frame_header_is_valid(AVCodecContext *avctx, const uint8_t *buf,
>      return 1;
>  }
>  
> +static size_t flac_fifo_size(FifoBuffer *f)

Missing const

> +{
> +    av_assert0(f->wndx >= f->rndx);

This assert looks very fishy: It will trigger if wndx has already
wrapped around while rndx has not yet (or rather, if wndx has wrapped
around once more than rndx). Or am I missing something here?

> +    return f->wndx - f->rndx;
> +}
> +
> +static size_t flac_fifo_space(FifoBuffer *f)
> +{
> +    return f->end - f->buffer - flac_fifo_size(f);
> +}
> +

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [FFmpeg-devel] [PATCH 6/7] lavu/fifo: drop useless comments
  2021-12-31 10:53 ` [FFmpeg-devel] [PATCH 6/7] lavu/fifo: drop useless comments Anton Khirnov
@ 2021-12-31 11:47   ` Andreas Rheinhardt
  0 siblings, 0 replies; 10+ messages in thread
From: Andreas Rheinhardt @ 2021-12-31 11:47 UTC (permalink / raw)
  To: ffmpeg-devel

Anton Khirnov:
> This object was never intended to be thread-safe, so these carry no
> useful information.
> ---
>  libavutil/fifo.c | 5 -----
>  1 file changed, 5 deletions(-)
> 
> diff --git a/libavutil/fifo.c b/libavutil/fifo.c
> index 171c1aa9cd..f38e8ff089 100644
> --- a/libavutil/fifo.c
> +++ b/libavutil/fifo.c
> @@ -144,7 +144,6 @@ int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size,
>              memcpy(wptr, src, len);
>              src = (uint8_t *)src + len;
>          }
> -// Write memory barrier needed for SMP here in theory
>          wptr += len;
>          if (wptr >= f->end)
>              wptr = f->buffer;
> @@ -197,7 +196,6 @@ int av_fifo_generic_peek_at(AVFifoBuffer *f, void *dest, int offset, int buf_siz
>  int av_fifo_generic_peek(AVFifoBuffer *f, void *dest, int buf_size,
>                           void (*func)(void *, void *, int))
>  {
> -// Read memory barrier needed for SMP here in theory
>      uint8_t *rptr = f->rptr;
>  
>      do {
> @@ -208,7 +206,6 @@ int av_fifo_generic_peek(AVFifoBuffer *f, void *dest, int buf_size,
>              memcpy(dest, rptr, len);
>              dest = (uint8_t *)dest + len;
>          }
> -// memory barrier needed for SMP here in theory
>          rptr += len;
>          if (rptr >= f->end)
>              rptr -= f->end - f->buffer;
> @@ -221,7 +218,6 @@ int av_fifo_generic_peek(AVFifoBuffer *f, void *dest, int buf_size,
>  int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size,
>                           void (*func)(void *, void *, int))
>  {
> -// Read memory barrier needed for SMP here in theory
>      do {
>          int len = FFMIN(f->end - f->rptr, buf_size);
>          if (func)
> @@ -230,7 +226,6 @@ int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size,
>              memcpy(dest, f->rptr, len);
>              dest = (uint8_t *)dest + len;
>          }
> -// memory barrier needed for SMP here in theory
>          av_fifo_drain(f, len);
>          buf_size -= len;
>      } while (buf_size > 0);
> 

LGTM.

- Andreas
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [FFmpeg-devel] [PATCH] lavc/flac_parser: use a custom FIFO implementation
  2021-12-31 11:30 ` [FFmpeg-devel] [PATCH 1/7] lavc/flac_parser: use a custom FIFO implementation Andreas Rheinhardt
@ 2022-01-02 14:24   ` Anton Khirnov
  0 siblings, 0 replies; 10+ messages in thread
From: Anton Khirnov @ 2022-01-02 14:24 UTC (permalink / raw)
  To: ffmpeg-devel

FLAC parser currently uses AVFifoBuffer in a highly non-trivial manner,
modifying its "internals" (the whole struct is currently public, but no
other code touches its contents directly). E.g. it does not use any
av_fifo functions for reading the FIFO contents, but implements its own.

Reimplement the needed parts of the AVFifoBuffer API in the FLAC parser,
making it completely self-contained. This will allow us to make
AVFifoBuffer private.
---
 libavcodec/flac_parser.c | 194 +++++++++++++++++++++++++++++++--------
 1 file changed, 156 insertions(+), 38 deletions(-)

Dropped [rw]ndx completely as they are not necessary - the only thing we
need in addition to read/write pointers is single flag that
distinguishes between full/empty when rptr==wptr.
---

diff --git a/libavcodec/flac_parser.c b/libavcodec/flac_parser.c
index 3b27b152fc..cd9a2cb574 100644
--- a/libavcodec/flac_parser.c
+++ b/libavcodec/flac_parser.c
@@ -34,7 +34,6 @@
 
 #include "libavutil/attributes.h"
 #include "libavutil/crc.h"
-#include "libavutil/fifo.h"
 #include "bytestream.h"
 #include "parser.h"
 #include "flac.h"
@@ -57,6 +56,14 @@
 #define MAX_FRAME_HEADER_SIZE 16
 #define MAX_FRAME_VERIFY_SIZE (MAX_FRAME_HEADER_SIZE + 1)
 
+typedef struct FifoBuffer {
+    uint8_t *buffer;
+    uint8_t *end;
+    uint8_t *rptr;
+    uint8_t *wptr;
+    int empty;
+} FifoBuffer;
+
 typedef struct FLACHeaderMarker {
     int offset;       /**< byte offset from start of FLACParseContext->buffer */
     int link_penalty[FLAC_MAX_SEQUENTIAL_HEADERS]; /**< array of local scores
@@ -84,7 +91,7 @@ typedef struct FLACParseContext {
     int nb_headers_buffered;       /**< number of headers that are buffered   */
     int best_header_valid;         /**< flag set when the parser returns junk;
                                         if set return best_header next time   */
-    AVFifoBuffer *fifo_buf;        /**< buffer to store all data until headers
+    FifoBuffer fifo_buf;           /**< buffer to store all data until headers
                                         can be verified                       */
     int end_padded;                /**< specifies if fifo_buf's end is padded */
     uint8_t *wrap_buf;             /**< general fifo read buffer when wrapped */
@@ -127,6 +134,18 @@ static int frame_header_is_valid(AVCodecContext *avctx, const uint8_t *buf,
     return 1;
 }
 
+static size_t flac_fifo_size(const FifoBuffer *f)
+{
+    if (f->wptr <= f->rptr && !f->empty)
+        return (f->wptr - f->buffer) + (f->end - f->rptr);
+    return f->wptr - f->rptr;
+}
+
+static size_t flac_fifo_space(const FifoBuffer *f)
+{
+    return f->end - f->buffer - flac_fifo_size(f);
+}
+
 /**
  * Non-destructive fast fifo pointer fetching
  * Returns a pointer from the specified offset.
@@ -143,7 +162,7 @@ static int frame_header_is_valid(AVCodecContext *avctx, const uint8_t *buf,
 static uint8_t *flac_fifo_read_wrap(FLACParseContext *fpc, int offset, int len,
                                     uint8_t **wrap_buf, int *allocated_size)
 {
-    AVFifoBuffer *f   = fpc->fifo_buf;
+    FifoBuffer   *f   = &fpc->fifo_buf;
     uint8_t *start    = f->rptr + offset;
     uint8_t *tmp_buf;
 
@@ -180,9 +199,8 @@ static uint8_t *flac_fifo_read_wrap(FLACParseContext *fpc, int offset, int len,
  * A second call to flac_fifo_read (with new offset and len) should be called
  * to get the post-wrap buf if the returned len is less than the requested.
  **/
-static uint8_t *flac_fifo_read(FLACParseContext *fpc, int offset, int *len)
+static uint8_t *flac_fifo_read(FifoBuffer *f, int offset, int *len)
 {
-    AVFifoBuffer *f   = fpc->fifo_buf;
     uint8_t *start    = f->rptr + offset;
 
     if (start >= f->end)
@@ -191,6 +209,108 @@ static uint8_t *flac_fifo_read(FLACParseContext *fpc, int offset, int *len)
     return start;
 }
 
+static int flac_fifo_grow(FifoBuffer *f, size_t inc)
+{
+    size_t size_old = f->end - f->buffer;
+    size_t offset_r = f->rptr - f->buffer;
+    size_t offset_w = f->wptr - f->buffer;
+    size_t size_new;
+
+    uint8_t *tmp;
+
+    if (size_old > SIZE_MAX - inc)
+        return AVERROR(EINVAL);
+    size_new = size_old + inc;
+
+    tmp = av_realloc(f->buffer, size_new);
+    if (!tmp)
+        return AVERROR(ENOMEM);
+
+    // move the data from the beginning of the ring buffer
+    // to the newly allocated space
+    if (offset_w <= offset_r && !f->empty) {
+        const size_t copy = FFMIN(inc, offset_w);
+        memcpy(tmp + size_old, tmp, copy);
+        if (copy < offset_w) {
+            memmove(tmp, tmp + copy, offset_w - copy);
+            offset_w -= copy;
+        } else
+            offset_w = size_old + copy;
+    }
+
+    f->buffer = tmp;
+    f->end    = f->buffer + size_new;
+    f->rptr   = f->buffer + offset_r;
+    f->wptr   = f->buffer + offset_w;
+
+    return 0;
+}
+
+static int flac_fifo_write(FifoBuffer *f, const uint8_t *src, size_t size)
+{
+    uint8_t *wptr;
+
+    if (flac_fifo_space(f) < size) {
+        int ret = flac_fifo_grow(f, FFMAX(flac_fifo_size(f), size));
+        if (ret < 0)
+            return ret;
+    }
+
+    if (size)
+        f->empty = 0;
+
+    wptr = f->wptr;
+    do {
+        size_t len = FFMIN(f->end - wptr, size);
+        memcpy(wptr, src, len);
+        src  += len;
+        wptr += len;
+        if (wptr >= f->end)
+            wptr = f->buffer;
+        size    -= len;
+    } while (size > 0);
+
+    f->wptr = wptr;
+
+    return 0;
+}
+
+static void flac_fifo_drain(FifoBuffer *f, size_t size)
+{
+    size_t size_cur = flac_fifo_size(f);
+
+    av_assert0(size_cur >= size);
+    if (size_cur == size)
+        f->empty = 1;
+
+    f->rptr += size;
+    if (f->rptr >= f->end)
+        f->rptr -= f->end - f->buffer;
+}
+
+static int flac_fifo_alloc(FifoBuffer *f, size_t size)
+{
+    memset(f, 0, sizeof(*f));
+
+    f->buffer = av_realloc(NULL, size);
+    if (!f->buffer)
+        return AVERROR(ENOMEM);
+
+    f->wptr = f->buffer;
+    f->rptr = f->buffer;
+    f->end  = f->buffer + size;
+
+    f->empty = 1;
+
+    return 0;
+}
+
+static void flac_fifo_free(FifoBuffer *f)
+{
+    av_freep(&f->buffer);
+    memset(f, 0, sizeof(*f));
+}
+
 static int find_headers_search_validate(FLACParseContext *fpc, int offset)
 {
     FLACFrameInfo fi;
@@ -263,9 +383,9 @@ static int find_new_headers(FLACParseContext *fpc, int search_start)
     fpc->nb_headers_found = 0;
 
     /* Search for a new header of at most 16 bytes. */
-    search_end = av_fifo_size(fpc->fifo_buf) - (MAX_FRAME_HEADER_SIZE - 1);
+    search_end = flac_fifo_size(&fpc->fifo_buf) - (MAX_FRAME_HEADER_SIZE - 1);
     read_len   = search_end - search_start + 1;
-    buf        = flac_fifo_read(fpc, search_start, &read_len);
+    buf        = flac_fifo_read(&fpc->fifo_buf, search_start, &read_len);
     size       = find_headers_search(fpc, buf, read_len, search_start);
     search_start += read_len - 1;
 
@@ -277,7 +397,7 @@ static int find_new_headers(FLACParseContext *fpc, int search_start)
         /* search_start + 1 is the post-wrap offset in the fifo. */
         read_len = search_end - (search_start + 1) + 1;
 
-        buf      = flac_fifo_read(fpc, search_start + 1, &read_len);
+        buf      = flac_fifo_read(&fpc->fifo_buf, search_start + 1, &read_len);
         wrap[1]  = buf[0];
 
         if ((AV_RB16(wrap) & 0xFFFE) == 0xFFF8) {
@@ -406,12 +526,12 @@ static int check_header_mismatch(FLACParseContext  *fpc,
             }
 
             read_len = end->offset - start->offset;
-            buf      = flac_fifo_read(fpc, start->offset, &read_len);
+            buf      = flac_fifo_read(&fpc->fifo_buf, start->offset, &read_len);
             crc      = av_crc(av_crc_get_table(AV_CRC_16_ANSI), 0, buf, read_len);
             read_len = (end->offset - start->offset) - read_len;
 
             if (read_len) {
-                buf = flac_fifo_read(fpc, end->offset - read_len, &read_len);
+                buf = flac_fifo_read(&fpc->fifo_buf, end->offset - read_len, &read_len);
                 crc = av_crc(av_crc_get_table(AV_CRC_16_ANSI), crc, buf, read_len);
             }
         }
@@ -500,7 +620,7 @@ static int get_best_header(FLACParseContext *fpc, const uint8_t **poutbuf,
     FLACHeaderMarker *header = fpc->best_header;
     FLACHeaderMarker *child  = header->best_child;
     if (!child) {
-        *poutbuf_size = av_fifo_size(fpc->fifo_buf) - header->offset;
+        *poutbuf_size = flac_fifo_size(&fpc->fifo_buf) - header->offset;
     } else {
         *poutbuf_size = child->offset - header->offset;
 
@@ -519,7 +639,6 @@ static int get_best_header(FLACParseContext *fpc, const uint8_t **poutbuf,
                                         &fpc->wrap_buf,
                                         &fpc->wrap_buf_allocated_size);
 
-
     if (fpc->pc->flags & PARSER_FLAG_USE_CODEC_TS) {
         if (header->fi.is_var_size)
           fpc->pc->pts = header->fi.frame_or_sample_num;
@@ -534,7 +653,7 @@ static int get_best_header(FLACParseContext *fpc, const uint8_t **poutbuf,
     /* Return the negative overread index so the client can compute pos.
        This should be the amount overread to the beginning of the child */
     if (child)
-        return child->offset - av_fifo_size(fpc->fifo_buf);
+        return child->offset - flac_fifo_size(&fpc->fifo_buf);
     return 0;
 }
 
@@ -586,7 +705,7 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx,
             fpc->nb_headers_buffered--;
         }
         /* Release returned data from ring buffer. */
-        av_fifo_drain(fpc->fifo_buf, best_child->offset);
+        flac_fifo_drain(&fpc->fifo_buf, best_child->offset);
 
         /* Fix the offset for the headers remaining to match the new buffer. */
         for (curr = best_child->next; curr; curr = curr->next)
@@ -620,7 +739,7 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx,
     while ((buf_size && read_end < buf + buf_size &&
             fpc->nb_headers_buffered < FLAC_MIN_HEADERS)
            || (!buf_size && !fpc->end_padded)) {
-        int start_offset;
+        int start_offset, ret;
 
         /* Pad the end once if EOF, to check the final region for headers. */
         if (!buf_size) {
@@ -634,8 +753,8 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx,
                                               nb_desired * FLAC_AVG_FRAME_SIZE);
         }
 
-        if (!av_fifo_space(fpc->fifo_buf) &&
-            av_fifo_size(fpc->fifo_buf) / FLAC_AVG_FRAME_SIZE >
+        if (!flac_fifo_space(&fpc->fifo_buf) &&
+            flac_fifo_size(&fpc->fifo_buf) / FLAC_AVG_FRAME_SIZE >
             fpc->nb_headers_buffered * 20) {
             /* There is less than one valid flac header buffered for 20 headers
              * buffered. Therefore the fifo is most likely filled with invalid
@@ -644,24 +763,20 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx,
         }
 
         /* Fill the buffer. */
-        if (   av_fifo_space(fpc->fifo_buf) < read_end - read_start
-            && av_fifo_realloc2(fpc->fifo_buf, (read_end - read_start) + 2*av_fifo_size(fpc->fifo_buf)) < 0) {
-            av_log(avctx, AV_LOG_ERROR,
-                   "couldn't reallocate buffer of size %"PTRDIFF_SPECIFIER"\n",
-                   (read_end - read_start) + av_fifo_size(fpc->fifo_buf));
-            goto handle_error;
-        }
-
         if (buf_size) {
-            av_fifo_generic_write(fpc->fifo_buf, (void*) read_start,
-                                  read_end - read_start, NULL);
+            ret = flac_fifo_write(&fpc->fifo_buf, read_start,
+                                  read_end - read_start);
         } else {
             int8_t pad[MAX_FRAME_HEADER_SIZE] = { 0 };
-            av_fifo_generic_write(fpc->fifo_buf, pad, sizeof(pad), NULL);
+            ret = flac_fifo_write(&fpc->fifo_buf, pad, sizeof(pad));
+        }
+        if (ret < 0) {
+            av_log(avctx, AV_LOG_ERROR, "Error buffering data\n");
+            goto handle_error;
         }
 
         /* Tag headers and update sequences. */
-        start_offset = av_fifo_size(fpc->fifo_buf) -
+        start_offset = flac_fifo_size(&fpc->fifo_buf) -
                        ((read_end - read_start) + (MAX_FRAME_HEADER_SIZE - 1));
         start_offset = FFMAX(0, start_offset);
         nb_headers   = find_new_headers(fpc, start_offset);
@@ -689,14 +804,15 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx,
 
         /* restore the state pre-padding */
         if (fpc->end_padded) {
-            int warp = fpc->fifo_buf->wptr - fpc->fifo_buf->buffer < MAX_FRAME_HEADER_SIZE;
+            int empty = flac_fifo_size(&fpc->fifo_buf) == MAX_FRAME_HEADER_SIZE;
+            int warp = fpc->fifo_buf.wptr - fpc->fifo_buf.buffer < MAX_FRAME_HEADER_SIZE;
             /* HACK: drain the tail of the fifo */
-            fpc->fifo_buf->wptr -= MAX_FRAME_HEADER_SIZE;
-            fpc->fifo_buf->wndx -= MAX_FRAME_HEADER_SIZE;
+            fpc->fifo_buf.wptr -= MAX_FRAME_HEADER_SIZE;
             if (warp) {
-                fpc->fifo_buf->wptr += fpc->fifo_buf->end -
-                    fpc->fifo_buf->buffer;
+                fpc->fifo_buf.wptr += fpc->fifo_buf.end -
+                    fpc->fifo_buf.buffer;
             }
+            fpc->fifo_buf.empty = empty;
             read_start = read_end = NULL;
         }
     }
@@ -727,7 +843,7 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx,
                                                 &fpc->wrap_buf,
                                                 &fpc->wrap_buf_allocated_size);
             return buf_size ? (read_end - buf) : (fpc->best_header->offset -
-                                                  av_fifo_size(fpc->fifo_buf));
+                                                  flac_fifo_size(&fpc->fifo_buf));
         }
         if (!buf_size)
             return get_best_header(fpc, poutbuf, poutbuf_size);
@@ -742,11 +858,13 @@ handle_error:
 static av_cold int flac_parse_init(AVCodecParserContext *c)
 {
     FLACParseContext *fpc = c->priv_data;
+    int ret;
+
     fpc->pc = c;
     /* There will generally be FLAC_MIN_HEADERS buffered in the fifo before
        it drains.  This is allocated early to avoid slow reallocation. */
-    fpc->fifo_buf = av_fifo_alloc_array(FLAC_MIN_HEADERS + 3, FLAC_AVG_FRAME_SIZE);
-    if (!fpc->fifo_buf) {
+    ret = flac_fifo_alloc(&fpc->fifo_buf, (FLAC_MIN_HEADERS + 3) * FLAC_AVG_FRAME_SIZE);
+    if (ret < 0) {
         av_log(fpc->avctx, AV_LOG_ERROR,
                 "couldn't allocate fifo_buf\n");
         return AVERROR(ENOMEM);
@@ -765,7 +883,7 @@ static void flac_parse_close(AVCodecParserContext *c)
         curr = temp;
     }
     fpc->headers = NULL;
-    av_fifo_freep(&fpc->fifo_buf);
+    flac_fifo_free(&fpc->fifo_buf);
     av_freep(&fpc->wrap_buf);
 }
 
-- 
2.33.0

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2022-01-02 14:24 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-31 10:53 [FFmpeg-devel] [PATCH 1/7] lavc/flac_parser: use a custom FIFO implementation Anton Khirnov
2021-12-31 10:53 ` [FFmpeg-devel] [PATCH 2/7] lavf/dvenc: replace av_fifo_peek2() with av_fifo_generic_peek_at() Anton Khirnov
2021-12-31 10:53 ` [FFmpeg-devel] [PATCH 3/7] lavu/fifo: deprecate av_fifo_peek2() Anton Khirnov
2021-12-31 10:53 ` [FFmpeg-devel] [PATCH 4/7] lavu/fifo: simplify av_fifo_alloc() Anton Khirnov
2021-12-31 10:53 ` [FFmpeg-devel] [PATCH 5/7] lavu/fifo: do not copy the whole fifo when reallocating Anton Khirnov
2021-12-31 10:53 ` [FFmpeg-devel] [PATCH 6/7] lavu/fifo: drop useless comments Anton Khirnov
2021-12-31 11:47   ` Andreas Rheinhardt
2021-12-31 10:53 ` [FFmpeg-devel] [PATCH 7/7] lavu/fifo: return errors on trying to read/write too much Anton Khirnov
2021-12-31 11:30 ` [FFmpeg-devel] [PATCH 1/7] lavc/flac_parser: use a custom FIFO implementation Andreas Rheinhardt
2022-01-02 14:24   ` [FFmpeg-devel] [PATCH] " Anton Khirnov

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git