Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
F
ffmpeg
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
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
ffmpeg
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 @@
/**
* @TODO
* support timeout
* support backward short seek
* support work with concatdec, hls
*/
...
...
@@ -43,8 +42,17 @@
#endif
#define BUFFER_CAPACITY (4 * 1024 * 1024)
#define READ_BACK_CAPACITY (4 * 1024 * 1024)
#define SHORT_SEEK_THRESHOLD (256 * 1024)
typedef
struct
RingBuffer
{
AVFifoBuffer
*
fifo
;
int
read_back_capacity
;
int
read_pos
;
}
RingBuffer
;
typedef
struct
Context
{
AVClass
*
class
;
URLContext
*
inner
;
...
...
@@ -61,7 +69,7 @@ typedef struct Context {
int64_t
logical_pos
;
int64_t
logical_size
;
AVFifoBuffer
*
fifo
;
RingBuffer
ring
;
pthread_cond_t
cond_wakeup_main
;
pthread_cond_t
cond_wakeup_background
;
...
...
@@ -72,6 +80,73 @@ typedef struct Context {
AVIOInterruptCB
interrupt_callback
;
}
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
)
{
URLContext
*
h
=
arg
;
...
...
@@ -102,7 +177,7 @@ static void *async_buffer_task(void *arg)
{
URLContext
*
h
=
arg
;
Context
*
c
=
h
->
priv_data
;
AVFifoBuffer
*
fifo
=
c
->
fifo
;
RingBuffer
*
ring
=
&
c
->
ring
;
int
ret
=
0
;
int64_t
seek_ret
;
...
...
@@ -132,14 +207,14 @@ static void *async_buffer_task(void *arg)
c
->
seek_ret
=
seek_ret
;
c
->
seek_request
=
0
;
av_fifo_reset
(
fifo
);
ring_reset
(
ring
);
pthread_cond_signal
(
&
c
->
cond_wakeup_main
);
pthread_mutex_unlock
(
&
c
->
mutex
);
continue
;
}
fifo_space
=
av_fifo_space
(
fifo
);
fifo_space
=
ring_space
(
ring
);
if
(
c
->
io_eof_reached
||
fifo_space
<=
0
)
{
pthread_cond_signal
(
&
c
->
cond_wakeup_main
);
pthread_cond_wait
(
&
c
->
cond_wakeup_background
,
&
c
->
mutex
);
...
...
@@ -149,7 +224,7 @@ static void *async_buffer_task(void *arg)
pthread_mutex_unlock
(
&
c
->
mutex
);
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
);
if
(
ret
<=
0
)
{
...
...
@@ -173,11 +248,9 @@ static int async_open(URLContext *h, const char *arg, int flags, AVDictionary **
av_strstart
(
arg
,
"async:"
,
&
arg
);
c
->
fifo
=
av_fifo_alloc
(
BUFFER_CAPACITY
);
if
(
!
c
->
fifo
)
{
ret
=
AVERROR
(
ENOMEM
);
ret
=
ring_init
(
&
c
->
ring
,
BUFFER_CAPACITY
,
READ_BACK_CAPACITY
);
if
(
ret
<
0
)
goto
fifo_fail
;
}
/* wrap interrupt callback */
c
->
interrupt_callback
=
h
->
interrupt_callback
;
...
...
@@ -225,7 +298,7 @@ cond_wakeup_main_fail:
mutex_fail:
ffurl_close
(
c
->
inner
);
url_fail:
av_fifo_freep
(
&
c
->
fifo
);
ring_destroy
(
&
c
->
ring
);
fifo_fail:
return
ret
;
}
...
...
@@ -248,7 +321,7 @@ static int async_close(URLContext *h)
pthread_cond_destroy
(
&
c
->
cond_wakeup_main
);
pthread_mutex_destroy
(
&
c
->
mutex
);
ffurl_close
(
c
->
inner
);
av_fifo_freep
(
&
c
->
fifo
);
ring_destroy
(
&
c
->
ring
);
return
0
;
}
...
...
@@ -257,7 +330,7 @@ static int async_read_internal(URLContext *h, void *dest, int size, int read_com
void
(
*
func
)(
void
*
,
void
*
,
int
))
{
Context
*
c
=
h
->
priv_data
;
AVFifoBuffer
*
fifo
=
c
->
fifo
;
RingBuffer
*
ring
=
&
c
->
ring
;
int
to_read
=
size
;
int
ret
=
0
;
...
...
@@ -269,10 +342,10 @@ static int async_read_internal(URLContext *h, void *dest, int size, int read_com
ret
=
AVERROR_EXIT
;
break
;
}
fifo_size
=
av_fifo_size
(
fifo
);
fifo_size
=
ring_size
(
ring
);
to_copy
=
FFMIN
(
to_read
,
fifo_size
);
if
(
to_copy
>
0
)
{
av_fifo_generic_read
(
fifo
,
dest
,
to_copy
,
func
);
ring_generic_read
(
ring
,
dest
,
to_copy
,
func
);
if
(
!
func
)
dest
=
(
uint8_t
*
)
dest
+
to_copy
;
c
->
logical_pos
+=
to_copy
;
...
...
@@ -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
)
{
Context
*
c
=
h
->
priv_data
;
AVFifoBuffer
*
fifo
=
c
->
fifo
;
RingBuffer
*
ring
=
&
c
->
ring
;
int64_t
ret
;
int64_t
new_logical_pos
;
int
fifo_size
;
int
fifo_size_of_read_back
;
if
(
whence
==
AVSEEK_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)
if
(
new_logical_pos
<
0
)
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
)
{
/* current position */
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
)))
{
int
pos_delta
=
(
int
)(
new_logical_pos
-
c
->
logical_pos
);
/* fast seek */
av_log
(
h
,
AV_LOG_TRACE
,
"async_seek: fask_seek %"
PRId64
" from %d dist:%d/%d
\n
"
,
new_logical_pos
,
(
int
)
c
->
logical_pos
,
(
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
;
}
else
if
(
c
->
logical_size
<=
0
)
{
/* 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