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 "vp8/common/onyxc_int.h"
13 : #if CONFIG_POSTPROC
14 : #include "vp8/common/postproc.h"
15 : #endif
16 : #include "vp8/common/onyxd.h"
17 : #include "onyxd_int.h"
18 : #include "vpx_mem/vpx_mem.h"
19 : #include "vp8/common/alloccommon.h"
20 : #include "vpx_scale/yv12extend.h"
21 : #include "vp8/common/loopfilter.h"
22 : #include "vp8/common/swapyv12buffer.h"
23 : #include "vp8/common/g_common.h"
24 : #include "vp8/common/threading.h"
25 : #include "decoderthreading.h"
26 : #include <stdio.h>
27 : #include <assert.h>
28 :
29 : #include "vp8/common/quant_common.h"
30 : #include "vpx_scale/vpxscale.h"
31 : #include "vp8/common/systemdependent.h"
32 : #include "vpx_ports/vpx_timer.h"
33 : #include "detokenize.h"
34 : #if CONFIG_ERROR_CONCEALMENT
35 : #include "error_concealment.h"
36 : #endif
37 : #if ARCH_ARM
38 : #include "vpx_ports/arm.h"
39 : #endif
40 :
41 : extern void vp8_init_loop_filter(VP8_COMMON *cm);
42 : extern void vp8cx_init_de_quantizer(VP8D_COMP *pbi);
43 : static int get_free_fb (VP8_COMMON *cm);
44 : static void ref_cnt_fb (int *buf, int *idx, int new_idx);
45 :
46 :
47 0 : void vp8dx_initialize()
48 : {
49 : static int init_done = 0;
50 :
51 0 : if (!init_done)
52 : {
53 0 : vp8_initialize_common();
54 0 : vp8_scale_machine_specific_config();
55 0 : init_done = 1;
56 : }
57 0 : }
58 :
59 :
60 0 : VP8D_PTR vp8dx_create_decompressor(VP8D_CONFIG *oxcf)
61 : {
62 0 : VP8D_COMP *pbi = vpx_memalign(32, sizeof(VP8D_COMP));
63 :
64 0 : if (!pbi)
65 0 : return NULL;
66 :
67 0 : vpx_memset(pbi, 0, sizeof(VP8D_COMP));
68 :
69 0 : if (setjmp(pbi->common.error.jmp))
70 : {
71 0 : pbi->common.error.setjmp = 0;
72 0 : vp8dx_remove_decompressor(pbi);
73 0 : return 0;
74 : }
75 :
76 0 : pbi->common.error.setjmp = 1;
77 0 : vp8dx_initialize();
78 :
79 0 : vp8_create_common(&pbi->common);
80 0 : vp8_dmachine_specific_config(pbi);
81 :
82 0 : pbi->common.current_video_frame = 0;
83 0 : pbi->ready_for_new_data = 1;
84 :
85 : #if CONFIG_MULTITHREAD
86 0 : pbi->max_threads = oxcf->max_threads;
87 0 : vp8_decoder_create_threads(pbi);
88 : #endif
89 :
90 : /* vp8cx_init_de_quantizer() is first called here. Add check in frame_init_dequantizer() to avoid
91 : * unnecessary calling of vp8cx_init_de_quantizer() for every frame.
92 : */
93 0 : vp8cx_init_de_quantizer(pbi);
94 :
95 0 : vp8_loop_filter_init(&pbi->common);
96 :
97 0 : pbi->common.error.setjmp = 0;
98 :
99 : #if CONFIG_ERROR_CONCEALMENT
100 : pbi->ec_enabled = oxcf->error_concealment;
101 : #else
102 0 : pbi->ec_enabled = 0;
103 : #endif
104 : /* Error concealment is activated after a key frame has been
105 : * decoded without errors when error concealment is enabled.
106 : */
107 0 : pbi->ec_active = 0;
108 :
109 0 : pbi->decoded_key_frame = 0;
110 :
111 0 : pbi->input_partition = oxcf->input_partition;
112 :
113 : /* Independent partitions is activated when a frame updates the
114 : * token probability table to have equal probabilities over the
115 : * PREV_COEF context.
116 : */
117 0 : pbi->independent_partitions = 0;
118 :
119 0 : return (VP8D_PTR) pbi;
120 : }
121 :
122 :
123 0 : void vp8dx_remove_decompressor(VP8D_PTR ptr)
124 : {
125 0 : VP8D_COMP *pbi = (VP8D_COMP *) ptr;
126 :
127 0 : if (!pbi)
128 0 : return;
129 :
130 : #if CONFIG_MULTITHREAD
131 0 : if (pbi->b_multithreaded_rd)
132 0 : vp8mt_de_alloc_temp_buffers(pbi, pbi->common.mb_rows);
133 0 : vp8_decoder_remove_threads(pbi);
134 : #endif
135 : #if CONFIG_ERROR_CONCEALMENT
136 : vp8_de_alloc_overlap_lists(pbi);
137 : #endif
138 0 : vp8_remove_common(&pbi->common);
139 0 : vpx_free(pbi->mbc);
140 0 : vpx_free(pbi);
141 : }
142 :
143 :
144 0 : vpx_codec_err_t vp8dx_get_reference(VP8D_PTR ptr, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd)
145 : {
146 0 : VP8D_COMP *pbi = (VP8D_COMP *) ptr;
147 0 : VP8_COMMON *cm = &pbi->common;
148 : int ref_fb_idx;
149 :
150 0 : if (ref_frame_flag == VP8_LAST_FLAG)
151 0 : ref_fb_idx = cm->lst_fb_idx;
152 0 : else if (ref_frame_flag == VP8_GOLD_FLAG)
153 0 : ref_fb_idx = cm->gld_fb_idx;
154 0 : else if (ref_frame_flag == VP8_ALT_FLAG)
155 0 : ref_fb_idx = cm->alt_fb_idx;
156 : else{
157 0 : vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
158 : "Invalid reference frame");
159 0 : return pbi->common.error.error_code;
160 : }
161 :
162 0 : if(cm->yv12_fb[ref_fb_idx].y_height != sd->y_height ||
163 0 : cm->yv12_fb[ref_fb_idx].y_width != sd->y_width ||
164 0 : cm->yv12_fb[ref_fb_idx].uv_height != sd->uv_height ||
165 0 : cm->yv12_fb[ref_fb_idx].uv_width != sd->uv_width){
166 0 : vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
167 : "Incorrect buffer dimensions");
168 : }
169 : else
170 0 : vp8_yv12_copy_frame_ptr(&cm->yv12_fb[ref_fb_idx], sd);
171 :
172 0 : return pbi->common.error.error_code;
173 : }
174 :
175 :
176 0 : vpx_codec_err_t vp8dx_set_reference(VP8D_PTR ptr, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd)
177 : {
178 0 : VP8D_COMP *pbi = (VP8D_COMP *) ptr;
179 0 : VP8_COMMON *cm = &pbi->common;
180 0 : int *ref_fb_ptr = NULL;
181 : int free_fb;
182 :
183 0 : if (ref_frame_flag == VP8_LAST_FLAG)
184 0 : ref_fb_ptr = &cm->lst_fb_idx;
185 0 : else if (ref_frame_flag == VP8_GOLD_FLAG)
186 0 : ref_fb_ptr = &cm->gld_fb_idx;
187 0 : else if (ref_frame_flag == VP8_ALT_FLAG)
188 0 : ref_fb_ptr = &cm->alt_fb_idx;
189 : else{
190 0 : vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
191 : "Invalid reference frame");
192 0 : return pbi->common.error.error_code;
193 : }
194 :
195 0 : if(cm->yv12_fb[*ref_fb_ptr].y_height != sd->y_height ||
196 0 : cm->yv12_fb[*ref_fb_ptr].y_width != sd->y_width ||
197 0 : cm->yv12_fb[*ref_fb_ptr].uv_height != sd->uv_height ||
198 0 : cm->yv12_fb[*ref_fb_ptr].uv_width != sd->uv_width){
199 0 : vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
200 : "Incorrect buffer dimensions");
201 : }
202 : else{
203 : /* Find an empty frame buffer. */
204 0 : free_fb = get_free_fb(cm);
205 : /* Decrease fb_idx_ref_cnt since it will be increased again in
206 : * ref_cnt_fb() below. */
207 0 : cm->fb_idx_ref_cnt[free_fb]--;
208 :
209 : /* Manage the reference counters and copy image. */
210 0 : ref_cnt_fb (cm->fb_idx_ref_cnt, ref_fb_ptr, free_fb);
211 0 : vp8_yv12_copy_frame_ptr(sd, &cm->yv12_fb[*ref_fb_ptr]);
212 : }
213 :
214 0 : return pbi->common.error.error_code;
215 : }
216 :
217 : /*For ARM NEON, d8-d15 are callee-saved registers, and need to be saved by us.*/
218 : #if HAVE_ARMV7
219 : extern void vp8_push_neon(int64_t *store);
220 : extern void vp8_pop_neon(int64_t *store);
221 : #endif
222 :
223 0 : static int get_free_fb (VP8_COMMON *cm)
224 : {
225 : int i;
226 0 : for (i = 0; i < NUM_YV12_BUFFERS; i++)
227 0 : if (cm->fb_idx_ref_cnt[i] == 0)
228 0 : break;
229 :
230 0 : assert(i < NUM_YV12_BUFFERS);
231 0 : cm->fb_idx_ref_cnt[i] = 1;
232 0 : return i;
233 : }
234 :
235 0 : static void ref_cnt_fb (int *buf, int *idx, int new_idx)
236 : {
237 0 : if (buf[*idx] > 0)
238 0 : buf[*idx]--;
239 :
240 0 : *idx = new_idx;
241 :
242 0 : buf[new_idx]++;
243 0 : }
244 :
245 : /* If any buffer copy / swapping is signalled it should be done here. */
246 0 : static int swap_frame_buffers (VP8_COMMON *cm)
247 : {
248 0 : int err = 0;
249 :
250 : /* The alternate reference frame or golden frame can be updated
251 : * using the new, last, or golden/alt ref frame. If it
252 : * is updated using the newly decoded frame it is a refresh.
253 : * An update using the last or golden/alt ref frame is a copy.
254 : */
255 0 : if (cm->copy_buffer_to_arf)
256 : {
257 0 : int new_fb = 0;
258 :
259 0 : if (cm->copy_buffer_to_arf == 1)
260 0 : new_fb = cm->lst_fb_idx;
261 0 : else if (cm->copy_buffer_to_arf == 2)
262 0 : new_fb = cm->gld_fb_idx;
263 : else
264 0 : err = -1;
265 :
266 0 : ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->alt_fb_idx, new_fb);
267 : }
268 :
269 0 : if (cm->copy_buffer_to_gf)
270 : {
271 0 : int new_fb = 0;
272 :
273 0 : if (cm->copy_buffer_to_gf == 1)
274 0 : new_fb = cm->lst_fb_idx;
275 0 : else if (cm->copy_buffer_to_gf == 2)
276 0 : new_fb = cm->alt_fb_idx;
277 : else
278 0 : err = -1;
279 :
280 0 : ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->gld_fb_idx, new_fb);
281 : }
282 :
283 0 : if (cm->refresh_golden_frame)
284 0 : ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->gld_fb_idx, cm->new_fb_idx);
285 :
286 0 : if (cm->refresh_alt_ref_frame)
287 0 : ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->alt_fb_idx, cm->new_fb_idx);
288 :
289 0 : if (cm->refresh_last_frame)
290 : {
291 0 : ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->lst_fb_idx, cm->new_fb_idx);
292 :
293 0 : cm->frame_to_show = &cm->yv12_fb[cm->lst_fb_idx];
294 : }
295 : else
296 0 : cm->frame_to_show = &cm->yv12_fb[cm->new_fb_idx];
297 :
298 0 : cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
299 :
300 0 : return err;
301 : }
302 :
303 0 : int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsigned char *source, int64_t time_stamp)
304 : {
305 : #if HAVE_ARMV7
306 : int64_t dx_store_reg[8];
307 : #endif
308 0 : VP8D_COMP *pbi = (VP8D_COMP *) ptr;
309 0 : VP8_COMMON *cm = &pbi->common;
310 0 : int retcode = 0;
311 :
312 : /*if(pbi->ready_for_new_data == 0)
313 : return -1;*/
314 :
315 0 : if (ptr == 0)
316 : {
317 0 : return -1;
318 : }
319 :
320 0 : pbi->common.error.error_code = VPX_CODEC_OK;
321 :
322 0 : if (pbi->input_partition && !(source == NULL && size == 0))
323 : {
324 : /* Store a pointer to this partition and return. We haven't
325 : * received the complete frame yet, so we will wait with decoding.
326 : */
327 0 : pbi->partitions[pbi->num_partitions] = source;
328 0 : pbi->partition_sizes[pbi->num_partitions] = size;
329 0 : pbi->source_sz += size;
330 0 : pbi->num_partitions++;
331 0 : if (pbi->num_partitions > (1<<pbi->common.multi_token_partition) + 1)
332 0 : pbi->common.multi_token_partition++;
333 0 : if (pbi->common.multi_token_partition > EIGHT_PARTITION)
334 : {
335 0 : pbi->common.error.error_code = VPX_CODEC_UNSUP_BITSTREAM;
336 0 : pbi->common.error.setjmp = 0;
337 0 : return -1;
338 : }
339 0 : return 0;
340 : }
341 : else
342 : {
343 0 : if (!pbi->input_partition)
344 : {
345 0 : pbi->Source = source;
346 0 : pbi->source_sz = size;
347 : }
348 :
349 0 : if (pbi->source_sz == 0)
350 : {
351 : /* This is used to signal that we are missing frames.
352 : * We do not know if the missing frame(s) was supposed to update
353 : * any of the reference buffers, but we act conservative and
354 : * mark only the last buffer as corrupted.
355 : */
356 0 : cm->yv12_fb[cm->lst_fb_idx].corrupted = 1;
357 :
358 : /* If error concealment is disabled we won't signal missing frames to
359 : * the decoder.
360 : */
361 0 : if (!pbi->ec_active)
362 : {
363 : /* Signal that we have no frame to show. */
364 0 : cm->show_frame = 0;
365 :
366 0 : pbi->num_partitions = 0;
367 0 : if (pbi->input_partition)
368 0 : pbi->common.multi_token_partition = 0;
369 :
370 : /* Nothing more to do. */
371 0 : return 0;
372 : }
373 : }
374 :
375 : #if HAVE_ARMV7
376 : #if CONFIG_RUNTIME_CPU_DETECT
377 : if (cm->rtcd.flags & HAS_NEON)
378 : #endif
379 : {
380 : vp8_push_neon(dx_store_reg);
381 : }
382 : #endif
383 :
384 0 : cm->new_fb_idx = get_free_fb (cm);
385 :
386 0 : if (setjmp(pbi->common.error.jmp))
387 : {
388 : #if HAVE_ARMV7
389 : #if CONFIG_RUNTIME_CPU_DETECT
390 : if (cm->rtcd.flags & HAS_NEON)
391 : #endif
392 : {
393 : vp8_pop_neon(dx_store_reg);
394 : }
395 : #endif
396 0 : pbi->common.error.setjmp = 0;
397 :
398 0 : pbi->num_partitions = 0;
399 0 : if (pbi->input_partition)
400 0 : pbi->common.multi_token_partition = 0;
401 :
402 : /* We do not know if the missing frame(s) was supposed to update
403 : * any of the reference buffers, but we act conservative and
404 : * mark only the last buffer as corrupted.
405 : */
406 0 : cm->yv12_fb[cm->lst_fb_idx].corrupted = 1;
407 :
408 0 : if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
409 0 : cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
410 0 : return -1;
411 : }
412 :
413 0 : pbi->common.error.setjmp = 1;
414 : }
415 :
416 0 : retcode = vp8_decode_frame(pbi);
417 :
418 0 : if (retcode < 0)
419 : {
420 : #if HAVE_ARMV7
421 : #if CONFIG_RUNTIME_CPU_DETECT
422 : if (cm->rtcd.flags & HAS_NEON)
423 : #endif
424 : {
425 : vp8_pop_neon(dx_store_reg);
426 : }
427 : #endif
428 0 : pbi->common.error.error_code = VPX_CODEC_ERROR;
429 0 : pbi->common.error.setjmp = 0;
430 0 : if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
431 0 : cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
432 0 : return retcode;
433 : }
434 :
435 : #if CONFIG_MULTITHREAD
436 0 : if (pbi->b_multithreaded_rd && cm->multi_token_partition != ONE_PARTITION)
437 : {
438 0 : if (swap_frame_buffers (cm))
439 : {
440 : #if HAVE_ARMV7
441 : #if CONFIG_RUNTIME_CPU_DETECT
442 : if (cm->rtcd.flags & HAS_NEON)
443 : #endif
444 : {
445 : vp8_pop_neon(dx_store_reg);
446 : }
447 : #endif
448 0 : pbi->common.error.error_code = VPX_CODEC_ERROR;
449 0 : pbi->common.error.setjmp = 0;
450 0 : return -1;
451 : }
452 : } else
453 : #endif
454 : {
455 0 : if (swap_frame_buffers (cm))
456 : {
457 : #if HAVE_ARMV7
458 : #if CONFIG_RUNTIME_CPU_DETECT
459 : if (cm->rtcd.flags & HAS_NEON)
460 : #endif
461 : {
462 : vp8_pop_neon(dx_store_reg);
463 : }
464 : #endif
465 0 : pbi->common.error.error_code = VPX_CODEC_ERROR;
466 0 : pbi->common.error.setjmp = 0;
467 0 : return -1;
468 : }
469 :
470 0 : if(cm->filter_level)
471 : {
472 : /* Apply the loop filter if appropriate. */
473 0 : vp8_loop_filter_frame(cm, &pbi->mb);
474 : }
475 0 : vp8_yv12_extend_frame_borders_ptr(cm->frame_to_show);
476 : }
477 :
478 :
479 0 : vp8_clear_system_state();
480 :
481 : #if CONFIG_ERROR_CONCEALMENT
482 : /* swap the mode infos to storage for future error concealment */
483 : if (pbi->ec_enabled && pbi->common.prev_mi)
484 : {
485 : const MODE_INFO* tmp = pbi->common.prev_mi;
486 : int row, col;
487 : pbi->common.prev_mi = pbi->common.mi;
488 : pbi->common.mi = tmp;
489 :
490 : /* Propagate the segment_ids to the next frame */
491 : for (row = 0; row < pbi->common.mb_rows; ++row)
492 : {
493 : for (col = 0; col < pbi->common.mb_cols; ++col)
494 : {
495 : const int i = row*pbi->common.mode_info_stride + col;
496 : pbi->common.mi[i].mbmi.segment_id =
497 : pbi->common.prev_mi[i].mbmi.segment_id;
498 : }
499 : }
500 : }
501 : #endif
502 :
503 : /*vp8_print_modes_and_motion_vectors( cm->mi, cm->mb_rows,cm->mb_cols, cm->current_video_frame);*/
504 :
505 0 : if (cm->show_frame)
506 0 : cm->current_video_frame++;
507 :
508 0 : pbi->ready_for_new_data = 0;
509 0 : pbi->last_time_stamp = time_stamp;
510 0 : pbi->num_partitions = 0;
511 0 : if (pbi->input_partition)
512 0 : pbi->common.multi_token_partition = 0;
513 0 : pbi->source_sz = 0;
514 :
515 : #if 0
516 : {
517 : int i;
518 : int64_t earliest_time = pbi->dr[0].time_stamp;
519 : int64_t latest_time = pbi->dr[0].time_stamp;
520 : int64_t time_diff = 0;
521 : int bytes = 0;
522 :
523 : pbi->dr[pbi->common.current_video_frame&0xf].size = pbi->bc.pos + pbi->bc2.pos + 4;;
524 : pbi->dr[pbi->common.current_video_frame&0xf].time_stamp = time_stamp;
525 :
526 : for (i = 0; i < 16; i++)
527 : {
528 :
529 : bytes += pbi->dr[i].size;
530 :
531 : if (pbi->dr[i].time_stamp < earliest_time)
532 : earliest_time = pbi->dr[i].time_stamp;
533 :
534 : if (pbi->dr[i].time_stamp > latest_time)
535 : latest_time = pbi->dr[i].time_stamp;
536 : }
537 :
538 : time_diff = latest_time - earliest_time;
539 :
540 : if (time_diff > 0)
541 : {
542 : pbi->common.bitrate = 80000.00 * bytes / time_diff ;
543 : pbi->common.framerate = 160000000.00 / time_diff ;
544 : }
545 :
546 : }
547 : #endif
548 :
549 : #if HAVE_ARMV7
550 : #if CONFIG_RUNTIME_CPU_DETECT
551 : if (cm->rtcd.flags & HAS_NEON)
552 : #endif
553 : {
554 : vp8_pop_neon(dx_store_reg);
555 : }
556 : #endif
557 0 : pbi->common.error.setjmp = 0;
558 0 : return retcode;
559 : }
560 0 : int vp8dx_get_raw_frame(VP8D_PTR ptr, YV12_BUFFER_CONFIG *sd, int64_t *time_stamp, int64_t *time_end_stamp, vp8_ppflags_t *flags)
561 : {
562 0 : int ret = -1;
563 0 : VP8D_COMP *pbi = (VP8D_COMP *) ptr;
564 :
565 0 : if (pbi->ready_for_new_data == 1)
566 0 : return ret;
567 :
568 : /* ie no raw frame to show!!! */
569 0 : if (pbi->common.show_frame == 0)
570 0 : return ret;
571 :
572 0 : pbi->ready_for_new_data = 1;
573 0 : *time_stamp = pbi->last_time_stamp;
574 0 : *time_end_stamp = 0;
575 :
576 0 : sd->clrtype = pbi->common.clr_type;
577 : #if CONFIG_POSTPROC
578 0 : ret = vp8_post_proc_frame(&pbi->common, sd, flags);
579 : #else
580 :
581 : if (pbi->common.frame_to_show)
582 : {
583 : *sd = *pbi->common.frame_to_show;
584 : sd->y_width = pbi->common.Width;
585 : sd->y_height = pbi->common.Height;
586 : sd->uv_height = pbi->common.Height / 2;
587 : ret = 0;
588 : }
589 : else
590 : {
591 : ret = -1;
592 : }
593 :
594 : #endif /*!CONFIG_POSTPROC*/
595 0 : vp8_clear_system_state();
596 0 : return ret;
597 : }
|