vp9_pred_common.c 14.4 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
#include "vp9/common/vp9_treecoder.h"
15
16
17
18

// TBD prediction functions for various bitstream signals

// Returns a context number for the given MB prediction signal
19
unsigned char vp9_get_pred_context(const VP9_COMMON *const cm,
Paul Wilkins's avatar
Paul Wilkins committed
20
21
                                   const MACROBLOCKD *const xd,
                                   PRED_ID pred_id) {
John Koleszar's avatar
John Koleszar committed
22
23
24
25
26
27
28
29
  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) {
30
    case PRED_SEG_ID:
John Koleszar's avatar
John Koleszar committed
31
32
33
      pred_context = (m - 1)->mbmi.seg_id_predicted +
                     (m - cm->mode_info_stride)->mbmi.seg_id_predicted;
      break;
34
35
36


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

41
    case PRED_COMP:
John Koleszar's avatar
John Koleszar committed
42
43
      // Context based on use of comp pred flag by neighbours
      // pred_context =
44
45
      //   ((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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

      // 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;
61

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

67
68
69
70
71
72
73
74
    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)
75
          left_interp = vp9_switchable_interp_map[(m - 1)->mbmi.interp_filter];
76
        else
77
          left_interp = VP9_SWITCHABLE_FILTERS;
78
        assert(left_interp != -1);
79
        if (above_in_image && above_mode >= NEARESTMV && above_mode <= SPLITMV)
80
          above_interp = vp9_switchable_interp_map[
81
82
              (m - cm->mode_info_stride)->mbmi.interp_filter];
        else
83
          above_interp = VP9_SWITCHABLE_FILTERS;
84
        assert(above_interp != -1);
85
86
87

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

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

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

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

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

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

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

128
    case PRED_COMP:
John Koleszar's avatar
John Koleszar committed
129
130
131
132
133
      // 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;
134

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

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

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

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

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

  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;
182

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

  return pred_probability;
}

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

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

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

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

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

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

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

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

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

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

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


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

// Macroblock segment id prediction function
286
unsigned char vp9_get_pred_mb_segid(const VP9_COMMON *const cm,
Ronald S. Bultje's avatar
Ronald S. Bultje committed
287
                                    const MACROBLOCKD *const xd, int MbIndex) {
John Koleszar's avatar
John Koleszar committed
288
289
  // 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
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
#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
309
310
}

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

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

      // Score set to 0 if ref frame not allowed
      ref_score[i] = cm->ref_scores[i] * frame_allowed[i];
344
    }
John Koleszar's avatar
John Koleszar committed
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
374
  } 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
375
    }
John Koleszar's avatar
John Koleszar committed
376
  }
377

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

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

  tot_count = count[0] + count[1] + count[2] + count[3];
387
  probs[0] = get_prob(count[0], tot_count);
John Koleszar's avatar
John Koleszar committed
388
389

  tot_count -= count[0];
390
  probs[1] = get_prob(count[1], tot_count);
John Koleszar's avatar
John Koleszar committed
391
392

  tot_count -= count[1];
393
  probs[2] = get_prob(count[2], tot_count);
394
395
}

Paul Wilkins's avatar
Paul Wilkins committed
396
397
398
399
// 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.
400
void vp9_compute_mod_refprobs(VP9_COMMON *const cm) {
John Koleszar's avatar
John Koleszar committed
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
  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
422
  vp9_calc_ref_probs(norm_cnt, cm->mod_refprobs[INTRA_FRAME]);
John Koleszar's avatar
John Koleszar committed
423
424
425
426
427
428
  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
429
  vp9_calc_ref_probs(norm_cnt, cm->mod_refprobs[LAST_FRAME]);
John Koleszar's avatar
John Koleszar committed
430
431
432
433
434
435
  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
436
  vp9_calc_ref_probs(norm_cnt, cm->mod_refprobs[GOLDEN_FRAME]);
John Koleszar's avatar
John Koleszar committed
437
438
439
440
441
442
  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
443
  vp9_calc_ref_probs(norm_cnt, cm->mod_refprobs[ALTREF_FRAME]);
John Koleszar's avatar
John Koleszar committed
444
445
446
447
448
449
450
451
452
  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);
453
}