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 <assert.h> 12 #include <limits.h> 13 #include <stdio.h> 14 15 #include "./vpx_scale_rtcd.h" 16 17 #include "vpx_mem/vpx_mem.h" 18 #include "vpx_ports/vpx_timer.h" 19 #include "vpx_scale/vpx_scale.h" 20 21 #include "vp9/common/vp9_alloccommon.h" 22 #include "vp9/common/vp9_loopfilter.h" 23 #include "vp9/common/vp9_onyxc_int.h" 24 #if CONFIG_VP9_POSTPROC 25 #include "vp9/common/vp9_postproc.h" 26 #endif 27 #include "vp9/common/vp9_quant_common.h" 28 #include "vp9/common/vp9_systemdependent.h" 29 30 #include "vp9/decoder/vp9_decodeframe.h" 31 #include "vp9/decoder/vp9_decoder.h" 32 #include "vp9/decoder/vp9_detokenize.h" 33 #include "vp9/decoder/vp9_dthread.h" 34 35 static void initialize_dec() { 36 static int init_done = 0; 37 38 if (!init_done) { 39 vp9_init_neighbors(); 40 init_done = 1; 41 } 42 } 43 44 VP9Decoder *vp9_decoder_create() { 45 VP9Decoder *const pbi = vpx_memalign(32, sizeof(*pbi)); 46 VP9_COMMON *const cm = pbi ? &pbi->common : NULL; 47 48 if (!cm) 49 return NULL; 50 51 vp9_zero(*pbi); 52 53 if (setjmp(cm->error.jmp)) { 54 cm->error.setjmp = 0; 55 vp9_decoder_remove(pbi); 56 return NULL; 57 } 58 59 cm->error.setjmp = 1; 60 initialize_dec(); 61 62 vp9_rtcd(); 63 64 // Initialize the references to not point to any frame buffers. 65 vpx_memset(&cm->ref_frame_map, -1, sizeof(cm->ref_frame_map)); 66 67 cm->current_video_frame = 0; 68 pbi->ready_for_new_data = 1; 69 70 // vp9_init_dequantizer() is first called here. Add check in 71 // frame_init_dequantizer() to avoid unnecessary calling of 72 // vp9_init_dequantizer() for every frame. 73 vp9_init_dequantizer(cm); 74 75 vp9_loop_filter_init(cm); 76 77 cm->error.setjmp = 0; 78 79 vp9_get_worker_interface()->init(&pbi->lf_worker); 80 81 return pbi; 82 } 83 84 void vp9_decoder_remove(VP9Decoder *pbi) { 85 VP9_COMMON *const cm = &pbi->common; 86 int i; 87 88 vp9_get_worker_interface()->end(&pbi->lf_worker); 89 vpx_free(pbi->lf_worker.data1); 90 vpx_free(pbi->tile_data); 91 for (i = 0; i < pbi->num_tile_workers; ++i) { 92 VP9Worker *const worker = &pbi->tile_workers[i]; 93 vp9_get_worker_interface()->end(worker); 94 vpx_free(worker->data1); 95 vpx_free(worker->data2); 96 } 97 vpx_free(pbi->tile_workers); 98 99 if (pbi->num_tile_workers) { 100 const int sb_rows = 101 mi_cols_aligned_to_sb(cm->mi_rows) >> MI_BLOCK_SIZE_LOG2; 102 vp9_loop_filter_dealloc(&pbi->lf_row_sync, sb_rows); 103 } 104 105 vp9_remove_common(cm); 106 vpx_free(pbi); 107 } 108 109 static int equal_dimensions(const YV12_BUFFER_CONFIG *a, 110 const YV12_BUFFER_CONFIG *b) { 111 return a->y_height == b->y_height && a->y_width == b->y_width && 112 a->uv_height == b->uv_height && a->uv_width == b->uv_width; 113 } 114 115 vpx_codec_err_t vp9_copy_reference_dec(VP9Decoder *pbi, 116 VP9_REFFRAME ref_frame_flag, 117 YV12_BUFFER_CONFIG *sd) { 118 VP9_COMMON *cm = &pbi->common; 119 120 /* TODO(jkoleszar): The decoder doesn't have any real knowledge of what the 121 * encoder is using the frame buffers for. This is just a stub to keep the 122 * vpxenc --test-decode functionality working, and will be replaced in a 123 * later commit that adds VP9-specific controls for this functionality. 124 */ 125 if (ref_frame_flag == VP9_LAST_FLAG) { 126 const YV12_BUFFER_CONFIG *const cfg = 127 &cm->frame_bufs[cm->ref_frame_map[0]].buf; 128 if (!equal_dimensions(cfg, sd)) 129 vpx_internal_error(&cm->error, VPX_CODEC_ERROR, 130 "Incorrect buffer dimensions"); 131 else 132 vp8_yv12_copy_frame(cfg, sd); 133 } else { 134 vpx_internal_error(&cm->error, VPX_CODEC_ERROR, 135 "Invalid reference frame"); 136 } 137 138 return cm->error.error_code; 139 } 140 141 142 vpx_codec_err_t vp9_set_reference_dec(VP9_COMMON *cm, 143 VP9_REFFRAME ref_frame_flag, 144 YV12_BUFFER_CONFIG *sd) { 145 RefBuffer *ref_buf = NULL; 146 147 // TODO(jkoleszar): The decoder doesn't have any real knowledge of what the 148 // encoder is using the frame buffers for. This is just a stub to keep the 149 // vpxenc --test-decode functionality working, and will be replaced in a 150 // later commit that adds VP9-specific controls for this functionality. 151 if (ref_frame_flag == VP9_LAST_FLAG) { 152 ref_buf = &cm->frame_refs[0]; 153 } else if (ref_frame_flag == VP9_GOLD_FLAG) { 154 ref_buf = &cm->frame_refs[1]; 155 } else if (ref_frame_flag == VP9_ALT_FLAG) { 156 ref_buf = &cm->frame_refs[2]; 157 } else { 158 vpx_internal_error(&cm->error, VPX_CODEC_ERROR, 159 "Invalid reference frame"); 160 return cm->error.error_code; 161 } 162 163 if (!equal_dimensions(ref_buf->buf, sd)) { 164 vpx_internal_error(&cm->error, VPX_CODEC_ERROR, 165 "Incorrect buffer dimensions"); 166 } else { 167 int *ref_fb_ptr = &ref_buf->idx; 168 169 // Find an empty frame buffer. 170 const int free_fb = get_free_fb(cm); 171 // Decrease ref_count since it will be increased again in 172 // ref_cnt_fb() below. 173 cm->frame_bufs[free_fb].ref_count--; 174 175 // Manage the reference counters and copy image. 176 ref_cnt_fb(cm->frame_bufs, ref_fb_ptr, free_fb); 177 ref_buf->buf = &cm->frame_bufs[*ref_fb_ptr].buf; 178 vp8_yv12_copy_frame(sd, ref_buf->buf); 179 } 180 181 return cm->error.error_code; 182 } 183 184 /* If any buffer updating is signaled it should be done here. */ 185 static void swap_frame_buffers(VP9Decoder *pbi) { 186 int ref_index = 0, mask; 187 VP9_COMMON *const cm = &pbi->common; 188 189 for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) { 190 if (mask & 1) { 191 const int old_idx = cm->ref_frame_map[ref_index]; 192 ref_cnt_fb(cm->frame_bufs, &cm->ref_frame_map[ref_index], 193 cm->new_fb_idx); 194 if (old_idx >= 0 && cm->frame_bufs[old_idx].ref_count == 0) 195 cm->release_fb_cb(cm->cb_priv, 196 &cm->frame_bufs[old_idx].raw_frame_buffer); 197 } 198 ++ref_index; 199 } 200 201 cm->frame_to_show = get_frame_new_buffer(cm); 202 cm->frame_bufs[cm->new_fb_idx].ref_count--; 203 204 // Invalidate these references until the next frame starts. 205 for (ref_index = 0; ref_index < 3; ref_index++) 206 cm->frame_refs[ref_index].idx = INT_MAX; 207 } 208 209 int vp9_receive_compressed_data(VP9Decoder *pbi, 210 size_t size, const uint8_t **psource) { 211 VP9_COMMON *const cm = &pbi->common; 212 const uint8_t *source = *psource; 213 int retcode = 0; 214 215 cm->error.error_code = VPX_CODEC_OK; 216 217 if (size == 0) { 218 // This is used to signal that we are missing frames. 219 // We do not know if the missing frame(s) was supposed to update 220 // any of the reference buffers, but we act conservative and 221 // mark only the last buffer as corrupted. 222 // 223 // TODO(jkoleszar): Error concealment is undefined and non-normative 224 // at this point, but if it becomes so, [0] may not always be the correct 225 // thing to do here. 226 if (cm->frame_refs[0].idx != INT_MAX) 227 cm->frame_refs[0].buf->corrupted = 1; 228 } 229 230 // Check if the previous frame was a frame without any references to it. 231 if (cm->new_fb_idx >= 0 && cm->frame_bufs[cm->new_fb_idx].ref_count == 0) 232 cm->release_fb_cb(cm->cb_priv, 233 &cm->frame_bufs[cm->new_fb_idx].raw_frame_buffer); 234 cm->new_fb_idx = get_free_fb(cm); 235 236 if (setjmp(cm->error.jmp)) { 237 cm->error.setjmp = 0; 238 vp9_clear_system_state(); 239 240 // We do not know if the missing frame(s) was supposed to update 241 // any of the reference buffers, but we act conservative and 242 // mark only the last buffer as corrupted. 243 // 244 // TODO(jkoleszar): Error concealment is undefined and non-normative 245 // at this point, but if it becomes so, [0] may not always be the correct 246 // thing to do here. 247 if (cm->frame_refs[0].idx != INT_MAX && cm->frame_refs[0].buf != NULL) 248 cm->frame_refs[0].buf->corrupted = 1; 249 250 if (cm->new_fb_idx > 0 && cm->frame_bufs[cm->new_fb_idx].ref_count > 0) 251 cm->frame_bufs[cm->new_fb_idx].ref_count--; 252 253 return -1; 254 } 255 256 cm->error.setjmp = 1; 257 258 vp9_decode_frame(pbi, source, source + size, psource); 259 260 swap_frame_buffers(pbi); 261 262 vp9_clear_system_state(); 263 264 cm->last_width = cm->width; 265 cm->last_height = cm->height; 266 267 if (!cm->show_existing_frame) 268 cm->last_show_frame = cm->show_frame; 269 if (cm->show_frame) { 270 if (!cm->show_existing_frame) 271 vp9_swap_mi_and_prev_mi(cm); 272 273 cm->current_video_frame++; 274 } 275 276 pbi->ready_for_new_data = 0; 277 278 cm->error.setjmp = 0; 279 return retcode; 280 } 281 282 int vp9_get_raw_frame(VP9Decoder *pbi, YV12_BUFFER_CONFIG *sd, 283 vp9_ppflags_t *flags) { 284 VP9_COMMON *const cm = &pbi->common; 285 int ret = -1; 286 #if !CONFIG_VP9_POSTPROC 287 (void)*flags; 288 #endif 289 290 if (pbi->ready_for_new_data == 1) 291 return ret; 292 293 /* no raw frame to show!!! */ 294 if (!cm->show_frame) 295 return ret; 296 297 pbi->ready_for_new_data = 1; 298 299 #if CONFIG_VP9_POSTPROC 300 if (!cm->show_existing_frame) { 301 ret = vp9_post_proc_frame(cm, sd, flags); 302 } else { 303 *sd = *cm->frame_to_show; 304 ret = 0; 305 } 306 #else 307 *sd = *cm->frame_to_show; 308 ret = 0; 309 #endif /*!CONFIG_POSTPROC*/ 310 vp9_clear_system_state(); 311 return ret; 312 } 313