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