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_blockd.h" 15#include "vp9/common/vp9_entropymode.h" 16#include "vp9/common/vp9_entropymv.h" 17#include "vp9/common/vp9_onyxc_int.h" 18#include "vp9/common/vp9_systemdependent.h" 19 20static void clear_mi_border(const VP9_COMMON *cm, MODE_INFO *mi) { 21 int i; 22 23 // Top border row 24 vpx_memset(mi, 0, sizeof(*mi) * cm->mi_stride); 25 26 // Left border column 27 for (i = 1; i < cm->mi_rows + 1; ++i) 28 vpx_memset(&mi[i * cm->mi_stride], 0, sizeof(*mi)); 29} 30 31void vp9_set_mb_mi(VP9_COMMON *cm, int width, int height) { 32 const int aligned_width = ALIGN_POWER_OF_TWO(width, MI_SIZE_LOG2); 33 const int aligned_height = ALIGN_POWER_OF_TWO(height, MI_SIZE_LOG2); 34 35 cm->mi_cols = aligned_width >> MI_SIZE_LOG2; 36 cm->mi_rows = aligned_height >> MI_SIZE_LOG2; 37 cm->mi_stride = calc_mi_size(cm->mi_cols); 38 39 cm->mb_cols = (cm->mi_cols + 1) >> 1; 40 cm->mb_rows = (cm->mi_rows + 1) >> 1; 41 cm->MBs = cm->mb_rows * cm->mb_cols; 42} 43 44static void setup_mi(VP9_COMMON *cm) { 45 cm->mi = cm->mip + cm->mi_stride + 1; 46 cm->prev_mi = cm->prev_mip + cm->mi_stride + 1; 47 48 vpx_memset(cm->mip, 0, cm->mi_stride * (cm->mi_rows + 1) * sizeof(*cm->mip)); 49 clear_mi_border(cm, cm->prev_mip); 50} 51 52static int alloc_mi(VP9_COMMON *cm, int mi_size) { 53 int i; 54 55 for (i = 0; i < 2; ++i) { 56 cm->mip_array[i] = 57 (MODE_INFO *)vpx_calloc(mi_size, sizeof(MODE_INFO)); 58 if (cm->mip_array[i] == NULL) 59 return 1; 60 } 61 62 cm->mi_alloc_size = mi_size; 63 64 // Init the index. 65 cm->mi_idx = 0; 66 cm->prev_mi_idx = 1; 67 68 cm->mip = cm->mip_array[cm->mi_idx]; 69 cm->prev_mip = cm->mip_array[cm->prev_mi_idx]; 70 71 return 0; 72} 73 74static void free_mi(VP9_COMMON *cm) { 75 int i; 76 77 for (i = 0; i < 2; ++i) { 78 vpx_free(cm->mip_array[i]); 79 cm->mip_array[i] = NULL; 80 } 81 82 cm->mip = NULL; 83 cm->prev_mip = NULL; 84} 85 86void vp9_free_ref_frame_buffers(VP9_COMMON *cm) { 87 int i; 88 89 for (i = 0; i < FRAME_BUFFERS; ++i) { 90 vp9_free_frame_buffer(&cm->frame_bufs[i].buf); 91 92 if (cm->frame_bufs[i].ref_count > 0 && 93 cm->frame_bufs[i].raw_frame_buffer.data != NULL) { 94 cm->release_fb_cb(cm->cb_priv, &cm->frame_bufs[i].raw_frame_buffer); 95 cm->frame_bufs[i].ref_count = 0; 96 } 97 } 98 99 vp9_free_frame_buffer(&cm->post_proc_buffer); 100} 101 102void vp9_free_context_buffers(VP9_COMMON *cm) { 103 free_mi(cm); 104 105 vpx_free(cm->last_frame_seg_map); 106 cm->last_frame_seg_map = NULL; 107 108 vpx_free(cm->above_context); 109 cm->above_context = NULL; 110 111 vpx_free(cm->above_seg_context); 112 cm->above_seg_context = NULL; 113} 114 115int vp9_alloc_context_buffers(VP9_COMMON *cm, int width, int height) { 116 vp9_free_context_buffers(cm); 117 118 vp9_set_mb_mi(cm, width, height); 119 if (alloc_mi(cm, cm->mi_stride * calc_mi_size(cm->mi_rows))) 120 goto fail; 121 122 cm->last_frame_seg_map = (uint8_t *)vpx_calloc(cm->mi_rows * cm->mi_cols, 1); 123 if (!cm->last_frame_seg_map) goto fail; 124 125 cm->above_context = (ENTROPY_CONTEXT *)vpx_calloc( 126 2 * mi_cols_aligned_to_sb(cm->mi_cols) * MAX_MB_PLANE, 127 sizeof(*cm->above_context)); 128 if (!cm->above_context) goto fail; 129 130 cm->above_seg_context = (PARTITION_CONTEXT *)vpx_calloc( 131 mi_cols_aligned_to_sb(cm->mi_cols), sizeof(*cm->above_seg_context)); 132 if (!cm->above_seg_context) goto fail; 133 134 return 0; 135 136 fail: 137 vp9_free_context_buffers(cm); 138 return 1; 139} 140 141static void init_frame_bufs(VP9_COMMON *cm) { 142 int i; 143 144 cm->new_fb_idx = FRAME_BUFFERS - 1; 145 cm->frame_bufs[cm->new_fb_idx].ref_count = 1; 146 147 for (i = 0; i < REF_FRAMES; ++i) { 148 cm->ref_frame_map[i] = i; 149 cm->frame_bufs[i].ref_count = 1; 150 } 151} 152 153int vp9_alloc_ref_frame_buffers(VP9_COMMON *cm, int width, int height) { 154 int i; 155 const int ss_x = cm->subsampling_x; 156 const int ss_y = cm->subsampling_y; 157 158 vp9_free_ref_frame_buffers(cm); 159 160 for (i = 0; i < FRAME_BUFFERS; ++i) { 161 cm->frame_bufs[i].ref_count = 0; 162 if (vp9_alloc_frame_buffer(&cm->frame_bufs[i].buf, width, height, 163 ss_x, ss_y, 164#if CONFIG_VP9_HIGHBITDEPTH 165 cm->use_highbitdepth, 166#endif 167 VP9_ENC_BORDER_IN_PIXELS) < 0) 168 goto fail; 169 } 170 171 init_frame_bufs(cm); 172 173#if CONFIG_INTERNAL_STATS || CONFIG_VP9_POSTPROC 174 if (vp9_alloc_frame_buffer(&cm->post_proc_buffer, width, height, ss_x, ss_y, 175#if CONFIG_VP9_HIGHBITDEPTH 176 cm->use_highbitdepth, 177#endif 178 VP9_ENC_BORDER_IN_PIXELS) < 0) 179 goto fail; 180#endif 181 182 return 0; 183 184 fail: 185 vp9_free_ref_frame_buffers(cm); 186 return 1; 187} 188 189void vp9_remove_common(VP9_COMMON *cm) { 190 vp9_free_ref_frame_buffers(cm); 191 vp9_free_context_buffers(cm); 192 vp9_free_internal_frame_buffers(&cm->int_frame_buffers); 193} 194 195void vp9_init_context_buffers(VP9_COMMON *cm) { 196 setup_mi(cm); 197 if (cm->last_frame_seg_map) 198 vpx_memset(cm->last_frame_seg_map, 0, cm->mi_rows * cm->mi_cols); 199} 200 201void vp9_swap_mi_and_prev_mi(VP9_COMMON *cm) { 202 // Swap indices. 203 const int tmp = cm->mi_idx; 204 cm->mi_idx = cm->prev_mi_idx; 205 cm->prev_mi_idx = tmp; 206 207 // Current mip will be the prev_mip for the next frame. 208 cm->mip = cm->mip_array[cm->mi_idx]; 209 cm->prev_mip = cm->mip_array[cm->prev_mi_idx]; 210 211 // Update the upper left visible macroblock ptrs. 212 cm->mi = cm->mip + cm->mi_stride + 1; 213 cm->prev_mi = cm->prev_mip + cm->mi_stride + 1; 214} 215