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
972c71e9
Commit
972c71e9
authored
Nov 12, 2016
by
Anton Khirnov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
lavc: add support for filtering packets before decoding
parent
061a0c14
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
169 additions
and
12 deletions
+169
-12
configure
configure
+1
-0
avcodec.h
libavcodec/avcodec.h
+6
-0
decode.c
libavcodec/decode.c
+151
-12
decode.h
libavcodec/decode.h
+2
-0
internal.h
libavcodec/internal.h
+6
-0
utils.c
libavcodec/utils.c
+3
-0
No files found.
configure
View file @
972c71e9
...
...
@@ -2467,6 +2467,7 @@ transcode_aac_example_deps="avcodec avformat avresample"
# libraries, in linking order
avcodec_deps
=
"avutil"
avcodec_select
=
"null_bsf"
avdevice_deps
=
"avformat avcodec avutil"
avfilter_deps
=
"avutil"
avformat_deps
=
"avcodec avutil"
...
...
libavcodec/avcodec.h
View file @
972c71e9
...
...
@@ -3243,6 +3243,12 @@ typedef struct AVCodec {
* See FF_CODEC_CAP_* in internal.h
*/
int
caps_internal
;
/**
* Decoding only, a comma-separated list of bitstream filters to apply to
* packets before decoding.
*/
const
char
*
bsfs
;
}
AVCodec
;
/**
...
...
libavcodec/decode.c
View file @
972c71e9
...
...
@@ -154,6 +154,116 @@ static int unrefcount_frame(AVCodecInternal *avci, AVFrame *frame)
return
0
;
}
static
int
bsfs_init
(
AVCodecContext
*
avctx
)
{
AVCodecInternal
*
avci
=
avctx
->
internal
;
DecodeFilterContext
*
s
=
&
avci
->
filter
;
const
char
*
bsfs_str
;
int
ret
;
if
(
s
->
nb_bsfs
)
return
0
;
bsfs_str
=
avctx
->
codec
->
bsfs
?
avctx
->
codec
->
bsfs
:
"null"
;
while
(
bsfs_str
&&
*
bsfs_str
)
{
AVBSFContext
**
tmp
;
const
AVBitStreamFilter
*
filter
;
char
*
bsf
;
bsf
=
av_get_token
(
&
bsfs_str
,
","
);
if
(
!
bsf
)
{
ret
=
AVERROR
(
ENOMEM
);
goto
fail
;
}
filter
=
av_bsf_get_by_name
(
bsf
);
if
(
!
filter
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"A non-existing bitstream filter %s "
"requested by a decoder. This is a bug, please report it.
\n
"
,
bsf
);
ret
=
AVERROR_BUG
;
av_freep
(
&
bsf
);
goto
fail
;
}
av_freep
(
&
bsf
);
tmp
=
av_realloc_array
(
s
->
bsfs
,
s
->
nb_bsfs
+
1
,
sizeof
(
*
s
->
bsfs
));
if
(
!
tmp
)
{
ret
=
AVERROR
(
ENOMEM
);
goto
fail
;
}
s
->
bsfs
=
tmp
;
s
->
nb_bsfs
++
;
ret
=
av_bsf_alloc
(
filter
,
&
s
->
bsfs
[
s
->
nb_bsfs
-
1
]);
if
(
ret
<
0
)
goto
fail
;
if
(
s
->
nb_bsfs
==
1
)
{
/* We do not currently have an API for passing the input timebase into decoders,
* but no filters used here should actually need it.
* So we make up some plausible-looking number (the MPEG 90kHz timebase) */
s
->
bsfs
[
s
->
nb_bsfs
-
1
]
->
time_base_in
=
(
AVRational
){
1
,
90000
};
ret
=
avcodec_parameters_from_context
(
s
->
bsfs
[
s
->
nb_bsfs
-
1
]
->
par_in
,
avctx
);
}
else
{
s
->
bsfs
[
s
->
nb_bsfs
-
1
]
->
time_base_in
=
s
->
bsfs
[
s
->
nb_bsfs
-
2
]
->
time_base_out
;
ret
=
avcodec_parameters_copy
(
s
->
bsfs
[
s
->
nb_bsfs
-
1
]
->
par_in
,
s
->
bsfs
[
s
->
nb_bsfs
-
2
]
->
par_out
);
}
if
(
ret
<
0
)
goto
fail
;
ret
=
av_bsf_init
(
s
->
bsfs
[
s
->
nb_bsfs
-
1
]);
if
(
ret
<
0
)
goto
fail
;
}
return
0
;
fail:
ff_decode_bsfs_uninit
(
avctx
);
return
ret
;
}
/* try to get one output packet from the filter chain */
static
int
bsfs_poll
(
AVCodecContext
*
avctx
,
AVPacket
*
pkt
)
{
DecodeFilterContext
*
s
=
&
avctx
->
internal
->
filter
;
int
idx
,
ret
;
/* start with the last filter in the chain */
idx
=
s
->
nb_bsfs
-
1
;
while
(
idx
>=
0
)
{
/* request a packet from the currently selected filter */
ret
=
av_bsf_receive_packet
(
s
->
bsfs
[
idx
],
pkt
);
if
(
ret
==
AVERROR
(
EAGAIN
))
{
/* no packets available, try the next filter up the chain */
ret
=
0
;
idx
--
;
continue
;
}
else
if
(
ret
<
0
&&
ret
!=
AVERROR_EOF
)
{
return
ret
;
}
/* got a packet or EOF -- pass it to the caller or to the next filter
* down the chain */
if
(
idx
==
s
->
nb_bsfs
-
1
)
{
return
ret
;
}
else
{
idx
++
;
ret
=
av_bsf_send_packet
(
s
->
bsfs
[
idx
],
ret
<
0
?
NULL
:
pkt
);
if
(
ret
<
0
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"Error pre-processing a packet before decoding
\n
"
);
av_packet_unref
(
pkt
);
return
ret
;
}
}
}
return
AVERROR
(
EAGAIN
);
}
int
ff_decode_get_packet
(
AVCodecContext
*
avctx
,
AVPacket
*
pkt
)
{
AVCodecInternal
*
avci
=
avctx
->
internal
;
...
...
@@ -162,10 +272,11 @@ int ff_decode_get_packet(AVCodecContext *avctx, AVPacket *pkt)
if
(
avci
->
draining
)
return
AVERROR_EOF
;
if
(
!
avci
->
buffer_pkt
->
data
&&
!
avci
->
buffer_pkt
->
side_data_elems
)
return
AVERROR
(
EAGAIN
);
av_packet_move_ref
(
pkt
,
avci
->
buffer_pkt
);
ret
=
bsfs_poll
(
avctx
,
pkt
);
if
(
ret
==
AVERROR_EOF
)
avci
->
draining
=
1
;
if
(
ret
<
0
)
return
ret
;
ret
=
extract_packet_props
(
avctx
->
internal
,
pkt
);
if
(
ret
<
0
)
...
...
@@ -313,17 +424,23 @@ int attribute_align_arg avcodec_send_packet(AVCodecContext *avctx, const AVPacke
if
(
avctx
->
internal
->
draining
)
return
AVERROR_EOF
;
if
(
avci
->
buffer_pkt
->
data
||
avci
->
buffer_pkt
->
side_data_elems
)
return
AVERROR
(
EAGAIN
);
ret
=
bsfs_init
(
avctx
);
if
(
ret
<
0
)
return
ret
;
if
(
!
avpkt
||
!
avpkt
->
size
)
{
avctx
->
internal
->
draining
=
1
;
}
else
{
av_packet_unref
(
avci
->
buffer_pkt
);
if
(
avpkt
&&
(
avpkt
->
data
||
avpkt
->
side_data_elems
))
{
ret
=
av_packet_ref
(
avci
->
buffer_pkt
,
avpkt
);
if
(
ret
<
0
)
return
ret
;
}
ret
=
av_bsf_send_packet
(
avci
->
filter
.
bsfs
[
0
],
avci
->
buffer_pkt
);
if
(
ret
<
0
)
{
av_packet_unref
(
avci
->
buffer_pkt
);
return
ret
;
}
if
(
!
avci
->
buffer_frame
->
buf
[
0
])
{
ret
=
decode_receive_frame_internal
(
avctx
,
avci
->
buffer_frame
);
if
(
ret
<
0
&&
ret
!=
AVERROR
(
EAGAIN
)
&&
ret
!=
AVERROR_EOF
)
...
...
@@ -343,6 +460,10 @@ int attribute_align_arg avcodec_receive_frame(AVCodecContext *avctx, AVFrame *fr
if
(
!
avcodec_is_open
(
avctx
)
||
!
av_codec_is_decoder
(
avctx
->
codec
))
return
AVERROR
(
EINVAL
);
ret
=
bsfs_init
(
avctx
);
if
(
ret
<
0
)
return
ret
;
if
(
avci
->
buffer_frame
->
buf
[
0
])
{
av_frame_move_ref
(
frame
,
avci
->
buffer_frame
);
}
else
{
...
...
@@ -415,13 +536,18 @@ static int compat_decode(AVCodecContext *avctx, AVFrame *frame,
}
}
if
(
avci
->
draining
||
avci
->
compat_decode_consumed
<
pkt
->
size
)
if
(
avci
->
draining
||
(
!
avctx
->
codec
->
bsfs
&&
avci
->
compat_decode_consumed
<
pkt
->
size
)
)
break
;
}
finish:
if
(
ret
==
0
)
ret
=
FFMIN
(
avci
->
compat_decode_consumed
,
pkt
->
size
);
if
(
ret
==
0
)
{
/* if there are any bsfs then assume full packet is always consumed */
if
(
avctx
->
codec
->
bsfs
)
ret
=
pkt
->
size
;
else
ret
=
FFMIN
(
avci
->
compat_decode_consumed
,
pkt
->
size
);
}
avci
->
compat_decode_consumed
=
0
;
avci
->
compat_decode_partial_size
=
(
ret
>=
0
)
?
pkt
->
size
-
ret
:
0
;
...
...
@@ -958,6 +1084,19 @@ void avcodec_flush_buffers(AVCodecContext *avctx)
else
if
(
avctx
->
codec
->
flush
)
avctx
->
codec
->
flush
(
avctx
);
ff_decode_bsfs_uninit
(
avctx
);
if
(
!
avctx
->
refcounted_frames
)
av_frame_unref
(
avctx
->
internal
->
to_free
);
}
void
ff_decode_bsfs_uninit
(
AVCodecContext
*
avctx
)
{
DecodeFilterContext
*
s
=
&
avctx
->
internal
->
filter
;
int
i
;
for
(
i
=
0
;
i
<
s
->
nb_bsfs
;
i
++
)
av_bsf_free
(
&
s
->
bsfs
[
i
]);
av_freep
(
&
s
->
bsfs
);
s
->
nb_bsfs
=
0
;
}
libavcodec/decode.h
View file @
972c71e9
...
...
@@ -32,4 +32,6 @@
*/
int
ff_decode_get_packet
(
AVCodecContext
*
avctx
,
AVPacket
*
pkt
);
void
ff_decode_bsfs_uninit
(
AVCodecContext
*
avctx
);
#endif
/* AVCODEC_DECODE_H */
libavcodec/internal.h
View file @
972c71e9
...
...
@@ -99,6 +99,11 @@ typedef struct DecodeSimpleContext {
AVFrame
*
out_frame
;
}
DecodeSimpleContext
;
typedef
struct
DecodeFilterContext
{
AVBSFContext
**
bsfs
;
int
nb_bsfs
;
}
DecodeFilterContext
;
typedef
struct
AVCodecInternal
{
/**
* Whether the parent AVCodecContext is a copy of the context which had
...
...
@@ -136,6 +141,7 @@ typedef struct AVCodecInternal {
void
*
thread_ctx
;
DecodeSimpleContext
ds
;
DecodeFilterContext
filter
;
/**
* Properties (timestamps+side data) extracted from the last packet passed
...
...
libavcodec/utils.c
View file @
972c71e9
...
...
@@ -40,6 +40,7 @@
#include "libavutil/samplefmt.h"
#include "libavutil/dict.h"
#include "avcodec.h"
#include "decode.h"
#include "libavutil/opt.h"
#include "me_cmp.h"
#include "mpegvideo.h"
...
...
@@ -789,6 +790,8 @@ av_cold int avcodec_close(AVCodecContext *avctx)
avctx
->
hwaccel
->
uninit
(
avctx
);
av_freep
(
&
avctx
->
internal
->
hwaccel_priv_data
);
ff_decode_bsfs_uninit
(
avctx
);
av_freep
(
&
avctx
->
internal
);
}
...
...
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