* [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
* 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 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
* [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