Replace scaling byte with explicit display size

If the intended display size is different than the size the frame is
coded at, then send that size explicitly in the bitstream. Adds a new
bit to the frame header to indicate whether the extra size fields
are present.

Change-Id: I525c66f22d207efaf1e5f903c6a2a91b80245854
This commit is contained in:
John Koleszar
2013-03-14 14:36:08 -07:00
parent c5b317057b
commit 8a3f55f2d4
4 changed files with 48 additions and 44 deletions

View File

@@ -169,10 +169,10 @@ typedef struct VP9Common {
int Width;
int Height;
int display_width;
int display_height;
int last_width;
int last_height;
int horiz_scale;
int vert_scale;
YUV_TYPE clr_type;
CLAMP_TYPE clamp_type;

View File

@@ -1275,12 +1275,13 @@ int vp9_decode_frame(VP9D_COMP *pbi, const unsigned char **p_data_end) {
if (data_end - data < 3) {
vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME, "Truncated packet");
} else {
int scaling_active;
pc->last_frame_type = pc->frame_type;
pc->frame_type = (FRAME_TYPE)(data[0] & 1);
pc->version = (data[0] >> 1) & 7;
pc->show_frame = (data[0] >> 4) & 1;
first_partition_length_in_bytes =
(data[0] | (data[1] << 8) | (data[2] << 16)) >> 5;
scaling_active = (data[0] >> 5) & 1;
first_partition_length_in_bytes = data[1] | (data[2] << 8);
if (!read_is_valid(data, first_partition_length_in_bytes, data_end))
vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
@@ -1310,14 +1311,20 @@ int vp9_decode_frame(VP9D_COMP *pbi, const unsigned char **p_data_end) {
* if we have enough data. Otherwise we will end up with the wrong
* size.
*/
if (data + 5 < data_end) {
pc->Width = read_le16(data);
pc->Height = read_le16(data + 2);
pc->horiz_scale = data[4] >> 4;
pc->vert_scale = data[4] & 0x0F;
if (scaling_active && data + 4 < data_end) {
pc->display_width = read_le16(data + 0);
pc->display_height = read_le16(data + 2);
data += 4;
}
if (data + 4 < data_end) {
pc->Width = read_le16(data + 0);
pc->Height = read_le16(data + 2);
data += 4;
}
if (!scaling_active) {
pc->display_width = pc->Width;
pc->display_height = pc->Height;
}
data += 5;
if (width != pc->Width || height != pc->Height) {
if (pc->Width <= 0) {

View File

@@ -2270,7 +2270,18 @@ void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest,
{
int v;
// support arbitrary resolutions
if (pc->Width != pc->display_width || pc->Height != pc->display_height) {
v = pc->display_width;
cx_data[0] = v;
cx_data[1] = v >> 8;
v = pc->display_height;
cx_data[2] = v;
cx_data[3] = v >> 8;
cx_data += 4;
extra_bytes_packed += 4;
}
v = pc->Width;
cx_data[0] = v;
cx_data[1] = v >> 8;
@@ -2279,11 +2290,8 @@ void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest,
cx_data[2] = v;
cx_data[3] = v >> 8;
// use a separate byte to store the scale factors, each ranging 0-15
cx_data[4] = (pc->horiz_scale << 4) | (pc->vert_scale);
extra_bytes_packed += 5;
cx_data += 5;
extra_bytes_packed += 4;
cx_data += 4;
}
vp9_start_encode(&header_bc, cx_data);
@@ -2801,11 +2809,15 @@ void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest,
/* update frame tag */
{
int v = (oh.first_partition_length_in_bytes << 5) |
int scaling = (pc->Width != pc->display_width
|| pc->Height != pc->display_height);
int v = (oh.first_partition_length_in_bytes << 8) |
(scaling << 5) |
(oh.show_frame << 4) |
(oh.version << 1) |
oh.type;
assert(oh.first_partition_length_in_bytes <= 0xffff);
dest[0] = v;
dest[1] = v >> 8;
dest[2] = v >> 16;

View File

@@ -1115,6 +1115,9 @@ static void init_config(VP9_PTR ptr, VP9_CONFIG *oxcf) {
cm->version = oxcf->Version;
vp9_setup_version(cm);
cm->Width = oxcf->Width;
cm->Height = oxcf->Height;
// change includes all joint functionality
vp9_change_config(ptr, oxcf);
@@ -1299,8 +1302,8 @@ void vp9_change_config(VP9_PTR ptr, VP9_CONFIG *oxcf) {
cpi->target_bandwidth = cpi->oxcf.target_bandwidth;
cm->Width = cpi->oxcf.Width;
cm->Height = cpi->oxcf.Height;
cm->display_width = cpi->oxcf.Width;
cm->display_height = cpi->oxcf.Height;
// VP8 sharpness level mapping 0-7 (vs 0-10 in general VPx dialogs)
if (cpi->oxcf.Sharpness > 7)
@@ -1308,18 +1311,6 @@ void vp9_change_config(VP9_PTR ptr, VP9_CONFIG *oxcf) {
cm->sharpness_level = cpi->oxcf.Sharpness;
if (cm->horiz_scale != NORMAL || cm->vert_scale != NORMAL) {
int UNINITIALIZED_IS_SAFE(hr), UNINITIALIZED_IS_SAFE(hs);
int UNINITIALIZED_IS_SAFE(vr), UNINITIALIZED_IS_SAFE(vs);
Scale2Ratio(cm->horiz_scale, &hr, &hs);
Scale2Ratio(cm->vert_scale, &vr, &vs);
// always go to the next whole number
cm->Width = (hs - 1 + cpi->oxcf.Width * hr) / hs;
cm->Height = (vs - 1 + cpi->oxcf.Height * vr) / vs;
}
// Increasing the size of the frame beyond the first seen frame, or some
// otherwise signalled maximum size, is not supported.
// TODO(jkoleszar): exit gracefully.
@@ -4149,6 +4140,7 @@ int vp9_set_internal_size(VP9_PTR comp,
VPX_SCALING horiz_mode, VPX_SCALING vert_mode) {
VP9_COMP *cpi = (VP9_COMP *) comp;
VP9_COMMON *cm = &cpi->common;
int hr = 0, hs = 0, vr = 0, vs = 0;
if (horiz_mode > ONETWO)
return -1;
@@ -4156,20 +4148,13 @@ int vp9_set_internal_size(VP9_PTR comp,
if (vert_mode > ONETWO)
return -1;
if (cm->horiz_scale != horiz_mode || cm->vert_scale != vert_mode) {
int UNINITIALIZED_IS_SAFE(hr), UNINITIALIZED_IS_SAFE(hs);
int UNINITIALIZED_IS_SAFE(vr), UNINITIALIZED_IS_SAFE(vs);
Scale2Ratio(horiz_mode, &hr, &hs);
Scale2Ratio(vert_mode, &vr, &vs);
cm->horiz_scale = horiz_mode;
cm->vert_scale = vert_mode;
// always go to the next whole number
cm->Width = (hs - 1 + cpi->oxcf.Width * hr) / hs;
cm->Height = (vs - 1 + cpi->oxcf.Height * vr) / vs;
Scale2Ratio(cm->horiz_scale, &hr, &hs);
Scale2Ratio(cm->vert_scale, &vr, &vs);
// always go to the next whole number
cm->Width = (hs - 1 + cpi->oxcf.Width * hr) / hs;
cm->Height = (vs - 1 + cpi->oxcf.Height * vr) / vs;
}
assert(cm->Width <= cpi->initial_width);
assert(cm->Height <= cpi->initial_height);
update_frame_size(cpi);