Home | History | Annotate | Download | only in common
      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 "./vpx_config.h"
     12 #include "vpx_mem/vpx_mem.h"
     13 
     14 #include "vp9/common/vp9_alloccommon.h"
     15 #include "vp9/common/vp9_blockd.h"
     16 #include "vp9/common/vp9_entropymode.h"
     17 #include "vp9/common/vp9_entropymv.h"
     18 #include "vp9/common/vp9_onyxc_int.h"
     19 
     20 void vp9_set_mb_mi(VP9_COMMON *cm, int width, int height) {
     21   const int aligned_width = ALIGN_POWER_OF_TWO(width, MI_SIZE_LOG2);
     22   const int aligned_height = ALIGN_POWER_OF_TWO(height, MI_SIZE_LOG2);
     23 
     24   cm->mi_cols = aligned_width >> MI_SIZE_LOG2;
     25   cm->mi_rows = aligned_height >> MI_SIZE_LOG2;
     26   cm->mi_stride = calc_mi_size(cm->mi_cols);
     27 
     28   cm->mb_cols = (cm->mi_cols + 1) >> 1;
     29   cm->mb_rows = (cm->mi_rows + 1) >> 1;
     30   cm->MBs = cm->mb_rows * cm->mb_cols;
     31 }
     32 
     33 static int alloc_seg_map(VP9_COMMON *cm, int seg_map_size) {
     34   int i;
     35 
     36   for (i = 0; i < NUM_PING_PONG_BUFFERS; ++i) {
     37     cm->seg_map_array[i] = (uint8_t *)vpx_calloc(seg_map_size, 1);
     38     if (cm->seg_map_array[i] == NULL) return 1;
     39   }
     40   cm->seg_map_alloc_size = seg_map_size;
     41 
     42   // Init the index.
     43   cm->seg_map_idx = 0;
     44   cm->prev_seg_map_idx = 1;
     45 
     46   cm->current_frame_seg_map = cm->seg_map_array[cm->seg_map_idx];
     47   cm->last_frame_seg_map = cm->seg_map_array[cm->prev_seg_map_idx];
     48 
     49   return 0;
     50 }
     51 
     52 static void free_seg_map(VP9_COMMON *cm) {
     53   int i;
     54 
     55   for (i = 0; i < NUM_PING_PONG_BUFFERS; ++i) {
     56     vpx_free(cm->seg_map_array[i]);
     57     cm->seg_map_array[i] = NULL;
     58   }
     59 
     60   cm->current_frame_seg_map = NULL;
     61   cm->last_frame_seg_map = NULL;
     62 }
     63 
     64 void vp9_free_ref_frame_buffers(BufferPool *pool) {
     65   int i;
     66 
     67   for (i = 0; i < FRAME_BUFFERS; ++i) {
     68     if (!pool->frame_bufs[i].released &&
     69         pool->frame_bufs[i].raw_frame_buffer.data != NULL) {
     70       pool->release_fb_cb(pool->cb_priv, &pool->frame_bufs[i].raw_frame_buffer);
     71       pool->frame_bufs[i].ref_count = 0;
     72       pool->frame_bufs[i].released = 1;
     73     }
     74     vpx_free(pool->frame_bufs[i].mvs);
     75     pool->frame_bufs[i].mvs = NULL;
     76     vpx_free_frame_buffer(&pool->frame_bufs[i].buf);
     77   }
     78 }
     79 
     80 void vp9_free_postproc_buffers(VP9_COMMON *cm) {
     81 #if CONFIG_VP9_POSTPROC
     82   vpx_free_frame_buffer(&cm->post_proc_buffer);
     83   vpx_free_frame_buffer(&cm->post_proc_buffer_int);
     84   vpx_free(cm->postproc_state.limits);
     85   cm->postproc_state.limits = NULL;
     86   vpx_free(cm->postproc_state.generated_noise);
     87   cm->postproc_state.generated_noise = NULL;
     88 #else
     89   (void)cm;
     90 #endif
     91 }
     92 
     93 void vp9_free_context_buffers(VP9_COMMON *cm) {
     94   cm->free_mi(cm);
     95   free_seg_map(cm);
     96   vpx_free(cm->above_context);
     97   cm->above_context = NULL;
     98   vpx_free(cm->above_seg_context);
     99   cm->above_seg_context = NULL;
    100   vpx_free(cm->lf.lfm);
    101   cm->lf.lfm = NULL;
    102 }
    103 
    104 int vp9_alloc_loop_filter(VP9_COMMON *cm) {
    105   vpx_free(cm->lf.lfm);
    106   // Each lfm holds bit masks for all the 8x8 blocks in a 64x64 region.  The
    107   // stride and rows are rounded up / truncated to a multiple of 8.
    108   cm->lf.lfm_stride = (cm->mi_cols + (MI_BLOCK_SIZE - 1)) >> 3;
    109   cm->lf.lfm = (LOOP_FILTER_MASK *)vpx_calloc(
    110       ((cm->mi_rows + (MI_BLOCK_SIZE - 1)) >> 3) * cm->lf.lfm_stride,
    111       sizeof(*cm->lf.lfm));
    112   if (!cm->lf.lfm) return 1;
    113   return 0;
    114 }
    115 
    116 int vp9_alloc_context_buffers(VP9_COMMON *cm, int width, int height) {
    117   int new_mi_size;
    118 
    119   vp9_set_mb_mi(cm, width, height);
    120   new_mi_size = cm->mi_stride * calc_mi_size(cm->mi_rows);
    121   if (cm->mi_alloc_size < new_mi_size) {
    122     cm->free_mi(cm);
    123     if (cm->alloc_mi(cm, new_mi_size)) goto fail;
    124   }
    125 
    126   if (cm->seg_map_alloc_size < cm->mi_rows * cm->mi_cols) {
    127     // Create the segmentation map structure and set to 0.
    128     free_seg_map(cm);
    129     if (alloc_seg_map(cm, cm->mi_rows * cm->mi_cols)) goto fail;
    130   }
    131 
    132   if (cm->above_context_alloc_cols < cm->mi_cols) {
    133     vpx_free(cm->above_context);
    134     cm->above_context = (ENTROPY_CONTEXT *)vpx_calloc(
    135         2 * mi_cols_aligned_to_sb(cm->mi_cols) * MAX_MB_PLANE,
    136         sizeof(*cm->above_context));
    137     if (!cm->above_context) goto fail;
    138 
    139     vpx_free(cm->above_seg_context);
    140     cm->above_seg_context = (PARTITION_CONTEXT *)vpx_calloc(
    141         mi_cols_aligned_to_sb(cm->mi_cols), sizeof(*cm->above_seg_context));
    142     if (!cm->above_seg_context) goto fail;
    143     cm->above_context_alloc_cols = cm->mi_cols;
    144   }
    145 
    146   if (vp9_alloc_loop_filter(cm)) goto fail;
    147 
    148   return 0;
    149 
    150 fail:
    151   // clear the mi_* values to force a realloc on resync
    152   vp9_set_mb_mi(cm, 0, 0);
    153   vp9_free_context_buffers(cm);
    154   return 1;
    155 }
    156 
    157 void vp9_remove_common(VP9_COMMON *cm) {
    158 #if CONFIG_VP9_POSTPROC
    159   vp9_free_postproc_buffers(cm);
    160 #endif
    161   vp9_free_context_buffers(cm);
    162 
    163   vpx_free(cm->fc);
    164   cm->fc = NULL;
    165   vpx_free(cm->frame_contexts);
    166   cm->frame_contexts = NULL;
    167 }
    168 
    169 void vp9_init_context_buffers(VP9_COMMON *cm) {
    170   cm->setup_mi(cm);
    171   if (cm->last_frame_seg_map)
    172     memset(cm->last_frame_seg_map, 0, cm->mi_rows * cm->mi_cols);
    173 }
    174 
    175 void vp9_swap_current_and_last_seg_map(VP9_COMMON *cm) {
    176   // Swap indices.
    177   const int tmp = cm->seg_map_idx;
    178   cm->seg_map_idx = cm->prev_seg_map_idx;
    179   cm->prev_seg_map_idx = tmp;
    180 
    181   cm->current_frame_seg_map = cm->seg_map_array[cm->seg_map_idx];
    182   cm->last_frame_seg_map = cm->seg_map_array[cm->prev_seg_map_idx];
    183 }
    184