vp9_decodframe.c 39.2 KB
Newer Older
        vp9_rb_read_bit(rb);  // has extra plane
      } else {
        cm->subsampling_y = cm->subsampling_x = 1;
      }
      if (cm->version == 1) {
        cm->subsampling_y = cm->subsampling_x = 0;
        vp9_rb_read_bit(rb);  // has extra plane
      } else {
        vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
                           "RGB not supported in profile 0");
      }
John Koleszar's avatar
John Koleszar committed

    vp9_setup_past_independence(cm, xd);

    pbi->refresh_frame_flags = (1 << NUM_REF_FRAMES) - 1;

    for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i)
      cm->active_ref_idx[i] = cm->new_fb_idx;

    setup_frame_size(pbi, rb);
  } else {
    if (cm->error_resilient_mode)
      vp9_setup_past_independence(cm, xd);

    pbi->refresh_frame_flags = vp9_rb_read_literal(rb, NUM_REF_FRAMES);

    for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i) {
      const int ref = vp9_rb_read_literal(rb, NUM_REF_FRAMES_LG2);
      cm->active_ref_idx[i] = cm->ref_frame_map[ref];
      cm->ref_frame_sign_bias[LAST_FRAME + i] = vp9_rb_read_bit(rb);
    setup_frame_size(pbi, rb);

    // Read the sign bias for each reference frame buffer.
    cm->allow_comp_inter_inter = 0;
    for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i) {
      vp9_setup_scale_factors(cm, i);
      cm->allow_comp_inter_inter |= i > 0 &&
          cm->ref_frame_sign_bias[i + 1] != cm->ref_frame_sign_bias[1];
    }
    if (cm->allow_comp_inter_inter) {
      // which one is always-on in comp inter-inter?
      if (cm->ref_frame_sign_bias[LAST_FRAME] ==
          cm->ref_frame_sign_bias[GOLDEN_FRAME]) {
        cm->comp_fixed_ref = ALTREF_FRAME;
        cm->comp_var_ref[0] = LAST_FRAME;
        cm->comp_var_ref[1] = GOLDEN_FRAME;
      } else if (cm->ref_frame_sign_bias[LAST_FRAME] ==
                 cm->ref_frame_sign_bias[ALTREF_FRAME]) {
        cm->comp_fixed_ref = GOLDEN_FRAME;
        cm->comp_var_ref[0] = LAST_FRAME;
        cm->comp_var_ref[1] = ALTREF_FRAME;
      } else {
        cm->comp_fixed_ref = LAST_FRAME;
        cm->comp_var_ref[0] = GOLDEN_FRAME;
        cm->comp_var_ref[1] = ALTREF_FRAME;
      }
    }

    xd->allow_high_precision_mv = vp9_rb_read_bit(rb);
    cm->mcomp_filter_type = read_interp_filter_type(rb);
  }

  if (!cm->error_resilient_mode) {
    cm->reset_frame_context = vp9_rb_read_bit(rb);
    cm->refresh_frame_context = vp9_rb_read_bit(rb);
    cm->frame_parallel_decoding_mode = vp9_rb_read_bit(rb);
  } else {
    cm->reset_frame_context = 0;
    cm->refresh_frame_context = 0;
    cm->frame_parallel_decoding_mode = 1;
  }

  cm->intra_only = cm->show_frame ? 0 : vp9_rb_read_bit(rb);
  cm->frame_context_idx = vp9_rb_read_literal(rb, NUM_FRAME_CONTEXTS_LG2);
  cm->clr_type = (YUV_TYPE)vp9_rb_read_bit(rb);

  setup_loopfilter(pbi, rb);
  setup_quantization(pbi, rb);
  setup_segmentation(pbi, rb);

  setup_tile_info(cm, rb);
  return vp9_rb_read_literal(rb, 16);
}
John Koleszar's avatar
John Koleszar committed

int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) {
  int i;
  vp9_reader header_bc, residual_bc;
  VP9_COMMON *const pc = &pbi->common;
  MACROBLOCKD *const xd = &pbi->mb;
  const uint8_t *data = pbi->source;
  const uint8_t *data_end = pbi->source + pbi->source_sz;
Yaowu Xu's avatar
Yaowu Xu committed

  struct vp9_read_bit_buffer rb = { data, data_end, 0,
                                    pc, error_handler };
  const size_t first_partition_size = read_uncompressed_header(pbi, &rb);
  const int keyframe = pc->frame_type == KEY_FRAME;
  YV12_BUFFER_CONFIG *new_fb = &pc->yv12_fb[pc->new_fb_idx];
  if (!first_partition_size) {
    // showing a frame directly
    *p_data_end = data + 1;
    return 0;
  }
  data += vp9_rb_bytes_read(&rb);
  xd->corrupted = 0;
  new_fb->corrupted = 0;
  if ((!pbi->decoded_key_frame && !keyframe) ||
      pc->width == 0 || pc->height == 0) {
John Koleszar's avatar
John Koleszar committed
    return -1;
  }
  vp9_setup_version(pc);
  if (!read_is_valid(data, first_partition_size, data_end))
    vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
                       "Truncated packet or corrupt partition 0 length");
  xd->mode_info_context = pc->mi;
  xd->prev_mode_info_context = pc->prev_mi;
  xd->frame_type = pc->frame_type;
  xd->mode_info_stride = pc->mode_info_stride;
  if (vp9_reader_init(&header_bc, data, first_partition_size))
John Koleszar's avatar
John Koleszar committed
    vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
                       "Failed to allocate bool decoder 0");
  mb_init_dequantizer(pc, &pbi->mb);  // MB level dequantizer setup
    vp9_setup_interp_filters(xd, pc->mcomp_filter_type, pc);
John Koleszar's avatar
John Koleszar committed

  pc->fc = pc->frame_contexts[pc->frame_context_idx];
John Koleszar's avatar
John Koleszar committed

  update_frame_context(&pc->fc);
  setup_txfm_mode(pc, xd->lossless, &header_bc);

  read_coef_probs(pbi, &header_bc);
Yaowu Xu's avatar
Yaowu Xu committed

  // Initialize xd pointers. Any reference should do for xd->pre, so use 0.
  setup_pre_planes(xd, &pc->yv12_fb[pc->active_ref_idx[0]], NULL,
                   0, 0, NULL, NULL);
  setup_dst_planes(xd, new_fb, 0, 0);
John Koleszar's avatar
John Koleszar committed
  // Create the segmentation map structure and set to 0
  if (!pc->last_frame_seg_map)
    CHECK_MEM_ERROR(pc->last_frame_seg_map,
                    vpx_calloc((pc->mi_rows * pc->mi_cols), 1));
  vp9_setup_block_dptrs(xd, pc->subsampling_x, pc->subsampling_y);
Dmitry Kovalev's avatar
Dmitry Kovalev committed
  // clear out the coeff buffer
  for (i = 0; i < MAX_MB_PLANE; ++i)
    vp9_zero(xd->plane[i].qcoeff);
  vp9_decode_mode_mvs_init(pbi, &header_bc);
  decode_tiles(pbi, data, first_partition_size, &residual_bc);
John Koleszar's avatar
John Koleszar committed

  pc->last_width = pc->width;
  pc->last_height = pc->height;
  new_fb->corrupted = vp9_reader_has_error(&header_bc) | xd->corrupted;
John Koleszar's avatar
John Koleszar committed

  if (!pbi->decoded_key_frame) {
    if (keyframe && !new_fb->corrupted)
John Koleszar's avatar
John Koleszar committed
      pbi->decoded_key_frame = 1;
    else
      vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
John Koleszar's avatar
John Koleszar committed
                         "A stream must start with a complete key frame");
  }
  if (!pc->error_resilient_mode && !pc->frame_parallel_decoding_mode) {
    vp9_adapt_coef_probs(pc);
      vp9_adapt_mode_probs(pc);
      vp9_adapt_nmv_probs(pc, xd->allow_high_precision_mv);
John Koleszar's avatar
John Koleszar committed
  }
  if (pc->refresh_frame_context)
    pc->frame_contexts[pc->frame_context_idx] = pc->fc;
  *p_data_end = vp9_reader_find_end(&residual_bc);
John Koleszar's avatar
John Koleszar committed
  return 0;
John Koleszar's avatar
John Koleszar committed
}