FFmpeg
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 
61  int64_t seek_pos;
64  int64_t seek_ret;
65 
67  int io_error;
69 
70  int64_t logical_pos;
71  int64_t logical_size;
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 
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 {
144  av_assert2(offset >= -ring_size_of_read_back(ring));
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 
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 
188  if (async_check_interrupt(h)) {
189  c->io_eof_reached = 1;
190  c->io_error = AVERROR_EXIT;
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 
211  continue;
212  }
213 
214  fifo_space = ring_space(ring);
215  if (c->io_eof_reached || fifo_space <= 0) {
219  continue;
220  }
222 
223  to_copy = FFMIN(4096, fifo_space);
224  ret = ring_generic_write(ring, (void *)h, to_copy, wrapped_url_read);
225 
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 
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 */
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  av_log(h, AV_LOG_ERROR, "pthread_mutex_init failed : %s\n", av_err2str(ret));
266  goto mutex_fail;
267  }
268 
270  if (ret != 0) {
271  av_log(h, AV_LOG_ERROR, "pthread_cond_init failed : %s\n", av_err2str(ret));
272  goto cond_wakeup_main_fail;
273  }
274 
276  if (ret != 0) {
277  av_log(h, AV_LOG_ERROR, "pthread_cond_init failed : %s\n", av_err2str(ret));
278  goto cond_wakeup_background_fail;
279  }
280 
282  if (ret) {
283  av_log(h, AV_LOG_ERROR, "pthread_create failed : %s\n", av_err2str(ret));
284  goto thread_fail;
285  }
286 
287  return 0;
288 
289 thread_fail:
291 cond_wakeup_background_fail:
293 cond_wakeup_main_fail:
295 mutex_fail:
296  ffurl_close(c->inner);
297 url_fail:
298  ring_destroy(&c->ring);
299 fifo_fail:
300  return ret;
301 }
302 
304 {
305  Context *c = h->priv_data;
306  int ret;
307 
309  c->abort_request = 1;
312 
314  if (ret != 0)
315  av_log(h, AV_LOG_ERROR, "pthread_join(): %s\n", av_err2str(ret));
316 
320  ffurl_close(c->inner);
321  ring_destroy(&c->ring);
322 
323  return 0;
324 }
325 
326 static int async_read_internal(URLContext *h, void *dest, int size, int read_complete,
327  void (*func)(void*, void*, int))
328 {
329  Context *c = h->priv_data;
330  RingBuffer *ring = &c->ring;
331  int to_read = size;
332  int ret = 0;
333 
335 
336  while (to_read > 0) {
337  int fifo_size, to_copy;
338  if (async_check_interrupt(h)) {
339  ret = AVERROR_EXIT;
340  break;
341  }
342  fifo_size = ring_size(ring);
343  to_copy = FFMIN(to_read, fifo_size);
344  if (to_copy > 0) {
345  ring_generic_read(ring, dest, to_copy, func);
346  if (!func)
347  dest = (uint8_t *)dest + to_copy;
348  c->logical_pos += to_copy;
349  to_read -= to_copy;
350  ret = size - to_read;
351 
352  if (to_read <= 0 || !read_complete)
353  break;
354  } else if (c->io_eof_reached) {
355  if (ret <= 0) {
356  if (c->io_error)
357  ret = c->io_error;
358  else
359  ret = AVERROR_EOF;
360  }
361  break;
362  }
365  }
366 
369 
370  return ret;
371 }
372 
373 static int async_read(URLContext *h, unsigned char *buf, int size)
374 {
375  return async_read_internal(h, buf, size, 0, NULL);
376 }
377 
378 static void fifo_do_not_copy_func(void* dest, void* src, int size) {
379  // do not copy
380 }
381 
382 static int64_t async_seek(URLContext *h, int64_t pos, int whence)
383 {
384  Context *c = h->priv_data;
385  RingBuffer *ring = &c->ring;
386  int64_t ret;
387  int64_t new_logical_pos;
388  int fifo_size;
389  int fifo_size_of_read_back;
390 
391  if (whence == AVSEEK_SIZE) {
392  av_log(h, AV_LOG_TRACE, "async_seek: AVSEEK_SIZE: %"PRId64"\n", (int64_t)c->logical_size);
393  return c->logical_size;
394  } else if (whence == SEEK_CUR) {
395  av_log(h, AV_LOG_TRACE, "async_seek: %"PRId64"\n", pos);
396  new_logical_pos = pos + c->logical_pos;
397  } else if (whence == SEEK_SET){
398  av_log(h, AV_LOG_TRACE, "async_seek: %"PRId64"\n", pos);
399  new_logical_pos = pos;
400  } else {
401  return AVERROR(EINVAL);
402  }
403  if (new_logical_pos < 0)
404  return AVERROR(EINVAL);
405 
406  fifo_size = ring_size(ring);
407  fifo_size_of_read_back = ring_size_of_read_back(ring);
408  if (new_logical_pos == c->logical_pos) {
409  /* current position */
410  return c->logical_pos;
411  } else if ((new_logical_pos >= (c->logical_pos - fifo_size_of_read_back)) &&
412  (new_logical_pos < (c->logical_pos + fifo_size + SHORT_SEEK_THRESHOLD))) {
413  int pos_delta = (int)(new_logical_pos - c->logical_pos);
414  /* fast seek */
415  av_log(h, AV_LOG_TRACE, "async_seek: fask_seek %"PRId64" from %d dist:%d/%d\n",
416  new_logical_pos, (int)c->logical_pos,
417  (int)(new_logical_pos - c->logical_pos), fifo_size);
418 
419  if (pos_delta > 0) {
420  // fast seek forwards
422  } else {
423  // fast seek backwards
424  ring_drain(ring, pos_delta);
425  c->logical_pos = new_logical_pos;
426  }
427 
428  return c->logical_pos;
429  } else if (c->logical_size <= 0) {
430  /* can not seek */
431  return AVERROR(EINVAL);
432  } else if (new_logical_pos > c->logical_size) {
433  /* beyond end */
434  return AVERROR(EINVAL);
435  }
436 
438 
439  c->seek_request = 1;
440  c->seek_pos = new_logical_pos;
441  c->seek_whence = SEEK_SET;
442  c->seek_completed = 0;
443  c->seek_ret = 0;
444 
445  while (1) {
446  if (async_check_interrupt(h)) {
447  ret = AVERROR_EXIT;
448  break;
449  }
450  if (c->seek_completed) {
451  if (c->seek_ret >= 0)
452  c->logical_pos = c->seek_ret;
453  ret = c->seek_ret;
454  break;
455  }
458  }
459 
461 
462  return ret;
463 }
464 
465 #define OFFSET(x) offsetof(Context, x)
466 #define D AV_OPT_FLAG_DECODING_PARAM
467 
468 static const AVOption options[] = {
469  {NULL},
470 };
471 
472 #undef D
473 #undef OFFSET
474 
475 static const AVClass async_context_class = {
476  .class_name = "Async",
477  .item_name = av_default_item_name,
478  .option = options,
479  .version = LIBAVUTIL_VERSION_INT,
480 };
481 
483  .name = "async",
484  .url_open2 = async_open,
485  .url_read = async_read,
486  .url_seek = async_seek,
487  .url_close = async_close,
488  .priv_data_size = sizeof(Context),
489  .priv_data_class = &async_context_class,
490 };
491 
492 #if 0
493 
494 #define TEST_SEEK_POS (1536)
495 #define TEST_STREAM_SIZE (2048)
496 
497 typedef struct TestContext {
498  AVClass *class;
499  int64_t logical_pos;
500  int64_t logical_size;
501 
502  /* options */
503  int opt_read_error;
504 } TestContext;
505 
506 static int async_test_open(URLContext *h, const char *arg, int flags, AVDictionary **options)
507 {
508  TestContext *c = h->priv_data;
509  c->logical_pos = 0;
510  c->logical_size = TEST_STREAM_SIZE;
511  return 0;
512 }
513 
514 static int async_test_close(URLContext *h)
515 {
516  return 0;
517 }
518 
519 static int async_test_read(URLContext *h, unsigned char *buf, int size)
520 {
521  TestContext *c = h->priv_data;
522  int i;
523  int read_len = 0;
524 
525  if (c->opt_read_error)
526  return c->opt_read_error;
527 
528  if (c->logical_pos >= c->logical_size)
529  return AVERROR_EOF;
530 
531  for (i = 0; i < size; ++i) {
532  buf[i] = c->logical_pos & 0xFF;
533 
534  c->logical_pos++;
535  read_len++;
536 
537  if (c->logical_pos >= c->logical_size)
538  break;
539  }
540 
541  return read_len;
542 }
543 
544 static int64_t async_test_seek(URLContext *h, int64_t pos, int whence)
545 {
546  TestContext *c = h->priv_data;
547  int64_t new_logical_pos;
548 
549  if (whence == AVSEEK_SIZE) {
550  return c->logical_size;
551  } else if (whence == SEEK_CUR) {
552  new_logical_pos = pos + c->logical_pos;
553  } else if (whence == SEEK_SET){
554  new_logical_pos = pos;
555  } else {
556  return AVERROR(EINVAL);
557  }
558  if (new_logical_pos < 0)
559  return AVERROR(EINVAL);
560 
561  c->logical_pos = new_logical_pos;
562  return new_logical_pos;
563 }
564 
565 #define OFFSET(x) offsetof(TestContext, x)
566 #define D AV_OPT_FLAG_DECODING_PARAM
567 
568 static const AVOption async_test_options[] = {
569  { "async-test-read-error", "cause read fail",
570  OFFSET(opt_read_error), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, .flags = D },
571  {NULL},
572 };
573 
574 #undef D
575 #undef OFFSET
576 
577 static const AVClass async_test_context_class = {
578  .class_name = "Async-Test",
579  .item_name = av_default_item_name,
580  .option = async_test_options,
581  .version = LIBAVUTIL_VERSION_INT,
582 };
583 
584 const URLProtocol ff_async_test_protocol = {
585  .name = "async-test",
586  .url_open2 = async_test_open,
587  .url_read = async_test_read,
588  .url_seek = async_test_seek,
589  .url_close = async_test_close,
590  .priv_data_size = sizeof(TestContext),
591  .priv_data_class = &async_test_context_class,
592 };
593 
594 int main(void)
595 {
596  URLContext *h = NULL;
597  int i;
598  int ret;
599  int64_t size;
600  int64_t pos;
601  int64_t read_len;
602  unsigned char buf[4096];
604 
605  ffurl_register_protocol(&ff_async_protocol);
606  ffurl_register_protocol(&ff_async_test_protocol);
607 
608  /*
609  * test normal read
610  */
611  ret = ffurl_open(&h, "async:async-test:", AVIO_FLAG_READ, NULL, NULL);
612  printf("open: %d\n", ret);
613 
614  size = ffurl_size(h);
615  printf("size: %"PRId64"\n", size);
616 
617  pos = ffurl_seek(h, 0, SEEK_CUR);
618  read_len = 0;
619  while (1) {
620  ret = ffurl_read(h, buf, sizeof(buf));
621  if (ret == AVERROR_EOF) {
622  printf("read-error: AVERROR_EOF at %"PRId64"\n", ffurl_seek(h, 0, SEEK_CUR));
623  break;
624  }
625  else if (ret == 0)
626  break;
627  else if (ret < 0) {
628  printf("read-error: %d at %"PRId64"\n", ret, ffurl_seek(h, 0, SEEK_CUR));
629  goto fail;
630  } else {
631  for (i = 0; i < ret; ++i) {
632  if (buf[i] != (pos & 0xFF)) {
633  printf("read-mismatch: actual %d, expecting %d, at %"PRId64"\n",
634  (int)buf[i], (int)(pos & 0xFF), pos);
635  break;
636  }
637  pos++;
638  }
639  }
640 
641  read_len += ret;
642  }
643  printf("read: %"PRId64"\n", read_len);
644 
645  /*
646  * test normal seek
647  */
648  ret = ffurl_read(h, buf, 1);
649  printf("read: %d\n", ret);
650 
651  pos = ffurl_seek(h, TEST_SEEK_POS, SEEK_SET);
652  printf("seek: %"PRId64"\n", pos);
653 
654  read_len = 0;
655  while (1) {
656  ret = ffurl_read(h, buf, sizeof(buf));
657  if (ret == AVERROR_EOF)
658  break;
659  else if (ret == 0)
660  break;
661  else if (ret < 0) {
662  printf("read-error: %d at %"PRId64"\n", ret, ffurl_seek(h, 0, SEEK_CUR));
663  goto fail;
664  } else {
665  for (i = 0; i < ret; ++i) {
666  if (buf[i] != (pos & 0xFF)) {
667  printf("read-mismatch: actual %d, expecting %d, at %"PRId64"\n",
668  (int)buf[i], (int)(pos & 0xFF), pos);
669  break;
670  }
671  pos++;
672  }
673  }
674 
675  read_len += ret;
676  }
677  printf("read: %"PRId64"\n", read_len);
678 
679  ret = ffurl_read(h, buf, 1);
680  printf("read: %d\n", ret);
681 
682  /*
683  * test read error
684  */
685  ffurl_close(h);
686  av_dict_set_int(&opts, "async-test-read-error", -10000, 0);
687  ret = ffurl_open(&h, "async:async-test:", AVIO_FLAG_READ, NULL, &opts);
688  printf("open: %d\n", ret);
689 
690  ret = ffurl_read(h, buf, 1);
691  printf("read: %d\n", ret);
692 
693 fail:
694  av_dict_free(&opts);
695  ffurl_close(h);
696  return 0;
697 }
698 
699 #endif
Definition: async.c:56
static int wrapped_url_read(void *src, void *dst, int size)
Definition: async.c:164
#define NULL
Definition: coverity.c:32
#define READ_BACK_CAPACITY
Definition: async.c:45
static av_always_inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
Definition: os2threads.h:108
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:307
int io_error
Definition: async.c:67
#define pthread_mutex_lock(a)
Definition: ffprobe.c:61
int inner_io_error
Definition: async.c:66
static int async_check_interrupt(void *arg)
Definition: async.c:150
static av_always_inline int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
Definition: os2threads.h:166
AVOption.
Definition: opt.h:246
int read_pos
Definition: async.c:53
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
static int async_read_internal(URLContext *h, void *dest, int size, int read_complete, void(*func)(void *, void *, int))
Definition: async.c:326
int is_streamed
true if streamed (no seek possible), default = false
Definition: url.h:45
AVIOInterruptCB interrupt_callback
Definition: url.h:47
#define AVIO_FLAG_READ
read-only
Definition: avio.h:674
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:191
AVFifoBuffer * fifo
Definition: async.c:50
pthread_mutex_t mutex
Definition: async.c:76
static const AVClass async_context_class
Definition: async.c:475
static int ring_size(RingBuffer *ring)
Definition: async.c:105
#define src
Definition: vp8dsp.c:254
#define D
Definition: async.c:466
static av_always_inline int pthread_cond_destroy(pthread_cond_t *cond)
Definition: os2threads.h:140
static int ring_space(RingBuffer *ring)
Definition: async.c:110
static const AVOption options[]
Definition: async.c:468
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
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
static int ring_drain(RingBuffer *ring, int offset)
Definition: async.c:142
static int ring_generic_write(RingBuffer *ring, void *src, int size, int(*func)(void *, void *, int))
Definition: async.c:131
uint8_t
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
Definition: avassert.h:64
AVOptions.
const URLProtocol ff_async_protocol
Definition: async.c:482
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition: log.h:202
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
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
#define SHORT_SEEK_THRESHOLD
Definition: async.c:46
static int ring_generic_read(RingBuffer *ring, void *dest, int buf_size, void(*func)(void *, void *, int))
Definition: async.c:115
#define AVERROR_EOF
End of file.
Definition: error.h:55
static av_always_inline int pthread_cond_signal(pthread_cond_t *cond)
Definition: os2threads.h:148
ptrdiff_t size
Definition: opengl_enc.c:100
int main(int argc, char *argv[])
Definition: avio_dir_cmd.c:134
#define av_log(a,...)
int(* callback)(void *)
Definition: avio.h:59
static void * async_buffer_task(void *arg)
Definition: async.c:176
Callback for checking whether to abort blocking functions.
Definition: avio.h:58
static int64_t async_seek(URLContext *h, int64_t pos, int whence)
Definition: async.c:382
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
error code definitions
int64_t logical_pos
Definition: async.c:70
const char * protocol_whitelist
Definition: url.h:49
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values. ...
Definition: dict.c:203
const char * arg
Definition: jacosubdec.c:66
simple assert() macros that are a bit more flexible than ISO C assert().
URLContext * inner
Definition: async.c:58
static void fifo_do_not_copy_func(void *dest, void *src, int size)
Definition: async.c:378
#define fail()
Definition: checkasm.h:121
static int async_open(URLContext *h, const char *arg, int flags, AVDictionary **options)
Definition: async.c:240
#define OFFSET(x)
Definition: async.c:465
AVDictionary * opts
Definition: movenc.c:50
#define FFMIN(a, b)
Definition: common.h:96
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition: error.h:119
AVIOInterruptCB interrupt_callback
Definition: async.c:80
static av_always_inline int pthread_join(pthread_t thread, void **value_ptr)
Definition: os2threads.h:90
static av_always_inline int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
Definition: os2threads.h:100
int seek_whence
Definition: async.c:62
#define pthread_mutex_unlock(a)
Definition: ffprobe.c:65
int abort_request
Definition: async.c:79
#define AVERROR_EXIT
Immediate exit was requested; the called function should not be restarted.
Definition: error.h:56
int seek_request
Definition: async.c:60
static av_always_inline int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg)
Definition: os2threads.h:76
const char * protocol_blacklist
Definition: url.h:50
int ff_check_interrupt(AVIOInterruptCB *cb)
Check if the user has requested to interrupt a blocking function associated with cb.
Definition: avio.c:664
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_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
pthread_t async_buffer_thread
Definition: async.c:77
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:611
a very simple circular buffer FIFO implementation
void * buf
Definition: avisynth_c.h:766
Definition: url.h:38
int64_t seek_pos
Definition: async.c:61
int seek_completed
Definition: async.c:63
int(* func)(AVBPrint *dst, const char *in, const char *arg)
Definition: jacosubdec.c:67
Describe the class of an AVClass context structure.
Definition: log.h:67
int64_t logical_size
Definition: async.c:71
void * priv_data
Definition: url.h:41
static void ring_destroy(RingBuffer *ring)
Definition: async.c:94
static int ring_size_of_read_back(RingBuffer *ring)
Definition: async.c:137
RingBuffer ring
Definition: async.c:72
const char * name
Definition: url.h:55
static int ring_init(RingBuffer *ring, unsigned int capacity, int read_back_capacity)
Definition: async.c:83
#define flags(name, subs,...)
Definition: cbs_av1.c:561
int ffurl_close(URLContext *h)
Definition: avio.c:467
static void ring_reset(RingBuffer *ring)
Definition: async.c:99
int read_back_capacity
Definition: async.c:51
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
int
_fmutex pthread_mutex_t
Definition: os2threads.h:49
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:434
int ffurl_open(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options)
Definition: avio.c:355
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
static av_always_inline int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
Definition: os2threads.h:129
#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
pthread_cond_t cond_wakeup_main
Definition: async.c:74
int64_t seek_ret
Definition: async.c:64
AVFifoBuffer * av_fifo_alloc(unsigned int size)
Initialize an AVFifoBuffer.
Definition: fifo.c:43
static int async_close(URLContext *h)
Definition: async.c:303
printf("static const uint8_t my_array[100] = {\n")
#define BUFFER_CAPACITY
support timeout support work with concatdec, hls
Definition: async.c:44
int io_eof_reached
Definition: async.c:68
unbuffered private I/O API
void av_fifo_freep(AVFifoBuffer **f)
Free an AVFifoBuffer and reset pointer to NULL.
Definition: fifo.c:63
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
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Frame references ownership and permissions
void av_fifo_drain(AVFifoBuffer *f, int size)
Discard data from the FIFO.
Definition: fifo.c:233
static int async_read(URLContext *h, unsigned char *buf, int size)
Definition: async.c:373
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:407
pthread_cond_t cond_wakeup_background
Definition: async.c:75