X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavutil%2Ffifo.c;h=7bd48a2271adb958ce38257bc3c2a2a57761b5e4;hb=0a830b95d597633905074744fc8391229ac03bec;hp=07fb4ec8114b3efe4f7fb936c9bc066e6f38604f;hpb=c9b35246191fdc1dd70b8cb067711c10c4e75173;p=ffmpeg diff --git a/libavutil/fifo.c b/libavutil/fifo.c index 07fb4ec8114..7bd48a2271a 100644 --- a/libavutil/fifo.c +++ b/libavutil/fifo.c @@ -148,29 +148,65 @@ int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size, return total - size; } +int av_fifo_generic_peek_at(AVFifoBuffer *f, void *dest, int offset, int buf_size, void (*func)(void*, void*, int)) +{ + 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 >= f->end - rptr) + rptr += offset - (f->end - f->buffer); + else + rptr += offset; + + while (buf_size > 0) { + int len; + + if (rptr >= f->end) + rptr -= f->end - f->buffer; + + len = FFMIN(f->end - rptr, buf_size); + if (func) + func(dest, rptr, len); + else { + memcpy(dest, rptr, len); + dest = (uint8_t *)dest + len; + } + + buf_size -= len; + rptr += len; + } + + return 0; +} + 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; - uint32_t rndx = f->rndx; do { - int len = FFMIN(f->end - f->rptr, buf_size); + int len = FFMIN(f->end - rptr, buf_size); if (func) - func(dest, f->rptr, len); + func(dest, rptr, len); else { - memcpy(dest, f->rptr, len); + memcpy(dest, rptr, len); dest = (uint8_t *)dest + len; } // memory barrier needed for SMP here in theory - av_fifo_drain(f, len); + rptr += len; + if (rptr >= f->end) + rptr -= f->end - f->buffer; buf_size -= len; } while (buf_size > 0); - f->rptr = rptr; - f->rndx = rndx; - return 0; } @@ -223,6 +259,14 @@ int main(void) } printf("\n"); + /* peek_at at FIFO */ + n = av_fifo_size(fifo) / sizeof(int); + for (i = 0; i < n; i++) { + av_fifo_generic_peek_at(fifo, &j, i * sizeof(int), sizeof(j), NULL); + printf("%d: %d\n", i, j); + } + printf("\n"); + /* read data */ for (i = 0; av_fifo_size(fifo) >= sizeof(int); i++) { av_fifo_generic_read(fifo, &j, sizeof(int), NULL); @@ -230,6 +274,21 @@ int main(void) } printf("\n"); + /* test *ndx overflow */ + av_fifo_reset(fifo); + fifo->rndx = fifo->wndx = ~(uint32_t)0 - 5; + + /* fill data */ + for (i = 0; av_fifo_space(fifo) >= sizeof(int); i++) + av_fifo_generic_write(fifo, &i, sizeof(int), NULL); + + /* peek_at at FIFO */ + n = av_fifo_size(fifo) / sizeof(int); + for (i = 0; i < n; i++) { + av_fifo_generic_peek_at(fifo, &j, i * sizeof(int), sizeof(j), NULL); + printf("%d: %d\n", i, j); + } + av_fifo_free(fifo); return 0;