Commit ea8aaf15 authored by Jim Bankoski's avatar Jim Bankoski
Browse files

create super fast rtc mode

This patch only works if the video is a width and height that are both
a multiple of 32..   It sets every partition to 16x16, and does INTRADC
only on the first frame and ZEROMV on every other frame.   It always does
does the largest possible transform, and loop filter level is set to 4.

Was ~20% faster than speed -5 of vp8

Now 20% slower but adds motion search ( every block ), nearest, near
and zeromv

The SVC test was changed because - while this realtime mode produces
bad quality albeit quickly, it isn't obeying all the rules it should
about which frames are available.

Change-Id: I235c0b22573957986d41497dfb84568ec1dec8c7
parent 00bfacb7
......@@ -234,7 +234,7 @@ TEST_F(SvcTest, FirstFrameHasLayers) {
video.Begin();
res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
video.duration(), VPX_DL_REALTIME);
video.duration(), VPX_DL_GOOD_QUALITY);
EXPECT_EQ(VPX_CODEC_OK, res);
const vpx_codec_err_t res_dec = decoder_->DecodeFrame(
......@@ -262,7 +262,7 @@ TEST_F(SvcTest, EncodeThreeFrames) {
video.Begin();
// This frame is a keyframe.
res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
video.duration(), VPX_DL_REALTIME);
video.duration(), VPX_DL_GOOD_QUALITY);
ASSERT_EQ(VPX_CODEC_OK, res);
EXPECT_EQ(1, vpx_svc_is_keyframe(&svc_));
......@@ -275,7 +275,7 @@ TEST_F(SvcTest, EncodeThreeFrames) {
video.Next();
// This is a P-frame.
res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
video.duration(), VPX_DL_REALTIME);
video.duration(), VPX_DL_GOOD_QUALITY);
ASSERT_EQ(VPX_CODEC_OK, res);
EXPECT_EQ(0, vpx_svc_is_keyframe(&svc_));
......@@ -288,7 +288,7 @@ TEST_F(SvcTest, EncodeThreeFrames) {
video.Next();
// This is a P-frame.
res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
video.duration(), VPX_DL_REALTIME);
video.duration(), VPX_DL_GOOD_QUALITY);
ASSERT_EQ(VPX_CODEC_OK, res);
EXPECT_EQ(0, vpx_svc_is_keyframe(&svc_));
......
......@@ -55,6 +55,7 @@ extern "C" {
MODE_FIRSTPASS = 0x3,
MODE_SECONDPASS = 0x4,
MODE_SECONDPASS_BEST = 0x5,
MODE_REALTIME = 0x6,
} MODE;
typedef enum {
......
This diff is collapsed.
......@@ -355,7 +355,6 @@ static void optimize_init_b(int plane, BLOCK_SIZE bsize,
pd->above_context, pd->left_context,
num_4x4_w, num_4x4_h);
}
void vp9_xform_quant(int plane, int block, BLOCK_SIZE plane_bsize,
TX_SIZE tx_size, void *arg) {
struct encode_b_args* const args = arg;
......
......@@ -1258,6 +1258,11 @@ void vp9_change_config(VP9_PTR ptr, VP9_CONFIG *oxcf) {
cpi->pass = 2;
cpi->compressor_speed = 0;
break;
case MODE_REALTIME:
cpi->pass = 0;
cpi->compressor_speed = 3;
break;
}
cpi->oxcf.worst_allowed_q = q_trans[oxcf->worst_allowed_q];
......@@ -2541,7 +2546,10 @@ static void loopfilter_frame(VP9_COMP *cpi, VP9_COMMON *cm) {
vpx_usec_timer_start(&timer);
vp9_pick_filter_level(cpi->Source, cpi, cpi->sf.use_fast_lpf_pick);
if (cpi->compressor_speed == 3)
lf->filter_level = 4;
else
vp9_pick_filter_level(cpi->Source, cpi, cpi->sf.use_fast_lpf_pick);
vpx_usec_timer_mark(&timer);
cpi->time_pick_lpf += vpx_usec_timer_elapsed(&timer);
......@@ -2730,7 +2738,9 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
if (cpi->sf.recode_loop != 0) {
vp9_save_coding_context(cpi);
cpi->dummy_packing = 1;
vp9_pack_bitstream(cpi, dest, size);
if (cpi->compressor_speed != 3)
vp9_pack_bitstream(cpi, dest, size);
cpi->rc.projected_frame_size = (*size) << 3;
vp9_restore_coding_context(cpi);
......@@ -3088,11 +3098,22 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
&frame_under_shoot_limit,
&frame_over_shoot_limit);
// Decide q and q bounds
// Decide q and q bounds.
q = vp9_rc_pick_q_and_adjust_q_bounds(cpi,
&bottom_index,
&top_index);
// JBB : This is realtime mode. In real time mode the first frame
// should be larger. Q of 0 is disabled because we force tx size to be
// 16x16...
if (cpi->compressor_speed == 3) {
if (cpi->common.current_video_frame == 0)
q /= 3;
if (q == 0)
q++;
}
if (!frame_is_intra_only(cm)) {
cm->interp_filter = DEFAULT_INTERP_FILTER;
/* TODO: Decide this more intelligently */
......
......@@ -80,7 +80,7 @@ static int full_pixel_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
step_param = 6;
further_steps = (cpi->sf.max_step_search_steps - 1) - step_param;
for (i = LAST_FRAME; i <= ALTREF_FRAME && cpi->common.show_frame; ++i) {
for (i = LAST_FRAME; i <= LAST_FRAME && cpi->common.show_frame; ++i) {
if ((x->pred_mv_sad[ref] >> 3) > x->pred_mv_sad[i]) {
tmp_mv->as_int = INVALID_MV;
......@@ -142,8 +142,7 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
int mi_row, int mi_col,
int *returnrate,
int64_t *returndistortion,
BLOCK_SIZE bsize,
PICK_MODE_CONTEXT *ctx) {
BLOCK_SIZE bsize) {
MACROBLOCKD *xd = &x->e_mbd;
MB_MODE_INFO *mbmi = &xd->mi_8x8[0]->mbmi;
const BLOCK_SIZE block_size = get_plane_block_size(bsize, &xd->plane[0]);
......@@ -155,6 +154,7 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
VP9_ALT_FLAG };
int64_t best_rd = INT64_MAX;
int64_t this_rd;
int64_t cost[4]= { 0, 100, 150, 205 };
x->skip_encode = cpi->sf.skip_encode_frame && x->q_index < QIDX_SKIP_THRESH;
......@@ -171,7 +171,7 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
mbmi->tx_size = MIN(max_txsize_lookup[bsize],
tx_mode_to_biggest_tx_size[cpi->common.tx_mode]);
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
for (ref_frame = LAST_FRAME; ref_frame <= LAST_FRAME ; ++ref_frame) {
x->pred_mv_sad[ref_frame] = INT_MAX;
if (cpi->ref_frame_flags & flag_list[ref_frame]) {
vp9_setup_buffer_inter(cpi, x, tile,
......@@ -182,7 +182,7 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
frame_mv[ZEROMV][ref_frame].as_int = 0;
}
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
for (ref_frame = LAST_FRAME; ref_frame <= LAST_FRAME ; ++ref_frame) {
int rate_mv = 0;
if (!(cpi->ref_frame_flags & flag_list[ref_frame]))
......@@ -191,29 +191,42 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
// Select prediction reference frames.
xd->plane[0].pre[0] = yv12_mb[ref_frame][0];
x->mode_sad[ref_frame][INTER_OFFSET(NEWMV)] =
full_pixel_motion_search(cpi, x, tile, bsize, mi_row, mi_col,
&frame_mv[NEWMV][ref_frame], &rate_mv);
if (frame_mv[NEWMV][ref_frame].as_int == INVALID_MV)
continue;
clamp_mv2(&frame_mv[NEARESTMV][ref_frame].as_mv, xd);
clamp_mv2(&frame_mv[NEARMV][ref_frame].as_mv, xd);
for (this_mode = NEARESTMV; this_mode <= NEWMV; ++this_mode) {
int rate = x->inter_mode_cost[mbmi->mode_context[ref_frame]]
[INTER_OFFSET(this_mode)];
int64_t dist = x->mode_sad[ref_frame][INTER_OFFSET(this_mode)] *
x->mode_sad[ref_frame][INTER_OFFSET(this_mode)];
this_rd = RDCOST(x->rdmult, x->rddiv, rate, dist);
int rate = cost[this_mode - NEARESTMV];
int64_t dist;
if (this_mode == NEWMV) {
if (this_rd < 300)
continue;
x->mode_sad[ref_frame][INTER_OFFSET(NEWMV)] =
full_pixel_motion_search(cpi, x, tile, bsize, mi_row, mi_col,
&frame_mv[NEWMV][ref_frame], &rate_mv);
if (frame_mv[NEWMV][ref_frame].as_int == INVALID_MV)
continue;
}
dist = x->mode_sad[ref_frame][INTER_OFFSET(this_mode)];
this_rd = rate + dist;
if (this_rd < best_rd) {
best_rd = this_rd;
mbmi->mode = this_mode;
mbmi->ref_frame[0] = ref_frame;
mbmi->mv[0].as_int = frame_mv[this_mode][ref_frame].as_int;
xd->mi_8x8[0]->bmi[0].as_mv[0].as_int = mbmi->mv[0].as_int;
mbmi->interp_filter = EIGHTTAP;
mbmi->ref_frame[1] = INTRA_FRAME;
mbmi->tx_size = max_txsize_lookup[bsize];
mbmi->uv_mode = this_mode;
mbmi->skip_coeff = 0;
mbmi->sb_type = bsize;
mbmi->segment_id = 0;
}
}
}
......@@ -223,8 +236,5 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
// TODO(jingning) intra prediction search, if the best SAD is above a certain
// threshold.
// store mode decisions
ctx->mic = *xd->mi_8x8[0];
return INT64_MAX;
}
......@@ -22,8 +22,7 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
int mi_row, int mi_col,
int *returnrate,
int64_t *returndistortion,
BLOCK_SIZE bsize,
PICK_MODE_CONTEXT *ctx);
BLOCK_SIZE bsize);
#ifdef __cplusplus
} // extern "C"
......
......@@ -280,22 +280,24 @@ void vp9_initialize_rd_consts(VP9_COMP *cpi) {
fill_token_costs(x->token_costs, cm->fc.coef_probs);
for (i = 0; i < PARTITION_CONTEXTS; i++)
vp9_cost_tokens(x->partition_cost[i], get_partition_probs(cm, i),
vp9_partition_tree);
fill_mode_costs(cpi);
if (!frame_is_intra_only(cm)) {
vp9_build_nmv_cost_table(x->nmvjointcost,
cm->allow_high_precision_mv ? x->nmvcost_hp
: x->nmvcost,
&cm->fc.nmvc,
cm->allow_high_precision_mv, 1, 1);
for (i = 0; i < INTER_MODE_CONTEXTS; ++i)
vp9_cost_tokens((int *)x->inter_mode_cost[i],
cm->fc.inter_mode_probs[i], vp9_inter_mode_tree);
if (cpi->compressor_speed != 3) {
for (i = 0; i < PARTITION_CONTEXTS; i++)
vp9_cost_tokens(x->partition_cost[i], get_partition_probs(cm, i),
vp9_partition_tree);
fill_mode_costs(cpi);
if (!frame_is_intra_only(cm)) {
vp9_build_nmv_cost_table(x->nmvjointcost,
cm->allow_high_precision_mv ? x->nmvcost_hp
: x->nmvcost,
&cm->fc.nmvc,
cm->allow_high_precision_mv, 1, 1);
for (i = 0; i < INTER_MODE_CONTEXTS; ++i)
vp9_cost_tokens((int *)x->inter_mode_cost[i],
cm->fc.inter_mode_probs[i], vp9_inter_mode_tree);
}
}
}
......@@ -2466,6 +2468,7 @@ static void single_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
for (i = 0; i < MAX_MB_PLANE; i++)
xd->plane[i].pre[0] = backup_yv12[i];
}
return;
}
static void joint_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
......
......@@ -563,10 +563,21 @@ static void pick_quickcompress_mode(vpx_codec_alg_priv_t *ctx,
unsigned int new_qc;
/* Use best quality mode if no deadline is given. */
if (deadline)
new_qc = MODE_GOODQUALITY;
else
new_qc = MODE_BESTQUALITY;
new_qc = MODE_BESTQUALITY;
if (deadline) {
uint64_t duration_us;
/* Convert duration parameter from stream timebase to microseconds */
duration_us = (uint64_t)duration * 1000000
* (uint64_t)ctx->cfg.g_timebase.num
/ (uint64_t)ctx->cfg.g_timebase.den;
/* If the deadline is more that the duration this frame is to be shown,
* use good quality mode. Otherwise use realtime mode.
*/
new_qc = (deadline > duration_us) ? MODE_GOODQUALITY : MODE_REALTIME;
}
if (ctx->cfg.g_pass == VPX_RC_FIRST_PASS)
new_qc = MODE_FIRSTPASS;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment