Home | History | Annotate | Download | only in encoder
      1 /*
      2  *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include <limits.h>
     12 #include "vpx_config.h"
     13 #include "onyx_int.h"
     14 #include "mr_dissim.h"
     15 #include "vpx_dsp/vpx_dsp_common.h"
     16 #include "vpx_mem/vpx_mem.h"
     17 #include "rdopt.h"
     18 #include "vp8/common/common.h"
     19 
     20 void vp8_cal_low_res_mb_cols(VP8_COMP *cpi) {
     21   int low_res_w;
     22 
     23   /* Support arbitrary down-sampling factor */
     24   unsigned int iw = cpi->oxcf.Width * cpi->oxcf.mr_down_sampling_factor.den +
     25                     cpi->oxcf.mr_down_sampling_factor.num - 1;
     26 
     27   low_res_w = iw / cpi->oxcf.mr_down_sampling_factor.num;
     28   cpi->mr_low_res_mb_cols = ((low_res_w + 15) >> 4);
     29 }
     30 
     31 #define GET_MV(x)                         \
     32   if (x->mbmi.ref_frame != INTRA_FRAME) { \
     33     mvx[cnt] = x->mbmi.mv.as_mv.row;      \
     34     mvy[cnt] = x->mbmi.mv.as_mv.col;      \
     35     cnt++;                                \
     36   }
     37 
     38 #define GET_MV_SIGN(x)                                  \
     39   if (x->mbmi.ref_frame != INTRA_FRAME) {               \
     40     mvx[cnt] = x->mbmi.mv.as_mv.row;                    \
     41     mvy[cnt] = x->mbmi.mv.as_mv.col;                    \
     42     if (cm->ref_frame_sign_bias[x->mbmi.ref_frame] !=   \
     43         cm->ref_frame_sign_bias[tmp->mbmi.ref_frame]) { \
     44       mvx[cnt] *= -1;                                   \
     45       mvy[cnt] *= -1;                                   \
     46     }                                                   \
     47     cnt++;                                              \
     48   }
     49 
     50 void vp8_cal_dissimilarity(VP8_COMP *cpi) {
     51   VP8_COMMON *cm = &cpi->common;
     52   int i;
     53 
     54   /* Note: The first row & first column in mip are outside the frame, which
     55    * were initialized to all 0.(ref_frame, mode, mv...)
     56    * Their ref_frame = 0 means they won't be counted in the following
     57    * calculation.
     58    */
     59   if (cpi->oxcf.mr_total_resolutions > 1 &&
     60       cpi->oxcf.mr_encoder_id < (cpi->oxcf.mr_total_resolutions - 1)) {
     61     /* Store info for show/no-show frames for supporting alt_ref.
     62      * If parent frame is alt_ref, child has one too.
     63      */
     64     LOWER_RES_FRAME_INFO *store_info =
     65         (LOWER_RES_FRAME_INFO *)cpi->oxcf.mr_low_res_mode_info;
     66 
     67     store_info->frame_type = cm->frame_type;
     68 
     69     if (cm->frame_type != KEY_FRAME) {
     70       store_info->is_frame_dropped = 0;
     71       for (i = 1; i < MAX_REF_FRAMES; ++i)
     72         store_info->low_res_ref_frames[i] = cpi->current_ref_frames[i];
     73     }
     74 
     75     if (cm->frame_type != KEY_FRAME) {
     76       int mb_row;
     77       int mb_col;
     78       /* Point to beginning of allocated MODE_INFO arrays. */
     79       MODE_INFO *tmp = cm->mip + cm->mode_info_stride;
     80       LOWER_RES_MB_INFO *store_mode_info = store_info->mb_info;
     81 
     82       for (mb_row = 0; mb_row < cm->mb_rows; ++mb_row) {
     83         tmp++;
     84         for (mb_col = 0; mb_col < cm->mb_cols; ++mb_col) {
     85           int dissim = INT_MAX;
     86 
     87           if (tmp->mbmi.ref_frame != INTRA_FRAME) {
     88             int mvx[8];
     89             int mvy[8];
     90             int mmvx;
     91             int mmvy;
     92             int cnt = 0;
     93             const MODE_INFO *here = tmp;
     94             const MODE_INFO *above = here - cm->mode_info_stride;
     95             const MODE_INFO *left = here - 1;
     96             const MODE_INFO *aboveleft = above - 1;
     97             const MODE_INFO *aboveright = NULL;
     98             const MODE_INFO *right = NULL;
     99             const MODE_INFO *belowleft = NULL;
    100             const MODE_INFO *below = NULL;
    101             const MODE_INFO *belowright = NULL;
    102 
    103             /* If alternate reference frame is used, we have to
    104              * check sign of MV. */
    105             if (cpi->oxcf.play_alternate) {
    106               /* Gather mv of neighboring MBs */
    107               GET_MV_SIGN(above)
    108               GET_MV_SIGN(left)
    109               GET_MV_SIGN(aboveleft)
    110 
    111               if (mb_col < (cm->mb_cols - 1)) {
    112                 right = here + 1;
    113                 aboveright = above + 1;
    114                 GET_MV_SIGN(right)
    115                 GET_MV_SIGN(aboveright)
    116               }
    117 
    118               if (mb_row < (cm->mb_rows - 1)) {
    119                 below = here + cm->mode_info_stride;
    120                 belowleft = below - 1;
    121                 GET_MV_SIGN(below)
    122                 GET_MV_SIGN(belowleft)
    123               }
    124 
    125               if (mb_col < (cm->mb_cols - 1) && mb_row < (cm->mb_rows - 1)) {
    126                 belowright = below + 1;
    127                 GET_MV_SIGN(belowright)
    128               }
    129             } else {
    130               /* No alt_ref and gather mv of neighboring MBs */
    131               GET_MV(above)
    132               GET_MV(left)
    133               GET_MV(aboveleft)
    134 
    135               if (mb_col < (cm->mb_cols - 1)) {
    136                 right = here + 1;
    137                 aboveright = above + 1;
    138                 GET_MV(right)
    139                 GET_MV(aboveright)
    140               }
    141 
    142               if (mb_row < (cm->mb_rows - 1)) {
    143                 below = here + cm->mode_info_stride;
    144                 belowleft = below - 1;
    145                 GET_MV(below)
    146                 GET_MV(belowleft)
    147               }
    148 
    149               if (mb_col < (cm->mb_cols - 1) && mb_row < (cm->mb_rows - 1)) {
    150                 belowright = below + 1;
    151                 GET_MV(belowright)
    152               }
    153             }
    154 
    155             if (cnt > 0) {
    156               int max_mvx = mvx[0];
    157               int min_mvx = mvx[0];
    158               int max_mvy = mvy[0];
    159               int min_mvy = mvy[0];
    160               int i;
    161 
    162               if (cnt > 1) {
    163                 for (i = 1; i < cnt; ++i) {
    164                   if (mvx[i] > max_mvx)
    165                     max_mvx = mvx[i];
    166                   else if (mvx[i] < min_mvx)
    167                     min_mvx = mvx[i];
    168                   if (mvy[i] > max_mvy)
    169                     max_mvy = mvy[i];
    170                   else if (mvy[i] < min_mvy)
    171                     min_mvy = mvy[i];
    172                 }
    173               }
    174 
    175               mmvx = VPXMAX(abs(min_mvx - here->mbmi.mv.as_mv.row),
    176                             abs(max_mvx - here->mbmi.mv.as_mv.row));
    177               mmvy = VPXMAX(abs(min_mvy - here->mbmi.mv.as_mv.col),
    178                             abs(max_mvy - here->mbmi.mv.as_mv.col));
    179               dissim = VPXMAX(mmvx, mmvy);
    180             }
    181           }
    182 
    183           /* Store mode info for next resolution encoding */
    184           store_mode_info->mode = tmp->mbmi.mode;
    185           store_mode_info->ref_frame = tmp->mbmi.ref_frame;
    186           store_mode_info->mv.as_int = tmp->mbmi.mv.as_int;
    187           store_mode_info->dissim = dissim;
    188           tmp++;
    189           store_mode_info++;
    190         }
    191       }
    192     }
    193   }
    194 }
    195 
    196 /* This function is called only when this frame is dropped at current
    197    resolution level. */
    198 void vp8_store_drop_frame_info(VP8_COMP *cpi) {
    199   /* If the frame is dropped in lower-resolution encoding, this information
    200      is passed to higher resolution level so that the encoder knows there
    201      is no mode & motion info available.
    202    */
    203   if (cpi->oxcf.mr_total_resolutions > 1 &&
    204       cpi->oxcf.mr_encoder_id < (cpi->oxcf.mr_total_resolutions - 1)) {
    205     /* Store info for show/no-show frames for supporting alt_ref.
    206      * If parent frame is alt_ref, child has one too.
    207      */
    208     LOWER_RES_FRAME_INFO *store_info =
    209         (LOWER_RES_FRAME_INFO *)cpi->oxcf.mr_low_res_mode_info;
    210 
    211     /* Set frame_type to be INTER_FRAME since we won't drop key frame. */
    212     store_info->frame_type = INTER_FRAME;
    213     store_info->is_frame_dropped = 1;
    214   }
    215 }
    216