LCOV - code coverage report
Current view: top level - third_party/aom/av1/encoder - encodemv.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 178 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 10 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2016, Alliance for Open Media. All rights reserved
       3             :  *
       4             :  * This source code is subject to the terms of the BSD 2 Clause License and
       5             :  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
       6             :  * was not distributed with this source code in the LICENSE file, you can
       7             :  * obtain it at www.aomedia.org/license/software. If the Alliance for Open
       8             :  * Media Patent License 1.0 was not distributed with this source code in the
       9             :  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
      10             :  */
      11             : 
      12             : #include <math.h>
      13             : 
      14             : #include "av1/common/common.h"
      15             : #include "av1/common/entropymode.h"
      16             : 
      17             : #include "av1/encoder/cost.h"
      18             : #include "av1/encoder/encodemv.h"
      19             : #include "av1/encoder/subexp.h"
      20             : 
      21             : #include "aom_dsp/aom_dsp_common.h"
      22             : 
      23             : static struct av1_token mv_joint_encodings[MV_JOINTS];
      24             : static struct av1_token mv_class_encodings[MV_CLASSES];
      25             : static struct av1_token mv_fp_encodings[MV_FP_SIZE];
      26             : 
      27           0 : void av1_entropy_mv_init(void) {
      28           0 :   av1_tokens_from_tree(mv_joint_encodings, av1_mv_joint_tree);
      29           0 :   av1_tokens_from_tree(mv_class_encodings, av1_mv_class_tree);
      30           0 :   av1_tokens_from_tree(mv_fp_encodings, av1_mv_fp_tree);
      31           0 : }
      32             : 
      33           0 : static void encode_mv_component(aom_writer *w, int comp, nmv_component *mvcomp,
      34             :                                 int usehp) {
      35             :   int offset;
      36           0 :   const int sign = comp < 0;
      37           0 :   const int mag = sign ? -comp : comp;
      38           0 :   const int mv_class = av1_get_mv_class(mag - 1, &offset);
      39           0 :   const int d = offset >> 3;         // int mv data
      40           0 :   const int fr = (offset >> 1) & 3;  // fractional mv data
      41           0 :   const int hp = offset & 1;         // high precision mv data
      42             : 
      43           0 :   assert(comp != 0);
      44             : 
      45             :   // Sign
      46           0 :   aom_write(w, sign, mvcomp->sign);
      47             : 
      48             :   // Class
      49           0 :   aom_write_symbol(w, mv_class, mvcomp->class_cdf, MV_CLASSES);
      50             : 
      51             :   // Integer bits
      52           0 :   if (mv_class == MV_CLASS_0) {
      53           0 :     aom_write(w, d, mvcomp->class0[0]);
      54             :   } else {
      55             :     int i;
      56           0 :     const int n = mv_class + CLASS0_BITS - 1;  // number of bits
      57           0 :     for (i = 0; i < n; ++i) aom_write(w, (d >> i) & 1, mvcomp->bits[i]);
      58             :   }
      59             : 
      60             :   // Fractional bits
      61           0 :   aom_write_symbol(
      62             :       w, fr, mv_class == MV_CLASS_0 ? mvcomp->class0_fp_cdf[d] : mvcomp->fp_cdf,
      63             :       MV_FP_SIZE);
      64             : 
      65             :   // High precision bit
      66           0 :   if (usehp)
      67           0 :     aom_write(w, hp, mv_class == MV_CLASS_0 ? mvcomp->class0_hp : mvcomp->hp);
      68           0 : }
      69             : 
      70           0 : static void build_nmv_component_cost_table(int *mvcost,
      71             :                                            const nmv_component *const mvcomp,
      72             :                                            int usehp) {
      73             :   int i, v;
      74             :   int sign_cost[2], class_cost[MV_CLASSES], class0_cost[CLASS0_SIZE];
      75             :   int bits_cost[MV_OFFSET_BITS][2];
      76             :   int class0_fp_cost[CLASS0_SIZE][MV_FP_SIZE], fp_cost[MV_FP_SIZE];
      77             :   int class0_hp_cost[2], hp_cost[2];
      78             : 
      79           0 :   sign_cost[0] = av1_cost_zero(mvcomp->sign);
      80           0 :   sign_cost[1] = av1_cost_one(mvcomp->sign);
      81           0 :   av1_cost_tokens(class_cost, mvcomp->classes, av1_mv_class_tree);
      82           0 :   av1_cost_tokens(class0_cost, mvcomp->class0, av1_mv_class0_tree);
      83           0 :   for (i = 0; i < MV_OFFSET_BITS; ++i) {
      84           0 :     bits_cost[i][0] = av1_cost_zero(mvcomp->bits[i]);
      85           0 :     bits_cost[i][1] = av1_cost_one(mvcomp->bits[i]);
      86             :   }
      87             : 
      88           0 :   for (i = 0; i < CLASS0_SIZE; ++i)
      89           0 :     av1_cost_tokens(class0_fp_cost[i], mvcomp->class0_fp[i], av1_mv_fp_tree);
      90           0 :   av1_cost_tokens(fp_cost, mvcomp->fp, av1_mv_fp_tree);
      91             : 
      92           0 :   if (usehp) {
      93           0 :     class0_hp_cost[0] = av1_cost_zero(mvcomp->class0_hp);
      94           0 :     class0_hp_cost[1] = av1_cost_one(mvcomp->class0_hp);
      95           0 :     hp_cost[0] = av1_cost_zero(mvcomp->hp);
      96           0 :     hp_cost[1] = av1_cost_one(mvcomp->hp);
      97             :   }
      98           0 :   mvcost[0] = 0;
      99           0 :   for (v = 1; v <= MV_MAX; ++v) {
     100           0 :     int z, c, o, d, e, f, cost = 0;
     101           0 :     z = v - 1;
     102           0 :     c = av1_get_mv_class(z, &o);
     103           0 :     cost += class_cost[c];
     104           0 :     d = (o >> 3);     /* int mv data */
     105           0 :     f = (o >> 1) & 3; /* fractional pel mv data */
     106           0 :     e = (o & 1);      /* high precision mv data */
     107           0 :     if (c == MV_CLASS_0) {
     108           0 :       cost += class0_cost[d];
     109             :     } else {
     110           0 :       const int b = c + CLASS0_BITS - 1; /* number of bits */
     111           0 :       for (i = 0; i < b; ++i) cost += bits_cost[i][((d >> i) & 1)];
     112             :     }
     113           0 :     if (c == MV_CLASS_0) {
     114           0 :       cost += class0_fp_cost[d][f];
     115             :     } else {
     116           0 :       cost += fp_cost[f];
     117             :     }
     118           0 :     if (usehp) {
     119           0 :       if (c == MV_CLASS_0) {
     120           0 :         cost += class0_hp_cost[e];
     121             :       } else {
     122           0 :         cost += hp_cost[e];
     123             :       }
     124             :     }
     125           0 :     mvcost[v] = cost + sign_cost[0];
     126           0 :     mvcost[-v] = cost + sign_cost[1];
     127             :   }
     128           0 : }
     129             : 
     130           0 : static void update_mv(aom_writer *w, const unsigned int ct[2], aom_prob *cur_p,
     131             :                       aom_prob upd_p) {
     132             :   (void)upd_p;
     133             : #if CONFIG_TILE_GROUPS
     134             :   // Just use the default maximum number of tile groups to avoid passing in the
     135             :   // actual
     136             :   // number
     137           0 :   av1_cond_prob_diff_update(w, cur_p, ct, DEFAULT_MAX_NUM_TG);
     138             : #else
     139             :   av1_cond_prob_diff_update(w, cur_p, ct, 1);
     140             : #endif
     141           0 : }
     142             : 
     143             : #if !CONFIG_EC_ADAPT
     144             : static void write_mv_update(const aom_tree_index *tree,
     145             :                             aom_prob probs[/*n - 1*/],
     146             :                             const unsigned int counts[/*n - 1*/], int n,
     147             :                             aom_writer *w) {
     148             :   int i;
     149             :   unsigned int branch_ct[32][2];
     150             : 
     151             :   // Assuming max number of probabilities <= 32
     152             :   assert(n <= 32);
     153             : 
     154             :   av1_tree_probs_from_distribution(tree, branch_ct, counts);
     155             :   for (i = 0; i < n - 1; ++i)
     156             :     update_mv(w, branch_ct[i], &probs[i], MV_UPDATE_PROB);
     157             : }
     158             : #endif
     159             : 
     160           0 : void av1_write_nmv_probs(AV1_COMMON *cm, int usehp, aom_writer *w,
     161             :                          nmv_context_counts *const nmv_counts) {
     162             :   int i;
     163           0 :   int nmv_ctx = 0;
     164           0 :   for (nmv_ctx = 0; nmv_ctx < NMV_CONTEXTS; ++nmv_ctx) {
     165           0 :     nmv_context *const mvc = &cm->fc->nmvc[nmv_ctx];
     166           0 :     nmv_context_counts *const counts = &nmv_counts[nmv_ctx];
     167             : #if !CONFIG_EC_ADAPT
     168             :     write_mv_update(av1_mv_joint_tree, mvc->joints, counts->joints, MV_JOINTS,
     169             :                     w);
     170             : 
     171             :     for (i = 0; i < 2; ++i) {
     172             :       int j;
     173             :       nmv_component *comp = &mvc->comps[i];
     174             :       nmv_component_counts *comp_counts = &counts->comps[i];
     175             : 
     176             :       update_mv(w, comp_counts->sign, &comp->sign, MV_UPDATE_PROB);
     177             :       write_mv_update(av1_mv_class_tree, comp->classes, comp_counts->classes,
     178             :                       MV_CLASSES, w);
     179             :       write_mv_update(av1_mv_class0_tree, comp->class0, comp_counts->class0,
     180             :                       CLASS0_SIZE, w);
     181             :       for (j = 0; j < MV_OFFSET_BITS; ++j)
     182             :         update_mv(w, comp_counts->bits[j], &comp->bits[j], MV_UPDATE_PROB);
     183             :     }
     184             : 
     185             :     for (i = 0; i < 2; ++i) {
     186             :       int j;
     187             :       for (j = 0; j < CLASS0_SIZE; ++j)
     188             :         write_mv_update(av1_mv_fp_tree, mvc->comps[i].class0_fp[j],
     189             :                         counts->comps[i].class0_fp[j], MV_FP_SIZE, w);
     190             : 
     191             :       write_mv_update(av1_mv_fp_tree, mvc->comps[i].fp, counts->comps[i].fp,
     192             :                       MV_FP_SIZE, w);
     193             :     }
     194             : #endif
     195             : 
     196           0 :     if (usehp) {
     197           0 :       for (i = 0; i < 2; ++i) {
     198           0 :         update_mv(w, counts->comps[i].class0_hp, &mvc->comps[i].class0_hp,
     199             :                   MV_UPDATE_PROB);
     200           0 :         update_mv(w, counts->comps[i].hp, &mvc->comps[i].hp, MV_UPDATE_PROB);
     201             :       }
     202             :     }
     203             :   }
     204           0 : }
     205             : 
     206           0 : void av1_encode_mv(AV1_COMP *cpi, aom_writer *w, const MV *mv, const MV *ref,
     207             :                    nmv_context *mvctx, int usehp) {
     208           0 :   const MV diff = { mv->row - ref->row, mv->col - ref->col };
     209           0 :   const MV_JOINT_TYPE j = av1_get_mv_joint(&diff);
     210           0 :   aom_write_symbol(w, j, mvctx->joint_cdf, MV_JOINTS);
     211           0 :   if (mv_joint_vertical(j))
     212           0 :     encode_mv_component(w, diff.row, &mvctx->comps[0], usehp);
     213             : 
     214           0 :   if (mv_joint_horizontal(j))
     215           0 :     encode_mv_component(w, diff.col, &mvctx->comps[1], usehp);
     216             : 
     217             :   // If auto_mv_step_size is enabled then keep track of the largest
     218             :   // motion vector component used.
     219           0 :   if (cpi->sf.mv.auto_mv_step_size) {
     220           0 :     unsigned int maxv = AOMMAX(abs(mv->row), abs(mv->col)) >> 3;
     221           0 :     cpi->max_mv_magnitude = AOMMAX(maxv, cpi->max_mv_magnitude);
     222             :   }
     223           0 : }
     224             : 
     225             : #if CONFIG_INTRABC
     226             : void av1_encode_dv(aom_writer *w, const MV *mv, const MV *ref,
     227             :                    nmv_context *mvctx) {
     228             :   const MV diff = { mv->row - ref->row, mv->col - ref->col };
     229             :   const MV_JOINT_TYPE j = av1_get_mv_joint(&diff);
     230             : 
     231             :   aom_write_symbol(w, j, mvctx->joint_cdf, MV_JOINTS);
     232             :   if (mv_joint_vertical(j))
     233             :     encode_mv_component(w, diff.row, &mvctx->comps[0], 0);
     234             : 
     235             :   if (mv_joint_horizontal(j))
     236             :     encode_mv_component(w, diff.col, &mvctx->comps[1], 0);
     237             : }
     238             : #endif  // CONFIG_INTRABC
     239             : 
     240           0 : void av1_build_nmv_cost_table(int *mvjoint, int *mvcost[2],
     241             :                               const nmv_context *ctx, int usehp) {
     242           0 :   av1_cost_tokens(mvjoint, ctx->joints, av1_mv_joint_tree);
     243           0 :   build_nmv_component_cost_table(mvcost[0], &ctx->comps[0], usehp);
     244           0 :   build_nmv_component_cost_table(mvcost[1], &ctx->comps[1], usehp);
     245           0 : }
     246             : 
     247             : #if CONFIG_EXT_INTER
     248           0 : static void inc_mvs(const MB_MODE_INFO *mbmi, const MB_MODE_INFO_EXT *mbmi_ext,
     249             :                     const int_mv mvs[2], const int_mv pred_mvs[2],
     250             :                     nmv_context_counts *nmv_counts) {
     251             :   int i;
     252           0 :   PREDICTION_MODE mode = mbmi->mode;
     253             : 
     254           0 :   if (mode == NEWMV || mode == NEW_NEWMV) {
     255           0 :     for (i = 0; i < 1 + has_second_ref(mbmi); ++i) {
     256           0 :       const MV *ref = &mbmi_ext->ref_mvs[mbmi->ref_frame[i]][0].as_mv;
     257           0 :       const MV diff = { mvs[i].as_mv.row - ref->row,
     258           0 :                         mvs[i].as_mv.col - ref->col };
     259           0 :       int8_t rf_type = av1_ref_frame_type(mbmi->ref_frame);
     260           0 :       int nmv_ctx =
     261           0 :           av1_nmv_ctx(mbmi_ext->ref_mv_count[rf_type],
     262           0 :                       mbmi_ext->ref_mv_stack[rf_type], i, mbmi->ref_mv_idx);
     263           0 :       nmv_context_counts *counts = &nmv_counts[nmv_ctx];
     264             :       (void)pred_mvs;
     265           0 :       av1_inc_mv(&diff, counts, 1);
     266             :     }
     267           0 :   } else if (mode == NEAREST_NEWMV || mode == NEAR_NEWMV) {
     268           0 :     const MV *ref = &mbmi_ext->ref_mvs[mbmi->ref_frame[1]][0].as_mv;
     269           0 :     const MV diff = { mvs[1].as_mv.row - ref->row,
     270           0 :                       mvs[1].as_mv.col - ref->col };
     271           0 :     int8_t rf_type = av1_ref_frame_type(mbmi->ref_frame);
     272           0 :     int nmv_ctx =
     273           0 :         av1_nmv_ctx(mbmi_ext->ref_mv_count[rf_type],
     274           0 :                     mbmi_ext->ref_mv_stack[rf_type], 1, mbmi->ref_mv_idx);
     275           0 :     nmv_context_counts *counts = &nmv_counts[nmv_ctx];
     276           0 :     av1_inc_mv(&diff, counts, 1);
     277           0 :   } else if (mode == NEW_NEARESTMV || mode == NEW_NEARMV) {
     278           0 :     const MV *ref = &mbmi_ext->ref_mvs[mbmi->ref_frame[0]][0].as_mv;
     279           0 :     const MV diff = { mvs[0].as_mv.row - ref->row,
     280           0 :                       mvs[0].as_mv.col - ref->col };
     281           0 :     int8_t rf_type = av1_ref_frame_type(mbmi->ref_frame);
     282           0 :     int nmv_ctx =
     283           0 :         av1_nmv_ctx(mbmi_ext->ref_mv_count[rf_type],
     284           0 :                     mbmi_ext->ref_mv_stack[rf_type], 0, mbmi->ref_mv_idx);
     285           0 :     nmv_context_counts *counts = &nmv_counts[nmv_ctx];
     286           0 :     av1_inc_mv(&diff, counts, 1);
     287             :   }
     288           0 : }
     289             : 
     290           0 : static void inc_mvs_sub8x8(const MODE_INFO *mi, int block, const int_mv mvs[2],
     291             :                            const MB_MODE_INFO_EXT *mbmi_ext,
     292             :                            nmv_context_counts *nmv_counts) {
     293             :   int i;
     294           0 :   PREDICTION_MODE mode = mi->bmi[block].as_mode;
     295           0 :   const MB_MODE_INFO *mbmi = &mi->mbmi;
     296             : 
     297           0 :   if (mode == NEWMV || mode == NEW_NEWMV) {
     298           0 :     for (i = 0; i < 1 + has_second_ref(&mi->mbmi); ++i) {
     299           0 :       const MV *ref = &mi->bmi[block].ref_mv[i].as_mv;
     300           0 :       const MV diff = { mvs[i].as_mv.row - ref->row,
     301           0 :                         mvs[i].as_mv.col - ref->col };
     302           0 :       int8_t rf_type = av1_ref_frame_type(mbmi->ref_frame);
     303           0 :       int nmv_ctx =
     304           0 :           av1_nmv_ctx(mbmi_ext->ref_mv_count[rf_type],
     305           0 :                       mbmi_ext->ref_mv_stack[rf_type], i, mbmi->ref_mv_idx);
     306           0 :       nmv_context_counts *counts = &nmv_counts[nmv_ctx];
     307           0 :       av1_inc_mv(&diff, counts, 1);
     308             :     }
     309           0 :   } else if (mode == NEAREST_NEWMV || mode == NEAR_NEWMV) {
     310           0 :     const MV *ref = &mi->bmi[block].ref_mv[1].as_mv;
     311           0 :     const MV diff = { mvs[1].as_mv.row - ref->row,
     312           0 :                       mvs[1].as_mv.col - ref->col };
     313           0 :     int8_t rf_type = av1_ref_frame_type(mbmi->ref_frame);
     314           0 :     int nmv_ctx =
     315           0 :         av1_nmv_ctx(mbmi_ext->ref_mv_count[rf_type],
     316           0 :                     mbmi_ext->ref_mv_stack[rf_type], 1, mbmi->ref_mv_idx);
     317           0 :     nmv_context_counts *counts = &nmv_counts[nmv_ctx];
     318           0 :     av1_inc_mv(&diff, counts, 1);
     319           0 :   } else if (mode == NEW_NEARESTMV || mode == NEW_NEARMV) {
     320           0 :     const MV *ref = &mi->bmi[block].ref_mv[0].as_mv;
     321           0 :     const MV diff = { mvs[0].as_mv.row - ref->row,
     322           0 :                       mvs[0].as_mv.col - ref->col };
     323           0 :     int8_t rf_type = av1_ref_frame_type(mbmi->ref_frame);
     324           0 :     int nmv_ctx =
     325           0 :         av1_nmv_ctx(mbmi_ext->ref_mv_count[rf_type],
     326           0 :                     mbmi_ext->ref_mv_stack[rf_type], 0, mbmi->ref_mv_idx);
     327           0 :     nmv_context_counts *counts = &nmv_counts[nmv_ctx];
     328           0 :     av1_inc_mv(&diff, counts, 1);
     329             :   }
     330           0 : }
     331             : #else
     332             : static void inc_mvs(const MB_MODE_INFO *mbmi, const MB_MODE_INFO_EXT *mbmi_ext,
     333             :                     const int_mv mvs[2], const int_mv pred_mvs[2],
     334             :                     nmv_context_counts *nmv_counts) {
     335             :   int i;
     336             : 
     337             :   for (i = 0; i < 1 + has_second_ref(mbmi); ++i) {
     338             :     int8_t rf_type = av1_ref_frame_type(mbmi->ref_frame);
     339             :     int nmv_ctx =
     340             :         av1_nmv_ctx(mbmi_ext->ref_mv_count[rf_type],
     341             :                     mbmi_ext->ref_mv_stack[rf_type], i, mbmi->ref_mv_idx);
     342             :     nmv_context_counts *counts = &nmv_counts[nmv_ctx];
     343             :     const MV *ref = &pred_mvs[i].as_mv;
     344             :     const MV diff = { mvs[i].as_mv.row - ref->row,
     345             :                       mvs[i].as_mv.col - ref->col };
     346             :     av1_inc_mv(&diff, counts, 1);
     347             :   }
     348             : }
     349             : #endif  // CONFIG_EXT_INTER
     350             : 
     351           0 : void av1_update_mv_count(ThreadData *td) {
     352           0 :   const MACROBLOCKD *xd = &td->mb.e_mbd;
     353           0 :   const MODE_INFO *mi = xd->mi[0];
     354           0 :   const MB_MODE_INFO *const mbmi = &mi->mbmi;
     355           0 :   const MB_MODE_INFO_EXT *mbmi_ext = td->mb.mbmi_ext;
     356             : #if CONFIG_CB4X4
     357           0 :   const int unify_bsize = 1;
     358             : #else
     359             :   const int unify_bsize = 0;
     360             : #endif
     361             : 
     362           0 :   if (mbmi->sb_type < BLOCK_8X8 && !unify_bsize) {
     363           0 :     const int num_4x4_w = num_4x4_blocks_wide_lookup[mbmi->sb_type];
     364           0 :     const int num_4x4_h = num_4x4_blocks_high_lookup[mbmi->sb_type];
     365             :     int idx, idy;
     366             : 
     367           0 :     for (idy = 0; idy < 2; idy += num_4x4_h) {
     368           0 :       for (idx = 0; idx < 2; idx += num_4x4_w) {
     369           0 :         const int i = idy * 2 + idx;
     370             : 
     371             : #if CONFIG_EXT_INTER
     372           0 :         if (have_newmv_in_inter_mode(mi->bmi[i].as_mode))
     373           0 :           inc_mvs_sub8x8(mi, i, mi->bmi[i].as_mv, mbmi_ext, td->counts->mv);
     374             : #else
     375             :         if (mi->bmi[i].as_mode == NEWMV)
     376             :           inc_mvs(mbmi, mbmi_ext, mi->bmi[i].as_mv, mi->bmi[i].pred_mv,
     377             :                   td->counts->mv);
     378             : #endif  // CONFIG_EXT_INTER
     379             :       }
     380             :     }
     381             :   } else {
     382             : #if CONFIG_EXT_INTER
     383           0 :     if (have_newmv_in_inter_mode(mbmi->mode))
     384             : #else
     385             :     if (mbmi->mode == NEWMV)
     386             : #endif  // CONFIG_EXT_INTER
     387           0 :       inc_mvs(mbmi, mbmi_ext, mbmi->mv, mbmi->pred_mv, td->counts->mv);
     388             :   }
     389           0 : }

Generated by: LCOV version 1.13