Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
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 */
11 #include <assert.h>
12 #include <limits.h>
13 #include <stdio.h>
15 #include "vp9/common/vp9_onyxc_int.h"
16 #if CONFIG_VP9_POSTPROC
17 #include "vp9/common/vp9_postproc.h"
18 #endif
19 #include "vp9/decoder/vp9_onyxd.h"
20 #include "vp9/decoder/vp9_onyxd_int.h"
21 #include "vpx_mem/vpx_mem.h"
22 #include "vp9/common/vp9_alloccommon.h"
23 #include "vp9/common/vp9_loopfilter.h"
24 #include "vp9/common/vp9_quant_common.h"
25 #include "vpx_scale/vpx_scale.h"
26 #include "vp9/common/vp9_systemdependent.h"
27 #include "vpx_ports/vpx_timer.h"
28 #include "vp9/decoder/vp9_decodframe.h"
29 #include "vp9/decoder/vp9_detokenize.h"
30 #include "./vpx_scale_rtcd.h"
32 #define WRITE_RECON_BUFFER 0
33 #if WRITE_RECON_BUFFER == 1
34 static void recon_write_yuv_frame(const char *name,
35 const YV12_BUFFER_CONFIG *s,
36 int w, int _h) {
37 FILE *yuv_file = fopen(name, "ab");
38 const uint8_t *src = s->y_buffer;
39 int h = _h;
41 do {
42 fwrite(src, w, 1, yuv_file);
43 src += s->y_stride;
44 } while (--h);
46 src = s->u_buffer;
47 h = (_h + 1) >> 1;
48 w = (w + 1) >> 1;
50 do {
51 fwrite(src, w, 1, yuv_file);
52 src += s->uv_stride;
53 } while (--h);
55 src = s->v_buffer;
56 h = (_h + 1) >> 1;
58 do {
59 fwrite(src, w, 1, yuv_file);
60 src += s->uv_stride;
61 } while (--h);
63 fclose(yuv_file);
64 }
65 #endif
66 #if WRITE_RECON_BUFFER == 2
67 void write_dx_frame_to_file(YV12_BUFFER_CONFIG *frame, int this_frame) {
68 // write the frame
69 FILE *yframe;
70 int i;
71 char filename[255];
73 snprintf(filename, sizeof(filename)-1, "dx\\y%04d.raw", this_frame);
74 yframe = fopen(filename, "wb");
76 for (i = 0; i < frame->y_height; i++)
77 fwrite(frame->y_buffer + i * frame->y_stride,
78 frame->y_width, 1, yframe);
80 fclose(yframe);
81 snprintf(filename, sizeof(filename)-1, "dx\\u%04d.raw", this_frame);
82 yframe = fopen(filename, "wb");
84 for (i = 0; i < frame->uv_height; i++)
85 fwrite(frame->u_buffer + i * frame->uv_stride,
86 frame->uv_width, 1, yframe);
88 fclose(yframe);
89 snprintf(filename, sizeof(filename)-1, "dx\\v%04d.raw", this_frame);
90 yframe = fopen(filename, "wb");
92 for (i = 0; i < frame->uv_height; i++)
93 fwrite(frame->v_buffer + i * frame->uv_stride,
94 frame->uv_width, 1, yframe);
96 fclose(yframe);
97 }
98 #endif
100 void vp9_initialize_dec() {
101 static int init_done = 0;
103 if (!init_done) {
104 vp9_initialize_common();
105 vp9_init_quant_tables();
106 init_done = 1;
107 }
108 }
110 static void init_macroblockd(VP9D_COMP *const pbi) {
111 MACROBLOCKD *xd = &pbi->mb;
112 struct macroblockd_plane *const pd = xd->plane;
113 int i;
115 for (i = 0; i < MAX_MB_PLANE; ++i) {
116 pd[i].qcoeff = pbi->qcoeff[i];
117 pd[i].dqcoeff = pbi->dqcoeff[i];
118 pd[i].eobs = pbi->eobs[i];
119 }
120 }
122 VP9D_PTR vp9_create_decompressor(VP9D_CONFIG *oxcf) {
123 VP9D_COMP *const pbi = vpx_memalign(32, sizeof(VP9D_COMP));
124 VP9_COMMON *const cm = pbi ? &pbi->common : NULL;
126 if (!cm)
127 return NULL;
129 vp9_zero(*pbi);
131 if (setjmp(cm->error.jmp)) {
132 cm->error.setjmp = 0;
133 vp9_remove_decompressor(pbi);
134 return NULL;
135 }
137 cm->error.setjmp = 1;
138 vp9_initialize_dec();
140 vp9_create_common(cm);
142 pbi->oxcf = *oxcf;
143 pbi->ready_for_new_data = 1;
144 cm->current_video_frame = 0;
146 // vp9_init_dequantizer() is first called here. Add check in
147 // frame_init_dequantizer() to avoid unnecessary calling of
148 // vp9_init_dequantizer() for every frame.
149 vp9_init_dequantizer(cm);
151 vp9_loop_filter_init(cm);
153 cm->error.setjmp = 0;
154 pbi->decoded_key_frame = 0;
156 init_macroblockd(pbi);
158 vp9_worker_init(&pbi->lf_worker);
160 return pbi;
161 }
163 void vp9_remove_decompressor(VP9D_PTR ptr) {
164 int i;
165 VP9D_COMP *const pbi = (VP9D_COMP *)ptr;
167 if (!pbi)
168 return;
170 vp9_remove_common(&pbi->common);
171 vp9_worker_end(&pbi->lf_worker);
172 vpx_free(pbi->lf_worker.data1);
173 for (i = 0; i < pbi->num_tile_workers; ++i) {
174 VP9Worker *const worker = &pbi->tile_workers[i];
175 vp9_worker_end(worker);
176 vpx_free(worker->data1);
177 vpx_free(worker->data2);
178 }
179 vpx_free(pbi->tile_workers);
180 vpx_free(pbi->mi_streams);
181 vpx_free(pbi->above_context[0]);
182 vpx_free(pbi->above_seg_context);
183 vpx_free(pbi);
184 }
186 static int equal_dimensions(YV12_BUFFER_CONFIG *a, YV12_BUFFER_CONFIG *b) {
187 return a->y_height == b->y_height && a->y_width == b->y_width &&
188 a->uv_height == b->uv_height && a->uv_width == b->uv_width;
189 }
191 vpx_codec_err_t vp9_copy_reference_dec(VP9D_PTR ptr,
192 VP9_REFFRAME ref_frame_flag,
193 YV12_BUFFER_CONFIG *sd) {
194 VP9D_COMP *pbi = (VP9D_COMP *) ptr;
195 VP9_COMMON *cm = &pbi->common;
197 /* TODO(jkoleszar): The decoder doesn't have any real knowledge of what the
198 * encoder is using the frame buffers for. This is just a stub to keep the
199 * vpxenc --test-decode functionality working, and will be replaced in a
200 * later commit that adds VP9-specific controls for this functionality.
201 */
202 if (ref_frame_flag == VP9_LAST_FLAG) {
203 YV12_BUFFER_CONFIG *cfg = &cm->yv12_fb[cm->ref_frame_map[0]];
204 if (!equal_dimensions(cfg, sd))
205 vpx_internal_error(&cm->error, VPX_CODEC_ERROR,
206 "Incorrect buffer dimensions");
207 else
208 vp8_yv12_copy_frame(cfg, sd);
209 } else {
210 vpx_internal_error(&cm->error, VPX_CODEC_ERROR,
211 "Invalid reference frame");
212 }
214 return cm->error.error_code;
215 }
218 vpx_codec_err_t vp9_set_reference_dec(VP9D_PTR ptr, VP9_REFFRAME ref_frame_flag,
219 YV12_BUFFER_CONFIG *sd) {
220 VP9D_COMP *pbi = (VP9D_COMP *) ptr;
221 VP9_COMMON *cm = &pbi->common;
222 int *ref_fb_ptr = NULL;
224 /* TODO(jkoleszar): The decoder doesn't have any real knowledge of what the
225 * encoder is using the frame buffers for. This is just a stub to keep the
226 * vpxenc --test-decode functionality working, and will be replaced in a
227 * later commit that adds VP9-specific controls for this functionality.
228 */
229 if (ref_frame_flag == VP9_LAST_FLAG) {
230 ref_fb_ptr = &pbi->common.active_ref_idx[0];
231 } else if (ref_frame_flag == VP9_GOLD_FLAG) {
232 ref_fb_ptr = &pbi->common.active_ref_idx[1];
233 } else if (ref_frame_flag == VP9_ALT_FLAG) {
234 ref_fb_ptr = &pbi->common.active_ref_idx[2];
235 } else {
236 vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
237 "Invalid reference frame");
238 return pbi->common.error.error_code;
239 }
241 if (!equal_dimensions(&cm->yv12_fb[*ref_fb_ptr], sd)) {
242 vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
243 "Incorrect buffer dimensions");
244 } else {
245 // Find an empty frame buffer.
246 const int free_fb = get_free_fb(cm);
247 // Decrease fb_idx_ref_cnt since it will be increased again in
248 // ref_cnt_fb() below.
249 cm->fb_idx_ref_cnt[free_fb]--;
251 // Manage the reference counters and copy image.
252 ref_cnt_fb(cm->fb_idx_ref_cnt, ref_fb_ptr, free_fb);
253 vp8_yv12_copy_frame(sd, &cm->yv12_fb[*ref_fb_ptr]);
254 }
256 return pbi->common.error.error_code;
257 }
260 int vp9_get_reference_dec(VP9D_PTR ptr, int index, YV12_BUFFER_CONFIG **fb) {
261 VP9D_COMP *pbi = (VP9D_COMP *) ptr;
262 VP9_COMMON *cm = &pbi->common;
264 if (index < 0 || index >= NUM_REF_FRAMES)
265 return -1;
267 *fb = &cm->yv12_fb[cm->ref_frame_map[index]];
268 return 0;
269 }
271 /* If any buffer updating is signaled it should be done here. */
272 static void swap_frame_buffers(VP9D_COMP *pbi) {
273 int ref_index = 0, mask;
274 VP9_COMMON *const cm = &pbi->common;
276 for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) {
277 if (mask & 1)
278 ref_cnt_fb(cm->fb_idx_ref_cnt, &cm->ref_frame_map[ref_index],
279 cm->new_fb_idx);
280 ++ref_index;
281 }
283 cm->frame_to_show = get_frame_new_buffer(cm);
284 cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
286 // Invalidate these references until the next frame starts.
287 for (ref_index = 0; ref_index < 3; ref_index++)
288 cm->active_ref_idx[ref_index] = INT_MAX;
289 }
291 int vp9_receive_compressed_data(VP9D_PTR ptr,
292 size_t size, const uint8_t **psource,
293 int64_t time_stamp) {
294 VP9D_COMP *pbi = (VP9D_COMP *) ptr;
295 VP9_COMMON *cm = &pbi->common;
296 const uint8_t *source = *psource;
297 int retcode = 0;
299 /*if(pbi->ready_for_new_data == 0)
300 return -1;*/
302 if (ptr == 0)
303 return -1;
305 cm->error.error_code = VPX_CODEC_OK;
307 pbi->source = source;
308 pbi->source_sz = size;
310 if (pbi->source_sz == 0) {
311 /* This is used to signal that we are missing frames.
312 * We do not know if the missing frame(s) was supposed to update
313 * any of the reference buffers, but we act conservative and
314 * mark only the last buffer as corrupted.
315 *
316 * TODO(jkoleszar): Error concealment is undefined and non-normative
317 * at this point, but if it becomes so, [0] may not always be the correct
318 * thing to do here.
319 */
320 if (cm->active_ref_idx[0] != INT_MAX)
321 get_frame_ref_buffer(cm, 0)->corrupted = 1;
322 }
324 cm->new_fb_idx = get_free_fb(cm);
326 if (setjmp(cm->error.jmp)) {
327 cm->error.setjmp = 0;
329 /* We do not know if the missing frame(s) was supposed to update
330 * any of the reference buffers, but we act conservative and
331 * mark only the last buffer as corrupted.
332 *
333 * TODO(jkoleszar): Error concealment is undefined and non-normative
334 * at this point, but if it becomes so, [0] may not always be the correct
335 * thing to do here.
336 */
337 if (cm->active_ref_idx[0] != INT_MAX)
338 get_frame_ref_buffer(cm, 0)->corrupted = 1;
340 if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
341 cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
343 return -1;
344 }
346 cm->error.setjmp = 1;
348 retcode = vp9_decode_frame(pbi, psource);
350 if (retcode < 0) {
351 cm->error.error_code = VPX_CODEC_ERROR;
352 cm->error.setjmp = 0;
353 if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
354 cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
355 return retcode;
356 }
358 swap_frame_buffers(pbi);
360 #if WRITE_RECON_BUFFER == 2
361 if (cm->show_frame)
362 write_dx_frame_to_file(cm->frame_to_show,
363 cm->current_video_frame);
364 else
365 write_dx_frame_to_file(cm->frame_to_show,
366 cm->current_video_frame + 1000);
367 #endif
369 if (!pbi->do_loopfilter_inline) {
370 vp9_loop_filter_frame(cm, &pbi->mb, pbi->common.lf.filter_level, 0, 0);
371 }
373 #if WRITE_RECON_BUFFER == 2
374 if (cm->show_frame)
375 write_dx_frame_to_file(cm->frame_to_show,
376 cm->current_video_frame + 2000);
377 else
378 write_dx_frame_to_file(cm->frame_to_show,
379 cm->current_video_frame + 3000);
380 #endif
382 vp9_extend_frame_inner_borders(cm->frame_to_show,
383 cm->subsampling_x,
384 cm->subsampling_y);
386 #if WRITE_RECON_BUFFER == 1
387 if (cm->show_frame)
388 recon_write_yuv_frame("recon.yuv", cm->frame_to_show,
389 cm->width, cm->height);
390 #endif
392 vp9_clear_system_state();
394 cm->last_show_frame = cm->show_frame;
395 if (cm->show_frame) {
396 // current mip will be the prev_mip for the next frame
397 MODE_INFO *temp = cm->prev_mip;
398 MODE_INFO **temp2 = cm->prev_mi_grid_base;
399 cm->prev_mip = cm->mip;
400 cm->mip = temp;
401 cm->prev_mi_grid_base = cm->mi_grid_base;
402 cm->mi_grid_base = temp2;
404 // update the upper left visible macroblock ptrs
405 cm->mi = cm->mip + cm->mode_info_stride + 1;
406 cm->prev_mi = cm->prev_mip + cm->mode_info_stride + 1;
407 cm->mi_grid_visible = cm->mi_grid_base + cm->mode_info_stride + 1;
408 cm->prev_mi_grid_visible = cm->prev_mi_grid_base + cm->mode_info_stride + 1;
410 pbi->mb.mi_8x8 = cm->mi_grid_visible;
411 pbi->mb.mi_8x8[0] = cm->mi;
413 cm->current_video_frame++;
414 }
416 pbi->ready_for_new_data = 0;
417 pbi->last_time_stamp = time_stamp;
418 pbi->source_sz = 0;
420 cm->error.setjmp = 0;
421 return retcode;
422 }
424 int vp9_get_raw_frame(VP9D_PTR ptr, YV12_BUFFER_CONFIG *sd,
425 int64_t *time_stamp, int64_t *time_end_stamp,
426 vp9_ppflags_t *flags) {
427 int ret = -1;
428 VP9D_COMP *pbi = (VP9D_COMP *) ptr;
430 if (pbi->ready_for_new_data == 1)
431 return ret;
433 /* ie no raw frame to show!!! */
434 if (pbi->common.show_frame == 0)
435 return ret;
437 pbi->ready_for_new_data = 1;
438 *time_stamp = pbi->last_time_stamp;
439 *time_end_stamp = 0;
441 #if CONFIG_VP9_POSTPROC
442 ret = vp9_post_proc_frame(&pbi->common, sd, flags);
443 #else
445 if (pbi->common.frame_to_show) {
446 *sd = *pbi->common.frame_to_show;
447 sd->y_width = pbi->common.width;
448 sd->y_height = pbi->common.height;
449 sd->uv_width = sd->y_width >> pbi->common.subsampling_x;
450 sd->uv_height = sd->y_height >> pbi->common.subsampling_y;
452 ret = 0;
453 } else {
454 ret = -1;
455 }
457 #endif /*!CONFIG_POSTPROC*/
458 vp9_clear_system_state();
459 return ret;
460 }