47#define BUFFER_CAPACITY (4 * 1024 * 1024)
48#define READ_BACK_CAPACITY (4 * 1024 * 1024)
49#define SHORT_SEEK_THRESHOLD (256 * 1024)
143 c->inner_io_error =
ret < 0 ?
ret : 0;
145 return c->inner_io_error;
198 int fifo_space, to_copy;
202 c->io_eof_reached = 1;
209 if (
c->seek_request) {
210 seek_ret =
ffurl_seek(
c->inner,
c->seek_pos,
c->seek_whence);
212 c->io_eof_reached = 0;
217 c->seek_completed = 1;
218 c->seek_ret = seek_ret;
228 if (
c->io_eof_reached || fifo_space <= 0) {
236 to_copy =
FFMIN(4096, fifo_space);
241 c->io_eof_reached = 1;
242 if (
c->inner_io_error < 0)
243 c->io_error =
c->inner_io_error;
267 c->interrupt_callback =
h->interrupt_callback;
275 h->is_streamed =
c->inner->is_streamed;
288 goto cond_wakeup_main_fail;
295 goto cond_wakeup_background_fail;
309cond_wakeup_background_fail:
311cond_wakeup_main_fail:
348 int read_complete = !dest;
354 while (to_read > 0) {
365 dest = (uint8_t *)dest + to_copy;
366 c->logical_pos += to_copy;
370 if (to_read <= 0 || !read_complete)
372 }
else if (
c->io_eof_reached) {
403 int fifo_size_of_read_back;
407 return c->logical_size;
408 }
else if (whence == SEEK_CUR) {
410 new_logical_pos =
pos +
c->logical_pos;
411 }
else if (whence == SEEK_SET){
413 new_logical_pos =
pos;
417 if (new_logical_pos < 0)
422 if (new_logical_pos ==
c->logical_pos) {
424 return c->logical_pos;
425 }
else if ((new_logical_pos >= (
c->logical_pos - fifo_size_of_read_back)) &&
427 int pos_delta = (int)(new_logical_pos -
c->logical_pos);
430 new_logical_pos, (
int)
c->logical_pos,
431 (
int)(new_logical_pos -
c->logical_pos),
fifo_size);
439 c->logical_pos = new_logical_pos;
442 return c->logical_pos;
443 }
else if (
c->logical_size <= 0) {
446 }
else if (new_logical_pos >
c->logical_size) {
454 c->seek_pos = new_logical_pos;
455 c->seek_whence = SEEK_SET;
456 c->seek_completed = 0;
464 if (
c->seek_completed) {
465 if (
c->seek_ret >= 0)
466 c->logical_pos =
c->seek_ret;
479#define OFFSET(x) offsetof(AsyncContext, x)
480#define D AV_OPT_FLAG_DECODING_PARAM
490 .class_name =
"Async",
508#define TEST_SEEK_POS (1536)
509#define TEST_STREAM_SIZE (2048)
524 c->logical_size = TEST_STREAM_SIZE;
539 if (
c->opt_read_error)
540 return c->opt_read_error;
542 if (
c->logical_pos >=
c->logical_size)
546 buf[
i] =
c->logical_pos & 0xFF;
551 if (
c->logical_pos >=
c->logical_size)
564 return c->logical_size;
565 }
else if (whence == SEEK_CUR) {
566 new_logical_pos =
pos +
c->logical_pos;
567 }
else if (whence == SEEK_SET){
568 new_logical_pos =
pos;
572 if (new_logical_pos < 0)
575 c->logical_pos = new_logical_pos;
576 return new_logical_pos;
579#define OFFSET(x) offsetof(TestContext, x)
580#define D AV_OPT_FLAG_DECODING_PARAM
582static const AVOption async_test_options[] = {
583 {
"async-test-read-error",
"cause read fail",
591static const AVClass async_test_context_class = {
592 .class_name =
"Async-Test",
594 .option = async_test_options,
599 .name =
"async-test",
600 .url_open2 = async_test_open,
601 .url_read = async_test_read,
602 .url_seek = async_test_seek,
603 .url_close = async_test_close,
605 .priv_data_class = &async_test_context_class,
616 unsigned char buf[4096];
620 ffurl_register_protocol(&ff_async_test_protocol);
646 for (
i = 0;
i <
ret; ++
i) {
647 if (buf[
i] != (
pos & 0xFF)) {
648 printf(
"read-mismatch: actual %d, expecting %d, at %"PRId64
"\n",
649 (
int)buf[
i], (
int)(
pos & 0xFF),
pos);
658 printf(
"read: %"PRId64
"\n", read_len);
680 for (
i = 0;
i <
ret; ++
i) {
681 if (buf[
i] != (
pos & 0xFF)) {
682 printf(
"read-mismatch: actual %d, expecting %d, at %"PRId64
"\n",
683 (
int)buf[
i], (
int)(
pos & 0xFF),
pos);
692 printf(
"read: %"PRId64
"\n", read_len);
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
static AVDictionary * opts
static int async_check_interrupt(void *arg)
static const AVClass async_context_class
static int ring_drain(RingBuffer *ring, int offset)
static void * async_buffer_task(void *arg)
static int async_read(URLContext *h, unsigned char *buf, int size)
static int ring_space(RingBuffer *ring)
const URLProtocol ff_async_protocol
#define READ_BACK_CAPACITY
#define BUFFER_CAPACITY
@TODO support timeout support work with concatdec, hls
static void ring_reset(RingBuffer *ring)
static int async_open(URLContext *h, const char *arg, int flags, AVDictionary **options)
static int async_close(URLContext *h)
static void ring_destroy(RingBuffer *ring)
#define SHORT_SEEK_THRESHOLD
static int wrapped_url_read(void *src, void *dst, size_t *size)
static int ring_read(RingBuffer *ring, void *dest, int buf_size)
static int ring_init(RingBuffer *ring, unsigned int capacity, int read_back_capacity)
static int ring_size_of_read_back(RingBuffer *ring)
static int ring_write(RingBuffer *ring, URLContext *h, size_t size)
static int ring_size(RingBuffer *ring)
static int64_t async_seek(URLContext *h, int64_t pos, int whence)
static int async_read_internal(URLContext *h, void *dest, int size)
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
int ff_check_interrupt(AVIOInterruptCB *cb)
Check if the user has requested to interrupt a blocking function associated with cb.
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.
int64_t ffurl_size(URLContext *h)
Return the filesize of the resource accessed by h, AVERROR(ENOSYS) if the operation is not supported ...
int ffurl_closep(URLContext **hh)
Close the resource accessed by the URLContext h, and free the memory used by it.
int ffurl_close(URLContext *h)
#define AVIO_FLAG_READ
read-only
#define AVSEEK_SIZE
Passing this as the "whence" parameter to a seek function causes it to return the filesize without se...
#define flags(name, subs,...)
#define i(width, name, range_min, range_max)
__device__ int printf(const char *,...)
@ AV_OPT_TYPE_INT
Underlying C type is int.
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
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.
#define AVERROR_EXIT
Immediate exit was requested; the called function should not be restarted.
#define AVERROR_EOF
End of file.
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
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.
void av_fifo_freep2(AVFifo **f)
Free an AVFifo and reset pointer to NULL.
void av_fifo_reset2(AVFifo *f)
size_t av_fifo_can_write(const AVFifo *f)
size_t av_fifo_can_read(const AVFifo *f)
int av_fifo_peek(const AVFifo *f, void *buf, size_t nb_elems, size_t offset)
Read data from a FIFO without modifying FIFO state.
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.
void av_fifo_drain2(AVFifo *f, size_t size)
Discard the specified amount of data from an AVFifo.
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
const char * av_default_item_name(void *ptr)
Return the context name.
int av_strstart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str.
#define LIBAVUTIL_VERSION_INT
static int ff_thread_setname(const char *name)
static av_always_inline int pthread_cond_signal(pthread_cond_t *cond)
static av_always_inline int pthread_mutex_lock(pthread_mutex_t *mutex)
static av_always_inline int pthread_cond_destroy(pthread_cond_t *cond)
static av_always_inline int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
static av_always_inline int pthread_join(pthread_t thread, void **value_ptr)
static av_always_inline int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
static av_always_inline int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg)
static av_always_inline int pthread_mutex_unlock(pthread_mutex_t *mutex)
static av_always_inline int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
static av_always_inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
#define atomic_store(object, desired)
#define atomic_load(object)
#define atomic_init(obj, value)
Describe the class of an AVClass context structure.
Callback for checking whether to abort blocking functions.
pthread_cond_t cond_wakeup_background
pthread_cond_t cond_wakeup_main
pthread_t async_buffer_thread
AVIOInterruptCB interrupt_callback
unbuffered private I/O API
static 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.
static int ffurl_read(URLContext *h, uint8_t *buf, int size)
Read up to size bytes from the resource accessed by h, and store the read bytes in buf.