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
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"
...
@@ -2467,6 +2467,7 @@ transcode_aac_example_deps="avcodec avformat avresample"
# libraries, in linking order
# libraries, in linking order
avcodec_deps
=
"avutil"
avcodec_deps
=
"avutil"
avcodec_select
=
"null_bsf"
avdevice_deps
=
"avformat avcodec avutil"
avdevice_deps
=
"avformat avcodec avutil"
avfilter_deps
=
"avutil"
avfilter_deps
=
"avutil"
avformat_deps
=
"avcodec avutil"
avformat_deps
=
"avcodec avutil"
...
...
libavcodec/avcodec.h
View file @
972c71e9
...
@@ -3243,6 +3243,12 @@ typedef struct AVCodec {
...
@@ -3243,6 +3243,12 @@ typedef struct AVCodec {
* See FF_CODEC_CAP_* in internal.h
* See FF_CODEC_CAP_* in internal.h
*/
*/
int
caps_internal
;
int
caps_internal
;
/**
* Decoding only, a comma-separated list of bitstream filters to apply to
* packets before decoding.
*/
const
char
*
bsfs
;
}
AVCodec
;
}
AVCodec
;
/**
/**
...
...
libavcodec/decode.c
View file @
972c71e9
...
@@ -154,6 +154,116 @@ static int unrefcount_frame(AVCodecInternal *avci, AVFrame *frame)
...
@@ -154,6 +154,116 @@ static int unrefcount_frame(AVCodecInternal *avci, AVFrame *frame)
return
0
;
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
)
int
ff_decode_get_packet
(
AVCodecContext
*
avctx
,
AVPacket
*
pkt
)
{
{
AVCodecInternal
*
avci
=
avctx
->
internal
;
AVCodecInternal
*
avci
=
avctx
->
internal
;
...
@@ -162,10 +272,11 @@ int ff_decode_get_packet(AVCodecContext *avctx, AVPacket *pkt)
...
@@ -162,10 +272,11 @@ int ff_decode_get_packet(AVCodecContext *avctx, AVPacket *pkt)
if
(
avci
->
draining
)
if
(
avci
->
draining
)
return
AVERROR_EOF
;
return
AVERROR_EOF
;
if
(
!
avci
->
buffer_pkt
->
data
&&
!
avci
->
buffer_pkt
->
side_data_elems
)
ret
=
bsfs_poll
(
avctx
,
pkt
);
return
AVERROR
(
EAGAIN
);
if
(
ret
==
AVERROR_EOF
)
avci
->
draining
=
1
;
av_packet_move_ref
(
pkt
,
avci
->
buffer_pkt
);
if
(
ret
<
0
)
return
ret
;
ret
=
extract_packet_props
(
avctx
->
internal
,
pkt
);
ret
=
extract_packet_props
(
avctx
->
internal
,
pkt
);
if
(
ret
<
0
)
if
(
ret
<
0
)
...
@@ -313,17 +424,23 @@ int attribute_align_arg avcodec_send_packet(AVCodecContext *avctx, const AVPacke
...
@@ -313,17 +424,23 @@ int attribute_align_arg avcodec_send_packet(AVCodecContext *avctx, const AVPacke
if
(
avctx
->
internal
->
draining
)
if
(
avctx
->
internal
->
draining
)
return
AVERROR_EOF
;
return
AVERROR_EOF
;
if
(
avci
->
buffer_pkt
->
data
||
avci
->
buffer_pkt
->
side_data_elems
)
ret
=
bsfs_init
(
avctx
);
return
AVERROR
(
EAGAIN
);
if
(
ret
<
0
)
return
ret
;
if
(
!
avpkt
||
!
avpkt
->
size
)
{
av_packet_unref
(
avci
->
buffer_pkt
);
avctx
->
internal
->
draining
=
1
;
if
(
avpkt
&&
(
avpkt
->
data
||
avpkt
->
side_data_elems
))
{
}
else
{
ret
=
av_packet_ref
(
avci
->
buffer_pkt
,
avpkt
);
ret
=
av_packet_ref
(
avci
->
buffer_pkt
,
avpkt
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
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
])
{
if
(
!
avci
->
buffer_frame
->
buf
[
0
])
{
ret
=
decode_receive_frame_internal
(
avctx
,
avci
->
buffer_frame
);
ret
=
decode_receive_frame_internal
(
avctx
,
avci
->
buffer_frame
);
if
(
ret
<
0
&&
ret
!=
AVERROR
(
EAGAIN
)
&&
ret
!=
AVERROR_EOF
)
if
(
ret
<
0
&&
ret
!=
AVERROR
(
EAGAIN
)
&&
ret
!=
AVERROR_EOF
)
...
@@ -343,6 +460,10 @@ int attribute_align_arg avcodec_receive_frame(AVCodecContext *avctx, AVFrame *fr
...
@@ -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
))
if
(
!
avcodec_is_open
(
avctx
)
||
!
av_codec_is_decoder
(
avctx
->
codec
))
return
AVERROR
(
EINVAL
);
return
AVERROR
(
EINVAL
);
ret
=
bsfs_init
(
avctx
);
if
(
ret
<
0
)
return
ret
;
if
(
avci
->
buffer_frame
->
buf
[
0
])
{
if
(
avci
->
buffer_frame
->
buf
[
0
])
{
av_frame_move_ref
(
frame
,
avci
->
buffer_frame
);
av_frame_move_ref
(
frame
,
avci
->
buffer_frame
);
}
else
{
}
else
{
...
@@ -415,13 +536,18 @@ static int compat_decode(AVCodecContext *avctx, AVFrame *frame,
...
@@ -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
;
break
;
}
}
finish:
finish:
if
(
ret
==
0
)
if
(
ret
==
0
)
{
ret
=
FFMIN
(
avci
->
compat_decode_consumed
,
pkt
->
size
);
/* 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_consumed
=
0
;
avci
->
compat_decode_partial_size
=
(
ret
>=
0
)
?
pkt
->
size
-
ret
:
0
;
avci
->
compat_decode_partial_size
=
(
ret
>=
0
)
?
pkt
->
size
-
ret
:
0
;
...
@@ -958,6 +1084,19 @@ void avcodec_flush_buffers(AVCodecContext *avctx)
...
@@ -958,6 +1084,19 @@ void avcodec_flush_buffers(AVCodecContext *avctx)
else
if
(
avctx
->
codec
->
flush
)
else
if
(
avctx
->
codec
->
flush
)
avctx
->
codec
->
flush
(
avctx
);
avctx
->
codec
->
flush
(
avctx
);
ff_decode_bsfs_uninit
(
avctx
);
if
(
!
avctx
->
refcounted_frames
)
if
(
!
avctx
->
refcounted_frames
)
av_frame_unref
(
avctx
->
internal
->
to_free
);
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 @@
...
@@ -32,4 +32,6 @@
*/
*/
int
ff_decode_get_packet
(
AVCodecContext
*
avctx
,
AVPacket
*
pkt
);
int
ff_decode_get_packet
(
AVCodecContext
*
avctx
,
AVPacket
*
pkt
);
void
ff_decode_bsfs_uninit
(
AVCodecContext
*
avctx
);
#endif
/* AVCODEC_DECODE_H */
#endif
/* AVCODEC_DECODE_H */
libavcodec/internal.h
View file @
972c71e9
...
@@ -99,6 +99,11 @@ typedef struct DecodeSimpleContext {
...
@@ -99,6 +99,11 @@ typedef struct DecodeSimpleContext {
AVFrame
*
out_frame
;
AVFrame
*
out_frame
;
}
DecodeSimpleContext
;
}
DecodeSimpleContext
;
typedef
struct
DecodeFilterContext
{
AVBSFContext
**
bsfs
;
int
nb_bsfs
;
}
DecodeFilterContext
;
typedef
struct
AVCodecInternal
{
typedef
struct
AVCodecInternal
{
/**
/**
* Whether the parent AVCodecContext is a copy of the context which had
* Whether the parent AVCodecContext is a copy of the context which had
...
@@ -136,6 +141,7 @@ typedef struct AVCodecInternal {
...
@@ -136,6 +141,7 @@ typedef struct AVCodecInternal {
void
*
thread_ctx
;
void
*
thread_ctx
;
DecodeSimpleContext
ds
;
DecodeSimpleContext
ds
;
DecodeFilterContext
filter
;
/**
/**
* Properties (timestamps+side data) extracted from the last packet passed
* Properties (timestamps+side data) extracted from the last packet passed
...
...
libavcodec/utils.c
View file @
972c71e9
...
@@ -40,6 +40,7 @@
...
@@ -40,6 +40,7 @@
#include "libavutil/samplefmt.h"
#include "libavutil/samplefmt.h"
#include "libavutil/dict.h"
#include "libavutil/dict.h"
#include "avcodec.h"
#include "avcodec.h"
#include "decode.h"
#include "libavutil/opt.h"
#include "libavutil/opt.h"
#include "me_cmp.h"
#include "me_cmp.h"
#include "mpegvideo.h"
#include "mpegvideo.h"
...
@@ -789,6 +790,8 @@ av_cold int avcodec_close(AVCodecContext *avctx)
...
@@ -789,6 +790,8 @@ av_cold int avcodec_close(AVCodecContext *avctx)
avctx
->
hwaccel
->
uninit
(
avctx
);
avctx
->
hwaccel
->
uninit
(
avctx
);
av_freep
(
&
avctx
->
internal
->
hwaccel_priv_data
);
av_freep
(
&
avctx
->
internal
->
hwaccel_priv_data
);
ff_decode_bsfs_uninit
(
avctx
);
av_freep
(
&
avctx
->
internal
);
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