tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

context_tree.c (10803B)


      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 "av1/encoder/context_tree.h"
     13 #include "av1/encoder/encoder.h"
     14 #include "av1/encoder/rd.h"
     15 #include <assert.h>
     16 
     17 void av1_copy_tree_context(PICK_MODE_CONTEXT *dst_ctx,
     18                           PICK_MODE_CONTEXT *src_ctx) {
     19  dst_ctx->mic = src_ctx->mic;
     20  dst_ctx->mbmi_ext_best = src_ctx->mbmi_ext_best;
     21 
     22  dst_ctx->num_4x4_blk = src_ctx->num_4x4_blk;
     23  dst_ctx->skippable = src_ctx->skippable;
     24 #if CONFIG_INTERNAL_STATS
     25  dst_ctx->best_mode_index = src_ctx->best_mode_index;
     26 #endif  // CONFIG_INTERNAL_STATS
     27 
     28  memcpy(dst_ctx->blk_skip, src_ctx->blk_skip,
     29         sizeof(uint8_t) * src_ctx->num_4x4_blk);
     30  av1_copy_array(dst_ctx->tx_type_map, src_ctx->tx_type_map,
     31                 src_ctx->num_4x4_blk);
     32 
     33  dst_ctx->rd_stats = src_ctx->rd_stats;
     34  dst_ctx->rd_mode_is_ready = src_ctx->rd_mode_is_ready;
     35 }
     36 
     37 void av1_setup_shared_coeff_buffer(const SequenceHeader *const seq_params,
     38                                   PC_TREE_SHARED_BUFFERS *shared_bufs,
     39                                   struct aom_internal_error_info *error) {
     40  const int num_planes = seq_params->monochrome ? 1 : MAX_MB_PLANE;
     41  const int max_sb_square_y = 1 << num_pels_log2_lookup[seq_params->sb_size];
     42  const int max_sb_square_uv = max_sb_square_y >> (seq_params->subsampling_x +
     43                                                   seq_params->subsampling_y);
     44  for (int i = 0; i < num_planes; i++) {
     45    const int max_num_pix =
     46        (i == AOM_PLANE_Y) ? max_sb_square_y : max_sb_square_uv;
     47    AOM_CHECK_MEM_ERROR(error, shared_bufs->coeff_buf[i],
     48                        aom_memalign(32, max_num_pix * sizeof(tran_low_t)));
     49    AOM_CHECK_MEM_ERROR(error, shared_bufs->qcoeff_buf[i],
     50                        aom_memalign(32, max_num_pix * sizeof(tran_low_t)));
     51    AOM_CHECK_MEM_ERROR(error, shared_bufs->dqcoeff_buf[i],
     52                        aom_memalign(32, max_num_pix * sizeof(tran_low_t)));
     53  }
     54 }
     55 
     56 void av1_free_shared_coeff_buffer(PC_TREE_SHARED_BUFFERS *shared_bufs) {
     57  for (int i = 0; i < 3; i++) {
     58    aom_free(shared_bufs->coeff_buf[i]);
     59    aom_free(shared_bufs->qcoeff_buf[i]);
     60    aom_free(shared_bufs->dqcoeff_buf[i]);
     61    shared_bufs->coeff_buf[i] = NULL;
     62    shared_bufs->qcoeff_buf[i] = NULL;
     63    shared_bufs->dqcoeff_buf[i] = NULL;
     64  }
     65 }
     66 
     67 PICK_MODE_CONTEXT *av1_alloc_pmc(const struct AV1_COMP *const cpi,
     68                                 BLOCK_SIZE bsize,
     69                                 PC_TREE_SHARED_BUFFERS *shared_bufs) {
     70  PICK_MODE_CONTEXT *volatile ctx = NULL;
     71  const AV1_COMMON *const cm = &cpi->common;
     72  struct aom_internal_error_info error;
     73 
     74  if (setjmp(error.jmp)) {
     75    av1_free_pmc(ctx, av1_num_planes(cm));
     76    return NULL;
     77  }
     78  error.setjmp = 1;
     79 
     80  AOM_CHECK_MEM_ERROR(&error, ctx, aom_calloc(1, sizeof(*ctx)));
     81  ctx->rd_mode_is_ready = 0;
     82 
     83  const int num_planes = av1_num_planes(cm);
     84  const int num_pix = block_size_wide[bsize] * block_size_high[bsize];
     85  const int num_blk = num_pix / 16;
     86 
     87  AOM_CHECK_MEM_ERROR(&error, ctx->blk_skip,
     88                      aom_calloc(num_blk, sizeof(*ctx->blk_skip)));
     89  AOM_CHECK_MEM_ERROR(&error, ctx->tx_type_map,
     90                      aom_calloc(num_blk, sizeof(*ctx->tx_type_map)));
     91  ctx->num_4x4_blk = num_blk;
     92 
     93  for (int i = 0; i < num_planes; ++i) {
     94    ctx->coeff[i] = shared_bufs->coeff_buf[i];
     95    ctx->qcoeff[i] = shared_bufs->qcoeff_buf[i];
     96    ctx->dqcoeff[i] = shared_bufs->dqcoeff_buf[i];
     97    AOM_CHECK_MEM_ERROR(&error, ctx->eobs[i],
     98                        aom_memalign(32, num_blk * sizeof(*ctx->eobs[i])));
     99    AOM_CHECK_MEM_ERROR(
    100        &error, ctx->txb_entropy_ctx[i],
    101        aom_memalign(32, num_blk * sizeof(*ctx->txb_entropy_ctx[i])));
    102  }
    103 
    104  if (num_pix <= MAX_PALETTE_SQUARE) {
    105    for (int i = 0; i < 2; ++i) {
    106      if (cm->features.allow_screen_content_tools) {
    107        AOM_CHECK_MEM_ERROR(
    108            &error, ctx->color_index_map[i],
    109            aom_memalign(32, num_pix * sizeof(*ctx->color_index_map[i])));
    110      } else {
    111        ctx->color_index_map[i] = NULL;
    112      }
    113    }
    114  }
    115 
    116  av1_invalid_rd_stats(&ctx->rd_stats);
    117 
    118  return ctx;
    119 }
    120 
    121 void av1_reset_pmc(PICK_MODE_CONTEXT *ctx) {
    122  av1_zero_array(ctx->blk_skip, ctx->num_4x4_blk);
    123  av1_zero_array(ctx->tx_type_map, ctx->num_4x4_blk);
    124  av1_invalid_rd_stats(&ctx->rd_stats);
    125 }
    126 
    127 void av1_free_pmc(PICK_MODE_CONTEXT *ctx, int num_planes) {
    128  if (ctx == NULL) return;
    129 
    130  aom_free(ctx->blk_skip);
    131  ctx->blk_skip = NULL;
    132  aom_free(ctx->tx_type_map);
    133  for (int i = 0; i < num_planes; ++i) {
    134    ctx->coeff[i] = NULL;
    135    ctx->qcoeff[i] = NULL;
    136    ctx->dqcoeff[i] = NULL;
    137    aom_free(ctx->eobs[i]);
    138    ctx->eobs[i] = NULL;
    139    aom_free(ctx->txb_entropy_ctx[i]);
    140    ctx->txb_entropy_ctx[i] = NULL;
    141  }
    142 
    143  for (int i = 0; i < 2; ++i) {
    144    if (ctx->color_index_map[i]) {
    145      aom_free(ctx->color_index_map[i]);
    146      ctx->color_index_map[i] = NULL;
    147    }
    148  }
    149 
    150  aom_free(ctx);
    151 }
    152 
    153 PC_TREE *av1_alloc_pc_tree_node(BLOCK_SIZE bsize) {
    154  PC_TREE *pc_tree = aom_calloc(1, sizeof(*pc_tree));
    155  if (pc_tree == NULL) return NULL;
    156 
    157  pc_tree->partitioning = PARTITION_NONE;
    158  pc_tree->block_size = bsize;
    159 
    160  return pc_tree;
    161 }
    162 
    163 #define FREE_PMC_NODE(CTX)         \
    164  do {                             \
    165    av1_free_pmc(CTX, num_planes); \
    166    CTX = NULL;                    \
    167  } while (0)
    168 
    169 void av1_free_pc_tree_recursive(PC_TREE *pc_tree, int num_planes, int keep_best,
    170                                int keep_none,
    171                                PARTITION_SEARCH_TYPE partition_search_type) {
    172  if (pc_tree == NULL) return;
    173 
    174  // Avoid freeing of extended partitions as they are not supported when
    175  // partition_search_type is VAR_BASED_PARTITION.
    176  if (partition_search_type == VAR_BASED_PARTITION && !keep_best &&
    177      !keep_none) {
    178    FREE_PMC_NODE(pc_tree->none);
    179 
    180    for (int i = 0; i < 2; ++i) {
    181      FREE_PMC_NODE(pc_tree->horizontal[i]);
    182      FREE_PMC_NODE(pc_tree->vertical[i]);
    183    }
    184 
    185 #if !defined(NDEBUG) && !CONFIG_REALTIME_ONLY
    186    for (int i = 0; i < 3; ++i) {
    187      assert(pc_tree->horizontala[i] == NULL);
    188      assert(pc_tree->horizontalb[i] == NULL);
    189      assert(pc_tree->verticala[i] == NULL);
    190      assert(pc_tree->verticalb[i] == NULL);
    191    }
    192    for (int i = 0; i < 4; ++i) {
    193      assert(pc_tree->horizontal4[i] == NULL);
    194      assert(pc_tree->vertical4[i] == NULL);
    195    }
    196 #endif
    197 
    198    for (int i = 0; i < 4; ++i) {
    199      if (pc_tree->split[i] != NULL) {
    200        av1_free_pc_tree_recursive(pc_tree->split[i], num_planes, 0, 0,
    201                                   partition_search_type);
    202        pc_tree->split[i] = NULL;
    203      }
    204    }
    205    aom_free(pc_tree);
    206    return;
    207  }
    208 
    209  const PARTITION_TYPE partition = pc_tree->partitioning;
    210 
    211  if (!keep_none && (!keep_best || (partition != PARTITION_NONE)))
    212    FREE_PMC_NODE(pc_tree->none);
    213 
    214  for (int i = 0; i < 2; ++i) {
    215    if (!keep_best || (partition != PARTITION_HORZ))
    216      FREE_PMC_NODE(pc_tree->horizontal[i]);
    217    if (!keep_best || (partition != PARTITION_VERT))
    218      FREE_PMC_NODE(pc_tree->vertical[i]);
    219  }
    220 #if !CONFIG_REALTIME_ONLY
    221  for (int i = 0; i < 3; ++i) {
    222    if (!keep_best || (partition != PARTITION_HORZ_A))
    223      FREE_PMC_NODE(pc_tree->horizontala[i]);
    224    if (!keep_best || (partition != PARTITION_HORZ_B))
    225      FREE_PMC_NODE(pc_tree->horizontalb[i]);
    226    if (!keep_best || (partition != PARTITION_VERT_A))
    227      FREE_PMC_NODE(pc_tree->verticala[i]);
    228    if (!keep_best || (partition != PARTITION_VERT_B))
    229      FREE_PMC_NODE(pc_tree->verticalb[i]);
    230  }
    231  for (int i = 0; i < 4; ++i) {
    232    if (!keep_best || (partition != PARTITION_HORZ_4))
    233      FREE_PMC_NODE(pc_tree->horizontal4[i]);
    234    if (!keep_best || (partition != PARTITION_VERT_4))
    235      FREE_PMC_NODE(pc_tree->vertical4[i]);
    236  }
    237 #endif
    238  if (!keep_best || (partition != PARTITION_SPLIT)) {
    239    for (int i = 0; i < 4; ++i) {
    240      if (pc_tree->split[i] != NULL) {
    241        av1_free_pc_tree_recursive(pc_tree->split[i], num_planes, 0, 0,
    242                                   partition_search_type);
    243        pc_tree->split[i] = NULL;
    244      }
    245    }
    246  }
    247 
    248  if (!keep_best && !keep_none) aom_free(pc_tree);
    249 }
    250 
    251 int av1_setup_sms_tree(AV1_COMP *const cpi, ThreadData *td) {
    252  // The structure 'sms_tree' is used to store the simple motion search data for
    253  // partition pruning in inter frames. Hence, the memory allocations and
    254  // initializations related to it are avoided for allintra encoding mode.
    255  if (cpi->oxcf.kf_cfg.key_freq_max == 0) return 0;
    256 
    257  AV1_COMMON *const cm = &cpi->common;
    258  const int stat_generation_stage = is_stat_generation_stage(cpi);
    259  const int is_sb_size_128 = cm->seq_params->sb_size == BLOCK_128X128;
    260  const int tree_nodes =
    261      av1_get_pc_tree_nodes(is_sb_size_128, stat_generation_stage);
    262  int sms_tree_index = 0;
    263  SIMPLE_MOTION_DATA_TREE *this_sms;
    264  int square_index = 1;
    265  int nodes;
    266 
    267  aom_free(td->sms_tree);
    268  td->sms_tree =
    269      (SIMPLE_MOTION_DATA_TREE *)aom_calloc(tree_nodes, sizeof(*td->sms_tree));
    270  if (!td->sms_tree) return -1;
    271  this_sms = &td->sms_tree[0];
    272 
    273  if (!stat_generation_stage) {
    274    const int leaf_factor = is_sb_size_128 ? 4 : 1;
    275    const int leaf_nodes = 256 * leaf_factor;
    276 
    277    // Sets up all the leaf nodes in the tree.
    278    for (sms_tree_index = 0; sms_tree_index < leaf_nodes; ++sms_tree_index) {
    279      SIMPLE_MOTION_DATA_TREE *const tree = &td->sms_tree[sms_tree_index];
    280      tree->block_size = square[0];
    281    }
    282 
    283    // Each node has 4 leaf nodes, fill each block_size level of the tree
    284    // from leafs to the root.
    285    for (nodes = leaf_nodes >> 2; nodes > 0; nodes >>= 2) {
    286      for (int i = 0; i < nodes; ++i) {
    287        SIMPLE_MOTION_DATA_TREE *const tree = &td->sms_tree[sms_tree_index];
    288        tree->block_size = square[square_index];
    289        for (int j = 0; j < 4; j++) tree->split[j] = this_sms++;
    290        ++sms_tree_index;
    291      }
    292      ++square_index;
    293    }
    294  } else {
    295    // Allocation for firstpass/LAP stage
    296    // TODO(Mufaddal): refactor square_index to use a common block_size macro
    297    // from firstpass.c
    298    SIMPLE_MOTION_DATA_TREE *const tree = &td->sms_tree[sms_tree_index];
    299    square_index = 2;
    300    tree->block_size = square[square_index];
    301  }
    302 
    303  // Set up the root node for the largest superblock size
    304  td->sms_root = &td->sms_tree[tree_nodes - 1];
    305  return 0;
    306 }
    307 
    308 void av1_free_sms_tree(ThreadData *td) {
    309  aom_free(td->sms_tree);
    310  td->sms_tree = NULL;
    311 }