• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
28 #include "vp8/common/quant_common.h"
29 #include "vpx_scale/vpxscale.h"
30 #include "vp8/common/systemdependent.h"
31 #include "vpx_ports/vpx_timer.h"
32 #include "detokenize.h"
33 #if ARCH_ARM
34 #include "vpx_ports/arm.h"
35 #endif
36 
37 extern void vp8_init_loop_filter(VP8_COMMON *cm);
38 extern void vp8cx_init_de_quantizer(VP8D_COMP *pbi);
39 
40 
vp8dx_initialize()41 void vp8dx_initialize()
42 {
43     static int init_done = 0;
44 
45     if (!init_done)
46     {
47         vp8_initialize_common();
48         vp8_scale_machine_specific_config();
49         init_done = 1;
50     }
51 }
52 
53 
vp8dx_create_decompressor(VP8D_CONFIG * oxcf)54 VP8D_PTR vp8dx_create_decompressor(VP8D_CONFIG *oxcf)
55 {
56     VP8D_COMP *pbi = vpx_memalign(32, sizeof(VP8D_COMP));
57 
58     if (!pbi)
59         return NULL;
60 
61     vpx_memset(pbi, 0, sizeof(VP8D_COMP));
62 
63     if (setjmp(pbi->common.error.jmp))
64     {
65         pbi->common.error.setjmp = 0;
66         vp8dx_remove_decompressor(pbi);
67         return 0;
68     }
69 
70     pbi->common.error.setjmp = 1;
71     vp8dx_initialize();
72 
73     vp8_create_common(&pbi->common);
74     vp8_dmachine_specific_config(pbi);
75 
76     pbi->common.current_video_frame = 0;
77     pbi->ready_for_new_data = 1;
78 
79     pbi->CPUFreq = 0; /*vp8_get_processor_freq();*/
80 #if CONFIG_MULTITHREAD
81     pbi->max_threads = oxcf->max_threads;
82     vp8_decoder_create_threads(pbi);
83 #endif
84 
85     /* vp8cx_init_de_quantizer() is first called here. Add check in frame_init_dequantizer() to avoid
86      *  unnecessary calling of vp8cx_init_de_quantizer() for every frame.
87      */
88     vp8cx_init_de_quantizer(pbi);
89 
90     {
91         VP8_COMMON *cm = &pbi->common;
92 
93         vp8_init_loop_filter(cm);
94         cm->last_frame_type = KEY_FRAME;
95         cm->last_filter_type = cm->filter_type;
96         cm->last_sharpness_level = cm->sharpness_level;
97     }
98 
99     pbi->common.error.setjmp = 0;
100     return (VP8D_PTR) pbi;
101 }
102 
103 
vp8dx_remove_decompressor(VP8D_PTR ptr)104 void vp8dx_remove_decompressor(VP8D_PTR ptr)
105 {
106     VP8D_COMP *pbi = (VP8D_COMP *) ptr;
107 
108     if (!pbi)
109         return;
110 
111 #if CONFIG_MULTITHREAD
112     if (pbi->b_multithreaded_rd)
113         vp8mt_de_alloc_temp_buffers(pbi, pbi->common.mb_rows);
114     vp8_decoder_remove_threads(pbi);
115 #endif
116     vp8_remove_common(&pbi->common);
117     vpx_free(pbi);
118 }
119 
120 
vp8dx_get_reference(VP8D_PTR ptr,VP8_REFFRAME ref_frame_flag,YV12_BUFFER_CONFIG * sd)121 int vp8dx_get_reference(VP8D_PTR ptr, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd)
122 {
123     VP8D_COMP *pbi = (VP8D_COMP *) ptr;
124     VP8_COMMON *cm = &pbi->common;
125     int ref_fb_idx;
126 
127     if (ref_frame_flag == VP8_LAST_FLAG)
128         ref_fb_idx = cm->lst_fb_idx;
129     else if (ref_frame_flag == VP8_GOLD_FLAG)
130         ref_fb_idx = cm->gld_fb_idx;
131     else if (ref_frame_flag == VP8_ALT_FLAG)
132         ref_fb_idx = cm->alt_fb_idx;
133     else
134         return -1;
135 
136     vp8_yv12_copy_frame_ptr(&cm->yv12_fb[ref_fb_idx], sd);
137 
138     return 0;
139 }
140 
141 
vp8dx_set_reference(VP8D_PTR ptr,VP8_REFFRAME ref_frame_flag,YV12_BUFFER_CONFIG * sd)142 int vp8dx_set_reference(VP8D_PTR ptr, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd)
143 {
144     VP8D_COMP *pbi = (VP8D_COMP *) ptr;
145     VP8_COMMON *cm = &pbi->common;
146     int ref_fb_idx;
147 
148     if (ref_frame_flag == VP8_LAST_FLAG)
149         ref_fb_idx = cm->lst_fb_idx;
150     else if (ref_frame_flag == VP8_GOLD_FLAG)
151         ref_fb_idx = cm->gld_fb_idx;
152     else if (ref_frame_flag == VP8_ALT_FLAG)
153         ref_fb_idx = cm->alt_fb_idx;
154     else
155         return -1;
156 
157     vp8_yv12_copy_frame_ptr(sd, &cm->yv12_fb[ref_fb_idx]);
158 
159     return 0;
160 }
161 
162 /*For ARM NEON, d8-d15 are callee-saved registers, and need to be saved by us.*/
163 #if HAVE_ARMV7
164 extern void vp8_push_neon(INT64 *store);
165 extern void vp8_pop_neon(INT64 *store);
166 #endif
167 
get_free_fb(VP8_COMMON * cm)168 static int get_free_fb (VP8_COMMON *cm)
169 {
170     int i;
171     for (i = 0; i < NUM_YV12_BUFFERS; i++)
172         if (cm->fb_idx_ref_cnt[i] == 0)
173             break;
174 
175     cm->fb_idx_ref_cnt[i] = 1;
176     return i;
177 }
178 
ref_cnt_fb(int * buf,int * idx,int new_idx)179 static void ref_cnt_fb (int *buf, int *idx, int new_idx)
180 {
181     if (buf[*idx] > 0)
182         buf[*idx]--;
183 
184     *idx = new_idx;
185 
186     buf[new_idx]++;
187 }
188 
189 /* If any buffer copy / swapping is signalled it should be done here. */
swap_frame_buffers(VP8_COMMON * cm)190 static int swap_frame_buffers (VP8_COMMON *cm)
191 {
192     int err = 0;
193 
194     /* The alternate reference frame or golden frame can be updated
195      *  using the new, last, or golden/alt ref frame.  If it
196      *  is updated using the newly decoded frame it is a refresh.
197      *  An update using the last or golden/alt ref frame is a copy.
198      */
199     if (cm->copy_buffer_to_arf)
200     {
201         int new_fb = 0;
202 
203         if (cm->copy_buffer_to_arf == 1)
204             new_fb = cm->lst_fb_idx;
205         else if (cm->copy_buffer_to_arf == 2)
206             new_fb = cm->gld_fb_idx;
207         else
208             err = -1;
209 
210         ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->alt_fb_idx, new_fb);
211     }
212 
213     if (cm->copy_buffer_to_gf)
214     {
215         int new_fb = 0;
216 
217         if (cm->copy_buffer_to_gf == 1)
218             new_fb = cm->lst_fb_idx;
219         else if (cm->copy_buffer_to_gf == 2)
220             new_fb = cm->alt_fb_idx;
221         else
222             err = -1;
223 
224         ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->gld_fb_idx, new_fb);
225     }
226 
227     if (cm->refresh_golden_frame)
228         ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->gld_fb_idx, cm->new_fb_idx);
229 
230     if (cm->refresh_alt_ref_frame)
231         ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->alt_fb_idx, cm->new_fb_idx);
232 
233     if (cm->refresh_last_frame)
234     {
235         ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->lst_fb_idx, cm->new_fb_idx);
236 
237         cm->frame_to_show = &cm->yv12_fb[cm->lst_fb_idx];
238     }
239     else
240         cm->frame_to_show = &cm->yv12_fb[cm->new_fb_idx];
241 
242     cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
243 
244     return err;
245 }
246 
vp8dx_receive_compressed_data(VP8D_PTR ptr,unsigned long size,const unsigned char * source,INT64 time_stamp)247 int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsigned char *source, INT64 time_stamp)
248 {
249 #if HAVE_ARMV7
250     INT64 dx_store_reg[8];
251 #endif
252     VP8D_COMP *pbi = (VP8D_COMP *) ptr;
253     VP8_COMMON *cm = &pbi->common;
254     int retcode = 0;
255     struct vpx_usec_timer timer;
256 
257     /*if(pbi->ready_for_new_data == 0)
258         return -1;*/
259 
260     if (ptr == 0)
261     {
262         return -1;
263     }
264 
265     pbi->common.error.error_code = VPX_CODEC_OK;
266 
267     if (size == 0)
268     {
269        /* This is used to signal that we are missing frames.
270         * We do not know if the missing frame(s) was supposed to update
271         * any of the reference buffers, but we act conservative and
272         * mark only the last buffer as corrupted.
273         */
274         cm->yv12_fb[cm->lst_fb_idx].corrupted = 1;
275 
276         /* Signal that we have no frame to show. */
277         cm->show_frame = 0;
278 
279         /* Nothing more to do. */
280         return 0;
281     }
282 
283 
284 #if HAVE_ARMV7
285 #if CONFIG_RUNTIME_CPU_DETECT
286     if (cm->rtcd.flags & HAS_NEON)
287 #endif
288     {
289         vp8_push_neon(dx_store_reg);
290     }
291 #endif
292 
293     cm->new_fb_idx = get_free_fb (cm);
294 
295     if (setjmp(pbi->common.error.jmp))
296     {
297 #if HAVE_ARMV7
298 #if CONFIG_RUNTIME_CPU_DETECT
299         if (cm->rtcd.flags & HAS_NEON)
300 #endif
301         {
302             vp8_pop_neon(dx_store_reg);
303         }
304 #endif
305         pbi->common.error.setjmp = 0;
306 
307        /* We do not know if the missing frame(s) was supposed to update
308         * any of the reference buffers, but we act conservative and
309         * mark only the last buffer as corrupted.
310         */
311         cm->yv12_fb[cm->lst_fb_idx].corrupted = 1;
312 
313         if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
314           cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
315         return -1;
316     }
317 
318     pbi->common.error.setjmp = 1;
319 
320     vpx_usec_timer_start(&timer);
321 
322     /*cm->current_video_frame++;*/
323     pbi->Source = source;
324     pbi->source_sz = size;
325 
326     retcode = vp8_decode_frame(pbi);
327 
328     if (retcode < 0)
329     {
330 #if HAVE_ARMV7
331 #if CONFIG_RUNTIME_CPU_DETECT
332         if (cm->rtcd.flags & HAS_NEON)
333 #endif
334         {
335             vp8_pop_neon(dx_store_reg);
336         }
337 #endif
338         pbi->common.error.error_code = VPX_CODEC_ERROR;
339         pbi->common.error.setjmp = 0;
340         if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
341           cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
342         return retcode;
343     }
344 
345 #if CONFIG_MULTITHREAD
346     if (pbi->b_multithreaded_rd && cm->multi_token_partition != ONE_PARTITION)
347     {
348         if (swap_frame_buffers (cm))
349         {
350 #if HAVE_ARMV7
351 #if CONFIG_RUNTIME_CPU_DETECT
352             if (cm->rtcd.flags & HAS_NEON)
353 #endif
354             {
355                 vp8_pop_neon(dx_store_reg);
356             }
357 #endif
358             pbi->common.error.error_code = VPX_CODEC_ERROR;
359             pbi->common.error.setjmp = 0;
360             return -1;
361         }
362     } else
363 #endif
364     {
365         if (swap_frame_buffers (cm))
366         {
367 #if HAVE_ARMV7
368 #if CONFIG_RUNTIME_CPU_DETECT
369             if (cm->rtcd.flags & HAS_NEON)
370 #endif
371             {
372                 vp8_pop_neon(dx_store_reg);
373             }
374 #endif
375             pbi->common.error.error_code = VPX_CODEC_ERROR;
376             pbi->common.error.setjmp = 0;
377             return -1;
378         }
379 
380         if(pbi->common.filter_level)
381         {
382             struct vpx_usec_timer lpftimer;
383             vpx_usec_timer_start(&lpftimer);
384             /* Apply the loop filter if appropriate. */
385 
386             vp8_loop_filter_frame(cm, &pbi->mb, cm->filter_level);
387 
388             vpx_usec_timer_mark(&lpftimer);
389             pbi->time_loop_filtering += vpx_usec_timer_elapsed(&lpftimer);
390 
391             cm->last_frame_type = cm->frame_type;
392             cm->last_filter_type = cm->filter_type;
393             cm->last_sharpness_level = cm->sharpness_level;
394         }
395         vp8_yv12_extend_frame_borders_ptr(cm->frame_to_show);
396     }
397 
398 
399     vp8_clear_system_state();
400 
401     vpx_usec_timer_mark(&timer);
402     pbi->decode_microseconds = vpx_usec_timer_elapsed(&timer);
403 
404     pbi->time_decoding += pbi->decode_microseconds;
405 
406     /*vp8_print_modes_and_motion_vectors( cm->mi, cm->mb_rows,cm->mb_cols, cm->current_video_frame);*/
407 
408     if (cm->show_frame)
409         cm->current_video_frame++;
410 
411     pbi->ready_for_new_data = 0;
412     pbi->last_time_stamp = time_stamp;
413 
414 #if 0
415     {
416         int i;
417         INT64 earliest_time = pbi->dr[0].time_stamp;
418         INT64 latest_time = pbi->dr[0].time_stamp;
419         INT64 time_diff = 0;
420         int bytes = 0;
421 
422         pbi->dr[pbi->common.current_video_frame&0xf].size = pbi->bc.pos + pbi->bc2.pos + 4;;
423         pbi->dr[pbi->common.current_video_frame&0xf].time_stamp = time_stamp;
424 
425         for (i = 0; i < 16; i++)
426         {
427 
428             bytes += pbi->dr[i].size;
429 
430             if (pbi->dr[i].time_stamp < earliest_time)
431                 earliest_time = pbi->dr[i].time_stamp;
432 
433             if (pbi->dr[i].time_stamp > latest_time)
434                 latest_time = pbi->dr[i].time_stamp;
435         }
436 
437         time_diff = latest_time - earliest_time;
438 
439         if (time_diff > 0)
440         {
441             pbi->common.bitrate = 80000.00 * bytes / time_diff  ;
442             pbi->common.framerate = 160000000.00 / time_diff ;
443         }
444 
445     }
446 #endif
447 
448 #if HAVE_ARMV7
449 #if CONFIG_RUNTIME_CPU_DETECT
450     if (cm->rtcd.flags & HAS_NEON)
451 #endif
452     {
453         vp8_pop_neon(dx_store_reg);
454     }
455 #endif
456     pbi->common.error.setjmp = 0;
457     return retcode;
458 }
vp8dx_get_raw_frame(VP8D_PTR ptr,YV12_BUFFER_CONFIG * sd,INT64 * time_stamp,INT64 * time_end_stamp,vp8_ppflags_t * flags)459 int vp8dx_get_raw_frame(VP8D_PTR ptr, YV12_BUFFER_CONFIG *sd, INT64 *time_stamp, INT64 *time_end_stamp, vp8_ppflags_t *flags)
460 {
461     int ret = -1;
462     VP8D_COMP *pbi = (VP8D_COMP *) ptr;
463 
464     if (pbi->ready_for_new_data == 1)
465         return ret;
466 
467     /* ie no raw frame to show!!! */
468     if (pbi->common.show_frame == 0)
469         return ret;
470 
471     pbi->ready_for_new_data = 1;
472     *time_stamp = pbi->last_time_stamp;
473     *time_end_stamp = 0;
474 
475     sd->clrtype = pbi->common.clr_type;
476 #if CONFIG_POSTPROC
477     ret = vp8_post_proc_frame(&pbi->common, sd, flags);
478 #else
479 
480     if (pbi->common.frame_to_show)
481     {
482         *sd = *pbi->common.frame_to_show;
483         sd->y_width = pbi->common.Width;
484         sd->y_height = pbi->common.Height;
485         sd->uv_height = pbi->common.Height / 2;
486         ret = 0;
487     }
488     else
489     {
490         ret = -1;
491     }
492 
493 #endif /*!CONFIG_POSTPROC*/
494     vp8_clear_system_state();
495     return ret;
496 }
497