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 "./vpx_scale_rtcd.h"
     16 
     17 #include "vpx_mem/vpx_mem.h"
     18 #include "vpx_ports/vpx_timer.h"
     19 #include "vpx_scale/vpx_scale.h"
     20 
     21 #include "vp9/common/vp9_alloccommon.h"
     22 #include "vp9/common/vp9_loopfilter.h"
     23 #include "vp9/common/vp9_onyxc_int.h"
     24 #if CONFIG_VP9_POSTPROC
     25 #include "vp9/common/vp9_postproc.h"
     26 #endif
     27 #include "vp9/common/vp9_quant_common.h"
     28 #include "vp9/common/vp9_systemdependent.h"
     29 
     30 #include "vp9/decoder/vp9_decodeframe.h"
     31 #include "vp9/decoder/vp9_decoder.h"
     32 #include "vp9/decoder/vp9_detokenize.h"
     33 #include "vp9/decoder/vp9_dthread.h"
     34 
     35 static void initialize_dec() {
     36   static int init_done = 0;
     37 
     38   if (!init_done) {
     39     vp9_init_neighbors();
     40     init_done = 1;
     41   }
     42 }
     43 
     44 VP9Decoder *vp9_decoder_create() {
     45   VP9Decoder *const pbi = vpx_memalign(32, sizeof(*pbi));
     46   VP9_COMMON *const cm = pbi ? &pbi->common : NULL;
     47 
     48   if (!cm)
     49     return NULL;
     50 
     51   vp9_zero(*pbi);
     52 
     53   if (setjmp(cm->error.jmp)) {
     54     cm->error.setjmp = 0;
     55     vp9_decoder_remove(pbi);
     56     return NULL;
     57   }
     58 
     59   cm->error.setjmp = 1;
     60   initialize_dec();
     61 
     62   vp9_rtcd();
     63 
     64   // Initialize the references to not point to any frame buffers.
     65   vpx_memset(&cm->ref_frame_map, -1, sizeof(cm->ref_frame_map));
     66 
     67   cm->current_video_frame = 0;
     68   pbi->ready_for_new_data = 1;
     69 
     70   // vp9_init_dequantizer() is first called here. Add check in
     71   // frame_init_dequantizer() to avoid unnecessary calling of
     72   // vp9_init_dequantizer() for every frame.
     73   vp9_init_dequantizer(cm);
     74 
     75   vp9_loop_filter_init(cm);
     76 
     77   cm->error.setjmp = 0;
     78 
     79   vp9_get_worker_interface()->init(&pbi->lf_worker);
     80 
     81   return pbi;
     82 }
     83 
     84 void vp9_decoder_remove(VP9Decoder *pbi) {
     85   VP9_COMMON *const cm = &pbi->common;
     86   int i;
     87 
     88   vp9_get_worker_interface()->end(&pbi->lf_worker);
     89   vpx_free(pbi->lf_worker.data1);
     90   vpx_free(pbi->tile_data);
     91   for (i = 0; i < pbi->num_tile_workers; ++i) {
     92     VP9Worker *const worker = &pbi->tile_workers[i];
     93     vp9_get_worker_interface()->end(worker);
     94     vpx_free(worker->data1);
     95     vpx_free(worker->data2);
     96   }
     97   vpx_free(pbi->tile_workers);
     98 
     99   if (pbi->num_tile_workers) {
    100     const int sb_rows =
    101         mi_cols_aligned_to_sb(cm->mi_rows) >> MI_BLOCK_SIZE_LOG2;
    102     vp9_loop_filter_dealloc(&pbi->lf_row_sync, sb_rows);
    103   }
    104 
    105   vp9_remove_common(cm);
    106   vpx_free(pbi);
    107 }
    108 
    109 static int equal_dimensions(const YV12_BUFFER_CONFIG *a,
    110                             const YV12_BUFFER_CONFIG *b) {
    111     return a->y_height == b->y_height && a->y_width == b->y_width &&
    112            a->uv_height == b->uv_height && a->uv_width == b->uv_width;
    113 }
    114 
    115 vpx_codec_err_t vp9_copy_reference_dec(VP9Decoder *pbi,
    116                                        VP9_REFFRAME ref_frame_flag,
    117                                        YV12_BUFFER_CONFIG *sd) {
    118   VP9_COMMON *cm = &pbi->common;
    119 
    120   /* TODO(jkoleszar): The decoder doesn't have any real knowledge of what the
    121    * encoder is using the frame buffers for. This is just a stub to keep the
    122    * vpxenc --test-decode functionality working, and will be replaced in a
    123    * later commit that adds VP9-specific controls for this functionality.
    124    */
    125   if (ref_frame_flag == VP9_LAST_FLAG) {
    126     const YV12_BUFFER_CONFIG *const cfg =
    127         &cm->frame_bufs[cm->ref_frame_map[0]].buf;
    128     if (!equal_dimensions(cfg, sd))
    129       vpx_internal_error(&cm->error, VPX_CODEC_ERROR,
    130                          "Incorrect buffer dimensions");
    131     else
    132       vp8_yv12_copy_frame(cfg, sd);
    133   } else {
    134     vpx_internal_error(&cm->error, VPX_CODEC_ERROR,
    135                        "Invalid reference frame");
    136   }
    137 
    138   return cm->error.error_code;
    139 }
    140 
    141 
    142 vpx_codec_err_t vp9_set_reference_dec(VP9_COMMON *cm,
    143                                       VP9_REFFRAME ref_frame_flag,
    144                                       YV12_BUFFER_CONFIG *sd) {
    145   RefBuffer *ref_buf = NULL;
    146 
    147   // TODO(jkoleszar): The decoder doesn't have any real knowledge of what the
    148   // encoder is using the frame buffers for. This is just a stub to keep the
    149   // vpxenc --test-decode functionality working, and will be replaced in a
    150   // later commit that adds VP9-specific controls for this functionality.
    151   if (ref_frame_flag == VP9_LAST_FLAG) {
    152     ref_buf = &cm->frame_refs[0];
    153   } else if (ref_frame_flag == VP9_GOLD_FLAG) {
    154     ref_buf = &cm->frame_refs[1];
    155   } else if (ref_frame_flag == VP9_ALT_FLAG) {
    156     ref_buf = &cm->frame_refs[2];
    157   } else {
    158     vpx_internal_error(&cm->error, VPX_CODEC_ERROR,
    159                        "Invalid reference frame");
    160     return cm->error.error_code;
    161   }
    162 
    163   if (!equal_dimensions(ref_buf->buf, sd)) {
    164     vpx_internal_error(&cm->error, VPX_CODEC_ERROR,
    165                        "Incorrect buffer dimensions");
    166   } else {
    167     int *ref_fb_ptr = &ref_buf->idx;
    168 
    169     // Find an empty frame buffer.
    170     const int free_fb = get_free_fb(cm);
    171     // Decrease ref_count since it will be increased again in
    172     // ref_cnt_fb() below.
    173     cm->frame_bufs[free_fb].ref_count--;
    174 
    175     // Manage the reference counters and copy image.
    176     ref_cnt_fb(cm->frame_bufs, ref_fb_ptr, free_fb);
    177     ref_buf->buf = &cm->frame_bufs[*ref_fb_ptr].buf;
    178     vp8_yv12_copy_frame(sd, ref_buf->buf);
    179   }
    180 
    181   return cm->error.error_code;
    182 }
    183 
    184 /* If any buffer updating is signaled it should be done here. */
    185 static void swap_frame_buffers(VP9Decoder *pbi) {
    186   int ref_index = 0, mask;
    187   VP9_COMMON *const cm = &pbi->common;
    188 
    189   for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) {
    190     if (mask & 1) {
    191       const int old_idx = cm->ref_frame_map[ref_index];
    192       ref_cnt_fb(cm->frame_bufs, &cm->ref_frame_map[ref_index],
    193                  cm->new_fb_idx);
    194       if (old_idx >= 0 && cm->frame_bufs[old_idx].ref_count == 0)
    195         cm->release_fb_cb(cm->cb_priv,
    196                           &cm->frame_bufs[old_idx].raw_frame_buffer);
    197     }
    198     ++ref_index;
    199   }
    200 
    201   cm->frame_to_show = get_frame_new_buffer(cm);
    202   cm->frame_bufs[cm->new_fb_idx].ref_count--;
    203 
    204   // Invalidate these references until the next frame starts.
    205   for (ref_index = 0; ref_index < 3; ref_index++)
    206     cm->frame_refs[ref_index].idx = INT_MAX;
    207 }
    208 
    209 int vp9_receive_compressed_data(VP9Decoder *pbi,
    210                                 size_t size, const uint8_t **psource) {
    211   VP9_COMMON *const cm = &pbi->common;
    212   const uint8_t *source = *psource;
    213   int retcode = 0;
    214 
    215   cm->error.error_code = VPX_CODEC_OK;
    216 
    217   if (size == 0) {
    218     // This is used to signal that we are missing frames.
    219     // We do not know if the missing frame(s) was supposed to update
    220     // any of the reference buffers, but we act conservative and
    221     // mark only the last buffer as corrupted.
    222     //
    223     // TODO(jkoleszar): Error concealment is undefined and non-normative
    224     // at this point, but if it becomes so, [0] may not always be the correct
    225     // thing to do here.
    226     if (cm->frame_refs[0].idx != INT_MAX)
    227       cm->frame_refs[0].buf->corrupted = 1;
    228   }
    229 
    230   // Check if the previous frame was a frame without any references to it.
    231   if (cm->new_fb_idx >= 0 && cm->frame_bufs[cm->new_fb_idx].ref_count == 0)
    232     cm->release_fb_cb(cm->cb_priv,
    233                       &cm->frame_bufs[cm->new_fb_idx].raw_frame_buffer);
    234   cm->new_fb_idx = get_free_fb(cm);
    235 
    236   if (setjmp(cm->error.jmp)) {
    237     cm->error.setjmp = 0;
    238     vp9_clear_system_state();
    239 
    240     // We do not know if the missing frame(s) was supposed to update
    241     // any of the reference buffers, but we act conservative and
    242     // mark only the last buffer as corrupted.
    243     //
    244     // TODO(jkoleszar): Error concealment is undefined and non-normative
    245     // at this point, but if it becomes so, [0] may not always be the correct
    246     // thing to do here.
    247     if (cm->frame_refs[0].idx != INT_MAX && cm->frame_refs[0].buf != NULL)
    248       cm->frame_refs[0].buf->corrupted = 1;
    249 
    250     if (cm->new_fb_idx > 0 && cm->frame_bufs[cm->new_fb_idx].ref_count > 0)
    251       cm->frame_bufs[cm->new_fb_idx].ref_count--;
    252 
    253     return -1;
    254   }
    255 
    256   cm->error.setjmp = 1;
    257 
    258   vp9_decode_frame(pbi, source, source + size, psource);
    259 
    260   swap_frame_buffers(pbi);
    261 
    262   vp9_clear_system_state();
    263 
    264   cm->last_width = cm->width;
    265   cm->last_height = cm->height;
    266 
    267   if (!cm->show_existing_frame)
    268     cm->last_show_frame = cm->show_frame;
    269   if (cm->show_frame) {
    270     if (!cm->show_existing_frame)
    271       vp9_swap_mi_and_prev_mi(cm);
    272 
    273     cm->current_video_frame++;
    274   }
    275 
    276   pbi->ready_for_new_data = 0;
    277 
    278   cm->error.setjmp = 0;
    279   return retcode;
    280 }
    281 
    282 int vp9_get_raw_frame(VP9Decoder *pbi, YV12_BUFFER_CONFIG *sd,
    283                       vp9_ppflags_t *flags) {
    284   VP9_COMMON *const cm = &pbi->common;
    285   int ret = -1;
    286 #if !CONFIG_VP9_POSTPROC
    287   (void)*flags;
    288 #endif
    289 
    290   if (pbi->ready_for_new_data == 1)
    291     return ret;
    292 
    293   /* no raw frame to show!!! */
    294   if (!cm->show_frame)
    295     return ret;
    296 
    297   pbi->ready_for_new_data = 1;
    298 
    299 #if CONFIG_VP9_POSTPROC
    300   if (!cm->show_existing_frame) {
    301     ret = vp9_post_proc_frame(cm, sd, flags);
    302   } else {
    303     *sd = *cm->frame_to_show;
    304     ret = 0;
    305   }
    306 #else
    307   *sd = *cm->frame_to_show;
    308   ret = 0;
    309 #endif /*!CONFIG_POSTPROC*/
    310   vp9_clear_system_state();
    311   return ret;
    312 }
    313