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 
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  av_log(h, AV_LOG_ERROR, "pthread_mutex_init failed : %s\n", av_err2str(ret));
266  goto mutex_fail;
267  }
268 
269  ret = pthread_cond_init(&c->cond_wakeup_main, NULL);
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 
275  ret = pthread_cond_init(&c->cond_wakeup_background, NULL);
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 
281  ret = pthread_create(&c->async_buffer_thread, NULL, async_buffer_task, h);
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:
290  pthread_cond_destroy(&c->cond_wakeup_background);
291 cond_wakeup_background_fail:
292  pthread_cond_destroy(&c->cond_wakeup_main);
293 cond_wakeup_main_fail:
294  pthread_mutex_destroy(&c->mutex);
295 mutex_fail:
296  ffurl_closep(&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 
308  pthread_mutex_lock(&c->mutex);
309  c->abort_request = 1;
310  pthread_cond_signal(&c->cond_wakeup_background);
311  pthread_mutex_unlock(&c->mutex);
312 
313  ret = pthread_join(c->async_buffer_thread, NULL);
314  if (ret != 0)
315  av_log(h, AV_LOG_ERROR, "pthread_join(): %s\n", av_err2str(ret));
316 
317  pthread_cond_destroy(&c->cond_wakeup_background);
318  pthread_cond_destroy(&c->cond_wakeup_main);
319  pthread_mutex_destroy(&c->mutex);
320  ffurl_closep(&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 
334  pthread_mutex_lock(&c->mutex);
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  }
363  pthread_cond_signal(&c->cond_wakeup_background);
364  pthread_cond_wait(&c->cond_wakeup_main, &c->mutex);
365  }
366 
367  pthread_cond_signal(&c->cond_wakeup_background);
368  pthread_mutex_unlock(&c->mutex);
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 
437  pthread_mutex_lock(&c->mutex);
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  }
456  pthread_cond_signal(&c->cond_wakeup_background);
457  pthread_cond_wait(&c->cond_wakeup_main, &c->mutex);
458  }
459 
460  pthread_mutex_unlock(&c->mutex);
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
func
int(* func)(AVBPrint *dst, const char *in, const char *arg)
Definition: jacosubdec.c:67
pthread_mutex_t
_fmutex pthread_mutex_t
Definition: os2threads.h:53
RingBuffer
Definition: async.c:48
pthread_join
static av_always_inline int pthread_join(pthread_t thread, void **value_ptr)
Definition: os2threads.h:94
async_close
static int async_close(URLContext *h)
Definition: async.c:303
AVERROR
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
opt.h
ring_space
static int ring_space(RingBuffer *ring)
Definition: async.c:110
Context::mutex
pthread_mutex_t mutex
Definition: async.c:76
av_fifo_generic_write
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
ffurl_seek
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
thread.h
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:55
pthread_mutex_init
static av_always_inline int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
Definition: os2threads.h:104
async_buffer_task
static void * async_buffer_task(void *arg)
Definition: async.c:176
options
static const AVOption options[]
Definition: async.c:468
Context::abort_request
int abort_request
Definition: async.c:79
Context::io_error
int io_error
Definition: async.c:67
AVOption
AVOption.
Definition: opt.h:246
AVSEEK_SIZE
#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
Context::seek_pos
int64_t seek_pos
Definition: async.c:61
ffurl_close
int ffurl_close(URLContext *h)
Definition: avio.c:469
AVDictionary
Definition: dict.c:30
av_fifo_reset
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
ring_size
static int ring_size(RingBuffer *ring)
Definition: async.c:105
URLProtocol
Definition: url.h:54
av_fifo_drain
void av_fifo_drain(AVFifoBuffer *f, int size)
Discard data from the FIFO.
Definition: fifo.c:233
ring_generic_write
static int ring_generic_write(RingBuffer *ring, void *src, int size, int(*func)(void *, void *, int))
Definition: async.c:131
Context::async_buffer_thread
pthread_t async_buffer_thread
Definition: async.c:77
AVIOInterruptCB
Callback for checking whether to abort blocking functions.
Definition: avio.h:58
Context::cond_wakeup_background
pthread_cond_t cond_wakeup_background
Definition: async.c:75
AVFifoBuffer
Definition: fifo.h:31
Context::logical_size
int64_t logical_size
Definition: async.c:71
Context
Definition: async.c:56
fifo.h
Context::cond_wakeup_main
pthread_cond_t cond_wakeup_main
Definition: async.c:74
fail
#define fail()
Definition: checkasm.h:123
RingBuffer::read_pos
int read_pos
Definition: async.c:53
RingBuffer::fifo
AVFifoBuffer * fifo
Definition: async.c:50
Context::seek_whence
int seek_whence
Definition: async.c:62
ff_check_interrupt
int ff_check_interrupt(AVIOInterruptCB *cb)
Check if the user has requested to interrupt a blocking function associated with cb.
Definition: avio.c:666
Context::seek_request
int seek_request
Definition: async.c:60
BUFFER_CAPACITY
#define BUFFER_CAPACITY
@TODO support timeout support work with concatdec, hls
Definition: async.c:44
async_context_class
static const AVClass async_context_class
Definition: async.c:475
Context::seek_completed
int seek_completed
Definition: async.c:63
READ_BACK_CAPACITY
#define READ_BACK_CAPACITY
Definition: async.c:45
async_check_interrupt
static int async_check_interrupt(void *arg)
Definition: async.c:150
avassert.h
AV_LOG_TRACE
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition: log.h:202
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
av_fifo_space
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
ffurl_open
int ffurl_open(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options)
Definition: avio.c:357
ffurl_open_whitelist
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
ring_destroy
static void ring_destroy(RingBuffer *ring)
Definition: async.c:94
Context::io_eof_reached
int io_eof_reached
Definition: async.c:68
ring_init
static int ring_init(RingBuffer *ring, unsigned int capacity, int read_back_capacity)
Definition: async.c:83
SHORT_SEEK_THRESHOLD
#define SHORT_SEEK_THRESHOLD
Definition: async.c:46
arg
const char * arg
Definition: jacosubdec.c:66
pthread_create
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
opts
AVDictionary * opts
Definition: movenc.c:50
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
main
int main(int argc, char *argv[])
Definition: avio_list_dir.c:112
TestContext
Definition: opt.c:31
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:67
NULL
#define NULL
Definition: coverity.c:32
Context::interrupt_callback
AVIOInterruptCB interrupt_callback
Definition: async.c:80
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:235
src
#define src
Definition: vp8dsp.c:254
c
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
pthread_mutex_unlock
#define pthread_mutex_unlock(a)
Definition: ffprobe.c:66
error.h
Context::ring
RingBuffer ring
Definition: async.c:72
D
#define D
Definition: async.c:466
fifo_do_not_copy_func
static void fifo_do_not_copy_func(void *dest, void *src, int size)
Definition: async.c:378
av_err2str
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition: error.h:119
size
int size
Definition: twinvq_data.h:11134
URLProtocol::name
const char * name
Definition: url.h:55
async_open
static int async_open(URLContext *h, const char *arg, int flags, AVDictionary **options)
Definition: async.c:240
OFFSET
#define OFFSET(x)
Definition: async.c:465
printf
printf("static const uint8_t my_array[100] = {\n")
Context::inner_io_error
int inner_io_error
Definition: async.c:66
FFMIN
#define FFMIN(a, b)
Definition: common.h:96
offset
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
Definition: writing_filters.txt:86
av_dict_free
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition: dict.c:203
av_strstart
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
pthread_t
Definition: os2threads.h:44
pthread_cond_destroy
static av_always_inline int pthread_cond_destroy(pthread_cond_t *cond)
Definition: os2threads.h:144
pthread_mutex_destroy
static av_always_inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
Definition: os2threads.h:112
async_read
static int async_read(URLContext *h, unsigned char *buf, int size)
Definition: async.c:373
av_assert2
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
Definition: avassert.h:64
URLContext
Definition: url.h:38
log.h
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
Context::seek_ret
int64_t seek_ret
Definition: async.c:64
url.h
uint8_t
uint8_t
Definition: audio_convert.c:194
pthread_cond_t
Definition: os2threads.h:58
wrapped_url_read
static int wrapped_url_read(void *src, void *dst, int size)
Definition: async.c:164
RingBuffer::read_back_capacity
int read_back_capacity
Definition: async.c:51
Context::inner
URLContext * inner
Definition: async.c:58
async_read_internal
static int async_read_internal(URLContext *h, void *dest, int size, int read_complete, void(*func)(void *, void *, int))
Definition: async.c:326
ffurl_closep
int ffurl_closep(URLContext **hh)
Close the resource accessed by the URLContext h, and free the memory used by it.
Definition: avio.c:446
ret
ret
Definition: filter_design.txt:187
async_seek
static int64_t async_seek(URLContext *h, int64_t pos, int whence)
Definition: async.c:382
AVClass::class_name
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
pos
unsigned int pos
Definition: spdifenc.c:412
ff_async_protocol
const URLProtocol ff_async_protocol
Definition: async.c:482
pthread_cond_signal
static av_always_inline int pthread_cond_signal(pthread_cond_t *cond)
Definition: os2threads.h:152
Context::logical_pos
int64_t logical_pos
Definition: async.c:70
ffurl_read
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
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:223
pthread_cond_wait
static av_always_inline int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
Definition: os2threads.h:192
av_dict_set_int
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
AVIO_FLAG_READ
#define AVIO_FLAG_READ
read-only
Definition: avio.h:674
ring_generic_read
static int ring_generic_read(RingBuffer *ring, void *dest, int buf_size, void(*func)(void *, void *, int))
Definition: async.c:115
av_fifo_size
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
av_fifo_generic_peek_at
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
ring_reset
static void ring_reset(RingBuffer *ring)
Definition: async.c:99
AVIOInterruptCB::callback
int(* callback)(void *)
Definition: avio.h:59
ring_size_of_read_back
static int ring_size_of_read_back(RingBuffer *ring)
Definition: async.c:137
av_fifo_freep
void av_fifo_freep(AVFifoBuffer **f)
Free an AVFifoBuffer and reset pointer to NULL.
Definition: fifo.c:63
av_fifo_alloc
AVFifoBuffer * av_fifo_alloc(unsigned int size)
Initialize an AVFifoBuffer.
Definition: fifo.c:43
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:565
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
ffurl_size
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
pthread_cond_init
static av_always_inline int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
Definition: os2threads.h:133
h
h
Definition: vp9dsp_template.c:2038
AVERROR_EXIT
#define AVERROR_EXIT
Immediate exit was requested; the called function should not be restarted.
Definition: error.h:56
ring_drain
static int ring_drain(RingBuffer *ring, int offset)
Definition: async.c:142
avstring.h
int
int
Definition: ffmpeg_filter.c:192
pthread_mutex_lock
#define pthread_mutex_lock(a)
Definition: ffprobe.c:62