Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
F
ffmpeg.wasm-core
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Linshizhi
ffmpeg.wasm-core
Commits
6c7f289f
Commit
6c7f289f
authored
Oct 13, 2015
by
Zhang Rui
Committed by
Michael Niedermayer
Oct 14, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
avformat/async: cache some data for fast seek backward
Signed-off-by:
Michael Niedermayer
<
michael@niedermayer.cc
>
parent
87ff61b9
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
104 additions
and
19 deletions
+104
-19
async.c
libavformat/async.c
+104
-19
No files found.
libavformat/async.c
View file @
6c7f289f
...
@@ -24,7 +24,6 @@
...
@@ -24,7 +24,6 @@
/**
/**
* @TODO
* @TODO
* support timeout
* support timeout
* support backward short seek
* support work with concatdec, hls
* support work with concatdec, hls
*/
*/
...
@@ -43,8 +42,17 @@
...
@@ -43,8 +42,17 @@
#endif
#endif
#define BUFFER_CAPACITY (4 * 1024 * 1024)
#define BUFFER_CAPACITY (4 * 1024 * 1024)
#define READ_BACK_CAPACITY (4 * 1024 * 1024)
#define SHORT_SEEK_THRESHOLD (256 * 1024)
#define SHORT_SEEK_THRESHOLD (256 * 1024)
typedef
struct
RingBuffer
{
AVFifoBuffer
*
fifo
;
int
read_back_capacity
;
int
read_pos
;
}
RingBuffer
;
typedef
struct
Context
{
typedef
struct
Context
{
AVClass
*
class
;
AVClass
*
class
;
URLContext
*
inner
;
URLContext
*
inner
;
...
@@ -61,7 +69,7 @@ typedef struct Context {
...
@@ -61,7 +69,7 @@ typedef struct Context {
int64_t
logical_pos
;
int64_t
logical_pos
;
int64_t
logical_size
;
int64_t
logical_size
;
AVFifoBuffer
*
fifo
;
RingBuffer
ring
;
pthread_cond_t
cond_wakeup_main
;
pthread_cond_t
cond_wakeup_main
;
pthread_cond_t
cond_wakeup_background
;
pthread_cond_t
cond_wakeup_background
;
...
@@ -72,6 +80,73 @@ typedef struct Context {
...
@@ -72,6 +80,73 @@ typedef struct Context {
AVIOInterruptCB
interrupt_callback
;
AVIOInterruptCB
interrupt_callback
;
}
Context
;
}
Context
;
static
int
ring_init
(
RingBuffer
*
ring
,
unsigned
int
capacity
,
int
read_back_capacity
)
{
memset
(
ring
,
0
,
sizeof
(
RingBuffer
));
ring
->
fifo
=
av_fifo_alloc
(
capacity
+
read_back_capacity
);
if
(
!
ring
->
fifo
)
return
AVERROR
(
ENOMEM
);
ring
->
read_back_capacity
=
read_back_capacity
;
return
0
;
}
static
void
ring_destroy
(
RingBuffer
*
ring
)
{
av_fifo_freep
(
&
ring
->
fifo
);
}
static
void
ring_reset
(
RingBuffer
*
ring
)
{
av_fifo_reset
(
ring
->
fifo
);
ring
->
read_pos
=
0
;
}
static
int
ring_size
(
RingBuffer
*
ring
)
{
return
av_fifo_size
(
ring
->
fifo
)
-
ring
->
read_pos
;
}
static
int
ring_space
(
RingBuffer
*
ring
)
{
return
av_fifo_space
(
ring
->
fifo
);
}
static
int
ring_generic_read
(
RingBuffer
*
ring
,
void
*
dest
,
int
buf_size
,
void
(
*
func
)(
void
*
,
void
*
,
int
))
{
int
ret
;
av_assert2
(
buf_size
<=
ring_size
(
ring
));
ret
=
av_fifo_generic_peek_at
(
ring
->
fifo
,
dest
,
ring
->
read_pos
,
buf_size
,
func
);
ring
->
read_pos
+=
buf_size
;
if
(
ring
->
read_pos
>
ring
->
read_back_capacity
)
{
av_fifo_drain
(
ring
->
fifo
,
ring
->
read_pos
-
ring
->
read_back_capacity
);
ring
->
read_pos
=
ring
->
read_back_capacity
;
}
return
ret
;
}
static
int
ring_generic_write
(
RingBuffer
*
ring
,
void
*
src
,
int
size
,
int
(
*
func
)(
void
*
,
void
*
,
int
))
{
av_assert2
(
size
<=
ring_space
(
ring
));
return
av_fifo_generic_write
(
ring
->
fifo
,
src
,
size
,
func
);
}
static
int
ring_size_of_read_back
(
RingBuffer
*
ring
)
{
return
ring
->
read_pos
;
}
static
int
ring_drain
(
RingBuffer
*
ring
,
int
offset
)
{
av_assert2
(
offset
>=
-
ring_size_of_read_back
(
ring
));
av_assert2
(
offset
<=
-
ring_size
(
ring
));
ring
->
read_pos
+=
offset
;
return
0
;
}
static
int
async_check_interrupt
(
void
*
arg
)
static
int
async_check_interrupt
(
void
*
arg
)
{
{
URLContext
*
h
=
arg
;
URLContext
*
h
=
arg
;
...
@@ -102,7 +177,7 @@ static void *async_buffer_task(void *arg)
...
@@ -102,7 +177,7 @@ static void *async_buffer_task(void *arg)
{
{
URLContext
*
h
=
arg
;
URLContext
*
h
=
arg
;
Context
*
c
=
h
->
priv_data
;
Context
*
c
=
h
->
priv_data
;
AVFifoBuffer
*
fifo
=
c
->
fifo
;
RingBuffer
*
ring
=
&
c
->
ring
;
int
ret
=
0
;
int
ret
=
0
;
int64_t
seek_ret
;
int64_t
seek_ret
;
...
@@ -132,14 +207,14 @@ static void *async_buffer_task(void *arg)
...
@@ -132,14 +207,14 @@ static void *async_buffer_task(void *arg)
c
->
seek_ret
=
seek_ret
;
c
->
seek_ret
=
seek_ret
;
c
->
seek_request
=
0
;
c
->
seek_request
=
0
;
av_fifo_reset
(
fifo
);
ring_reset
(
ring
);
pthread_cond_signal
(
&
c
->
cond_wakeup_main
);
pthread_cond_signal
(
&
c
->
cond_wakeup_main
);
pthread_mutex_unlock
(
&
c
->
mutex
);
pthread_mutex_unlock
(
&
c
->
mutex
);
continue
;
continue
;
}
}
fifo_space
=
av_fifo_space
(
fifo
);
fifo_space
=
ring_space
(
ring
);
if
(
c
->
io_eof_reached
||
fifo_space
<=
0
)
{
if
(
c
->
io_eof_reached
||
fifo_space
<=
0
)
{
pthread_cond_signal
(
&
c
->
cond_wakeup_main
);
pthread_cond_signal
(
&
c
->
cond_wakeup_main
);
pthread_cond_wait
(
&
c
->
cond_wakeup_background
,
&
c
->
mutex
);
pthread_cond_wait
(
&
c
->
cond_wakeup_background
,
&
c
->
mutex
);
...
@@ -149,7 +224,7 @@ static void *async_buffer_task(void *arg)
...
@@ -149,7 +224,7 @@ static void *async_buffer_task(void *arg)
pthread_mutex_unlock
(
&
c
->
mutex
);
pthread_mutex_unlock
(
&
c
->
mutex
);
to_copy
=
FFMIN
(
4096
,
fifo_space
);
to_copy
=
FFMIN
(
4096
,
fifo_space
);
ret
=
av_fifo_generic_write
(
fifo
,
(
void
*
)
h
,
to_copy
,
(
void
*
)
wrapped_url_read
);
ret
=
ring_generic_write
(
ring
,
(
void
*
)
h
,
to_copy
,
(
void
*
)
wrapped_url_read
);
pthread_mutex_lock
(
&
c
->
mutex
);
pthread_mutex_lock
(
&
c
->
mutex
);
if
(
ret
<=
0
)
{
if
(
ret
<=
0
)
{
...
@@ -173,11 +248,9 @@ static int async_open(URLContext *h, const char *arg, int flags, AVDictionary **
...
@@ -173,11 +248,9 @@ static int async_open(URLContext *h, const char *arg, int flags, AVDictionary **
av_strstart
(
arg
,
"async:"
,
&
arg
);
av_strstart
(
arg
,
"async:"
,
&
arg
);
c
->
fifo
=
av_fifo_alloc
(
BUFFER_CAPACITY
);
ret
=
ring_init
(
&
c
->
ring
,
BUFFER_CAPACITY
,
READ_BACK_CAPACITY
);
if
(
!
c
->
fifo
)
{
if
(
ret
<
0
)
ret
=
AVERROR
(
ENOMEM
);
goto
fifo_fail
;
goto
fifo_fail
;
}
/* wrap interrupt callback */
/* wrap interrupt callback */
c
->
interrupt_callback
=
h
->
interrupt_callback
;
c
->
interrupt_callback
=
h
->
interrupt_callback
;
...
@@ -225,7 +298,7 @@ cond_wakeup_main_fail:
...
@@ -225,7 +298,7 @@ cond_wakeup_main_fail:
mutex_fail:
mutex_fail:
ffurl_close
(
c
->
inner
);
ffurl_close
(
c
->
inner
);
url_fail:
url_fail:
av_fifo_freep
(
&
c
->
fifo
);
ring_destroy
(
&
c
->
ring
);
fifo_fail:
fifo_fail:
return
ret
;
return
ret
;
}
}
...
@@ -248,7 +321,7 @@ static int async_close(URLContext *h)
...
@@ -248,7 +321,7 @@ static int async_close(URLContext *h)
pthread_cond_destroy
(
&
c
->
cond_wakeup_main
);
pthread_cond_destroy
(
&
c
->
cond_wakeup_main
);
pthread_mutex_destroy
(
&
c
->
mutex
);
pthread_mutex_destroy
(
&
c
->
mutex
);
ffurl_close
(
c
->
inner
);
ffurl_close
(
c
->
inner
);
av_fifo_freep
(
&
c
->
fifo
);
ring_destroy
(
&
c
->
ring
);
return
0
;
return
0
;
}
}
...
@@ -257,7 +330,7 @@ static int async_read_internal(URLContext *h, void *dest, int size, int read_com
...
@@ -257,7 +330,7 @@ static int async_read_internal(URLContext *h, void *dest, int size, int read_com
void
(
*
func
)(
void
*
,
void
*
,
int
))
void
(
*
func
)(
void
*
,
void
*
,
int
))
{
{
Context
*
c
=
h
->
priv_data
;
Context
*
c
=
h
->
priv_data
;
AVFifoBuffer
*
fifo
=
c
->
fifo
;
RingBuffer
*
ring
=
&
c
->
ring
;
int
to_read
=
size
;
int
to_read
=
size
;
int
ret
=
0
;
int
ret
=
0
;
...
@@ -269,10 +342,10 @@ static int async_read_internal(URLContext *h, void *dest, int size, int read_com
...
@@ -269,10 +342,10 @@ static int async_read_internal(URLContext *h, void *dest, int size, int read_com
ret
=
AVERROR_EXIT
;
ret
=
AVERROR_EXIT
;
break
;
break
;
}
}
fifo_size
=
av_fifo_size
(
fifo
);
fifo_size
=
ring_size
(
ring
);
to_copy
=
FFMIN
(
to_read
,
fifo_size
);
to_copy
=
FFMIN
(
to_read
,
fifo_size
);
if
(
to_copy
>
0
)
{
if
(
to_copy
>
0
)
{
av_fifo_generic_read
(
fifo
,
dest
,
to_copy
,
func
);
ring_generic_read
(
ring
,
dest
,
to_copy
,
func
);
if
(
!
func
)
if
(
!
func
)
dest
=
(
uint8_t
*
)
dest
+
to_copy
;
dest
=
(
uint8_t
*
)
dest
+
to_copy
;
c
->
logical_pos
+=
to_copy
;
c
->
logical_pos
+=
to_copy
;
...
@@ -312,10 +385,11 @@ static void fifo_do_not_copy_func(void* dest, void* src, int size) {
...
@@ -312,10 +385,11 @@ static void fifo_do_not_copy_func(void* dest, void* src, int size) {
static
int64_t
async_seek
(
URLContext
*
h
,
int64_t
pos
,
int
whence
)
static
int64_t
async_seek
(
URLContext
*
h
,
int64_t
pos
,
int
whence
)
{
{
Context
*
c
=
h
->
priv_data
;
Context
*
c
=
h
->
priv_data
;
AVFifoBuffer
*
fifo
=
c
->
fifo
;
RingBuffer
*
ring
=
&
c
->
ring
;
int64_t
ret
;
int64_t
ret
;
int64_t
new_logical_pos
;
int64_t
new_logical_pos
;
int
fifo_size
;
int
fifo_size
;
int
fifo_size_of_read_back
;
if
(
whence
==
AVSEEK_SIZE
)
{
if
(
whence
==
AVSEEK_SIZE
)
{
av_log
(
h
,
AV_LOG_TRACE
,
"async_seek: AVSEEK_SIZE: %"
PRId64
"
\n
"
,
(
int64_t
)
c
->
logical_size
);
av_log
(
h
,
AV_LOG_TRACE
,
"async_seek: AVSEEK_SIZE: %"
PRId64
"
\n
"
,
(
int64_t
)
c
->
logical_size
);
...
@@ -332,17 +406,28 @@ static int64_t async_seek(URLContext *h, int64_t pos, int whence)
...
@@ -332,17 +406,28 @@ static int64_t async_seek(URLContext *h, int64_t pos, int whence)
if
(
new_logical_pos
<
0
)
if
(
new_logical_pos
<
0
)
return
AVERROR
(
EINVAL
);
return
AVERROR
(
EINVAL
);
fifo_size
=
av_fifo_size
(
fifo
);
fifo_size
=
ring_size
(
ring
);
fifo_size_of_read_back
=
ring_size_of_read_back
(
ring
);
if
(
new_logical_pos
==
c
->
logical_pos
)
{
if
(
new_logical_pos
==
c
->
logical_pos
)
{
/* current position */
/* current position */
return
c
->
logical_pos
;
return
c
->
logical_pos
;
}
else
if
((
new_logical_pos
>
c
->
logical_pos
)
&&
}
else
if
((
new_logical_pos
>
=
(
c
->
logical_pos
-
fifo_size_of_read_back
)
)
&&
(
new_logical_pos
<
(
c
->
logical_pos
+
fifo_size
+
SHORT_SEEK_THRESHOLD
)))
{
(
new_logical_pos
<
(
c
->
logical_pos
+
fifo_size
+
SHORT_SEEK_THRESHOLD
)))
{
int
pos_delta
=
(
int
)(
new_logical_pos
-
c
->
logical_pos
);
/* fast seek */
/* fast seek */
av_log
(
h
,
AV_LOG_TRACE
,
"async_seek: fask_seek %"
PRId64
" from %d dist:%d/%d
\n
"
,
av_log
(
h
,
AV_LOG_TRACE
,
"async_seek: fask_seek %"
PRId64
" from %d dist:%d/%d
\n
"
,
new_logical_pos
,
(
int
)
c
->
logical_pos
,
new_logical_pos
,
(
int
)
c
->
logical_pos
,
(
int
)(
new_logical_pos
-
c
->
logical_pos
),
fifo_size
);
(
int
)(
new_logical_pos
-
c
->
logical_pos
),
fifo_size
);
async_read_internal
(
h
,
NULL
,
(
int
)(
new_logical_pos
-
c
->
logical_pos
),
1
,
fifo_do_not_copy_func
);
if
(
pos_delta
>
0
)
{
// fast seek forwards
async_read_internal
(
h
,
NULL
,
pos_delta
,
1
,
fifo_do_not_copy_func
);
}
else
{
// fast seek backwards
ring_drain
(
ring
,
pos_delta
);
c
->
logical_pos
=
new_logical_pos
;
}
return
c
->
logical_pos
;
return
c
->
logical_pos
;
}
else
if
(
c
->
logical_size
<=
0
)
{
}
else
if
(
c
->
logical_size
<=
0
)
{
/* can not seek */
/* can not seek */
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment