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