vp9_pred_common.c 14.7 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 "vp9/common/vp9_pred_common.h"
#include "vp9/common/vp9_seg_common.h"
14
15
16
17

// TBD prediction functions for various bitstream signals

// Returns a context number for the given MB prediction signal
18
unsigned char vp9_get_pred_context(const VP9_COMMON *const cm,
Paul Wilkins's avatar
Paul Wilkins committed
19
20
                                   const MACROBLOCKD *const xd,
                                   PRED_ID pred_id) {
John Koleszar's avatar
John Koleszar committed
21
22
23
24
25
26
27
28
  int pred_context;
  MODE_INFO *m = xd->mode_info_context;

  // 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) {
29
    case PRED_SEG_ID:
John Koleszar's avatar
John Koleszar committed
30
31
32
      pred_context = (m - 1)->mbmi.seg_id_predicted +
                     (m - cm->mode_info_stride)->mbmi.seg_id_predicted;
      break;
33
34
35


    case PRED_REF:
John Koleszar's avatar
John Koleszar committed
36
37
38
      pred_context = (m - 1)->mbmi.ref_predicted +
                     (m - cm->mode_info_stride)->mbmi.ref_predicted;
      break;
39

40
    case PRED_COMP:
John Koleszar's avatar
John Koleszar committed
41
42
      // Context based on use of comp pred flag by neighbours
      // pred_context =
43
44
      //   ((m - 1)->mbmi.second_ref_frame > INTRA_FRAME) +
      //    ((m - cm->mode_info_stride)->mbmi.second_ref_frame > INTRA_FRAME);
John Koleszar's avatar
John Koleszar committed
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

      // Context based on mode and reference frame
      // if ( m->mbmi.ref_frame == LAST_FRAME )
      //    pred_context = 0 + (m->mbmi.mode != ZEROMV);
      // else if ( m->mbmi.ref_frame == GOLDEN_FRAME )
      //    pred_context = 2 + (m->mbmi.mode != ZEROMV);
      // else
      //    pred_context = 4 + (m->mbmi.mode != ZEROMV);

      if (m->mbmi.ref_frame == LAST_FRAME)
        pred_context = 0;
      else
        pred_context = 1;

      break;
60

61
    case PRED_MBSKIP:
John Koleszar's avatar
John Koleszar committed
62
63
64
      pred_context = (m - 1)->mbmi.mb_skip_coeff +
                     (m - cm->mode_info_stride)->mbmi.mb_skip_coeff;
      break;
65

66
67
68
69
70
71
72
73
    case PRED_SWITCHABLE_INTERP:
      {
        int left_in_image = (m - 1)->mbmi.mb_in_image;
        int above_in_image = (m - cm->mode_info_stride)->mbmi.mb_in_image;
        int left_mode = (m - 1)->mbmi.mode;
        int above_mode = (m - cm->mode_info_stride)->mbmi.mode;
        int left_interp, above_interp;
        if (left_in_image && left_mode >= NEARESTMV && left_mode <= SPLITMV)
74
          left_interp = vp9_switchable_interp_map[(m - 1)->mbmi.interp_filter];
75
        else
76
          left_interp = VP9_SWITCHABLE_FILTERS;
77
        assert(left_interp != -1);
78
        if (above_in_image && above_mode >= NEARESTMV && above_mode <= SPLITMV)
79
          above_interp = vp9_switchable_interp_map[
80
81
              (m - cm->mode_info_stride)->mbmi.interp_filter];
        else
82
          above_interp = VP9_SWITCHABLE_FILTERS;
83
        assert(above_interp != -1);
84
85
86

        if (left_interp == above_interp)
          pred_context = left_interp;
87
88
        else if (left_interp == VP9_SWITCHABLE_FILTERS &&
                 above_interp != VP9_SWITCHABLE_FILTERS)
89
          pred_context = above_interp;
90
91
        else if (left_interp != VP9_SWITCHABLE_FILTERS &&
                 above_interp == VP9_SWITCHABLE_FILTERS)
92
93
          pred_context = left_interp;
        else
94
          pred_context = VP9_SWITCHABLE_FILTERS;
95
96
97
      }
      break;

98
    default:
John Koleszar's avatar
John Koleszar committed
99
100
101
102
      // TODO *** add error trap code.
      pred_context = 0;
      break;
  }
103

John Koleszar's avatar
John Koleszar committed
104
  return pred_context;
105
106
107
108
}

// This function returns a context probability for coding a given
// prediction signal
109
vp9_prob vp9_get_pred_prob(const VP9_COMMON *const cm,
Paul Wilkins's avatar
Paul Wilkins committed
110
111
                          const MACROBLOCKD *const xd,
                          PRED_ID pred_id) {
112
  vp9_prob pred_probability;
John Koleszar's avatar
John Koleszar committed
113
114
115
  int pred_context;

  // Get the appropriate prediction context
Paul Wilkins's avatar
Paul Wilkins committed
116
  pred_context = vp9_get_pred_context(cm, xd, pred_id);
John Koleszar's avatar
John Koleszar committed
117
118

  switch (pred_id) {
119
    case PRED_SEG_ID:
John Koleszar's avatar
John Koleszar committed
120
121
      pred_probability = cm->segment_pred_probs[pred_context];
      break;
122
123

    case PRED_REF:
John Koleszar's avatar
John Koleszar committed
124
125
      pred_probability = cm->ref_pred_probs[pred_context];
      break;
126

127
    case PRED_COMP:
John Koleszar's avatar
John Koleszar committed
128
129
130
131
132
      // 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.
      pred_probability = cm->prob_comppred[pred_context];
      break;
133

134
    case PRED_MBSKIP:
John Koleszar's avatar
John Koleszar committed
135
136
      pred_probability = cm->mbskip_pred_probs[pred_context];
      break;
137

138
    default:
John Koleszar's avatar
John Koleszar committed
139
140
141
142
      // TODO *** add error trap code.
      pred_probability = 128;
      break;
  }
143

John Koleszar's avatar
John Koleszar committed
144
  return pred_probability;
145
146
}

147
148
// This function returns a context probability ptr for coding a given
// prediction signal
149
const vp9_prob *vp9_get_pred_probs(const VP9_COMMON *const cm,
Paul Wilkins's avatar
Paul Wilkins committed
150
151
                                   const MACROBLOCKD *const xd,
                                   PRED_ID pred_id) {
152
  const vp9_prob *pred_probability;
153
154
155
  int pred_context;

  // Get the appropriate prediction context
Paul Wilkins's avatar
Paul Wilkins committed
156
  pred_context = vp9_get_pred_context(cm, xd, pred_id);
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180

  switch (pred_id) {
    case PRED_SEG_ID:
      pred_probability = &cm->segment_pred_probs[pred_context];
      break;

    case PRED_REF:
      pred_probability = &cm->ref_pred_probs[pred_context];
      break;

    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.
      pred_probability = &cm->prob_comppred[pred_context];
      break;

    case PRED_MBSKIP:
      pred_probability = &cm->mbskip_pred_probs[pred_context];
      break;

    case PRED_SWITCHABLE_INTERP:
      pred_probability = &cm->fc.switchable_interp_prob[pred_context][0];
      break;
181

182
183
184
185
186
187
188
189
190
    default:
      // TODO *** add error trap code.
      pred_probability = NULL;
      break;
  }

  return pred_probability;
}

191
192
// 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
193
194
unsigned char vp9_get_pred_flag(const MACROBLOCKD *const xd,
                                PRED_ID pred_id) {
John Koleszar's avatar
John Koleszar committed
195
  unsigned char pred_flag = 0;
196

John Koleszar's avatar
John Koleszar committed
197
  switch (pred_id) {
198
    case PRED_SEG_ID:
John Koleszar's avatar
John Koleszar committed
199
200
      pred_flag = xd->mode_info_context->mbmi.seg_id_predicted;
      break;
201
202

    case PRED_REF:
John Koleszar's avatar
John Koleszar committed
203
204
      pred_flag = xd->mode_info_context->mbmi.ref_predicted;
      break;
205

206
    case PRED_MBSKIP:
John Koleszar's avatar
John Koleszar committed
207
208
      pred_flag = xd->mode_info_context->mbmi.mb_skip_coeff;
      break;
209

210
    default:
John Koleszar's avatar
John Koleszar committed
211
212
213
214
      // TODO *** add error trap code.
      pred_flag = 0;
      break;
  }
215

John Koleszar's avatar
John Koleszar committed
216
  return pred_flag;
217
218
219
220
}

// 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
221
222
223
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
224
225
226
227
#if CONFIG_SUPERBLOCKS
  const int mis = xd->mode_info_stride;
#endif

John Koleszar's avatar
John Koleszar committed
228
  switch (pred_id) {
229
    case PRED_SEG_ID:
John Koleszar's avatar
John Koleszar committed
230
      xd->mode_info_context->mbmi.seg_id_predicted = pred_flag;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
231
232
#if CONFIG_SUPERBLOCKS
      if (xd->mode_info_context->mbmi.encoded_as_sb) {
233
        if (xd->mb_to_right_edge >= 0)
Ronald S. Bultje's avatar
Ronald S. Bultje committed
234
          xd->mode_info_context[1].mbmi.seg_id_predicted = pred_flag;
235
        if (xd->mb_to_bottom_edge >= 0) {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
236
          xd->mode_info_context[mis].mbmi.seg_id_predicted = pred_flag;
237
          if (xd->mb_to_right_edge >= 0)
Ronald S. Bultje's avatar
Ronald S. Bultje committed
238
239
            xd->mode_info_context[mis + 1].mbmi.seg_id_predicted = pred_flag;
        }
Ronald S. Bultje's avatar
Ronald S. Bultje committed
240
241
      }
#endif
John Koleszar's avatar
John Koleszar committed
242
      break;
243
244

    case PRED_REF:
John Koleszar's avatar
John Koleszar committed
245
      xd->mode_info_context->mbmi.ref_predicted = pred_flag;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
246
247
#if CONFIG_SUPERBLOCKS
      if (xd->mode_info_context->mbmi.encoded_as_sb) {
248
        if (xd->mb_to_right_edge >= 0)
Ronald S. Bultje's avatar
Ronald S. Bultje committed
249
          xd->mode_info_context[1].mbmi.ref_predicted = pred_flag;
250
        if (xd->mb_to_bottom_edge >= 0) {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
251
          xd->mode_info_context[mis].mbmi.ref_predicted = pred_flag;
252
          if (xd->mb_to_right_edge >= 0)
Ronald S. Bultje's avatar
Ronald S. Bultje committed
253
254
            xd->mode_info_context[mis + 1].mbmi.ref_predicted = pred_flag;
        }
Ronald S. Bultje's avatar
Ronald S. Bultje committed
255
256
      }
#endif
John Koleszar's avatar
John Koleszar committed
257
      break;
258

259
    case PRED_MBSKIP:
John Koleszar's avatar
John Koleszar committed
260
      xd->mode_info_context->mbmi.mb_skip_coeff = pred_flag;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
261
262
#if CONFIG_SUPERBLOCKS
      if (xd->mode_info_context->mbmi.encoded_as_sb) {
263
        if (xd->mb_to_right_edge >= 0)
Ronald S. Bultje's avatar
Ronald S. Bultje committed
264
          xd->mode_info_context[1].mbmi.mb_skip_coeff = pred_flag;
265
        if (xd->mb_to_bottom_edge >= 0) {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
266
          xd->mode_info_context[mis].mbmi.mb_skip_coeff = pred_flag;
267
          if (xd->mb_to_right_edge >= 0)
Ronald S. Bultje's avatar
Ronald S. Bultje committed
268
269
270
271
            xd->mode_info_context[mis + 1].mbmi.mb_skip_coeff = pred_flag;
        }
      }
#endif
John Koleszar's avatar
John Koleszar committed
272
      break;
273

274
    default:
John Koleszar's avatar
John Koleszar committed
275
276
277
      // TODO *** add error trap code.
      break;
  }
278
279
280
281
282
283
284
}


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

// Macroblock segment id prediction function
285
unsigned char vp9_get_pred_mb_segid(const VP9_COMMON *const cm,
Ronald S. Bultje's avatar
Ronald S. Bultje committed
286
                                    const MACROBLOCKD *const xd, int MbIndex) {
John Koleszar's avatar
John Koleszar committed
287
288
  // Currently the prediction for the macroblock segment ID is
  // the value stored for this macroblock in the previous frame.
Ronald S. Bultje's avatar
Ronald S. Bultje committed
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
#if CONFIG_SUPERBLOCKS
  if (!xd->mode_info_context->mbmi.encoded_as_sb) {
#endif
    return cm->last_frame_seg_map[MbIndex];
#if CONFIG_SUPERBLOCKS
  } else {
    int seg_id = cm->last_frame_seg_map[MbIndex];
    int mb_col = MbIndex % cm->mb_cols;
    int mb_row = MbIndex / cm->mb_cols;
    if (mb_col + 1 < cm->mb_cols)
      seg_id = seg_id && cm->last_frame_seg_map[MbIndex + 1];
    if (mb_row + 1 < cm->mb_rows) {
      seg_id = seg_id && cm->last_frame_seg_map[MbIndex + cm->mb_cols];
      if (mb_col + 1 < cm->mb_cols)
        seg_id = seg_id && cm->last_frame_seg_map[MbIndex + cm->mb_cols + 1];
    }
    return seg_id;
  }
#endif
308
309
}

310
MV_REFERENCE_FRAME vp9_get_pred_ref(const VP9_COMMON *const cm,
Paul Wilkins's avatar
Paul Wilkins committed
311
                                    const MACROBLOCKD *const xd) {
John Koleszar's avatar
John Koleszar committed
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
  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 seg_ref_active;
  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
331
  seg_ref_active = vp9_segfeature_active(xd, segment_id, SEG_LVL_REF_FRAME);
John Koleszar's avatar
John Koleszar committed
332
333
334
335
336
337
338

  // 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] =
339
        vp9_check_segref(xd, segment_id, i);
John Koleszar's avatar
John Koleszar committed
340
341
342

      // Score set to 0 if ref frame not allowed
      ref_score[i] = cm->ref_scores[i] * frame_allowed[i];
343
    }
John Koleszar's avatar
John Koleszar committed
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
  } 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
  left_in_image = (m - 1)->mbmi.mb_in_image;
  above_in_image = (m - cm->mode_info_stride)->mbmi.mb_in_image;
  above_left_in_image = (m - 1 - cm->mode_info_stride)->mbmi.mb_in_image;

  // 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
374
    }
John Koleszar's avatar
John Koleszar committed
375
  }
376

John Koleszar's avatar
John Koleszar committed
377
  return pred_ref;
378
379
380
381
}

// Functions to computes a set of modified reference frame probabilities
// to use when the prediction of the reference frame value fails
382
void vp9_calc_ref_probs(int *count, vp9_prob *probs) {
John Koleszar's avatar
John Koleszar committed
383
384
385
386
  int tot_count;

  tot_count = count[0] + count[1] + count[2] + count[3];
  if (tot_count) {
387
    probs[0] = (vp9_prob)((count[0] * 255 + (tot_count >> 1)) / tot_count);
John Koleszar's avatar
John Koleszar committed
388
389
390
391
392
393
    probs[0] += !probs[0];
  } else
    probs[0] = 128;

  tot_count -= count[0];
  if (tot_count) {
394
    probs[1] = (vp9_prob)((count[1] * 255 + (tot_count >> 1)) / tot_count);
John Koleszar's avatar
John Koleszar committed
395
396
397
398
399
400
    probs[1] += !probs[1];
  } else
    probs[1] = 128;

  tot_count -= count[1];
  if (tot_count) {
401
    probs[2] = (vp9_prob)((count[2] * 255 + (tot_count >> 1)) / tot_count);
John Koleszar's avatar
John Koleszar committed
402
403
404
    probs[2] += !probs[2];
  } else
    probs[2] = 128;
405
406
407

}

Paul Wilkins's avatar
Paul Wilkins committed
408
409
410
411
// 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.
412
void vp9_compute_mod_refprobs(VP9_COMMON *const cm) {
John Koleszar's avatar
John Koleszar committed
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
  int norm_cnt[MAX_REF_FRAMES];
  int intra_count;
  int inter_count;
  int last_count;
  int gfarf_count;
  int gf_count;
  int arf_count;

  intra_count = cm->prob_intra_coded;
  inter_count = (255 - intra_count);
  last_count = (inter_count * cm->prob_last_coded) / 255;
  gfarf_count = inter_count - last_count;
  gf_count = (gfarf_count * cm->prob_gf_coded) / 255;
  arf_count = gfarf_count - gf_count;

  // 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
434
  vp9_calc_ref_probs(norm_cnt, cm->mod_refprobs[INTRA_FRAME]);
John Koleszar's avatar
John Koleszar committed
435
436
437
438
439
440
  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
441
  vp9_calc_ref_probs(norm_cnt, cm->mod_refprobs[LAST_FRAME]);
John Koleszar's avatar
John Koleszar committed
442
443
444
445
446
447
  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
448
  vp9_calc_ref_probs(norm_cnt, cm->mod_refprobs[GOLDEN_FRAME]);
John Koleszar's avatar
John Koleszar committed
449
450
451
452
453
454
  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
455
  vp9_calc_ref_probs(norm_cnt, cm->mod_refprobs[ALTREF_FRAME]);
John Koleszar's avatar
John Koleszar committed
456
457
458
459
460
461
462
463
464
  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);
465
}