media/libvpx/vp9/decoder/vp9_onyxd_if.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/media/libvpx/vp9/decoder/vp9_onyxd_if.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,460 @@
     1.4 +/*
     1.5 + *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
     1.6 + *
     1.7 + *  Use of this source code is governed by a BSD-style license
     1.8 + *  that can be found in the LICENSE file in the root of the source
     1.9 + *  tree. An additional intellectual property rights grant can be found
    1.10 + *  in the file PATENTS.  All contributing project authors may
    1.11 + *  be found in the AUTHORS file in the root of the source tree.
    1.12 + */
    1.13 +
    1.14 +#include <assert.h>
    1.15 +#include <limits.h>
    1.16 +#include <stdio.h>
    1.17 +
    1.18 +#include "vp9/common/vp9_onyxc_int.h"
    1.19 +#if CONFIG_VP9_POSTPROC
    1.20 +#include "vp9/common/vp9_postproc.h"
    1.21 +#endif
    1.22 +#include "vp9/decoder/vp9_onyxd.h"
    1.23 +#include "vp9/decoder/vp9_onyxd_int.h"
    1.24 +#include "vpx_mem/vpx_mem.h"
    1.25 +#include "vp9/common/vp9_alloccommon.h"
    1.26 +#include "vp9/common/vp9_loopfilter.h"
    1.27 +#include "vp9/common/vp9_quant_common.h"
    1.28 +#include "vpx_scale/vpx_scale.h"
    1.29 +#include "vp9/common/vp9_systemdependent.h"
    1.30 +#include "vpx_ports/vpx_timer.h"
    1.31 +#include "vp9/decoder/vp9_decodframe.h"
    1.32 +#include "vp9/decoder/vp9_detokenize.h"
    1.33 +#include "./vpx_scale_rtcd.h"
    1.34 +
    1.35 +#define WRITE_RECON_BUFFER 0
    1.36 +#if WRITE_RECON_BUFFER == 1
    1.37 +static void recon_write_yuv_frame(const char *name,
    1.38 +                                  const YV12_BUFFER_CONFIG *s,
    1.39 +                                  int w, int _h) {
    1.40 +  FILE *yuv_file = fopen(name, "ab");
    1.41 +  const uint8_t *src = s->y_buffer;
    1.42 +  int h = _h;
    1.43 +
    1.44 +  do {
    1.45 +    fwrite(src, w, 1,  yuv_file);
    1.46 +    src += s->y_stride;
    1.47 +  } while (--h);
    1.48 +
    1.49 +  src = s->u_buffer;
    1.50 +  h = (_h + 1) >> 1;
    1.51 +  w = (w + 1) >> 1;
    1.52 +
    1.53 +  do {
    1.54 +    fwrite(src, w, 1,  yuv_file);
    1.55 +    src += s->uv_stride;
    1.56 +  } while (--h);
    1.57 +
    1.58 +  src = s->v_buffer;
    1.59 +  h = (_h + 1) >> 1;
    1.60 +
    1.61 +  do {
    1.62 +    fwrite(src, w, 1, yuv_file);
    1.63 +    src += s->uv_stride;
    1.64 +  } while (--h);
    1.65 +
    1.66 +  fclose(yuv_file);
    1.67 +}
    1.68 +#endif
    1.69 +#if WRITE_RECON_BUFFER == 2
    1.70 +void write_dx_frame_to_file(YV12_BUFFER_CONFIG *frame, int this_frame) {
    1.71 +  // write the frame
    1.72 +  FILE *yframe;
    1.73 +  int i;
    1.74 +  char filename[255];
    1.75 +
    1.76 +  snprintf(filename, sizeof(filename)-1, "dx\\y%04d.raw", this_frame);
    1.77 +  yframe = fopen(filename, "wb");
    1.78 +
    1.79 +  for (i = 0; i < frame->y_height; i++)
    1.80 +    fwrite(frame->y_buffer + i * frame->y_stride,
    1.81 +           frame->y_width, 1, yframe);
    1.82 +
    1.83 +  fclose(yframe);
    1.84 +  snprintf(filename, sizeof(filename)-1, "dx\\u%04d.raw", this_frame);
    1.85 +  yframe = fopen(filename, "wb");
    1.86 +
    1.87 +  for (i = 0; i < frame->uv_height; i++)
    1.88 +    fwrite(frame->u_buffer + i * frame->uv_stride,
    1.89 +           frame->uv_width, 1, yframe);
    1.90 +
    1.91 +  fclose(yframe);
    1.92 +  snprintf(filename, sizeof(filename)-1, "dx\\v%04d.raw", this_frame);
    1.93 +  yframe = fopen(filename, "wb");
    1.94 +
    1.95 +  for (i = 0; i < frame->uv_height; i++)
    1.96 +    fwrite(frame->v_buffer + i * frame->uv_stride,
    1.97 +           frame->uv_width, 1, yframe);
    1.98 +
    1.99 +  fclose(yframe);
   1.100 +}
   1.101 +#endif
   1.102 +
   1.103 +void vp9_initialize_dec() {
   1.104 +  static int init_done = 0;
   1.105 +
   1.106 +  if (!init_done) {
   1.107 +    vp9_initialize_common();
   1.108 +    vp9_init_quant_tables();
   1.109 +    init_done = 1;
   1.110 +  }
   1.111 +}
   1.112 +
   1.113 +static void init_macroblockd(VP9D_COMP *const pbi) {
   1.114 +  MACROBLOCKD *xd = &pbi->mb;
   1.115 +  struct macroblockd_plane *const pd = xd->plane;
   1.116 +  int i;
   1.117 +
   1.118 +  for (i = 0; i < MAX_MB_PLANE; ++i) {
   1.119 +    pd[i].qcoeff  = pbi->qcoeff[i];
   1.120 +    pd[i].dqcoeff = pbi->dqcoeff[i];
   1.121 +    pd[i].eobs    = pbi->eobs[i];
   1.122 +  }
   1.123 +}
   1.124 +
   1.125 +VP9D_PTR vp9_create_decompressor(VP9D_CONFIG *oxcf) {
   1.126 +  VP9D_COMP *const pbi = vpx_memalign(32, sizeof(VP9D_COMP));
   1.127 +  VP9_COMMON *const cm = pbi ? &pbi->common : NULL;
   1.128 +
   1.129 +  if (!cm)
   1.130 +    return NULL;
   1.131 +
   1.132 +  vp9_zero(*pbi);
   1.133 +
   1.134 +  if (setjmp(cm->error.jmp)) {
   1.135 +    cm->error.setjmp = 0;
   1.136 +    vp9_remove_decompressor(pbi);
   1.137 +    return NULL;
   1.138 +  }
   1.139 +
   1.140 +  cm->error.setjmp = 1;
   1.141 +  vp9_initialize_dec();
   1.142 +
   1.143 +  vp9_create_common(cm);
   1.144 +
   1.145 +  pbi->oxcf = *oxcf;
   1.146 +  pbi->ready_for_new_data = 1;
   1.147 +  cm->current_video_frame = 0;
   1.148 +
   1.149 +  // vp9_init_dequantizer() is first called here. Add check in
   1.150 +  // frame_init_dequantizer() to avoid unnecessary calling of
   1.151 +  // vp9_init_dequantizer() for every frame.
   1.152 +  vp9_init_dequantizer(cm);
   1.153 +
   1.154 +  vp9_loop_filter_init(cm);
   1.155 +
   1.156 +  cm->error.setjmp = 0;
   1.157 +  pbi->decoded_key_frame = 0;
   1.158 +
   1.159 +  init_macroblockd(pbi);
   1.160 +
   1.161 +  vp9_worker_init(&pbi->lf_worker);
   1.162 +
   1.163 +  return pbi;
   1.164 +}
   1.165 +
   1.166 +void vp9_remove_decompressor(VP9D_PTR ptr) {
   1.167 +  int i;
   1.168 +  VP9D_COMP *const pbi = (VP9D_COMP *)ptr;
   1.169 +
   1.170 +  if (!pbi)
   1.171 +    return;
   1.172 +
   1.173 +  vp9_remove_common(&pbi->common);
   1.174 +  vp9_worker_end(&pbi->lf_worker);
   1.175 +  vpx_free(pbi->lf_worker.data1);
   1.176 +  for (i = 0; i < pbi->num_tile_workers; ++i) {
   1.177 +    VP9Worker *const worker = &pbi->tile_workers[i];
   1.178 +    vp9_worker_end(worker);
   1.179 +    vpx_free(worker->data1);
   1.180 +    vpx_free(worker->data2);
   1.181 +  }
   1.182 +  vpx_free(pbi->tile_workers);
   1.183 +  vpx_free(pbi->mi_streams);
   1.184 +  vpx_free(pbi->above_context[0]);
   1.185 +  vpx_free(pbi->above_seg_context);
   1.186 +  vpx_free(pbi);
   1.187 +}
   1.188 +
   1.189 +static int equal_dimensions(YV12_BUFFER_CONFIG *a, YV12_BUFFER_CONFIG *b) {
   1.190 +    return a->y_height == b->y_height && a->y_width == b->y_width &&
   1.191 +           a->uv_height == b->uv_height && a->uv_width == b->uv_width;
   1.192 +}
   1.193 +
   1.194 +vpx_codec_err_t vp9_copy_reference_dec(VP9D_PTR ptr,
   1.195 +                                       VP9_REFFRAME ref_frame_flag,
   1.196 +                                       YV12_BUFFER_CONFIG *sd) {
   1.197 +  VP9D_COMP *pbi = (VP9D_COMP *) ptr;
   1.198 +  VP9_COMMON *cm = &pbi->common;
   1.199 +
   1.200 +  /* TODO(jkoleszar): The decoder doesn't have any real knowledge of what the
   1.201 +   * encoder is using the frame buffers for. This is just a stub to keep the
   1.202 +   * vpxenc --test-decode functionality working, and will be replaced in a
   1.203 +   * later commit that adds VP9-specific controls for this functionality.
   1.204 +   */
   1.205 +  if (ref_frame_flag == VP9_LAST_FLAG) {
   1.206 +    YV12_BUFFER_CONFIG *cfg = &cm->yv12_fb[cm->ref_frame_map[0]];
   1.207 +    if (!equal_dimensions(cfg, sd))
   1.208 +      vpx_internal_error(&cm->error, VPX_CODEC_ERROR,
   1.209 +                         "Incorrect buffer dimensions");
   1.210 +    else
   1.211 +      vp8_yv12_copy_frame(cfg, sd);
   1.212 +  } else {
   1.213 +    vpx_internal_error(&cm->error, VPX_CODEC_ERROR,
   1.214 +                       "Invalid reference frame");
   1.215 +  }
   1.216 +
   1.217 +  return cm->error.error_code;
   1.218 +}
   1.219 +
   1.220 +
   1.221 +vpx_codec_err_t vp9_set_reference_dec(VP9D_PTR ptr, VP9_REFFRAME ref_frame_flag,
   1.222 +                                      YV12_BUFFER_CONFIG *sd) {
   1.223 +  VP9D_COMP *pbi = (VP9D_COMP *) ptr;
   1.224 +  VP9_COMMON *cm = &pbi->common;
   1.225 +  int *ref_fb_ptr = NULL;
   1.226 +
   1.227 +  /* TODO(jkoleszar): The decoder doesn't have any real knowledge of what the
   1.228 +   * encoder is using the frame buffers for. This is just a stub to keep the
   1.229 +   * vpxenc --test-decode functionality working, and will be replaced in a
   1.230 +   * later commit that adds VP9-specific controls for this functionality.
   1.231 +   */
   1.232 +  if (ref_frame_flag == VP9_LAST_FLAG) {
   1.233 +    ref_fb_ptr = &pbi->common.active_ref_idx[0];
   1.234 +  } else if (ref_frame_flag == VP9_GOLD_FLAG) {
   1.235 +    ref_fb_ptr = &pbi->common.active_ref_idx[1];
   1.236 +  } else if (ref_frame_flag == VP9_ALT_FLAG) {
   1.237 +    ref_fb_ptr = &pbi->common.active_ref_idx[2];
   1.238 +  } else {
   1.239 +    vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
   1.240 +                       "Invalid reference frame");
   1.241 +    return pbi->common.error.error_code;
   1.242 +  }
   1.243 +
   1.244 +  if (!equal_dimensions(&cm->yv12_fb[*ref_fb_ptr], sd)) {
   1.245 +    vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
   1.246 +                       "Incorrect buffer dimensions");
   1.247 +  } else {
   1.248 +    // Find an empty frame buffer.
   1.249 +    const int free_fb = get_free_fb(cm);
   1.250 +    // Decrease fb_idx_ref_cnt since it will be increased again in
   1.251 +    // ref_cnt_fb() below.
   1.252 +    cm->fb_idx_ref_cnt[free_fb]--;
   1.253 +
   1.254 +    // Manage the reference counters and copy image.
   1.255 +    ref_cnt_fb(cm->fb_idx_ref_cnt, ref_fb_ptr, free_fb);
   1.256 +    vp8_yv12_copy_frame(sd, &cm->yv12_fb[*ref_fb_ptr]);
   1.257 +  }
   1.258 +
   1.259 +  return pbi->common.error.error_code;
   1.260 +}
   1.261 +
   1.262 +
   1.263 +int vp9_get_reference_dec(VP9D_PTR ptr, int index, YV12_BUFFER_CONFIG **fb) {
   1.264 +  VP9D_COMP *pbi = (VP9D_COMP *) ptr;
   1.265 +  VP9_COMMON *cm = &pbi->common;
   1.266 +
   1.267 +  if (index < 0 || index >= NUM_REF_FRAMES)
   1.268 +    return -1;
   1.269 +
   1.270 +  *fb = &cm->yv12_fb[cm->ref_frame_map[index]];
   1.271 +  return 0;
   1.272 +}
   1.273 +
   1.274 +/* If any buffer updating is signaled it should be done here. */
   1.275 +static void swap_frame_buffers(VP9D_COMP *pbi) {
   1.276 +  int ref_index = 0, mask;
   1.277 +  VP9_COMMON *const cm = &pbi->common;
   1.278 +
   1.279 +  for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) {
   1.280 +    if (mask & 1)
   1.281 +      ref_cnt_fb(cm->fb_idx_ref_cnt, &cm->ref_frame_map[ref_index],
   1.282 +                 cm->new_fb_idx);
   1.283 +    ++ref_index;
   1.284 +  }
   1.285 +
   1.286 +  cm->frame_to_show = get_frame_new_buffer(cm);
   1.287 +  cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
   1.288 +
   1.289 +  // Invalidate these references until the next frame starts.
   1.290 +  for (ref_index = 0; ref_index < 3; ref_index++)
   1.291 +    cm->active_ref_idx[ref_index] = INT_MAX;
   1.292 +}
   1.293 +
   1.294 +int vp9_receive_compressed_data(VP9D_PTR ptr,
   1.295 +                                size_t size, const uint8_t **psource,
   1.296 +                                int64_t time_stamp) {
   1.297 +  VP9D_COMP *pbi = (VP9D_COMP *) ptr;
   1.298 +  VP9_COMMON *cm = &pbi->common;
   1.299 +  const uint8_t *source = *psource;
   1.300 +  int retcode = 0;
   1.301 +
   1.302 +  /*if(pbi->ready_for_new_data == 0)
   1.303 +      return -1;*/
   1.304 +
   1.305 +  if (ptr == 0)
   1.306 +    return -1;
   1.307 +
   1.308 +  cm->error.error_code = VPX_CODEC_OK;
   1.309 +
   1.310 +  pbi->source = source;
   1.311 +  pbi->source_sz = size;
   1.312 +
   1.313 +  if (pbi->source_sz == 0) {
   1.314 +    /* This is used to signal that we are missing frames.
   1.315 +     * We do not know if the missing frame(s) was supposed to update
   1.316 +     * any of the reference buffers, but we act conservative and
   1.317 +     * mark only the last buffer as corrupted.
   1.318 +     *
   1.319 +     * TODO(jkoleszar): Error concealment is undefined and non-normative
   1.320 +     * at this point, but if it becomes so, [0] may not always be the correct
   1.321 +     * thing to do here.
   1.322 +     */
   1.323 +    if (cm->active_ref_idx[0] != INT_MAX)
   1.324 +      get_frame_ref_buffer(cm, 0)->corrupted = 1;
   1.325 +  }
   1.326 +
   1.327 +  cm->new_fb_idx = get_free_fb(cm);
   1.328 +
   1.329 +  if (setjmp(cm->error.jmp)) {
   1.330 +    cm->error.setjmp = 0;
   1.331 +
   1.332 +    /* We do not know if the missing frame(s) was supposed to update
   1.333 +     * any of the reference buffers, but we act conservative and
   1.334 +     * mark only the last buffer as corrupted.
   1.335 +     *
   1.336 +     * TODO(jkoleszar): Error concealment is undefined and non-normative
   1.337 +     * at this point, but if it becomes so, [0] may not always be the correct
   1.338 +     * thing to do here.
   1.339 +     */
   1.340 +    if (cm->active_ref_idx[0] != INT_MAX)
   1.341 +      get_frame_ref_buffer(cm, 0)->corrupted = 1;
   1.342 +
   1.343 +    if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
   1.344 +      cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
   1.345 +
   1.346 +    return -1;
   1.347 +  }
   1.348 +
   1.349 +  cm->error.setjmp = 1;
   1.350 +
   1.351 +  retcode = vp9_decode_frame(pbi, psource);
   1.352 +
   1.353 +  if (retcode < 0) {
   1.354 +    cm->error.error_code = VPX_CODEC_ERROR;
   1.355 +    cm->error.setjmp = 0;
   1.356 +    if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
   1.357 +      cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
   1.358 +    return retcode;
   1.359 +  }
   1.360 +
   1.361 +  swap_frame_buffers(pbi);
   1.362 +
   1.363 +#if WRITE_RECON_BUFFER == 2
   1.364 +  if (cm->show_frame)
   1.365 +    write_dx_frame_to_file(cm->frame_to_show,
   1.366 +                           cm->current_video_frame);
   1.367 +  else
   1.368 +    write_dx_frame_to_file(cm->frame_to_show,
   1.369 +                           cm->current_video_frame + 1000);
   1.370 +#endif
   1.371 +
   1.372 +  if (!pbi->do_loopfilter_inline) {
   1.373 +    vp9_loop_filter_frame(cm, &pbi->mb, pbi->common.lf.filter_level, 0, 0);
   1.374 +  }
   1.375 +
   1.376 +#if WRITE_RECON_BUFFER == 2
   1.377 +  if (cm->show_frame)
   1.378 +    write_dx_frame_to_file(cm->frame_to_show,
   1.379 +                           cm->current_video_frame + 2000);
   1.380 +  else
   1.381 +    write_dx_frame_to_file(cm->frame_to_show,
   1.382 +                           cm->current_video_frame + 3000);
   1.383 +#endif
   1.384 +
   1.385 +  vp9_extend_frame_inner_borders(cm->frame_to_show,
   1.386 +                                 cm->subsampling_x,
   1.387 +                                 cm->subsampling_y);
   1.388 +
   1.389 +#if WRITE_RECON_BUFFER == 1
   1.390 +  if (cm->show_frame)
   1.391 +    recon_write_yuv_frame("recon.yuv", cm->frame_to_show,
   1.392 +                          cm->width, cm->height);
   1.393 +#endif
   1.394 +
   1.395 +  vp9_clear_system_state();
   1.396 +
   1.397 +  cm->last_show_frame = cm->show_frame;
   1.398 +  if (cm->show_frame) {
   1.399 +    // current mip will be the prev_mip for the next frame
   1.400 +    MODE_INFO *temp = cm->prev_mip;
   1.401 +    MODE_INFO **temp2 = cm->prev_mi_grid_base;
   1.402 +    cm->prev_mip = cm->mip;
   1.403 +    cm->mip = temp;
   1.404 +    cm->prev_mi_grid_base = cm->mi_grid_base;
   1.405 +    cm->mi_grid_base = temp2;
   1.406 +
   1.407 +    // update the upper left visible macroblock ptrs
   1.408 +    cm->mi = cm->mip + cm->mode_info_stride + 1;
   1.409 +    cm->prev_mi = cm->prev_mip + cm->mode_info_stride + 1;
   1.410 +    cm->mi_grid_visible = cm->mi_grid_base + cm->mode_info_stride + 1;
   1.411 +    cm->prev_mi_grid_visible = cm->prev_mi_grid_base + cm->mode_info_stride + 1;
   1.412 +
   1.413 +    pbi->mb.mi_8x8 = cm->mi_grid_visible;
   1.414 +    pbi->mb.mi_8x8[0] = cm->mi;
   1.415 +
   1.416 +    cm->current_video_frame++;
   1.417 +  }
   1.418 +
   1.419 +  pbi->ready_for_new_data = 0;
   1.420 +  pbi->last_time_stamp = time_stamp;
   1.421 +  pbi->source_sz = 0;
   1.422 +
   1.423 +  cm->error.setjmp = 0;
   1.424 +  return retcode;
   1.425 +}
   1.426 +
   1.427 +int vp9_get_raw_frame(VP9D_PTR ptr, YV12_BUFFER_CONFIG *sd,
   1.428 +                      int64_t *time_stamp, int64_t *time_end_stamp,
   1.429 +                      vp9_ppflags_t *flags) {
   1.430 +  int ret = -1;
   1.431 +  VP9D_COMP *pbi = (VP9D_COMP *) ptr;
   1.432 +
   1.433 +  if (pbi->ready_for_new_data == 1)
   1.434 +    return ret;
   1.435 +
   1.436 +  /* ie no raw frame to show!!! */
   1.437 +  if (pbi->common.show_frame == 0)
   1.438 +    return ret;
   1.439 +
   1.440 +  pbi->ready_for_new_data = 1;
   1.441 +  *time_stamp = pbi->last_time_stamp;
   1.442 +  *time_end_stamp = 0;
   1.443 +
   1.444 +#if CONFIG_VP9_POSTPROC
   1.445 +  ret = vp9_post_proc_frame(&pbi->common, sd, flags);
   1.446 +#else
   1.447 +
   1.448 +  if (pbi->common.frame_to_show) {
   1.449 +    *sd = *pbi->common.frame_to_show;
   1.450 +    sd->y_width = pbi->common.width;
   1.451 +    sd->y_height = pbi->common.height;
   1.452 +    sd->uv_width = sd->y_width >> pbi->common.subsampling_x;
   1.453 +    sd->uv_height = sd->y_height >> pbi->common.subsampling_y;
   1.454 +
   1.455 +    ret = 0;
   1.456 +  } else {
   1.457 +    ret = -1;
   1.458 +  }
   1.459 +
   1.460 +#endif /*!CONFIG_POSTPROC*/
   1.461 +  vp9_clear_system_state();
   1.462 +  return ret;
   1.463 +}

mercurial