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