PVQ uses backward updated context in a tile
In the beginning of encoding and bitstream packing,
the frame context in common of codec is copied to the frame context
in each tile.
Initial prob and context is based on flat probability and
does not come from table at the moment.
The bd-rate change for the test set objective-1-fast
on awcy with high delay mode is:
PSNR PSNR HVS SSIM CIEDE 2000 PSNR Cb PSNR Cr MS SSIM
-0.77 -1.05 -0.74 -0.67 -0.67 -0.77 -0.88
Change-Id: Ic9105ac68aceb7486cb5f6f1c0b19df5853f2cb9
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index f802662..5c5599f 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -1037,7 +1037,7 @@
const BLOCK_SIZE plane_bsize =
get_plane_block_size(AOMMAX(bsize, BLOCK_8X8), pd);
- adapt = &x->daala_enc.state.adapt;
+ adapt = x->daala_enc.state.adapt;
max_blocks_wide = max_block_wide(xd, plane_bsize, plane);
max_blocks_high = max_block_high(xd, plane_bsize, plane);
@@ -4121,6 +4121,10 @@
this_tile->tctx = *cm->fc;
cpi->td.mb.e_mbd.tile_ctx = &this_tile->tctx;
#endif
+#if CONFIG_PVQ
+ cpi->td.mb.pvq_q = &this_tile->pvq_q;
+ cpi->td.mb.daala_enc.state.adapt = &this_tile->tctx.pvq_context;
+#endif // CONFIG_PVQ
#if CONFIG_ANS
buf_ans_write_init(buf_ans, dst + total_size);
write_modes(cpi, &tile_info, buf_ans, &tok, tok_end);
@@ -4129,11 +4133,6 @@
tile_size = buf_ans_write_end(buf_ans);
#else
aom_start_encode(&mode_bc, dst + total_size);
-#if CONFIG_PVQ
- // NOTE: This will not work with CONFIG_ANS turned on.
- od_adapt_ctx_reset(&cpi->td.mb.daala_enc.state.adapt, 0);
- cpi->td.mb.pvq_q = &this_tile->pvq_q;
-#endif
write_modes(cpi, &tile_info, &mode_bc, &tok, tok_end);
#if !CONFIG_LV_MAP
assert(tok == tok_end);
diff --git a/av1/encoder/daala_compat_enc.c b/av1/encoder/daala_compat_enc.c
index 1933d5c..3df424c 100644
--- a/av1/encoder/daala_compat_enc.c
+++ b/av1/encoder/daala_compat_enc.c
@@ -17,7 +17,7 @@
#else
#error "CONFIG_PVQ currently requires CONFIG_DAALA_EC."
#endif
- OD_COPY(&rbuf->adapt, &enc->state.adapt, 1);
+ OD_COPY(&rbuf->adapt, enc->state.adapt, 1);
}
void od_encode_rollback(daala_enc_ctx *enc, const od_rollback_buffer *rbuf) {
@@ -26,5 +26,5 @@
#else
#error "CONFIG_PVQ currently requires CONFIG_DAALA_EC."
#endif
- OD_COPY(&enc->state.adapt, &rbuf->adapt, 1);
+ OD_COPY(enc->state.adapt, &rbuf->adapt, 1);
}
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index d101f02..fa65bb9 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -4866,9 +4866,7 @@
const TileInfo *const tile_info = &this_tile->tile_info;
TOKENEXTRA *tok = cpi->tile_tok[tile_row][tile_col];
int mi_row;
-#if CONFIG_PVQ
- od_adapt_ctx *adapt;
-#endif
+
#if CONFIG_DEPENDENT_HORZTILES
#if CONFIG_TILE_GROUPS
if ((!cm->dependent_horz_tiles) || (tile_row == 0) ||
@@ -4957,14 +4955,11 @@
#error "CONFIG_PVQ currently requires CONFIG_DAALA_EC."
#endif
- adapt = &td->mb.daala_enc.state.adapt;
-
#if CONFIG_DAALA_EC
od_ec_enc_reset(&td->mb.daala_enc.w.ec);
#else
#error "CONFIG_PVQ currently requires CONFIG_DAALA_EC."
#endif
- od_adapt_ctx_reset(adapt, 0);
#endif // #if CONFIG_PVQ
#if CONFIG_EC_ADAPT
@@ -4972,6 +4967,10 @@
td->mb.e_mbd.tile_ctx = &this_tile->tctx;
#endif // #if CONFIG_EC_ADAPT
+#if CONFIG_PVQ
+ td->mb.daala_enc.state.adapt = &this_tile->tctx.pvq_context;
+#endif // CONFIG_PVQ
+
for (mi_row = tile_info->mi_row_start; mi_row < tile_info->mi_row_end;
mi_row += cm->mib_size) {
encode_rd_sb_row(cpi, td, this_tile, mi_row, &tok);
diff --git a/av1/encoder/encodemb.c b/av1/encoder/encodemb.c
index ceeac84..03ec981 100644
--- a/av1/encoder/encodemb.c
+++ b/av1/encoder/encodemb.c
@@ -1257,9 +1257,9 @@
// Encode residue of DC coeff, if required.
if (!has_dc_skip || out_int32[0]) {
- generic_encode(&daala_enc->w, &daala_enc->state.adapt.model_dc[plane],
+ generic_encode(&daala_enc->w, &daala_enc->state.adapt->model_dc[plane],
abs(out_int32[0]) - has_dc_skip, -1,
- &daala_enc->state.adapt.ex_dc[plane][tx_size][0], 2);
+ &daala_enc->state.adapt->ex_dc[plane][tx_size][0], 2);
}
if (out_int32[0]) {
aom_write_bit(&daala_enc->w, out_int32[0] < 0);
diff --git a/av1/encoder/firstpass.c b/av1/encoder/firstpass.c
index 74c8491..03b3b49 100644
--- a/av1/encoder/firstpass.c
+++ b/av1/encoder/firstpass.c
@@ -503,6 +503,7 @@
const int mb_scale = mi_size_wide[BLOCK_16X16];
#if CONFIG_PVQ
PVQ_QUEUE pvq_q;
+ od_adapt_ctx pvq_context;
#endif
// First pass code requires valid last and new frame buffers.
@@ -541,8 +542,6 @@
#if CONFIG_PVQ
// For pass 1 of 2-pass encoding, init here for PVQ for now.
{
- od_adapt_ctx *adapt;
-
pvq_q.buf_len = 5000;
CHECK_MEM_ERROR(cm, pvq_q.buf,
aom_malloc(pvq_q.buf_len * sizeof(PVQ_INFO)));
@@ -567,13 +566,11 @@
#error "CONFIG_PVQ currently requires CONFIG_DAALA_EC."
#endif
- adapt = &x->daala_enc.state.adapt;
#if CONFIG_DAALA_EC
od_ec_enc_reset(&x->daala_enc.w.ec);
#else
#error "CONFIG_PVQ currently requires CONFIG_DAALA_EC."
#endif
- od_adapt_ctx_reset(adapt, 0);
}
#endif
@@ -595,6 +592,10 @@
av1_init_scan_order(cm);
#endif
av1_convolve_init(cm);
+#if CONFIG_PVQ
+ od_adapt_ctx_reset(&pvq_context, 0);
+ x->daala_enc.state.adapt = &pvq_context;
+#endif // CONFIG_PVQ
av1_initialize_rd_consts(cpi);
// Tiling is ignored in the first pass.
diff --git a/av1/encoder/pvq_encoder.c b/av1/encoder/pvq_encoder.c
index 4811544..945ecf8 100644
--- a/av1/encoder/pvq_encoder.c
+++ b/av1/encoder/pvq_encoder.c
@@ -797,10 +797,10 @@
else
pvq_qm = 0;
- exg = &enc->state.adapt.pvq.pvq_exg[pli][bs][0];
- ext = enc->state.adapt.pvq.pvq_ext + bs*PVQ_MAX_PARTITIONS;
- skip_cdf = enc->state.adapt.skip_cdf[2*bs + (pli != 0)];
- model = enc->state.adapt.pvq.pvq_param_model;
+ exg = &enc->state.adapt->pvq.pvq_exg[pli][bs][0];
+ ext = enc->state.adapt->pvq.pvq_ext + bs*PVQ_MAX_PARTITIONS;
+ skip_cdf = enc->state.adapt->skip_cdf[2*bs + (pli != 0)];
+ model = enc->state.adapt->pvq.pvq_param_model;
nb_bands = OD_BAND_OFFSETS[bs][0];
off = &OD_BAND_OFFSETS[bs][1];
@@ -847,7 +847,7 @@
qg[i] = pvq_theta(out + off[i], in + off[i], ref + off[i], size[i],
q, y + off[i], &theta[i], &max_theta[i],
- &k[i], beta[i], &skip_diff, nodesync, is_keyframe, pli, &enc->state.adapt,
+ &k[i], beta[i], &skip_diff, nodesync, is_keyframe, pli, enc->state.adapt,
qm + off[i], qm_inv + off[i], enc->pvq_norm_lambda, speed);
}
od_encode_checkpoint(enc, &buf);
@@ -871,8 +871,8 @@
#error "CONFIG_PVQ currently requires CONFIG_DAALA_EC."
#endif
od_encode_checkpoint(enc, &dc_buf);
- generic_encode(&enc->w, &enc->state.adapt.model_dc[pli],
- n - 1, -1, &enc->state.adapt.ex_dc[pli][bs][0], 2);
+ generic_encode(&enc->w, &enc->state.adapt->model_dc[pli],
+ n - 1, -1, &enc->state.adapt->ex_dc[pli][bs][0], 2);
#if CONFIG_DAALA_EC
tell2 = od_ec_enc_tell_frac(&enc->w.ec) - tell2;
#else
@@ -926,14 +926,14 @@
encode_flip = pli != 0 && is_keyframe && theta[i] != -1 && !cfl_encoded;
if (i == 0 || (!skip_rest && !(skip_dir & (1 << ((i - 1)%3))))) {
pvq_encode_partition(&enc->w, qg[i], theta[i], max_theta[i], y + off[i],
- size[i], k[i], model, &enc->state.adapt, exg + i, ext + i,
+ size[i], k[i], model, enc->state.adapt, exg + i, ext + i,
nodesync, (pli != 0)*OD_TXSIZES*PVQ_MAX_PARTITIONS
+ bs*PVQ_MAX_PARTITIONS + i, is_keyframe, i == 0 && (i < nb_bands - 1),
skip_rest, encode_flip, flip);
}
if (i == 0 && !skip_rest && bs > 0) {
aom_write_symbol(&enc->w, skip_dir,
- &enc->state.adapt.pvq.pvq_skip_dir_cdf[(pli != 0) + 2*(bs - 1)][0], 7);
+ &enc->state.adapt->pvq.pvq_skip_dir_cdf[(pli != 0) + 2*(bs - 1)][0], 7);
}
if (encode_flip) cfl_encoded = 1;
}
@@ -977,8 +977,8 @@
#error "CONFIG_PVQ currently requires CONFIG_DAALA_EC."
#endif
od_encode_checkpoint(enc, &dc_buf);
- generic_encode(&enc->w, &enc->state.adapt.model_dc[pli],
- n - 1, -1, &enc->state.adapt.ex_dc[pli][bs][0], 2);
+ generic_encode(&enc->w, &enc->state.adapt->model_dc[pli],
+ n - 1, -1, &enc->state.adapt->ex_dc[pli][bs][0], 2);
#if CONFIG_DAALA_EC
tell2 = od_ec_enc_tell_frac(&enc->w.ec) - tell2;
#else