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