Commit e7508413 authored by Fergus Simpson's avatar Fergus Simpson

frame_superres: Add scale to uncompressed header

A bit and a three bit literal have been added to the uncompressed frame
header for use by the frame superres experiment.

The bit is true if scaling is to be used, and is immediately followed by
a three bit literal that encodes the scale to use. If the first bit is
false, scaling is disabled and the scale factor numerator is set to the
denominator (ie. 1:1 scaling). No literal follows if scaling is
disabled.

The denominator has been defined as a constant 16. The literal is biased
by a defined constant of 8 - allowing fractions from 1/2 to 15/16
scaling in steps of 1/16 when scaling is used. Experimentation will be
needed to discover which of these are useful.

The bit and literal are immediately after the optional render_width and
render_height, so that the superres parameters can be written and read
just after the regular width and height, without interfering with the
render_size parameters.

This patch also adds an arbitrary write to make the scale 1:1, so as to
not trigger any scaling until it's ready.

Accompanying encode and decode helper functions are added.

Change-Id: I8caa6247c73f5c7f84ef1fde1e80eb9b20bde0e3
parent b37226e4
......@@ -504,6 +504,8 @@ typedef enum {
} RestorationType;
#if CONFIG_FRAME_SUPERRES
#define SUPERRES_SCALE_DENOMINATOR 16
#define SUPERRES_SCALE_BITS 3
#define SUPERRES_SCALE_NUMERATOR_MIN 8
#endif // CONFIG_FRAME_SUPERRES
#endif // CONFIG_LOOP_RESTORATION
#ifdef __cplusplus
......
......@@ -2798,6 +2798,38 @@ static void setup_render_size(AV1_COMMON *cm, struct aom_read_bit_buffer *rb) {
av1_read_frame_size(rb, &cm->render_width, &cm->render_height);
}
#if CONFIG_LOOP_RESTORATION && CONFIG_FRAME_SUPERRES
// TODO(afergs): make "struct aom_read_bit_buffer *const rb"?
static void setup_superres_size(AV1_COMMON *const cm,
struct aom_read_bit_buffer *rb, int *width,
int *height) {
// TODO(afergs): Test this behaviour
// Frame superres is probably in compatible with this render resolution
assert(cm->width == cm->render_width && cm->height == cm->render_height);
cm->superres_width = cm->width;
cm->superres_height = cm->height;
if (aom_rb_read_bit(rb)) {
cm->superres_scale_numerator =
(uint8_t)aom_rb_read_literal(rb, SUPERRES_SCALE_BITS);
cm->superres_scale_numerator += SUPERRES_SCALE_NUMERATOR_MIN;
// Don't edit cm->width or cm->height directly, or the buffers won't get
// resized correctly
// TODO(afergs): Should the render resolution not be modified? It's the same
// by default (ie. when it isn't sent)...
// resize_context_buffers() will change cm->width to equal cm->render_width,
// then they'll be the same again
*width = cm->render_width =
cm->width * cm->superres_scale_numerator / SUPERRES_SCALE_DENOMINATOR;
*height = cm->render_height =
cm->height * cm->superres_scale_numerator / SUPERRES_SCALE_DENOMINATOR;
} else {
// 1:1 scaling - ie. no scaling, scale not provided
cm->superres_scale_numerator = SUPERRES_SCALE_DENOMINATOR;
}
}
#endif // CONFIG_LOOP_RESTORATION && CONFIG_FRAME_SUPERRES
static void resize_mv_buffer(AV1_COMMON *cm) {
aom_free(cm->cur_frame->mvs);
cm->cur_frame->mi_rows = cm->mi_rows;
......@@ -2843,8 +2875,11 @@ static void setup_frame_size(AV1_COMMON *cm, struct aom_read_bit_buffer *rb) {
int width, height;
BufferPool *const pool = cm->buffer_pool;
av1_read_frame_size(rb, &width, &height);
resize_context_buffers(cm, width, height);
setup_render_size(cm, rb);
#if CONFIG_LOOP_RESTORATION && CONFIG_FRAME_SUPERRES
setup_superres_size(cm, rb, &width, &height);
#endif // CONFIG_LOOP_RESTORATION && CONFIG_FRAME_SUPERRES
resize_context_buffers(cm, width, height);
lock_buffer_pool(pool);
if (aom_realloc_frame_buffer(
......
......@@ -4168,12 +4168,48 @@ static void write_render_size(const AV1_COMMON *cm,
}
}
#if CONFIG_LOOP_RESTORATION && CONFIG_FRAME_SUPERRES
static void write_superres_scale(const AV1_COMMON *const cm,
struct aom_write_bit_buffer *wb) {
// This scaling and frame superres are probably incompatible
assert(cm->width == cm->render_width && cm->height == cm->render_height);
// First bit is whether to to scale or not
if (cm->superres_scale_numerator == SUPERRES_SCALE_DENOMINATOR) {
aom_wb_write_bit(wb, 0); // no scaling
} else {
aom_wb_write_bit(wb, 1); // scaling, write scale factor
// TODO(afergs): write factor to the compressed header instead
aom_wb_write_literal(
wb, cm->superres_scale_numerator - SUPERRES_SCALE_NUMERATOR_MIN,
SUPERRES_SCALE_BITS);
}
}
#endif // CONFIG_LOOP_RESTORATION && CONFIG_FRAME_SUPERRES
static void write_frame_size(const AV1_COMMON *cm,
struct aom_write_bit_buffer *wb) {
aom_wb_write_literal(wb, cm->width - 1, 16);
aom_wb_write_literal(wb, cm->height - 1, 16);
#if CONFIG_LOOP_RESTORATION && CONFIG_FRAME_SUPERRES
// If SUPERRES scaling is happening, write the full resolution instead of the
// downscaled resolution. The decoder will reduce this resolution itself.
if (cm->superres_scale_numerator != SUPERRES_SCALE_DENOMINATOR) {
aom_wb_write_literal(wb, cm->superres_width - 1, 16);
aom_wb_write_literal(wb, cm->superres_height - 1, 16);
} else {
#endif // CONFIG_LOOP_RESTORATION && CONFIG_FRAME_SUPERRES
aom_wb_write_literal(wb, cm->width - 1, 16);
aom_wb_write_literal(wb, cm->height - 1, 16);
#if CONFIG_LOOP_RESTORATION && CONFIG_FRAME_SUPERRES
}
#endif // CONFIG_LOOP_RESTORATION && CONFIG_FRAME_SUPERRES
// TODO(afergs): Also write something different to render_size?
// When superres scales, they'll be almost guaranteed to be
// different on the other side.
write_render_size(cm, wb);
#if CONFIG_LOOP_RESTORATION && CONFIG_FRAME_SUPERRES
write_superres_scale(cm, wb);
#endif // CONFIG_LOOP_RESTORATION && CONFIG_FRAME_SUPERRES
}
static void write_frame_size_with_refs(AV1_COMP *cpi,
......@@ -4198,9 +4234,7 @@ static void write_frame_size_with_refs(AV1_COMP *cpi,
}
if (!found) {
aom_wb_write_literal(wb, cm->width - 1, 16);
aom_wb_write_literal(wb, cm->height - 1, 16);
write_render_size(cm, wb);
write_frame_size(cm, wb);
}
}
......@@ -4318,6 +4352,11 @@ static void write_uncompressed_header(AV1_COMP *cpi,
}
#endif
#if CONFIG_LOOP_RESTORATION && CONFIG_FRAME_SUPERRES
// TODO(afergs): Remove - this is just to stop superres from breaking
cm->superres_scale_numerator = SUPERRES_SCALE_DENOMINATOR;
#endif // CONFIG_LOOP_RESTORATION && CONFIG_FRAME_SUPERRES
if (cm->frame_type == KEY_FRAME) {
write_sync_code(wb);
write_bitdepth_colorspace_sampling(cm, wb);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment