vp9_pred_common.c 14.5 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:
John Koleszar's avatar
John Koleszar committed
32
33
34
      pred_context = (m - 1)->mbmi.seg_id_predicted +
                     (m - cm->mode_info_stride)->mbmi.seg_id_predicted;
      break;
35
36
37


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  return pred_probability;
}

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

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

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

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

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

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

// 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
223
224
225
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
226
227
  const int mis = xd->mode_info_stride;

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
233
234
235
236
237
238
239
240
241
242
      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
243
        }
Ronald S. Bultje's avatar
Ronald S. Bultje committed
244
      }
John Koleszar's avatar
John Koleszar committed
245
      break;
246
247

    case PRED_REF:
John Koleszar's avatar
John Koleszar committed
248
      xd->mode_info_context->mbmi.ref_predicted = pred_flag;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
249
250
251
252
253
254
255
256
257
258
      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
259
        }
Ronald S. Bultje's avatar
Ronald S. Bultje committed
260
      }
John Koleszar's avatar
John Koleszar committed
261
      break;
262

263
    case PRED_MBSKIP:
John Koleszar's avatar
John Koleszar committed
264
      xd->mode_info_context->mbmi.mb_skip_coeff = pred_flag;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
265
266
267
268
269
270
271
272
273
274
      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
275
276
        }
      }
John Koleszar's avatar
John Koleszar committed
277
      break;
278

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


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

// Macroblock segment id prediction function
290
unsigned char vp9_get_pred_mb_segid(const VP9_COMMON *const cm,
Ronald S. Bultje's avatar
Ronald S. Bultje committed
291
                                    const MACROBLOCKD *const xd, int MbIndex) {
John Koleszar's avatar
John Koleszar committed
292
293
  // 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
294
  if (!xd->mode_info_context->mbmi.sb_type) {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
295
296
    return cm->last_frame_seg_map[MbIndex];
  } else {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
297
298
299
300
301
302
303
304
305
306
307
308
    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
309
    }
Ronald S. Bultje's avatar
Ronald S. Bultje committed
310

Ronald S. Bultje's avatar
Ronald S. Bultje committed
311
312
    return seg_id;
  }
313
314
}

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

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

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

John Koleszar's avatar
John Koleszar committed
382
  return pred_ref;
383
384
385
386
}

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

  tot_count = count[0] + count[1] + count[2] + count[3];
391
  probs[0] = get_prob(count[0], tot_count);
John Koleszar's avatar
John Koleszar committed
392
393

  tot_count -= count[0];
394
  probs[1] = get_prob(count[1], tot_count);
John Koleszar's avatar
John Koleszar committed
395
396

  tot_count -= count[1];
397
  probs[2] = get_prob(count[2], tot_count);
398
399
}

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