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