44 #define BUFFER_CAPACITY (4 * 1024 * 1024)
45 #define READ_BACK_CAPACITY (4 * 1024 * 1024)
46 #define SHORT_SEEK_THRESHOLD (256 * 1024)
155 if (
c->abort_request)
159 c->abort_request = 1;
161 return c->abort_request;
171 c->inner_io_error = ret < 0 ? ret : 0;
185 int fifo_space, to_copy;
189 c->io_eof_reached = 1;
196 if (
c->seek_request) {
197 seek_ret =
ffurl_seek(
c->inner,
c->seek_pos,
c->seek_whence);
199 c->io_eof_reached = 0;
204 c->seek_completed = 1;
205 c->seek_ret = seek_ret;
215 if (
c->io_eof_reached || fifo_space <= 0) {
223 to_copy =
FFMIN(4096, fifo_space);
228 c->io_eof_reached = 1;
229 if (
c->inner_io_error < 0)
230 c->io_error =
c->inner_io_error;
253 c->interrupt_callback =
h->interrupt_callback;
261 h->is_streamed =
c->inner->is_streamed;
274 goto cond_wakeup_main_fail;
281 goto cond_wakeup_background_fail;
295 cond_wakeup_background_fail:
297 cond_wakeup_main_fail:
313 c->abort_request = 1;
331 void (*
func)(
void*,
void*,
int))
340 while (to_read > 0) {
341 int fifo_size, to_copy;
347 to_copy =
FFMIN(to_read, fifo_size);
351 dest = (
uint8_t *)dest + to_copy;
352 c->logical_pos += to_copy;
354 ret =
size - to_read;
356 if (to_read <= 0 || !read_complete)
358 }
else if (
c->io_eof_reached) {
393 int fifo_size_of_read_back;
397 return c->logical_size;
398 }
else if (whence == SEEK_CUR) {
400 new_logical_pos =
pos +
c->logical_pos;
401 }
else if (whence == SEEK_SET){
403 new_logical_pos =
pos;
407 if (new_logical_pos < 0)
412 if (new_logical_pos ==
c->logical_pos) {
414 return c->logical_pos;
415 }
else if ((new_logical_pos >= (
c->logical_pos - fifo_size_of_read_back)) &&
417 int pos_delta = (
int)(new_logical_pos -
c->logical_pos);
420 new_logical_pos, (
int)
c->logical_pos,
421 (
int)(new_logical_pos -
c->logical_pos), fifo_size);
429 c->logical_pos = new_logical_pos;
432 return c->logical_pos;
433 }
else if (
c->logical_size <= 0) {
436 }
else if (new_logical_pos >
c->logical_size) {
444 c->seek_pos = new_logical_pos;
445 c->seek_whence = SEEK_SET;
446 c->seek_completed = 0;
454 if (
c->seek_completed) {
455 if (
c->seek_ret >= 0)
456 c->logical_pos =
c->seek_ret;
469 #define OFFSET(x) offsetof(Context, x)
470 #define D AV_OPT_FLAG_DECODING_PARAM
492 .priv_data_size =
sizeof(
Context),
498 #define TEST_SEEK_POS (1536)
499 #define TEST_STREAM_SIZE (2048)
514 c->logical_size = TEST_STREAM_SIZE;
523 static int async_test_read(
URLContext *
h,
unsigned char *buf,
int size)
529 if (
c->opt_read_error)
530 return c->opt_read_error;
532 if (
c->logical_pos >=
c->logical_size)
536 buf[
i] =
c->logical_pos & 0xFF;
541 if (
c->logical_pos >=
c->logical_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;
562 if (new_logical_pos < 0)
565 c->logical_pos = new_logical_pos;
566 return new_logical_pos;
569 #define OFFSET(x) offsetof(TestContext, x)
570 #define D AV_OPT_FLAG_DECODING_PARAM
572 static const AVOption async_test_options[] = {
573 {
"async-test-read-error",
"cause read fail",
581 static const AVClass async_test_context_class = {
584 .option = async_test_options,
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,
595 .priv_data_class = &async_test_context_class,
606 unsigned char buf[4096];
610 ffurl_register_protocol(&ff_async_test_protocol);
617 printf(
"open: %d\n", ret);
620 printf(
"size: %"PRId64
"\n",
size);
627 printf(
"read-error: AVERROR_EOF at %"PRId64
"\n",
ffurl_seek(
h, 0, SEEK_CUR));
633 printf(
"read-error: %d at %"PRId64
"\n", ret,
ffurl_seek(
h, 0, SEEK_CUR));
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);
648 printf(
"read: %"PRId64
"\n", read_len);
654 printf(
"read: %d\n", ret);
657 printf(
"seek: %"PRId64
"\n",
pos);
667 printf(
"read-error: %d at %"PRId64
"\n", ret,
ffurl_seek(
h, 0, SEEK_CUR));
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);
682 printf(
"read: %"PRId64
"\n", read_len);
685 printf(
"read: %d\n", ret);
694 printf(
"open: %d\n", ret);
697 printf(
"read: %d\n", ret);
static int async_check_interrupt(void *arg)
static int wrapped_url_read(void *src, void *dst, int size)
static void * async_buffer_task(void *arg)
static const AVClass async_context_class
static int ring_drain(RingBuffer *ring, int offset)
static const AVOption options[]
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 ring_init(RingBuffer *ring, unsigned int capacity, int read_back_capacity)
static int ring_size_of_read_back(RingBuffer *ring)
static int ring_size(RingBuffer *ring)
static int ring_generic_write(RingBuffer *ring, void *src, int size, int(*func)(void *, void *, int))
static void fifo_do_not_copy_func(void *dest, void *src, int size)
static int ring_generic_read(RingBuffer *ring, void *dest, int buf_size, void(*func)(void *, void *, int))
static int64_t async_seek(URLContext *h, int64_t pos, int whence)
static int async_read_internal(URLContext *h, void *dest, int size, int read_complete, void(*func)(void *, void *, int))
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 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.
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_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.
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
ORing this as the "whence" parameter to a seek function causes it to return the filesize without seek...
int main(int argc, char *argv[])
#define flags(name, subs,...)
#define pthread_mutex_lock(a)
#define pthread_mutex_unlock(a)
a very simple circular buffer FIFO implementation
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...
#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
int(* func)(AVBPrint *dst, const char *in, const char *arg)
void av_fifo_drain(AVFifoBuffer *f, int size)
Discard data from the FIFO.
void av_fifo_reset(AVFifoBuffer *f)
Reset the AVFifoBuffer to the state right after av_fifo_alloc, in particular it is emptied.
void av_fifo_freep(AVFifoBuffer **f)
Free an AVFifoBuffer and reset pointer to NULL.
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 ...
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...
AVFifoBuffer * av_fifo_alloc(unsigned int size)
Initialize an AVFifoBuffer.
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.
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.
static av_always_inline int pthread_cond_signal(pthread_cond_t *cond)
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_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
static av_always_inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
Describe the class of an AVClass context structure.
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Callback for checking whether to abort blocking functions.
AVIOInterruptCB interrupt_callback
pthread_t async_buffer_thread
pthread_cond_t cond_wakeup_background
pthread_cond_t cond_wakeup_main
unbuffered private I/O API
static const uint8_t offset[127][2]