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 31static void set_mb_mi(VP9_COMMON *cm, int aligned_width, int aligned_height) { 32 cm->mi_cols = aligned_width >> MI_SIZE_LOG2; 33 cm->mi_rows = aligned_height >> MI_SIZE_LOG2; 34 cm->mi_stride = cm->mi_cols + MI_BLOCK_SIZE; 35 36 cm->mb_cols = (cm->mi_cols + 1) >> 1; 37 cm->mb_rows = (cm->mi_rows + 1) >> 1; 38 cm->MBs = cm->mb_rows * cm->mb_cols; 39} 40 41static void setup_mi(VP9_COMMON *cm) { 42 cm->mi = cm->mip + cm->mi_stride + 1; 43 cm->prev_mi = cm->prev_mip + cm->mi_stride + 1; 44 cm->mi_grid_visible = cm->mi_grid_base + cm->mi_stride + 1; 45 cm->prev_mi_grid_visible = cm->prev_mi_grid_base + cm->mi_stride + 1; 46 47 vpx_memset(cm->mip, 0, cm->mi_stride * (cm->mi_rows + 1) * sizeof(*cm->mip)); 48 49 vpx_memset(cm->mi_grid_base, 0, cm->mi_stride * (cm->mi_rows + 1) * 50 sizeof(*cm->mi_grid_base)); 51 52 clear_mi_border(cm, cm->prev_mip); 53} 54 55static int alloc_mi(VP9_COMMON *cm, int mi_size) { 56 cm->mip = (MODE_INFO *)vpx_calloc(mi_size, sizeof(*cm->mip)); 57 if (cm->mip == NULL) 58 return 1; 59 60 cm->prev_mip = (MODE_INFO *)vpx_calloc(mi_size, sizeof(*cm->prev_mip)); 61 if (cm->prev_mip == NULL) 62 return 1; 63 64 cm->mi_grid_base = 65 (MODE_INFO **)vpx_calloc(mi_size, sizeof(*cm->mi_grid_base)); 66 if (cm->mi_grid_base == NULL) 67 return 1; 68 69 cm->prev_mi_grid_base = 70 (MODE_INFO **)vpx_calloc(mi_size, sizeof(*cm->prev_mi_grid_base)); 71 if (cm->prev_mi_grid_base == NULL) 72 return 1; 73 74 return 0; 75} 76 77static void free_mi(VP9_COMMON *cm) { 78 vpx_free(cm->mip); 79 vpx_free(cm->prev_mip); 80 vpx_free(cm->mi_grid_base); 81 vpx_free(cm->prev_mi_grid_base); 82 83 cm->mip = NULL; 84 cm->prev_mip = NULL; 85 cm->mi_grid_base = NULL; 86 cm->prev_mi_grid_base = NULL; 87} 88 89void vp9_free_frame_buffers(VP9_COMMON *cm) { 90 int i; 91 92 for (i = 0; i < FRAME_BUFFERS; ++i) { 93 vp9_free_frame_buffer(&cm->frame_bufs[i].buf); 94 95 if (cm->frame_bufs[i].ref_count > 0 && 96 cm->frame_bufs[i].raw_frame_buffer.data != NULL) { 97 cm->release_fb_cb(cm->cb_priv, &cm->frame_bufs[i].raw_frame_buffer); 98 cm->frame_bufs[i].ref_count = 0; 99 } 100 } 101 102 vp9_free_frame_buffer(&cm->post_proc_buffer); 103 104 free_mi(cm); 105 106 vpx_free(cm->last_frame_seg_map); 107 cm->last_frame_seg_map = NULL; 108 109 vpx_free(cm->above_context); 110 cm->above_context = NULL; 111 112 vpx_free(cm->above_seg_context); 113 cm->above_seg_context = NULL; 114} 115 116int vp9_resize_frame_buffers(VP9_COMMON *cm, int width, int height) { 117 const int aligned_width = ALIGN_POWER_OF_TWO(width, MI_SIZE_LOG2); 118 const int aligned_height = ALIGN_POWER_OF_TWO(height, MI_SIZE_LOG2); 119 const int ss_x = cm->subsampling_x; 120 const int ss_y = cm->subsampling_y; 121 122 if (vp9_realloc_frame_buffer(&cm->post_proc_buffer, width, height, ss_x, ss_y, 123 VP9_DEC_BORDER_IN_PIXELS, NULL, NULL, NULL) < 0) 124 goto fail; 125 126 set_mb_mi(cm, aligned_width, aligned_height); 127 128 free_mi(cm); 129 if (alloc_mi(cm, cm->mi_stride * (cm->mi_rows + MI_BLOCK_SIZE))) 130 goto fail; 131 132 setup_mi(cm); 133 134 // Create the segmentation map structure and set to 0. 135 vpx_free(cm->last_frame_seg_map); 136 cm->last_frame_seg_map = (uint8_t *)vpx_calloc(cm->mi_rows * cm->mi_cols, 1); 137 if (!cm->last_frame_seg_map) 138 goto fail; 139 140 vpx_free(cm->above_context); 141 cm->above_context = 142 (ENTROPY_CONTEXT *)vpx_calloc(2 * mi_cols_aligned_to_sb(cm->mi_cols) * 143 MAX_MB_PLANE, 144 sizeof(*cm->above_context)); 145 if (!cm->above_context) 146 goto fail; 147 148 vpx_free(cm->above_seg_context); 149 cm->above_seg_context = 150 (PARTITION_CONTEXT *)vpx_calloc(mi_cols_aligned_to_sb(cm->mi_cols), 151 sizeof(*cm->above_seg_context)); 152 if (!cm->above_seg_context) 153 goto fail; 154 155 return 0; 156 157 fail: 158 vp9_free_frame_buffers(cm); 159 return 1; 160} 161 162int vp9_alloc_frame_buffers(VP9_COMMON *cm, int width, int height) { 163 const int aligned_width = ALIGN_POWER_OF_TWO(width, MI_SIZE_LOG2); 164 const int aligned_height = ALIGN_POWER_OF_TWO(height, MI_SIZE_LOG2); 165 const int ss_x = cm->subsampling_x; 166 const int ss_y = cm->subsampling_y; 167 int i; 168 169 vp9_free_frame_buffers(cm); 170 171 for (i = 0; i < FRAME_BUFFERS; i++) { 172 cm->frame_bufs[i].ref_count = 0; 173 if (vp9_alloc_frame_buffer(&cm->frame_bufs[i].buf, width, height, 174 ss_x, ss_y, VP9_ENC_BORDER_IN_PIXELS) < 0) 175 goto fail; 176 } 177 178 cm->new_fb_idx = FRAME_BUFFERS - 1; 179 cm->frame_bufs[cm->new_fb_idx].ref_count = 1; 180 181 for (i = 0; i < REF_FRAMES; i++) { 182 cm->ref_frame_map[i] = i; 183 cm->frame_bufs[i].ref_count = 1; 184 } 185 186 if (vp9_alloc_frame_buffer(&cm->post_proc_buffer, width, height, ss_x, ss_y, 187 VP9_ENC_BORDER_IN_PIXELS) < 0) 188 goto fail; 189 190 set_mb_mi(cm, aligned_width, aligned_height); 191 192 if (alloc_mi(cm, cm->mi_stride * (cm->mi_rows + MI_BLOCK_SIZE))) 193 goto fail; 194 195 setup_mi(cm); 196 197 // Create the segmentation map structure and set to 0. 198 cm->last_frame_seg_map = (uint8_t *)vpx_calloc(cm->mi_rows * cm->mi_cols, 1); 199 if (!cm->last_frame_seg_map) 200 goto fail; 201 202 cm->above_context = 203 (ENTROPY_CONTEXT *)vpx_calloc(2 * mi_cols_aligned_to_sb(cm->mi_cols) * 204 MAX_MB_PLANE, 205 sizeof(*cm->above_context)); 206 if (!cm->above_context) 207 goto fail; 208 209 cm->above_seg_context = 210 (PARTITION_CONTEXT *)vpx_calloc(mi_cols_aligned_to_sb(cm->mi_cols), 211 sizeof(*cm->above_seg_context)); 212 if (!cm->above_seg_context) 213 goto fail; 214 215 return 0; 216 217 fail: 218 vp9_free_frame_buffers(cm); 219 return 1; 220} 221 222void vp9_remove_common(VP9_COMMON *cm) { 223 vp9_free_frame_buffers(cm); 224 vp9_free_internal_frame_buffers(&cm->int_frame_buffers); 225} 226 227void vp9_update_frame_size(VP9_COMMON *cm) { 228 const int aligned_width = ALIGN_POWER_OF_TWO(cm->width, MI_SIZE_LOG2); 229 const int aligned_height = ALIGN_POWER_OF_TWO(cm->height, MI_SIZE_LOG2); 230 231 set_mb_mi(cm, aligned_width, aligned_height); 232 setup_mi(cm); 233 234 // Initialize the previous frame segment map to 0. 235 if (cm->last_frame_seg_map) 236 vpx_memset(cm->last_frame_seg_map, 0, cm->mi_rows * cm->mi_cols); 237} 238 239void vp9_swap_mi_and_prev_mi(VP9_COMMON *cm) { 240 // Current mip will be the prev_mip for the next frame. 241 MODE_INFO *temp = cm->prev_mip; 242 MODE_INFO **temp2 = cm->prev_mi_grid_base; 243 cm->prev_mip = cm->mip; 244 cm->mip = temp; 245 cm->prev_mi_grid_base = cm->mi_grid_base; 246 cm->mi_grid_base = temp2; 247 248 // Update the upper left visible macroblock ptrs. 249 cm->mi = cm->mip + cm->mi_stride + 1; 250 cm->prev_mi = cm->prev_mip + cm->mi_stride + 1; 251 cm->mi_grid_visible = cm->mi_grid_base + cm->mi_stride + 1; 252 cm->prev_mi_grid_visible = cm->prev_mi_grid_base + cm->mi_stride + 1; 253} 254