Home | History | Annotate | Download | only in decoder
      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 #include <assert.h>
     12 #include <limits.h>
     13 #include <stdio.h>
     14 
     15 #include "vp9/common/vp9_onyxc_int.h"
     16 #if CONFIG_VP9_POSTPROC
     17 #include "vp9/common/vp9_postproc.h"
     18 #endif
     19 #include "vp9/decoder/vp9_onyxd.h"
     20 #include "vp9/decoder/vp9_onyxd_int.h"
     21 #include "vpx_mem/vpx_mem.h"
     22 #include "vp9/common/vp9_alloccommon.h"
     23 #include "vp9/common/vp9_loopfilter.h"
     24 #include "vp9/common/vp9_quant_common.h"
     25 #include "vpx_scale/vpx_scale.h"
     26 #include "vp9/common/vp9_systemdependent.h"
     27 #include "vpx_ports/vpx_timer.h"
     28 #include "vp9/decoder/vp9_decodframe.h"
     29 #include "vp9/decoder/vp9_detokenize.h"
     30 #include "./vpx_scale_rtcd.h"
     31 
     32 #define WRITE_RECON_BUFFER 0
     33 #if WRITE_RECON_BUFFER == 1
     34 static void recon_write_yuv_frame(const char *name,
     35                                   const YV12_BUFFER_CONFIG *s,
     36                                   int w, int _h) {
     37   FILE *yuv_file = fopen(name, "ab");
     38   const uint8_t *src = s->y_buffer;
     39   int h = _h;
     40 
     41   do {
     42     fwrite(src, w, 1,  yuv_file);
     43     src += s->y_stride;
     44   } while (--h);
     45 
     46   src = s->u_buffer;
     47   h = (_h + 1) >> 1;
     48   w = (w + 1) >> 1;
     49 
     50   do {
     51     fwrite(src, w, 1,  yuv_file);
     52     src += s->uv_stride;
     53   } while (--h);
     54 
     55   src = s->v_buffer;
     56   h = (_h + 1) >> 1;
     57 
     58   do {
     59     fwrite(src, w, 1, yuv_file);
     60     src += s->uv_stride;
     61   } while (--h);
     62 
     63   fclose(yuv_file);
     64 }
     65 #endif
     66 #if WRITE_RECON_BUFFER == 2
     67 void write_dx_frame_to_file(YV12_BUFFER_CONFIG *frame, int this_frame) {
     68 
     69   // write the frame
     70   FILE *yframe;
     71   int i;
     72   char filename[255];
     73 
     74   sprintf(filename, "dx\\y%04d.raw", this_frame);
     75   yframe = fopen(filename, "wb");
     76 
     77   for (i = 0; i < frame->y_height; i++)
     78     fwrite(frame->y_buffer + i * frame->y_stride,
     79            frame->y_width, 1, yframe);
     80 
     81   fclose(yframe);
     82   sprintf(filename, "dx\\u%04d.raw", this_frame);
     83   yframe = fopen(filename, "wb");
     84 
     85   for (i = 0; i < frame->uv_height; i++)
     86     fwrite(frame->u_buffer + i * frame->uv_stride,
     87            frame->uv_width, 1, yframe);
     88 
     89   fclose(yframe);
     90   sprintf(filename, "dx\\v%04d.raw", this_frame);
     91   yframe = fopen(filename, "wb");
     92 
     93   for (i = 0; i < frame->uv_height; i++)
     94     fwrite(frame->v_buffer + i * frame->uv_stride,
     95            frame->uv_width, 1, yframe);
     96 
     97   fclose(yframe);
     98 }
     99 #endif
    100 
    101 void vp9_initialize_dec() {
    102   static int init_done = 0;
    103 
    104   if (!init_done) {
    105     vp9_initialize_common();
    106     vp9_init_quant_tables();
    107     init_done = 1;
    108   }
    109 }
    110 
    111 VP9D_PTR vp9_create_decompressor(VP9D_CONFIG *oxcf) {
    112   VP9D_COMP *const pbi = vpx_memalign(32, sizeof(VP9D_COMP));
    113   VP9_COMMON *const cm = pbi ? &pbi->common : NULL;
    114 
    115   if (!cm)
    116     return NULL;
    117 
    118   vp9_zero(*pbi);
    119 
    120   if (setjmp(cm->error.jmp)) {
    121     cm->error.setjmp = 0;
    122     vp9_remove_decompressor(pbi);
    123     return NULL;
    124   }
    125 
    126   cm->error.setjmp = 1;
    127   vp9_initialize_dec();
    128 
    129   vp9_create_common(cm);
    130 
    131   pbi->oxcf = *oxcf;
    132   pbi->ready_for_new_data = 1;
    133   cm->current_video_frame = 0;
    134 
    135   // vp9_init_dequantizer() is first called here. Add check in
    136   // frame_init_dequantizer() to avoid unnecessary calling of
    137   // vp9_init_dequantizer() for every frame.
    138   vp9_init_dequantizer(cm);
    139 
    140   vp9_loop_filter_init(cm);
    141 
    142   cm->error.setjmp = 0;
    143   pbi->decoded_key_frame = 0;
    144 
    145   if (pbi->oxcf.max_threads > 1) {
    146     vp9_worker_init(&pbi->lf_worker);
    147     pbi->lf_worker.data1 = vpx_malloc(sizeof(LFWorkerData));
    148     pbi->lf_worker.hook = (VP9WorkerHook)vp9_loop_filter_worker;
    149     if (pbi->lf_worker.data1 == NULL || !vp9_worker_reset(&pbi->lf_worker)) {
    150       vp9_remove_decompressor(pbi);
    151       return NULL;
    152     }
    153   }
    154 
    155   return pbi;
    156 }
    157 
    158 void vp9_remove_decompressor(VP9D_PTR ptr) {
    159   VP9D_COMP *const pbi = (VP9D_COMP *)ptr;
    160 
    161   if (!pbi)
    162     return;
    163 
    164   vp9_remove_common(&pbi->common);
    165   vp9_worker_end(&pbi->lf_worker);
    166   vpx_free(pbi->lf_worker.data1);
    167   vpx_free(pbi);
    168 }
    169 
    170 static int equal_dimensions(YV12_BUFFER_CONFIG *a, YV12_BUFFER_CONFIG *b) {
    171     return a->y_height == b->y_height && a->y_width == b->y_width &&
    172            a->uv_height == b->uv_height && a->uv_width == b->uv_width;
    173 }
    174 
    175 vpx_codec_err_t vp9_copy_reference_dec(VP9D_PTR ptr,
    176                                        VP9_REFFRAME ref_frame_flag,
    177                                        YV12_BUFFER_CONFIG *sd) {
    178   VP9D_COMP *pbi = (VP9D_COMP *) ptr;
    179   VP9_COMMON *cm = &pbi->common;
    180   int ref_fb_idx;
    181 
    182   /* TODO(jkoleszar): The decoder doesn't have any real knowledge of what the
    183    * encoder is using the frame buffers for. This is just a stub to keep the
    184    * vpxenc --test-decode functionality working, and will be replaced in a
    185    * later commit that adds VP9-specific controls for this functionality.
    186    */
    187   if (ref_frame_flag == VP9_LAST_FLAG) {
    188     ref_fb_idx = cm->ref_frame_map[0];
    189   } else {
    190     vpx_internal_error(&cm->error, VPX_CODEC_ERROR,
    191                        "Invalid reference frame");
    192     return cm->error.error_code;
    193   }
    194 
    195   if (!equal_dimensions(&cm->yv12_fb[ref_fb_idx], sd)) {
    196     vpx_internal_error(&cm->error, VPX_CODEC_ERROR,
    197                        "Incorrect buffer dimensions");
    198   } else {
    199     vp8_yv12_copy_frame(&cm->yv12_fb[ref_fb_idx], sd);
    200   }
    201 
    202   return cm->error.error_code;
    203 }
    204 
    205 
    206 vpx_codec_err_t vp9_set_reference_dec(VP9D_PTR ptr, VP9_REFFRAME ref_frame_flag,
    207                                       YV12_BUFFER_CONFIG *sd) {
    208   VP9D_COMP *pbi = (VP9D_COMP *) ptr;
    209   VP9_COMMON *cm = &pbi->common;
    210   int *ref_fb_ptr = NULL;
    211 
    212   /* TODO(jkoleszar): The decoder doesn't have any real knowledge of what the
    213    * encoder is using the frame buffers for. This is just a stub to keep the
    214    * vpxenc --test-decode functionality working, and will be replaced in a
    215    * later commit that adds VP9-specific controls for this functionality.
    216    */
    217   if (ref_frame_flag == VP9_LAST_FLAG)
    218     ref_fb_ptr = &pbi->common.active_ref_idx[0];
    219   else if (ref_frame_flag == VP9_GOLD_FLAG)
    220     ref_fb_ptr = &pbi->common.active_ref_idx[1];
    221   else if (ref_frame_flag == VP9_ALT_FLAG)
    222     ref_fb_ptr = &pbi->common.active_ref_idx[2];
    223   else {
    224     vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
    225                        "Invalid reference frame");
    226     return pbi->common.error.error_code;
    227   }
    228 
    229   if (!equal_dimensions(&cm->yv12_fb[*ref_fb_ptr], sd)) {
    230     vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
    231                        "Incorrect buffer dimensions");
    232   } else {
    233     // Find an empty frame buffer.
    234     const int free_fb = get_free_fb(cm);
    235     // Decrease fb_idx_ref_cnt since it will be increased again in
    236     // ref_cnt_fb() below.
    237     cm->fb_idx_ref_cnt[free_fb]--;
    238 
    239     // Manage the reference counters and copy image.
    240     ref_cnt_fb(cm->fb_idx_ref_cnt, ref_fb_ptr, free_fb);
    241     vp8_yv12_copy_frame(sd, &cm->yv12_fb[*ref_fb_ptr]);
    242   }
    243 
    244   return pbi->common.error.error_code;
    245 }
    246 
    247 
    248 int vp9_get_reference_dec(VP9D_PTR ptr, int index, YV12_BUFFER_CONFIG **fb) {
    249   VP9D_COMP *pbi = (VP9D_COMP *) ptr;
    250   VP9_COMMON *cm = &pbi->common;
    251 
    252   if (index < 0 || index >= NUM_REF_FRAMES)
    253     return -1;
    254 
    255   *fb = &cm->yv12_fb[cm->ref_frame_map[index]];
    256   return 0;
    257 }
    258 
    259 /* If any buffer updating is signaled it should be done here. */
    260 static void swap_frame_buffers(VP9D_COMP *pbi) {
    261   int ref_index = 0, mask;
    262   VP9_COMMON *const cm = &pbi->common;
    263 
    264   for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) {
    265     if (mask & 1)
    266       ref_cnt_fb(cm->fb_idx_ref_cnt, &cm->ref_frame_map[ref_index],
    267                  cm->new_fb_idx);
    268     ++ref_index;
    269   }
    270 
    271   cm->frame_to_show = &cm->yv12_fb[cm->new_fb_idx];
    272   cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
    273 
    274   // Invalidate these references until the next frame starts.
    275   for (ref_index = 0; ref_index < 3; ref_index++)
    276     cm->active_ref_idx[ref_index] = INT_MAX;
    277 }
    278 
    279 int vp9_receive_compressed_data(VP9D_PTR ptr,
    280                                 uint64_t size, const uint8_t **psource,
    281                                 int64_t time_stamp) {
    282   VP9D_COMP *pbi = (VP9D_COMP *) ptr;
    283   VP9_COMMON *cm = &pbi->common;
    284   const uint8_t *source = *psource;
    285   int retcode = 0;
    286 
    287   /*if(pbi->ready_for_new_data == 0)
    288       return -1;*/
    289 
    290   if (ptr == 0)
    291     return -1;
    292 
    293   cm->error.error_code = VPX_CODEC_OK;
    294 
    295   pbi->source = source;
    296   pbi->source_sz = size;
    297 
    298   if (pbi->source_sz == 0) {
    299     /* This is used to signal that we are missing frames.
    300      * We do not know if the missing frame(s) was supposed to update
    301      * any of the reference buffers, but we act conservative and
    302      * mark only the last buffer as corrupted.
    303      *
    304      * TODO(jkoleszar): Error concealment is undefined and non-normative
    305      * at this point, but if it becomes so, [0] may not always be the correct
    306      * thing to do here.
    307      */
    308     if (cm->active_ref_idx[0] != INT_MAX)
    309       cm->yv12_fb[cm->active_ref_idx[0]].corrupted = 1;
    310   }
    311 
    312   cm->new_fb_idx = get_free_fb(cm);
    313 
    314   if (setjmp(cm->error.jmp)) {
    315     cm->error.setjmp = 0;
    316 
    317     /* We do not know if the missing frame(s) was supposed to update
    318      * any of the reference buffers, but we act conservative and
    319      * mark only the last buffer as corrupted.
    320      *
    321      * TODO(jkoleszar): Error concealment is undefined and non-normative
    322      * at this point, but if it becomes so, [0] may not always be the correct
    323      * thing to do here.
    324      */
    325     if (cm->active_ref_idx[0] != INT_MAX)
    326       cm->yv12_fb[cm->active_ref_idx[0]].corrupted = 1;
    327 
    328     if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
    329       cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
    330 
    331     return -1;
    332   }
    333 
    334   cm->error.setjmp = 1;
    335 
    336   retcode = vp9_decode_frame(pbi, psource);
    337 
    338   if (retcode < 0) {
    339     cm->error.error_code = VPX_CODEC_ERROR;
    340     cm->error.setjmp = 0;
    341     if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
    342       cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
    343     return retcode;
    344   }
    345 
    346   {
    347     swap_frame_buffers(pbi);
    348 
    349 #if WRITE_RECON_BUFFER == 2
    350     if (cm->show_frame)
    351       write_dx_frame_to_file(cm->frame_to_show,
    352                              cm->current_video_frame);
    353     else
    354       write_dx_frame_to_file(cm->frame_to_show,
    355                              cm->current_video_frame + 1000);
    356 #endif
    357 
    358     if (!pbi->do_loopfilter_inline) {
    359       /* Apply the loop filter if appropriate. */
    360       vp9_loop_filter_frame(cm, &pbi->mb, pbi->common.lf.filter_level, 0, 0);
    361     }
    362 
    363 #if WRITE_RECON_BUFFER == 2
    364     if (cm->show_frame)
    365       write_dx_frame_to_file(cm->frame_to_show,
    366                              cm->current_video_frame + 2000);
    367     else
    368       write_dx_frame_to_file(cm->frame_to_show,
    369                              cm->current_video_frame + 3000);
    370 #endif
    371 
    372     vp9_extend_frame_inner_borders(cm->frame_to_show,
    373                                    cm->subsampling_x,
    374                                    cm->subsampling_y);
    375   }
    376 
    377 #if WRITE_RECON_BUFFER == 1
    378   if (cm->show_frame)
    379     recon_write_yuv_frame("recon.yuv", cm->frame_to_show,
    380                           cm->width, cm->height);
    381 #endif
    382 
    383   vp9_clear_system_state();
    384 
    385   cm->last_show_frame = cm->show_frame;
    386   if (cm->show_frame) {
    387     // current mip will be the prev_mip for the next frame
    388     MODE_INFO *temp = cm->prev_mip;
    389     MODE_INFO **temp2 = cm->prev_mi_grid_base;
    390     cm->prev_mip = cm->mip;
    391     cm->mip = temp;
    392     cm->prev_mi_grid_base = cm->mi_grid_base;
    393     cm->mi_grid_base = temp2;
    394 
    395     // update the upper left visible macroblock ptrs
    396     cm->mi = cm->mip + cm->mode_info_stride + 1;
    397     cm->prev_mi = cm->prev_mip + cm->mode_info_stride + 1;
    398     cm->mi_grid_visible = cm->mi_grid_base + cm->mode_info_stride + 1;
    399     cm->prev_mi_grid_visible = cm->prev_mi_grid_base + cm->mode_info_stride + 1;
    400 
    401     cm->current_video_frame++;
    402   }
    403 
    404   pbi->ready_for_new_data = 0;
    405   pbi->last_time_stamp = time_stamp;
    406   pbi->source_sz = 0;
    407 
    408   cm->error.setjmp = 0;
    409   return retcode;
    410 }
    411 
    412 int vp9_get_raw_frame(VP9D_PTR ptr, YV12_BUFFER_CONFIG *sd,
    413                       int64_t *time_stamp, int64_t *time_end_stamp,
    414                       vp9_ppflags_t *flags) {
    415   int ret = -1;
    416   VP9D_COMP *pbi = (VP9D_COMP *) ptr;
    417 
    418   if (pbi->ready_for_new_data == 1)
    419     return ret;
    420 
    421   /* ie no raw frame to show!!! */
    422   if (pbi->common.show_frame == 0)
    423     return ret;
    424 
    425   pbi->ready_for_new_data = 1;
    426   *time_stamp = pbi->last_time_stamp;
    427   *time_end_stamp = 0;
    428 
    429 #if CONFIG_VP9_POSTPROC
    430   ret = vp9_post_proc_frame(&pbi->common, sd, flags);
    431 #else
    432 
    433   if (pbi->common.frame_to_show) {
    434     *sd = *pbi->common.frame_to_show;
    435     sd->y_width = pbi->common.width;
    436     sd->y_height = pbi->common.height;
    437     sd->uv_width = sd->y_width >> pbi->common.subsampling_x;
    438     sd->uv_height = sd->y_height >> pbi->common.subsampling_y;
    439 
    440     ret = 0;
    441   } else {
    442     ret = -1;
    443   }
    444 
    445 #endif /*!CONFIG_POSTPROC*/
    446   vp9_clear_system_state();
    447   return ret;
    448 }
    449