PageRenderTime 51ms CodeModel.GetById 18ms app.highlight 28ms RepoModel.GetById 1ms app.codeStats 0ms

/media/libvpx/vp8/decoder/onyxd_if.c

http://github.com/zpao/v8monkey
C | 597 lines | 442 code | 101 blank | 54 comment | 96 complexity | 4fb63de99f41f7c9d0ed1bd1a2843170 MD5 | raw file
  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
 41extern void vp8_init_loop_filter(VP8_COMMON *cm);
 42extern void vp8cx_init_de_quantizer(VP8D_COMP *pbi);
 43static int get_free_fb (VP8_COMMON *cm);
 44static void ref_cnt_fb (int *buf, int *idx, int new_idx);
 45
 46
 47void 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
 60VP8D_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    vp8_loop_filter_init(&pbi->common);
 96
 97    pbi->common.error.setjmp = 0;
 98
 99#if CONFIG_ERROR_CONCEALMENT
100    pbi->ec_enabled = oxcf->error_concealment;
101#else
102    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    pbi->ec_active = 0;
108
109    pbi->decoded_key_frame = 0;
110
111    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    pbi->independent_partitions = 0;
118
119    return (VP8D_PTR) pbi;
120}
121
122
123void vp8dx_remove_decompressor(VP8D_PTR ptr)
124{
125    VP8D_COMP *pbi = (VP8D_COMP *) ptr;
126
127    if (!pbi)
128        return;
129
130#if CONFIG_MULTITHREAD
131    if (pbi->b_multithreaded_rd)
132        vp8mt_de_alloc_temp_buffers(pbi, pbi->common.mb_rows);
133    vp8_decoder_remove_threads(pbi);
134#endif
135#if CONFIG_ERROR_CONCEALMENT
136    vp8_de_alloc_overlap_lists(pbi);
137#endif
138    vp8_remove_common(&pbi->common);
139    vpx_free(pbi->mbc);
140    vpx_free(pbi);
141}
142
143
144vpx_codec_err_t vp8dx_get_reference(VP8D_PTR ptr, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd)
145{
146    VP8D_COMP *pbi = (VP8D_COMP *) ptr;
147    VP8_COMMON *cm = &pbi->common;
148    int ref_fb_idx;
149
150    if (ref_frame_flag == VP8_LAST_FLAG)
151        ref_fb_idx = cm->lst_fb_idx;
152    else if (ref_frame_flag == VP8_GOLD_FLAG)
153        ref_fb_idx = cm->gld_fb_idx;
154    else if (ref_frame_flag == VP8_ALT_FLAG)
155        ref_fb_idx = cm->alt_fb_idx;
156    else{
157        vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
158            "Invalid reference frame");
159        return pbi->common.error.error_code;
160    }
161
162    if(cm->yv12_fb[ref_fb_idx].y_height != sd->y_height ||
163        cm->yv12_fb[ref_fb_idx].y_width != sd->y_width ||
164        cm->yv12_fb[ref_fb_idx].uv_height != sd->uv_height ||
165        cm->yv12_fb[ref_fb_idx].uv_width != sd->uv_width){
166        vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
167            "Incorrect buffer dimensions");
168    }
169    else
170        vp8_yv12_copy_frame_ptr(&cm->yv12_fb[ref_fb_idx], sd);
171
172    return pbi->common.error.error_code;
173}
174
175
176vpx_codec_err_t vp8dx_set_reference(VP8D_PTR ptr, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd)
177{
178    VP8D_COMP *pbi = (VP8D_COMP *) ptr;
179    VP8_COMMON *cm = &pbi->common;
180    int *ref_fb_ptr = NULL;
181    int free_fb;
182
183    if (ref_frame_flag == VP8_LAST_FLAG)
184        ref_fb_ptr = &cm->lst_fb_idx;
185    else if (ref_frame_flag == VP8_GOLD_FLAG)
186        ref_fb_ptr = &cm->gld_fb_idx;
187    else if (ref_frame_flag == VP8_ALT_FLAG)
188        ref_fb_ptr = &cm->alt_fb_idx;
189    else{
190        vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
191            "Invalid reference frame");
192        return pbi->common.error.error_code;
193    }
194
195    if(cm->yv12_fb[*ref_fb_ptr].y_height != sd->y_height ||
196        cm->yv12_fb[*ref_fb_ptr].y_width != sd->y_width ||
197        cm->yv12_fb[*ref_fb_ptr].uv_height != sd->uv_height ||
198        cm->yv12_fb[*ref_fb_ptr].uv_width != sd->uv_width){
199        vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
200            "Incorrect buffer dimensions");
201    }
202    else{
203        /* Find an empty frame buffer. */
204        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        cm->fb_idx_ref_cnt[free_fb]--;
208
209        /* Manage the reference counters and copy image. */
210        ref_cnt_fb (cm->fb_idx_ref_cnt, ref_fb_ptr, free_fb);
211        vp8_yv12_copy_frame_ptr(sd, &cm->yv12_fb[*ref_fb_ptr]);
212    }
213
214   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
219extern void vp8_push_neon(int64_t *store);
220extern void vp8_pop_neon(int64_t *store);
221#endif
222
223static int get_free_fb (VP8_COMMON *cm)
224{
225    int i;
226    for (i = 0; i < NUM_YV12_BUFFERS; i++)
227        if (cm->fb_idx_ref_cnt[i] == 0)
228            break;
229
230    assert(i < NUM_YV12_BUFFERS);
231    cm->fb_idx_ref_cnt[i] = 1;
232    return i;
233}
234
235static void ref_cnt_fb (int *buf, int *idx, int new_idx)
236{
237    if (buf[*idx] > 0)
238        buf[*idx]--;
239
240    *idx = new_idx;
241
242    buf[new_idx]++;
243}
244
245/* If any buffer copy / swapping is signalled it should be done here. */
246static int swap_frame_buffers (VP8_COMMON *cm)
247{
248    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    if (cm->copy_buffer_to_arf)
256    {
257        int new_fb = 0;
258
259        if (cm->copy_buffer_to_arf == 1)
260            new_fb = cm->lst_fb_idx;
261        else if (cm->copy_buffer_to_arf == 2)
262            new_fb = cm->gld_fb_idx;
263        else
264            err = -1;
265
266        ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->alt_fb_idx, new_fb);
267    }
268
269    if (cm->copy_buffer_to_gf)
270    {
271        int new_fb = 0;
272
273        if (cm->copy_buffer_to_gf == 1)
274            new_fb = cm->lst_fb_idx;
275        else if (cm->copy_buffer_to_gf == 2)
276            new_fb = cm->alt_fb_idx;
277        else
278            err = -1;
279
280        ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->gld_fb_idx, new_fb);
281    }
282
283    if (cm->refresh_golden_frame)
284        ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->gld_fb_idx, cm->new_fb_idx);
285
286    if (cm->refresh_alt_ref_frame)
287        ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->alt_fb_idx, cm->new_fb_idx);
288
289    if (cm->refresh_last_frame)
290    {
291        ref_cnt_fb (cm->fb_idx_ref_cnt, &cm->lst_fb_idx, cm->new_fb_idx);
292
293        cm->frame_to_show = &cm->yv12_fb[cm->lst_fb_idx];
294    }
295    else
296        cm->frame_to_show = &cm->yv12_fb[cm->new_fb_idx];
297
298    cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
299
300    return err;
301}
302
303int 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    VP8D_COMP *pbi = (VP8D_COMP *) ptr;
309    VP8_COMMON *cm = &pbi->common;
310    int retcode = 0;
311
312    /*if(pbi->ready_for_new_data == 0)
313        return -1;*/
314
315    if (ptr == 0)
316    {
317        return -1;
318    }
319
320    pbi->common.error.error_code = VPX_CODEC_OK;
321
322    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        pbi->partitions[pbi->num_partitions] = source;
328        pbi->partition_sizes[pbi->num_partitions] = size;
329        pbi->source_sz += size;
330        pbi->num_partitions++;
331        if (pbi->num_partitions > (1<<pbi->common.multi_token_partition) + 1)
332            pbi->common.multi_token_partition++;
333        if (pbi->common.multi_token_partition > EIGHT_PARTITION)
334        {
335            pbi->common.error.error_code = VPX_CODEC_UNSUP_BITSTREAM;
336            pbi->common.error.setjmp = 0;
337            return -1;
338        }
339        return 0;
340    }
341    else
342    {
343        if (!pbi->input_partition)
344        {
345            pbi->Source = source;
346            pbi->source_sz = size;
347        }
348
349        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            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            if (!pbi->ec_active)
362            {
363                /* Signal that we have no frame to show. */
364                cm->show_frame = 0;
365
366                pbi->num_partitions = 0;
367                if (pbi->input_partition)
368                    pbi->common.multi_token_partition = 0;
369
370                /* Nothing more to do. */
371                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        cm->new_fb_idx = get_free_fb (cm);
385
386        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            pbi->common.error.setjmp = 0;
397
398            pbi->num_partitions = 0;
399            if (pbi->input_partition)
400                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            cm->yv12_fb[cm->lst_fb_idx].corrupted = 1;
407
408            if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
409              cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
410            return -1;
411        }
412
413        pbi->common.error.setjmp = 1;
414    }
415
416    retcode = vp8_decode_frame(pbi);
417
418    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        pbi->common.error.error_code = VPX_CODEC_ERROR;
429        pbi->common.error.setjmp = 0;
430        if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
431          cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
432        return retcode;
433    }
434
435#if CONFIG_MULTITHREAD
436    if (pbi->b_multithreaded_rd && cm->multi_token_partition != ONE_PARTITION)
437    {
438        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            pbi->common.error.error_code = VPX_CODEC_ERROR;
449            pbi->common.error.setjmp = 0;
450            return -1;
451        }
452    } else
453#endif
454    {
455        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            pbi->common.error.error_code = VPX_CODEC_ERROR;
466            pbi->common.error.setjmp = 0;
467            return -1;
468        }
469
470        if(cm->filter_level)
471        {
472            /* Apply the loop filter if appropriate. */
473            vp8_loop_filter_frame(cm, &pbi->mb);
474        }
475        vp8_yv12_extend_frame_borders_ptr(cm->frame_to_show);
476    }
477
478
479    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    if (cm->show_frame)
506        cm->current_video_frame++;
507
508    pbi->ready_for_new_data = 0;
509    pbi->last_time_stamp = time_stamp;
510    pbi->num_partitions = 0;
511    if (pbi->input_partition)
512        pbi->common.multi_token_partition = 0;
513    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    pbi->common.error.setjmp = 0;
558    return retcode;
559}
560int 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    int ret = -1;
563    VP8D_COMP *pbi = (VP8D_COMP *) ptr;
564
565    if (pbi->ready_for_new_data == 1)
566        return ret;
567
568    /* ie no raw frame to show!!! */
569    if (pbi->common.show_frame == 0)
570        return ret;
571
572    pbi->ready_for_new_data = 1;
573    *time_stamp = pbi->last_time_stamp;
574    *time_end_stamp = 0;
575
576    sd->clrtype = pbi->common.clr_type;
577#if CONFIG_POSTPROC
578    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    vp8_clear_system_state();
596    return ret;
597}