Merge "Update IMAGE_ABI_VERSION which wasn't updated after color_range enum was introduced."
diff --git a/configure b/configure
index f12779c..c3c0f40 100755
--- a/configure
+++ b/configure
@@ -35,6 +35,9 @@
${toggle_debug_libs} in/exclude debug version of libraries
${toggle_static_msvcrt} use static MSVCRT (VS builds only)
${toggle_vp9_highbitdepth} use VP9 high bit depth (10/12) profiles
+ ${toggle_better_hw_compatibility}
+ enable encoder to produce streams with better
+ hardware decoder compatibility
${toggle_vp8} VP8 codec support
${toggle_vp9} VP9 codec support
${toggle_vp10} VP10 codec support
@@ -322,6 +325,7 @@
vp9_temporal_denoising
coefficient_range_checking
vp9_highbitdepth
+ better_hw_compatibility
experimental
size_limit
${EXPERIMENT_LIST}
@@ -380,6 +384,7 @@
temporal_denoising
vp9_temporal_denoising
coefficient_range_checking
+ better_hw_compatibility
vp9_highbitdepth
experimental
"
diff --git a/vp10/decoder/decodeframe.c b/vp10/decoder/decodeframe.c
index c0fbc49..2bfedf6 100644
--- a/vp10/decoder/decodeframe.c
+++ b/vp10/decoder/decodeframe.c
@@ -2109,8 +2109,8 @@
setup_segmentation_dequant(cm);
#if CONFIG_MISC_FIXES
- cm->tx_mode = (xd->lossless[0]) ? ONLY_4X4
- : read_tx_mode(rb);
+ cm->tx_mode = (!cm->seg.enabled && xd->lossless[0]) ? ONLY_4X4
+ : read_tx_mode(rb);
cm->reference_mode = read_frame_reference_mode(cm, rb);
#endif
diff --git a/vp10/decoder/decodemv.c b/vp10/decoder/decodemv.c
index b516333..2bad07a 100644
--- a/vp10/decoder/decodemv.c
+++ b/vp10/decoder/decodemv.c
@@ -100,6 +100,8 @@
TX_MODE tx_mode = cm->tx_mode;
BLOCK_SIZE bsize = xd->mi[0]->mbmi.sb_type;
const TX_SIZE max_tx_size = max_txsize_lookup[bsize];
+ if (xd->lossless[xd->mi[0]->mbmi.segment_id])
+ return TX_4X4;
if (allow_select && tx_mode == TX_MODE_SELECT && bsize >= BLOCK_8X8)
return read_selected_tx_size(cm, xd, max_tx_size, r);
else
diff --git a/vp10/encoder/bitstream.c b/vp10/encoder/bitstream.c
index 361ac99..d4b8c36 100644
--- a/vp10/encoder/bitstream.c
+++ b/vp10/encoder/bitstream.c
@@ -303,7 +303,7 @@
vpx_write(w, is_inter, vp10_get_intra_inter_prob(cm, xd));
if (bsize >= BLOCK_8X8 && cm->tx_mode == TX_MODE_SELECT &&
- !(is_inter && skip)) {
+ !(is_inter && skip) && !xd->lossless[segment_id]) {
write_selected_tx_size(cm, xd, w);
}
@@ -391,7 +391,8 @@
write_skip(cm, xd, mbmi->segment_id, mi, w);
- if (bsize >= BLOCK_8X8 && cm->tx_mode == TX_MODE_SELECT)
+ if (bsize >= BLOCK_8X8 && cm->tx_mode == TX_MODE_SELECT &&
+ !xd->lossless[mbmi->segment_id])
write_selected_tx_size(cm, xd, w);
if (bsize >= BLOCK_8X8) {
@@ -1260,7 +1261,7 @@
encode_quantization(cm, wb);
encode_segmentation(cm, xd, wb);
#if CONFIG_MISC_FIXES
- if (xd->lossless[0])
+ if (!cm->seg.enabled && xd->lossless[0])
cm->tx_mode = TX_4X4;
else
write_txfm_mode(cm->tx_mode, wb);
diff --git a/vp9/common/vp9_reconinter.c b/vp9/common/vp9_reconinter.c
index d8c14ec..37658dc 100644
--- a/vp9/common/vp9_reconinter.c
+++ b/vp9/common/vp9_reconinter.c
@@ -190,6 +190,12 @@
// Co-ordinate of containing block to pixel precision.
const int x_start = (-xd->mb_to_left_edge >> (3 + pd->subsampling_x));
const int y_start = (-xd->mb_to_top_edge >> (3 + pd->subsampling_y));
+#if CONFIG_BETTER_HW_COMPATIBILITY
+ assert(xd->mi[0]->mbmi.sb_type != BLOCK_4X8 &&
+ xd->mi[0]->mbmi.sb_type != BLOCK_8X4);
+ assert(mv_q4.row == mv.row * (1 << (1 - pd->subsampling_y)) &&
+ mv_q4.col == mv.col * (1 << (1 - pd->subsampling_x)));
+#endif
if (plane == 0)
pre_buf->buf = xd->block_refs[ref]->buf->y_buffer;
else if (plane == 1)
diff --git a/vp9/decoder/vp9_decodeframe.c b/vp9/decoder/vp9_decodeframe.c
index 39e4dcf..3fd87cc 100644
--- a/vp9/decoder/vp9_decodeframe.c
+++ b/vp9/decoder/vp9_decodeframe.c
@@ -587,7 +587,12 @@
// Co-ordinate of containing block to pixel precision.
int x_start = (-xd->mb_to_left_edge >> (3 + pd->subsampling_x));
int y_start = (-xd->mb_to_top_edge >> (3 + pd->subsampling_y));
-
+#if CONFIG_BETTER_HW_COMPATIBILITY
+ assert(xd->mi[0]->mbmi.sb_type != BLOCK_4X8 &&
+ xd->mi[0]->mbmi.sb_type != BLOCK_8X4);
+ assert(mv_q4.row == mv->row * (1 << (1 - pd->subsampling_y)) &&
+ mv_q4.col == mv->col * (1 << (1 - pd->subsampling_x)));
+#endif
// Co-ordinate of the block to 1/16th pixel precision.
x0_16 = (x_start + x) << SUBPEL_BITS;
y0_16 = (y_start + y) << SUBPEL_BITS;
diff --git a/vp9/encoder/vp9_aq_cyclicrefresh.c b/vp9/encoder/vp9_aq_cyclicrefresh.c
index 7c71d9d..63db214 100644
--- a/vp9/encoder/vp9_aq_cyclicrefresh.c
+++ b/vp9/encoder/vp9_aq_cyclicrefresh.c
@@ -209,20 +209,12 @@
if (refresh_this_block == 0 &&
bsize <= BLOCK_16X16 &&
cpi->oxcf.content != VP9E_CONTENT_SCREEN) {
- // Take center pixel in block to determine is_skin.
- const int y_width_shift = (4 << b_width_log2_lookup[bsize]) >> 1;
- const int y_height_shift = (4 << b_height_log2_lookup[bsize]) >> 1;
- const int uv_width_shift = y_width_shift >> 1;
- const int uv_height_shift = y_height_shift >> 1;
- const int stride = p[0].src.stride;
- const int strideuv = p[1].src.stride;
- const uint8_t ysource =
- p[0].src.buf[y_height_shift * stride + y_width_shift];
- const uint8_t usource =
- p[1].src.buf[uv_height_shift * strideuv + uv_width_shift];
- const uint8_t vsource =
- p[2].src.buf[uv_height_shift * strideuv + uv_width_shift];
- is_skin = vp9_skin_pixel(ysource, usource, vsource);
+ is_skin = vp9_compute_skin_block(p[0].src.buf,
+ p[1].src.buf,
+ p[2].src.buf,
+ p[0].src.stride,
+ p[1].src.stride,
+ bsize);
if (is_skin)
refresh_this_block = 1;
}
diff --git a/vp9/encoder/vp9_denoiser.c b/vp9/encoder/vp9_denoiser.c
index 93aa40a..6533902 100644
--- a/vp9/encoder/vp9_denoiser.c
+++ b/vp9/encoder/vp9_denoiser.c
@@ -333,20 +333,12 @@
int is_skin = 0;
if (bs <= BLOCK_16X16 && denoiser->denoising_level >= kDenLow) {
- // Take center pixel in block to determine is_skin.
- const int y_width_shift = (4 << b_width_log2_lookup[bs]) >> 1;
- const int y_height_shift = (4 << b_height_log2_lookup[bs]) >> 1;
- const int uv_width_shift = y_width_shift >> 1;
- const int uv_height_shift = y_height_shift >> 1;
- const int stride = mb->plane[0].src.stride;
- const int strideuv = mb->plane[1].src.stride;
- const uint8_t ysource =
- mb->plane[0].src.buf[y_height_shift * stride + y_width_shift];
- const uint8_t usource =
- mb->plane[1].src.buf[uv_height_shift * strideuv + uv_width_shift];
- const uint8_t vsource =
- mb->plane[2].src.buf[uv_height_shift * strideuv + uv_width_shift];
- is_skin = vp9_skin_pixel(ysource, usource, vsource);
+ is_skin = vp9_compute_skin_block(mb->plane[0].src.buf,
+ mb->plane[1].src.buf,
+ mb->plane[2].src.buf,
+ mb->plane[0].src.stride,
+ mb->plane[1].src.stride,
+ bs);
}
mv_col = ctx->best_sse_mv.as_mv.col;
diff --git a/vp9/encoder/vp9_noise_estimate.c b/vp9/encoder/vp9_noise_estimate.c
index 4befbb0..008a40a 100644
--- a/vp9/encoder/vp9_noise_estimate.c
+++ b/vp9/encoder/vp9_noise_estimate.c
@@ -145,10 +145,6 @@
const uint8_t *src_u = cpi->Source->u_buffer;
const uint8_t *src_v = cpi->Source->v_buffer;
const int src_uvstride = cpi->Source->uv_stride;
- const int y_width_shift = (4 << b_width_log2_lookup[bsize]) >> 1;
- const int y_height_shift = (4 << b_height_log2_lookup[bsize]) >> 1;
- const int uv_width_shift = y_width_shift >> 1;
- const int uv_height_shift = y_height_shift >> 1;
int mi_row, mi_col;
int num_low_motion = 0;
int frame_low_motion = 1;
@@ -173,13 +169,12 @@
// been encoded as zero/low motion x (= thresh_consec_zeromv) frames
// in a row. consec_zero_mv[] defined for 8x8 blocks, so consider all
// 4 sub-blocks for 16x16 block. Also, avoid skin blocks.
- const uint8_t ysource =
- src_y[y_height_shift * src_ystride + y_width_shift];
- const uint8_t usource =
- src_u[uv_height_shift * src_uvstride + uv_width_shift];
- const uint8_t vsource =
- src_v[uv_height_shift * src_uvstride + uv_width_shift];
- int is_skin = vp9_skin_pixel(ysource, usource, vsource);
+ int is_skin = vp9_compute_skin_block(src_y,
+ src_u,
+ src_v,
+ src_ystride,
+ src_uvstride,
+ bsize);
if (frame_low_motion &&
cr->consec_zero_mv[bl_index] > thresh_consec_zeromv &&
cr->consec_zero_mv[bl_index1] > thresh_consec_zeromv &&
diff --git a/vp9/encoder/vp9_pickmode.c b/vp9/encoder/vp9_pickmode.c
index b929758..71b8bdb 100644
--- a/vp9/encoder/vp9_pickmode.c
+++ b/vp9/encoder/vp9_pickmode.c
@@ -1263,9 +1263,6 @@
ref_frame = ref_mode_set[idx].ref_frame;
if (cpi->use_svc) {
ref_frame = ref_mode_set_svc[idx].ref_frame;
- if (svc_force_zero_mode[ref_frame - 1] &&
- frame_mv[this_mode][ref_frame].as_int != 0)
- continue;
}
if (!(cpi->ref_frame_flags & flag_list[ref_frame]))
@@ -1273,6 +1270,12 @@
if (const_motion[ref_frame] && this_mode == NEARMV)
continue;
+ if (cpi->use_svc) {
+ if (svc_force_zero_mode[ref_frame - 1] &&
+ frame_mv[this_mode][ref_frame].as_int != 0)
+ continue;
+ }
+
if (!(frame_mv[this_mode][ref_frame].as_int == 0 &&
ref_frame == LAST_FRAME)) {
i = (ref_frame == LAST_FRAME) ? GOLDEN_FRAME : LAST_FRAME;
@@ -1855,6 +1858,13 @@
if (ref_frame_skip_mask & (1 << ref_frame))
continue;
+#if CONFIG_BETTER_HW_COMPATIBILITY
+ if ((bsize == BLOCK_8X4 || bsize == BLOCK_4X8) &&
+ ref_frame > INTRA_FRAME &&
+ vp9_is_scaled(&cm->frame_refs[ref_frame - 1].sf))
+ continue;
+#endif
+
// TODO(jingning, agrange): Scaling reference frame not supported for
// sub8x8 blocks. Is this supported now?
if (ref_frame > INTRA_FRAME &&
diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c
index bcd8f01..b8d1720 100644
--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -3035,7 +3035,7 @@
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
if (!(cpi->ref_frame_flags & flag_list[ref_frame])) {
// Skip checking missing references in both single and compound reference
- // modes. Note that a mode will be skipped iff both reference frames
+ // modes. Note that a mode will be skipped if both reference frames
// are masked out.
ref_frame_skip_mask[0] |= (1 << ref_frame);
ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
@@ -3818,6 +3818,16 @@
ref_frame = vp9_ref_order[ref_index].ref_frame[0];
second_ref_frame = vp9_ref_order[ref_index].ref_frame[1];
+#if CONFIG_BETTER_HW_COMPATIBILITY
+ // forbid 8X4 and 4X8 partitions if any reference frame is scaled.
+ if (bsize == BLOCK_8X4 || bsize == BLOCK_4X8) {
+ int ref_scaled = vp9_is_scaled(&cm->frame_refs[ref_frame - 1].sf);
+ if (second_ref_frame > INTRA_FRAME)
+ ref_scaled += vp9_is_scaled(&cm->frame_refs[second_ref_frame - 1].sf);
+ if (ref_scaled)
+ continue;
+ }
+#endif
// Look at the reference frame of the best mode so far and set the
// skip mask to look at a subset of the remaining modes.
if (ref_index > 2 && sf->mode_skip_start < MAX_MODES) {
diff --git a/vp9/encoder/vp9_skin_detection.c b/vp9/encoder/vp9_skin_detection.c
index c2763b7..0ca1665 100644
--- a/vp9/encoder/vp9_skin_detection.c
+++ b/vp9/encoder/vp9_skin_detection.c
@@ -48,6 +48,20 @@
return (evaluate_skin_color_difference(cb, cr) < skin_threshold);
}
+int vp9_compute_skin_block(const uint8_t *y, const uint8_t *u, const uint8_t *v,
+ int stride, int strideuv, int bsize) {
+ // Take center pixel in block to determine is_skin.
+ const int y_width_shift = (4 << b_width_log2_lookup[bsize]) >> 1;
+ const int y_height_shift = (4 << b_height_log2_lookup[bsize]) >> 1;
+ const int uv_width_shift = y_width_shift >> 1;
+ const int uv_height_shift = y_height_shift >> 1;
+ const uint8_t ysource = y[y_height_shift * stride + y_width_shift];
+ const uint8_t usource = u[uv_height_shift * strideuv + uv_width_shift];
+ const uint8_t vsource = v[uv_height_shift * strideuv + uv_width_shift];
+ return vp9_skin_pixel(ysource, usource, vsource);
+}
+
+
#ifdef OUTPUT_YUV_SKINMAP
// For viewing skin map on input source.
void vp9_compute_skin_map(VP9_COMP *const cpi, FILE *yuv_skinmap_file) {
diff --git a/vp9/encoder/vp9_skin_detection.h b/vp9/encoder/vp9_skin_detection.h
index 0a87ef9..73f7c39 100644
--- a/vp9/encoder/vp9_skin_detection.h
+++ b/vp9/encoder/vp9_skin_detection.h
@@ -23,6 +23,9 @@
int vp9_skin_pixel(const uint8_t y, const uint8_t cb, const uint8_t cr);
+int vp9_compute_skin_block(const uint8_t *y, const uint8_t *u, const uint8_t *v,
+ int stride, int strideuv, int bsize);
+
#ifdef OUTPUT_YUV_SKINMAP
// For viewing skin map on input source.
void vp9_compute_skin_map(struct VP9_COMP *const cpi, FILE *yuv_skinmap_file);
diff --git a/vp9/encoder/vp9_svc_layercontext.c b/vp9/encoder/vp9_svc_layercontext.c
index a4e7eb1..30a7d10 100644
--- a/vp9/encoder/vp9_svc_layercontext.c
+++ b/vp9/encoder/vp9_svc_layercontext.c
@@ -36,6 +36,12 @@
svc->current_superframe = 0;
for (i = 0; i < REF_FRAMES; ++i)
svc->ref_frame_index[i] = -1;
+ for (sl = 0; sl < oxcf->ss_number_layers; ++sl) {
+ cpi->svc.ext_frame_flags[sl] = 0;
+ cpi->svc.ext_lst_fb_idx[sl] = 0;
+ cpi->svc.ext_gld_fb_idx[sl] = 1;
+ cpi->svc.ext_alt_fb_idx[sl] = 2;
+ }
if (cpi->oxcf.error_resilient_mode == 0 && cpi->oxcf.pass == 2) {
if (vpx_realloc_frame_buffer(&cpi->svc.empty_frame.img,
@@ -566,6 +572,8 @@
// Note that the check (cpi->ext_refresh_frame_flags_pending == 0) is
// needed to support the case where the frame flags may be passed in via
// vpx_codec_encode(), which can be used for the temporal-only svc case.
+ // TODO(marpan): Consider adding an enc_config parameter to better handle
+ // this case.
if (cpi->ext_refresh_frame_flags_pending == 0) {
int sl;
cpi->svc.spatial_layer_id = cpi->svc.spatial_layer_to_encode;