FFmpeg  4.4.5
async.c
Go to the documentation of this file.
1 /*
2  * Input async protocol.
3  * Copyright (c) 2015 Zhang Rui <bbcallen@gmail.com>
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  *
21  * Based on libavformat/cache.c by Michael Niedermayer
22  */
23 
24  /**
25  * @TODO
26  * support timeout
27  * support work with concatdec, hls
28  */
29 
30 #include "libavutil/avassert.h"
31 #include "libavutil/avstring.h"
32 #include "libavutil/error.h"
33 #include "libavutil/fifo.h"
34 #include "libavutil/log.h"
35 #include "libavutil/opt.h"
36 #include "libavutil/thread.h"
37 #include "url.h"
38 #include <stdint.h>
39 
40 #if HAVE_UNISTD_H
41 #include <unistd.h>
42 #endif
43 
44 #define BUFFER_CAPACITY (4 * 1024 * 1024)
45 #define READ_BACK_CAPACITY (4 * 1024 * 1024)
46 #define SHORT_SEEK_THRESHOLD (256 * 1024)
47 
48 typedef struct RingBuffer
49 {
52 
53  int read_pos;
54 } RingBuffer;
55 
56 typedef struct Context {
57  AVClass *class;
59 
65 
67  int io_error;
69 
73 
78 
81 } Context;
82 
83 static int ring_init(RingBuffer *ring, unsigned int capacity, int read_back_capacity)
84 {
85  memset(ring, 0, sizeof(RingBuffer));
86  ring->fifo = av_fifo_alloc(capacity + read_back_capacity);
87  if (!ring->fifo)
88  return AVERROR(ENOMEM);
89 
90  ring->read_back_capacity = read_back_capacity;
91  return 0;
92 }
93 
94 static void ring_destroy(RingBuffer *ring)
95 {
96  av_fifo_freep(&ring->fifo);
97 }
98 
99 static void ring_reset(RingBuffer *ring)
100 {
101  av_fifo_reset(ring->fifo);
102  ring->read_pos = 0;
103 }
104 
105 static int ring_size(RingBuffer *ring)
106 {
107  return av_fifo_size(ring->fifo) - ring->read_pos;
108 }
109 
110 static int ring_space(RingBuffer *ring)
111 {
112  return av_fifo_space(ring->fifo);
113 }
114 
115 static int ring_generic_read(RingBuffer *ring, void *dest, int buf_size, void (*func)(void*, void*, int))
116 {
117  int ret;
118 
119  av_assert2(buf_size <= ring_size(ring));
120  ret = av_fifo_generic_peek_at(ring->fifo, dest, ring->read_pos, buf_size, func);
121  ring->read_pos += buf_size;
122 
123  if (ring->read_pos > ring->read_back_capacity) {
124  av_fifo_drain(ring->fifo, ring->read_pos - ring->read_back_capacity);
125  ring->read_pos = ring->read_back_capacity;
126  }
127 
128  return ret;
129 }
130 
131 static int ring_generic_write(RingBuffer *ring, void *src, int size, int (*func)(void*, void*, int))
132 {
133  av_assert2(size <= ring_space(ring));
134  return av_fifo_generic_write(ring->fifo, src, size, func);
135 }
136 
138 {
139  return ring->read_pos;
140 }
141 
142 static int ring_drain(RingBuffer *ring, int offset)
143 {
145  av_assert2(offset <= ring_size(ring));
146  ring->read_pos += offset;
147  return 0;
148 }
149 
150 static int async_check_interrupt(void *arg)
151 {
152  URLContext *h = arg;
153  Context *c = h->priv_data;
154 
155  if (c->abort_request)
156  return 1;
157 
158  if (ff_check_interrupt(&c->interrupt_callback))
159  c->abort_request = 1;
160 
161  return c->abort_request;
162 }
163 
164 static int wrapped_url_read(void *src, void *dst, int size)
165 {
166  URLContext *h = src;
167  Context *c = h->priv_data;
168  int ret;
169 
170  ret = ffurl_read(c->inner, dst, size);
171  c->inner_io_error = ret < 0 ? ret : 0;
172 
173  return ret;
174 }
175 
176 static void *async_buffer_task(void *arg)
177 {
178  URLContext *h = arg;
179  Context *c = h->priv_data;
180  RingBuffer *ring = &c->ring;
181  int ret = 0;
182  int64_t seek_ret;
183 
184  while (1) {
185  int fifo_space, to_copy;
186 
187  pthread_mutex_lock(&c->mutex);
188  if (async_check_interrupt(h)) {
189  c->io_eof_reached = 1;
190  c->io_error = AVERROR_EXIT;
191  pthread_cond_signal(&c->cond_wakeup_main);
192  pthread_mutex_unlock(&c->mutex);
193  break;
194  }
195 
196  if (c->seek_request) {
197  seek_ret = ffurl_seek(c->inner, c->seek_pos, c->seek_whence);
198  if (seek_ret >= 0) {
199  c->io_eof_reached = 0;
200  c->io_error = 0;
201  ring_reset(ring);
202  }
203 
204  c->seek_completed = 1;
205  c->seek_ret = seek_ret;
206  c->seek_request = 0;
207 
208 
209  pthread_cond_signal(&c->cond_wakeup_main);
210  pthread_mutex_unlock(&c->mutex);
211  continue;
212  }
213 
214  fifo_space = ring_space(ring);
215  if (c->io_eof_reached || fifo_space <= 0) {
216  pthread_cond_signal(&c->cond_wakeup_main);
217  pthread_cond_wait(&c->cond_wakeup_background, &c->mutex);
218  pthread_mutex_unlock(&c->mutex);
219  continue;
220  }
221  pthread_mutex_unlock(&c->mutex);
222 
223  to_copy = FFMIN(4096, fifo_space);
224  ret = ring_generic_write(ring, (void *)h, to_copy, wrapped_url_read);
225 
226  pthread_mutex_lock(&c->mutex);
227  if (ret <= 0) {
228  c->io_eof_reached = 1;
229  if (c->inner_io_error < 0)
230  c->io_error = c->inner_io_error;
231  }
232 
233  pthread_cond_signal(&c->cond_wakeup_main);
234  pthread_mutex_unlock(&c->mutex);
235  }
236 
237  return NULL;
238 }
239 
240 static int async_open(URLContext *h, const char *arg, int flags, AVDictionary **options)
241 {
242  Context *c = h->priv_data;
243  int ret;
244  AVIOInterruptCB interrupt_callback = {.callback = async_check_interrupt, .opaque = h};
245 
246  av_strstart(arg, "async:", &arg);
247 
249  if (ret < 0)
250  goto fifo_fail;
251 
252  /* wrap interrupt callback */
253  c->interrupt_callback = h->interrupt_callback;
254  ret = ffurl_open_whitelist(&c->inner, arg, flags, &interrupt_callback, options, h->protocol_whitelist, h->protocol_blacklist, h);
255  if (ret != 0) {
256  av_log(h, AV_LOG_ERROR, "ffurl_open failed : %s, %s\n", av_err2str(ret), arg);
257  goto url_fail;
258  }
259 
260  c->logical_size = ffurl_size(c->inner);
261  h->is_streamed = c->inner->is_streamed;
262 
263  ret = pthread_mutex_init(&c->mutex, NULL);
264  if (ret != 0) {
265  ret = AVERROR(ret);
266  av_log(h, AV_LOG_ERROR, "pthread_mutex_init failed : %s\n", av_err2str(ret));
267  goto mutex_fail;
268  }
269 
270  ret = pthread_cond_init(&c->cond_wakeup_main, NULL);
271  if (ret != 0) {
272  ret = AVERROR(ret);
273  av_log(h, AV_LOG_ERROR, "pthread_cond_init failed : %s\n", av_err2str(ret));
274  goto cond_wakeup_main_fail;
275  }
276 
277  ret = pthread_cond_init(&c->cond_wakeup_background, NULL);
278  if (ret != 0) {
279  ret = AVERROR(ret);
280  av_log(h, AV_LOG_ERROR, "pthread_cond_init failed : %s\n", av_err2str(ret));
281  goto cond_wakeup_background_fail;
282  }
283 
284  ret = pthread_create(&c->async_buffer_thread, NULL, async_buffer_task, h);
285  if (ret) {
286  ret = AVERROR(ret);
287  av_log(h, AV_LOG_ERROR, "pthread_create failed : %s\n", av_err2str(ret));
288  goto thread_fail;
289  }
290 
291  return 0;
292 
293 thread_fail:
294  pthread_cond_destroy(&c->cond_wakeup_background);
295 cond_wakeup_background_fail:
296  pthread_cond_destroy(&c->cond_wakeup_main);
297 cond_wakeup_main_fail:
298  pthread_mutex_destroy(&c->mutex);
299 mutex_fail:
300  ffurl_closep(&c->inner);
301 url_fail:
302  ring_destroy(&c->ring);
303 fifo_fail:
304  return ret;
305 }
306 
308 {
309  Context *c = h->priv_data;
310  int ret;
311 
312  pthread_mutex_lock(&c->mutex);
313  c->abort_request = 1;
314  pthread_cond_signal(&c->cond_wakeup_background);
315  pthread_mutex_unlock(&c->mutex);
316 
317  ret = pthread_join(c->async_buffer_thread, NULL);
318  if (ret != 0)
319  av_log(h, AV_LOG_ERROR, "pthread_join(): %s\n", av_err2str(ret));
320 
321  pthread_cond_destroy(&c->cond_wakeup_background);
322  pthread_cond_destroy(&c->cond_wakeup_main);
323  pthread_mutex_destroy(&c->mutex);
324  ffurl_closep(&c->inner);
325  ring_destroy(&c->ring);
326 
327  return 0;
328 }
329 
330 static int async_read_internal(URLContext *h, void *dest, int size, int read_complete,
331  void (*func)(void*, void*, int))
332 {
333  Context *c = h->priv_data;
334  RingBuffer *ring = &c->ring;
335  int to_read = size;
336  int ret = 0;
337 
338  pthread_mutex_lock(&c->mutex);
339 
340  while (to_read > 0) {
341  int fifo_size, to_copy;
342  if (async_check_interrupt(h)) {
343  ret = AVERROR_EXIT;
344  break;
345  }
346  fifo_size = ring_size(ring);
347  to_copy = FFMIN(to_read, fifo_size);
348  if (to_copy > 0) {
349  ring_generic_read(ring, dest, to_copy, func);
350  if (!func)
351  dest = (uint8_t *)dest + to_copy;
352  c->logical_pos += to_copy;
353  to_read -= to_copy;
354  ret = size - to_read;
355 
356  if (to_read <= 0 || !read_complete)
357  break;
358  } else if (c->io_eof_reached) {
359  if (ret <= 0) {
360  if (c->io_error)
361  ret = c->io_error;
362  else
363  ret = AVERROR_EOF;
364  }
365  break;
366  }
367  pthread_cond_signal(&c->cond_wakeup_background);
368  pthread_cond_wait(&c->cond_wakeup_main, &c->mutex);
369  }
370 
371  pthread_cond_signal(&c->cond_wakeup_background);
372  pthread_mutex_unlock(&c->mutex);
373 
374  return ret;
375 }
376 
377 static int async_read(URLContext *h, unsigned char *buf, int size)
378 {
379  return async_read_internal(h, buf, size, 0, NULL);
380 }
381 
382 static void fifo_do_not_copy_func(void* dest, void* src, int size) {
383  // do not copy
384 }
385 
386 static int64_t async_seek(URLContext *h, int64_t pos, int whence)
387 {
388  Context *c = h->priv_data;
389  RingBuffer *ring = &c->ring;
390  int64_t ret;
391  int64_t new_logical_pos;
392  int fifo_size;
393  int fifo_size_of_read_back;
394 
395  if (whence == AVSEEK_SIZE) {
396  av_log(h, AV_LOG_TRACE, "async_seek: AVSEEK_SIZE: %"PRId64"\n", (int64_t)c->logical_size);
397  return c->logical_size;
398  } else if (whence == SEEK_CUR) {
399  av_log(h, AV_LOG_TRACE, "async_seek: %"PRId64"\n", pos);
400  new_logical_pos = pos + c->logical_pos;
401  } else if (whence == SEEK_SET){
402  av_log(h, AV_LOG_TRACE, "async_seek: %"PRId64"\n", pos);
403  new_logical_pos = pos;
404  } else {
405  return AVERROR(EINVAL);
406  }
407  if (new_logical_pos < 0)
408  return AVERROR(EINVAL);
409 
410  fifo_size = ring_size(ring);
411  fifo_size_of_read_back = ring_size_of_read_back(ring);
412  if (new_logical_pos == c->logical_pos) {
413  /* current position */
414  return c->logical_pos;
415  } else if ((new_logical_pos >= (c->logical_pos - fifo_size_of_read_back)) &&
416  (new_logical_pos < (c->logical_pos + fifo_size + SHORT_SEEK_THRESHOLD))) {
417  int pos_delta = (int)(new_logical_pos - c->logical_pos);
418  /* fast seek */
419  av_log(h, AV_LOG_TRACE, "async_seek: fask_seek %"PRId64" from %d dist:%d/%d\n",
420  new_logical_pos, (int)c->logical_pos,
421  (int)(new_logical_pos - c->logical_pos), fifo_size);
422 
423  if (pos_delta > 0) {
424  // fast seek forwards
426  } else {
427  // fast seek backwards
428  ring_drain(ring, pos_delta);
429  c->logical_pos = new_logical_pos;
430  }
431 
432  return c->logical_pos;
433  } else if (c->logical_size <= 0) {
434  /* can not seek */
435  return AVERROR(EINVAL);
436  } else if (new_logical_pos > c->logical_size) {
437  /* beyond end */
438  return AVERROR(EINVAL);
439  }
440 
441  pthread_mutex_lock(&c->mutex);
442 
443  c->seek_request = 1;
444  c->seek_pos = new_logical_pos;
445  c->seek_whence = SEEK_SET;
446  c->seek_completed = 0;
447  c->seek_ret = 0;
448 
449  while (1) {
450  if (async_check_interrupt(h)) {
451  ret = AVERROR_EXIT;
452  break;
453  }
454  if (c->seek_completed) {
455  if (c->seek_ret >= 0)
456  c->logical_pos = c->seek_ret;
457  ret = c->seek_ret;
458  break;
459  }
460  pthread_cond_signal(&c->cond_wakeup_background);
461  pthread_cond_wait(&c->cond_wakeup_main, &c->mutex);
462  }
463 
464  pthread_mutex_unlock(&c->mutex);
465 
466  return ret;
467 }
468 
469 #define OFFSET(x) offsetof(Context, x)
470 #define D AV_OPT_FLAG_DECODING_PARAM
471 
472 static const AVOption options[] = {
473  {NULL},
474 };
475 
476 #undef D
477 #undef OFFSET
478 
479 static const AVClass async_context_class = {
480  .class_name = "Async",
481  .item_name = av_default_item_name,
482  .option = options,
483  .version = LIBAVUTIL_VERSION_INT,
484 };
485 
487  .name = "async",
488  .url_open2 = async_open,
489  .url_read = async_read,
490  .url_seek = async_seek,
491  .url_close = async_close,
492  .priv_data_size = sizeof(Context),
493  .priv_data_class = &async_context_class,
494 };
495 
496 #if 0
497 
498 #define TEST_SEEK_POS (1536)
499 #define TEST_STREAM_SIZE (2048)
500 
501 typedef struct TestContext {
502  AVClass *class;
503  int64_t logical_pos;
504  int64_t logical_size;
505 
506  /* options */
507  int opt_read_error;
508 } TestContext;
509 
510 static int async_test_open(URLContext *h, const char *arg, int flags, AVDictionary **options)
511 {
512  TestContext *c = h->priv_data;
513  c->logical_pos = 0;
514  c->logical_size = TEST_STREAM_SIZE;
515  return 0;
516 }
517 
518 static int async_test_close(URLContext *h)
519 {
520  return 0;
521 }
522 
523 static int async_test_read(URLContext *h, unsigned char *buf, int size)
524 {
525  TestContext *c = h->priv_data;
526  int i;
527  int read_len = 0;
528 
529  if (c->opt_read_error)
530  return c->opt_read_error;
531 
532  if (c->logical_pos >= c->logical_size)
533  return AVERROR_EOF;
534 
535  for (i = 0; i < size; ++i) {
536  buf[i] = c->logical_pos & 0xFF;
537 
538  c->logical_pos++;
539  read_len++;
540 
541  if (c->logical_pos >= c->logical_size)
542  break;
543  }
544 
545  return read_len;
546 }
547 
548 static int64_t async_test_seek(URLContext *h, int64_t pos, int whence)
549 {
550  TestContext *c = h->priv_data;
551  int64_t new_logical_pos;
552 
553  if (whence == AVSEEK_SIZE) {
554  return c->logical_size;
555  } else if (whence == SEEK_CUR) {
556  new_logical_pos = pos + c->logical_pos;
557  } else if (whence == SEEK_SET){
558  new_logical_pos = pos;
559  } else {
560  return AVERROR(EINVAL);
561  }
562  if (new_logical_pos < 0)
563  return AVERROR(EINVAL);
564 
565  c->logical_pos = new_logical_pos;
566  return new_logical_pos;
567 }
568 
569 #define OFFSET(x) offsetof(TestContext, x)
570 #define D AV_OPT_FLAG_DECODING_PARAM
571 
572 static const AVOption async_test_options[] = {
573  { "async-test-read-error", "cause read fail",
574  OFFSET(opt_read_error), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, .flags = D },
575  {NULL},
576 };
577 
578 #undef D
579 #undef OFFSET
580 
581 static const AVClass async_test_context_class = {
582  .class_name = "Async-Test",
583  .item_name = av_default_item_name,
584  .option = async_test_options,
585  .version = LIBAVUTIL_VERSION_INT,
586 };
587 
588 const URLProtocol ff_async_test_protocol = {
589  .name = "async-test",
590  .url_open2 = async_test_open,
591  .url_read = async_test_read,
592  .url_seek = async_test_seek,
593  .url_close = async_test_close,
594  .priv_data_size = sizeof(TestContext),
595  .priv_data_class = &async_test_context_class,
596 };
597 
598 int main(void)
599 {
600  URLContext *h = NULL;
601  int i;
602  int ret;
603  int64_t size;
604  int64_t pos;
605  int64_t read_len;
606  unsigned char buf[4096];
608 
609  ffurl_register_protocol(&ff_async_protocol);
610  ffurl_register_protocol(&ff_async_test_protocol);
611 
612  /*
613  * test normal read
614  */
615  ret = ffurl_open_whitelist(&h, "async:async-test:", AVIO_FLAG_READ,
616  NULL, NULL, NULL, NULL, NULL);
617  printf("open: %d\n", ret);
618 
619  size = ffurl_size(h);
620  printf("size: %"PRId64"\n", size);
621 
622  pos = ffurl_seek(h, 0, SEEK_CUR);
623  read_len = 0;
624  while (1) {
625  ret = ffurl_read(h, buf, sizeof(buf));
626  if (ret == AVERROR_EOF) {
627  printf("read-error: AVERROR_EOF at %"PRId64"\n", ffurl_seek(h, 0, SEEK_CUR));
628  break;
629  }
630  else if (ret == 0)
631  break;
632  else if (ret < 0) {
633  printf("read-error: %d at %"PRId64"\n", ret, ffurl_seek(h, 0, SEEK_CUR));
634  goto fail;
635  } else {
636  for (i = 0; i < ret; ++i) {
637  if (buf[i] != (pos & 0xFF)) {
638  printf("read-mismatch: actual %d, expecting %d, at %"PRId64"\n",
639  (int)buf[i], (int)(pos & 0xFF), pos);
640  break;
641  }
642  pos++;
643  }
644  }
645 
646  read_len += ret;
647  }
648  printf("read: %"PRId64"\n", read_len);
649 
650  /*
651  * test normal seek
652  */
653  ret = ffurl_read(h, buf, 1);
654  printf("read: %d\n", ret);
655 
656  pos = ffurl_seek(h, TEST_SEEK_POS, SEEK_SET);
657  printf("seek: %"PRId64"\n", pos);
658 
659  read_len = 0;
660  while (1) {
661  ret = ffurl_read(h, buf, sizeof(buf));
662  if (ret == AVERROR_EOF)
663  break;
664  else if (ret == 0)
665  break;
666  else if (ret < 0) {
667  printf("read-error: %d at %"PRId64"\n", ret, ffurl_seek(h, 0, SEEK_CUR));
668  goto fail;
669  } else {
670  for (i = 0; i < ret; ++i) {
671  if (buf[i] != (pos & 0xFF)) {
672  printf("read-mismatch: actual %d, expecting %d, at %"PRId64"\n",
673  (int)buf[i], (int)(pos & 0xFF), pos);
674  break;
675  }
676  pos++;
677  }
678  }
679 
680  read_len += ret;
681  }
682  printf("read: %"PRId64"\n", read_len);
683 
684  ret = ffurl_read(h, buf, 1);
685  printf("read: %d\n", ret);
686 
687  /*
688  * test read error
689  */
690  ffurl_close(h);
691  av_dict_set_int(&opts, "async-test-read-error", -10000, 0);
692  ret = ffurl_open_whitelist(&h, "async:async-test:", AVIO_FLAG_READ,
693  NULL, &opts, NULL, NULL, NULL);
694  printf("open: %d\n", ret);
695 
696  ret = ffurl_read(h, buf, 1);
697  printf("read: %d\n", ret);
698 
699 fail:
700  av_dict_free(&opts);
701  ffurl_close(h);
702  return 0;
703 }
704 
705 #endif
static int async_check_interrupt(void *arg)
Definition: async.c:150
static int wrapped_url_read(void *src, void *dst, int size)
Definition: async.c:164
static void * async_buffer_task(void *arg)
Definition: async.c:176
static const AVClass async_context_class
Definition: async.c:479
static int ring_drain(RingBuffer *ring, int offset)
Definition: async.c:142
static const AVOption options[]
Definition: async.c:472
static int async_read(URLContext *h, unsigned char *buf, int size)
Definition: async.c:377
static int ring_space(RingBuffer *ring)
Definition: async.c:110
const URLProtocol ff_async_protocol
Definition: async.c:486
#define READ_BACK_CAPACITY
Definition: async.c:45
#define BUFFER_CAPACITY
@TODO support timeout support work with concatdec, hls
Definition: async.c:44
static void ring_reset(RingBuffer *ring)
Definition: async.c:99
static int async_open(URLContext *h, const char *arg, int flags, AVDictionary **options)
Definition: async.c:240
static int async_close(URLContext *h)
Definition: async.c:307
static void ring_destroy(RingBuffer *ring)
Definition: async.c:94
#define SHORT_SEEK_THRESHOLD
Definition: async.c:46
static int ring_init(RingBuffer *ring, unsigned int capacity, int read_back_capacity)
Definition: async.c:83
static int ring_size_of_read_back(RingBuffer *ring)
Definition: async.c:137
static int ring_size(RingBuffer *ring)
Definition: async.c:105
#define OFFSET(x)
Definition: async.c:469
static int ring_generic_write(RingBuffer *ring, void *src, int size, int(*func)(void *, void *, int))
Definition: async.c:131
static void fifo_do_not_copy_func(void *dest, void *src, int size)
Definition: async.c:382
static int ring_generic_read(RingBuffer *ring, void *dest, int buf_size, void(*func)(void *, void *, int))
Definition: async.c:115
static int64_t async_seek(URLContext *h, int64_t pos, int whence)
Definition: async.c:386
static int async_read_internal(URLContext *h, void *dest, int size, int read_complete, void(*func)(void *, void *, int))
Definition: async.c:330
#define D
Definition: async.c:470
uint8_t
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
Definition: avassert.h:64
int ffurl_read(URLContext *h, unsigned char *buf, int size)
Read up to size bytes from the resource accessed by h, and store the read bytes in buf.
Definition: avio.c:404
int ff_check_interrupt(AVIOInterruptCB *cb)
Check if the user has requested to interrupt a blocking function associated with cb.
Definition: avio.c:661
int ffurl_open_whitelist(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options, const char *whitelist, const char *blacklist, URLContext *parent)
Create an URLContext for accessing to the resource indicated by url, and open it.
Definition: avio.c:309
int64_t ffurl_seek(URLContext *h, int64_t pos, int whence)
Change the position that will be used by the next read/write operation on the resource accessed by h.
Definition: avio.c:431
int64_t ffurl_size(URLContext *h)
Return the filesize of the resource accessed by h, AVERROR(ENOSYS) if the operation is not supported ...
Definition: avio.c:608
int ffurl_closep(URLContext **hh)
Close the resource accessed by the URLContext h, and free the memory used by it.
Definition: avio.c:441
int ffurl_close(URLContext *h)
Definition: avio.c:464
#define AVIO_FLAG_READ
read-only
Definition: avio.h:674
#define AVSEEK_SIZE
ORing this as the "whence" parameter to a seek function causes it to return the filesize without seek...
Definition: avio.h:531
int main(int argc, char *argv[])
#define flags(name, subs,...)
Definition: cbs_av1.c:572
#define fail()
Definition: checkasm.h:133
#define FFMIN(a, b)
Definition: common.h:105
#define NULL
Definition: coverity.c:32
long long int64_t
Definition: coverity.c:34
error code definitions
int
#define pthread_mutex_lock(a)
Definition: ffprobe.c:63
#define pthread_mutex_unlock(a)
Definition: ffprobe.c:67
a very simple circular buffer FIFO implementation
@ AV_OPT_TYPE_INT
Definition: opt.h:225
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition: dict.c:203
int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags)
Convenience wrapper for av_dict_set that converts the value to a string and stores it.
Definition: dict.c:147
#define AVERROR_EXIT
Immediate exit was requested; the called function should not be restarted.
Definition: error.h:56
#define AVERROR_EOF
End of file.
Definition: error.h:55
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition: error.h:119
#define AVERROR(e)
Definition: error.h:43
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition: log.h:220
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:235
int av_strstart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str.
Definition: avstring.c:34
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
int i
Definition: input.c:407
int(* func)(AVBPrint *dst, const char *in, const char *arg)
Definition: jacosubdec.c:67
const char * arg
Definition: jacosubdec.c:66
void av_fifo_drain(AVFifoBuffer *f, int size)
Discard data from the FIFO.
Definition: fifo.c:233
void av_fifo_reset(AVFifoBuffer *f)
Reset the AVFifoBuffer to the state right after av_fifo_alloc, in particular it is emptied.
Definition: fifo.c:71
void av_fifo_freep(AVFifoBuffer **f)
Free an AVFifoBuffer and reset pointer to NULL.
Definition: fifo.c:63
int av_fifo_size(const AVFifoBuffer *f)
Return the amount of data in bytes in the AVFifoBuffer, that is the amount of data you can read from ...
Definition: fifo.c:77
int av_fifo_space(const AVFifoBuffer *f)
Return the amount of space in bytes in the AVFifoBuffer, that is the amount of data you can write int...
Definition: fifo.c:82
AVFifoBuffer * av_fifo_alloc(unsigned int size)
Initialize an AVFifoBuffer.
Definition: fifo.c:43
int av_fifo_generic_peek_at(AVFifoBuffer *f, void *dest, int offset, int buf_size, void(*func)(void *, void *, int))
Feed data at specific position from an AVFifoBuffer to a user-supplied callback.
Definition: fifo.c:151
int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size, int(*func)(void *, void *, int))
Feed data from a user-supplied callback to an AVFifoBuffer.
Definition: fifo.c:122
AVOptions.
static av_always_inline int pthread_cond_signal(pthread_cond_t *cond)
Definition: os2threads.h:152
static av_always_inline int pthread_cond_destroy(pthread_cond_t *cond)
Definition: os2threads.h:144
static av_always_inline int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
Definition: os2threads.h:104
static av_always_inline int pthread_join(pthread_t thread, void **value_ptr)
Definition: os2threads.h:94
static av_always_inline int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
Definition: os2threads.h:133
static av_always_inline int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg)
Definition: os2threads.h:80
_fmutex pthread_mutex_t
Definition: os2threads.h:53
static av_always_inline int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
Definition: os2threads.h:192
static av_always_inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
Definition: os2threads.h:112
unsigned int pos
Definition: spdifenc.c:412
Describe the class of an AVClass context structure.
Definition: log.h:67
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:72
Callback for checking whether to abort blocking functions.
Definition: avio.h:58
int(* callback)(void *)
Definition: avio.h:59
AVOption.
Definition: opt.h:248
Definition: async.c:56
int64_t seek_ret
Definition: async.c:64
AVIOInterruptCB interrupt_callback
Definition: async.c:80
pthread_mutex_t mutex
Definition: async.c:76
URLContext * inner
Definition: async.c:58
int io_error
Definition: async.c:67
RingBuffer ring
Definition: async.c:72
int64_t seek_pos
Definition: async.c:61
int seek_completed
Definition: async.c:63
pthread_t async_buffer_thread
Definition: async.c:77
int seek_whence
Definition: async.c:62
int seek_request
Definition: async.c:60
int64_t logical_pos
Definition: async.c:70
int64_t logical_size
Definition: async.c:71
int inner_io_error
Definition: async.c:66
pthread_cond_t cond_wakeup_background
Definition: async.c:75
int io_eof_reached
Definition: async.c:68
int abort_request
Definition: async.c:79
pthread_cond_t cond_wakeup_main
Definition: async.c:74
int read_pos
Definition: async.c:53
int read_back_capacity
Definition: async.c:51
AVFifoBuffer * fifo
Definition: async.c:50
Definition: url.h:38
const char * name
Definition: url.h:55
#define av_log(a,...)
#define src
Definition: vp8dsp.c:255
AVDictionary * opts
Definition: movenc.c:50
int size
unbuffered private I/O API
static const uint8_t offset[127][2]
Definition: vf_spp.c:107
static double c[64]