From 393b4856273c06aa0e7f0aec90a2b93a19aaf2d2 Mon Sep 17 00:00:00 2001 From: John Koleszar Date: Wed, 6 Feb 2013 15:54:52 -0800 Subject: [PATCH] Initial support for resolution changes on P-frames Allows inter-frames to change resolution. Currently these are almost equivalent to keyframes, as only intra prediction modes are allowed, but without the other context resets that occur on keyframes. Change-Id: Icd1a2a5af0d9462cc792588427b0a1f5b12e40d3 --- vp9/decoder/vp9_decodframe.c | 26 +++++++++++++------------- vp9/encoder/vp9_bitstream.c | 33 +++++++++++++++++---------------- vp9/encoder/vp9_onyx_if.c | 17 +++++++++++++++++ vp9/encoder/vp9_rdopt.c | 12 ++++++++++++ vp9/vp9_cx_iface.c | 8 +------- 5 files changed, 60 insertions(+), 36 deletions(-) diff --git a/vp9/decoder/vp9_decodframe.c b/vp9/decoder/vp9_decodframe.c index b9b62d5..7717980 100644 --- a/vp9/decoder/vp9_decodframe.c +++ b/vp9/decoder/vp9_decodframe.c @@ -1367,9 +1367,6 @@ int vp9_decode_frame(VP9D_COMP *pbi, const unsigned char **p_data_end) { vp9_setup_version(pc); if (pc->frame_type == KEY_FRAME) { - const int Width = pc->Width; - const int Height = pc->Height; - /* vet via sync code */ /* When error concealment is enabled we should only check the sync * code if we have enough bits available @@ -1379,18 +1376,23 @@ int vp9_decode_frame(VP9D_COMP *pbi, const unsigned char **p_data_end) { vpx_internal_error(&pc->error, VPX_CODEC_UNSUP_BITSTREAM, "Invalid frame sync code"); } + data += 3; + } + { + const int Width = pc->Width; + const int Height = pc->Height; /* If error concealment is enabled we should only parse the new size * if we have enough data. Otherwise we will end up with the wrong * size. */ - if (data + 6 < data_end) { - pc->Width = (data[3] | (data[4] << 8)) & 0x3fff; - pc->horiz_scale = data[4] >> 6; - pc->Height = (data[5] | (data[6] << 8)) & 0x3fff; - pc->vert_scale = data[6] >> 6; + if (data + 4 < data_end) { + pc->Width = (data[0] | (data[1] << 8)) & 0x3fff; + pc->horiz_scale = data[1] >> 6; + pc->Height = (data[2] | (data[3] << 8)) & 0x3fff; + pc->vert_scale = data[3] >> 6; } - data += 7; + data += 4; if (Width != pc->Width || Height != pc->Height) { if (pc->Width <= 0) { @@ -1423,10 +1425,8 @@ int vp9_decode_frame(VP9D_COMP *pbi, const unsigned char **p_data_end) { (unsigned int)first_partition_length_in_bytes)) vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR, "Failed to allocate bool decoder 0"); - if (pc->frame_type == KEY_FRAME) { - pc->clr_type = (YUV_TYPE)vp9_read_bit(&header_bc); - pc->clamp_type = (CLAMP_TYPE)vp9_read_bit(&header_bc); - } + pc->clr_type = (YUV_TYPE)vp9_read_bit(&header_bc); + pc->clamp_type = (CLAMP_TYPE)vp9_read_bit(&header_bc); pc->error_resilient_mode = vp9_read_bit(&header_bc); /* Is segmentation enabled */ diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c index 2e69b84..b2c5d72 100644 --- a/vp9/encoder/vp9_bitstream.c +++ b/vp9/encoder/vp9_bitstream.c @@ -1526,33 +1526,34 @@ void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest, * and color type. */ if (oh.type == KEY_FRAME) { - int v; - // Start / synch code cx_data[0] = 0x9D; cx_data[1] = 0x01; cx_data[2] = 0x2a; + extra_bytes_packed = 3; + cx_data += extra_bytes_packed; + } + { + int v; + /* TODO(jkoleszar): support arbitrary resolutions */ v = (pc->horiz_scale << 14) | pc->Width; - cx_data[3] = v; - cx_data[4] = v >> 8; + cx_data[0] = v; + cx_data[1] = v >> 8; v = (pc->vert_scale << 14) | pc->Height; - cx_data[5] = v; - cx_data[6] = v >> 8; + cx_data[2] = v; + cx_data[3] = v >> 8; - extra_bytes_packed = 7; - cx_data += extra_bytes_packed; - - vp9_start_encode(&header_bc, cx_data); + extra_bytes_packed += 4; + cx_data += 4; + } - // signal clr type - vp9_write_bit(&header_bc, pc->clr_type); - vp9_write_bit(&header_bc, pc->clamp_type); + vp9_start_encode(&header_bc, cx_data); - } else { - vp9_start_encode(&header_bc, cx_data); - } + // TODO(jkoleszar): remove these two unused bits? + vp9_write_bit(&header_bc, pc->clr_type); + vp9_write_bit(&header_bc, pc->clamp_type); // error resilient mode vp9_write_bit(&header_bc, pc->error_resilient_mode); diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c index e6e9cdd..2ad0c04 100644 --- a/vp9/encoder/vp9_onyx_if.c +++ b/vp9/encoder/vp9_onyx_if.c @@ -3995,6 +3995,23 @@ int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags, cm->mb_cols * 16, cm->mb_rows * 16, VP9BORDERINPIXELS); + /* Disable any references that have different size */ + if ((cm->yv12_fb[cm->active_ref_idx[cpi->lst_fb_idx]].y_width != + cm->yv12_fb[cm->new_fb_idx].y_width) || + (cm->yv12_fb[cm->active_ref_idx[cpi->lst_fb_idx]].y_height != + cm->yv12_fb[cm->new_fb_idx].y_height)) + cpi->ref_frame_flags &= ~VP9_LAST_FLAG; + if ((cm->yv12_fb[cm->active_ref_idx[cpi->gld_fb_idx]].y_width != + cm->yv12_fb[cm->new_fb_idx].y_width) || + (cm->yv12_fb[cm->active_ref_idx[cpi->gld_fb_idx]].y_height != + cm->yv12_fb[cm->new_fb_idx].y_height)) + cpi->ref_frame_flags &= ~VP9_GOLD_FLAG; + if ((cm->yv12_fb[cm->active_ref_idx[cpi->alt_fb_idx]].y_width != + cm->yv12_fb[cm->new_fb_idx].y_width) || + (cm->yv12_fb[cm->active_ref_idx[cpi->alt_fb_idx]].y_height != + cm->yv12_fb[cm->new_fb_idx].y_height)) + cpi->ref_frame_flags &= ~VP9_ALT_FLAG; + vp9_setup_interp_filters(&cpi->mb.e_mbd, DEFAULT_INTERP_FILTER, cm); if (cpi->pass == 1) { Pass1Encode(cpi, size, dest, frame_flags); diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c index 200a6a9..59d2309 100644 --- a/vp9/encoder/vp9_rdopt.c +++ b/vp9/encoder/vp9_rdopt.c @@ -3510,6 +3510,8 @@ static void rd_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int recon_uvoffset, int *returnrate, int *returndistortion, int64_t *returnintra) { + static const int flag_list[4] = { 0, VP9_LAST_FLAG, VP9_GOLD_FLAG, + VP9_ALT_FLAG }; VP9_COMMON *cm = &cpi->common; MACROBLOCKD *xd = &x->e_mbd; union b_mode_info best_bmodes[16]; @@ -3677,6 +3679,16 @@ static void rd_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, if (best_rd <= cpi->rd_threshes[mode_index]) continue; + // Ensure that the references used by this mode are available. + if (mbmi->ref_frame && + !(cpi->ref_frame_flags & flag_list[mbmi->ref_frame])) + continue; + + if (mbmi->second_ref_frame > 0 && + !(cpi->ref_frame_flags & flag_list[mbmi->second_ref_frame])) + continue; + + // current coding mode under rate-distortion optimization test loop #if CONFIG_COMP_INTERINTRA_PRED mbmi->interintra_mode = (MB_PREDICTION_MODE)(DC_PRED - 1); diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c index 75df0e0..210792f 100644 --- a/vp9/vp9_cx_iface.c +++ b/vp9/vp9_cx_iface.c @@ -80,7 +80,6 @@ struct vpx_codec_alg_priv { unsigned char *pending_cx_data; unsigned int pending_cx_data_sz; vpx_image_t preview_img; - unsigned int next_frame_flag; vp8_postproc_cfg_t preview_ppcfg; vpx_codec_pkt_list_decl(64) pkt_list; // changed to accomendate the maximum number of lagged frames allowed unsigned int fixed_kf_cntr; @@ -675,14 +674,11 @@ static vpx_codec_err_t vp8e_encode(vpx_codec_alg_priv_t *ctx, if (img != NULL) { res = image2yuvconfig(img, &sd); - if (vp9_receive_raw_frame(ctx->cpi, ctx->next_frame_flag | lib_flags, + if (vp9_receive_raw_frame(ctx->cpi, lib_flags, &sd, dst_time_stamp, dst_end_time_stamp)) { VP9_COMP *cpi = (VP9_COMP *)ctx->cpi; res = update_error_state(ctx, &cpi->common.error); } - - /* reset for next frame */ - ctx->next_frame_flag = 0; } cx_data = ctx->cx_data; @@ -984,8 +980,6 @@ static vpx_codec_err_t vp8e_set_scalemode(vpx_codec_alg_priv_t *ctx, scalemode.v_scaling_mode); if (!res) { - /*force next frame a key frame to effect scaling mode */ - ctx->next_frame_flag |= FRAMEFLAGS_KEY; return VPX_CODEC_OK; } else return VPX_CODEC_INVALID_PARAM; -- 2.7.4