media/libvpx/vp9/common/vp9_pred_common.c

Thu, 15 Jan 2015 15:59:08 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:59:08 +0100
branch
TOR_BUG_9701
changeset 10
ac0c01689b40
permissions
-rw-r--r--

Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     2 /*
     3  *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
     4  *
     5  *  Use of this source code is governed by a BSD-style license
     6  *  that can be found in the LICENSE file in the root of the source
     7  *  tree. An additional intellectual property rights grant can be found
     8  *  in the file PATENTS.  All contributing project authors may
     9  *  be found in the AUTHORS file in the root of the source tree.
    10  */
    12 #include <limits.h>
    14 #include "vp9/common/vp9_common.h"
    15 #include "vp9/common/vp9_pred_common.h"
    16 #include "vp9/common/vp9_seg_common.h"
    17 #include "vp9/common/vp9_treecoder.h"
    19 static INLINE const MB_MODE_INFO *get_above_mbmi(const MODE_INFO *const above) {
    20   return (above != NULL) ? &above->mbmi : NULL;
    21 }
    23 static INLINE const MB_MODE_INFO *get_left_mbmi(const MODE_INFO *const left) {
    24   return (left != NULL) ? &left->mbmi : NULL;
    25 }
    27 // Returns a context number for the given MB prediction signal
    28 unsigned char vp9_get_pred_context_switchable_interp(const MACROBLOCKD *xd) {
    29   const MODE_INFO *const above_mi = get_above_mi(xd);
    30   const MODE_INFO *const left_mi = get_left_mi(xd);
    31   const int above_in_image = above_mi != NULL;
    32   const int left_in_image = left_mi != NULL;
    33   // Note:
    34   // The mode info data structure has a one element border above and to the
    35   // left of the entries correpsonding to real macroblocks.
    36   // The prediction flags in these dummy entries are initialised to 0.
    37   // left
    38   const int left_mv_pred = left_in_image ? is_inter_block(&left_mi->mbmi)
    39                                          : 0;
    40   const int left_interp = left_in_image && left_mv_pred
    41                               ? left_mi->mbmi.interp_filter
    42                               : SWITCHABLE_FILTERS;
    44   // above
    45   const int above_mv_pred = above_in_image ? is_inter_block(&above_mi->mbmi)
    46                                            : 0;
    47   const int above_interp = above_in_image && above_mv_pred
    48                                ? above_mi->mbmi.interp_filter
    49                                : SWITCHABLE_FILTERS;
    51   if (left_interp == above_interp)
    52     return left_interp;
    53   else if (left_interp == SWITCHABLE_FILTERS &&
    54            above_interp != SWITCHABLE_FILTERS)
    55     return above_interp;
    56   else if (left_interp != SWITCHABLE_FILTERS &&
    57            above_interp == SWITCHABLE_FILTERS)
    58     return left_interp;
    59   else
    60     return SWITCHABLE_FILTERS;
    61 }
    62 // Returns a context number for the given MB prediction signal
    63 unsigned char vp9_get_pred_context_intra_inter(const MACROBLOCKD *xd) {
    64   const MODE_INFO *const above_mi = get_above_mi(xd);
    65   const MODE_INFO *const left_mi = get_left_mi(xd);
    66   const MB_MODE_INFO *const above_mbmi = get_above_mbmi(above_mi);
    67   const MB_MODE_INFO *const left_mbmi = get_left_mbmi(left_mi);
    68   const int above_in_image = above_mi != NULL;
    69   const int left_in_image = left_mi != NULL;
    70   const int above_intra = above_in_image ? !is_inter_block(above_mbmi) : 1;
    71   const int left_intra = left_in_image ? !is_inter_block(left_mbmi) : 1;
    73   // The mode info data structure has a one element border above and to the
    74   // left of the entries corresponding to real macroblocks.
    75   // The prediction flags in these dummy entries are initialized to 0.
    76   // 0 - inter/inter, inter/--, --/inter, --/--
    77   // 1 - intra/inter, inter/intra
    78   // 2 - intra/--, --/intra
    79   // 3 - intra/intra
    80   if (above_in_image && left_in_image)  // both edges available
    81     return left_intra && above_intra ? 3
    82                                      : left_intra || above_intra;
    83   else if (above_in_image || left_in_image)  // one edge available
    84     return 2 * (above_in_image ? above_intra : left_intra);
    85   else
    86     return 0;
    87 }
    88 // Returns a context number for the given MB prediction signal
    89 unsigned char vp9_get_pred_context_comp_inter_inter(const VP9_COMMON *cm,
    90                                                     const MACROBLOCKD *xd) {
    91   int pred_context;
    92   const MODE_INFO *const above_mi = get_above_mi(xd);
    93   const MODE_INFO *const left_mi = get_left_mi(xd);
    94   const MB_MODE_INFO *const above_mbmi = get_above_mbmi(above_mi);
    95   const MB_MODE_INFO *const left_mbmi = get_left_mbmi(left_mi);
    96   const int above_in_image = above_mi != NULL;
    97   const int left_in_image = left_mi != NULL;
    98   // Note:
    99   // The mode info data structure has a one element border above and to the
   100   // left of the entries correpsonding to real macroblocks.
   101   // The prediction flags in these dummy entries are initialised to 0.
   102   if (above_in_image && left_in_image) {  // both edges available
   103     if (!has_second_ref(above_mbmi) && !has_second_ref(left_mbmi))
   104       // neither edge uses comp pred (0/1)
   105       pred_context = (above_mbmi->ref_frame[0] == cm->comp_fixed_ref) ^
   106                      (left_mbmi->ref_frame[0] == cm->comp_fixed_ref);
   107     else if (!has_second_ref(above_mbmi))
   108       // one of two edges uses comp pred (2/3)
   109       pred_context = 2 + (above_mbmi->ref_frame[0] == cm->comp_fixed_ref ||
   110                           !is_inter_block(above_mbmi));
   111     else if (!has_second_ref(left_mbmi))
   112       // one of two edges uses comp pred (2/3)
   113       pred_context = 2 + (left_mbmi->ref_frame[0] == cm->comp_fixed_ref ||
   114                           !is_inter_block(left_mbmi));
   115     else  // both edges use comp pred (4)
   116       pred_context = 4;
   117   } else if (above_in_image || left_in_image) {  // one edge available
   118     const MB_MODE_INFO *edge_mbmi = above_in_image ? above_mbmi : left_mbmi;
   120     if (!has_second_ref(edge_mbmi))
   121       // edge does not use comp pred (0/1)
   122       pred_context = edge_mbmi->ref_frame[0] == cm->comp_fixed_ref;
   123     else
   124       // edge uses comp pred (3)
   125       pred_context = 3;
   126   } else {  // no edges available (1)
   127     pred_context = 1;
   128   }
   129   assert(pred_context >= 0 && pred_context < COMP_INTER_CONTEXTS);
   130   return pred_context;
   131 }
   133 // Returns a context number for the given MB prediction signal
   134 unsigned char vp9_get_pred_context_comp_ref_p(const VP9_COMMON *cm,
   135                                               const MACROBLOCKD *xd) {
   136   int pred_context;
   137   const MODE_INFO *const above_mi = get_above_mi(xd);
   138   const MODE_INFO *const left_mi = get_left_mi(xd);
   139   const MB_MODE_INFO *const above_mbmi = get_above_mbmi(above_mi);
   140   const MB_MODE_INFO *const left_mbmi = get_left_mbmi(left_mi);
   141   const int above_in_image = above_mi != NULL;
   142   const int left_in_image = left_mi != NULL;
   143   const int above_intra = above_in_image ? !is_inter_block(above_mbmi) : 1;
   144   const int left_intra = left_in_image ? !is_inter_block(left_mbmi) : 1;
   145   // Note:
   146   // The mode info data structure has a one element border above and to the
   147   // left of the entries correpsonding to real macroblocks.
   148   // The prediction flags in these dummy entries are initialised to 0.
   149   const int fix_ref_idx = cm->ref_frame_sign_bias[cm->comp_fixed_ref];
   150   const int var_ref_idx = !fix_ref_idx;
   152   if (above_in_image && left_in_image) {  // both edges available
   153     if (above_intra && left_intra) {  // intra/intra (2)
   154       pred_context = 2;
   155     } else if (above_intra || left_intra) {  // intra/inter
   156       const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi;
   158       if (!has_second_ref(edge_mbmi))  // single pred (1/3)
   159         pred_context = 1 + 2 * (edge_mbmi->ref_frame[0] != cm->comp_var_ref[1]);
   160       else  // comp pred (1/3)
   161         pred_context = 1 + 2 * (edge_mbmi->ref_frame[var_ref_idx]
   162                                     != cm->comp_var_ref[1]);
   163     } else {  // inter/inter
   164       const int l_sg = !has_second_ref(left_mbmi);
   165       const int a_sg = !has_second_ref(above_mbmi);
   166       MV_REFERENCE_FRAME vrfa = a_sg ? above_mbmi->ref_frame[0]
   167                                      : above_mbmi->ref_frame[var_ref_idx];
   168       MV_REFERENCE_FRAME vrfl = l_sg ? left_mbmi->ref_frame[0]
   169                                      : left_mbmi->ref_frame[var_ref_idx];
   171       if (vrfa == vrfl && cm->comp_var_ref[1] == vrfa) {
   172         pred_context = 0;
   173       } else if (l_sg && a_sg) {  // single/single
   174         if ((vrfa == cm->comp_fixed_ref && vrfl == cm->comp_var_ref[0]) ||
   175             (vrfl == cm->comp_fixed_ref && vrfa == cm->comp_var_ref[0]))
   176           pred_context = 4;
   177         else if (vrfa == vrfl)
   178           pred_context = 3;
   179         else
   180           pred_context = 1;
   181       } else if (l_sg || a_sg) {  // single/comp
   182         MV_REFERENCE_FRAME vrfc = l_sg ? vrfa : vrfl;
   183         MV_REFERENCE_FRAME rfs = a_sg ? vrfa : vrfl;
   184         if (vrfc == cm->comp_var_ref[1] && rfs != cm->comp_var_ref[1])
   185           pred_context = 1;
   186         else if (rfs == cm->comp_var_ref[1] && vrfc != cm->comp_var_ref[1])
   187           pred_context = 2;
   188         else
   189           pred_context = 4;
   190       } else if (vrfa == vrfl) {  // comp/comp
   191         pred_context = 4;
   192       } else {
   193         pred_context = 2;
   194       }
   195     }
   196   } else if (above_in_image || left_in_image) {  // one edge available
   197     const MB_MODE_INFO *edge_mbmi = above_in_image ? above_mbmi : left_mbmi;
   199     if (!is_inter_block(edge_mbmi)) {
   200       pred_context = 2;
   201     } else {
   202       if (has_second_ref(edge_mbmi))
   203         pred_context = 4 * (edge_mbmi->ref_frame[var_ref_idx]
   204                               != cm->comp_var_ref[1]);
   205       else
   206         pred_context = 3 * (edge_mbmi->ref_frame[0] != cm->comp_var_ref[1]);
   207     }
   208   } else {  // no edges available (2)
   209     pred_context = 2;
   210   }
   211   assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
   213   return pred_context;
   214 }
   215 unsigned char vp9_get_pred_context_single_ref_p1(const MACROBLOCKD *xd) {
   216   int pred_context;
   217   const MODE_INFO *const above_mi = get_above_mi(xd);
   218   const MODE_INFO *const left_mi = get_left_mi(xd);
   219   const MB_MODE_INFO *const above_mbmi = get_above_mbmi(above_mi);
   220   const MB_MODE_INFO *const left_mbmi = get_left_mbmi(left_mi);
   221   const int above_in_image = above_mi != NULL;
   222   const int left_in_image = left_mi != NULL;
   223   const int above_intra = above_in_image ? !is_inter_block(above_mbmi) : 1;
   224   const int left_intra = left_in_image ? !is_inter_block(left_mbmi) : 1;
   225   // Note:
   226   // The mode info data structure has a one element border above and to the
   227   // left of the entries correpsonding to real macroblocks.
   228   // The prediction flags in these dummy entries are initialised to 0.
   229   if (above_in_image && left_in_image) {  // both edges available
   230     if (above_intra && left_intra) {  // intra/intra
   231       pred_context = 2;
   232     } else if (above_intra || left_intra) {  // intra/inter or inter/intra
   233       const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi;
   234       if (!has_second_ref(edge_mbmi))
   235         pred_context = 4 * (edge_mbmi->ref_frame[0] == LAST_FRAME);
   236       else
   237         pred_context = 1 + (edge_mbmi->ref_frame[0] == LAST_FRAME ||
   238                             edge_mbmi->ref_frame[1] == LAST_FRAME);
   239     } else {  // inter/inter
   240       if (!has_second_ref(above_mbmi) && !has_second_ref(left_mbmi)) {
   241         pred_context = 2 * (above_mbmi->ref_frame[0] == LAST_FRAME) +
   242                        2 * (left_mbmi->ref_frame[0] == LAST_FRAME);
   243       } else if (has_second_ref(above_mbmi) && has_second_ref(left_mbmi)) {
   244         pred_context = 1 + (above_mbmi->ref_frame[0] == LAST_FRAME ||
   245                             above_mbmi->ref_frame[1] == LAST_FRAME ||
   246                             left_mbmi->ref_frame[0] == LAST_FRAME ||
   247                             left_mbmi->ref_frame[1] == LAST_FRAME);
   248       } else {
   249         const MV_REFERENCE_FRAME rfs = !has_second_ref(above_mbmi) ?
   250                   above_mbmi->ref_frame[0] : left_mbmi->ref_frame[0];
   251         const MV_REFERENCE_FRAME crf1 = has_second_ref(above_mbmi) ?
   252                   above_mbmi->ref_frame[0] : left_mbmi->ref_frame[0];
   253         const MV_REFERENCE_FRAME crf2 = has_second_ref(above_mbmi) ?
   254                   above_mbmi->ref_frame[1] : left_mbmi->ref_frame[1];
   256         if (rfs == LAST_FRAME)
   257           pred_context = 3 + (crf1 == LAST_FRAME || crf2 == LAST_FRAME);
   258         else
   259           pred_context = crf1 == LAST_FRAME || crf2 == LAST_FRAME;
   260       }
   261     }
   262   } else if (above_in_image || left_in_image) {  // one edge available
   263     const MB_MODE_INFO *edge_mbmi = above_in_image ? above_mbmi : left_mbmi;
   264     if (!is_inter_block(edge_mbmi)) {  // intra
   265       pred_context = 2;
   266     } else {  // inter
   267       if (!has_second_ref(edge_mbmi))
   268         pred_context = 4 * (edge_mbmi->ref_frame[0] == LAST_FRAME);
   269       else
   270         pred_context = 1 + (edge_mbmi->ref_frame[0] == LAST_FRAME ||
   271                             edge_mbmi->ref_frame[1] == LAST_FRAME);
   272     }
   273   } else {  // no edges available
   274     pred_context = 2;
   275   }
   277   assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
   278   return pred_context;
   279 }
   281 unsigned char vp9_get_pred_context_single_ref_p2(const MACROBLOCKD *xd) {
   282   int pred_context;
   283   const MODE_INFO *const above_mi = get_above_mi(xd);
   284   const MODE_INFO *const left_mi = get_left_mi(xd);
   285   const MB_MODE_INFO *const above_mbmi = get_above_mbmi(above_mi);
   286   const MB_MODE_INFO *const left_mbmi = get_left_mbmi(left_mi);
   287   const int above_in_image = above_mi != NULL;
   288   const int left_in_image = left_mi != NULL;
   289   const int above_intra = above_in_image ? !is_inter_block(above_mbmi) : 1;
   290   const int left_intra = left_in_image ? !is_inter_block(left_mbmi) : 1;
   292   // Note:
   293   // The mode info data structure has a one element border above and to the
   294   // left of the entries correpsonding to real macroblocks.
   295   // The prediction flags in these dummy entries are initialised to 0.
   296   if (above_in_image && left_in_image) {  // both edges available
   297     if (above_intra && left_intra) {  // intra/intra
   298       pred_context = 2;
   299     } else if (above_intra || left_intra) {  // intra/inter or inter/intra
   300       const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi;
   301       if (!has_second_ref(edge_mbmi)) {
   302         if (edge_mbmi->ref_frame[0] == LAST_FRAME)
   303           pred_context = 3;
   304         else
   305           pred_context = 4 * (edge_mbmi->ref_frame[0] == GOLDEN_FRAME);
   306       } else {
   307         pred_context = 1 + 2 * (edge_mbmi->ref_frame[0] == GOLDEN_FRAME ||
   308                                 edge_mbmi->ref_frame[1] == GOLDEN_FRAME);
   309       }
   310     } else {  // inter/inter
   311       if (!has_second_ref(above_mbmi) && !has_second_ref(left_mbmi)) {
   312         if (above_mbmi->ref_frame[0] == LAST_FRAME &&
   313             left_mbmi->ref_frame[0] == LAST_FRAME) {
   314           pred_context = 3;
   315         } else if (above_mbmi->ref_frame[0] == LAST_FRAME ||
   316                    left_mbmi->ref_frame[0] == LAST_FRAME) {
   317           const MB_MODE_INFO *edge_mbmi =
   318               above_mbmi->ref_frame[0] == LAST_FRAME ? left_mbmi : above_mbmi;
   320           pred_context = 4 * (edge_mbmi->ref_frame[0] == GOLDEN_FRAME);
   321         } else {
   322           pred_context = 2 * (above_mbmi->ref_frame[0] == GOLDEN_FRAME) +
   323                          2 * (left_mbmi->ref_frame[0] == GOLDEN_FRAME);
   324         }
   325       } else if (has_second_ref(above_mbmi) && has_second_ref(left_mbmi)) {
   326         if (above_mbmi->ref_frame[0] == left_mbmi->ref_frame[0] &&
   327             above_mbmi->ref_frame[1] == left_mbmi->ref_frame[1])
   328           pred_context = 3 * (above_mbmi->ref_frame[0] == GOLDEN_FRAME ||
   329                               above_mbmi->ref_frame[1] == GOLDEN_FRAME ||
   330                               left_mbmi->ref_frame[0] == GOLDEN_FRAME ||
   331                               left_mbmi->ref_frame[1] == GOLDEN_FRAME);
   332         else
   333           pred_context = 2;
   334       } else {
   335         const MV_REFERENCE_FRAME rfs = !has_second_ref(above_mbmi) ?
   336                   above_mbmi->ref_frame[0] : left_mbmi->ref_frame[0];
   337         const MV_REFERENCE_FRAME crf1 = has_second_ref(above_mbmi) ?
   338                   above_mbmi->ref_frame[0] : left_mbmi->ref_frame[0];
   339         const MV_REFERENCE_FRAME crf2 = has_second_ref(above_mbmi) ?
   340                   above_mbmi->ref_frame[1] : left_mbmi->ref_frame[1];
   342         if (rfs == GOLDEN_FRAME)
   343           pred_context = 3 + (crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME);
   344         else if (rfs == ALTREF_FRAME)
   345           pred_context = crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME;
   346         else
   347           pred_context = 1 + 2 * (crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME);
   348       }
   349     }
   350   } else if (above_in_image || left_in_image) {  // one edge available
   351     const MB_MODE_INFO *edge_mbmi = above_in_image ? above_mbmi : left_mbmi;
   353     if (!is_inter_block(edge_mbmi) ||
   354         (edge_mbmi->ref_frame[0] == LAST_FRAME && !has_second_ref(edge_mbmi)))
   355       pred_context = 2;
   356     else if (!has_second_ref(edge_mbmi))
   357       pred_context = 4 * (edge_mbmi->ref_frame[0] == GOLDEN_FRAME);
   358     else
   359       pred_context = 3 * (edge_mbmi->ref_frame[0] == GOLDEN_FRAME ||
   360                           edge_mbmi->ref_frame[1] == GOLDEN_FRAME);
   361   } else {  // no edges available (2)
   362     pred_context = 2;
   363   }
   364   assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
   365   return pred_context;
   366 }
   367 // Returns a context number for the given MB prediction signal
   368 // The mode info data structure has a one element border above and to the
   369 // left of the entries corresponding to real blocks.
   370 // The prediction flags in these dummy entries are initialized to 0.
   371 unsigned char vp9_get_pred_context_tx_size(const MACROBLOCKD *xd) {
   372   const MODE_INFO *const above_mi = get_above_mi(xd);
   373   const MODE_INFO *const left_mi = get_left_mi(xd);
   374   const MB_MODE_INFO *const above_mbmi = get_above_mbmi(above_mi);
   375   const MB_MODE_INFO *const left_mbmi = get_left_mbmi(left_mi);
   376   const int above_in_image = above_mi != NULL;
   377   const int left_in_image = left_mi != NULL;
   378   const int max_tx_size = max_txsize_lookup[xd->mi_8x8[0]->mbmi.sb_type];
   379   int above_context = max_tx_size;
   380   int left_context = max_tx_size;
   382   if (above_in_image)
   383     above_context = above_mbmi->skip_coeff ? max_tx_size
   384                                            : above_mbmi->tx_size;
   386   if (left_in_image)
   387     left_context = left_mbmi->skip_coeff ? max_tx_size
   388                                          : left_mbmi->tx_size;
   390   if (!left_in_image)
   391     left_context = above_context;
   393   if (!above_in_image)
   394     above_context = left_context;
   396   return above_context + left_context > max_tx_size;
   397 }
   399 void vp9_set_pred_flag_seg_id(MACROBLOCKD *xd, uint8_t pred_flag) {
   400   xd->mi_8x8[0]->mbmi.seg_id_predicted = pred_flag;
   401 }
   403 int vp9_get_segment_id(VP9_COMMON *cm, const uint8_t *segment_ids,
   404                        BLOCK_SIZE bsize, int mi_row, int mi_col) {
   405   const int mi_offset = mi_row * cm->mi_cols + mi_col;
   406   const int bw = num_8x8_blocks_wide_lookup[bsize];
   407   const int bh = num_8x8_blocks_high_lookup[bsize];
   408   const int xmis = MIN(cm->mi_cols - mi_col, bw);
   409   const int ymis = MIN(cm->mi_rows - mi_row, bh);
   410   int x, y, segment_id = INT_MAX;
   412   for (y = 0; y < ymis; y++)
   413     for (x = 0; x < xmis; x++)
   414       segment_id = MIN(segment_id,
   415                        segment_ids[mi_offset + y * cm->mi_cols + x]);
   417   assert(segment_id >= 0 && segment_id < MAX_SEGMENTS);
   418   return segment_id;
   419 }

mercurial