Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
Xiph.Org
aom-rav1e
Commits
af898b56
Commit
af898b56
authored
Nov 10, 2014
by
Marco
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Various updates to vp8.
Change-Id: Icc7a816491897107764e4c936288e9000e6319b8
parent
d5937cd2
Changes
18
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
1627 additions
and
371 deletions
+1627
-371
examples/vp8_multi_resolution_encoder.c
examples/vp8_multi_resolution_encoder.c
+696
-258
examples/vpx_temporal_svc_encoder.c
examples/vpx_temporal_svc_encoder.c
+6
-0
test/error_resilience_test.cc
test/error_resilience_test.cc
+199
-1
vp8/common/blockd.h
vp8/common/blockd.h
+4
-0
vp8/common/onyx.h
vp8/common/onyx.h
+1
-0
vp8/encoder/block.h
vp8/encoder/block.h
+4
-0
vp8/encoder/denoising.c
vp8/encoder/denoising.c
+13
-6
vp8/encoder/denoising.h
vp8/encoder/denoising.h
+2
-2
vp8/encoder/encodeframe.c
vp8/encoder/encodeframe.c
+7
-1
vp8/encoder/ethreading.c
vp8/encoder/ethreading.c
+7
-2
vp8/encoder/onyx_if.c
vp8/encoder/onyx_if.c
+264
-44
vp8/encoder/onyx_int.h
vp8/encoder/onyx_int.h
+9
-0
vp8/encoder/pickinter.c
vp8/encoder/pickinter.c
+293
-32
vp8/encoder/quantize.c
vp8/encoder/quantize.c
+16
-2
vp8/encoder/ratectrl.c
vp8/encoder/ratectrl.c
+7
-1
vp8/vp8_cx_iface.c
vp8/vp8_cx_iface.c
+77
-21
vpx/vp8cx.h
vpx/vp8cx.h
+17
-0
vpxenc.c
vpxenc.c
+5
-1
No files found.
examples/vp8_multi_resolution_encoder.c
View file @
af898b56
This diff is collapsed.
Click to expand it.
examples/vpx_temporal_svc_encoder.c
View file @
af898b56
...
...
@@ -675,6 +675,9 @@ int main(int argc, char **argv) {
die_codec
(
&
codec
,
"Failed to set SVC"
);
}
}
if
(
strncmp
(
encoder
->
name
,
"vp8"
,
3
)
==
0
)
{
vpx_codec_control
(
&
codec
,
VP8E_SET_SCREEN_CONTENT_MODE
,
0
);
}
vpx_codec_control
(
&
codec
,
VP8E_SET_STATIC_THRESHOLD
,
1
);
vpx_codec_control
(
&
codec
,
VP8E_SET_TOKEN_PARTITIONS
,
1
);
// This controls the maximum target size of the key frame.
...
...
@@ -697,6 +700,9 @@ int main(int argc, char **argv) {
cfg
.
ts_layer_id
[
frame_cnt
%
cfg
.
ts_periodicity
];
if
(
strncmp
(
encoder
->
name
,
"vp9"
,
3
)
==
0
)
{
vpx_codec_control
(
&
codec
,
VP9E_SET_SVC_LAYER_ID
,
&
layer_id
);
}
else
if
(
strncmp
(
encoder
->
name
,
"vp8"
,
3
)
==
0
)
{
vpx_codec_control
(
&
codec
,
VP8E_SET_TEMPORAL_LAYER_ID
,
layer_id
.
temporal_layer_id
);
}
flags
=
layer_flags
[
frame_cnt
%
flag_periodicity
];
frame_avail
=
vpx_img_read
(
&
raw
,
infile
);
...
...
test/error_resilience_test.cc
View file @
af898b56
...
...
@@ -316,7 +316,205 @@ TEST_P(ErrorResilienceTestLarge, 2LayersDropEnhancement) {
Reset
();
}
class
ErrorResilienceTestLargeCodecControls
:
public
::
libvpx_test
::
EncoderTest
,
public
::
libvpx_test
::
CodecTestWithParam
<
libvpx_test
::
TestMode
>
{
protected:
ErrorResilienceTestLargeCodecControls
()
:
EncoderTest
(
GET_PARAM
(
0
)),
encoding_mode_
(
GET_PARAM
(
1
))
{
Reset
();
}
virtual
~
ErrorResilienceTestLargeCodecControls
()
{}
void
Reset
()
{
last_pts_
=
0
;
tot_frame_number_
=
0
;
// For testing up to 3 layers.
for
(
int
i
=
0
;
i
<
3
;
++
i
)
{
bits_total_
[
i
]
=
0
;
}
duration_
=
0.0
;
}
virtual
void
SetUp
()
{
InitializeConfig
();
SetMode
(
encoding_mode_
);
}
//
// Frame flags and layer id for temporal layers.
//
// For two layers, test pattern is:
// 1 3
// 0 2 .....
// For three layers, test pattern is:
// 1 3 5 7
// 2 6
// 0 4 ....
// LAST is always update on base/layer 0, GOLDEN is updated on layer 1,
// and ALTREF is updated on top layer for 3 layer pattern.
int
SetFrameFlags
(
int
frame_num
,
int
num_temp_layers
)
{
int
frame_flags
=
0
;
if
(
num_temp_layers
==
2
)
{
if
(
frame_num
%
2
==
0
)
{
// Layer 0: predict from L and ARF, update L.
frame_flags
=
VP8_EFLAG_NO_REF_GF
|
VP8_EFLAG_NO_UPD_GF
|
VP8_EFLAG_NO_UPD_ARF
;
}
else
{
// Layer 1: predict from L, G and ARF, and update G.
frame_flags
=
VP8_EFLAG_NO_UPD_ARF
|
VP8_EFLAG_NO_UPD_LAST
|
VP8_EFLAG_NO_UPD_ENTROPY
;
}
}
else
if
(
num_temp_layers
==
3
)
{
if
(
frame_num
%
4
==
0
)
{
// Layer 0: predict from L, update L.
frame_flags
=
VP8_EFLAG_NO_UPD_GF
|
VP8_EFLAG_NO_UPD_ARF
|
VP8_EFLAG_NO_REF_GF
|
VP8_EFLAG_NO_REF_ARF
;
}
else
if
((
frame_num
-
2
)
%
4
==
0
)
{
// Layer 1: predict from L, G, update G.
frame_flags
=
VP8_EFLAG_NO_UPD_ARF
|
VP8_EFLAG_NO_UPD_LAST
|
VP8_EFLAG_NO_REF_ARF
;
}
else
if
((
frame_num
-
1
)
%
2
==
0
)
{
// Layer 2: predict from L, G, ARF; update ARG.
frame_flags
=
VP8_EFLAG_NO_UPD_GF
|
VP8_EFLAG_NO_UPD_LAST
;
}
}
return
frame_flags
;
}
int
SetLayerId
(
int
frame_num
,
int
num_temp_layers
)
{
int
layer_id
=
0
;
if
(
num_temp_layers
==
2
)
{
if
(
frame_num
%
2
==
0
)
{
layer_id
=
0
;
}
else
{
layer_id
=
1
;
}
}
else
if
(
num_temp_layers
==
3
)
{
if
(
frame_num
%
4
==
0
)
{
layer_id
=
0
;
}
else
if
((
frame_num
-
2
)
%
4
==
0
)
{
layer_id
=
1
;
}
else
if
((
frame_num
-
1
)
%
2
==
0
)
{
layer_id
=
2
;
}
}
return
layer_id
;
}
virtual
void
PreEncodeFrameHook
(
libvpx_test
::
VideoSource
*
video
,
libvpx_test
::
Encoder
*
encoder
)
{
if
(
cfg_
.
ts_number_layers
>
1
)
{
int
layer_id
=
SetLayerId
(
video
->
frame
(),
cfg_
.
ts_number_layers
);
int
frame_flags
=
SetFrameFlags
(
video
->
frame
(),
cfg_
.
ts_number_layers
);
if
(
video
->
frame
()
>
0
)
{
encoder
->
Control
(
VP8E_SET_TEMPORAL_LAYER_ID
,
layer_id
);
encoder
->
Control
(
VP8E_SET_FRAME_FLAGS
,
frame_flags
);
}
const
vpx_rational_t
tb
=
video
->
timebase
();
timebase_
=
static_cast
<
double
>
(
tb
.
num
)
/
tb
.
den
;
duration_
=
0
;
return
;
}
}
virtual
void
FramePktHook
(
const
vpx_codec_cx_pkt_t
*
pkt
)
{
// Time since last timestamp = duration.
vpx_codec_pts_t
duration
=
pkt
->
data
.
frame
.
pts
-
last_pts_
;
if
(
duration
>
1
)
{
// Update counter for total number of frames (#frames input to encoder).
// Needed for setting the proper layer_id below.
tot_frame_number_
+=
static_cast
<
int
>
(
duration
-
1
);
}
int
layer
=
SetLayerId
(
tot_frame_number_
,
cfg_
.
ts_number_layers
);
const
size_t
frame_size_in_bits
=
pkt
->
data
.
frame
.
sz
*
8
;
// Update the total encoded bits. For temporal layers, update the cumulative
// encoded bits per layer.
for
(
int
i
=
layer
;
i
<
static_cast
<
int
>
(
cfg_
.
ts_number_layers
);
++
i
)
{
bits_total_
[
i
]
+=
frame_size_in_bits
;
}
// Update the most recent pts.
last_pts_
=
pkt
->
data
.
frame
.
pts
;
++
tot_frame_number_
;
}
virtual
void
EndPassHook
(
void
)
{
duration_
=
(
last_pts_
+
1
)
*
timebase_
;
if
(
cfg_
.
ts_number_layers
>
1
)
{
for
(
int
layer
=
0
;
layer
<
static_cast
<
int
>
(
cfg_
.
ts_number_layers
);
++
layer
)
{
if
(
bits_total_
[
layer
])
{
// Effective file datarate:
effective_datarate_
[
layer
]
=
(
bits_total_
[
layer
]
/
1000.0
)
/
duration_
;
}
}
}
}
double
effective_datarate_
[
3
];
private:
libvpx_test
::
TestMode
encoding_mode_
;
vpx_codec_pts_t
last_pts_
;
double
timebase_
;
int64_t
bits_total_
[
3
];
double
duration_
;
int
tot_frame_number_
;
};
// Check two codec controls used for:
// (1) for setting temporal layer id, and (2) for settings encoder flags.
// This test invokes those controls for each frame, and verifies encoder/decoder
// mismatch and basic rate control response.
// TODO(marpan): Maybe move this test to datarate_test.cc.
TEST_P
(
ErrorResilienceTestLargeCodecControls
,
CodecControl3TemporalLayers
)
{
cfg_
.
rc_buf_initial_sz
=
500
;
cfg_
.
rc_buf_optimal_sz
=
500
;
cfg_
.
rc_buf_sz
=
1000
;
cfg_
.
rc_dropframe_thresh
=
1
;
cfg_
.
rc_min_quantizer
=
2
;
cfg_
.
rc_max_quantizer
=
56
;
cfg_
.
rc_end_usage
=
VPX_CBR
;
cfg_
.
rc_dropframe_thresh
=
1
;
cfg_
.
g_lag_in_frames
=
0
;
cfg_
.
kf_mode
=
VPX_KF_DISABLED
;
cfg_
.
g_error_resilient
=
1
;
// 3 Temporal layers. Framerate decimation (4, 2, 1).
cfg_
.
ts_number_layers
=
3
;
cfg_
.
ts_rate_decimator
[
0
]
=
4
;
cfg_
.
ts_rate_decimator
[
1
]
=
2
;
cfg_
.
ts_rate_decimator
[
2
]
=
1
;
cfg_
.
ts_periodicity
=
4
;
cfg_
.
ts_layer_id
[
0
]
=
0
;
cfg_
.
ts_layer_id
[
1
]
=
2
;
cfg_
.
ts_layer_id
[
2
]
=
1
;
cfg_
.
ts_layer_id
[
3
]
=
2
;
::
libvpx_test
::
I420VideoSource
video
(
"hantro_collage_w352h288.yuv"
,
352
,
288
,
30
,
1
,
0
,
200
);
for
(
int
i
=
200
;
i
<=
800
;
i
+=
200
)
{
cfg_
.
rc_target_bitrate
=
i
;
Reset
();
// 40-20-40 bitrate allocation for 3 temporal layers.
cfg_
.
ts_target_bitrate
[
0
]
=
40
*
cfg_
.
rc_target_bitrate
/
100
;
cfg_
.
ts_target_bitrate
[
1
]
=
60
*
cfg_
.
rc_target_bitrate
/
100
;
cfg_
.
ts_target_bitrate
[
2
]
=
cfg_
.
rc_target_bitrate
;
ASSERT_NO_FATAL_FAILURE
(
RunLoop
(
&
video
));
for
(
int
j
=
0
;
j
<
static_cast
<
int
>
(
cfg_
.
ts_number_layers
);
++
j
)
{
ASSERT_GE
(
effective_datarate_
[
j
],
cfg_
.
ts_target_bitrate
[
j
]
*
0.75
)
<<
" The datarate for the file is lower than target by too much, "
"for layer: "
<<
j
;
ASSERT_LE
(
effective_datarate_
[
j
],
cfg_
.
ts_target_bitrate
[
j
]
*
1.25
)
<<
" The datarate for the file is greater than target by too much, "
"for layer: "
<<
j
;
}
}
}
VP8_INSTANTIATE_TEST_CASE
(
ErrorResilienceTestLarge
,
ONE_PASS_TEST_MODES
);
VP8_INSTANTIATE_TEST_CASE
(
ErrorResilienceTestLargeCodecControls
,
ONE_PASS_TEST_MODES
);
VP9_INSTANTIATE_TEST_CASE
(
ErrorResilienceTestLarge
,
ONE_PASS_TEST_MODES
);
}
// namespace
vp8/common/blockd.h
View file @
af898b56
...
...
@@ -187,8 +187,12 @@ typedef struct
{
FRAME_TYPE
frame_type
;
int
is_frame_dropped
;
// The frame rate for the lowest resolution.
double
low_res_framerate
;
/* The frame number of each reference frames */
unsigned
int
low_res_ref_frames
[
MAX_REF_FRAMES
];
// The video frame counter value for the key frame, for lowest resolution.
unsigned
int
key_frame_counter_value
;
LOWER_RES_MB_INFO
*
mb_info
;
}
LOWER_RES_FRAME_INFO
;
#endif
...
...
vp8/common/onyx.h
View file @
af898b56
...
...
@@ -122,6 +122,7 @@ extern "C"
int
Sharpness
;
int
cpu_used
;
unsigned
int
rc_max_intra_bitrate_pct
;
unsigned
int
screen_content_mode
;
/* mode ->
*(0)=Realtime/Live Encoding. This mode is optimized for realtim
...
...
vp8/encoder/block.h
View file @
af898b56
...
...
@@ -125,6 +125,8 @@ typedef struct macroblock
int
optimize
;
int
q_index
;
int
is_skin
;
int
denoise_zeromv
;
#if CONFIG_TEMPORAL_DENOISING
int
increase_denoising
;
...
...
@@ -161,6 +163,8 @@ typedef struct macroblock
void
(
*
short_walsh4x4
)(
short
*
input
,
short
*
output
,
int
pitch
);
void
(
*
quantize_b
)(
BLOCK
*
b
,
BLOCKD
*
d
);
unsigned
int
mbs_zero_last_dot_suppress
;
int
zero_last_dot_suppress
;
}
MACROBLOCK
;
...
...
vp8/encoder/denoising.c
View file @
af898b56
...
...
@@ -391,7 +391,7 @@ void vp8_denoiser_set_parameters(VP8_DENOISER *denoiser, int mode) {
denoiser
->
denoise_pars
.
scale_increase_filter
=
1
;
denoiser
->
denoise_pars
.
denoise_mv_bias
=
60
;
denoiser
->
denoise_pars
.
pickmode_mv_bias
=
75
;
denoiser
->
denoise_pars
.
qp_thresh
=
8
5
;
denoiser
->
denoise_pars
.
qp_thresh
=
8
0
;
denoiser
->
denoise_pars
.
consec_zerolast
=
15
;
denoiser
->
denoise_pars
.
spatial_blur
=
0
;
}
...
...
@@ -456,10 +456,10 @@ int vp8_denoiser_allocate(VP8_DENOISER *denoiser, int width, int height,
denoiser
->
bitrate_threshold
=
400000
;
// (bits/sec).
denoiser
->
threshold_aggressive_mode
=
80
;
if
(
width
*
height
>
1280
*
720
)
{
denoiser
->
bitrate_threshold
=
25
00000
;
denoiser
->
threshold_aggressive_mode
=
18
0
;
denoiser
->
bitrate_threshold
=
30
00000
;
denoiser
->
threshold_aggressive_mode
=
20
0
;
}
else
if
(
width
*
height
>
960
*
540
)
{
denoiser
->
bitrate_threshold
=
1
0
00000
;
denoiser
->
bitrate_threshold
=
1
2
00000
;
denoiser
->
threshold_aggressive_mode
=
120
;
}
else
if
(
width
*
height
>
640
*
480
)
{
denoiser
->
bitrate_threshold
=
600000
;
...
...
@@ -483,7 +483,6 @@ void vp8_denoiser_free(VP8_DENOISER *denoiser)
vpx_free
(
denoiser
->
denoise_state
);
}
void
vp8_denoiser_denoise_mb
(
VP8_DENOISER
*
denoiser
,
MACROBLOCK
*
x
,
unsigned
int
best_sse
,
...
...
@@ -554,6 +553,7 @@ void vp8_denoiser_denoise_mb(VP8_DENOISER *denoiser,
* Note that any changes to the mode info only affects the
* denoising.
*/
x
->
denoise_zeromv
=
1
;
mbmi
->
ref_frame
=
x
->
best_zeromv_reference_frame
;
...
...
@@ -603,6 +603,12 @@ void vp8_denoiser_denoise_mb(VP8_DENOISER *denoiser,
motion_threshold
=
denoiser
->
denoise_pars
.
scale_motion_thresh
*
NOISE_MOTION_THRESHOLD
;
// If block is considered to be skin area, lower the motion threshold.
// In current version set threshold = 1, so only denoise very low
// (i.e., zero) mv on skin.
if
(
x
->
is_skin
)
motion_threshold
=
1
;
if
(
motion_magnitude2
<
denoiser
->
denoise_pars
.
scale_increase_filter
*
NOISE_MOTION_THRESHOLD
)
x
->
increase_denoising
=
1
;
...
...
@@ -662,6 +668,7 @@ void vp8_denoiser_denoise_mb(VP8_DENOISER *denoiser,
/* No filtering of this block; it differs too much from the predictor,
* or the motion vector magnitude is considered too big.
*/
x
->
denoise_zeromv
=
0
;
vp8_copy_mem16x16
(
x
->
thismb
,
16
,
denoiser
->
yv12_running_avg
[
INTRA_FRAME
].
y_buffer
+
recon_yoffset
,
...
...
@@ -692,7 +699,7 @@ void vp8_denoiser_denoise_mb(VP8_DENOISER *denoiser,
int
uv_stride
=
denoiser
->
yv12_running_avg
[
INTRA_FRAME
].
uv_stride
;
// Fix filter level to some nominal value for now.
int
filter_level
=
32
;
int
filter_level
=
48
;
int
hev_index
=
lfi_n
->
hev_thr_lut
[
INTER_FRAME
][
filter_level
];
lfi
.
mblim
=
lfi_n
->
mblim
[
filter_level
];
...
...
vp8/encoder/denoising.h
View file @
af898b56
...
...
@@ -19,7 +19,7 @@ extern "C" {
#endif
#define SUM_DIFF_THRESHOLD (16 * 16 * 2)
#define SUM_DIFF_THRESHOLD_HIGH (600)
#define SUM_DIFF_THRESHOLD_HIGH (600)
// ~(16 * 16 * 1.5)
#define MOTION_MAGNITUDE_THRESHOLD (8*3)
#define SUM_DIFF_THRESHOLD_UV (96) // (8 * 8 * 1.5)
...
...
@@ -27,7 +27,7 @@ extern "C" {
#define SUM_DIFF_FROM_AVG_THRESH_UV (8 * 8 * 8)
#define MOTION_MAGNITUDE_THRESHOLD_UV (8*3)
#define MAX_GF_ARF_DENOISE_RANGE (
16
)
#define MAX_GF_ARF_DENOISE_RANGE (
8
)
enum
vp8_denoiser_decision
{
...
...
vp8/encoder/encodeframe.c
View file @
af898b56
...
...
@@ -522,7 +522,8 @@ void encode_mb_row(VP8_COMP *cpi,
}
#endif
// Keep track of how many (consecutive) times a block is coded
// Keep track of how many (consecutive) times a block is coded
// as ZEROMV_LASTREF, for base layer frames.
// Reset to 0 if its coded as anything else.
if
(
cpi
->
current_layer
==
0
)
{
...
...
@@ -531,9 +532,14 @@ void encode_mb_row(VP8_COMP *cpi,
// Increment, check for wrap-around.
if
(
cpi
->
consec_zero_last
[
map_index
+
mb_col
]
<
255
)
cpi
->
consec_zero_last
[
map_index
+
mb_col
]
+=
1
;
if
(
cpi
->
consec_zero_last_mvbias
[
map_index
+
mb_col
]
<
255
)
cpi
->
consec_zero_last_mvbias
[
map_index
+
mb_col
]
+=
1
;
}
else
{
cpi
->
consec_zero_last
[
map_index
+
mb_col
]
=
0
;
cpi
->
consec_zero_last_mvbias
[
map_index
+
mb_col
]
=
0
;
}
if
(
x
->
zero_last_dot_suppress
)
cpi
->
consec_zero_last_mvbias
[
map_index
+
mb_col
]
=
0
;
}
/* Special case code for cyclic refresh
...
...
vp8/encoder/ethreading.c
View file @
af898b56
...
...
@@ -215,11 +215,15 @@ THREAD_FUNCTION thread_encoding_proc(void *p_data)
LAST_FRAME
)
{
// Increment, check for wrap-around.
if
(
cpi
->
consec_zero_last
[
map_index
+
mb_col
]
<
255
)
cpi
->
consec_zero_last
[
map_index
+
mb_col
]
+=
1
;
cpi
->
consec_zero_last
[
map_index
+
mb_col
]
+=
1
;
if
(
cpi
->
consec_zero_last_mvbias
[
map_index
+
mb_col
]
<
255
)
cpi
->
consec_zero_last_mvbias
[
map_index
+
mb_col
]
+=
1
;
}
else
{
cpi
->
consec_zero_last
[
map_index
+
mb_col
]
=
0
;
cpi
->
consec_zero_last_mvbias
[
map_index
+
mb_col
]
=
0
;
}
if
(
x
->
zero_last_dot_suppress
)
cpi
->
consec_zero_last_mvbias
[
map_index
+
mb_col
]
=
0
;
}
/* Special case code for cyclic refresh
...
...
@@ -505,6 +509,7 @@ void vp8cx_init_mbrthread_data(VP8_COMP *cpi,
mb
->
intra_error
=
0
;
vp8_zero
(
mb
->
count_mb_ref_frame_usage
);
mb
->
mbs_tested_so_far
=
0
;
mb
->
mbs_zero_last_dot_suppress
=
0
;
}
}
...
...
vp8/encoder/onyx_if.c
View file @
af898b56
This diff is collapsed.
Click to expand it.
vp8/encoder/onyx_int.h
View file @
af898b56
...
...
@@ -513,10 +513,18 @@ typedef struct VP8_COMP
signed
char
*
cyclic_refresh_map
;
// Count on how many (consecutive) times a macroblock uses ZER0MV_LAST.
unsigned
char
*
consec_zero_last
;
// Counter that is reset when a block is checked for a mode-bias against
// ZEROMV_LASTREF.
unsigned
char
*
consec_zero_last_mvbias
;
// Frame counter for the temporal pattern. Counter is rest when the temporal
// layers are changed dynamically (run-time change).
unsigned
int
temporal_pattern_counter
;
// Temporal layer id.
int
temporal_layer_id
;
// Measure of average squared difference between source and denoised signal.
int
mse_source_denoised
;
#if CONFIG_MULTITHREAD
/* multithread data */
...
...
@@ -687,6 +695,7 @@ typedef struct VP8_COMP
#endif
/* The frame number of each reference frames */
unsigned
int
current_ref_frames
[
MAX_REF_FRAMES
];
// Closest reference frame to current frame.
MV_REFERENCE_FRAME
closest_reference_frame
;
struct
rd_costs_struct
...
...
vp8/encoder/pickinter.c
View file @
af898b56
...
...
@@ -40,6 +40,134 @@ extern const MB_PREDICTION_MODE vp8_mode_order[MAX_MODES];
extern
int
vp8_cost_mv_ref
(
MB_PREDICTION_MODE
m
,
const
int
near_mv_ref_ct
[
4
]);
// Fixed point implementation of a skin color classifier. Skin color
// is model by a Gaussian distribution in the CbCr color space.
// See ../../test/skin_color_detector_test.cc where the reference
// skin color classifier is defined.
// Fixed-point skin color model parameters.
static
const
int
skin_mean
[
2
]
=
{
7463
,
9614
};
// q6
static
const
int
skin_inv_cov
[
4
]
=
{
4107
,
1663
,
1663
,
2157
};
// q16
static
const
int
skin_threshold
=
1570636
;
// q18
// Evaluates the Mahalanobis distance measure for the input CbCr values.
static
int
evaluate_skin_color_difference
(
int
cb
,
int
cr
)
{
const
int
cb_q6
=
cb
<<
6
;
const
int
cr_q6
=
cr
<<
6
;
const
int
cb_diff_q12
=
(
cb_q6
-
skin_mean
[
0
])
*
(
cb_q6
-
skin_mean
[
0
]);
const
int
cbcr_diff_q12
=
(
cb_q6
-
skin_mean
[
0
])
*
(
cr_q6
-
skin_mean
[
1
]);
const
int
cr_diff_q12
=
(
cr_q6
-
skin_mean
[
1
])
*
(
cr_q6
-
skin_mean
[
1
]);
const
int
cb_diff_q2
=
(
cb_diff_q12
+
(
1
<<
9
))
>>
10
;
const
int
cbcr_diff_q2
=
(
cbcr_diff_q12
+
(
1
<<
9
))
>>
10
;
const
int
cr_diff_q2
=
(
cr_diff_q12
+
(
1
<<
9
))
>>
10
;
const
int
skin_diff
=
skin_inv_cov
[
0
]
*
cb_diff_q2
+
skin_inv_cov
[
1
]
*
cbcr_diff_q2
+
skin_inv_cov
[
2
]
*
cbcr_diff_q2
+
skin_inv_cov
[
3
]
*
cr_diff_q2
;
return
skin_diff
;
}
static
int
macroblock_corner_grad
(
unsigned
char
*
signal
,
int
stride
,
int
offsetx
,
int
offsety
,
int
sgnx
,
int
sgny
)
{
int
y1
=
signal
[
offsetx
*
stride
+
offsety
];
int
y2
=
signal
[
offsetx
*
stride
+
offsety
+
sgny
];
int
y3
=
signal
[(
offsetx
+
sgnx
)
*
stride
+
offsety
];
int
y4
=
signal
[(
offsetx
+
sgnx
)
*
stride
+
offsety
+
sgny
];
return
MAX
(
MAX
(
abs
(
y1
-
y2
),
abs
(
y1
-
y3
)),
abs
(
y1
-
y4
));
}
static
int
check_dot_artifact_candidate
(
VP8_COMP
*
cpi
,
MACROBLOCK
*
x
,
unsigned
char
*
target_last
,
int
stride
,
unsigned
char
*
last_ref
,
int
mb_row
,
int
mb_col
,
int
channel
)
{
int
threshold1
=
6
;
int
threshold2
=
3
;
unsigned
int
max_num
=
(
cpi
->
common
.
MBs
)
/
10
;
int
grad_last
=
0
;
int
grad_source
=
0
;
int
index
=
mb_row
*
cpi
->
common
.
mb_cols
+
mb_col
;
// Threshold for #consecutive (base layer) frames using zero_last mode.
int
num_frames
=
30
;
int
shift
=
15
;
if
(
channel
>
0
)
{
shift
=
7
;
}
if
(
cpi
->
oxcf
.
number_of_layers
>
1
)
{
num_frames
=
20
;
}
x
->
zero_last_dot_suppress
=
0
;
// Blocks on base layer frames that have been using ZEROMV_LAST repeatedly
// (i.e, at least |x| consecutive frames are candidates for increasing the
// rd adjustment for zero_last mode.
// Only allow this for at most |max_num| blocks per frame.
// Don't allow this for screen content input.
if
(
cpi
->
current_layer
==
0
&&
cpi
->
consec_zero_last_mvbias
[
index
]
>
num_frames
&&
x
->
mbs_zero_last_dot_suppress
<
max_num
&&
!
cpi
->
oxcf
.
screen_content_mode
)
{
// If this block is checked here, label it so we don't check it again until
// ~|x| framaes later.
x
->
zero_last_dot_suppress
=
1
;
// Dot artifact is noticeable as strong gradient at corners of macroblock,
// for flat areas. As a simple detector for now, we look for a high
// corner gradient on last ref, and a smaller gradient on source.
// Check 4 corners, return if any satisfy condition.
// Top-left:
grad_last
=
macroblock_corner_grad
(
last_ref
,
stride
,
0
,
0
,
1
,
1
);
grad_source
=
macroblock_corner_grad
(
target_last
,
stride
,
0
,
0
,
1
,
1
);
if
(
grad_last
>=
threshold1
&&
grad_source
<=
threshold2
)
{
x
->
mbs_zero_last_dot_suppress
++
;
return
1
;
}
// Top-right:
grad_last
=
macroblock_corner_grad
(
last_ref
,
stride
,
0
,
shift
,
1
,
-
1
);
grad_source
=
macroblock_corner_grad
(
target_last
,
stride
,
0
,
shift
,
1
,
-
1
);
if
(
grad_last
>=
threshold1
&&
grad_source
<=
threshold2
)
{
x
->
mbs_zero_last_dot_suppress
++
;
return
1
;
}
// Bottom-left:
grad_last
=
macroblock_corner_grad
(
last_ref
,
stride
,
shift
,
0
,
-
1
,
1
);
grad_source
=
macroblock_corner_grad
(
target_last
,
stride
,
shift
,
0
,
-
1
,
1
);
if
(
grad_last
>=
threshold1
&&
grad_source
<=
threshold2
)
{
x
->
mbs_zero_last_dot_suppress
++
;
return
1
;
}
// Bottom-right:
grad_last
=
macroblock_corner_grad
(
last_ref
,
stride
,
shift
,
shift
,
-
1
,
-
1
);
grad_source
=
macroblock_corner_grad
(
target_last
,
stride
,
shift
,
shift
,
-
1
,
-
1
);
if
(
grad_last
>=
threshold1
&&
grad_source
<=
threshold2
)
{
x
->
mbs_zero_last_dot_suppress
++
;
return
1
;
}
return
0
;
}
return
0
;
}
// Checks if the input yCbCr values corresponds to skin color.
static
int
is_skin_color
(
int
y
,
int
cb
,
int
cr
)
{
if
(
y
<
40
||
y
>
220
)
{
return
0
;
}
return
(
evaluate_skin_color_difference
(
cb
,
cr
)
<
skin_threshold
);
}
int
vp8_skip_fractional_mv_step
(
MACROBLOCK
*
mb
,
BLOCK
*
b
,
BLOCKD
*
d
,
int_mv
*
bestmv
,
int_mv
*
ref_mv
,
int
error_per_bit
,
...
...
@@ -514,10 +642,17 @@ static int evaluate_inter_mode(unsigned int* sse, int rate2, int* distortion2,
#endif
// Adjust rd for ZEROMV and LAST, if LAST is the closest reference frame.
if
(
this_mode
==
ZEROMV
&&
x
->
e_mbd
.
mode_info_context
->
mbmi
.
ref_frame
==
LAST_FRAME
&&
(
denoise_aggressive
||
cpi
->
closest_reference_frame
==
LAST_FRAME
))
{
this_rd
=
((
int64_t
)
this_rd
)
*
rd_adj
/
100
;
// TODO: We should also add condition on distance of closest to current.
if
(
!
cpi
->
oxcf
.
screen_content_mode
&&
this_mode
==
ZEROMV
&&
x
->
e_mbd
.
mode_info_context
->
mbmi
.
ref_frame
==
LAST_FRAME
&&
(
denoise_aggressive
||
(
cpi
->
closest_reference_frame
==
LAST_FRAME
)))
{
// No adjustment if block is considered to be skin area.
if
(
x
->
is_skin
)
rd_adj
=
100
;
this_rd
=
((
int64_t
)
this_rd
)
*
rd_adj
/
100
;
}
check_for_encode_breakout
(
*
sse
,
x
);
...
...
@@ -597,6 +732,15 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
#endif
int
sf_improved_mv_pred
=
cpi
->
sf
.
improved_mv_pred
;
#if CONFIG_MULTI_RES_ENCODING
int
dissim
=
INT_MAX
;
int
parent_ref_frame
=
0
;
int_mv
parent_ref_mv
;
MB_PREDICTION_MODE
parent_mode
=
0
;
int
parent_ref_valid
=
0
;
#endif
int_mv
mvp
;