1/* 2 * This file is part of FFmpeg. 3 * 4 * FFmpeg is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * FFmpeg is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with FFmpeg; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 19#include <stdio.h> 20#include <stdlib.h> 21#include "libavutil/common.h" 22#include "libavutil/fifo.h" 23#include "libavutil/lfg.h" 24#include "libavutil/random_seed.h" 25 26typedef struct CBState { 27 unsigned int read_idx; 28 unsigned int write_idx; 29 unsigned int to_process; 30 unsigned int offset; 31} CBState; 32 33static int read_cb(void *opaque, void *buf, size_t *nb_elems) 34{ 35 CBState *s = opaque; 36 unsigned *b = buf; 37 38 *nb_elems = FFMIN(*nb_elems, s->to_process); 39 40 for (unsigned i = 0; i < *nb_elems; i++) 41 if (b[i] != s->read_idx + s->offset + i) { 42 printf("Mismatch at idx %u offset %u i %u\n", 43 s->read_idx, s->offset, i); 44 return AVERROR_BUG; 45 } 46 47 s->offset += *nb_elems; 48 s->to_process -= *nb_elems; 49 50 return 0; 51} 52 53static int write_cb(void *opaque, void *buf, size_t *nb_elems) 54{ 55 CBState *s = opaque; 56 unsigned *b = buf; 57 58 *nb_elems = FFMIN(*nb_elems, s->to_process); 59 60 for (unsigned i = 0; i < *nb_elems; i++) 61 b[i] = s->write_idx + i; 62 63 s->write_idx += *nb_elems; 64 s->to_process -= *nb_elems; 65 66 return 0; 67} 68 69int main(void) 70{ 71 /* create a FIFO buffer */ 72 AVFifo *fifo = av_fifo_alloc2(13, sizeof(int), 0); 73 int i, j, n, *p; 74 75 /* fill data */ 76 for (i = 0; av_fifo_can_write(fifo); i++) 77 av_fifo_write(fifo, &i, 1); 78 79 /* peek_at at FIFO */ 80 n = av_fifo_can_read(fifo); 81 for (i = 0; i < n; i++) { 82 av_fifo_peek(fifo, &j, 1, i); 83 printf("%d: %d\n", i, j); 84 } 85 printf("\n"); 86 87 /* generic peek at FIFO */ 88 89 n = av_fifo_can_read(fifo); 90 p = malloc(n * av_fifo_elem_size(fifo)); 91 if (p == NULL) { 92 fprintf(stderr, "failed to allocate memory.\n"); 93 exit(1); 94 } 95 96 (void) av_fifo_peek(fifo, p, n, 0); 97 98 /* read data at p */ 99 for(i = 0; i < n; ++i) 100 printf("%d: %d\n", i, p[i]); 101 102 putchar('\n'); 103 104 /* read data */ 105 for (i = 0; av_fifo_can_read(fifo); i++) { 106 av_fifo_read(fifo, &j, 1); 107 printf("%d ", j); 108 } 109 printf("\n"); 110 111 /* fill data */ 112 for (i = 0; av_fifo_can_write(fifo); i++) 113 av_fifo_write(fifo, &i, 1); 114 115 /* peek_at at FIFO */ 116 n = av_fifo_can_read(fifo); 117 for (i = 0; i < n; i++) { 118 av_fifo_peek(fifo, &j, 1, i); 119 printf("%d: %d\n", i, j); 120 } 121 putchar('\n'); 122 123 /* test fifo_grow */ 124 (void) av_fifo_grow2(fifo, 15); 125 126 /* fill data */ 127 n = av_fifo_can_read(fifo); 128 for (i = n; av_fifo_can_write(fifo); ++i) 129 av_fifo_write(fifo, &i, 1); 130 131 /* peek_at at FIFO */ 132 n = av_fifo_can_read(fifo); 133 for (i = 0; i < n; i++) { 134 av_fifo_peek(fifo, &j, 1, i); 135 printf("%d: %d\n", i, j); 136 } 137 138 av_fifo_freep2(&fifo); 139 140 /* test randomly-sized write/read/peek with a callback */ 141 { 142 CBState s = { 0 }; 143 uint32_t seed = av_get_random_seed(); 144 145 AVLFG lfg; 146 int ret; 147 148 av_lfg_init(&lfg, seed); 149 150 fifo = av_fifo_alloc2(1, sizeof(unsigned), AV_FIFO_FLAG_AUTO_GROW); 151 152 for (i = 0; i < 32; i++) { 153 size_t nb_elems = 16; 154 unsigned to_process = av_lfg_get(&lfg) % nb_elems; 155 156 s.to_process = to_process; 157 158 ret = av_fifo_write_from_cb(fifo, write_cb, &s, &nb_elems); 159 if (ret < 0 || s.to_process || nb_elems != to_process) { 160 printf("FIFO write fail; seed %"PRIu32"\n", seed); 161 return 1; 162 } 163 164 nb_elems = av_fifo_can_read(fifo); 165 if (nb_elems > 1) { 166 s.offset = av_lfg_get(&lfg) % (nb_elems - 1); 167 nb_elems -= s.offset; 168 169 s.to_process = av_lfg_get(&lfg) % nb_elems; 170 to_process = s.to_process; 171 172 ret = av_fifo_peek_to_cb(fifo, read_cb, &s, &nb_elems, s.offset); 173 if (ret < 0 || s.to_process || nb_elems != to_process) { 174 printf("FIFO peek fail; seed %"PRIu32"\n", seed); 175 return 1; 176 } 177 } 178 179 nb_elems = av_fifo_can_read(fifo); 180 to_process = nb_elems ? av_lfg_get(&lfg) % nb_elems : 0; 181 s.to_process = to_process; 182 s.offset = 0; 183 184 ret = av_fifo_read_to_cb(fifo, read_cb, &s, &nb_elems); 185 if (ret < 0 || s.to_process || to_process != nb_elems) { 186 printf("FIFO read fail; seed %"PRIu32"\n", seed); 187 return 1; 188 } 189 s.read_idx += s.offset; 190 } 191 } 192 193 av_fifo_freep2(&fifo); 194 free(p); 195 196 return 0; 197} 198