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
This commit is contained in:
Родитель
c03d45def9
Коммит
393b485627
|
@ -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 */
|
||||
|
|
|
@ -1526,34 +1526,35 @@ 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);
|
||||
|
||||
// signal clr type
|
||||
vp9_write_bit(&header_bc, pc->clr_type);
|
||||
vp9_write_bit(&header_bc, pc->clamp_type);
|
||||
|
||||
} else {
|
||||
vp9_start_encode(&header_bc, cx_data);
|
||||
extra_bytes_packed += 4;
|
||||
cx_data += 4;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче