Use lossless for Q0
authorYaowu Xu <yaowu@google.com>
Wed, 13 Feb 2013 22:22:15 +0000 (14:22 -0800)
committerYaowu Xu <yaowu@google.com>
Tue, 19 Feb 2013 14:18:42 +0000 (06:18 -0800)
The commit changes the coding mode to lossless whenever the lowest
quantizer is choosen.

As expected, test results showed no difference for cif and std-hd
set where Q0 is rarely used. For yt and yt-hd set, Q0 is used for
a number of clips, where this commit helped a lot in the high end.

Average over all clips in the sets:
yt: 2.391% 1.017% 1.066%
hd: 1.937%  .764%  .787%

Change-Id: I9fa9df8646fd70cb09ffe9e4202b86b67da16765

vp9/common/vp9_blockd.h
vp9/encoder/vp9_bitstream.c
vp9/encoder/vp9_encodeframe.c
vp9/encoder/vp9_onyx_if.c
vp9/encoder/vp9_quantize.c

index 46701a5..602b2a1 100644 (file)
@@ -140,7 +140,7 @@ typedef enum {
 #define VP9_MVREFS (1 + SPLITMV - NEARESTMV)
 
 #if CONFIG_LOSSLESS
-#define WHT_UPSCALE_FACTOR 3
+#define WHT_UPSCALE_FACTOR 2
 #endif
 
 typedef enum {
index 41fa4ed..8d6cfe9 100644 (file)
@@ -1673,8 +1673,8 @@ void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest,
   pc->sb32_coded = get_binary_prob(cpi->sb32_count[0], cpi->sb32_count[1]);
   vp9_write_literal(&header_bc, pc->sb32_coded, 8);
 #if CONFIG_LOSSLESS
-  vp9_write_bit(&header_bc, cpi->oxcf.lossless);
-  if (cpi->oxcf.lossless) {
+  vp9_write_bit(&header_bc, cpi->mb.e_mbd.lossless);
+  if (cpi->mb.e_mbd.lossless) {
     pc->txfm_mode = ONLY_4X4;
   }
   else
index 6708f62..4cf1022 100644 (file)
@@ -30,7 +30,7 @@
 #include "vp9/common/vp9_seg_common.h"
 #include "vp9/common/vp9_tile_common.h"
 #include "vp9/encoder/vp9_tokenize.h"
-#include "vp9_rtcd.h"
+#include "./vp9_rtcd.h"
 #include <stdio.h>
 #include <math.h>
 #include <limits.h>
@@ -1225,6 +1225,25 @@ static void init_encode_frame_mb_context(VP9_COMP *cpi) {
   if (cm->full_pixel)
     xd->fullpixel_mask = 0xfffffff8;
 }
+#if CONFIG_LOSSLESS
+static void switch_lossless_mode(VP9_COMP *cpi, int lossless) {
+  if (lossless) {
+    cpi->mb.fwd_txm8x4            = vp9_short_walsh8x4_x8;
+    cpi->mb.fwd_txm4x4            = vp9_short_walsh4x4_x8;
+    cpi->mb.e_mbd.inv_txm4x4_1    = vp9_short_inv_walsh4x4_1_x8;
+    cpi->mb.e_mbd.inv_txm4x4      = vp9_short_inv_walsh4x4_x8;
+    cpi->mb.optimize              = 0;
+    cpi->common.filter_level      = 0;
+    cpi->zbin_mode_boost_enabled  = FALSE;
+    cpi->common.txfm_mode         = ONLY_4X4;
+  } else {
+    cpi->mb.fwd_txm8x4            = vp9_short_fdct8x4;
+    cpi->mb.fwd_txm4x4            = vp9_short_fdct4x4;
+    cpi->mb.e_mbd.inv_txm4x4_1    = vp9_short_idct4x4llm_1;
+    cpi->mb.e_mbd.inv_txm4x4      = vp9_short_idct4x4llm;
+  }
+}
+#endif
 
 static void encode_frame_internal(VP9_COMP *cpi) {
   int mb_row;
@@ -1282,6 +1301,14 @@ static void encode_frame_internal(VP9_COMP *cpi) {
   vp9_zero(cpi->mb_mv_ref_count);
 #endif
 
+#if CONFIG_LOSSLESS
+  // force lossless mode when Q0 is selected
+  cpi->mb.e_mbd.lossless = (cm->base_qindex == 0 &&
+                            cm->y1dc_delta_q == 0 &&
+                            cm->uvdc_delta_q == 0 &&
+                            cm->uvac_delta_q == 0);
+  switch_lossless_mode(cpi, cpi->mb.e_mbd.lossless);
+#endif
   vp9_frame_init_quantizer(cpi);
 
   vp9_initialize_rd_consts(cpi, cm->base_qindex + cm->y1dc_delta_q);
index b54f4ad..2528122 100644 (file)
@@ -847,7 +847,7 @@ void vp9_set_speed_features(VP9_COMP *cpi) {
   cpi->mb.fwd_txm4x4    = vp9_short_fdct4x4;
 
 #if CONFIG_LOSSLESS
-  if (cpi->oxcf.lossless) {
+  if (cpi->oxcf.lossless || cpi->mb.e_mbd.lossless) {
     cpi->mb.fwd_txm8x4    = vp9_short_walsh8x4_x8;
     cpi->mb.fwd_txm4x4    = vp9_short_walsh4x4_x8;
   }
@@ -2469,7 +2469,7 @@ static void loopfilter_frame(VP9_COMP *cpi, VP9_COMMON *cm) {
     cm->filter_level = 0;
   }
 #if CONFIG_LOSSLESS
-  else if (cpi->oxcf.lossless) {
+  else if (cpi->mb.e_mbd.lossless) {
     cm->filter_level = 0;
   }
 #endif
index f092b59..aed379a 100644 (file)
@@ -411,15 +411,11 @@ void vp9_init_quantizer(VP9_COMP *cpi) {
 
   for (Q = 0; Q < QINDEX_RANGE; Q++) {
     int qzbin_factor = (vp9_dc_quant(Q, 0) < 148) ? 84 : 80;
-
     int qrounding_factor = 48;
-#if CONFIG_LOSSLESS
-    if (cpi->oxcf.lossless && Q == 0) {
+    if (Q == 0) {
       qzbin_factor = 64;
       qrounding_factor = 64;
     }
-#endif
-
     // dc values
     quant_val = vp9_dc_quant(Q, cpi->common.y1dc_delta_q);
     invert_quant(cpi->Y1quant[Q] + 0,