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
b5df289e
Commit
b5df289e
authored
Jun 22, 2017
by
Mark Thompson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
lavc: Add coded bitstream read/write support for VP9
parent
300ef253
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
1282 additions
and
1 deletion
+1282
-1
configure
configure
+2
-0
bitstream_filters.texi
doc/bitstream_filters.texi
+1
-1
Makefile
libavcodec/Makefile
+1
-0
cbs.c
libavcodec/cbs.c
+6
-0
cbs.h
libavcodec/cbs.h
+1
-0
cbs_internal.h
libavcodec/cbs_internal.h
+1
-0
cbs_vp9.c
libavcodec/cbs_vp9.c
+679
-0
cbs_vp9.h
libavcodec/cbs_vp9.h
+201
-0
cbs_vp9_syntax_template.c
libavcodec/cbs_vp9_syntax_template.c
+390
-0
No files found.
configure
View file @
b5df289e
...
@@ -2236,6 +2236,7 @@ CONFIG_EXTRA="
...
@@ -2236,6 +2236,7 @@ CONFIG_EXTRA="
cbs_h264
cbs_h264
cbs_h265
cbs_h265
cbs_mpeg2
cbs_mpeg2
cbs_vp9
dirac_parse
dirac_parse
dvprofile
dvprofile
exif
exif
...
@@ -2497,6 +2498,7 @@ threads_if_any="$THREADS_LIST"
...
@@ -2497,6 +2498,7 @@ threads_if_any="$THREADS_LIST"
cbs_h264_select
=
"cbs golomb"
cbs_h264_select
=
"cbs golomb"
cbs_h265_select
=
"cbs golomb"
cbs_h265_select
=
"cbs golomb"
cbs_mpeg2_select
=
"cbs"
cbs_mpeg2_select
=
"cbs"
cbs_vp9_select
=
"cbs"
dct_select
=
"rdft"
dct_select
=
"rdft"
dirac_parse_select
=
"golomb"
dirac_parse_select
=
"golomb"
error_resilience_select
=
"me_cmp"
error_resilience_select
=
"me_cmp"
...
...
doc/bitstream_filters.texi
View file @
b5df289e
...
@@ -505,7 +505,7 @@ Log trace output containing all syntax elements in the coded stream
...
@@ -505,7 +505,7 @@ Log trace output containing all syntax elements in the coded stream
headers (everything above the level of individual coded blocks).
headers (everything above the level of individual coded blocks).
This can be useful for debugging low-level stream issues.
This can be useful for debugging low-level stream issues.
Supports H.264, H.265
and MPEG-2
.
Supports H.264, H.265
, MPEG-2 and VP9
.
@section vp9_superframe
@section vp9_superframe
...
...
libavcodec/Makefile
View file @
b5df289e
...
@@ -65,6 +65,7 @@ OBJS-$(CONFIG_CBS) += cbs.o
...
@@ -65,6 +65,7 @@ OBJS-$(CONFIG_CBS) += cbs.o
OBJS-$(CONFIG_CBS_H264)
+=
cbs_h2645.o
h2645_parse.o
OBJS-$(CONFIG_CBS_H264)
+=
cbs_h2645.o
h2645_parse.o
OBJS-$(CONFIG_CBS_H265)
+=
cbs_h2645.o
h2645_parse.o
OBJS-$(CONFIG_CBS_H265)
+=
cbs_h2645.o
h2645_parse.o
OBJS-$(CONFIG_CBS_MPEG2)
+=
cbs_mpeg2.o
OBJS-$(CONFIG_CBS_MPEG2)
+=
cbs_mpeg2.o
OBJS-$(CONFIG_CBS_VP9)
+=
cbs_vp9.o
OBJS-$(CONFIG_CRYSTALHD)
+=
crystalhd.o
OBJS-$(CONFIG_CRYSTALHD)
+=
crystalhd.o
OBJS-$(CONFIG_DCT)
+=
dct.o
dct32_fixed.o
dct32_float.o
OBJS-$(CONFIG_DCT)
+=
dct.o
dct32_fixed.o
dct32_float.o
OBJS-$(CONFIG_ERROR_RESILIENCE)
+=
error_resilience.o
OBJS-$(CONFIG_ERROR_RESILIENCE)
+=
error_resilience.o
...
...
libavcodec/cbs.c
View file @
b5df289e
...
@@ -38,6 +38,9 @@ static const CodedBitstreamType *cbs_type_table[] = {
...
@@ -38,6 +38,9 @@ static const CodedBitstreamType *cbs_type_table[] = {
#if CONFIG_CBS_MPEG2
#if CONFIG_CBS_MPEG2
&
ff_cbs_type_mpeg2
,
&
ff_cbs_type_mpeg2
,
#endif
#endif
#if CONFIG_CBS_VP9
&
ff_cbs_type_vp9
,
#endif
};
};
const
enum
AVCodecID
ff_cbs_all_codec_ids
[]
=
{
const
enum
AVCodecID
ff_cbs_all_codec_ids
[]
=
{
...
@@ -49,6 +52,9 @@ const enum AVCodecID ff_cbs_all_codec_ids[] = {
...
@@ -49,6 +52,9 @@ const enum AVCodecID ff_cbs_all_codec_ids[] = {
#endif
#endif
#if CONFIG_CBS_MPEG2
#if CONFIG_CBS_MPEG2
AV_CODEC_ID_MPEG2VIDEO
,
AV_CODEC_ID_MPEG2VIDEO
,
#endif
#if CONFIG_CBS_VP9
AV_CODEC_ID_VP9
,
#endif
#endif
AV_CODEC_ID_NONE
AV_CODEC_ID_NONE
};
};
...
...
libavcodec/cbs.h
View file @
b5df289e
...
@@ -48,6 +48,7 @@ struct CodedBitstreamType;
...
@@ -48,6 +48,7 @@ struct CodedBitstreamType;
* H.264 / AVC: nal_unit_type
* H.264 / AVC: nal_unit_type
* H.265 / HEVC: nal_unit_type
* H.265 / HEVC: nal_unit_type
* MPEG-2: start code value (without prefix)
* MPEG-2: start code value (without prefix)
* VP9: unused, set to zero (every unit is a frame)
*/
*/
typedef
uint32_t
CodedBitstreamUnitType
;
typedef
uint32_t
CodedBitstreamUnitType
;
...
...
libavcodec/cbs_internal.h
View file @
b5df289e
...
@@ -89,6 +89,7 @@ int ff_cbs_write_unsigned(CodedBitstreamContext *ctx, PutBitContext *pbc,
...
@@ -89,6 +89,7 @@ int ff_cbs_write_unsigned(CodedBitstreamContext *ctx, PutBitContext *pbc,
extern
const
CodedBitstreamType
ff_cbs_type_h264
;
extern
const
CodedBitstreamType
ff_cbs_type_h264
;
extern
const
CodedBitstreamType
ff_cbs_type_h265
;
extern
const
CodedBitstreamType
ff_cbs_type_h265
;
extern
const
CodedBitstreamType
ff_cbs_type_mpeg2
;
extern
const
CodedBitstreamType
ff_cbs_type_mpeg2
;
extern
const
CodedBitstreamType
ff_cbs_type_vp9
;
#endif
/* AVCODEC_CBS_INTERNAL_H */
#endif
/* AVCODEC_CBS_INTERNAL_H */
libavcodec/cbs_vp9.c
0 → 100644
View file @
b5df289e
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/avassert.h"
#include "cbs.h"
#include "cbs_internal.h"
#include "cbs_vp9.h"
#include "internal.h"
static
int
cbs_vp9_read_s
(
CodedBitstreamContext
*
ctx
,
GetBitContext
*
gbc
,
int
width
,
const
char
*
name
,
const
int
*
subscripts
,
int32_t
*
write_to
)
{
uint32_t
magnitude
;
int
position
,
sign
;
int32_t
value
;
if
(
ctx
->
trace_enable
)
position
=
get_bits_count
(
gbc
);
if
(
get_bits_left
(
gbc
)
<
width
+
1
)
{
av_log
(
ctx
->
log_ctx
,
AV_LOG_ERROR
,
"Invalid signed value at "
"%s: bitstream ended.
\n
"
,
name
);
return
AVERROR_INVALIDDATA
;
}
magnitude
=
get_bits
(
gbc
,
width
);
sign
=
get_bits1
(
gbc
);
value
=
sign
?
-
(
int32_t
)
magnitude
:
magnitude
;
if
(
ctx
->
trace_enable
)
{
char
bits
[
33
];
int
i
;
for
(
i
=
0
;
i
<
width
;
i
++
)
bits
[
i
]
=
magnitude
>>
(
width
-
i
-
1
)
&
1
?
'1'
:
'0'
;
bits
[
i
]
=
sign
?
'1'
:
'0'
;
bits
[
i
+
1
]
=
0
;
ff_cbs_trace_syntax_element
(
ctx
,
position
,
name
,
subscripts
,
bits
,
value
);
}
*
write_to
=
value
;
return
0
;
}
static
int
cbs_vp9_write_s
(
CodedBitstreamContext
*
ctx
,
PutBitContext
*
pbc
,
int
width
,
const
char
*
name
,
const
int
*
subscripts
,
int32_t
value
)
{
uint32_t
magnitude
;
int
sign
;
if
(
put_bits_left
(
pbc
)
<
width
+
1
)
return
AVERROR
(
ENOSPC
);
sign
=
value
<
0
;
magnitude
=
sign
?
-
value
:
value
;
if
(
ctx
->
trace_enable
)
{
char
bits
[
33
];
int
i
;
for
(
i
=
0
;
i
<
width
;
i
++
)
bits
[
i
]
=
magnitude
>>
(
width
-
i
-
1
)
&
1
?
'1'
:
'0'
;
bits
[
i
]
=
sign
?
'1'
:
'0'
;
bits
[
i
+
1
]
=
0
;
ff_cbs_trace_syntax_element
(
ctx
,
put_bits_count
(
pbc
),
name
,
subscripts
,
bits
,
value
);
}
put_bits
(
pbc
,
width
,
magnitude
);
put_bits
(
pbc
,
1
,
sign
);
return
0
;
}
static
int
cbs_vp9_read_increment
(
CodedBitstreamContext
*
ctx
,
GetBitContext
*
gbc
,
uint32_t
range_min
,
uint32_t
range_max
,
const
char
*
name
,
uint32_t
*
write_to
)
{
uint32_t
value
;
int
position
,
i
;
char
bits
[
8
];
av_assert0
(
range_min
<=
range_max
&&
range_max
-
range_min
<
sizeof
(
bits
)
-
1
);
if
(
ctx
->
trace_enable
)
position
=
get_bits_count
(
gbc
);
for
(
i
=
0
,
value
=
range_min
;
value
<
range_max
;)
{
if
(
get_bits_left
(
gbc
)
<
1
)
{
av_log
(
ctx
->
log_ctx
,
AV_LOG_ERROR
,
"Invalid increment value at "
"%s: bitstream ended.
\n
"
,
name
);
return
AVERROR_INVALIDDATA
;
}
if
(
get_bits1
(
gbc
))
{
bits
[
i
++
]
=
'1'
;
++
value
;
}
else
{
bits
[
i
++
]
=
'0'
;
break
;
}
}
if
(
ctx
->
trace_enable
)
{
bits
[
i
]
=
0
;
ff_cbs_trace_syntax_element
(
ctx
,
position
,
name
,
NULL
,
bits
,
value
);
}
*
write_to
=
value
;
return
0
;
}
static
int
cbs_vp9_write_increment
(
CodedBitstreamContext
*
ctx
,
PutBitContext
*
pbc
,
uint32_t
range_min
,
uint32_t
range_max
,
const
char
*
name
,
uint32_t
value
)
{
int
len
;
av_assert0
(
range_min
<=
range_max
&&
range_max
-
range_min
<
8
);
if
(
value
<
range_min
||
value
>
range_max
)
{
av_log
(
ctx
->
log_ctx
,
AV_LOG_ERROR
,
"%s out of range: "
"%"
PRIu32
", but must be in [%"
PRIu32
",%"
PRIu32
"].
\n
"
,
name
,
value
,
range_min
,
range_max
);
return
AVERROR_INVALIDDATA
;
}
if
(
value
==
range_max
)
len
=
range_max
-
range_min
;
else
len
=
value
-
range_min
+
1
;
if
(
put_bits_left
(
pbc
)
<
len
)
return
AVERROR
(
ENOSPC
);
if
(
ctx
->
trace_enable
)
{
char
bits
[
8
];
int
i
;
for
(
i
=
0
;
i
<
len
;
i
++
)
{
if
(
range_min
+
i
==
value
)
bits
[
i
]
=
'0'
;
else
bits
[
i
]
=
'1'
;
}
bits
[
i
]
=
0
;
ff_cbs_trace_syntax_element
(
ctx
,
put_bits_count
(
pbc
),
name
,
NULL
,
bits
,
value
);
}
if
(
len
>
0
)
put_bits
(
pbc
,
len
,
(
1
<<
len
)
-
1
-
(
value
!=
range_max
));
return
0
;
}
static
int
cbs_vp9_read_le
(
CodedBitstreamContext
*
ctx
,
GetBitContext
*
gbc
,
int
width
,
const
char
*
name
,
const
int
*
subscripts
,
uint32_t
*
write_to
)
{
uint32_t
value
;
int
position
,
b
;
av_assert0
(
width
%
8
==
0
);
if
(
ctx
->
trace_enable
)
position
=
get_bits_count
(
gbc
);
if
(
get_bits_left
(
gbc
)
<
width
)
{
av_log
(
ctx
->
log_ctx
,
AV_LOG_ERROR
,
"Invalid le value at "
"%s: bitstream ended.
\n
"
,
name
);
return
AVERROR_INVALIDDATA
;
}
value
=
0
;
for
(
b
=
0
;
b
<
width
;
b
+=
8
)
value
|=
get_bits
(
gbc
,
8
)
<<
b
;
if
(
ctx
->
trace_enable
)
{
char
bits
[
33
];
int
i
;
for
(
b
=
0
;
b
<
width
;
b
+=
8
)
for
(
i
=
0
;
i
<
8
;
i
++
)
bits
[
b
+
i
]
=
value
>>
(
b
+
i
)
&
1
?
'1'
:
'0'
;
bits
[
b
]
=
0
;
ff_cbs_trace_syntax_element
(
ctx
,
position
,
name
,
subscripts
,
bits
,
value
);
}
*
write_to
=
value
;
return
0
;
}
static
int
cbs_vp9_write_le
(
CodedBitstreamContext
*
ctx
,
PutBitContext
*
pbc
,
int
width
,
const
char
*
name
,
const
int
*
subscripts
,
uint32_t
value
)
{
int
b
;
av_assert0
(
width
%
8
==
0
);
if
(
put_bits_left
(
pbc
)
<
width
)
return
AVERROR
(
ENOSPC
);
if
(
ctx
->
trace_enable
)
{
char
bits
[
33
];
int
i
;
for
(
b
=
0
;
b
<
width
;
b
+=
8
)
for
(
i
=
0
;
i
<
8
;
i
++
)
bits
[
b
+
i
]
=
value
>>
(
b
+
i
)
&
1
?
'1'
:
'0'
;
bits
[
b
]
=
0
;
ff_cbs_trace_syntax_element
(
ctx
,
put_bits_count
(
pbc
),
name
,
subscripts
,
bits
,
value
);
}
for
(
b
=
0
;
b
<
width
;
b
+=
8
)
put_bits
(
pbc
,
8
,
value
>>
b
&
0xff
);
return
0
;
}
#define HEADER(name) do { \
ff_cbs_trace_header(ctx, name); \
} while (0)
#define CHECK(call) do { \
err = (call); \
if (err < 0) \
return err; \
} while (0)
#define FUNC_NAME(rw, codec, name) cbs_ ## codec ## _ ## rw ## _ ## name
#define FUNC_VP9(rw, name) FUNC_NAME(rw, vp9, name)
#define FUNC(name) FUNC_VP9(READWRITE, name)
#define SUBSCRIPTS(subs, ...) (subs > 0 ? ((int[subs + 1]){ subs, __VA_ARGS__ }) : NULL)
#define f(width, name) \
xf(width, name, current->name, 0)
#define s(width, name) \
xs(width, name, current->name, 0)
#define fs(width, name, subs, ...) \
xf(width, name, current->name, subs, __VA_ARGS__)
#define ss(width, name, subs, ...) \
xs(width, name, current->name, subs, __VA_ARGS__)
#define READ
#define READWRITE read
#define RWContext GetBitContext
#define xf(width, name, var, subs, ...) do { \
uint32_t value = 0; \
CHECK(ff_cbs_read_unsigned(ctx, rw, width, #name, \
SUBSCRIPTS(subs, __VA_ARGS__), \
&value, 0, (1 << width) - 1)); \
var = value; \
} while (0)
#define xs(width, name, var, subs, ...) do { \
int32_t value = 0; \
CHECK(cbs_vp9_read_s(ctx, rw, width, #name, \
SUBSCRIPTS(subs, __VA_ARGS__), &value)); \
var = value; \
} while (0)
#define increment(name, min, max) do { \
uint32_t value = 0; \
CHECK(cbs_vp9_read_increment(ctx, rw, min, max, #name, &value)); \
current->name = value; \
} while (0)
#define fle(width, name, subs, ...) do { \
CHECK(cbs_vp9_read_le(ctx, rw, width, #name, \
SUBSCRIPTS(subs, __VA_ARGS__), ¤t->name)); \
} while (0)
#define delta_q(name) do { \
uint8_t delta_coded; \
int8_t delta_q; \
xf(1, name.delta_coded, delta_coded, 0); \
if (delta_coded) \
xs(4, name.delta_q, delta_q, 0); \
else \
delta_q = 0; \
current->name = delta_q; \
} while (0)
#define prob(name, subs, ...) do { \
uint8_t prob_coded; \
int8_t prob; \
xf(1, name.prob_coded, prob_coded, subs, __VA_ARGS__); \
if (prob_coded) \
xf(8, name.prob, prob, subs, __VA_ARGS__); \
else \
prob = 255; \
current->name = prob; \
} while (0)
#define infer(name, value) do { \
current->name = value; \
} while (0)
#define byte_alignment(rw) (get_bits_count(rw) % 8)
#include "cbs_vp9_syntax_template.c"
#undef READ
#undef READWRITE
#undef RWContext
#undef xf
#undef xs
#undef increment
#undef fle
#undef delta_q
#undef prob
#undef infer
#undef byte_alignment
#define WRITE
#define READWRITE write
#define RWContext PutBitContext
#define xf(width, name, var, subs, ...) do { \
CHECK(ff_cbs_write_unsigned(ctx, rw, width, #name, \
SUBSCRIPTS(subs, __VA_ARGS__), \
var, 0, (1 << width) - 1)); \
} while (0)
#define xs(width, name, var, subs, ...) do { \
CHECK(cbs_vp9_write_s(ctx, rw, width, #name, \
SUBSCRIPTS(subs, __VA_ARGS__), var)); \
} while (0)
#define increment(name, min, max) do { \
CHECK(cbs_vp9_write_increment(ctx, rw, min, max, #name, current->name)); \
} while (0)
#define fle(width, name, subs, ...) do { \
CHECK(cbs_vp9_write_le(ctx, rw, width, #name, \
SUBSCRIPTS(subs, __VA_ARGS__), current->name)); \
} while (0)
#define delta_q(name) do { \
xf(1, name.delta_coded, !!current->name, 0); \
if (current->name) \
xs(4, name.delta_q, current->name, 0); \
} while (0)
#define prob(name, subs, ...) do { \
xf(1, name.prob_coded, current->name != 255, subs, __VA_ARGS__); \
if (current->name != 255) \
xf(8, name.prob, current->name, subs, __VA_ARGS__); \
} while (0)
#define infer(name, value) do { \
if (current->name != (value)) { \
av_log(ctx->log_ctx, AV_LOG_WARNING, "Warning: " \
"%s does not match inferred value: " \
"%"PRId64", but should be %"PRId64".\n", \
#name, (int64_t)current->name, (int64_t)(value)); \
} \
} while (0)
#define byte_alignment(rw) (put_bits_count(rw) % 8)
#include "cbs_vp9_syntax_template.c"
#undef READ
#undef READWRITE
#undef RWContext
#undef xf
#undef xs
#undef increment
#undef fle
#undef delta_q
#undef prob
#undef infer
#undef byte_alignment
static
int
cbs_vp9_split_fragment
(
CodedBitstreamContext
*
ctx
,
CodedBitstreamFragment
*
frag
,
int
header
)
{
uint8_t
superframe_header
;
int
err
;
// Last byte in the packet.
superframe_header
=
frag
->
data
[
frag
->
data_size
-
1
];
if
((
superframe_header
&
0xe0
)
==
0xc0
)
{
VP9RawSuperframeIndex
sfi
;
GetBitContext
gbc
;
size_t
index_size
,
pos
;
int
i
;
index_size
=
2
+
(((
superframe_header
&
0x18
)
>>
3
)
+
1
)
*
((
superframe_header
&
0x07
)
+
1
);
err
=
init_get_bits
(
&
gbc
,
frag
->
data
+
frag
->
data_size
-
index_size
,
8
*
index_size
);
if
(
err
<
0
)
return
err
;
err
=
cbs_vp9_read_superframe_index
(
ctx
,
&
gbc
,
&
sfi
);
if
(
err
<
0
)
return
err
;
pos
=
0
;
for
(
i
=
0
;
i
<=
sfi
.
frames_in_superframe_minus_1
;
i
++
)
{
if
(
pos
+
sfi
.
frame_sizes
[
i
]
+
index_size
>
frag
->
data_size
)
{
av_log
(
ctx
->
log_ctx
,
AV_LOG_ERROR
,
"Frame %d too large "
"in superframe: %"
PRIu32
" bytes.
\n
"
,
i
,
sfi
.
frame_sizes
[
i
]);
return
AVERROR_INVALIDDATA
;
}
err
=
ff_cbs_insert_unit_data
(
ctx
,
frag
,
-
1
,
0
,
frag
->
data
+
pos
,
sfi
.
frame_sizes
[
i
],
frag
->
data_ref
);
if
(
err
<
0
)
return
err
;
pos
+=
sfi
.
frame_sizes
[
i
];
}
if
(
pos
+
index_size
!=
frag
->
data_size
)
{
av_log
(
ctx
->
log_ctx
,
AV_LOG_WARNING
,
"Extra padding at "
"end of superframe: %zu bytes.
\n
"
,
frag
->
data_size
-
(
pos
+
index_size
));
}
return
0
;
}
else
{
err
=
ff_cbs_insert_unit_data
(
ctx
,
frag
,
-
1
,
0
,
frag
->
data
,
frag
->
data_size
,
frag
->
data_ref
);
if
(
err
<
0
)
return
err
;
}
return
0
;
}
static
void
cbs_vp9_free_frame
(
void
*
unit
,
uint8_t
*
content
)
{
VP9RawFrame
*
frame
=
(
VP9RawFrame
*
)
content
;
av_buffer_unref
(
&
frame
->
data_ref
);
av_freep
(
&
frame
);
}
static
int
cbs_vp9_read_unit
(
CodedBitstreamContext
*
ctx
,
CodedBitstreamUnit
*
unit
)
{
VP9RawFrame
*
frame
;
GetBitContext
gbc
;
int
err
,
pos
;
err
=
init_get_bits
(
&
gbc
,
unit
->
data
,
8
*
unit
->
data_size
);
if
(
err
<
0
)
return
err
;
err
=
ff_cbs_alloc_unit_content
(
ctx
,
unit
,
sizeof
(
*
frame
),
&
cbs_vp9_free_frame
);
if
(
err
<
0
)
return
err
;
frame
=
unit
->
content
;
err
=
cbs_vp9_read_frame
(
ctx
,
&
gbc
,
frame
);
if
(
err
<
0
)
return
err
;
pos
=
get_bits_count
(
&
gbc
);
av_assert0
(
pos
%
8
==
0
);
pos
/=
8
;
av_assert0
(
pos
<=
unit
->
data_size
);
if
(
pos
==
unit
->
data_size
)
{
// No data (e.g. a show-existing-frame frame).
}
else
{
frame
->
data_ref
=
av_buffer_ref
(
unit
->
data_ref
);
if
(
!
frame
->
data_ref
)
return
AVERROR
(
ENOMEM
);
frame
->
data
=
unit
->
data
+
pos
;
frame
->
data_size
=
unit
->
data_size
-
pos
;
}
return
0
;
}
static
int
cbs_vp9_write_unit
(
CodedBitstreamContext
*
ctx
,
CodedBitstreamUnit
*
unit
)
{
CodedBitstreamVP9Context
*
priv
=
ctx
->
priv_data
;
VP9RawFrame
*
frame
=
unit
->
content
;
PutBitContext
pbc
;
int
err
;
if
(
!
priv
->
write_buffer
)
{
// Initial write buffer size is 1MB.
priv
->
write_buffer_size
=
1024
*
1024
;
reallocate_and_try_again:
err
=
av_reallocp
(
&
priv
->
write_buffer
,
priv
->
write_buffer_size
);
if
(
err
<
0
)
{
av_log
(
ctx
->
log_ctx
,
AV_LOG_ERROR
,
"Unable to allocate a "
"sufficiently large write buffer (last attempt "
"%zu bytes).
\n
"
,
priv
->
write_buffer_size
);
return
err
;
}
}
init_put_bits
(
&
pbc
,
priv
->
write_buffer
,
priv
->
write_buffer_size
);
err
=
cbs_vp9_write_frame
(
ctx
,
&
pbc
,
frame
);
if
(
err
==
AVERROR
(
ENOSPC
))
{
priv
->
write_buffer_size
*=
2
;
goto
reallocate_and_try_again
;
}
if
(
err
<
0
)
return
err
;
// Frame must be byte-aligned.
av_assert0
(
put_bits_count
(
&
pbc
)
%
8
==
0
);
unit
->
data_size
=
put_bits_count
(
&
pbc
)
/
8
;
unit
->
data_bit_padding
=
0
;
flush_put_bits
(
&
pbc
);
if
(
frame
->
data
)
{
if
(
unit
->
data_size
+
frame
->
data_size
>
priv
->
write_buffer_size
)
{
priv
->
write_buffer_size
*=
2
;
goto
reallocate_and_try_again
;
}
memcpy
(
priv
->
write_buffer
+
unit
->
data_size
,
frame
->
data
,
frame
->
data_size
);
unit
->
data_size
+=
frame
->
data_size
;
}
err
=
ff_cbs_alloc_unit_data
(
ctx
,
unit
,
unit
->
data_size
);
if
(
err
<
0
)
return
err
;
memcpy
(
unit
->
data
,
priv
->
write_buffer
,
unit
->
data_size
);
return
0
;
}
static
int
cbs_vp9_assemble_fragment
(
CodedBitstreamContext
*
ctx
,
CodedBitstreamFragment
*
frag
)
{
int
err
;
if
(
frag
->
nb_units
==
1
)
{
// Output is just the content of the single frame.
CodedBitstreamUnit
*
frame
=
&
frag
->
units
[
0
];
frag
->
data_ref
=
av_buffer_ref
(
frame
->
data_ref
);
if
(
!
frag
->
data_ref
)
return
AVERROR
(
ENOMEM
);
frag
->
data
=
frame
->
data
;
frag
->
data_size
=
frame
->
data_size
;
}
else
{
// Build superframe out of frames.
VP9RawSuperframeIndex
sfi
;
PutBitContext
pbc
;
AVBufferRef
*
ref
;
uint8_t
*
data
;
size_t
size
,
max
,
pos
;
int
i
,
size_len
;
if
(
frag
->
nb_units
>
8
)
{
av_log
(
ctx
->
log_ctx
,
AV_LOG_ERROR
,
"Too many frames to "
"make superframe: %d.
\n
"
,
frag
->
nb_units
);
return
AVERROR
(
EINVAL
);
}
max
=
0
;
for
(
i
=
0
;
i
<
frag
->
nb_units
;
i
++
)
if
(
max
<
frag
->
units
[
i
].
data_size
)
max
=
frag
->
units
[
i
].
data_size
;
if
(
max
<
2
)
size_len
=
1
;
else
size_len
=
av_log2
(
max
)
/
8
+
1
;
av_assert0
(
size_len
<=
4
);
sfi
.
superframe_marker
=
VP9_SUPERFRAME_MARKER
;
sfi
.
bytes_per_framesize_minus_1
=
size_len
-
1
;
sfi
.
frames_in_superframe_minus_1
=
frag
->
nb_units
-
1
;
size
=
2
;
for
(
i
=
0
;
i
<
frag
->
nb_units
;
i
++
)
{
size
+=
size_len
+
frag
->
units
[
i
].
data_size
;
sfi
.
frame_sizes
[
i
]
=
frag
->
units
[
i
].
data_size
;
}
ref
=
av_buffer_alloc
(
size
+
AV_INPUT_BUFFER_PADDING_SIZE
);
if
(
!
ref
)
return
AVERROR
(
ENOMEM
);
data
=
ref
->
data
;
memset
(
data
+
size
,
0
,
AV_INPUT_BUFFER_PADDING_SIZE
);
pos
=
0
;
for
(
i
=
0
;
i
<
frag
->
nb_units
;
i
++
)
{
av_assert0
(
size
-
pos
>
frag
->
units
[
i
].
data_size
);
memcpy
(
data
+
pos
,
frag
->
units
[
i
].
data
,
frag
->
units
[
i
].
data_size
);
pos
+=
frag
->
units
[
i
].
data_size
;
}
av_assert0
(
size
-
pos
==
2
+
frag
->
nb_units
*
size_len
);
init_put_bits
(
&
pbc
,
data
+
pos
,
size
-
pos
);
err
=
cbs_vp9_write_superframe_index
(
ctx
,
&
pbc
,
&
sfi
);
if
(
err
<
0
)
{
av_log
(
ctx
->
log_ctx
,
AV_LOG_ERROR
,
"Failed to write "
"superframe index.
\n
"
);
av_buffer_unref
(
&
ref
);
return
err
;
}
av_assert0
(
put_bits_left
(
&
pbc
)
==
0
);
flush_put_bits
(
&
pbc
);
frag
->
data_ref
=
ref
;
frag
->
data
=
data
;
frag
->
data_size
=
size
;
}
return
0
;
}
static
void
cbs_vp9_close
(
CodedBitstreamContext
*
ctx
)
{
CodedBitstreamVP9Context
*
priv
=
ctx
->
priv_data
;
av_freep
(
&
priv
->
write_buffer
);
}
const
CodedBitstreamType
ff_cbs_type_vp9
=
{
.
codec_id
=
AV_CODEC_ID_VP9
,
.
priv_data_size
=
sizeof
(
CodedBitstreamVP9Context
),
.
split_fragment
=
&
cbs_vp9_split_fragment
,
.
read_unit
=
&
cbs_vp9_read_unit
,
.
write_unit
=
&
cbs_vp9_write_unit
,
.
assemble_fragment
=
&
cbs_vp9_assemble_fragment
,
.
close
=
&
cbs_vp9_close
,
};
libavcodec/cbs_vp9.h
0 → 100644
View file @
b5df289e
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVCODEC_CBS_VP9_H
#define AVCODEC_CBS_VP9_H
#include <stddef.h>
#include <stdint.h>
#include "cbs.h"
// Miscellaneous constants (section 3).
enum
{
VP9_REFS_PER_FRAME
=
3
,
VP9_MIN_TILE_WIDTH_B64
=
4
,
VP9_MAX_TILE_WIDTH_B64
=
64
,
VP9_NUM_REF_FRAMES
=
8
,
VP9_MAX_REF_FRAMES
=
4
,
VP9_MAX_SEGMENTS
=
8
,
VP9_SEG_LVL_MAX
=
4
,
};
// Frame types (section 7.2).
enum
{
VP9_KEY_FRAME
=
0
,
VP9_NON_KEY_FRAME
=
1
,
};
// Frame sync bytes (section 7.2.1).
enum
{
VP9_FRAME_SYNC_0
=
0x49
,
VP9_FRAME_SYNC_1
=
0x83
,
VP9_FRAME_SYNC_2
=
0x42
,
};
// Color space values (section 7.2.2).
enum
{
VP9_CS_UNKNOWN
=
0
,
VP9_CS_BT_601
=
1
,
VP9_CS_BT_709
=
2
,
VP9_CS_SMPTE_170
=
3
,
VP9_CS_SMPTE_240
=
4
,
VP9_CS_BT_2020
=
5
,
VP9_CS_RESERVED
=
6
,
VP9_CS_RGB
=
7
,
};
// Reference frame types (section 7.4.12).
enum
{
VP9_INTRA_FRAME
=
0
,
VP9_LAST_FRAME
=
1
,
VP9_GOLDEN_FRAME
=
2
,
VP9_ALTREF_FRAME
=
3
,
};
// Superframe properties (section B.3).
enum
{
VP9_MAX_FRAMES_IN_SUPERFRAME
=
8
,
VP9_SUPERFRAME_MARKER
=
6
,
};
typedef
struct
VP9RawFrameHeader
{
uint8_t
frame_marker
;
uint8_t
profile_low_bit
;
uint8_t
profile_high_bit
;
uint8_t
profile_reserved_zero
;
uint8_t
show_existing_frame
;
uint8_t
frame_to_show_map_idx
;
uint8_t
frame_type
;
uint8_t
show_frame
;
uint8_t
error_resilient_mode
;
// Color config.
uint8_t
ten_or_twelve_bit
;
uint8_t
color_space
;
uint8_t
color_range
;
uint8_t
subsampling_x
;
uint8_t
subsampling_y
;
uint8_t
color_config_reserved_zero
;
uint8_t
refresh_frame_flags
;
uint8_t
intra_only
;
uint8_t
reset_frame_context
;
uint8_t
ref_frame_idx
[
VP9_REFS_PER_FRAME
];
uint8_t
ref_frame_sign_bias
[
VP9_MAX_REF_FRAMES
];
uint8_t
allow_high_precision_mv
;
uint8_t
refresh_frame_context
;
uint8_t
frame_parallel_decoding_mode
;
uint8_t
frame_context_idx
;
// Frame/render size.
uint8_t
found_ref
[
VP9_REFS_PER_FRAME
];
uint16_t
frame_width_minus_1
;
uint16_t
frame_height_minus_1
;
uint8_t
render_and_frame_size_different
;
uint16_t
render_width_minus_1
;
uint16_t
render_height_minus_1
;
// Interpolation filter.
uint8_t
is_filter_switchable
;
uint8_t
raw_interpolation_filter_type
;
// Loop filter params.
uint8_t
loop_filter_level
;
uint8_t
loop_filter_sharpness
;
uint8_t
loop_filter_delta_enabled
;
uint8_t
loop_filter_delta_update
;
uint8_t
update_ref_delta
[
VP9_MAX_REF_FRAMES
];
int8_t
loop_filter_ref_deltas
[
VP9_MAX_REF_FRAMES
];
uint8_t
update_mode_delta
[
2
];
int8_t
loop_filter_mode_deltas
[
2
];
// Quantization params.
uint8_t
base_q_idx
;
int8_t
delta_q_y_dc
;
int8_t
delta_q_uv_dc
;
int8_t
delta_q_uv_ac
;
// Segmentation params.
uint8_t
segmentation_enabled
;
uint8_t
segmentation_update_map
;
uint8_t
segmentation_tree_probs
[
7
];
uint8_t
segmentation_temporal_update
;
uint8_t
segmentation_pred_prob
[
3
];
uint8_t
segmentation_update_data
;
uint8_t
segmentation_abs_or_delta_update
;
uint8_t
feature_enabled
[
VP9_MAX_SEGMENTS
][
VP9_SEG_LVL_MAX
];
uint8_t
feature_value
[
VP9_MAX_SEGMENTS
][
VP9_SEG_LVL_MAX
];
uint8_t
feature_sign
[
VP9_MAX_SEGMENTS
][
VP9_SEG_LVL_MAX
];
// Tile info.
uint8_t
tile_cols_log2
;
uint8_t
tile_rows_log2
;
uint16_t
header_size_in_bytes
;
}
VP9RawFrameHeader
;
typedef
struct
VP9RawFrame
{
VP9RawFrameHeader
header
;
uint8_t
*
data
;
size_t
data_size
;
AVBufferRef
*
data_ref
;
}
VP9RawFrame
;
typedef
struct
VP9RawSuperframeIndex
{
uint8_t
superframe_marker
;
uint8_t
bytes_per_framesize_minus_1
;
uint8_t
frames_in_superframe_minus_1
;
uint32_t
frame_sizes
[
VP9_MAX_FRAMES_IN_SUPERFRAME
];
}
VP9RawSuperframeIndex
;
typedef
struct
VP9RawSuperframe
{
VP9RawFrame
frames
[
VP9_MAX_FRAMES_IN_SUPERFRAME
];
VP9RawSuperframeIndex
index
;
}
VP9RawSuperframe
;
typedef
struct
CodedBitstreamVP9Context
{
// Frame dimensions in 8x8 mode info blocks.
uint16_t
mi_cols
;
uint16_t
mi_rows
;
// Frame dimensions in 64x64 superblocks.
uint16_t
sb64_cols
;
uint16_t
sb64_rows
;
// Write buffer.
uint8_t
*
write_buffer
;
size_t
write_buffer_size
;
}
CodedBitstreamVP9Context
;
#endif
/* AVCODEC_CBS_VP9_H */
libavcodec/cbs_vp9_syntax_template.c
0 → 100644
View file @
b5df289e
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
static
int
FUNC
(
frame_sync_code
)(
CodedBitstreamContext
*
ctx
,
RWContext
*
rw
,
VP9RawFrameHeader
*
current
)
{
uint8_t
frame_sync_byte_0
=
VP9_FRAME_SYNC_0
;
uint8_t
frame_sync_byte_1
=
VP9_FRAME_SYNC_1
;
uint8_t
frame_sync_byte_2
=
VP9_FRAME_SYNC_2
;
int
err
;
xf
(
8
,
frame_sync_byte_0
,
frame_sync_byte_0
,
0
);
xf
(
8
,
frame_sync_byte_1
,
frame_sync_byte_1
,
0
);
xf
(
8
,
frame_sync_byte_2
,
frame_sync_byte_2
,
0
);
if
(
frame_sync_byte_0
!=
VP9_FRAME_SYNC_0
||
frame_sync_byte_1
!=
VP9_FRAME_SYNC_1
||
frame_sync_byte_2
!=
VP9_FRAME_SYNC_2
)
{
av_log
(
ctx
->
log_ctx
,
AV_LOG_ERROR
,
"Invalid frame sync code: "
"%02x %02x %02x.
\n
"
,
frame_sync_byte_0
,
frame_sync_byte_1
,
frame_sync_byte_2
);
return
AVERROR_INVALIDDATA
;
}
return
0
;
}
static
int
FUNC
(
color_config
)(
CodedBitstreamContext
*
ctx
,
RWContext
*
rw
,
VP9RawFrameHeader
*
current
,
int
profile
)
{
int
err
;
if
(
profile
>=
2
)
f
(
1
,
ten_or_twelve_bit
);
f
(
3
,
color_space
);
if
(
current
->
color_space
!=
VP9_CS_RGB
)
{
f
(
1
,
color_range
);
if
(
profile
==
1
||
profile
==
3
)
{
f
(
1
,
subsampling_x
);
f
(
1
,
subsampling_y
);
f
(
1
,
color_config_reserved_zero
);
}
else
{
infer
(
subsampling_x
,
1
);
infer
(
subsampling_y
,
1
);
}
}
else
{
infer
(
color_range
,
1
);
if
(
profile
==
1
||
profile
==
3
)
{
infer
(
subsampling_x
,
0
);
infer
(
subsampling_y
,
0
);
}
}
return
0
;
}
static
int
FUNC
(
frame_size
)(
CodedBitstreamContext
*
ctx
,
RWContext
*
rw
,
VP9RawFrameHeader
*
current
)
{
CodedBitstreamVP9Context
*
vp9
=
ctx
->
priv_data
;
int
err
;
f
(
16
,
frame_width_minus_1
);
f
(
16
,
frame_height_minus_1
);
vp9
->
mi_cols
=
(
current
->
frame_width_minus_1
+
8
)
>>
3
;
vp9
->
mi_rows
=
(
current
->
frame_height_minus_1
+
8
)
>>
3
;
vp9
->
sb64_cols
=
(
vp9
->
mi_cols
+
7
)
>>
3
;
vp9
->
sb64_rows
=
(
vp9
->
mi_rows
+
7
)
>>
3
;
return
0
;
}
static
int
FUNC
(
render_size
)(
CodedBitstreamContext
*
ctx
,
RWContext
*
rw
,
VP9RawFrameHeader
*
current
)
{
int
err
;
f
(
1
,
render_and_frame_size_different
);
if
(
current
->
render_and_frame_size_different
)
{
f
(
16
,
render_width_minus_1
);
f
(
16
,
render_height_minus_1
);
}
return
0
;
}
static
int
FUNC
(
frame_size_with_refs
)(
CodedBitstreamContext
*
ctx
,
RWContext
*
rw
,
VP9RawFrameHeader
*
current
)
{
int
err
,
i
;
for
(
i
=
0
;
i
<
VP9_REFS_PER_FRAME
;
i
++
)
{
fs
(
1
,
found_ref
[
i
],
1
,
i
);
if
(
current
->
found_ref
[
i
])
break
;
}
if
(
i
>=
VP9_REFS_PER_FRAME
)
CHECK
(
FUNC
(
frame_size
)(
ctx
,
rw
,
current
));
CHECK
(
FUNC
(
render_size
)(
ctx
,
rw
,
current
));
return
0
;
}
static
int
FUNC
(
interpolation_filter
)(
CodedBitstreamContext
*
ctx
,
RWContext
*
rw
,
VP9RawFrameHeader
*
current
)
{
int
err
;
f
(
1
,
is_filter_switchable
);
if
(
!
current
->
is_filter_switchable
)
f
(
2
,
raw_interpolation_filter_type
);
return
0
;
}
static
int
FUNC
(
loop_filter_params
)(
CodedBitstreamContext
*
ctx
,
RWContext
*
rw
,
VP9RawFrameHeader
*
current
)
{
int
err
,
i
;
f
(
6
,
loop_filter_level
);
f
(
3
,
loop_filter_sharpness
);
f
(
1
,
loop_filter_delta_enabled
);
if
(
current
->
loop_filter_delta_enabled
)
{
f
(
1
,
loop_filter_delta_update
);
if
(
current
->
loop_filter_delta_update
)
{
for
(
i
=
0
;
i
<
VP9_MAX_REF_FRAMES
;
i
++
)
{
fs
(
1
,
update_ref_delta
[
i
],
1
,
i
);
if
(
current
->
update_ref_delta
[
i
])
ss
(
6
,
loop_filter_ref_deltas
[
i
],
1
,
i
);
}
for
(
i
=
0
;
i
<
2
;
i
++
)
{
fs
(
1
,
update_mode_delta
[
i
],
1
,
i
);
if
(
current
->
update_mode_delta
[
i
])
ss
(
6
,
loop_filter_mode_deltas
[
i
],
1
,
i
);
}
}
}
return
0
;
}
static
int
FUNC
(
quantization_params
)(
CodedBitstreamContext
*
ctx
,
RWContext
*
rw
,
VP9RawFrameHeader
*
current
)
{
int
err
;
f
(
8
,
base_q_idx
);
delta_q
(
delta_q_y_dc
);
delta_q
(
delta_q_uv_dc
);
delta_q
(
delta_q_uv_ac
);
return
0
;
}
static
int
FUNC
(
segmentation_params
)(
CodedBitstreamContext
*
ctx
,
RWContext
*
rw
,
VP9RawFrameHeader
*
current
)
{
static
const
int
segmentation_feature_bits
[
VP9_SEG_LVL_MAX
]
=
{
8
,
6
,
2
,
0
};
static
const
int
segmentation_feature_signed
[
VP9_SEG_LVL_MAX
]
=
{
1
,
1
,
0
,
0
};
int
err
,
i
,
j
;
f
(
1
,
segmentation_enabled
);
if
(
current
->
segmentation_enabled
)
{
f
(
1
,
segmentation_update_map
);
if
(
current
->
segmentation_update_map
)
{
for
(
i
=
0
;
i
<
7
;
i
++
)
prob
(
segmentation_tree_probs
[
i
],
1
,
i
);
f
(
1
,
segmentation_temporal_update
);
for
(
i
=
0
;
i
<
3
;
i
++
)
{
if
(
current
->
segmentation_temporal_update
)
prob
(
segmentation_pred_prob
[
i
],
1
,
i
);
else
infer
(
segmentation_pred_prob
[
i
],
255
);
}
}
f
(
1
,
segmentation_update_data
);
if
(
current
->
segmentation_update_data
)
{
f
(
1
,
segmentation_abs_or_delta_update
);
for
(
i
=
0
;
i
<
VP9_MAX_SEGMENTS
;
i
++
)
{
for
(
j
=
0
;
j
<
VP9_SEG_LVL_MAX
;
j
++
)
{
fs
(
1
,
feature_enabled
[
i
][
j
],
2
,
i
,
j
);
if
(
current
->
feature_enabled
[
i
][
j
]
&&
segmentation_feature_bits
[
j
])
{
fs
(
segmentation_feature_bits
[
j
],
feature_value
[
i
][
j
],
2
,
i
,
j
);
if
(
segmentation_feature_signed
[
j
])
fs
(
1
,
feature_sign
[
i
][
j
],
2
,
i
,
j
);
else
infer
(
feature_sign
[
i
][
j
],
0
);
}
else
{
infer
(
feature_value
[
i
][
j
],
0
);
infer
(
feature_sign
[
i
][
j
],
0
);
}
}
}
}
}
return
0
;
}
static
int
FUNC
(
tile_info
)(
CodedBitstreamContext
*
ctx
,
RWContext
*
rw
,
VP9RawFrameHeader
*
current
)
{
CodedBitstreamVP9Context
*
vp9
=
ctx
->
priv_data
;
int
min_log2_tile_cols
,
max_log2_tile_cols
;
int
err
;
min_log2_tile_cols
=
0
;
while
((
VP9_MAX_TILE_WIDTH_B64
<<
min_log2_tile_cols
)
<
vp9
->
sb64_cols
)
++
min_log2_tile_cols
;
max_log2_tile_cols
=
0
;
while
((
vp9
->
sb64_cols
>>
(
max_log2_tile_cols
+
1
))
>=
VP9_MIN_TILE_WIDTH_B64
)
++
max_log2_tile_cols
;
increment
(
tile_cols_log2
,
min_log2_tile_cols
,
max_log2_tile_cols
);
increment
(
tile_rows_log2
,
0
,
2
);
return
0
;
}
static
int
FUNC
(
uncompressed_header
)(
CodedBitstreamContext
*
ctx
,
RWContext
*
rw
,
VP9RawFrameHeader
*
current
)
{
int
profile
,
i
;
int
err
;
f
(
2
,
frame_marker
);
f
(
1
,
profile_low_bit
);
f
(
1
,
profile_high_bit
);
profile
=
(
current
->
profile_high_bit
<<
1
)
+
current
->
profile_low_bit
;
if
(
profile
==
3
)
f
(
1
,
profile_reserved_zero
);
f
(
1
,
show_existing_frame
);
if
(
current
->
show_existing_frame
)
{
f
(
3
,
frame_to_show_map_idx
);
infer
(
header_size_in_bytes
,
0
);
infer
(
refresh_frame_flags
,
0x00
);
infer
(
loop_filter_level
,
0
);
return
0
;
}
f
(
1
,
frame_type
);
f
(
1
,
show_frame
);
f
(
1
,
error_resilient_mode
);
if
(
current
->
frame_type
==
VP9_KEY_FRAME
)
{
CHECK
(
FUNC
(
frame_sync_code
)(
ctx
,
rw
,
current
));
CHECK
(
FUNC
(
color_config
)(
ctx
,
rw
,
current
,
profile
));
CHECK
(
FUNC
(
frame_size
)(
ctx
,
rw
,
current
));
CHECK
(
FUNC
(
render_size
)(
ctx
,
rw
,
current
));
infer
(
refresh_frame_flags
,
0xff
);
}
else
{
if
(
current
->
show_frame
==
0
)
f
(
1
,
intra_only
);
else
infer
(
intra_only
,
0
);
if
(
current
->
error_resilient_mode
==
0
)
f
(
2
,
reset_frame_context
);
else
infer
(
reset_frame_context
,
0
);
if
(
current
->
intra_only
==
1
)
{
CHECK
(
FUNC
(
frame_sync_code
)(
ctx
,
rw
,
current
));
if
(
profile
>
0
)
{
CHECK
(
FUNC
(
color_config
)(
ctx
,
rw
,
current
,
profile
));
}
else
{
infer
(
color_space
,
1
);
infer
(
subsampling_x
,
1
);
infer
(
subsampling_y
,
1
);
}
f
(
8
,
refresh_frame_flags
);
CHECK
(
FUNC
(
frame_size
)(
ctx
,
rw
,
current
));
CHECK
(
FUNC
(
render_size
)(
ctx
,
rw
,
current
));
}
else
{
f
(
8
,
refresh_frame_flags
);
for
(
i
=
0
;
i
<
VP9_REFS_PER_FRAME
;
i
++
)
{
fs
(
3
,
ref_frame_idx
[
i
],
1
,
i
);
fs
(
1
,
ref_frame_sign_bias
[
VP9_LAST_FRAME
+
i
],
1
,
VP9_LAST_FRAME
+
i
);
}
CHECK
(
FUNC
(
frame_size_with_refs
)(
ctx
,
rw
,
current
));
f
(
1
,
allow_high_precision_mv
);
CHECK
(
FUNC
(
interpolation_filter
)(
ctx
,
rw
,
current
));
}
}
if
(
current
->
error_resilient_mode
==
0
)
{
f
(
1
,
refresh_frame_context
);
f
(
1
,
frame_parallel_decoding_mode
);
}
else
{
infer
(
refresh_frame_context
,
0
);
infer
(
frame_parallel_decoding_mode
,
1
);
}
f
(
2
,
frame_context_idx
);
CHECK
(
FUNC
(
loop_filter_params
)(
ctx
,
rw
,
current
));
CHECK
(
FUNC
(
quantization_params
)(
ctx
,
rw
,
current
));
CHECK
(
FUNC
(
segmentation_params
)(
ctx
,
rw
,
current
));
CHECK
(
FUNC
(
tile_info
)(
ctx
,
rw
,
current
));
f
(
16
,
header_size_in_bytes
);
return
0
;
}
static
int
FUNC
(
trailing_bits
)(
CodedBitstreamContext
*
ctx
,
RWContext
*
rw
)
{
int
err
;
av_unused
int
zero
=
0
;
while
(
byte_alignment
(
rw
)
!=
0
)
xf
(
1
,
zero_bit
,
zero
,
0
);
return
0
;
}
static
int
FUNC
(
frame
)(
CodedBitstreamContext
*
ctx
,
RWContext
*
rw
,
VP9RawFrame
*
current
)
{
int
err
;
HEADER
(
"Frame"
);
CHECK
(
FUNC
(
uncompressed_header
)(
ctx
,
rw
,
&
current
->
header
));
CHECK
(
FUNC
(
trailing_bits
)(
ctx
,
rw
));
return
0
;
}
static
int
FUNC
(
superframe_index
)(
CodedBitstreamContext
*
ctx
,
RWContext
*
rw
,
VP9RawSuperframeIndex
*
current
)
{
int
err
,
i
;
HEADER
(
"Superframe Index"
);
f
(
3
,
superframe_marker
);
f
(
2
,
bytes_per_framesize_minus_1
);
f
(
3
,
frames_in_superframe_minus_1
);
for
(
i
=
0
;
i
<=
current
->
frames_in_superframe_minus_1
;
i
++
)
{
// Surprise little-endian!
fle
(
8
*
(
current
->
bytes_per_framesize_minus_1
+
1
),
frame_sizes
[
i
],
1
,
i
);
}
f
(
3
,
superframe_marker
);
f
(
2
,
bytes_per_framesize_minus_1
);
f
(
3
,
frames_in_superframe_minus_1
);
return
0
;
}
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