vp9_pred_common.c 12.6 KB
Newer Older
Ronald S. Bultje's avatar
Ronald S. Bultje committed
1

2
/*
Paul Wilkins's avatar
Paul Wilkins committed
3
 *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
4 5 6 7 8 9 10 11
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

12 13
#include <limits.h>

Ronald S. Bultje's avatar
Ronald S. Bultje committed
14
#include "vp9/common/vp9_common.h"
15 16
#include "vp9/common/vp9_pred_common.h"
#include "vp9/common/vp9_seg_common.h"
17
#include "vp9/common/vp9_treecoder.h"
18 19 20 21

// TBD prediction functions for various bitstream signals

// Returns a context number for the given MB prediction signal
22
unsigned char vp9_get_pred_context(const VP9_COMMON *const cm,
Paul Wilkins's avatar
Paul Wilkins committed
23 24
                                   const MACROBLOCKD *const xd,
                                   PRED_ID pred_id) {
John Koleszar's avatar
John Koleszar committed
25
  int pred_context;
26 27 28
  const MODE_INFO *const mi = xd->mode_info_context;
  const MODE_INFO *const above_mi = mi - cm->mode_info_stride;
  const MODE_INFO *const left_mi = mi - 1;
John Koleszar's avatar
John Koleszar committed
29 30 31 32 33
  // Note:
  // The mode info data structure has a one element border above and to the
  // left of the entries correpsonding to real macroblocks.
  // The prediction flags in these dummy entries are initialised to 0.
  switch (pred_id) {
34
    case PRED_SEG_ID:
35
      pred_context = above_mi->mbmi.seg_id_predicted;
36
      if (xd->left_available)
37
        pred_context += left_mi->mbmi.seg_id_predicted;
John Koleszar's avatar
John Koleszar committed
38
      break;
39 40

    case PRED_REF:
41
      pred_context = above_mi->mbmi.ref_predicted;
42
      if (xd->left_available)
43
        pred_context += left_mi->mbmi.ref_predicted;
John Koleszar's avatar
John Koleszar committed
44
      break;
45

46
    case PRED_COMP:
47
      if (mi->mbmi.ref_frame == LAST_FRAME)
John Koleszar's avatar
John Koleszar committed
48 49 50 51
        pred_context = 0;
      else
        pred_context = 1;
      break;
52

53
    case PRED_MBSKIP:
54
      pred_context = above_mi->mbmi.mb_skip_coeff;
55
      if (xd->left_available)
56
        pred_context += left_mi->mbmi.mb_skip_coeff;
John Koleszar's avatar
John Koleszar committed
57
      break;
58

59 60 61 62 63 64 65 66 67 68
    case PRED_SWITCHABLE_INTERP: {
      // left
      const int left_in_image = xd->left_available && left_mi->mbmi.mb_in_image;
      const int left_mv_pred = left_mi->mbmi.mode >= NEARESTMV &&
                               left_mi->mbmi.mode <= SPLITMV;
      const int left_interp = left_in_image && left_mv_pred ?
                    vp9_switchable_interp_map[left_mi->mbmi.interp_filter] :
                    VP9_SWITCHABLE_FILTERS;

      // above
69
      const int above_in_image = xd->up_available && above_mi->mbmi.mb_in_image;
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
      const int above_mv_pred = above_mi->mbmi.mode >= NEARESTMV &&
                                above_mi->mbmi.mode <= SPLITMV;
      const int above_interp = above_in_image && above_mv_pred ?
                    vp9_switchable_interp_map[above_mi->mbmi.interp_filter] :
                    VP9_SWITCHABLE_FILTERS;

      assert(left_interp != -1);
      assert(above_interp != -1);

      if (left_interp == above_interp)
        pred_context = left_interp;
      else if (left_interp == VP9_SWITCHABLE_FILTERS &&
               above_interp != VP9_SWITCHABLE_FILTERS)
         pred_context = above_interp;
      else if (left_interp != VP9_SWITCHABLE_FILTERS &&
               above_interp == VP9_SWITCHABLE_FILTERS)
        pred_context = left_interp;
      else
        pred_context = VP9_SWITCHABLE_FILTERS;

90
      break;
91
    }
92

93
    default:
Dmitry Kovalev's avatar
Dmitry Kovalev committed
94
      pred_context = 0;  // *** add error trap code.
John Koleszar's avatar
John Koleszar committed
95 96
      break;
  }
97

John Koleszar's avatar
John Koleszar committed
98
  return pred_context;
99 100 101 102
}

// This function returns a context probability for coding a given
// prediction signal
103
vp9_prob vp9_get_pred_prob(const VP9_COMMON *const cm,
Paul Wilkins's avatar
Paul Wilkins committed
104 105
                          const MACROBLOCKD *const xd,
                          PRED_ID pred_id) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
106
  const int pred_context = vp9_get_pred_context(cm, xd, pred_id);
John Koleszar's avatar
John Koleszar committed
107 108

  switch (pred_id) {
109
    case PRED_SEG_ID:
Dmitry Kovalev's avatar
Dmitry Kovalev committed
110
      return cm->segment_pred_probs[pred_context];
111
    case PRED_REF:
Dmitry Kovalev's avatar
Dmitry Kovalev committed
112
      return cm->ref_pred_probs[pred_context];
113
    case PRED_COMP:
John Koleszar's avatar
John Koleszar committed
114 115 116
      // In keeping with convention elsewhre the probability returned is
      // the probability of a "0" outcome which in this case means the
      // probability of comp pred off.
Dmitry Kovalev's avatar
Dmitry Kovalev committed
117
      return cm->prob_comppred[pred_context];
118
    case PRED_MBSKIP:
Dmitry Kovalev's avatar
Dmitry Kovalev committed
119
      return cm->mbskip_pred_probs[pred_context];
120
    default:
Dmitry Kovalev's avatar
Dmitry Kovalev committed
121
      return 128;  // *** add error trap code.
John Koleszar's avatar
John Koleszar committed
122
  }
123 124
}

125 126
// This function returns a context probability ptr for coding a given
// prediction signal
127
const vp9_prob *vp9_get_pred_probs(const VP9_COMMON *const cm,
Paul Wilkins's avatar
Paul Wilkins committed
128 129
                                   const MACROBLOCKD *const xd,
                                   PRED_ID pred_id) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
130
  const int pred_context = vp9_get_pred_context(cm, xd, pred_id);
131 132 133

  switch (pred_id) {
    case PRED_SEG_ID:
Dmitry Kovalev's avatar
Dmitry Kovalev committed
134
      return &cm->segment_pred_probs[pred_context];
135
    case PRED_REF:
Dmitry Kovalev's avatar
Dmitry Kovalev committed
136
      return &cm->ref_pred_probs[pred_context];
137 138 139 140
    case PRED_COMP:
      // In keeping with convention elsewhre the probability returned is
      // the probability of a "0" outcome which in this case means the
      // probability of comp pred off.
Dmitry Kovalev's avatar
Dmitry Kovalev committed
141
      return &cm->prob_comppred[pred_context];
142
    case PRED_MBSKIP:
Dmitry Kovalev's avatar
Dmitry Kovalev committed
143
      return &cm->mbskip_pred_probs[pred_context];
144
    case PRED_SWITCHABLE_INTERP:
Dmitry Kovalev's avatar
Dmitry Kovalev committed
145
      return &cm->fc.switchable_interp_prob[pred_context][0];
146
    default:
Dmitry Kovalev's avatar
Dmitry Kovalev committed
147
      return NULL;  // *** add error trap code.
148 149 150
  }
}

151 152
// This function returns the status of the given prediction signal.
// I.e. is the predicted value for the given signal correct.
Paul Wilkins's avatar
Paul Wilkins committed
153 154
unsigned char vp9_get_pred_flag(const MACROBLOCKD *const xd,
                                PRED_ID pred_id) {
John Koleszar's avatar
John Koleszar committed
155
  switch (pred_id) {
156
    case PRED_SEG_ID:
Dmitry Kovalev's avatar
Dmitry Kovalev committed
157
      return xd->mode_info_context->mbmi.seg_id_predicted;
158
    case PRED_REF:
Dmitry Kovalev's avatar
Dmitry Kovalev committed
159
      return  xd->mode_info_context->mbmi.ref_predicted;
160
    case PRED_MBSKIP:
Dmitry Kovalev's avatar
Dmitry Kovalev committed
161
      return xd->mode_info_context->mbmi.mb_skip_coeff;
162
    default:
Dmitry Kovalev's avatar
Dmitry Kovalev committed
163
      return 0;  // *** add error trap code.
John Koleszar's avatar
John Koleszar committed
164
  }
165 166 167 168
}

// This function sets the status of the given prediction signal.
// I.e. is the predicted value for the given signal correct.
Paul Wilkins's avatar
Paul Wilkins committed
169 170 171
void vp9_set_pred_flag(MACROBLOCKD *const xd,
                       PRED_ID pred_id,
                       unsigned char pred_flag) {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
172
  const int mis = xd->mode_info_stride;
173 174 175 176 177 178 179 180
  BLOCK_SIZE_TYPE bsize = xd->mode_info_context->mbmi.sb_type;
  const int bh = 1 << mb_height_log2(bsize);
  const int bw = 1 << mb_width_log2(bsize);
#define sub(a, b) (b) < 0 ? (a) + (b) : (a)
  const int x_mbs = sub(bw, xd->mb_to_right_edge >> 7);
  const int y_mbs = sub(bh, xd->mb_to_bottom_edge >> 7);
#undef sub
  int x, y;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
181

John Koleszar's avatar
John Koleszar committed
182
  switch (pred_id) {
183
    case PRED_SEG_ID:
184 185 186 187
      for (y = 0; y < y_mbs; y++) {
        for (x = 0; x < x_mbs; x++) {
          xd->mode_info_context[y * mis + x].mbmi.seg_id_predicted =
              pred_flag;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
188
        }
Ronald S. Bultje's avatar
Ronald S. Bultje committed
189
      }
John Koleszar's avatar
John Koleszar committed
190
      break;
191 192

    case PRED_REF:
193 194 195
      for (y = 0; y < y_mbs; y++) {
        for (x = 0; x < x_mbs; x++) {
          xd->mode_info_context[y * mis + x].mbmi.ref_predicted = pred_flag;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
196
        }
Ronald S. Bultje's avatar
Ronald S. Bultje committed
197
      }
John Koleszar's avatar
John Koleszar committed
198
      break;
199

200
    case PRED_MBSKIP:
201 202 203
      for (y = 0; y < y_mbs; y++) {
        for (x = 0; x < x_mbs; x++) {
          xd->mode_info_context[y * mis + x].mbmi.mb_skip_coeff = pred_flag;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
204 205
        }
      }
John Koleszar's avatar
John Koleszar committed
206
      break;
207

208
    default:
Dmitry Kovalev's avatar
Dmitry Kovalev committed
209
      // *** add error trap code.
John Koleszar's avatar
John Koleszar committed
210 211
      break;
  }
212 213 214 215 216 217 218
}


// The following contain the guts of the prediction code used to
// peredict various bitstream signals.

// Macroblock segment id prediction function
219 220 221
int vp9_get_pred_mb_segid(VP9_COMMON *cm, BLOCK_SIZE_TYPE sb_type,
                          int mb_row, int mb_col) {
  const int mb_index = mb_row * cm->mb_cols + mb_col;
222
  if (sb_type > BLOCK_SIZE_MB16X16) {
223 224 225 226 227
    const int bw = 1 << mb_width_log2(sb_type);
    const int bh = 1 << mb_height_log2(sb_type);
    const int ymbs = MIN(cm->mb_rows - mb_row, bh);
    const int xmbs = MIN(cm->mb_cols - mb_col, bw);
    int segment_id = INT_MAX;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
228 229
    int x, y;

230 231 232 233
    for (y = 0; y < ymbs; y++) {
      for (x = 0; x < xmbs; x++) {
        const int index = mb_index + (y * cm->mb_cols + x);
        segment_id = MIN(segment_id, cm->last_frame_seg_map[index]);
Ronald S. Bultje's avatar
Ronald S. Bultje committed
234
      }
Ronald S. Bultje's avatar
Ronald S. Bultje committed
235
    }
236 237 238
    return segment_id;
  } else {
    return cm->last_frame_seg_map[mb_index];
Ronald S. Bultje's avatar
Ronald S. Bultje committed
239
  }
240 241
}

242
MV_REFERENCE_FRAME vp9_get_pred_ref(const VP9_COMMON *const cm,
Paul Wilkins's avatar
Paul Wilkins committed
243
                                    const MACROBLOCKD *const xd) {
John Koleszar's avatar
John Koleszar committed
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
  MODE_INFO *m = xd->mode_info_context;

  MV_REFERENCE_FRAME left;
  MV_REFERENCE_FRAME above;
  MV_REFERENCE_FRAME above_left;
  MV_REFERENCE_FRAME pred_ref = LAST_FRAME;

  int segment_id = xd->mode_info_context->mbmi.segment_id;
  int i;

  unsigned char frame_allowed[MAX_REF_FRAMES] = {1, 1, 1, 1};
  unsigned char ref_score[MAX_REF_FRAMES];
  unsigned char best_score = 0;
  unsigned char left_in_image;
  unsigned char above_in_image;
  unsigned char above_left_in_image;

  // Is segment coding ennabled
Dmitry Kovalev's avatar
Dmitry Kovalev committed
262
  int seg_ref_active = vp9_segfeature_active(xd, segment_id, SEG_LVL_REF_FRAME);
John Koleszar's avatar
John Koleszar committed
263 264 265 266 267 268 269

  // Special case treatment if segment coding is enabled.
  // Dont allow prediction of a reference frame that the segment
  // does not allow
  if (seg_ref_active) {
    for (i = 0; i < MAX_REF_FRAMES; i++) {
      frame_allowed[i] =
270
        vp9_check_segref(xd, segment_id, i);
John Koleszar's avatar
John Koleszar committed
271 272 273

      // Score set to 0 if ref frame not allowed
      ref_score[i] = cm->ref_scores[i] * frame_allowed[i];
274
    }
John Koleszar's avatar
John Koleszar committed
275 276 277 278 279 280 281 282 283
  } else
    vpx_memcpy(ref_score, cm->ref_scores, sizeof(ref_score));

  // Reference frames used by neighbours
  left = (m - 1)->mbmi.ref_frame;
  above = (m - cm->mode_info_stride)->mbmi.ref_frame;
  above_left = (m - 1 - cm->mode_info_stride)->mbmi.ref_frame;

  // Are neighbours in image
284
  left_in_image = (m - 1)->mbmi.mb_in_image && xd->left_available;
John Koleszar's avatar
John Koleszar committed
285
  above_in_image = (m - cm->mode_info_stride)->mbmi.mb_in_image;
286 287
  above_left_in_image = (m - 1 - cm->mode_info_stride)->mbmi.mb_in_image &&
                        xd->left_available;
John Koleszar's avatar
John Koleszar committed
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305

  // Adjust scores for candidate reference frames based on neigbours
  if (frame_allowed[left] && left_in_image) {
    ref_score[left] += 16;
    if (above_left_in_image && (left == above_left))
      ref_score[left] += 4;
  }
  if (frame_allowed[above] && above_in_image) {
    ref_score[above] += 16;
    if (above_left_in_image && (above == above_left))
      ref_score[above] += 4;
  }

  // Now choose the candidate with the highest score
  for (i = 0; i < MAX_REF_FRAMES; i++) {
    if (ref_score[i] > best_score) {
      pred_ref = i;
      best_score = ref_score[i];
Paul Wilkins's avatar
Paul Wilkins committed
306
    }
John Koleszar's avatar
John Koleszar committed
307
  }
308

John Koleszar's avatar
John Koleszar committed
309
  return pred_ref;
310 311 312 313
}

// Functions to computes a set of modified reference frame probabilities
// to use when the prediction of the reference frame value fails
314
void vp9_calc_ref_probs(int *count, vp9_prob *probs) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
315
  int tot_count = count[0] + count[1] + count[2] + count[3];
316
  probs[0] = get_prob(count[0], tot_count);
John Koleszar's avatar
John Koleszar committed
317 318

  tot_count -= count[0];
319
  probs[1] = get_prob(count[1], tot_count);
John Koleszar's avatar
John Koleszar committed
320 321

  tot_count -= count[1];
322
  probs[2] = get_prob(count[2], tot_count);
323 324
}

Paul Wilkins's avatar
Paul Wilkins committed
325 326 327 328
// Computes a set of modified conditional probabilities for the reference frame
// Values willbe set to 0 for reference frame options that are not possible
// because wither they were predicted and prediction has failed or because
// they are not allowed for a given segment.
329
void vp9_compute_mod_refprobs(VP9_COMMON *const cm) {
John Koleszar's avatar
John Koleszar committed
330
  int norm_cnt[MAX_REF_FRAMES];
Dmitry Kovalev's avatar
Dmitry Kovalev committed
331 332 333 334 335 336
  const int intra_count = cm->prob_intra_coded;
  const int inter_count = (255 - intra_count);
  const int last_count = (inter_count * cm->prob_last_coded) / 255;
  const int gfarf_count = inter_count - last_count;
  const int gf_count = (gfarf_count * cm->prob_gf_coded) / 255;
  const int arf_count = gfarf_count - gf_count;
John Koleszar's avatar
John Koleszar committed
337 338 339 340 341 342 343

  // Work out modified reference frame probabilities to use where prediction
  // of the reference frame fails
  norm_cnt[0] = 0;
  norm_cnt[1] = last_count;
  norm_cnt[2] = gf_count;
  norm_cnt[3] = arf_count;
Paul Wilkins's avatar
Paul Wilkins committed
344
  vp9_calc_ref_probs(norm_cnt, cm->mod_refprobs[INTRA_FRAME]);
John Koleszar's avatar
John Koleszar committed
345 346 347 348 349 350
  cm->mod_refprobs[INTRA_FRAME][0] = 0;    // This branch implicit

  norm_cnt[0] = intra_count;
  norm_cnt[1] = 0;
  norm_cnt[2] = gf_count;
  norm_cnt[3] = arf_count;
Paul Wilkins's avatar
Paul Wilkins committed
351
  vp9_calc_ref_probs(norm_cnt, cm->mod_refprobs[LAST_FRAME]);
John Koleszar's avatar
John Koleszar committed
352 353 354 355 356 357
  cm->mod_refprobs[LAST_FRAME][1] = 0;    // This branch implicit

  norm_cnt[0] = intra_count;
  norm_cnt[1] = last_count;
  norm_cnt[2] = 0;
  norm_cnt[3] = arf_count;
Paul Wilkins's avatar
Paul Wilkins committed
358
  vp9_calc_ref_probs(norm_cnt, cm->mod_refprobs[GOLDEN_FRAME]);
John Koleszar's avatar
John Koleszar committed
359 360 361 362 363 364
  cm->mod_refprobs[GOLDEN_FRAME][2] = 0;  // This branch implicit

  norm_cnt[0] = intra_count;
  norm_cnt[1] = last_count;
  norm_cnt[2] = gf_count;
  norm_cnt[3] = 0;
Paul Wilkins's avatar
Paul Wilkins committed
365
  vp9_calc_ref_probs(norm_cnt, cm->mod_refprobs[ALTREF_FRAME]);
John Koleszar's avatar
John Koleszar committed
366 367 368 369 370 371 372 373 374
  cm->mod_refprobs[ALTREF_FRAME][2] = 0;  // This branch implicit

  // Score the reference frames based on overal frequency.
  // These scores contribute to the prediction choices.
  // Max score 17 min 1
  cm->ref_scores[INTRA_FRAME] = 1 + (intra_count * 16 / 255);
  cm->ref_scores[LAST_FRAME] = 1 + (last_count * 16 / 255);
  cm->ref_scores[GOLDEN_FRAME] = 1 + (gf_count * 16 / 255);
  cm->ref_scores[ALTREF_FRAME] = 1 + (arf_count * 16 / 255);
375
}