1*fb1b10abSAndroid Build Coastguard Worker 2*fb1b10abSAndroid Build Coastguard Worker /* 3*fb1b10abSAndroid Build Coastguard Worker * Copyright (c) 2012 The WebM project authors. All Rights Reserved. 4*fb1b10abSAndroid Build Coastguard Worker * 5*fb1b10abSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license 6*fb1b10abSAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source 7*fb1b10abSAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found 8*fb1b10abSAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may 9*fb1b10abSAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree. 10*fb1b10abSAndroid Build Coastguard Worker */ 11*fb1b10abSAndroid Build Coastguard Worker 12*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_common.h" 13*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_pred_common.h" 14*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_seg_common.h" 15*fb1b10abSAndroid Build Coastguard Worker vp9_compound_reference_allowed(const VP9_COMMON * cm)16*fb1b10abSAndroid Build Coastguard Workerint vp9_compound_reference_allowed(const VP9_COMMON *cm) { 17*fb1b10abSAndroid Build Coastguard Worker int i; 18*fb1b10abSAndroid Build Coastguard Worker for (i = 1; i < REFS_PER_FRAME; ++i) 19*fb1b10abSAndroid Build Coastguard Worker if (cm->ref_frame_sign_bias[i + 1] != cm->ref_frame_sign_bias[1]) return 1; 20*fb1b10abSAndroid Build Coastguard Worker 21*fb1b10abSAndroid Build Coastguard Worker return 0; 22*fb1b10abSAndroid Build Coastguard Worker } 23*fb1b10abSAndroid Build Coastguard Worker vp9_setup_compound_reference_mode(VP9_COMMON * cm)24*fb1b10abSAndroid Build Coastguard Workervoid vp9_setup_compound_reference_mode(VP9_COMMON *cm) { 25*fb1b10abSAndroid Build Coastguard Worker if (cm->ref_frame_sign_bias[LAST_FRAME] == 26*fb1b10abSAndroid Build Coastguard Worker cm->ref_frame_sign_bias[GOLDEN_FRAME]) { 27*fb1b10abSAndroid Build Coastguard Worker cm->comp_fixed_ref = ALTREF_FRAME; 28*fb1b10abSAndroid Build Coastguard Worker cm->comp_var_ref[0] = LAST_FRAME; 29*fb1b10abSAndroid Build Coastguard Worker cm->comp_var_ref[1] = GOLDEN_FRAME; 30*fb1b10abSAndroid Build Coastguard Worker } else if (cm->ref_frame_sign_bias[LAST_FRAME] == 31*fb1b10abSAndroid Build Coastguard Worker cm->ref_frame_sign_bias[ALTREF_FRAME]) { 32*fb1b10abSAndroid Build Coastguard Worker cm->comp_fixed_ref = GOLDEN_FRAME; 33*fb1b10abSAndroid Build Coastguard Worker cm->comp_var_ref[0] = LAST_FRAME; 34*fb1b10abSAndroid Build Coastguard Worker cm->comp_var_ref[1] = ALTREF_FRAME; 35*fb1b10abSAndroid Build Coastguard Worker } else { 36*fb1b10abSAndroid Build Coastguard Worker cm->comp_fixed_ref = LAST_FRAME; 37*fb1b10abSAndroid Build Coastguard Worker cm->comp_var_ref[0] = GOLDEN_FRAME; 38*fb1b10abSAndroid Build Coastguard Worker cm->comp_var_ref[1] = ALTREF_FRAME; 39*fb1b10abSAndroid Build Coastguard Worker } 40*fb1b10abSAndroid Build Coastguard Worker } 41*fb1b10abSAndroid Build Coastguard Worker vp9_get_reference_mode_context(const VP9_COMMON * cm,const MACROBLOCKD * xd)42*fb1b10abSAndroid Build Coastguard Workerint vp9_get_reference_mode_context(const VP9_COMMON *cm, 43*fb1b10abSAndroid Build Coastguard Worker const MACROBLOCKD *xd) { 44*fb1b10abSAndroid Build Coastguard Worker int ctx; 45*fb1b10abSAndroid Build Coastguard Worker const MODE_INFO *const above_mi = xd->above_mi; 46*fb1b10abSAndroid Build Coastguard Worker const MODE_INFO *const left_mi = xd->left_mi; 47*fb1b10abSAndroid Build Coastguard Worker const int has_above = !!above_mi; 48*fb1b10abSAndroid Build Coastguard Worker const int has_left = !!left_mi; 49*fb1b10abSAndroid Build Coastguard Worker // Note: 50*fb1b10abSAndroid Build Coastguard Worker // The mode info data structure has a one element border above and to the 51*fb1b10abSAndroid Build Coastguard Worker // left of the entries corresponding to real macroblocks. 52*fb1b10abSAndroid Build Coastguard Worker // The prediction flags in these dummy entries are initialized to 0. 53*fb1b10abSAndroid Build Coastguard Worker if (has_above && has_left) { // both edges available 54*fb1b10abSAndroid Build Coastguard Worker if (!has_second_ref(above_mi) && !has_second_ref(left_mi)) 55*fb1b10abSAndroid Build Coastguard Worker // neither edge uses comp pred (0/1) 56*fb1b10abSAndroid Build Coastguard Worker ctx = (above_mi->ref_frame[0] == cm->comp_fixed_ref) ^ 57*fb1b10abSAndroid Build Coastguard Worker (left_mi->ref_frame[0] == cm->comp_fixed_ref); 58*fb1b10abSAndroid Build Coastguard Worker else if (!has_second_ref(above_mi)) 59*fb1b10abSAndroid Build Coastguard Worker // one of two edges uses comp pred (2/3) 60*fb1b10abSAndroid Build Coastguard Worker ctx = 2 + (above_mi->ref_frame[0] == cm->comp_fixed_ref || 61*fb1b10abSAndroid Build Coastguard Worker !is_inter_block(above_mi)); 62*fb1b10abSAndroid Build Coastguard Worker else if (!has_second_ref(left_mi)) 63*fb1b10abSAndroid Build Coastguard Worker // one of two edges uses comp pred (2/3) 64*fb1b10abSAndroid Build Coastguard Worker ctx = 2 + (left_mi->ref_frame[0] == cm->comp_fixed_ref || 65*fb1b10abSAndroid Build Coastguard Worker !is_inter_block(left_mi)); 66*fb1b10abSAndroid Build Coastguard Worker else // both edges use comp pred (4) 67*fb1b10abSAndroid Build Coastguard Worker ctx = 4; 68*fb1b10abSAndroid Build Coastguard Worker } else if (has_above || has_left) { // one edge available 69*fb1b10abSAndroid Build Coastguard Worker const MODE_INFO *edge_mi = has_above ? above_mi : left_mi; 70*fb1b10abSAndroid Build Coastguard Worker 71*fb1b10abSAndroid Build Coastguard Worker if (!has_second_ref(edge_mi)) 72*fb1b10abSAndroid Build Coastguard Worker // edge does not use comp pred (0/1) 73*fb1b10abSAndroid Build Coastguard Worker ctx = edge_mi->ref_frame[0] == cm->comp_fixed_ref; 74*fb1b10abSAndroid Build Coastguard Worker else 75*fb1b10abSAndroid Build Coastguard Worker // edge uses comp pred (3) 76*fb1b10abSAndroid Build Coastguard Worker ctx = 3; 77*fb1b10abSAndroid Build Coastguard Worker } else { // no edges available (1) 78*fb1b10abSAndroid Build Coastguard Worker ctx = 1; 79*fb1b10abSAndroid Build Coastguard Worker } 80*fb1b10abSAndroid Build Coastguard Worker assert(ctx >= 0 && ctx < COMP_INTER_CONTEXTS); 81*fb1b10abSAndroid Build Coastguard Worker return ctx; 82*fb1b10abSAndroid Build Coastguard Worker } 83*fb1b10abSAndroid Build Coastguard Worker 84*fb1b10abSAndroid Build Coastguard Worker // Returns a context number for the given MB prediction signal vp9_get_pred_context_comp_ref_p(const VP9_COMMON * cm,const MACROBLOCKD * xd)85*fb1b10abSAndroid Build Coastguard Workerint vp9_get_pred_context_comp_ref_p(const VP9_COMMON *cm, 86*fb1b10abSAndroid Build Coastguard Worker const MACROBLOCKD *xd) { 87*fb1b10abSAndroid Build Coastguard Worker int pred_context; 88*fb1b10abSAndroid Build Coastguard Worker const MODE_INFO *const above_mi = xd->above_mi; 89*fb1b10abSAndroid Build Coastguard Worker const MODE_INFO *const left_mi = xd->left_mi; 90*fb1b10abSAndroid Build Coastguard Worker const int above_in_image = !!above_mi; 91*fb1b10abSAndroid Build Coastguard Worker const int left_in_image = !!left_mi; 92*fb1b10abSAndroid Build Coastguard Worker 93*fb1b10abSAndroid Build Coastguard Worker // Note: 94*fb1b10abSAndroid Build Coastguard Worker // The mode info data structure has a one element border above and to the 95*fb1b10abSAndroid Build Coastguard Worker // left of the entries corresponding to real macroblocks. 96*fb1b10abSAndroid Build Coastguard Worker // The prediction flags in these dummy entries are initialized to 0. 97*fb1b10abSAndroid Build Coastguard Worker const int fix_ref_idx = cm->ref_frame_sign_bias[cm->comp_fixed_ref]; 98*fb1b10abSAndroid Build Coastguard Worker const int var_ref_idx = !fix_ref_idx; 99*fb1b10abSAndroid Build Coastguard Worker 100*fb1b10abSAndroid Build Coastguard Worker if (above_in_image && left_in_image) { // both edges available 101*fb1b10abSAndroid Build Coastguard Worker const int above_intra = !is_inter_block(above_mi); 102*fb1b10abSAndroid Build Coastguard Worker const int left_intra = !is_inter_block(left_mi); 103*fb1b10abSAndroid Build Coastguard Worker 104*fb1b10abSAndroid Build Coastguard Worker if (above_intra && left_intra) { // intra/intra (2) 105*fb1b10abSAndroid Build Coastguard Worker pred_context = 2; 106*fb1b10abSAndroid Build Coastguard Worker } else if (above_intra || left_intra) { // intra/inter 107*fb1b10abSAndroid Build Coastguard Worker const MODE_INFO *edge_mi = above_intra ? left_mi : above_mi; 108*fb1b10abSAndroid Build Coastguard Worker 109*fb1b10abSAndroid Build Coastguard Worker if (!has_second_ref(edge_mi)) // single pred (1/3) 110*fb1b10abSAndroid Build Coastguard Worker pred_context = 1 + 2 * (edge_mi->ref_frame[0] != cm->comp_var_ref[1]); 111*fb1b10abSAndroid Build Coastguard Worker else // comp pred (1/3) 112*fb1b10abSAndroid Build Coastguard Worker pred_context = 113*fb1b10abSAndroid Build Coastguard Worker 1 + 2 * (edge_mi->ref_frame[var_ref_idx] != cm->comp_var_ref[1]); 114*fb1b10abSAndroid Build Coastguard Worker } else { // inter/inter 115*fb1b10abSAndroid Build Coastguard Worker const int l_sg = !has_second_ref(left_mi); 116*fb1b10abSAndroid Build Coastguard Worker const int a_sg = !has_second_ref(above_mi); 117*fb1b10abSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME vrfa = 118*fb1b10abSAndroid Build Coastguard Worker a_sg ? above_mi->ref_frame[0] : above_mi->ref_frame[var_ref_idx]; 119*fb1b10abSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME vrfl = 120*fb1b10abSAndroid Build Coastguard Worker l_sg ? left_mi->ref_frame[0] : left_mi->ref_frame[var_ref_idx]; 121*fb1b10abSAndroid Build Coastguard Worker 122*fb1b10abSAndroid Build Coastguard Worker if (vrfa == vrfl && cm->comp_var_ref[1] == vrfa) { 123*fb1b10abSAndroid Build Coastguard Worker pred_context = 0; 124*fb1b10abSAndroid Build Coastguard Worker } else if (l_sg && a_sg) { // single/single 125*fb1b10abSAndroid Build Coastguard Worker if ((vrfa == cm->comp_fixed_ref && vrfl == cm->comp_var_ref[0]) || 126*fb1b10abSAndroid Build Coastguard Worker (vrfl == cm->comp_fixed_ref && vrfa == cm->comp_var_ref[0])) 127*fb1b10abSAndroid Build Coastguard Worker pred_context = 4; 128*fb1b10abSAndroid Build Coastguard Worker else if (vrfa == vrfl) 129*fb1b10abSAndroid Build Coastguard Worker pred_context = 3; 130*fb1b10abSAndroid Build Coastguard Worker else 131*fb1b10abSAndroid Build Coastguard Worker pred_context = 1; 132*fb1b10abSAndroid Build Coastguard Worker } else if (l_sg || a_sg) { // single/comp 133*fb1b10abSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME vrfc = l_sg ? vrfa : vrfl; 134*fb1b10abSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME rfs = a_sg ? vrfa : vrfl; 135*fb1b10abSAndroid Build Coastguard Worker if (vrfc == cm->comp_var_ref[1] && rfs != cm->comp_var_ref[1]) 136*fb1b10abSAndroid Build Coastguard Worker pred_context = 1; 137*fb1b10abSAndroid Build Coastguard Worker else if (rfs == cm->comp_var_ref[1] && vrfc != cm->comp_var_ref[1]) 138*fb1b10abSAndroid Build Coastguard Worker pred_context = 2; 139*fb1b10abSAndroid Build Coastguard Worker else 140*fb1b10abSAndroid Build Coastguard Worker pred_context = 4; 141*fb1b10abSAndroid Build Coastguard Worker } else if (vrfa == vrfl) { // comp/comp 142*fb1b10abSAndroid Build Coastguard Worker pred_context = 4; 143*fb1b10abSAndroid Build Coastguard Worker } else { 144*fb1b10abSAndroid Build Coastguard Worker pred_context = 2; 145*fb1b10abSAndroid Build Coastguard Worker } 146*fb1b10abSAndroid Build Coastguard Worker } 147*fb1b10abSAndroid Build Coastguard Worker } else if (above_in_image || left_in_image) { // one edge available 148*fb1b10abSAndroid Build Coastguard Worker const MODE_INFO *edge_mi = above_in_image ? above_mi : left_mi; 149*fb1b10abSAndroid Build Coastguard Worker 150*fb1b10abSAndroid Build Coastguard Worker if (!is_inter_block(edge_mi)) { 151*fb1b10abSAndroid Build Coastguard Worker pred_context = 2; 152*fb1b10abSAndroid Build Coastguard Worker } else { 153*fb1b10abSAndroid Build Coastguard Worker if (has_second_ref(edge_mi)) 154*fb1b10abSAndroid Build Coastguard Worker pred_context = 155*fb1b10abSAndroid Build Coastguard Worker 4 * (edge_mi->ref_frame[var_ref_idx] != cm->comp_var_ref[1]); 156*fb1b10abSAndroid Build Coastguard Worker else 157*fb1b10abSAndroid Build Coastguard Worker pred_context = 3 * (edge_mi->ref_frame[0] != cm->comp_var_ref[1]); 158*fb1b10abSAndroid Build Coastguard Worker } 159*fb1b10abSAndroid Build Coastguard Worker } else { // no edges available (2) 160*fb1b10abSAndroid Build Coastguard Worker pred_context = 2; 161*fb1b10abSAndroid Build Coastguard Worker } 162*fb1b10abSAndroid Build Coastguard Worker assert(pred_context >= 0 && pred_context < REF_CONTEXTS); 163*fb1b10abSAndroid Build Coastguard Worker 164*fb1b10abSAndroid Build Coastguard Worker return pred_context; 165*fb1b10abSAndroid Build Coastguard Worker } 166*fb1b10abSAndroid Build Coastguard Worker vp9_get_pred_context_single_ref_p1(const MACROBLOCKD * xd)167*fb1b10abSAndroid Build Coastguard Workerint vp9_get_pred_context_single_ref_p1(const MACROBLOCKD *xd) { 168*fb1b10abSAndroid Build Coastguard Worker int pred_context; 169*fb1b10abSAndroid Build Coastguard Worker const MODE_INFO *const above_mi = xd->above_mi; 170*fb1b10abSAndroid Build Coastguard Worker const MODE_INFO *const left_mi = xd->left_mi; 171*fb1b10abSAndroid Build Coastguard Worker const int has_above = !!above_mi; 172*fb1b10abSAndroid Build Coastguard Worker const int has_left = !!left_mi; 173*fb1b10abSAndroid Build Coastguard Worker // Note: 174*fb1b10abSAndroid Build Coastguard Worker // The mode info data structure has a one element border above and to the 175*fb1b10abSAndroid Build Coastguard Worker // left of the entries corresponding to real macroblocks. 176*fb1b10abSAndroid Build Coastguard Worker // The prediction flags in these dummy entries are initialized to 0. 177*fb1b10abSAndroid Build Coastguard Worker if (has_above && has_left) { // both edges available 178*fb1b10abSAndroid Build Coastguard Worker const int above_intra = !is_inter_block(above_mi); 179*fb1b10abSAndroid Build Coastguard Worker const int left_intra = !is_inter_block(left_mi); 180*fb1b10abSAndroid Build Coastguard Worker 181*fb1b10abSAndroid Build Coastguard Worker if (above_intra && left_intra) { // intra/intra 182*fb1b10abSAndroid Build Coastguard Worker pred_context = 2; 183*fb1b10abSAndroid Build Coastguard Worker } else if (above_intra || left_intra) { // intra/inter or inter/intra 184*fb1b10abSAndroid Build Coastguard Worker const MODE_INFO *edge_mi = above_intra ? left_mi : above_mi; 185*fb1b10abSAndroid Build Coastguard Worker if (!has_second_ref(edge_mi)) 186*fb1b10abSAndroid Build Coastguard Worker pred_context = 4 * (edge_mi->ref_frame[0] == LAST_FRAME); 187*fb1b10abSAndroid Build Coastguard Worker else 188*fb1b10abSAndroid Build Coastguard Worker pred_context = 1 + (edge_mi->ref_frame[0] == LAST_FRAME || 189*fb1b10abSAndroid Build Coastguard Worker edge_mi->ref_frame[1] == LAST_FRAME); 190*fb1b10abSAndroid Build Coastguard Worker } else { // inter/inter 191*fb1b10abSAndroid Build Coastguard Worker const int above_has_second = has_second_ref(above_mi); 192*fb1b10abSAndroid Build Coastguard Worker const int left_has_second = has_second_ref(left_mi); 193*fb1b10abSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME above0 = above_mi->ref_frame[0]; 194*fb1b10abSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME above1 = above_mi->ref_frame[1]; 195*fb1b10abSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME left0 = left_mi->ref_frame[0]; 196*fb1b10abSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME left1 = left_mi->ref_frame[1]; 197*fb1b10abSAndroid Build Coastguard Worker 198*fb1b10abSAndroid Build Coastguard Worker if (above_has_second && left_has_second) { 199*fb1b10abSAndroid Build Coastguard Worker pred_context = 1 + (above0 == LAST_FRAME || above1 == LAST_FRAME || 200*fb1b10abSAndroid Build Coastguard Worker left0 == LAST_FRAME || left1 == LAST_FRAME); 201*fb1b10abSAndroid Build Coastguard Worker } else if (above_has_second || left_has_second) { 202*fb1b10abSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME rfs = !above_has_second ? above0 : left0; 203*fb1b10abSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME crf1 = above_has_second ? above0 : left0; 204*fb1b10abSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME crf2 = above_has_second ? above1 : left1; 205*fb1b10abSAndroid Build Coastguard Worker 206*fb1b10abSAndroid Build Coastguard Worker if (rfs == LAST_FRAME) 207*fb1b10abSAndroid Build Coastguard Worker pred_context = 3 + (crf1 == LAST_FRAME || crf2 == LAST_FRAME); 208*fb1b10abSAndroid Build Coastguard Worker else 209*fb1b10abSAndroid Build Coastguard Worker pred_context = (crf1 == LAST_FRAME || crf2 == LAST_FRAME); 210*fb1b10abSAndroid Build Coastguard Worker } else { 211*fb1b10abSAndroid Build Coastguard Worker pred_context = 2 * (above0 == LAST_FRAME) + 2 * (left0 == LAST_FRAME); 212*fb1b10abSAndroid Build Coastguard Worker } 213*fb1b10abSAndroid Build Coastguard Worker } 214*fb1b10abSAndroid Build Coastguard Worker } else if (has_above || has_left) { // one edge available 215*fb1b10abSAndroid Build Coastguard Worker const MODE_INFO *edge_mi = has_above ? above_mi : left_mi; 216*fb1b10abSAndroid Build Coastguard Worker if (!is_inter_block(edge_mi)) { // intra 217*fb1b10abSAndroid Build Coastguard Worker pred_context = 2; 218*fb1b10abSAndroid Build Coastguard Worker } else { // inter 219*fb1b10abSAndroid Build Coastguard Worker if (!has_second_ref(edge_mi)) 220*fb1b10abSAndroid Build Coastguard Worker pred_context = 4 * (edge_mi->ref_frame[0] == LAST_FRAME); 221*fb1b10abSAndroid Build Coastguard Worker else 222*fb1b10abSAndroid Build Coastguard Worker pred_context = 1 + (edge_mi->ref_frame[0] == LAST_FRAME || 223*fb1b10abSAndroid Build Coastguard Worker edge_mi->ref_frame[1] == LAST_FRAME); 224*fb1b10abSAndroid Build Coastguard Worker } 225*fb1b10abSAndroid Build Coastguard Worker } else { // no edges available 226*fb1b10abSAndroid Build Coastguard Worker pred_context = 2; 227*fb1b10abSAndroid Build Coastguard Worker } 228*fb1b10abSAndroid Build Coastguard Worker 229*fb1b10abSAndroid Build Coastguard Worker assert(pred_context >= 0 && pred_context < REF_CONTEXTS); 230*fb1b10abSAndroid Build Coastguard Worker return pred_context; 231*fb1b10abSAndroid Build Coastguard Worker } 232*fb1b10abSAndroid Build Coastguard Worker vp9_get_pred_context_single_ref_p2(const MACROBLOCKD * xd)233*fb1b10abSAndroid Build Coastguard Workerint vp9_get_pred_context_single_ref_p2(const MACROBLOCKD *xd) { 234*fb1b10abSAndroid Build Coastguard Worker int pred_context; 235*fb1b10abSAndroid Build Coastguard Worker const MODE_INFO *const above_mi = xd->above_mi; 236*fb1b10abSAndroid Build Coastguard Worker const MODE_INFO *const left_mi = xd->left_mi; 237*fb1b10abSAndroid Build Coastguard Worker const int has_above = !!above_mi; 238*fb1b10abSAndroid Build Coastguard Worker const int has_left = !!left_mi; 239*fb1b10abSAndroid Build Coastguard Worker 240*fb1b10abSAndroid Build Coastguard Worker // Note: 241*fb1b10abSAndroid Build Coastguard Worker // The mode info data structure has a one element border above and to the 242*fb1b10abSAndroid Build Coastguard Worker // left of the entries corresponding to real macroblocks. 243*fb1b10abSAndroid Build Coastguard Worker // The prediction flags in these dummy entries are initialized to 0. 244*fb1b10abSAndroid Build Coastguard Worker if (has_above && has_left) { // both edges available 245*fb1b10abSAndroid Build Coastguard Worker const int above_intra = !is_inter_block(above_mi); 246*fb1b10abSAndroid Build Coastguard Worker const int left_intra = !is_inter_block(left_mi); 247*fb1b10abSAndroid Build Coastguard Worker 248*fb1b10abSAndroid Build Coastguard Worker if (above_intra && left_intra) { // intra/intra 249*fb1b10abSAndroid Build Coastguard Worker pred_context = 2; 250*fb1b10abSAndroid Build Coastguard Worker } else if (above_intra || left_intra) { // intra/inter or inter/intra 251*fb1b10abSAndroid Build Coastguard Worker const MODE_INFO *edge_mi = above_intra ? left_mi : above_mi; 252*fb1b10abSAndroid Build Coastguard Worker if (!has_second_ref(edge_mi)) { 253*fb1b10abSAndroid Build Coastguard Worker if (edge_mi->ref_frame[0] == LAST_FRAME) 254*fb1b10abSAndroid Build Coastguard Worker pred_context = 3; 255*fb1b10abSAndroid Build Coastguard Worker else 256*fb1b10abSAndroid Build Coastguard Worker pred_context = 4 * (edge_mi->ref_frame[0] == GOLDEN_FRAME); 257*fb1b10abSAndroid Build Coastguard Worker } else { 258*fb1b10abSAndroid Build Coastguard Worker pred_context = 1 + 2 * (edge_mi->ref_frame[0] == GOLDEN_FRAME || 259*fb1b10abSAndroid Build Coastguard Worker edge_mi->ref_frame[1] == GOLDEN_FRAME); 260*fb1b10abSAndroid Build Coastguard Worker } 261*fb1b10abSAndroid Build Coastguard Worker } else { // inter/inter 262*fb1b10abSAndroid Build Coastguard Worker const int above_has_second = has_second_ref(above_mi); 263*fb1b10abSAndroid Build Coastguard Worker const int left_has_second = has_second_ref(left_mi); 264*fb1b10abSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME above0 = above_mi->ref_frame[0]; 265*fb1b10abSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME above1 = above_mi->ref_frame[1]; 266*fb1b10abSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME left0 = left_mi->ref_frame[0]; 267*fb1b10abSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME left1 = left_mi->ref_frame[1]; 268*fb1b10abSAndroid Build Coastguard Worker 269*fb1b10abSAndroid Build Coastguard Worker if (above_has_second && left_has_second) { 270*fb1b10abSAndroid Build Coastguard Worker if (above0 == left0 && above1 == left1) 271*fb1b10abSAndroid Build Coastguard Worker pred_context = 272*fb1b10abSAndroid Build Coastguard Worker 3 * (above0 == GOLDEN_FRAME || above1 == GOLDEN_FRAME || 273*fb1b10abSAndroid Build Coastguard Worker left0 == GOLDEN_FRAME || left1 == GOLDEN_FRAME); 274*fb1b10abSAndroid Build Coastguard Worker else 275*fb1b10abSAndroid Build Coastguard Worker pred_context = 2; 276*fb1b10abSAndroid Build Coastguard Worker } else if (above_has_second || left_has_second) { 277*fb1b10abSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME rfs = !above_has_second ? above0 : left0; 278*fb1b10abSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME crf1 = above_has_second ? above0 : left0; 279*fb1b10abSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME crf2 = above_has_second ? above1 : left1; 280*fb1b10abSAndroid Build Coastguard Worker 281*fb1b10abSAndroid Build Coastguard Worker if (rfs == GOLDEN_FRAME) 282*fb1b10abSAndroid Build Coastguard Worker pred_context = 3 + (crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME); 283*fb1b10abSAndroid Build Coastguard Worker else if (rfs == ALTREF_FRAME) 284*fb1b10abSAndroid Build Coastguard Worker pred_context = crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME; 285*fb1b10abSAndroid Build Coastguard Worker else 286*fb1b10abSAndroid Build Coastguard Worker pred_context = 1 + 2 * (crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME); 287*fb1b10abSAndroid Build Coastguard Worker } else { 288*fb1b10abSAndroid Build Coastguard Worker if (above0 == LAST_FRAME && left0 == LAST_FRAME) { 289*fb1b10abSAndroid Build Coastguard Worker pred_context = 3; 290*fb1b10abSAndroid Build Coastguard Worker } else if (above0 == LAST_FRAME || left0 == LAST_FRAME) { 291*fb1b10abSAndroid Build Coastguard Worker const MV_REFERENCE_FRAME edge0 = 292*fb1b10abSAndroid Build Coastguard Worker (above0 == LAST_FRAME) ? left0 : above0; 293*fb1b10abSAndroid Build Coastguard Worker pred_context = 4 * (edge0 == GOLDEN_FRAME); 294*fb1b10abSAndroid Build Coastguard Worker } else { 295*fb1b10abSAndroid Build Coastguard Worker pred_context = 296*fb1b10abSAndroid Build Coastguard Worker 2 * (above0 == GOLDEN_FRAME) + 2 * (left0 == GOLDEN_FRAME); 297*fb1b10abSAndroid Build Coastguard Worker } 298*fb1b10abSAndroid Build Coastguard Worker } 299*fb1b10abSAndroid Build Coastguard Worker } 300*fb1b10abSAndroid Build Coastguard Worker } else if (has_above || has_left) { // one edge available 301*fb1b10abSAndroid Build Coastguard Worker const MODE_INFO *edge_mi = has_above ? above_mi : left_mi; 302*fb1b10abSAndroid Build Coastguard Worker 303*fb1b10abSAndroid Build Coastguard Worker if (!is_inter_block(edge_mi) || 304*fb1b10abSAndroid Build Coastguard Worker (edge_mi->ref_frame[0] == LAST_FRAME && !has_second_ref(edge_mi))) 305*fb1b10abSAndroid Build Coastguard Worker pred_context = 2; 306*fb1b10abSAndroid Build Coastguard Worker else if (!has_second_ref(edge_mi)) 307*fb1b10abSAndroid Build Coastguard Worker pred_context = 4 * (edge_mi->ref_frame[0] == GOLDEN_FRAME); 308*fb1b10abSAndroid Build Coastguard Worker else 309*fb1b10abSAndroid Build Coastguard Worker pred_context = 3 * (edge_mi->ref_frame[0] == GOLDEN_FRAME || 310*fb1b10abSAndroid Build Coastguard Worker edge_mi->ref_frame[1] == GOLDEN_FRAME); 311*fb1b10abSAndroid Build Coastguard Worker } else { // no edges available (2) 312*fb1b10abSAndroid Build Coastguard Worker pred_context = 2; 313*fb1b10abSAndroid Build Coastguard Worker } 314*fb1b10abSAndroid Build Coastguard Worker assert(pred_context >= 0 && pred_context < REF_CONTEXTS); 315*fb1b10abSAndroid Build Coastguard Worker return pred_context; 316*fb1b10abSAndroid Build Coastguard Worker } 317