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
12#include "./vpx_config.h"
13#include "vpx_mem/vpx_mem.h"
14
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_findnearmv.h"
19#include "vp9/common/vp9_onyxc_int.h"
20#include "vp9/common/vp9_systemdependent.h"
21
22void vp9_update_mode_info_border(VP9_COMMON *cm, MODE_INFO *mi) {
23  const int stride = cm->mode_info_stride;
24  int i;
25
26  // Clear down top border row
27  vpx_memset(mi, 0, sizeof(MODE_INFO) * stride);
28
29  // Clear left border column
30  for (i = 1; i < cm->mi_rows + 1; i++)
31    vpx_memset(&mi[i * stride], 0, sizeof(MODE_INFO));
32}
33
34void vp9_free_frame_buffers(VP9_COMMON *cm) {
35  int i;
36
37  for (i = 0; i < NUM_YV12_BUFFERS; i++)
38    vp9_free_frame_buffer(&cm->yv12_fb[i]);
39
40  vp9_free_frame_buffer(&cm->post_proc_buffer);
41
42  vpx_free(cm->mip);
43  vpx_free(cm->prev_mip);
44  vpx_free(cm->last_frame_seg_map);
45  vpx_free(cm->mi_grid_base);
46  vpx_free(cm->prev_mi_grid_base);
47
48  cm->mip = NULL;
49  cm->prev_mip = NULL;
50  cm->last_frame_seg_map = NULL;
51  cm->mi_grid_base = NULL;
52  cm->prev_mi_grid_base = NULL;
53}
54
55static void set_mb_mi(VP9_COMMON *cm, int aligned_width, int aligned_height) {
56  cm->mi_cols = aligned_width >> MI_SIZE_LOG2;
57  cm->mi_rows = aligned_height >> MI_SIZE_LOG2;
58  cm->mode_info_stride = cm->mi_cols + MI_BLOCK_SIZE;
59
60  cm->mb_cols = (cm->mi_cols + 1) >> 1;
61  cm->mb_rows = (cm->mi_rows + 1) >> 1;
62  cm->MBs = cm->mb_rows * cm->mb_cols;
63}
64
65static void setup_mi(VP9_COMMON *cm) {
66  cm->mi = cm->mip + cm->mode_info_stride + 1;
67  cm->prev_mi = cm->prev_mip + cm->mode_info_stride + 1;
68  cm->mi_grid_visible = cm->mi_grid_base + cm->mode_info_stride + 1;
69  cm->prev_mi_grid_visible = cm->prev_mi_grid_base + cm->mode_info_stride + 1;
70
71  vpx_memset(cm->mip, 0,
72             cm->mode_info_stride * (cm->mi_rows + 1) * sizeof(MODE_INFO));
73
74  vpx_memset(cm->mi_grid_base, 0,
75             cm->mode_info_stride * (cm->mi_rows + 1) *
76             sizeof(*cm->mi_grid_base));
77
78  vp9_update_mode_info_border(cm, cm->mip);
79  vp9_update_mode_info_border(cm, cm->prev_mip);
80}
81
82int vp9_resize_frame_buffers(VP9_COMMON *cm, int width, int height) {
83  const int aligned_width = ALIGN_POWER_OF_TWO(width, MI_SIZE_LOG2);
84  const int aligned_height = ALIGN_POWER_OF_TWO(height, MI_SIZE_LOG2);
85  const int ss_x = cm->subsampling_x;
86  const int ss_y = cm->subsampling_y;
87  int mi_size;
88
89  if (vp9_realloc_frame_buffer(&cm->post_proc_buffer, width, height, ss_x, ss_y,
90                             VP9BORDERINPIXELS) < 0)
91    goto fail;
92
93  set_mb_mi(cm, aligned_width, aligned_height);
94
95  // Allocation
96  mi_size = cm->mode_info_stride * (cm->mi_rows + MI_BLOCK_SIZE);
97
98  vpx_free(cm->mip);
99  cm->mip = vpx_calloc(mi_size, sizeof(MODE_INFO));
100  if (!cm->mip)
101    goto fail;
102
103  vpx_free(cm->prev_mip);
104  cm->prev_mip = vpx_calloc(mi_size, sizeof(MODE_INFO));
105  if (!cm->prev_mip)
106    goto fail;
107
108  vpx_free(cm->mi_grid_base);
109  cm->mi_grid_base = vpx_calloc(mi_size, sizeof(*cm->mi_grid_base));
110  if (!cm->mi_grid_base)
111    goto fail;
112
113  vpx_free(cm->prev_mi_grid_base);
114  cm->prev_mi_grid_base = vpx_calloc(mi_size, sizeof(*cm->prev_mi_grid_base));
115  if (!cm->prev_mi_grid_base)
116    goto fail;
117
118  setup_mi(cm);
119
120  // Create the segmentation map structure and set to 0.
121  vpx_free(cm->last_frame_seg_map);
122  cm->last_frame_seg_map = vpx_calloc(cm->mi_rows * cm->mi_cols, 1);
123  if (!cm->last_frame_seg_map)
124    goto fail;
125
126  return 0;
127
128 fail:
129  vp9_free_frame_buffers(cm);
130  return 1;
131}
132
133int vp9_alloc_frame_buffers(VP9_COMMON *cm, int width, int height) {
134  int i;
135
136  const int aligned_width = ALIGN_POWER_OF_TWO(width, MI_SIZE_LOG2);
137  const int aligned_height = ALIGN_POWER_OF_TWO(height, MI_SIZE_LOG2);
138  const int ss_x = cm->subsampling_x;
139  const int ss_y = cm->subsampling_y;
140  int mi_size;
141
142  vp9_free_frame_buffers(cm);
143
144  for (i = 0; i < NUM_YV12_BUFFERS; i++) {
145    cm->fb_idx_ref_cnt[i] = 0;
146    if (vp9_alloc_frame_buffer(&cm->yv12_fb[i], width, height, ss_x, ss_y,
147                               VP9BORDERINPIXELS) < 0)
148      goto fail;
149  }
150
151  cm->new_fb_idx = NUM_YV12_BUFFERS - 1;
152  cm->fb_idx_ref_cnt[cm->new_fb_idx] = 1;
153
154  for (i = 0; i < ALLOWED_REFS_PER_FRAME; i++)
155    cm->active_ref_idx[i] = i;
156
157  for (i = 0; i < NUM_REF_FRAMES; i++) {
158    cm->ref_frame_map[i] = i;
159    cm->fb_idx_ref_cnt[i] = 1;
160  }
161
162  if (vp9_alloc_frame_buffer(&cm->post_proc_buffer, width, height, ss_x, ss_y,
163                             VP9BORDERINPIXELS) < 0)
164    goto fail;
165
166  set_mb_mi(cm, aligned_width, aligned_height);
167
168  // Allocation
169  mi_size = cm->mode_info_stride * (cm->mi_rows + MI_BLOCK_SIZE);
170
171  cm->mip = vpx_calloc(mi_size, sizeof(MODE_INFO));
172  if (!cm->mip)
173    goto fail;
174
175  cm->prev_mip = vpx_calloc(mi_size, sizeof(MODE_INFO));
176  if (!cm->prev_mip)
177    goto fail;
178
179  cm->mi_grid_base = vpx_calloc(mi_size, sizeof(*cm->mi_grid_base));
180  if (!cm->mi_grid_base)
181    goto fail;
182
183  cm->prev_mi_grid_base = vpx_calloc(mi_size, sizeof(*cm->prev_mi_grid_base));
184  if (!cm->prev_mi_grid_base)
185    goto fail;
186
187  setup_mi(cm);
188
189  // Create the segmentation map structure and set to 0.
190  cm->last_frame_seg_map = vpx_calloc(cm->mi_rows * cm->mi_cols, 1);
191  if (!cm->last_frame_seg_map)
192    goto fail;
193
194  return 0;
195
196 fail:
197  vp9_free_frame_buffers(cm);
198  return 1;
199}
200
201void vp9_create_common(VP9_COMMON *cm) {
202  vp9_machine_specific_config(cm);
203
204  cm->tx_mode = ONLY_4X4;
205  cm->comp_pred_mode = HYBRID_PREDICTION;
206}
207
208void vp9_remove_common(VP9_COMMON *cm) {
209  vp9_free_frame_buffers(cm);
210}
211
212void vp9_initialize_common() {
213  vp9_init_neighbors();
214  vp9_coef_tree_initialize();
215  vp9_entropy_mode_init();
216  vp9_entropy_mv_init();
217}
218
219void vp9_update_frame_size(VP9_COMMON *cm) {
220  const int aligned_width = ALIGN_POWER_OF_TWO(cm->width, MI_SIZE_LOG2);
221  const int aligned_height = ALIGN_POWER_OF_TWO(cm->height, MI_SIZE_LOG2);
222
223  set_mb_mi(cm, aligned_width, aligned_height);
224  setup_mi(cm);
225
226  // Initialize the previous frame segment map to 0.
227  if (cm->last_frame_seg_map)
228    vpx_memset(cm->last_frame_seg_map, 0, cm->mi_rows * cm->mi_cols);
229}
230