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  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 
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 
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 
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:
295 cond_wakeup_background_fail:
297 cond_wakeup_main_fail:
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 
313  c->abort_request = 1;
316 
318  if (ret != 0)
319  av_log(h, AV_LOG_ERROR, "pthread_join(): %s\n", av_err2str(ret));
320 
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 
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  }
369  }
370 
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 
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  }
462  }
463 
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(&h, "async:async-test:", AVIO_FLAG_READ, NULL, NULL);
616  printf("open: %d\n", ret);
617 
618  size = ffurl_size(h);
619  printf("size: %"PRId64"\n", size);
620 
621  pos = ffurl_seek(h, 0, SEEK_CUR);
622  read_len = 0;
623  while (1) {
624  ret = ffurl_read(h, buf, sizeof(buf));
625  if (ret == AVERROR_EOF) {
626  printf("read-error: AVERROR_EOF at %"PRId64"\n", ffurl_seek(h, 0, SEEK_CUR));
627  break;
628  }
629  else if (ret == 0)
630  break;
631  else if (ret < 0) {
632  printf("read-error: %d at %"PRId64"\n", ret, ffurl_seek(h, 0, SEEK_CUR));
633  goto fail;
634  } else {
635  for (i = 0; i < ret; ++i) {
636  if (buf[i] != (pos & 0xFF)) {
637  printf("read-mismatch: actual %d, expecting %d, at %"PRId64"\n",
638  (int)buf[i], (int)(pos & 0xFF), pos);
639  break;
640  }
641  pos++;
642  }
643  }
644 
645  read_len += ret;
646  }
647  printf("read: %"PRId64"\n", read_len);
648 
649  /*
650  * test normal seek
651  */
652  ret = ffurl_read(h, buf, 1);
653  printf("read: %d\n", ret);
654 
655  pos = ffurl_seek(h, TEST_SEEK_POS, SEEK_SET);
656  printf("seek: %"PRId64"\n", pos);
657 
658  read_len = 0;
659  while (1) {
660  ret = ffurl_read(h, buf, sizeof(buf));
661  if (ret == AVERROR_EOF)
662  break;
663  else if (ret == 0)
664  break;
665  else if (ret < 0) {
666  printf("read-error: %d at %"PRId64"\n", ret, ffurl_seek(h, 0, SEEK_CUR));
667  goto fail;
668  } else {
669  for (i = 0; i < ret; ++i) {
670  if (buf[i] != (pos & 0xFF)) {
671  printf("read-mismatch: actual %d, expecting %d, at %"PRId64"\n",
672  (int)buf[i], (int)(pos & 0xFF), pos);
673  break;
674  }
675  pos++;
676  }
677  }
678 
679  read_len += ret;
680  }
681  printf("read: %"PRId64"\n", read_len);
682 
683  ret = ffurl_read(h, buf, 1);
684  printf("read: %d\n", ret);
685 
686  /*
687  * test read error
688  */
689  ffurl_close(h);
690  av_dict_set_int(&opts, "async-test-read-error", -10000, 0);
691  ret = ffurl_open(&h, "async:async-test:", AVIO_FLAG_READ, NULL, &opts);
692  printf("open: %d\n", ret);
693 
694  ret = ffurl_read(h, buf, 1);
695  printf("read: %d\n", ret);
696 
697 fail:
698  av_dict_free(&opts);
699  ffurl_close(h);
700  return 0;
701 }
702 
703 #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:112
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:310
int io_error
Definition: async.c:67
#define pthread_mutex_lock(a)
Definition: ffprobe.c:63
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:192
AVOption.
Definition: opt.h:248
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:330
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:235
AVFifoBuffer * fifo
Definition: async.c:50
pthread_mutex_t mutex
Definition: async.c:76
static const AVClass async_context_class
Definition: async.c:479
static int ring_size(RingBuffer *ring)
Definition: async.c:105
#define D
Definition: async.c:470
static av_always_inline int pthread_cond_destroy(pthread_cond_t *cond)
Definition: os2threads.h:144
static int ring_space(RingBuffer *ring)
Definition: async.c:110
static const AVOption options[]
Definition: async.c:472
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:486
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition: log.h:220
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:152
ptrdiff_t size
Definition: opengl_enc.c:100
#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
#define src
Definition: vp8dsp.c:255
static int64_t async_seek(URLContext *h, int64_t pos, int whence)
Definition: async.c:386
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
error code definitions
int64_t logical_pos
Definition: async.c:70
const char * protocol_whitelist
Definition: url.h:49
unsigned int pos
Definition: spdifenc.c:410
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:382
#define fail()
Definition: checkasm.h:123
static int async_open(URLContext *h, const char *arg, int flags, AVDictionary **options)
Definition: async.c:240
#define OFFSET(x)
Definition: async.c:469
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:94
static av_always_inline int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
Definition: os2threads.h:104
int main(int argc, char *argv[])
int seek_whence
Definition: async.c:62
#define pthread_mutex_unlock(a)
Definition: ffprobe.c:67
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
int ffurl_closep(URLContext **hh)
Close the resource accessed by the URLContext h, and free the memory used by it.
Definition: avio.c:446
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
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:666
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:613
a very simple circular buffer FIFO implementation
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:469
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:53
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:436
int ffurl_open(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options)
Definition: avio.c:357
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:133
#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:307
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:377
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:409
int i
Definition: input.c:407
pthread_cond_t cond_wakeup_background
Definition: async.c:75