Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Xiph.Org
aom-rav1e
Commits
759afe52
Commit
759afe52
authored
Sep 03, 2014
by
Minghai Shang
Committed by
Gerrit Code Review
Sep 03, 2014
Browse files
Merge "[svc] Temporal svc with two pass rate control"
parents
14bcbdac
be3b08da
Changes
14
Hide whitespace changes
Inline
Side-by-side
examples/vp9_spatial_svc_encoder.c
View file @
759afe52
...
...
@@ -38,8 +38,10 @@ static const arg_def_t timebase_arg =
ARG_DEF
(
"t"
,
"timebase"
,
1
,
"timebase (num/den)"
);
static
const
arg_def_t
bitrate_arg
=
ARG_DEF
(
"b"
,
"target-bitrate"
,
1
,
"encoding bitrate, in kilobits per second"
);
static
const
arg_def_t
layers_arg
=
ARG_DEF
(
"l"
,
"layers"
,
1
,
"number of SVC layers"
);
static
const
arg_def_t
spatial_layers_arg
=
ARG_DEF
(
"sl"
,
"spatial-layers"
,
1
,
"number of spatial SVC layers"
);
static
const
arg_def_t
temporal_layers_arg
=
ARG_DEF
(
"tl"
,
"temporal-layers"
,
1
,
"number of temporal SVC layers"
);
static
const
arg_def_t
kf_dist_arg
=
ARG_DEF
(
"k"
,
"kf-dist"
,
1
,
"number of frames between keyframes"
);
static
const
arg_def_t
scale_factors_arg
=
...
...
@@ -65,10 +67,11 @@ static const arg_def_t max_bitrate_arg =
static
const
arg_def_t
*
svc_args
[]
=
{
&
frames_arg
,
&
width_arg
,
&
height_arg
,
&
timebase_arg
,
&
bitrate_arg
,
&
skip_frames_arg
,
&
layers_arg
,
&
timebase_arg
,
&
bitrate_arg
,
&
skip_frames_arg
,
&
spatial_
layers_arg
,
&
kf_dist_arg
,
&
scale_factors_arg
,
&
quantizers_arg
,
&
passes_arg
,
&
pass_arg
,
&
fpf_name_arg
,
&
min_q_arg
,
&
max_q_arg
,
&
min_bitrate_arg
,
&
max_bitrate_arg
,
NULL
&
min_bitrate_arg
,
&
max_bitrate_arg
,
&
temporal_layers_arg
,
NULL
};
static
const
uint32_t
default_frames_to_skip
=
0
;
...
...
@@ -79,6 +82,7 @@ static const uint32_t default_timebase_num = 1;
static
const
uint32_t
default_timebase_den
=
60
;
static
const
uint32_t
default_bitrate
=
1000
;
static
const
uint32_t
default_spatial_layers
=
5
;
static
const
uint32_t
default_temporal_layers
=
1
;
static
const
uint32_t
default_kf_dist
=
100
;
typedef
struct
{
...
...
@@ -119,6 +123,7 @@ static void parse_command_line(int argc, const char **argv_,
// initialize SvcContext with parameters that will be passed to vpx_svc_init
svc_ctx
->
log_level
=
SVC_LOG_DEBUG
;
svc_ctx
->
spatial_layers
=
default_spatial_layers
;
svc_ctx
->
temporal_layers
=
default_temporal_layers
;
// start with default encoder configuration
res
=
vpx_codec_enc_config_default
(
vpx_codec_vp9_cx
(),
enc_cfg
,
0
);
...
...
@@ -156,8 +161,10 @@ static void parse_command_line(int argc, const char **argv_,
enc_cfg
->
rc_target_bitrate
=
arg_parse_uint
(
&
arg
);
}
else
if
(
arg_match
(
&
arg
,
&
skip_frames_arg
,
argi
))
{
app_input
->
frames_to_skip
=
arg_parse_uint
(
&
arg
);
}
else
if
(
arg_match
(
&
arg
,
&
layers_arg
,
argi
))
{
}
else
if
(
arg_match
(
&
arg
,
&
spatial_
layers_arg
,
argi
))
{
svc_ctx
->
spatial_layers
=
arg_parse_uint
(
&
arg
);
}
else
if
(
arg_match
(
&
arg
,
&
temporal_layers_arg
,
argi
))
{
svc_ctx
->
temporal_layers
=
arg_parse_uint
(
&
arg
);
}
else
if
(
arg_match
(
&
arg
,
&
kf_dist_arg
,
argi
))
{
enc_cfg
->
kf_min_dist
=
arg_parse_uint
(
&
arg
);
enc_cfg
->
kf_max_dist
=
enc_cfg
->
kf_min_dist
;
...
...
test/svc_test.cc
View file @
759afe52
...
...
@@ -212,13 +212,13 @@ class SvcTest : public ::testing::Test {
EXPECT_EQ
(
received_frames
,
n
);
}
void
Drop
EnhancementLayers
(
struct
vpx_fixed_buf
*
const
inputs
,
const
int
num_super_frames
,
const
int
remained_layers
,
const
bool
is_multiple_frame_context
)
{
void
Drop
LayersAndMakeItVP9Comaptible
(
struct
vpx_fixed_buf
*
const
inputs
,
const
int
num_super_frames
,
const
int
remained_
spatial_
layers
,
const
bool
is_multiple_frame_context
s
)
{
ASSERT_TRUE
(
inputs
!=
NULL
);
ASSERT_GT
(
num_super_frames
,
0
);
ASSERT_GT
(
remained_layers
,
0
);
ASSERT_GT
(
remained_
spatial_
layers
,
0
);
for
(
int
i
=
0
;
i
<
num_super_frames
;
++
i
)
{
uint32_t
frame_sizes
[
8
]
=
{
0
};
...
...
@@ -234,64 +234,110 @@ class SvcTest : public ::testing::Test {
NULL
,
NULL
);
ASSERT_EQ
(
VPX_CODEC_OK
,
res
);
uint8_t
*
frame_data
=
static_cast
<
uint8_t
*>
(
inputs
[
i
].
buf
);
uint8_t
*
frame_start
=
frame_data
;
for
(
frame
=
0
;
frame
<
frame_count
;
++
frame
)
{
// Looking for a visible frame.
if
(
frame_data
[
0
]
&
0x02
)
{
++
frames_found
;
if
(
frames_found
==
remained_layers
)
break
;
if
(
frame_count
==
0
)
{
// There's no super frame but only a single frame.
ASSERT_EQ
(
1
,
remained_spatial_layers
);
if
(
is_multiple_frame_contexts
)
{
// Make a new super frame.
uint8_t
marker
=
0xc1
;
unsigned
int
mask
;
int
mag
;
// Choose the magnitude.
for
(
mag
=
0
,
mask
=
0xff
;
mag
<
4
;
++
mag
)
{
if
(
inputs
[
i
].
sz
<
mask
)
break
;
mask
<<=
8
;
mask
|=
0xff
;
}
marker
|=
mag
<<
3
;
int
index_sz
=
2
+
(
mag
+
1
)
*
2
;
inputs
[
i
].
buf
=
realloc
(
inputs
[
i
].
buf
,
inputs
[
i
].
sz
+
index_sz
+
16
);
ASSERT_TRUE
(
inputs
[
i
].
buf
!=
NULL
);
uint8_t
*
frame_data
=
static_cast
<
uint8_t
*>
(
inputs
[
i
].
buf
);
frame_data
[
0
]
&=
~
2
;
// Set the show_frame flag to 0.
frame_data
+=
inputs
[
i
].
sz
;
// Add an one byte frame with show_existing_frame.
*
frame_data
++
=
0x88
;
// Write the super frame index.
*
frame_data
++
=
marker
;
frame_sizes
[
0
]
=
inputs
[
i
].
sz
;
frame_sizes
[
1
]
=
1
;
for
(
int
j
=
0
;
j
<
2
;
++
j
)
{
unsigned
int
this_sz
=
frame_sizes
[
j
];
for
(
int
k
=
0
;
k
<=
mag
;
k
++
)
{
*
frame_data
++
=
this_sz
&
0xff
;
this_sz
>>=
8
;
}
}
*
frame_data
++
=
marker
;
inputs
[
i
].
sz
+=
index_sz
+
1
;
}
}
else
{
// Found a super frame.
uint8_t
*
frame_data
=
static_cast
<
uint8_t
*>
(
inputs
[
i
].
buf
);
uint8_t
*
frame_start
=
frame_data
;
for
(
frame
=
0
;
frame
<
frame_count
;
++
frame
)
{
// Looking for a visible frame.
if
(
frame_data
[
0
]
&
0x02
)
{
++
frames_found
;
if
(
frames_found
==
remained_spatial_layers
)
break
;
}
frame_data
+=
frame_sizes
[
frame
];
}
ASSERT_LT
(
frame
,
frame_count
)
<<
"Couldn't find a visible frame. "
<<
"remained_spatial_layers: "
<<
remained_spatial_layers
<<
" super_frame: "
<<
i
<<
" is_multiple_frame_context: "
<<
is_multiple_frame_contexts
;
if
(
frame
==
frame_count
-
1
&&
!
is_multiple_frame_contexts
)
continue
;
frame_data
+=
frame_sizes
[
frame
];
}
ASSERT_LT
(
frame
,
frame_count
)
<<
"Couldn't find a visible frame. "
<<
"remaining_layers: "
<<
remained_layers
<<
" super_frame: "
<<
i
<<
" is_multiple_frame_context: "
<<
is_multiple_frame_context
;
if
(
frame
==
frame_count
-
1
&&
!
is_multiple_frame_context
)
continue
;
frame_data
+=
frame_sizes
[
frame
];
// We need to add one more frame for multiple frame context.
if
(
is_multiple_frame_context
)
++
frame
;
uint8_t
marker
=
static_cast
<
const
uint8_t
*>
(
inputs
[
i
].
buf
)[
inputs
[
i
].
sz
-
1
];
const
uint32_t
mag
=
((
marker
>>
3
)
&
0x3
)
+
1
;
const
size_t
index_sz
=
2
+
mag
*
frame_count
;
const
size_t
new_index_sz
=
2
+
mag
*
(
frame
+
1
);
marker
&=
0x0f8
;
marker
|=
frame
;
// Copy existing frame sizes.
memmove
(
frame_data
+
(
is_multiple_frame_context
?
2
:
1
),
frame_start
+
inputs
[
i
].
sz
-
index_sz
+
1
,
new_index_sz
-
2
);
if
(
is_multiple_frame_context
)
{
// Add a one byte frame with flag show_existing frame.
*
frame_data
++
=
0x88
|
(
remained_layers
-
1
);
}
// New marker.
frame_data
[
0
]
=
marker
;
frame_data
+=
(
mag
*
(
frame
+
1
)
+
1
);
if
(
is_multiple_frame_context
)
{
// Write the frame size for the one byte frame.
frame_data
-=
mag
;
*
frame_data
++
=
1
;
for
(
uint32_t
j
=
1
;
j
<
mag
;
++
j
)
{
*
frame_data
++
=
0
;
// We need to add one more frame for multiple frame contexts.
if
(
is_multiple_frame_contexts
)
++
frame
;
uint8_t
marker
=
static_cast
<
const
uint8_t
*>
(
inputs
[
i
].
buf
)[
inputs
[
i
].
sz
-
1
];
const
uint32_t
mag
=
((
marker
>>
3
)
&
0x3
)
+
1
;
const
size_t
index_sz
=
2
+
mag
*
frame_count
;
const
size_t
new_index_sz
=
2
+
mag
*
(
frame
+
1
);
marker
&=
0x0f8
;
marker
|=
frame
;
// Copy existing frame sizes.
memmove
(
frame_data
+
(
is_multiple_frame_contexts
?
2
:
1
),
frame_start
+
inputs
[
i
].
sz
-
index_sz
+
1
,
new_index_sz
-
2
);
if
(
is_multiple_frame_contexts
)
{
// Add a one byte frame with flag show_existing_frame.
*
frame_data
++
=
0x88
|
(
remained_spatial_layers
-
1
);
}
// New marker.
frame_data
[
0
]
=
marker
;
frame_data
+=
(
mag
*
(
frame
+
1
)
+
1
);
if
(
is_multiple_frame_contexts
)
{
// Write the frame size for the one byte frame.
frame_data
-=
mag
;
*
frame_data
++
=
1
;
for
(
uint32_t
j
=
1
;
j
<
mag
;
++
j
)
{
*
frame_data
++
=
0
;
}
}
}
*
frame_data
++
=
marker
;
inputs
[
i
].
sz
=
frame_data
-
frame_start
;
*
frame_data
++
=
marker
;
inputs
[
i
].
sz
=
frame_data
-
frame_start
;
if
(
is_multiple_frame_context
)
{
// Change the show frame flag to 0 for all frames.
for
(
int
j
=
0
;
j
<
frame
;
++
j
)
{
frame_start
[
0
]
&=
~
2
;
frame_start
+=
frame_sizes
[
j
];
if
(
is_multiple_frame_contexts
)
{
// Change the show frame flag to 0 for all frames.
for
(
int
j
=
0
;
j
<
frame
;
++
j
)
{
frame_start
[
0
]
&=
~
2
;
frame_start
+=
frame_sizes
[
j
];
}
}
}
}
...
...
@@ -359,7 +405,7 @@ TEST_F(SvcTest, InvalidOptions) {
}
TEST_F
(
SvcTest
,
SetLayersOption
)
{
vpx_codec_err_t
res
=
vpx_svc_set_options
(
&
svc_
,
"layers=3"
);
vpx_codec_err_t
res
=
vpx_svc_set_options
(
&
svc_
,
"
spatial-
layers=3"
);
EXPECT_EQ
(
VPX_CODEC_OK
,
res
);
InitializeEncoder
();
EXPECT_EQ
(
3
,
svc_
.
spatial_layers
);
...
...
@@ -367,7 +413,7 @@ TEST_F(SvcTest, SetLayersOption) {
TEST_F
(
SvcTest
,
SetMultipleOptions
)
{
vpx_codec_err_t
res
=
vpx_svc_set_options
(
&
svc_
,
"layers=2 scale-factors=1/3,2/3"
);
vpx_svc_set_options
(
&
svc_
,
"
spatial-
layers=2 scale-factors=1/3,2/3"
);
EXPECT_EQ
(
VPX_CODEC_OK
,
res
);
InitializeEncoder
();
EXPECT_EQ
(
2
,
svc_
.
spatial_layers
);
...
...
@@ -529,7 +575,7 @@ TEST_F(SvcTest, TwoPassEncode20FramesWithAltRef) {
FreeBitstreamBuffers
(
&
outputs
[
0
],
20
);
}
TEST_F
(
SvcTest
,
TwoPassEncode2LayersDecodeBaseLayerOnly
)
{
TEST_F
(
SvcTest
,
TwoPassEncode2
Spatial
LayersDecodeBaseLayerOnly
)
{
// First pass encode
std
::
string
stats_buf
;
Pass1EncodeNFrames
(
10
,
2
,
&
stats_buf
);
...
...
@@ -540,12 +586,12 @@ TEST_F(SvcTest, TwoPassEncode2LayersDecodeBaseLayerOnly) {
vpx_fixed_buf
outputs
[
10
];
memset
(
&
outputs
[
0
],
0
,
sizeof
(
outputs
));
Pass2EncodeNFrames
(
&
stats_buf
,
10
,
2
,
&
outputs
[
0
]);
Drop
EnhancementLayers
(
&
outputs
[
0
],
10
,
1
,
false
);
Drop
LayersAndMakeItVP9Comaptible
(
&
outputs
[
0
],
10
,
1
,
false
);
DecodeNFrames
(
&
outputs
[
0
],
10
);
FreeBitstreamBuffers
(
&
outputs
[
0
],
10
);
}
TEST_F
(
SvcTest
,
TwoPassEncode5LayersDecode54321Layers
)
{
TEST_F
(
SvcTest
,
TwoPassEncode5
Spatial
LayersDecode54321Layers
)
{
// First pass encode
std
::
string
stats_buf
;
Pass1EncodeNFrames
(
10
,
5
,
&
stats_buf
);
...
...
@@ -558,13 +604,13 @@ TEST_F(SvcTest, TwoPassEncode5LayersDecode54321Layers) {
Pass2EncodeNFrames
(
&
stats_buf
,
10
,
5
,
&
outputs
[
0
]);
DecodeNFrames
(
&
outputs
[
0
],
10
);
Drop
EnhancementLayers
(
&
outputs
[
0
],
10
,
4
,
false
);
Drop
LayersAndMakeItVP9Comaptible
(
&
outputs
[
0
],
10
,
4
,
false
);
DecodeNFrames
(
&
outputs
[
0
],
10
);
Drop
EnhancementLayers
(
&
outputs
[
0
],
10
,
3
,
false
);
Drop
LayersAndMakeItVP9Comaptible
(
&
outputs
[
0
],
10
,
3
,
false
);
DecodeNFrames
(
&
outputs
[
0
],
10
);
Drop
EnhancementLayers
(
&
outputs
[
0
],
10
,
2
,
false
);
Drop
LayersAndMakeItVP9Comaptible
(
&
outputs
[
0
],
10
,
2
,
false
);
DecodeNFrames
(
&
outputs
[
0
],
10
);
Drop
EnhancementLayers
(
&
outputs
[
0
],
10
,
1
,
false
);
Drop
LayersAndMakeItVP9Comaptible
(
&
outputs
[
0
],
10
,
1
,
false
);
DecodeNFrames
(
&
outputs
[
0
],
10
);
FreeBitstreamBuffers
(
&
outputs
[
0
],
10
);
...
...
@@ -601,15 +647,15 @@ TEST_F(SvcTest, TwoPassEncode3SNRLayersDecode321Layers) {
memset
(
&
outputs
[
0
],
0
,
sizeof
(
outputs
));
Pass2EncodeNFrames
(
&
stats_buf
,
20
,
3
,
&
outputs
[
0
]);
DecodeNFrames
(
&
outputs
[
0
],
20
);
Drop
EnhancementLayers
(
&
outputs
[
0
],
20
,
2
,
false
);
Drop
LayersAndMakeItVP9Comaptible
(
&
outputs
[
0
],
20
,
2
,
false
);
DecodeNFrames
(
&
outputs
[
0
],
20
);
Drop
EnhancementLayers
(
&
outputs
[
0
],
20
,
1
,
false
);
Drop
LayersAndMakeItVP9Comaptible
(
&
outputs
[
0
],
20
,
1
,
false
);
DecodeNFrames
(
&
outputs
[
0
],
20
);
FreeBitstreamBuffers
(
&
outputs
[
0
],
20
);
}
TEST_F
(
SvcTest
,
SetMultipleFrameContextOption
)
{
TEST_F
(
SvcTest
,
SetMultipleFrameContext
s
Option
)
{
svc_
.
spatial_layers
=
5
;
vpx_codec_err_t
res
=
vpx_svc_set_options
(
&
svc_
,
"multi-frame-contexts=1"
);
...
...
@@ -622,7 +668,7 @@ TEST_F(SvcTest, SetMultipleFrameContextOption) {
InitializeEncoder
();
}
TEST_F
(
SvcTest
,
TwoPassEncode2LayersWithMultipleFrameContext
)
{
TEST_F
(
SvcTest
,
TwoPassEncode2
Spatial
LayersWithMultipleFrameContext
s
)
{
// First pass encode
std
::
string
stats_buf
;
Pass1EncodeNFrames
(
10
,
2
,
&
stats_buf
);
...
...
@@ -634,12 +680,13 @@ TEST_F(SvcTest, TwoPassEncode2LayersWithMultipleFrameContext) {
vpx_fixed_buf
outputs
[
10
];
memset
(
&
outputs
[
0
],
0
,
sizeof
(
outputs
));
Pass2EncodeNFrames
(
&
stats_buf
,
10
,
2
,
&
outputs
[
0
]);
Drop
EnhancementLayers
(
&
outputs
[
0
],
10
,
2
,
true
);
Drop
LayersAndMakeItVP9Comaptible
(
&
outputs
[
0
],
10
,
2
,
true
);
DecodeNFrames
(
&
outputs
[
0
],
10
);
FreeBitstreamBuffers
(
&
outputs
[
0
],
10
);
}
TEST_F
(
SvcTest
,
TwoPassEncode2LayersWithMultipleFrameContextDecodeBaselayer
)
{
TEST_F
(
SvcTest
,
TwoPassEncode2SpatialLayersWithMultipleFrameContextsDecodeBaselayer
)
{
// First pass encode
std
::
string
stats_buf
;
Pass1EncodeNFrames
(
10
,
2
,
&
stats_buf
);
...
...
@@ -651,12 +698,12 @@ TEST_F(SvcTest, TwoPassEncode2LayersWithMultipleFrameContextDecodeBaselayer) {
vpx_fixed_buf
outputs
[
10
];
memset
(
&
outputs
[
0
],
0
,
sizeof
(
outputs
));
Pass2EncodeNFrames
(
&
stats_buf
,
10
,
2
,
&
outputs
[
0
]);
Drop
EnhancementLayers
(
&
outputs
[
0
],
10
,
1
,
true
);
Drop
LayersAndMakeItVP9Comaptible
(
&
outputs
[
0
],
10
,
1
,
true
);
DecodeNFrames
(
&
outputs
[
0
],
10
);
FreeBitstreamBuffers
(
&
outputs
[
0
],
10
);
}
TEST_F
(
SvcTest
,
TwoPassEncode2SNRLayersWithMultipleFrameContext
)
{
TEST_F
(
SvcTest
,
TwoPassEncode2SNRLayersWithMultipleFrameContext
s
)
{
// First pass encode
std
::
string
stats_buf
;
vpx_svc_set_options
(
&
svc_
,
"scale-factors=1/1,1/1"
);
...
...
@@ -670,12 +717,13 @@ TEST_F(SvcTest, TwoPassEncode2SNRLayersWithMultipleFrameContext) {
vpx_fixed_buf
outputs
[
10
];
memset
(
&
outputs
[
0
],
0
,
sizeof
(
outputs
));
Pass2EncodeNFrames
(
&
stats_buf
,
10
,
2
,
&
outputs
[
0
]);
Drop
EnhancementLayers
(
&
outputs
[
0
],
10
,
2
,
true
);
Drop
LayersAndMakeItVP9Comaptible
(
&
outputs
[
0
],
10
,
2
,
true
);
DecodeNFrames
(
&
outputs
[
0
],
10
);
FreeBitstreamBuffers
(
&
outputs
[
0
],
10
);
}
TEST_F
(
SvcTest
,
TwoPassEncode3SNRLayersWithMultipleFrameContextDecode321Layer
)
{
TEST_F
(
SvcTest
,
TwoPassEncode3SNRLayersWithMultipleFrameContextsDecode321Layer
)
{
// First pass encode
std
::
string
stats_buf
;
vpx_svc_set_options
(
&
svc_
,
"scale-factors=1/1,1/1,1/1"
);
...
...
@@ -697,25 +745,114 @@ TEST_F(SvcTest, TwoPassEncode3SNRLayersWithMultipleFrameContextDecode321Layer) {
memcpy
(
outputs_new
[
i
].
buf
,
outputs
[
i
].
buf
,
outputs
[
i
].
sz
);
outputs_new
[
i
].
sz
=
outputs
[
i
].
sz
;
}
Drop
EnhancementLayers
(
&
outputs_new
[
0
],
10
,
3
,
true
);
Drop
LayersAndMakeItVP9Comaptible
(
&
outputs_new
[
0
],
10
,
3
,
true
);
DecodeNFrames
(
&
outputs_new
[
0
],
10
);
for
(
int
i
=
0
;
i
<
10
;
++
i
)
{
memcpy
(
outputs_new
[
i
].
buf
,
outputs
[
i
].
buf
,
outputs
[
i
].
sz
);
outputs_new
[
i
].
sz
=
outputs
[
i
].
sz
;
}
Drop
EnhancementLayers
(
&
outputs_new
[
0
],
10
,
2
,
true
);
Drop
LayersAndMakeItVP9Comaptible
(
&
outputs_new
[
0
],
10
,
2
,
true
);
DecodeNFrames
(
&
outputs_new
[
0
],
10
);
for
(
int
i
=
0
;
i
<
10
;
++
i
)
{
memcpy
(
outputs_new
[
i
].
buf
,
outputs
[
i
].
buf
,
outputs
[
i
].
sz
);
outputs_new
[
i
].
sz
=
outputs
[
i
].
sz
;
}
Drop
EnhancementLayers
(
&
outputs_new
[
0
],
10
,
1
,
true
);
Drop
LayersAndMakeItVP9Comaptible
(
&
outputs_new
[
0
],
10
,
1
,
true
);
DecodeNFrames
(
&
outputs_new
[
0
],
10
);
FreeBitstreamBuffers
(
&
outputs
[
0
],
10
);
FreeBitstreamBuffers
(
&
outputs_new
[
0
],
10
);
}
TEST_F
(
SvcTest
,
TwoPassEncode2TemporalLayers
)
{
// First pass encode
std
::
string
stats_buf
;
vpx_svc_set_options
(
&
svc_
,
"scale-factors=1/1"
);
svc_
.
temporal_layers
=
2
;
Pass1EncodeNFrames
(
10
,
1
,
&
stats_buf
);
// Second pass encode
codec_enc_
.
g_pass
=
VPX_RC_LAST_PASS
;
svc_
.
temporal_layers
=
2
;
vpx_svc_set_options
(
&
svc_
,
"auto-alt-refs=1 scale-factors=1/1"
);
vpx_fixed_buf
outputs
[
10
];
memset
(
&
outputs
[
0
],
0
,
sizeof
(
outputs
));
Pass2EncodeNFrames
(
&
stats_buf
,
10
,
1
,
&
outputs
[
0
]);
DecodeNFrames
(
&
outputs
[
0
],
10
);
FreeBitstreamBuffers
(
&
outputs
[
0
],
10
);
}
TEST_F
(
SvcTest
,
TwoPassEncode2TemporalLayersWithMultipleFrameContexts
)
{
// First pass encode
std
::
string
stats_buf
;
vpx_svc_set_options
(
&
svc_
,
"scale-factors=1/1"
);
svc_
.
temporal_layers
=
2
;
Pass1EncodeNFrames
(
10
,
1
,
&
stats_buf
);
// Second pass encode
codec_enc_
.
g_pass
=
VPX_RC_LAST_PASS
;
svc_
.
temporal_layers
=
2
;
codec_enc_
.
g_error_resilient
=
0
;
vpx_svc_set_options
(
&
svc_
,
"auto-alt-refs=1 scale-factors=1/1 "
"multi-frame-contexts=1"
);
vpx_fixed_buf
outputs
[
10
];
memset
(
&
outputs
[
0
],
0
,
sizeof
(
outputs
));
Pass2EncodeNFrames
(
&
stats_buf
,
10
,
1
,
&
outputs
[
0
]);
DropLayersAndMakeItVP9Comaptible
(
&
outputs
[
0
],
10
,
1
,
true
);
DecodeNFrames
(
&
outputs
[
0
],
10
);
FreeBitstreamBuffers
(
&
outputs
[
0
],
10
);
}
TEST_F
(
SvcTest
,
TwoPassEncode2TemporalLayersDecodeBaseLayer
)
{
// First pass encode
std
::
string
stats_buf
;
vpx_svc_set_options
(
&
svc_
,
"scale-factors=1/1"
);
svc_
.
temporal_layers
=
2
;
Pass1EncodeNFrames
(
10
,
1
,
&
stats_buf
);
// Second pass encode
codec_enc_
.
g_pass
=
VPX_RC_LAST_PASS
;
svc_
.
temporal_layers
=
2
;
vpx_svc_set_options
(
&
svc_
,
"auto-alt-refs=1 scale-factors=1/1"
);
vpx_fixed_buf
outputs
[
10
];
memset
(
&
outputs
[
0
],
0
,
sizeof
(
outputs
));
Pass2EncodeNFrames
(
&
stats_buf
,
10
,
1
,
&
outputs
[
0
]);
vpx_fixed_buf
base_layer
[
5
];
for
(
int
i
=
0
;
i
<
5
;
++
i
)
base_layer
[
i
]
=
outputs
[
i
*
2
];
DecodeNFrames
(
&
base_layer
[
0
],
5
);
FreeBitstreamBuffers
(
&
outputs
[
0
],
10
);
}
TEST_F
(
SvcTest
,
TwoPassEncode2TemporalLayersWithMultipleFrameContextsDecodeBaseLayer
)
{
// First pass encode
std
::
string
stats_buf
;
vpx_svc_set_options
(
&
svc_
,
"scale-factors=1/1"
);
svc_
.
temporal_layers
=
2
;
Pass1EncodeNFrames
(
10
,
1
,
&
stats_buf
);
// Second pass encode
codec_enc_
.
g_pass
=
VPX_RC_LAST_PASS
;
svc_
.
temporal_layers
=
2
;
codec_enc_
.
g_error_resilient
=
0
;
vpx_svc_set_options
(
&
svc_
,
"auto-alt-refs=1 scale-factors=1/1 "
"multi-frame-contexts=1"
);
vpx_fixed_buf
outputs
[
10
];
memset
(
&
outputs
[
0
],
0
,
sizeof
(
outputs
));
Pass2EncodeNFrames
(
&
stats_buf
,
10
,
1
,
&
outputs
[
0
]);
DropLayersAndMakeItVP9Comaptible
(
&
outputs
[
0
],
10
,
1
,
true
);
vpx_fixed_buf
base_layer
[
5
];
for
(
int
i
=
0
;
i
<
5
;
++
i
)
base_layer
[
i
]
=
outputs
[
i
*
2
];
DecodeNFrames
(
&
base_layer
[
0
],
5
);
FreeBitstreamBuffers
(
&
outputs
[
0
],
10
);
}
}
// namespace
vp9/encoder/vp9_bitstream.c
View file @
759afe52
...
...
@@ -999,8 +999,10 @@ static void write_frame_size_with_refs(VP9_COMP *cpi,
// Set "found" to 0 for temporal svc and for spatial svc key frame
if
(
cpi
->
use_svc
&&
(
cpi
->
svc
.
number_spatial_layers
==
1
||
cpi
->
svc
.
layer_context
[
cpi
->
svc
.
spatial_layer_id
].
is_key_frame
))
{
((
cpi
->
svc
.
number_temporal_layers
>
1
&&
cpi
->
oxcf
.
rc_mode
==
VPX_CBR
)
||
(
cpi
->
svc
.
number_spatial_layers
>
1
&&
cpi
->
svc
.
layer_context
[
cpi
->
svc
.
spatial_layer_id
].
is_key_frame
)))
{
found
=
0
;
}
vp9_wb_write_bit
(
wb
,
found
);
...
...
@@ -1093,7 +1095,7 @@ static void write_uncompressed_header(VP9_COMP *cpi,
// show_existing_frame flag which tells the decoder which frame we want to
// show.
if
(
!
cm
->
show_frame
||
(
is_
spatial
_svc
(
cpi
)
&&
cm
->
error_resilient_mode
==
0
))
(
is_
two_pass
_svc
(
cpi
)
&&
cm
->
error_resilient_mode
==
0
))
vp9_wb_write_bit
(
wb
,
cm
->
intra_only
);
if
(
!
cm
->
error_resilient_mode
)
...
...
vp9/encoder/vp9_bitstream.h
View file @
759afe52
...
...
@@ -26,7 +26,7 @@ static INLINE int vp9_preserve_existing_gf(VP9_COMP *cpi) {
return
!
cpi
->
multi_arf_allowed
&&
cpi
->
refresh_golden_frame
&&
cpi
->
rc
.
is_src_frame_alt_ref
&&
(
!
cpi
->
use_svc
||
// Add spatial svc base layer case here
(
is_
spatial
_svc
(
cpi
)
&&
(
is_
two_pass
_svc
(
cpi
)
&&
cpi
->
svc
.
spatial_layer_id
==
0
&&
cpi
->
svc
.
layer_context
[
0
].
gold_ref_idx
>=
0
&&
cpi
->
oxcf
.
ss_play_alternate
[
0
]));
...
...
vp9/encoder/vp9_encoder.c
View file @
759afe52
...
...
@@ -128,7 +128,7 @@ static void setup_frame(VP9_COMP *cpi) {
}
if
(
cm
->
frame_type
==
KEY_FRAME
)
{
if
(
!
is_
spatial
_svc
(
cpi
))
if
(
!
is_
two_pass
_svc
(
cpi
))
cpi
->
refresh_golden_frame
=
1
;
cpi
->
refresh_alt_ref_frame
=
1
;
vp9_zero
(
cpi
->
interp_filter_selected
);
...
...
@@ -525,7 +525,7 @@ static void update_frame_size(VP9_COMP *cpi) {
vp9_init_context_buffers
(
cm
);
init_macroblockd
(
cm
,
xd
);
if
(
is_
spatial
_svc
(
cpi
))
{
if
(
is_
two_pass
_svc
(
cpi
))
{
if
(
vp9_realloc_frame_buffer
(
&
cpi
->
alt_ref_buffer
,
cm
->
width
,
cm
->
height
,
cm
->
subsampling_x
,
cm
->
subsampling_y
,
...
...
@@ -580,7 +580,9 @@ static void init_config(struct VP9_COMP *cpi, VP9EncoderConfig *oxcf) {
cpi
->
svc
.
number_temporal_layers
=
oxcf
->
ts_number_layers
;
if
((
cpi
->
svc
.
number_temporal_layers
>
1
&&
cpi
->
oxcf
.
rc_mode
==
VPX_CBR
)
||
(
cpi
->
svc
.
number_spatial_layers
>
1
&&
cpi
->
oxcf
.
pass
==
2
))
{
((
cpi
->
svc
.
number_temporal_layers
>
1
||
cpi
->
svc
.
number_spatial_layers
>
1
)
&&
cpi
->
oxcf
.
pass
==
2
))
{
vp9_init_layer_context
(
cpi
);
}
...
...
@@ -672,7 +674,9 @@ void vp9_change_config(struct VP9_COMP *cpi, const VP9EncoderConfig *oxcf) {
if
((
cpi
->
svc
.
number_temporal_layers
>
1
&&
cpi
->
oxcf
.
rc_mode
==
VPX_CBR
)
||
(
cpi
->
svc
.
number_spatial_layers
>
1
&&
cpi
->
oxcf
.
pass
==
2
))
{
((
cpi
->
svc
.
number_temporal_layers
>
1
||
cpi
->
svc
.
number_spatial_layers
>
1
)
&&
cpi
->
oxcf
.
pass
==
2
))
{
vp9_update_layer_context_change_config
(
cpi
,
(
int
)
cpi
->
oxcf
.
target_bandwidth
);
}
...
...
@@ -923,7 +927,7 @@ VP9_COMP *vp9_create_compressor(VP9EncoderConfig *oxcf) {
const
int
packets
=
(
int
)(
oxcf
->
two_pass_stats_in
.
sz
/
packet_sz
);
if
(
cpi
->
svc
.
number_spatial_layers
>
1
&&
cpi
->
svc
.
number_temporal_layers
==
1
)
{
||
cpi
->
svc
.
number_temporal_layers
>
1
)
{
FIRSTPASS_STATS
*
const
stats
=
oxcf
->
two_pass_stats_in
.
buf
;
FIRSTPASS_STATS
*
stats_copy
[
VPX_SS_MAX_LAYERS
]
=
{
0
};
int
i
;
...
...
@@ -1531,7 +1535,7 @@ void vp9_update_reference_frames(VP9_COMP *cpi) {
cpi
->
alt_fb_idx
=
cpi
->
gld_fb_idx
;
cpi
->
gld_fb_idx
=
tmp
;
if
(
is_
spatial
_svc
(
cpi
))
{
if
(
is_
two_pass
_svc
(
cpi
))
{
cpi
->
svc
.
layer_context
[
0
].
gold_ref_idx
=
cpi
->
gld_fb_idx
;
cpi
->
svc
.
layer_context
[
0
].
alt_ref_idx
=
cpi
->
alt_fb_idx
;
}
...
...
@@ -1960,8 +1964,7 @@ static int get_ref_frame_flags(const VP9_COMP *cpi) {
if
(
gold_is_last
)
flags
&=
~
VP9_GOLD_FLAG
;
if
(
cpi
->
rc
.
frames_till_gf_update_due
==
INT_MAX
&&
!
is_spatial_svc
(
cpi
))
if
(
cpi
->
rc
.
frames_till_gf_update_due
==
INT_MAX
&&
!
is_two_pass_svc
(
cpi
))
flags
&=
~
VP9_GOLD_FLAG
;
if
(
alt_is_last
)
...
...
@@ -2008,7 +2011,7 @@ static int is_skippable_frame(const VP9_COMP *cpi) {
// can be skipped for partition check, and the partition size is assigned
// according to the variance
const
SVC
*
const
svc
=
&
cpi
->
svc
;
const
TWO_PASS
*
const
twopass
=
is_
spatial
_svc
(
cpi
)
?
const
TWO_PASS
*
const
twopass
=
is_
two_pass
_svc
(
cpi
)
?
&
svc
->
layer_context
[
svc
->
spatial_layer_id
].
twopass
:
&
cpi
->
twopass
;
return
(
!
frame_is_intra_only
(
&
cpi
->
common
)
&&
...
...
@@ -2160,18 +2163,34 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
cm
->
reset_frame_context
=
2
;
}
}
if
(
is_spatial_svc
(
cpi
)
&&
cm
->
error_resilient_mode
==
0
)
{
cm
->
frame_context_idx
=
cpi
->
svc
.
spatial_layer_id
;
if
(
is_two_pass_svc
(
cpi
)
&&
cm
->
error_resilient_mode
==
0
)
{
cm
->
frame_context_idx
=
cpi
->
svc
.
spatial_layer_id
*
cpi
->
svc
.
number_temporal_layers
+
cpi
->
svc
.
temporal_layer_id
;