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
98c97994
Commit
98c97994
authored
Mar 29, 2016
by
Anton Khirnov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
h264: decouple extradata parsing from the decoder
This will allow decoupling the parser from the decoder.
parent
728d90a0
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
159 additions
and
130 deletions
+159
-130
h264.c
libavcodec/h264.c
+5
-128
h264.h
libavcodec/h264.h
+0
-1
h264_parse.c
libavcodec/h264_parse.c
+144
-0
h264_parse.h
libavcodec/h264_parse.h
+5
-0
h264_parser.c
libavcodec/h264_parser.c
+5
-1
No files found.
libavcodec/h264.c
View file @
98c97994
...
@@ -278,117 +278,6 @@ fail:
...
@@ -278,117 +278,6 @@ fail:
return
AVERROR
(
ENOMEM
);
// ff_h264_free_tables will clean up for us
return
AVERROR
(
ENOMEM
);
// ff_h264_free_tables will clean up for us
}
}
static
int
decode_nal_units
(
H264Context
*
h
,
const
uint8_t
*
buf
,
int
buf_size
,
int
parse_extradata
);
/* There are (invalid) samples in the wild with mp4-style extradata, where the
* parameter sets are stored unescaped (i.e. as RBSP).
* This function catches the parameter set decoding failure and tries again
* after escaping it */
static
int
decode_extradata_ps_mp4
(
H264Context
*
h
,
const
uint8_t
*
buf
,
int
buf_size
)
{
int
ret
;
ret
=
decode_nal_units
(
h
,
buf
,
buf_size
,
1
);
if
(
ret
<
0
&&
!
(
h
->
avctx
->
err_recognition
&
AV_EF_EXPLODE
))
{
GetByteContext
gbc
;
PutByteContext
pbc
;
uint8_t
*
escaped_buf
;
int
escaped_buf_size
;
av_log
(
h
->
avctx
,
AV_LOG_WARNING
,
"SPS decoding failure, trying again after escaping the NAL
\n
"
);
if
(
buf_size
/
2
>=
(
INT16_MAX
-
AV_INPUT_BUFFER_PADDING_SIZE
)
/
3
)
return
AVERROR
(
ERANGE
);
escaped_buf_size
=
buf_size
*
3
/
2
+
AV_INPUT_BUFFER_PADDING_SIZE
;
escaped_buf
=
av_mallocz
(
escaped_buf_size
);
if
(
!
escaped_buf
)
return
AVERROR
(
ENOMEM
);
bytestream2_init
(
&
gbc
,
buf
,
buf_size
);
bytestream2_init_writer
(
&
pbc
,
escaped_buf
,
escaped_buf_size
);
while
(
bytestream2_get_bytes_left
(
&
gbc
))
{
if
(
bytestream2_get_bytes_left
(
&
gbc
)
>=
3
&&
bytestream2_peek_be24
(
&
gbc
)
<=
3
)
{
bytestream2_put_be24
(
&
pbc
,
3
);
bytestream2_skip
(
&
gbc
,
2
);
}
else
bytestream2_put_byte
(
&
pbc
,
bytestream2_get_byte
(
&
gbc
));
}
escaped_buf_size
=
bytestream2_tell_p
(
&
pbc
);
AV_WB16
(
escaped_buf
,
escaped_buf_size
-
2
);
ret
=
decode_nal_units
(
h
,
escaped_buf
,
escaped_buf_size
,
1
);
av_freep
(
&
escaped_buf
);
if
(
ret
<
0
)
return
ret
;
}
return
0
;
}
int
ff_h264_decode_extradata
(
H264Context
*
h
)
{
AVCodecContext
*
avctx
=
h
->
avctx
;
int
ret
;
if
(
avctx
->
extradata
[
0
]
==
1
)
{
int
i
,
cnt
,
nalsize
;
unsigned
char
*
p
=
avctx
->
extradata
;
h
->
is_avc
=
1
;
if
(
avctx
->
extradata_size
<
7
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"avcC %d too short
\n
"
,
avctx
->
extradata_size
);
return
AVERROR_INVALIDDATA
;
}
/* sps and pps in the avcC always have length coded with 2 bytes,
* so put a fake nal_length_size = 2 while parsing them */
h
->
nal_length_size
=
2
;
// Decode sps from avcC
cnt
=
*
(
p
+
5
)
&
0x1f
;
// Number of sps
p
+=
6
;
for
(
i
=
0
;
i
<
cnt
;
i
++
)
{
nalsize
=
AV_RB16
(
p
)
+
2
;
if
(
p
-
avctx
->
extradata
+
nalsize
>
avctx
->
extradata_size
)
return
AVERROR_INVALIDDATA
;
ret
=
decode_extradata_ps_mp4
(
h
,
p
,
nalsize
);
if
(
ret
<
0
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"Decoding sps %d from avcC failed
\n
"
,
i
);
return
ret
;
}
p
+=
nalsize
;
}
// Decode pps from avcC
cnt
=
*
(
p
++
);
// Number of pps
for
(
i
=
0
;
i
<
cnt
;
i
++
)
{
nalsize
=
AV_RB16
(
p
)
+
2
;
if
(
p
-
avctx
->
extradata
+
nalsize
>
avctx
->
extradata_size
)
return
AVERROR_INVALIDDATA
;
ret
=
decode_extradata_ps_mp4
(
h
,
p
,
nalsize
);
if
(
ret
<
0
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"Decoding pps %d from avcC failed
\n
"
,
i
);
return
ret
;
}
p
+=
nalsize
;
}
// Store right nal length size that will be used to parse all other nals
h
->
nal_length_size
=
(
avctx
->
extradata
[
4
]
&
0x03
)
+
1
;
}
else
{
h
->
is_avc
=
0
;
ret
=
decode_nal_units
(
h
,
avctx
->
extradata
,
avctx
->
extradata_size
,
1
);
if
(
ret
<
0
)
return
ret
;
}
return
0
;
}
static
int
h264_init_context
(
AVCodecContext
*
avctx
,
H264Context
*
h
)
static
int
h264_init_context
(
AVCodecContext
*
avctx
,
H264Context
*
h
)
{
{
int
i
;
int
i
;
...
@@ -462,7 +351,9 @@ av_cold int ff_h264_decode_init(AVCodecContext *avctx)
...
@@ -462,7 +351,9 @@ av_cold int ff_h264_decode_init(AVCodecContext *avctx)
}
}
if
(
avctx
->
extradata_size
>
0
&&
avctx
->
extradata
)
{
if
(
avctx
->
extradata_size
>
0
&&
avctx
->
extradata
)
{
ret
=
ff_h264_decode_extradata
(
h
);
ret
=
ff_h264_decode_extradata
(
avctx
->
extradata
,
avctx
->
extradata_size
,
&
h
->
ps
,
&
h
->
is_avc
,
&
h
->
nal_length_size
,
avctx
->
err_recognition
,
avctx
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
ff_h264_free_context
(
h
);
ff_h264_free_context
(
h
);
return
ret
;
return
ret
;
...
@@ -919,8 +810,7 @@ static int get_last_needed_nal(H264Context *h)
...
@@ -919,8 +810,7 @@ static int get_last_needed_nal(H264Context *h)
return
nals_needed
;
return
nals_needed
;
}
}
static
int
decode_nal_units
(
H264Context
*
h
,
const
uint8_t
*
buf
,
int
buf_size
,
static
int
decode_nal_units
(
H264Context
*
h
,
const
uint8_t
*
buf
,
int
buf_size
)
int
parse_extradata
)
{
{
AVCodecContext
*
const
avctx
=
h
->
avctx
;
AVCodecContext
*
const
avctx
=
h
->
avctx
;
unsigned
context_count
=
0
;
unsigned
context_count
=
0
;
...
@@ -956,19 +846,6 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size,
...
@@ -956,19 +846,6 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size,
continue
;
continue
;
again:
again:
/* Ignore every NAL unit type except PPS and SPS during extradata
* parsing. Decoding slices is not possible in codec init
* with frame-mt */
if
(
parse_extradata
&&
HAVE_THREADS
&&
(
h
->
avctx
->
active_thread_type
&
FF_THREAD_FRAME
)
&&
(
nal
->
type
!=
NAL_PPS
&&
nal
->
type
!=
NAL_SPS
))
{
if
(
nal
->
type
<
NAL_AUD
||
nal
->
type
>
NAL_AUXILIARY_SLICE
)
av_log
(
avctx
,
AV_LOG_INFO
,
"Ignoring NAL unit %d during extradata parsing
\n
"
,
nal
->
type
);
nal
->
type
=
NAL_FF_IGNORE
;
}
// FIXME these should stop being context-global variables
// FIXME these should stop being context-global variables
h
->
nal_ref_idc
=
nal
->
ref_idc
;
h
->
nal_ref_idc
=
nal
->
ref_idc
;
h
->
nal_unit_type
=
nal
->
type
;
h
->
nal_unit_type
=
nal
->
type
;
...
@@ -1183,7 +1060,7 @@ out:
...
@@ -1183,7 +1060,7 @@ out:
return
buf_index
;
return
buf_index
;
}
}
buf_index
=
decode_nal_units
(
h
,
buf
,
buf_size
,
0
);
buf_index
=
decode_nal_units
(
h
,
buf
,
buf_size
);
if
(
buf_index
<
0
)
if
(
buf_index
<
0
)
return
AVERROR_INVALIDDATA
;
return
AVERROR_INVALIDDATA
;
...
...
libavcodec/h264.h
View file @
98c97994
...
@@ -706,7 +706,6 @@ int ff_h264_decode_ref_pic_marking(H264Context *h, GetBitContext *gb,
...
@@ -706,7 +706,6 @@ int ff_h264_decode_ref_pic_marking(H264Context *h, GetBitContext *gb,
int
ff_generate_sliding_window_mmcos
(
H264Context
*
h
,
int
first_slice
);
int
ff_generate_sliding_window_mmcos
(
H264Context
*
h
,
int
first_slice
);
void
ff_h264_hl_decode_mb
(
const
H264Context
*
h
,
H264SliceContext
*
sl
);
void
ff_h264_hl_decode_mb
(
const
H264Context
*
h
,
H264SliceContext
*
sl
);
int
ff_h264_decode_extradata
(
H264Context
*
h
);
int
ff_h264_decode_init
(
AVCodecContext
*
avctx
);
int
ff_h264_decode_init
(
AVCodecContext
*
avctx
);
void
ff_h264_decode_init_vlc
(
void
);
void
ff_h264_decode_init_vlc
(
void
);
...
...
libavcodec/h264_parse.c
View file @
98c97994
...
@@ -16,6 +16,7 @@
...
@@ -16,6 +16,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
*/
#include "bytestream.h"
#include "get_bits.h"
#include "get_bits.h"
#include "golomb.h"
#include "golomb.h"
#include "h264.h"
#include "h264.h"
...
@@ -305,3 +306,146 @@ int ff_h264_init_poc(int pic_field_poc[2], int *pic_poc,
...
@@ -305,3 +306,146 @@ int ff_h264_init_poc(int pic_field_poc[2], int *pic_poc,
return
0
;
return
0
;
}
}
static
int
decode_extradata_ps
(
const
uint8_t
*
data
,
int
size
,
H264ParamSets
*
ps
,
int
is_avc
,
void
*
logctx
)
{
H2645Packet
pkt
=
{
0
};
int
i
,
ret
=
0
;
ret
=
ff_h2645_packet_split
(
&
pkt
,
data
,
size
,
logctx
,
is_avc
,
2
,
AV_CODEC_ID_H264
);
if
(
ret
<
0
)
goto
fail
;
for
(
i
=
0
;
i
<
pkt
.
nb_nals
;
i
++
)
{
H2645NAL
*
nal
=
&
pkt
.
nals
[
i
];
switch
(
nal
->
type
)
{
case
NAL_SPS
:
ret
=
ff_h264_decode_seq_parameter_set
(
&
nal
->
gb
,
logctx
,
ps
);
if
(
ret
<
0
)
goto
fail
;
break
;
case
NAL_PPS
:
ret
=
ff_h264_decode_picture_parameter_set
(
&
nal
->
gb
,
logctx
,
ps
,
nal
->
size_bits
);
if
(
ret
<
0
)
goto
fail
;
break
;
default:
av_log
(
logctx
,
AV_LOG_VERBOSE
,
"Ignoring NAL type %d in extradata
\n
"
,
nal
->
type
);
break
;
}
}
fail:
ff_h2645_packet_uninit
(
&
pkt
);
return
ret
;
}
/* There are (invalid) samples in the wild with mp4-style extradata, where the
* parameter sets are stored unescaped (i.e. as RBSP).
* This function catches the parameter set decoding failure and tries again
* after escaping it */
static
int
decode_extradata_ps_mp4
(
const
uint8_t
*
buf
,
int
buf_size
,
H264ParamSets
*
ps
,
int
err_recognition
,
void
*
logctx
)
{
int
ret
;
ret
=
decode_extradata_ps
(
buf
,
buf_size
,
ps
,
1
,
logctx
);
if
(
ret
<
0
&&
!
(
err_recognition
&
AV_EF_EXPLODE
))
{
GetByteContext
gbc
;
PutByteContext
pbc
;
uint8_t
*
escaped_buf
;
int
escaped_buf_size
;
av_log
(
logctx
,
AV_LOG_WARNING
,
"SPS decoding failure, trying again after escaping the NAL
\n
"
);
if
(
buf_size
/
2
>=
(
INT16_MAX
-
AV_INPUT_BUFFER_PADDING_SIZE
)
/
3
)
return
AVERROR
(
ERANGE
);
escaped_buf_size
=
buf_size
*
3
/
2
+
AV_INPUT_BUFFER_PADDING_SIZE
;
escaped_buf
=
av_mallocz
(
escaped_buf_size
);
if
(
!
escaped_buf
)
return
AVERROR
(
ENOMEM
);
bytestream2_init
(
&
gbc
,
buf
,
buf_size
);
bytestream2_init_writer
(
&
pbc
,
escaped_buf
,
escaped_buf_size
);
while
(
bytestream2_get_bytes_left
(
&
gbc
))
{
if
(
bytestream2_get_bytes_left
(
&
gbc
)
>=
3
&&
bytestream2_peek_be24
(
&
gbc
)
<=
3
)
{
bytestream2_put_be24
(
&
pbc
,
3
);
bytestream2_skip
(
&
gbc
,
2
);
}
else
bytestream2_put_byte
(
&
pbc
,
bytestream2_get_byte
(
&
gbc
));
}
escaped_buf_size
=
bytestream2_tell_p
(
&
pbc
);
AV_WB16
(
escaped_buf
,
escaped_buf_size
-
2
);
ret
=
decode_extradata_ps
(
escaped_buf
,
escaped_buf_size
,
ps
,
1
,
logctx
);
av_freep
(
&
escaped_buf
);
if
(
ret
<
0
)
return
ret
;
}
return
0
;
}
int
ff_h264_decode_extradata
(
const
uint8_t
*
data
,
int
size
,
H264ParamSets
*
ps
,
int
*
is_avc
,
int
*
nal_length_size
,
int
err_recognition
,
void
*
logctx
)
{
int
ret
;
if
(
data
[
0
]
==
1
)
{
int
i
,
cnt
,
nalsize
;
const
uint8_t
*
p
=
data
;
*
is_avc
=
1
;
if
(
size
<
7
)
{
av_log
(
logctx
,
AV_LOG_ERROR
,
"avcC %d too short
\n
"
,
size
);
return
AVERROR_INVALIDDATA
;
}
// Decode sps from avcC
cnt
=
*
(
p
+
5
)
&
0x1f
;
// Number of sps
p
+=
6
;
for
(
i
=
0
;
i
<
cnt
;
i
++
)
{
nalsize
=
AV_RB16
(
p
)
+
2
;
if
(
p
-
data
+
nalsize
>
size
)
return
AVERROR_INVALIDDATA
;
ret
=
decode_extradata_ps_mp4
(
p
,
nalsize
,
ps
,
err_recognition
,
logctx
);
if
(
ret
<
0
)
{
av_log
(
logctx
,
AV_LOG_ERROR
,
"Decoding sps %d from avcC failed
\n
"
,
i
);
return
ret
;
}
p
+=
nalsize
;
}
// Decode pps from avcC
cnt
=
*
(
p
++
);
// Number of pps
for
(
i
=
0
;
i
<
cnt
;
i
++
)
{
nalsize
=
AV_RB16
(
p
)
+
2
;
if
(
p
-
data
+
nalsize
>
size
)
return
AVERROR_INVALIDDATA
;
ret
=
decode_extradata_ps_mp4
(
p
,
nalsize
,
ps
,
err_recognition
,
logctx
);
if
(
ret
<
0
)
{
av_log
(
logctx
,
AV_LOG_ERROR
,
"Decoding pps %d from avcC failed
\n
"
,
i
);
return
ret
;
}
p
+=
nalsize
;
}
// Store right nal length size that will be used to parse all other nals
*
nal_length_size
=
(
data
[
4
]
&
0x03
)
+
1
;
}
else
{
*
is_avc
=
0
;
ret
=
decode_extradata_ps
(
data
,
size
,
ps
,
0
,
logctx
);
if
(
ret
<
0
)
return
ret
;
}
return
0
;
}
libavcodec/h264_parse.h
View file @
98c97994
...
@@ -54,6 +54,7 @@ typedef struct H264POCContext {
...
@@ -54,6 +54,7 @@ typedef struct H264POCContext {
struct
SPS
;
struct
SPS
;
struct
PPS
;
struct
PPS
;
struct
H264ParamSets
;
int
ff_h264_pred_weight_table
(
GetBitContext
*
gb
,
const
struct
SPS
*
sps
,
int
ff_h264_pred_weight_table
(
GetBitContext
*
gb
,
const
struct
SPS
*
sps
,
const
int
*
ref_count
,
int
slice_type_nos
,
const
int
*
ref_count
,
int
slice_type_nos
,
...
@@ -82,4 +83,8 @@ int ff_h264_init_poc(int pic_field_poc[2], int *pic_poc,
...
@@ -82,4 +83,8 @@ int ff_h264_init_poc(int pic_field_poc[2], int *pic_poc,
const
struct
SPS
*
sps
,
H264POCContext
*
poc
,
const
struct
SPS
*
sps
,
H264POCContext
*
poc
,
int
picture_structure
,
int
nal_ref_idc
);
int
picture_structure
,
int
nal_ref_idc
);
int
ff_h264_decode_extradata
(
const
uint8_t
*
data
,
int
size
,
struct
H264ParamSets
*
ps
,
int
*
is_avc
,
int
*
nal_length_size
,
int
err_recognition
,
void
*
logctx
);
#endif
/* AVCODEC_H264_PARSE_H */
#endif
/* AVCODEC_H264_PARSE_H */
libavcodec/h264_parser.c
View file @
98c97994
...
@@ -50,6 +50,8 @@ typedef struct H264ParseContext {
...
@@ -50,6 +50,8 @@ typedef struct H264ParseContext {
H264DSPContext
h264dsp
;
H264DSPContext
h264dsp
;
H264POCContext
poc
;
H264POCContext
poc
;
H264SEIContext
sei
;
H264SEIContext
sei
;
int
is_avc
;
int
nal_length_size
;
int
got_first
;
int
got_first
;
}
H264ParseContext
;
}
H264ParseContext
;
...
@@ -500,7 +502,9 @@ static int h264_parse(AVCodecParserContext *s,
...
@@ -500,7 +502,9 @@ static int h264_parse(AVCodecParserContext *s,
// NB: estimate_timings_from_pts behaves exactly like this.
// NB: estimate_timings_from_pts behaves exactly like this.
if
(
!
avctx
->
has_b_frames
)
if
(
!
avctx
->
has_b_frames
)
h
->
low_delay
=
1
;
h
->
low_delay
=
1
;
ff_h264_decode_extradata
(
h
);
ff_h264_decode_extradata
(
avctx
->
extradata
,
avctx
->
extradata_size
,
&
p
->
ps
,
&
p
->
is_avc
,
&
p
->
nal_length_size
,
avctx
->
err_recognition
,
avctx
);
}
}
}
}
...
...
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