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  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
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:307
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:431
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:472
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:248
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:464
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:133
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:661
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:479
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:220
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
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_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:309
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:255
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:67
error.h
Context::ring
RingBuffer ring
Definition: async.c:72
D
#define D
Definition: async.c:470
fifo_do_not_copy_func
static void fifo_do_not_copy_func(void *dest, void *src, int size)
Definition: async.c:382
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:10344
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:469
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:105
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:377
av_assert2
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
Definition: avassert.h:64
i
int i
Definition: input.c:407
URLContext
Definition: url.h:38
log.h
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:330
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:441
ret
ret
Definition: filter_design.txt:187
async_seek
static int64_t async_seek(URLContext *h, int64_t pos, int whence)
Definition: async.c:386
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:486
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:404
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:225
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:561
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:608
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:170
pthread_mutex_lock
#define pthread_mutex_lock(a)
Definition: ffprobe.c:63