Add encoder/decoder support for var-refs

Check the availability of the reference frames at the frame level at
both encoder and decoder, and if a reference frame is not available
for a specific video frame, remove the signaling of such reference
frame info at the block level.

This patch adds the consideration of the bit saving inside the RD
optimization loop.

Change-Id: I4c22f1b843b21c7d2b47e118c99c3ad615a3d4e4
diff --git a/av1/decoder/decodemv.c b/av1/decoder/decodemv.c
index 8acc06a..657eb6e 100644
--- a/av1/decoder/decodemv.c
+++ b/av1/decoder/decodemv.c
@@ -1260,65 +1260,145 @@
       const int idx = cm->ref_frame_sign_bias[cm->comp_fixed_ref];
 #endif  // CONFIG_EXT_REFS
 #endif
-      const int ctx = av1_get_pred_context_comp_ref_p(cm, xd);
 
+      const int ctx = av1_get_pred_context_comp_ref_p(cm, xd);
+#if CONFIG_VAR_REFS
+      int bit;
+      // Test need to explicitly code (L,L2) vs (L3,G) branch node in tree
+      if (L_OR_L2(cm) && L3_OR_G(cm))
+        bit = aom_read(r, fc->comp_ref_prob[ctx][0], ACCT_STR);
+      else
+        bit = L3_OR_G(cm);
+#else   // !CONFIG_VAR_REFS
       const int bit = aom_read(r, fc->comp_ref_prob[ctx][0], ACCT_STR);
+#endif  // CONFIG_VAR_REFS
       if (counts) ++counts->comp_ref[ctx][0][bit];
 
 #if CONFIG_EXT_REFS
       // Decode forward references.
       if (!bit) {
         const int ctx1 = av1_get_pred_context_comp_ref_p1(cm, xd);
+#if CONFIG_VAR_REFS
+        int bit1;
+        // Test need to explicitly code (L) vs (L2) branch node in tree
+        if (L_AND_L2(cm))
+          bit1 = aom_read(r, fc->comp_ref_prob[ctx1][1], ACCT_STR);
+        else
+          bit1 = LAST_IS_VALID(cm);
+#else   // !CONFIG_VAR_REFS
         const int bit1 = aom_read(r, fc->comp_ref_prob[ctx1][1], ACCT_STR);
+#endif  // CONFIG_VAR_REFS
         if (counts) ++counts->comp_ref[ctx1][1][bit1];
         ref_frame[!idx] = cm->comp_fwd_ref[bit1 ? 0 : 1];
       } else {
         const int ctx2 = av1_get_pred_context_comp_ref_p2(cm, xd);
+#if CONFIG_VAR_REFS
+        int bit2;
+        // Test need to explicitly code (L3) vs (G) branch node in tree
+        if (L3_AND_G(cm))
+          bit2 = aom_read(r, fc->comp_ref_prob[ctx2][2], ACCT_STR);
+        else
+          bit2 = GOLDEN_IS_VALID(cm);
+#else   // !CONFIG_VAR_REFS
         const int bit2 = aom_read(r, fc->comp_ref_prob[ctx2][2], ACCT_STR);
+#endif  // CONFIG_VAR_REFS
         if (counts) ++counts->comp_ref[ctx2][2][bit2];
         ref_frame[!idx] = cm->comp_fwd_ref[bit2 ? 3 : 2];
       }
 
       // Decode backward references.
-      {
-        const int ctx_bwd = av1_get_pred_context_comp_bwdref_p(cm, xd);
-        const int bit_bwd =
-            aom_read(r, fc->comp_bwdref_prob[ctx_bwd][0], ACCT_STR);
-        if (counts) ++counts->comp_bwdref[ctx_bwd][0][bit_bwd];
-        ref_frame[idx] = cm->comp_bwd_ref[bit_bwd];
-      }
-#else
+      const int ctx_bwd = av1_get_pred_context_comp_bwdref_p(cm, xd);
+#if CONFIG_VAR_REFS
+      int bit_bwd;
+      // Test need to explicitly code (BWD) vs (ALT) branch node in tree
+      if (BWD_AND_ALT(cm))
+        bit_bwd = aom_read(r, fc->comp_bwdref_prob[ctx_bwd][0], ACCT_STR);
+      else
+        bit_bwd = ALTREF_IS_VALID(cm);
+#else   // !CONFIG_VAR_REFS
+      const int bit_bwd =
+          aom_read(r, fc->comp_bwdref_prob[ctx_bwd][0], ACCT_STR);
+#endif  // CONFIG_VAR_REFS
+      if (counts) ++counts->comp_bwdref[ctx_bwd][0][bit_bwd];
+      ref_frame[idx] = cm->comp_bwd_ref[bit_bwd];
+#else   // !CONFIG_EXT_REFS
       ref_frame[!idx] = cm->comp_var_ref[bit];
       ref_frame[idx] = cm->comp_fixed_ref;
 #endif  // CONFIG_EXT_REFS
     } else if (mode == SINGLE_REFERENCE) {
 #if CONFIG_EXT_REFS
       const int ctx0 = av1_get_pred_context_single_ref_p1(xd);
+#if CONFIG_VAR_REFS
+      int bit0;
+      // Test need to explicitly code (L,L2,L3,G) vs (BWD,ALT) branch node in
+      // tree
+      if ((L_OR_L2(cm) || L3_OR_G(cm)) && BWD_OR_ALT(cm))
+        bit0 = aom_read(r, fc->single_ref_prob[ctx0][0], ACCT_STR);
+      else
+        bit0 = BWD_OR_ALT(cm);
+#else   // !CONFIG_VAR_REFS
       const int bit0 = aom_read(r, fc->single_ref_prob[ctx0][0], ACCT_STR);
+#endif  // CONFIG_VAR_REFS
       if (counts) ++counts->single_ref[ctx0][0][bit0];
 
       if (bit0) {
         const int ctx1 = av1_get_pred_context_single_ref_p2(xd);
+#if CONFIG_VAR_REFS
+        int bit1;
+        // Test need to explicitly code (BWD) vs (ALT) branch node in tree
+        if (BWD_AND_ALT(cm))
+          bit1 = aom_read(r, fc->single_ref_prob[ctx1][1], ACCT_STR);
+        else
+          bit1 = ALTREF_IS_VALID(cm);
+#else   // !CONFIG_VAR_REFS
         const int bit1 = aom_read(r, fc->single_ref_prob[ctx1][1], ACCT_STR);
+#endif  // CONFIG_VAR_REFS
         if (counts) ++counts->single_ref[ctx1][1][bit1];
         ref_frame[0] = bit1 ? ALTREF_FRAME : BWDREF_FRAME;
       } else {
         const int ctx2 = av1_get_pred_context_single_ref_p3(xd);
+#if CONFIG_VAR_REFS
+        int bit2;
+        // Test need to explicitly code (L,L2) vs (L3,G) branch node in tree
+        if (L_OR_L2(cm) && L3_OR_G(cm))
+          bit2 = aom_read(r, fc->single_ref_prob[ctx2][2], ACCT_STR);
+        else
+          bit2 = L3_OR_G(cm);
+#else   // !CONFIG_VAR_REFS
         const int bit2 = aom_read(r, fc->single_ref_prob[ctx2][2], ACCT_STR);
+#endif  // CONFIG_VAR_REFS
         if (counts) ++counts->single_ref[ctx2][2][bit2];
         if (bit2) {
           const int ctx4 = av1_get_pred_context_single_ref_p5(xd);
+#if CONFIG_VAR_REFS
+          int bit4;
+          // Test need to explicitly code (L3) vs (G) branch node in tree
+          if (L3_AND_G(cm))
+            bit4 = aom_read(r, fc->single_ref_prob[ctx4][4], ACCT_STR);
+          else
+            bit4 = GOLDEN_IS_VALID(cm);
+#else   // !CONFIG_VAR_REFS
           const int bit4 = aom_read(r, fc->single_ref_prob[ctx4][4], ACCT_STR);
+#endif  // CONFIG_VAR_REFS
           if (counts) ++counts->single_ref[ctx4][4][bit4];
           ref_frame[0] = bit4 ? GOLDEN_FRAME : LAST3_FRAME;
         } else {
           const int ctx3 = av1_get_pred_context_single_ref_p4(xd);
+#if CONFIG_VAR_REFS
+          int bit3;
+          // Test need to explicitly code (L) vs (L2) branch node in tree
+          if (L_AND_L2(cm))
+            bit3 = aom_read(r, fc->single_ref_prob[ctx3][3], ACCT_STR);
+          else
+            bit3 = LAST2_IS_VALID(cm);
+#else   // !CONFIG_VAR_REFS
           const int bit3 = aom_read(r, fc->single_ref_prob[ctx3][3], ACCT_STR);
+#endif  // CONFIG_VAR_REFS
           if (counts) ++counts->single_ref[ctx3][3][bit3];
           ref_frame[0] = bit3 ? LAST2_FRAME : LAST_FRAME;
         }
       }
-#else
+#else   // !CONFIG_EXT_REFS
       const int ctx0 = av1_get_pred_context_single_ref_p1(xd);
       const int bit0 = aom_read(r, fc->single_ref_prob[ctx0][0], ACCT_STR);
       if (counts) ++counts->single_ref[ctx0][0][bit0];