Commit af898b56 authored by Marco's avatar Marco

Various updates to vp8.

Change-Id: Icc7a816491897107764e4c936288e9000e6319b8
parent d5937cd2
This diff is collapsed.
......@@ -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);
......
......@@ -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
......@@ -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
......
......@@ -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
......
......@@ -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;
......
......@@ -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 = 85;
denoiser->denoise_pars.qp_thresh = 80;
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 = 2500000;
denoiser->threshold_aggressive_mode = 180;
denoiser->bitrate_threshold = 3000000;
denoiser->threshold_aggressive_mode = 200;
} else if (width * height > 960 * 540) {
denoiser->bitrate_threshold = 1000000;
denoiser->bitrate_threshold = 1200000;
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];
......
......@@ -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
{
......
......@@ -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
......
......@@ -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;
}
}
......
This diff is collapsed.
......@@ -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
......
This diff is collapsed.
......@@ -535,6 +535,7 @@ void vp8_set_quantizer(struct VP8_COMP *cpi, int Q)
MACROBLOCKD *mbd = &cpi->mb.e_mbd;
int update = 0;
int new_delta_q;
int new_uv_delta_q;
cm->base_qindex = Q;
/* if any of the delta_q values are changing update flag has to be set */
......@@ -542,8 +543,6 @@ void vp8_set_quantizer(struct VP8_COMP *cpi, int Q)
cm->y1dc_delta_q = 0;
cm->y2ac_delta_q = 0;
cm->uvdc_delta_q = 0;
cm->uvac_delta_q = 0;
if (Q < 4)
{
......@@ -555,6 +554,21 @@ void vp8_set_quantizer(struct VP8_COMP *cpi, int Q)
update |= cm->y2dc_delta_q != new_delta_q;
cm->y2dc_delta_q = new_delta_q;
new_uv_delta_q = 0;
// For screen content, lower the q value for UV channel. For now, select
// conservative delta; same delta for dc and ac, and decrease it with lower
// Q, and set to 0 below some threshold. May want to condition this in
// future on the variance/energy in UV channel.
if (cpi->oxcf.screen_content_mode && Q > 40) {
new_uv_delta_q = -(int)(0.15 * Q);
// Check range: magnitude of delta is 4 bits.
if (new_uv_delta_q < -15) {
new_uv_delta_q = -15;
}
}
update |= cm->uvdc_delta_q != new_uv_delta_q;
cm->uvdc_delta_q = new_uv_delta_q;
cm->uvac_delta_q = new_uv_delta_q;
/* Set Segment specific quatizers */
mbd->segment_feature_data[MB_LVL_ALT_Q][0] = cpi->segment_feature_data[MB_LVL_ALT_Q][0];
......
......@@ -708,7 +708,13 @@ static void calc_pframe_target_size(VP8_COMP *cpi)
Adjustment = (cpi->this_frame_target - min_frame_target);
if (cpi->frames_since_golden == (cpi->current_gf_interval >> 1))
cpi->this_frame_target += ((cpi->current_gf_interval - 1) * Adjustment);
{
Adjustment = (cpi->current_gf_interval - 1) * Adjustment;
// Limit adjustment to 10% of current target.
if (Adjustment > (10 * cpi->this_frame_target) / 100)
Adjustment = (10 * cpi->this_frame_target) / 100;
cpi->this_frame_target += Adjustment;
}
else
cpi->this_frame_target -= Adjustment;
}
......
......@@ -37,6 +37,7 @@ struct vp8_extracfg
vp8e_tuning tuning;
unsigned int cq_level; /* constrained quality level */
unsigned int rc_max_intra_bitrate_pct;
unsigned int screen_content_mode;
};
......@@ -62,6 +63,7 @@ static struct vp8_extracfg default_extracfg = {
0, /* tuning*/
10, /* cq_level */
0, /* rc_max_intra_bitrate_pct */
0, /* screen_content_mode */
};
struct vpx_codec_alg_priv
......@@ -79,6 +81,7 @@ struct vpx_codec_alg_priv
/* pkt_list size depends on the maximum number of lagged frames allowed. */
vpx_codec_pkt_list_decl(64) pkt_list;
unsigned int fixed_kf_cntr;
vpx_enc_frame_flags_t control_frame_flags;
};
......@@ -194,6 +197,7 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
RANGE_CHECK_HI(vp8_cfg, arnr_strength, 6);
RANGE_CHECK(vp8_cfg, arnr_type, 1, 3);
RANGE_CHECK(vp8_cfg, cq_level, 0, 63);
RANGE_CHECK_BOOL(vp8_cfg, screen_content_mode);
if (finalize && (cfg->rc_end_usage == VPX_CQ || cfg->rc_end_usage == VPX_Q))
RANGE_CHECK(vp8_cfg, cq_level,
cfg->rc_min_quantizer, cfg->rc_max_quantizer);
......@@ -231,7 +235,8 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
RANGE_CHECK_HI(cfg, ts_periodicity, 16);
for (i=1; i<cfg->ts_number_layers; i++)
if (cfg->ts_target_bitrate[i] <= cfg->ts_target_bitrate[i-1])
if (cfg->ts_target_bitrate[i] <= cfg->ts_target_bitrate[i-1] &&
cfg->rc_target_bitrate > 0)
ERROR("ts_target_bitrate entries are not strictly increasing");
RANGE_CHECK(cfg, ts_rate_decimator[cfg->ts_number_layers-1], 1, 1);
......@@ -397,6 +402,8 @@ static vpx_codec_err_t set_vp8e_config(VP8_CONFIG *oxcf,
oxcf->tuning = vp8_cfg.tuning;
oxcf->screen_content_mode = vp8_cfg.screen_content_mode;
/*
printf("Current VP8 Settings: \n");
printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
......@@ -586,6 +593,15 @@ static vpx_codec_err_t set_rc_max_intra_bitrate_pct(vpx_codec_alg_priv_t *ctx,
return update_extracfg(ctx, &extra_cfg);
}
static vpx_codec_err_t set_screen_content_mode(vpx_codec_alg_priv_t *ctx,
va_list args)
{
struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
extra_cfg.screen_content_mode =
CAST(VP8E_SET_SCREEN_CONTENT_MODE, args);
return update_extracfg(ctx, &extra_cfg);
}
static vpx_codec_err_t vp8e_mr_alloc_mem(const vpx_codec_enc_cfg_t *cfg,
void **mem_loc)
{
......@@ -768,27 +784,9 @@ static void pick_quickcompress_mode(vpx_codec_alg_priv_t *ctx,
}
}
static vpx_codec_err_t vp8e_encode(vpx_codec_alg_priv_t *ctx,
const vpx_image_t *img,
vpx_codec_pts_t pts,
unsigned long duration,
vpx_enc_frame_flags_t flags,
unsigned long deadline)
static vpx_codec_err_t set_reference_and_update(vpx_codec_alg_priv_t *ctx,
int flags)
{
vpx_codec_err_t res = VPX_CODEC_OK;
if (!ctx->cfg.rc_target_bitrate)
return res;
if (img)
res = validate_img(ctx, img);
if (!res)
res = validate_config(ctx, &ctx->cfg, &ctx->vp8_cfg, 1);
pick_quickcompress_mode(ctx, duration, deadline);
vpx_codec_pkt_list_init(&ctx->pkt_list);
/* Handle Flags */
if (((flags & VP8_EFLAG_NO_UPD_GF) && (flags & VP8_EFLAG_FORCE_GF))
......@@ -838,6 +836,42 @@ static vpx_codec_err_t vp8e_encode(vpx_codec_alg_priv_t *ctx,
vp8_update_entropy(ctx->cpi, 0);
}
return VPX_CODEC_OK;
}
static vpx_codec_err_t vp8e_encode(vpx_codec_alg_priv_t *ctx,
const vpx_image_t *img,
vpx_codec_pts_t pts,
unsigned long duration,
vpx_enc_frame_flags_t flags,
unsigned long deadline)
{
vpx_codec_err_t res = VPX_CODEC_OK;
if (!ctx->cfg.rc_target_bitrate)
return res;
if (!ctx->cfg.rc_target_bitrate)
return res;
if (img)
res = validate_img(ctx, img);
if (!res)
res = validate_config(ctx, &ctx->cfg, &ctx->vp8_cfg, 1);
pick_quickcompress_mode(ctx, duration, deadline);
vpx_codec_pkt_list_init(&ctx->pkt_list);
// If no flags are set in the encode call, then use the frame flags as
// defined via the control function: vp8e_set_frame_flags.
if (!flags) {
flags = ctx->control_frame_flags;
}
ctx->control_frame_flags = 0;
res = set_reference_and_update(ctx, flags);
/* Handle fixed keyframe intervals */
if (ctx->cfg.kf_mode == VPX_KF_AUTO
&& ctx->cfg.kf_min_dist == ctx->cfg.kf_max_dist)
......@@ -1140,6 +1174,25 @@ static vpx_codec_err_t vp8e_use_reference(vpx_codec_alg_priv_t *ctx,
return VPX_CODEC_OK;
}
static vpx_codec_err_t vp8e_set_frame_flags(vpx_codec_alg_priv_t *ctx,
va_list args)
{
int frame_flags = va_arg(args, int);
ctx->control_frame_flags = frame_flags;
return set_reference_and_update(ctx, frame_flags);
}
static vpx_codec_err_t vp8e_set_temporal_layer_id(vpx_codec_alg_priv_t *ctx,
va_list args)
{
int layer_id = va_arg(args, int);
if (layer_id < 0 || layer_id >= (int)ctx->cfg.ts_number_layers) {
return VPX_CODEC_INVALID_PARAM;
}
ctx->cpi->temporal_layer_id = layer_id;
return VPX_CODEC_OK;
}
static vpx_codec_err_t vp8e_set_roi_map(vpx_codec_alg_priv_t *ctx,
va_list args)
{
......@@ -1214,6 +1267,8 @@ static vpx_codec_ctrl_fn_map_t vp8e_ctf_maps[] =
{VP8E_UPD_ENTROPY, vp8e_update_entropy},
{VP8E_UPD_REFERENCE, vp8e_update_reference},
{VP8E_USE_REFERENCE, vp8e_use_reference},
{VP8E_SET_FRAME_FLAGS, vp8e_set_frame_flags},
{VP8E_SET_TEMPORAL_LAYER_ID, vp8e_set_temporal_layer_id},
{VP8E_SET_ROI_MAP, vp8e_set_roi_map},
{VP8E_SET_ACTIVEMAP, vp8e_set_activemap},
{VP8E_SET_SCALEMODE, vp8e_set_scalemode},
......@@ -1231,6 +1286,7 @@ static vpx_codec_ctrl_fn_map_t vp8e_ctf_maps[] =
{VP8E_SET_TUNING, set_tuning},
{VP8E_SET_CQ_LEVEL, set_cq_level},
{VP8E_SET_MAX_INTRA_BITRATE_PCT, set_rc_max_intra_bitrate_pct},
{VP8E_SET_SCREEN_CONTENT_MODE, set_screen_content_mode},
{ -1, NULL},
};
......
......@@ -193,6 +193,7 @@ enum vp8e_enc_control_id {
*
*/
VP8E_SET_MAX_INTRA_BITRATE_PCT,
VP8E_SET_FRAME_FLAGS, /**< control function to set reference and update frame flags */
/*!\brief Max data rate for Inter frames
*
......@@ -222,6 +223,17 @@ enum vp8e_enc_control_id {
*/
VP8E_SET_GF_CBR_BOOST_PCT,
/*!\brief Codec control function to set the temporal layer id
*
* For temporal scalability: this control allows the application to set the
* layer id for each frame to be encoded. Note that this control must be set
* for every frame prior to encoding. The usage of this control function
* supersedes the internal temporal pattern counter, which is now deprecated.
*/
VP8E_SET_TEMPORAL_LAYER_ID,
VP8E_SET_SCREEN_CONTENT_MODE, /**<control function to set encoder screen content mode */
/* TODO(jkoleszar): Move to vp9cx.h */
VP9E_SET_LOSSLESS,
VP9E_SET_TILE_COLUMNS,
......@@ -362,6 +374,8 @@ VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_UPD_ENTROPY, int)
VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_UPD_REFERENCE, int)
VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_USE_REFERENCE, int)
VPX_CTRL_USE_TYPE(VP8E_SET_FRAME_FLAGS, int)
VPX_CTRL_USE_TYPE(VP8E_SET_TEMPORAL_LAYER_ID, int)
VPX_CTRL_USE_TYPE(VP8E_SET_ROI_MAP, vpx_roi_map_t *)
VPX_CTRL_USE_TYPE(VP8E_SET_ACTIVEMAP, vpx_active_map_t *)
VPX_CTRL_USE_TYPE(VP8E_SET_SCALEMODE, vpx_scaling_mode_t *)
......@@ -395,6 +409,9 @@ VPX_CTRL_USE_TYPE(VP8E_SET_MAX_INTRA_BITRATE_PCT, unsigned int)
VPX_CTRL_USE_TYPE(VP8E_SET_MAX_INTER_BITRATE_PCT, unsigned int)
VPX_CTRL_USE_TYPE(VP8E_SET_GF_CBR_BOOST_PCT, unsigned int)
VPX_CTRL_USE_TYPE(VP8E_SET_SCREEN_CONTENT_MODE, unsigned int)
VPX_CTRL_USE_TYPE(VP9E_SET_LOSSLESS, unsigned int)
VPX_CTRL_USE_TYPE(VP9E_SET_FRAME_PARALLEL_DECODING, unsigned int)
......
......@@ -354,13 +354,16 @@ static const arg_def_t max_inter_rate_pct = ARG_DEF(
static const arg_def_t gf_cbr_boost_pct = ARG_DEF(
NULL, "gf-cbr-boost", 1, "Boost for Golden Frame in CBR mode (pct)");
static const arg_def_t screen_content_mode = ARG_DEF(NULL, "screen-content-mode", 1,
"Screen content mode");
#if CONFIG_VP8_ENCODER
static const arg_def_t token_parts = ARG_DEF(
NULL, "token-parts", 1, "Number of token partitions to use, log2");
static const arg_def_t *vp8_args[] = {
&cpu_used, &auto_altref, &noise_sens, &sharpness, &static_thresh,
&token_parts, &arnr_maxframes, &arnr_strength, &arnr_type,
&tune_ssim, &cq_level, &max_intra_rate_pct,
&tune_ssim, &cq_level, &max_intra_rate_pct, &screen_content_mode,
NULL
};
static const int vp8_arg_ctrl_map[] = {
......@@ -369,6 +372,7 @@ static const int vp8_arg_ctrl_map[] = {