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_alloc2(capacity + read_back_capacity, 1, 0);
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_freep2(&ring->fifo);
97 }
98 
99 static void ring_reset(RingBuffer *ring)
100 {
101  av_fifo_reset2(ring->fifo);
102  ring->read_pos = 0;
103 }
104 
105 static int ring_size(RingBuffer *ring)
106 {
107  return av_fifo_can_read(ring->fifo) - ring->read_pos;
108 }
109 
110 static int ring_space(RingBuffer *ring)
111 {
112  return av_fifo_can_write(ring->fifo);
113 }
114 
115 static int ring_read(RingBuffer *ring, void *dest, int buf_size)
116 {
117  int ret = 0;
118 
119  av_assert2(buf_size <= ring_size(ring));
120  if (dest)
121  ret = av_fifo_peek(ring->fifo, dest, buf_size, ring->read_pos);
122  ring->read_pos += buf_size;
123 
124  if (ring->read_pos > ring->read_back_capacity) {
125  av_fifo_drain2(ring->fifo, ring->read_pos - ring->read_back_capacity);
126  ring->read_pos = ring->read_back_capacity;
127  }
128 
129  return ret;
130 }
131 
132 static int wrapped_url_read(void *src, void *dst, size_t *size)
133 {
134  URLContext *h = src;
135  Context *c = h->priv_data;
136  int ret;
137 
138  ret = ffurl_read(c->inner, dst, *size);
139  *size = ret > 0 ? ret : 0;
140  c->inner_io_error = ret < 0 ? ret : 0;
141 
142  return c->inner_io_error;
143 }
144 
145 static int ring_write(RingBuffer *ring, URLContext *h, size_t size)
146 {
147  av_assert2(size <= ring_space(ring));
149 }
150 
152 {
153  return ring->read_pos;
154 }
155 
156 static int ring_drain(RingBuffer *ring, int offset)
157 {
159  av_assert2(offset <= ring_size(ring));
160  ring->read_pos += offset;
161  return 0;
162 }
163 
164 static int async_check_interrupt(void *arg)
165 {
166  URLContext *h = arg;
167  Context *c = h->priv_data;
168 
169  if (c->abort_request)
170  return 1;
171 
172  if (ff_check_interrupt(&c->interrupt_callback))
173  c->abort_request = 1;
174 
175  return c->abort_request;
176 }
177 
178 static void *async_buffer_task(void *arg)
179 {
180  URLContext *h = arg;
181  Context *c = h->priv_data;
182  RingBuffer *ring = &c->ring;
183  int ret = 0;
184  int64_t seek_ret;
185 
186  while (1) {
187  int fifo_space, to_copy;
188 
189  pthread_mutex_lock(&c->mutex);
190  if (async_check_interrupt(h)) {
191  c->io_eof_reached = 1;
192  c->io_error = AVERROR_EXIT;
193  pthread_cond_signal(&c->cond_wakeup_main);
194  pthread_mutex_unlock(&c->mutex);
195  break;
196  }
197 
198  if (c->seek_request) {
199  seek_ret = ffurl_seek(c->inner, c->seek_pos, c->seek_whence);
200  if (seek_ret >= 0) {
201  c->io_eof_reached = 0;
202  c->io_error = 0;
203  ring_reset(ring);
204  }
205 
206  c->seek_completed = 1;
207  c->seek_ret = seek_ret;
208  c->seek_request = 0;
209 
210 
211  pthread_cond_signal(&c->cond_wakeup_main);
212  pthread_mutex_unlock(&c->mutex);
213  continue;
214  }
215 
216  fifo_space = ring_space(ring);
217  if (c->io_eof_reached || fifo_space <= 0) {
218  pthread_cond_signal(&c->cond_wakeup_main);
219  pthread_cond_wait(&c->cond_wakeup_background, &c->mutex);
220  pthread_mutex_unlock(&c->mutex);
221  continue;
222  }
223  pthread_mutex_unlock(&c->mutex);
224 
225  to_copy = FFMIN(4096, fifo_space);
226  ret = ring_write(ring, h, to_copy);
227 
228  pthread_mutex_lock(&c->mutex);
229  if (ret <= 0) {
230  c->io_eof_reached = 1;
231  if (c->inner_io_error < 0)
232  c->io_error = c->inner_io_error;
233  }
234 
235  pthread_cond_signal(&c->cond_wakeup_main);
236  pthread_mutex_unlock(&c->mutex);
237  }
238 
239  return NULL;
240 }
241 
242 static int async_open(URLContext *h, const char *arg, int flags, AVDictionary **options)
243 {
244  Context *c = h->priv_data;
245  int ret;
246  AVIOInterruptCB interrupt_callback = {.callback = async_check_interrupt, .opaque = h};
247 
248  av_strstart(arg, "async:", &arg);
249 
251  if (ret < 0)
252  goto fifo_fail;
253 
254  /* wrap interrupt callback */
255  c->interrupt_callback = h->interrupt_callback;
256  ret = ffurl_open_whitelist(&c->inner, arg, flags, &interrupt_callback, options, h->protocol_whitelist, h->protocol_blacklist, h);
257  if (ret != 0) {
258  av_log(h, AV_LOG_ERROR, "ffurl_open failed : %s, %s\n", av_err2str(ret), arg);
259  goto url_fail;
260  }
261 
262  c->logical_size = ffurl_size(c->inner);
263  h->is_streamed = c->inner->is_streamed;
264 
265  ret = pthread_mutex_init(&c->mutex, NULL);
266  if (ret != 0) {
267  ret = AVERROR(ret);
268  av_log(h, AV_LOG_ERROR, "pthread_mutex_init failed : %s\n", av_err2str(ret));
269  goto mutex_fail;
270  }
271 
272  ret = pthread_cond_init(&c->cond_wakeup_main, NULL);
273  if (ret != 0) {
274  ret = AVERROR(ret);
275  av_log(h, AV_LOG_ERROR, "pthread_cond_init failed : %s\n", av_err2str(ret));
276  goto cond_wakeup_main_fail;
277  }
278 
279  ret = pthread_cond_init(&c->cond_wakeup_background, NULL);
280  if (ret != 0) {
281  ret = AVERROR(ret);
282  av_log(h, AV_LOG_ERROR, "pthread_cond_init failed : %s\n", av_err2str(ret));
283  goto cond_wakeup_background_fail;
284  }
285 
286  ret = pthread_create(&c->async_buffer_thread, NULL, async_buffer_task, h);
287  if (ret) {
288  ret = AVERROR(ret);
289  av_log(h, AV_LOG_ERROR, "pthread_create failed : %s\n", av_err2str(ret));
290  goto thread_fail;
291  }
292 
293  return 0;
294 
295 thread_fail:
296  pthread_cond_destroy(&c->cond_wakeup_background);
297 cond_wakeup_background_fail:
298  pthread_cond_destroy(&c->cond_wakeup_main);
299 cond_wakeup_main_fail:
300  pthread_mutex_destroy(&c->mutex);
301 mutex_fail:
302  ffurl_closep(&c->inner);
303 url_fail:
304  ring_destroy(&c->ring);
305 fifo_fail:
306  return ret;
307 }
308 
310 {
311  Context *c = h->priv_data;
312  int ret;
313 
314  pthread_mutex_lock(&c->mutex);
315  c->abort_request = 1;
316  pthread_cond_signal(&c->cond_wakeup_background);
317  pthread_mutex_unlock(&c->mutex);
318 
319  ret = pthread_join(c->async_buffer_thread, NULL);
320  if (ret != 0)
321  av_log(h, AV_LOG_ERROR, "pthread_join(): %s\n", av_err2str(ret));
322 
323  pthread_cond_destroy(&c->cond_wakeup_background);
324  pthread_cond_destroy(&c->cond_wakeup_main);
325  pthread_mutex_destroy(&c->mutex);
326  ffurl_closep(&c->inner);
327  ring_destroy(&c->ring);
328 
329  return 0;
330 }
331 
332 static int async_read_internal(URLContext *h, void *dest, int size)
333 {
334  Context *c = h->priv_data;
335  RingBuffer *ring = &c->ring;
336  int read_complete = !dest;
337  int to_read = size;
338  int ret = 0;
339 
340  pthread_mutex_lock(&c->mutex);
341 
342  while (to_read > 0) {
343  int fifo_size, to_copy;
344  if (async_check_interrupt(h)) {
345  ret = AVERROR_EXIT;
346  break;
347  }
348  fifo_size = ring_size(ring);
349  to_copy = FFMIN(to_read, fifo_size);
350  if (to_copy > 0) {
351  ring_read(ring, dest, to_copy);
352  if (dest)
353  dest = (uint8_t *)dest + to_copy;
354  c->logical_pos += to_copy;
355  to_read -= to_copy;
356  ret = size - to_read;
357 
358  if (to_read <= 0 || !read_complete)
359  break;
360  } else if (c->io_eof_reached) {
361  if (ret <= 0) {
362  if (c->io_error)
363  ret = c->io_error;
364  else
365  ret = AVERROR_EOF;
366  }
367  break;
368  }
369  pthread_cond_signal(&c->cond_wakeup_background);
370  pthread_cond_wait(&c->cond_wakeup_main, &c->mutex);
371  }
372 
373  pthread_cond_signal(&c->cond_wakeup_background);
374  pthread_mutex_unlock(&c->mutex);
375 
376  return ret;
377 }
378 
379 static int async_read(URLContext *h, unsigned char *buf, int size)
380 {
381  return async_read_internal(h, buf, size);
382 }
383 
384 static int64_t async_seek(URLContext *h, int64_t pos, int whence)
385 {
386  Context *c = h->priv_data;
387  RingBuffer *ring = &c->ring;
388  int64_t ret;
389  int64_t new_logical_pos;
390  int fifo_size;
391  int fifo_size_of_read_back;
392 
393  if (whence == AVSEEK_SIZE) {
394  av_log(h, AV_LOG_TRACE, "async_seek: AVSEEK_SIZE: %"PRId64"\n", (int64_t)c->logical_size);
395  return c->logical_size;
396  } else if (whence == SEEK_CUR) {
397  av_log(h, AV_LOG_TRACE, "async_seek: %"PRId64"\n", pos);
398  new_logical_pos = pos + c->logical_pos;
399  } else if (whence == SEEK_SET){
400  av_log(h, AV_LOG_TRACE, "async_seek: %"PRId64"\n", pos);
401  new_logical_pos = pos;
402  } else {
403  return AVERROR(EINVAL);
404  }
405  if (new_logical_pos < 0)
406  return AVERROR(EINVAL);
407 
408  fifo_size = ring_size(ring);
409  fifo_size_of_read_back = ring_size_of_read_back(ring);
410  if (new_logical_pos == c->logical_pos) {
411  /* current position */
412  return c->logical_pos;
413  } else if ((new_logical_pos >= (c->logical_pos - fifo_size_of_read_back)) &&
414  (new_logical_pos < (c->logical_pos + fifo_size + SHORT_SEEK_THRESHOLD))) {
415  int pos_delta = (int)(new_logical_pos - c->logical_pos);
416  /* fast seek */
417  av_log(h, AV_LOG_TRACE, "async_seek: fask_seek %"PRId64" from %d dist:%d/%d\n",
418  new_logical_pos, (int)c->logical_pos,
419  (int)(new_logical_pos - c->logical_pos), fifo_size);
420 
421  if (pos_delta > 0) {
422  // fast seek forwards
423  async_read_internal(h, NULL, pos_delta);
424  } else {
425  // fast seek backwards
426  ring_drain(ring, pos_delta);
427  c->logical_pos = new_logical_pos;
428  }
429 
430  return c->logical_pos;
431  } else if (c->logical_size <= 0) {
432  /* can not seek */
433  return AVERROR(EINVAL);
434  } else if (new_logical_pos > c->logical_size) {
435  /* beyond end */
436  return AVERROR(EINVAL);
437  }
438 
439  pthread_mutex_lock(&c->mutex);
440 
441  c->seek_request = 1;
442  c->seek_pos = new_logical_pos;
443  c->seek_whence = SEEK_SET;
444  c->seek_completed = 0;
445  c->seek_ret = 0;
446 
447  while (1) {
448  if (async_check_interrupt(h)) {
449  ret = AVERROR_EXIT;
450  break;
451  }
452  if (c->seek_completed) {
453  if (c->seek_ret >= 0)
454  c->logical_pos = c->seek_ret;
455  ret = c->seek_ret;
456  break;
457  }
458  pthread_cond_signal(&c->cond_wakeup_background);
459  pthread_cond_wait(&c->cond_wakeup_main, &c->mutex);
460  }
461 
462  pthread_mutex_unlock(&c->mutex);
463 
464  return ret;
465 }
466 
467 #define OFFSET(x) offsetof(Context, x)
468 #define D AV_OPT_FLAG_DECODING_PARAM
469 
470 static const AVOption options[] = {
471  {NULL},
472 };
473 
474 #undef D
475 #undef OFFSET
476 
477 static const AVClass async_context_class = {
478  .class_name = "Async",
479  .item_name = av_default_item_name,
480  .option = options,
481  .version = LIBAVUTIL_VERSION_INT,
482 };
483 
485  .name = "async",
486  .url_open2 = async_open,
487  .url_read = async_read,
488  .url_seek = async_seek,
489  .url_close = async_close,
490  .priv_data_size = sizeof(Context),
491  .priv_data_class = &async_context_class,
492 };
493 
494 #if 0
495 
496 #define TEST_SEEK_POS (1536)
497 #define TEST_STREAM_SIZE (2048)
498 
499 typedef struct TestContext {
500  AVClass *class;
501  int64_t logical_pos;
502  int64_t logical_size;
503 
504  /* options */
505  int opt_read_error;
506 } TestContext;
507 
508 static int async_test_open(URLContext *h, const char *arg, int flags, AVDictionary **options)
509 {
510  TestContext *c = h->priv_data;
511  c->logical_pos = 0;
512  c->logical_size = TEST_STREAM_SIZE;
513  return 0;
514 }
515 
516 static int async_test_close(URLContext *h)
517 {
518  return 0;
519 }
520 
521 static int async_test_read(URLContext *h, unsigned char *buf, int size)
522 {
523  TestContext *c = h->priv_data;
524  int i;
525  int read_len = 0;
526 
527  if (c->opt_read_error)
528  return c->opt_read_error;
529 
530  if (c->logical_pos >= c->logical_size)
531  return AVERROR_EOF;
532 
533  for (i = 0; i < size; ++i) {
534  buf[i] = c->logical_pos & 0xFF;
535 
536  c->logical_pos++;
537  read_len++;
538 
539  if (c->logical_pos >= c->logical_size)
540  break;
541  }
542 
543  return read_len;
544 }
545 
546 static int64_t async_test_seek(URLContext *h, int64_t pos, int whence)
547 {
548  TestContext *c = h->priv_data;
549  int64_t new_logical_pos;
550 
551  if (whence == AVSEEK_SIZE) {
552  return c->logical_size;
553  } else if (whence == SEEK_CUR) {
554  new_logical_pos = pos + c->logical_pos;
555  } else if (whence == SEEK_SET){
556  new_logical_pos = pos;
557  } else {
558  return AVERROR(EINVAL);
559  }
560  if (new_logical_pos < 0)
561  return AVERROR(EINVAL);
562 
563  c->logical_pos = new_logical_pos;
564  return new_logical_pos;
565 }
566 
567 #define OFFSET(x) offsetof(TestContext, x)
568 #define D AV_OPT_FLAG_DECODING_PARAM
569 
570 static const AVOption async_test_options[] = {
571  { "async-test-read-error", "cause read fail",
572  OFFSET(opt_read_error), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, .flags = D },
573  {NULL},
574 };
575 
576 #undef D
577 #undef OFFSET
578 
579 static const AVClass async_test_context_class = {
580  .class_name = "Async-Test",
581  .item_name = av_default_item_name,
582  .option = async_test_options,
583  .version = LIBAVUTIL_VERSION_INT,
584 };
585 
586 const URLProtocol ff_async_test_protocol = {
587  .name = "async-test",
588  .url_open2 = async_test_open,
589  .url_read = async_test_read,
590  .url_seek = async_test_seek,
591  .url_close = async_test_close,
592  .priv_data_size = sizeof(TestContext),
593  .priv_data_class = &async_test_context_class,
594 };
595 
596 int main(void)
597 {
598  URLContext *h = NULL;
599  int i;
600  int ret;
601  int64_t size;
602  int64_t pos;
603  int64_t read_len;
604  unsigned char buf[4096];
606 
607  ffurl_register_protocol(&ff_async_protocol);
608  ffurl_register_protocol(&ff_async_test_protocol);
609 
610  /*
611  * test normal read
612  */
613  ret = ffurl_open_whitelist(&h, "async:async-test:", AVIO_FLAG_READ,
614  NULL, NULL, NULL, NULL, NULL);
615  printf("open: %d\n", ret);
616 
617  size = ffurl_size(h);
618  printf("size: %"PRId64"\n", size);
619 
620  pos = ffurl_seek(h, 0, SEEK_CUR);
621  read_len = 0;
622  while (1) {
623  ret = ffurl_read(h, buf, sizeof(buf));
624  if (ret == AVERROR_EOF) {
625  printf("read-error: AVERROR_EOF at %"PRId64"\n", ffurl_seek(h, 0, SEEK_CUR));
626  break;
627  }
628  else if (ret == 0)
629  break;
630  else if (ret < 0) {
631  printf("read-error: %d at %"PRId64"\n", ret, ffurl_seek(h, 0, SEEK_CUR));
632  goto fail;
633  } else {
634  for (i = 0; i < ret; ++i) {
635  if (buf[i] != (pos & 0xFF)) {
636  printf("read-mismatch: actual %d, expecting %d, at %"PRId64"\n",
637  (int)buf[i], (int)(pos & 0xFF), pos);
638  break;
639  }
640  pos++;
641  }
642  }
643 
644  read_len += ret;
645  }
646  printf("read: %"PRId64"\n", read_len);
647 
648  /*
649  * test normal seek
650  */
651  ret = ffurl_read(h, buf, 1);
652  printf("read: %d\n", ret);
653 
654  pos = ffurl_seek(h, TEST_SEEK_POS, SEEK_SET);
655  printf("seek: %"PRId64"\n", pos);
656 
657  read_len = 0;
658  while (1) {
659  ret = ffurl_read(h, buf, sizeof(buf));
660  if (ret == AVERROR_EOF)
661  break;
662  else if (ret == 0)
663  break;
664  else if (ret < 0) {
665  printf("read-error: %d at %"PRId64"\n", ret, ffurl_seek(h, 0, SEEK_CUR));
666  goto fail;
667  } else {
668  for (i = 0; i < ret; ++i) {
669  if (buf[i] != (pos & 0xFF)) {
670  printf("read-mismatch: actual %d, expecting %d, at %"PRId64"\n",
671  (int)buf[i], (int)(pos & 0xFF), pos);
672  break;
673  }
674  pos++;
675  }
676  }
677 
678  read_len += ret;
679  }
680  printf("read: %"PRId64"\n", read_len);
681 
682  ret = ffurl_read(h, buf, 1);
683  printf("read: %d\n", ret);
684 
685  /*
686  * test read error
687  */
688  ffurl_close(h);
689  av_dict_set_int(&opts, "async-test-read-error", -10000, 0);
690  ret = ffurl_open_whitelist(&h, "async:async-test:", AVIO_FLAG_READ,
691  NULL, &opts, NULL, NULL, NULL);
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
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:309
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
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:428
thread.h
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:57
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:178
options
static const AVOption options[]
Definition: async.c:470
ring_write
static int ring_write(RingBuffer *ring, URLContext *h, size_t size)
Definition: async.c:145
Context::abort_request
int abort_request
Definition: async.c:79
Context::io_error
int io_error
Definition: async.c:67
av_fifo_can_read
size_t av_fifo_can_read(const AVFifo *f)
Definition: fifo.c:87
AVOption
AVOption.
Definition: opt.h:251
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:479
av_fifo_write_from_cb
int av_fifo_write_from_cb(AVFifo *f, AVFifoCB read_cb, void *opaque, size_t *nb_elems)
Write data from a user-provided callback into a FIFO.
Definition: fifo.c:193
Context::seek_pos
int64_t seek_pos
Definition: async.c:61
ffurl_close
int ffurl_close(URLContext *h)
Definition: avio.c:461
av_fifo_reset2
void av_fifo_reset2(AVFifo *f)
Definition: fifo.c:280
AVDictionary
Definition: dict.c:30
ring_size
static int ring_size(RingBuffer *ring)
Definition: async.c:105
URLProtocol
Definition: url.h:53
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:59
Context::cond_wakeup_background
pthread_cond_t cond_wakeup_background
Definition: async.c:75
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:130
RingBuffer::read_pos
int read_pos
Definition: async.c:53
RingBuffer::fifo
AVFifo * 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:658
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:477
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:164
avassert.h
AV_LOG_TRACE
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition: log.h:206
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
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:306
ring_destroy
static void ring_destroy(RingBuffer *ring)
Definition: async.c:94
Context::io_eof_reached
int io_eof_reached
Definition: async.c:68
wrapped_url_read
static int wrapped_url_read(void *src, void *dst, size_t *size)
Definition: async.c:132
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
av_fifo_can_write
size_t av_fifo_can_write(const AVFifo *f)
Definition: fifo.c:94
ring_read
static int ring_read(RingBuffer *ring, void *dest, int buf_size)
Definition: async.c:115
arg
const char * arg
Definition: jacosubdec.c:67
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:66
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:237
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:77
error.h
Context::ring
RingBuffer ring
Definition: async.c:72
AVFifo
Definition: fifo.c:35
D
#define D
Definition: async.c:468
av_fifo_peek
int av_fifo_peek(AVFifo *f, void *buf, size_t nb_elems, size_t offset)
Read data from a FIFO without modifying FIFO state.
Definition: fifo.c:255
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:121
size
int size
Definition: twinvq_data.h:10344
URLProtocol::name
const char * name
Definition: url.h:54
async_open
static int async_open(URLContext *h, const char *arg, int flags, AVDictionary **options)
Definition: async.c:242
OFFSET
#define OFFSET(x)
Definition: async.c:467
printf
printf("static const uint8_t my_array[100] = {\n")
Context::inner_io_error
int inner_io_error
Definition: async.c:66
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:37
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:379
av_assert2
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
Definition: avassert.h:64
URLContext
Definition: url.h:37
log.h
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:271
Context::seek_ret
int64_t seek_ret
Definition: async.c:64
av_fifo_alloc2
AVFifo * av_fifo_alloc2(size_t nb_elems, size_t elem_size, unsigned int flags)
Allocate and initialize an AVFifo with a given element size.
Definition: fifo.c:47
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
url.h
av_fifo_freep2
void av_fifo_freep2(AVFifo **f)
Free an AVFifo and reset pointer to NULL.
Definition: fifo.c:286
pthread_cond_t
Definition: os2threads.h:58
RingBuffer::read_back_capacity
int read_back_capacity
Definition: async.c:51
Context::inner
URLContext * inner
Definition: async.c:58
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:438
ret
ret
Definition: filter_design.txt:187
async_seek
static int64_t async_seek(URLContext *h, int64_t pos, int whence)
Definition: async.c:384
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:71
async_read_internal
static int async_read_internal(URLContext *h, void *dest, int size)
Definition: async.c:332
pos
unsigned int pos
Definition: spdifenc.c:412
ff_async_protocol
const URLProtocol ff_async_protocol
Definition: async.c:484
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:401
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:622
ring_reset
static void ring_reset(RingBuffer *ring)
Definition: async.c:99
AVIOInterruptCB::callback
int(* callback)(void *)
Definition: avio.h:60
ring_size_of_read_back
static int ring_size_of_read_back(RingBuffer *ring)
Definition: async.c:151
src
INIT_CLIP pixel * src
Definition: h264pred_template.c:418
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
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:605
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:58
ring_drain
static int ring_drain(RingBuffer *ring, int offset)
Definition: async.c:156
avstring.h
av_fifo_drain2
void av_fifo_drain2(AVFifo *f, size_t size)
Discard the specified amount of data from an AVFifo.
Definition: fifo.c:266
int
int
Definition: ffmpeg_filter.c:153
pthread_mutex_lock
#define pthread_mutex_lock(a)
Definition: ffprobe.c:73