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="
cbs_h264
cbs_h265
cbs_mpeg2
cbs_vp9
dirac_parse
dvprofile
exif
...
...
@@ -2497,6 +2498,7 @@ threads_if_any="$THREADS_LIST"
cbs_h264_select
=
"cbs golomb"
cbs_h265_select
=
"cbs golomb"
cbs_mpeg2_select
=
"cbs"
cbs_vp9_select
=
"cbs"
dct_select
=
"rdft"
dirac_parse_select
=
"golomb"
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
headers (everything above the level of individual coded blocks).
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
...
...
libavcodec/Makefile
View file @
b5df289e
...
...
@@ -65,6 +65,7 @@ OBJS-$(CONFIG_CBS) += cbs.o
OBJS-$(CONFIG_CBS_H264)
+=
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_VP9)
+=
cbs_vp9.o
OBJS-$(CONFIG_CRYSTALHD)
+=
crystalhd.o
OBJS-$(CONFIG_DCT)
+=
dct.o
dct32_fixed.o
dct32_float.o
OBJS-$(CONFIG_ERROR_RESILIENCE)
+=
error_resilience.o
...
...
libavcodec/cbs.c
View file @
b5df289e
...
...
@@ -38,6 +38,9 @@ static const CodedBitstreamType *cbs_type_table[] = {
#if CONFIG_CBS_MPEG2
&
ff_cbs_type_mpeg2
,
#endif
#if CONFIG_CBS_VP9
&
ff_cbs_type_vp9
,
#endif
};
const
enum
AVCodecID
ff_cbs_all_codec_ids
[]
=
{
...
...
@@ -49,6 +52,9 @@ const enum AVCodecID ff_cbs_all_codec_ids[] = {
#endif
#if CONFIG_CBS_MPEG2
AV_CODEC_ID_MPEG2VIDEO
,
#endif
#if CONFIG_CBS_VP9
AV_CODEC_ID_VP9
,
#endif
AV_CODEC_ID_NONE
};
...
...
libavcodec/cbs.h
View file @
b5df289e
...
...
@@ -48,6 +48,7 @@ struct CodedBitstreamType;
* H.264 / AVC: nal_unit_type
* H.265 / HEVC: nal_unit_type
* MPEG-2: start code value (without prefix)
* VP9: unused, set to zero (every unit is a frame)
*/
typedef
uint32_t
CodedBitstreamUnitType
;
...
...
libavcodec/cbs_internal.h
View file @
b5df289e
...
...
@@ -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_h265
;
extern
const
CodedBitstreamType
ff_cbs_type_mpeg2
;
extern
const
CodedBitstreamType
ff_cbs_type_vp9
;
#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