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.
 */

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

// TBD prediction functions for various bitstream signals

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


    case PRED_REF:
39
40
41
      pred_context = (m - cm->mode_info_stride)->mbmi.ref_predicted;
      if (xd->left_available)
        pred_context += (m - 1)->mbmi.ref_predicted;
John Koleszar's avatar
John Koleszar committed
42
      break;
43

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

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

65
    case PRED_MBSKIP:
66
67
68
      pred_context = (m - cm->mode_info_stride)->mbmi.mb_skip_coeff;
      if (xd->left_available)
        pred_context += (m - 1)->mbmi.mb_skip_coeff;
John Koleszar's avatar
John Koleszar committed
69
      break;
70

71
72
    case PRED_SWITCHABLE_INTERP:
      {
73
        int left_in_image = xd->left_available && (m - 1)->mbmi.mb_in_image;
74
75
76
77
78
        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)
79
          left_interp = vp9_switchable_interp_map[(m - 1)->mbmi.interp_filter];
80
        else
81
          left_interp = VP9_SWITCHABLE_FILTERS;
82
        assert(left_interp != -1);
83
        if (above_in_image && above_mode >= NEARESTMV && above_mode <= SPLITMV)
84
          above_interp = vp9_switchable_interp_map[
85
86
              (m - cm->mode_info_stride)->mbmi.interp_filter];
        else
87
          above_interp = VP9_SWITCHABLE_FILTERS;
88
        assert(above_interp != -1);
89
90
91

        if (left_interp == above_interp)
          pred_context = left_interp;
92
93
        else if (left_interp == VP9_SWITCHABLE_FILTERS &&
                 above_interp != VP9_SWITCHABLE_FILTERS)
94
          pred_context = above_interp;
95
96
        else if (left_interp != VP9_SWITCHABLE_FILTERS &&
                 above_interp == VP9_SWITCHABLE_FILTERS)
97
98
          pred_context = left_interp;
        else
99
          pred_context = VP9_SWITCHABLE_FILTERS;
100
101
102
      }
      break;

103
    default:
John Koleszar's avatar
John Koleszar committed
104
105
106
107
      // TODO *** add error trap code.
      pred_context = 0;
      break;
  }
108

John Koleszar's avatar
John Koleszar committed
109
  return pred_context;
110
111
112
113
}

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

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

  switch (pred_id) {
124
    case PRED_SEG_ID:
John Koleszar's avatar
John Koleszar committed
125
126
      pred_probability = cm->segment_pred_probs[pred_context];
      break;
127
128

    case PRED_REF:
John Koleszar's avatar
John Koleszar committed
129
130
      pred_probability = cm->ref_pred_probs[pred_context];
      break;
131

132
    case PRED_COMP:
John Koleszar's avatar
John Koleszar committed
133
134
135
136
137
      // 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;
138

139
    case PRED_MBSKIP:
John Koleszar's avatar
John Koleszar committed
140
141
      pred_probability = cm->mbskip_pred_probs[pred_context];
      break;
142

143
    default:
John Koleszar's avatar
John Koleszar committed
144
145
146
147
      // TODO *** add error trap code.
      pred_probability = 128;
      break;
  }
148

John Koleszar's avatar
John Koleszar committed
149
  return pred_probability;
150
151
}

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

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

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

187
188
189
190
191
192
193
194
195
    default:
      // TODO *** add error trap code.
      pred_probability = NULL;
      break;
  }

  return pred_probability;
}

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

John Koleszar's avatar
John Koleszar committed
202
  switch (pred_id) {
203
    case PRED_SEG_ID:
John Koleszar's avatar
John Koleszar committed
204
205
      pred_flag = xd->mode_info_context->mbmi.seg_id_predicted;
      break;
206
207

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

211
    case PRED_MBSKIP:
John Koleszar's avatar
John Koleszar committed
212
213
      pred_flag = xd->mode_info_context->mbmi.mb_skip_coeff;
      break;
214

215
    default:
John Koleszar's avatar
John Koleszar committed
216
217
218
219
      // TODO *** add error trap code.
      pred_flag = 0;
      break;
  }
220

John Koleszar's avatar
John Koleszar committed
221
  return pred_flag;
222
223
224
225
}

// 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
226
227
228
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
229
230
  const int mis = xd->mode_info_stride;

John Koleszar's avatar
John Koleszar committed
231
  switch (pred_id) {
232
    case PRED_SEG_ID:
John Koleszar's avatar
John Koleszar committed
233
      xd->mode_info_context->mbmi.seg_id_predicted = pred_flag;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
234
235
236
237
238
239
240
241
242
243
244
245
      if (xd->mode_info_context->mbmi.sb_type) {
#define sub(a, b) (b) < 0 ? (a) + (b) : (a)
        const int n_mbs = 1 << xd->mode_info_context->mbmi.sb_type;
        const int x_mbs = sub(n_mbs, xd->mb_to_right_edge >> 7);
        const int y_mbs = sub(n_mbs, xd->mb_to_bottom_edge >> 7);
        int x, y;

        for (y = 0; y < y_mbs; y++) {
          for (x = !y; 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
246
        }
Ronald S. Bultje's avatar
Ronald S. Bultje committed
247
      }
John Koleszar's avatar
John Koleszar committed
248
      break;
249
250

    case PRED_REF:
John Koleszar's avatar
John Koleszar committed
251
      xd->mode_info_context->mbmi.ref_predicted = pred_flag;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
252
253
254
255
256
257
258
259
260
261
      if (xd->mode_info_context->mbmi.sb_type) {
        const int n_mbs = 1 << xd->mode_info_context->mbmi.sb_type;
        const int x_mbs = sub(n_mbs, xd->mb_to_right_edge >> 7);
        const int y_mbs = sub(n_mbs, xd->mb_to_bottom_edge >> 7);
        int x, y;

        for (y = 0; y < y_mbs; y++) {
          for (x = !y; 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
262
        }
Ronald S. Bultje's avatar
Ronald S. Bultje committed
263
      }
John Koleszar's avatar
John Koleszar committed
264
      break;
265

266
    case PRED_MBSKIP:
John Koleszar's avatar
John Koleszar committed
267
      xd->mode_info_context->mbmi.mb_skip_coeff = pred_flag;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
268
269
270
271
272
273
274
275
276
277
      if (xd->mode_info_context->mbmi.sb_type) {
        const int n_mbs = 1 << xd->mode_info_context->mbmi.sb_type;
        const int x_mbs = sub(n_mbs, xd->mb_to_right_edge >> 7);
        const int y_mbs = sub(n_mbs, xd->mb_to_bottom_edge >> 7);
        int x, y;

        for (y = 0; y < y_mbs; y++) {
          for (x = !y; 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
278
279
        }
      }
John Koleszar's avatar
John Koleszar committed
280
      break;
281

282
    default:
John Koleszar's avatar
John Koleszar committed
283
284
285
      // TODO *** add error trap code.
      break;
  }
286
287
288
289
290
291
292
}


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

// Macroblock segment id prediction function
293
unsigned char vp9_get_pred_mb_segid(const VP9_COMMON *const cm,
Ronald S. Bultje's avatar
Ronald S. Bultje committed
294
                                    const MACROBLOCKD *const xd, int MbIndex) {
John Koleszar's avatar
John Koleszar committed
295
296
  // 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
297
  if (!xd->mode_info_context->mbmi.sb_type) {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
298
299
    return cm->last_frame_seg_map[MbIndex];
  } else {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
300
301
302
303
304
305
306
307
308
309
310
311
    const int n_mbs = 1 << xd->mode_info_context->mbmi.sb_type;
    const int mb_col = MbIndex % cm->mb_cols;
    const int mb_row = MbIndex / cm->mb_cols;
    const int x_mbs = MIN(n_mbs, cm->mb_cols - mb_col);
    const int y_mbs = MIN(n_mbs, cm->mb_rows - mb_row);
    int x, y;
    unsigned seg_id = -1;

    for (y = mb_row; y < mb_row + y_mbs; y++) {
      for (x = mb_col; x < mb_col + x_mbs; x++) {
        seg_id = MIN(seg_id, cm->last_frame_seg_map[cm->mb_cols * y + x]);
      }
Ronald S. Bultje's avatar
Ronald S. Bultje committed
312
    }
Ronald S. Bultje's avatar
Ronald S. Bultje committed
313

Ronald S. Bultje's avatar
Ronald S. Bultje committed
314
315
    return seg_id;
  }
316
317
}

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

  // 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] =
347
        vp9_check_segref(xd, segment_id, i);
John Koleszar's avatar
John Koleszar committed
348
349
350

      // Score set to 0 if ref frame not allowed
      ref_score[i] = cm->ref_scores[i] * frame_allowed[i];
351
    }
John Koleszar's avatar
John Koleszar committed
352
353
354
355
356
357
358
359
360
  } 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
361
  left_in_image = (m - 1)->mbmi.mb_in_image && xd->left_available;
John Koleszar's avatar
John Koleszar committed
362
  above_in_image = (m - cm->mode_info_stride)->mbmi.mb_in_image;
363
364
  above_left_in_image = (m - 1 - cm->mode_info_stride)->mbmi.mb_in_image &&
                        xd->left_available;
John Koleszar's avatar
John Koleszar committed
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382

  // 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
383
    }
John Koleszar's avatar
John Koleszar committed
384
  }
385

John Koleszar's avatar
John Koleszar committed
386
  return pred_ref;
387
388
389
390
}

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

  tot_count = count[0] + count[1] + count[2] + count[3];
395
  probs[0] = get_prob(count[0], tot_count);
John Koleszar's avatar
John Koleszar committed
396
397

  tot_count -= count[0];
398
  probs[1] = get_prob(count[1], tot_count);
John Koleszar's avatar
John Koleszar committed
399
400

  tot_count -= count[1];
401
  probs[2] = get_prob(count[2], tot_count);
402
403
}

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