frame_superres: Post encode/decode upscaling This patch implements the post-encode and post-decode upscaling for the frame superresolution experiment to work. Upscaling happens after cdef and before loop restoration. For now, this patch forces on random-superres. The patch also cleans up some broken rate control hooks from VP9 days, to be brought back later when the resize and superres tools are stable. Change-Id: If0a8f69224dfaa0f4ae7703bd429ea2af953c7a6
diff --git a/av1/common/onyxc_int.h b/av1/common/onyxc_int.h index ea265ec..be8a631 100644 --- a/av1/common/onyxc_int.h +++ b/av1/common/onyxc_int.h
@@ -302,6 +302,8 @@ #if CONFIG_FRAME_SUPERRES // The numerator of the superres scale; the denominator is fixed. uint8_t superres_scale_numerator; + int superres_upscaled_width; + int superres_upscaled_height; #endif // CONFIG_FRAME_SUPERRES #if CONFIG_LOOP_RESTORATION RestorationInfo rst_info[MAX_MB_PLANE];
diff --git a/av1/common/resize.c b/av1/common/resize.c index f6fdec7..b5db615 100644 --- a/av1/common/resize.c +++ b/av1/common/resize.c
@@ -816,11 +816,11 @@ #endif // CONFIG_HIGHBITDEPTH #if CONFIG_HIGHBITDEPTH -static void resize_and_extend_frame(const YV12_BUFFER_CONFIG *src, - YV12_BUFFER_CONFIG *dst, int bd) { +void av1_resize_and_extend_frame(const YV12_BUFFER_CONFIG *src, + YV12_BUFFER_CONFIG *dst, int bd) { #else -static void resize_and_extend_frame(const YV12_BUFFER_CONFIG *src, - YV12_BUFFER_CONFIG *dst) { +void av1_resize_and_extend_frame(const YV12_BUFFER_CONFIG *src, + YV12_BUFFER_CONFIG *dst) { #endif // CONFIG_HIGHBITDEPTH // TODO(dkovalev): replace YV12_BUFFER_CONFIG with aom_image_t int i; @@ -855,8 +855,8 @@ YV12_BUFFER_CONFIG *av1_scale_if_required_fast(AV1_COMMON *cm, YV12_BUFFER_CONFIG *unscaled, YV12_BUFFER_CONFIG *scaled) { - if (cm->mi_cols * MI_SIZE != unscaled->y_width || - cm->mi_rows * MI_SIZE != unscaled->y_height) { + if (cm->width != unscaled->y_crop_width || + cm->height != unscaled->y_crop_height) { // For 2x2 scaling down. aom_scale_frame(unscaled, scaled, unscaled->y_buffer, 9, 2, 1, 2, 1, 0); aom_extend_frame_borders(scaled); @@ -869,14 +869,107 @@ YV12_BUFFER_CONFIG *av1_scale_if_required(AV1_COMMON *cm, YV12_BUFFER_CONFIG *unscaled, YV12_BUFFER_CONFIG *scaled) { - if (cm->width != unscaled->y_width || cm->height != unscaled->y_height) { + if (cm->width != unscaled->y_crop_width || + cm->height != unscaled->y_crop_height) { #if CONFIG_HIGHBITDEPTH - resize_and_extend_frame(unscaled, scaled, (int)cm->bit_depth); + av1_resize_and_extend_frame(unscaled, scaled, (int)cm->bit_depth); #else - resize_and_extend_frame(unscaled, scaled); + av1_resize_and_extend_frame(unscaled, scaled); #endif // CONFIG_HIGHBITDEPTH return scaled; } else { return unscaled; } } + +#if CONFIG_FRAME_SUPERRES +void av1_calculate_superres_size(const AV1_COMMON *cm, int *width, + int *height) { + *width = *width * cm->superres_scale_numerator / SUPERRES_SCALE_DENOMINATOR; + *height = *height * cm->superres_scale_numerator / SUPERRES_SCALE_DENOMINATOR; +} + +// TODO(afergs): Look for in-place upscaling +// TODO(afergs): aom_ vs av1_ functions? Which can I use? +// Upscale decoded image. +void av1_superres_upscale(AV1_COMMON *cm, BufferPool *const pool) { + if (av1_superres_unscaled(cm)) return; + + YV12_BUFFER_CONFIG copy_buffer; + memset(©_buffer, 0, sizeof(copy_buffer)); + + YV12_BUFFER_CONFIG *const frame_to_show = get_frame_new_buffer(cm); + + if (aom_alloc_frame_buffer(©_buffer, cm->width, cm->height, + cm->subsampling_x, cm->subsampling_y, +#ifdef CONFIG_HIGHBITDEPTH + cm->use_highbitdepth, +#endif // CONFIG_HIGHBITDEPTH + AOM_BORDER_IN_PIXELS, cm->byte_alignment)) + aom_internal_error(&cm->error, AOM_CODEC_MEM_ERROR, + "Failed to allocate copy buffer for superres upscaling"); + + // Copy function assumes the frames are the same size, doesn't copy bit_depth. + aom_yv12_copy_frame(frame_to_show, ©_buffer); + copy_buffer.bit_depth = frame_to_show->bit_depth; + assert(copy_buffer.y_crop_width == cm->width); + assert(copy_buffer.y_crop_height == cm->height); + + // Realloc the current frame buffer at a higher resolution in place. + if (pool != NULL) { + // Use callbacks if on the decoder. + aom_codec_frame_buffer_t *fb = + &pool->frame_bufs[cm->new_fb_idx].raw_frame_buffer; + aom_release_frame_buffer_cb_fn_t release_fb_cb = pool->release_fb_cb; + aom_get_frame_buffer_cb_fn_t cb = pool->get_fb_cb; + void *cb_priv = pool->cb_priv; + + // Realloc with callback does not release the frame buffer - release first. + if (release_fb_cb(cb_priv, fb)) + aom_internal_error( + &cm->error, AOM_CODEC_MEM_ERROR, + "Failed to free current frame buffer before superres upscaling"); + + if (aom_realloc_frame_buffer( + frame_to_show, cm->superres_upscaled_width, + cm->superres_upscaled_height, cm->subsampling_x, cm->subsampling_y, +#ifdef CONFIG_HIGHBITDEPTH + cm->use_highbitdepth, +#endif // CONFIG_HIGHBITDEPTH + AOM_BORDER_IN_PIXELS, cm->byte_alignment, fb, cb, cb_priv)) + aom_internal_error( + &cm->error, AOM_CODEC_MEM_ERROR, + "Failed to allocate current frame buffer for superres upscaling"); + } else { + // Don't use callbacks on the encoder. + if (aom_alloc_frame_buffer(frame_to_show, cm->superres_upscaled_width, + cm->superres_upscaled_height, cm->subsampling_x, + cm->subsampling_y, +#ifdef CONFIG_HIGHBITDEPTH + cm->use_highbitdepth, +#endif // CONFIG_HIGHBITDEPTH + AOM_BORDER_IN_PIXELS, cm->byte_alignment)) + aom_internal_error( + &cm->error, AOM_CODEC_MEM_ERROR, + "Failed to reallocate current frame buffer for superres upscaling"); + } + // TODO(afergs): verify frame_to_show is correct after realloc + // encoder: + // decoder: + frame_to_show->bit_depth = copy_buffer.bit_depth; + assert(frame_to_show->y_crop_width == cm->superres_upscaled_width); + assert(frame_to_show->y_crop_height == cm->superres_upscaled_height); + + // Scale up and back into frame_to_show. + assert(frame_to_show->y_crop_width != cm->width); + assert(frame_to_show->y_crop_height != cm->height); +#if CONFIG_HIGHBITDEPTH + av1_resize_and_extend_frame(©_buffer, frame_to_show, (int)cm->bit_depth); +#else + av1_resize_and_extend_frame(©_buffer, frame_to_show); +#endif // CONFIG_HIGHBITDEPTH + + // Free the copy buffer + aom_free_frame_buffer(©_buffer); +} +#endif // CONFIG_FRAME_SUPERRES
diff --git a/av1/common/resize.h b/av1/common/resize.h index 9bdba33..e67b7fe 100644 --- a/av1/common/resize.h +++ b/av1/common/resize.h
@@ -63,6 +63,14 @@ int owidth, int bd); #endif // CONFIG_HIGHBITDEPTH +#if CONFIG_HIGHBITDEPTH +void av1_resize_and_extend_frame(const YV12_BUFFER_CONFIG *src, + YV12_BUFFER_CONFIG *dst, int bd); +#else +void av1_resize_and_extend_frame(const YV12_BUFFER_CONFIG *src, + YV12_BUFFER_CONFIG *dst); +#endif // CONFIG_HIGHBITDEPTH + YV12_BUFFER_CONFIG *av1_scale_if_required_fast(AV1_COMMON *cm, YV12_BUFFER_CONFIG *unscaled, YV12_BUFFER_CONFIG *scaled); @@ -71,6 +79,21 @@ YV12_BUFFER_CONFIG *unscaled, YV12_BUFFER_CONFIG *scaled); +#if CONFIG_FRAME_SUPERRES +// This is the size after superress scaling, which could be 1:1. +// Superres scaling happens after regular downscaling. +// TODO(afergs): Limit overall reduction to 1/2 of the original size +void av1_calculate_superres_size(const AV1_COMMON *cm, int *width, int *height); + +void av1_superres_upscale(AV1_COMMON *cm, BufferPool *const pool); + +// Returns 1 if a superres upscaled frame is unscaled and 0 otherwise. +static INLINE int av1_superres_unscaled(const AV1_COMMON *cm) { + return (cm->superres_scale_numerator == SUPERRES_SCALE_DENOMINATOR); +} + +#endif // CONFIG_FRAME_SUPERRES + #ifdef __cplusplus } // extern "C" #endif
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c index d7749dd..5e5db93 100644 --- a/av1/decoder/decodeframe.c +++ b/av1/decoder/decodeframe.c
@@ -49,6 +49,9 @@ #include "av1/common/quant_common.h" #include "av1/common/reconinter.h" #include "av1/common/reconintra.h" +#if CONFIG_FRAME_SUPERRES +#include "av1/common/resize.h" +#endif // CONFIG_FRAME_SUPERRES #include "av1/common/seg_common.h" #include "av1/common/thread_common.h" #include "av1/common/tile_common.h" @@ -2203,6 +2206,7 @@ partition, #endif bsize); + #if !(CONFIG_MOTION_VAR && CONFIG_NCOBMC) #if CONFIG_SUPERTX if (!supertx_enabled) @@ -3020,31 +3024,30 @@ } static void setup_render_size(AV1_COMMON *cm, struct aom_read_bit_buffer *rb) { +#if CONFIG_FRAME_SUPERRES + cm->render_width = cm->superres_upscaled_width; + cm->render_height = cm->superres_upscaled_height; +#else cm->render_width = cm->width; cm->render_height = cm->height; +#endif // CONFIG_FRAME_SUPERRES if (aom_rb_read_bit(rb)) av1_read_frame_size(rb, &cm->render_width, &cm->render_height); } #if 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): Save input resolution - it's the upscaled resolution +static void setup_superres(AV1_COMMON *const cm, struct aom_read_bit_buffer *rb, + int *width, int *height) { + cm->superres_upscaled_width = *width; + cm->superres_upscaled_height = *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 = *width * cm->superres_scale_numerator / SUPERRES_SCALE_DENOMINATOR; - *height = - *width * cm->superres_scale_numerator / SUPERRES_SCALE_DENOMINATOR; + av1_calculate_superres_size(cm, width, height); } else { // 1:1 scaling - ie. no scaling, scale not provided cm->superres_scale_numerator = SUPERRES_SCALE_DENOMINATOR; @@ -3097,10 +3100,10 @@ int width, height; BufferPool *const pool = cm->buffer_pool; av1_read_frame_size(rb, &width, &height); - setup_render_size(cm, rb); #if CONFIG_FRAME_SUPERRES - setup_superres_size(cm, rb, &width, &height); + setup_superres(cm, rb, &width, &height); #endif // CONFIG_FRAME_SUPERRES + setup_render_size(cm, rb); resize_context_buffers(cm, width, height); lock_buffer_pool(pool); @@ -3149,6 +3152,9 @@ height = buf->y_crop_height; cm->render_width = buf->render_width; cm->render_height = buf->render_height; +#if CONFIG_FRAME_SUPERRES + setup_superres(cm, rb, &width, &height); +#endif // CONFIG_FRAME_SUPERRES found = 1; break; } @@ -3156,10 +3162,10 @@ if (!found) { av1_read_frame_size(rb, &width, &height); - setup_render_size(cm, rb); #if CONFIG_FRAME_SUPERRES - setup_superres_size(cm, rb, &width, &height); + setup_superres(cm, rb, &width, &height); #endif // CONFIG_FRAME_SUPERRES + setup_render_size(cm, rb); } if (width <= 0 || height <= 0) @@ -5186,6 +5192,19 @@ } #endif +#if CONFIG_FRAME_SUPERRES +void superres_post_decode(AV1Decoder *pbi) { + AV1_COMMON *const cm = &pbi->common; + BufferPool *const pool = cm->buffer_pool; + + if (av1_superres_unscaled(cm)) return; + + lock_buffer_pool(pool); + av1_superres_upscale(cm, pool); + unlock_buffer_pool(pool); +} +#endif // CONFIG_FRAME_SUPERRES + void av1_decode_frame(AV1Decoder *pbi, const uint8_t *data, const uint8_t *data_end, const uint8_t **p_data_end) { AV1_COMMON *const cm = &pbi->common; @@ -5281,14 +5300,23 @@ #if CONFIG_TEMPMV_SIGNALING if (cm->use_prev_frame_mvs) { assert(!cm->error_resilient_mode && cm->prev_frame && - cm->width == last_fb_ref_buf->buf->y_width && - cm->height == last_fb_ref_buf->buf->y_height && +#if CONFIG_FRAME_SUPERRES + cm->width == cm->last_width && cm->height == cm->last_height && +#else + cm->width == last_fb_ref_buf->buf->y_crop_width && + cm->height == last_fb_ref_buf->buf->y_crop_height && +#endif // CONFIG_FRAME_SUPERRES !cm->prev_frame->intra_only); } #else cm->use_prev_frame_mvs = !cm->error_resilient_mode && cm->prev_frame && +#if CONFIG_FRAME_SUPERRES + cm->width == cm->last_width && + cm->height == cm->last_height && +#else cm->width == cm->prev_frame->buf.y_crop_width && cm->height == cm->prev_frame->buf.y_crop_height && +#endif // CONFIG_FRAME_SUPERRES !cm->last_intra_only && cm->last_show_frame && (cm->last_frame_type != KEY_FRAME); #endif // CONFIG_TEMPMV_SIGNALING @@ -5361,6 +5389,10 @@ } #endif // CONFIG_CDEF +#if CONFIG_FRAME_SUPERRES + superres_post_decode(pbi); +#endif // CONFIG_FRAME_SUPERRES + #if CONFIG_LOOP_RESTORATION if (cm->rst_info[0].frame_restoration_type != RESTORE_NONE || cm->rst_info[1].frame_restoration_type != RESTORE_NONE ||
diff --git a/av1/decoder/decoder.c b/av1/decoder/decoder.c index eac280d..15a227c 100644 --- a/av1/decoder/decoder.c +++ b/av1/decoder/decoder.c
@@ -444,7 +444,10 @@ // border. if (pbi->dec_tile_row == -1 && pbi->dec_tile_col == -1) #endif // CONFIG_EXT_TILE - aom_extend_frame_inner_borders(cm->frame_to_show); + // TODO(debargha): Fix encoder side mv range, so that we can use the + // inner border extension. As of now use the larger extension. + // aom_extend_frame_inner_borders(cm->frame_to_show); + aom_extend_frame_borders(cm->frame_to_show); aom_clear_system_state();
diff --git a/av1/encoder/aq_cyclicrefresh.c b/av1/encoder/aq_cyclicrefresh.c index b2b4106..05aa28c 100644 --- a/av1/encoder/aq_cyclicrefresh.c +++ b/av1/encoder/aq_cyclicrefresh.c
@@ -352,10 +352,7 @@ // For video conference clips, if the background has high motion in current // frame because of the camera movement, set this frame as the golden frame. // Use 70% and 5% as the thresholds for golden frame refreshing. - // Also, force this frame as a golden update frame if this frame will change - // the resolution (av1_resize_pending != 0). - if (av1_resize_pending(cpi) || - (cnt1 * 10 > (70 * rows * cols) && cnt2 * 20 < cnt1)) { + if (cnt1 * 10 > (70 * rows * cols) && cnt2 * 20 < cnt1) { av1_cyclic_refresh_set_golden_update(cpi); rc->frames_till_gf_update_due = rc->baseline_gf_interval;
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c index c44867b..fb8ab94 100644 --- a/av1/encoder/bitstream.c +++ b/av1/encoder/bitstream.c
@@ -4172,8 +4172,7 @@ static void write_render_size(const AV1_COMMON *cm, struct aom_write_bit_buffer *wb) { - const int scaling_active = - cm->width != cm->render_width || cm->height != cm->render_height; + const int scaling_active = !av1_resize_unscaled(cm); aom_wb_write_bit(wb, scaling_active); if (scaling_active) { aom_wb_write_literal(wb, cm->render_width - 1, 16); @@ -4189,7 +4188,6 @@ 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); @@ -4199,13 +4197,15 @@ static void write_frame_size(const AV1_COMMON *cm, struct aom_write_bit_buffer *wb) { +#if CONFIG_FRAME_SUPERRES + aom_wb_write_literal(wb, cm->superres_upscaled_width - 1, 16); + aom_wb_write_literal(wb, cm->superres_upscaled_height - 1, 16); + write_superres_scale(cm, wb); +#else aom_wb_write_literal(wb, cm->width - 1, 16); aom_wb_write_literal(wb, cm->height - 1, 16); - - write_render_size(cm, wb); -#if CONFIG_FRAME_SUPERRES - write_superres_scale(cm, wb); #endif // CONFIG_FRAME_SUPERRES + write_render_size(cm, wb); } static void write_frame_size_with_refs(AV1_COMP *cpi, @@ -4218,20 +4218,26 @@ YV12_BUFFER_CONFIG *cfg = get_ref_frame_buffer(cpi, ref_frame); if (cfg != NULL) { +#if CONFIG_FRAME_SUPERRES + found = cm->superres_upscaled_width == cfg->y_crop_width && + cm->superres_upscaled_height == cfg->y_crop_height; +#else found = cm->width == cfg->y_crop_width && cm->height == cfg->y_crop_height; +#endif found &= cm->render_width == cfg->render_width && cm->render_height == cfg->render_height; } aom_wb_write_bit(wb, found); if (found) { +#if CONFIG_FRAME_SUPERRES + write_superres_scale(cm, wb); +#endif // CONFIG_FRAME_SUPERRES break; } } - if (!found) { - write_frame_size(cm, wb); - } + if (!found) write_frame_size(cm, wb); } static void write_sync_code(struct aom_write_bit_buffer *wb) { @@ -4370,11 +4376,6 @@ } #endif -#if CONFIG_FRAME_SUPERRES - // TODO(afergs): Remove - this is just to stop superres from breaking - cm->superres_scale_numerator = SUPERRES_SCALE_DENOMINATOR; -#endif // CONFIG_FRAME_SUPERRES - if (cm->frame_type == KEY_FRAME) { write_sync_code(wb); write_bitdepth_colorspace_sampling(cm, wb);
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c index 4e30d16..a0eed78 100644 --- a/av1/encoder/encodeframe.c +++ b/av1/encoder/encodeframe.c
@@ -4860,17 +4860,31 @@ #if CONFIG_TEMPMV_SIGNALING if (cm->prev_frame) { cm->use_prev_frame_mvs &= !cm->error_resilient_mode && - cm->width == cm->prev_frame->buf.y_width && - cm->height == cm->prev_frame->buf.y_height && +#if CONFIG_FRAME_SUPERRES + cm->width == cm->last_width && + cm->height == cm->last_height && +#else + cm->width == cm->prev_frame->buf.y_crop_width && + cm->height == cm->prev_frame->buf.y_crop_height && +#endif // CONFIG_FRAME_SUPERRES !cm->intra_only && !cm->prev_frame->intra_only; } else { cm->use_prev_frame_mvs = 0; } #else - cm->use_prev_frame_mvs = !cm->error_resilient_mode && cm->prev_frame && - cm->width == cm->prev_frame->buf.y_crop_width && - cm->height == cm->prev_frame->buf.y_crop_height && - !cm->intra_only && cm->last_show_frame; + if (cm->prev_frame) { + cm->use_prev_frame_mvs = !cm->error_resilient_mode && +#if CONFIG_FRAME_SUPERRES + cm->width == cm->last_width && + cm->height == cm->last_height && +#else + cm->width == cm->prev_frame->buf.y_crop_width && + cm->height == cm->prev_frame->buf.y_crop_height && +#endif // CONFIG_FRAME_SUPERRES + !cm->intra_only && cm->last_show_frame; + } else { + cm->use_prev_frame_mvs = 0; + } #endif // CONFIG_TEMPMV_SIGNALING // Special case: set prev_mi to NULL when the previous mode info
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c index f27928b..e9a27a9 100644 --- a/av1/encoder/encoder.c +++ b/av1/encoder/encoder.c
@@ -2099,10 +2099,6 @@ cpi->resize_state = 0; cpi->resize_avg_qp = 0; cpi->resize_buffer_underflow = 0; - cpi->resize_scale_num = 16; - cpi->resize_scale_den = 16; - cpi->resize_next_scale_num = 16; - cpi->resize_next_scale_den = 16; cpi->common.buffer_pool = pool; @@ -2450,6 +2446,8 @@ av1_loop_filter_init(cm); #if CONFIG_FRAME_SUPERRES cm->superres_scale_numerator = SUPERRES_SCALE_DENOMINATOR; + cm->superres_upscaled_width = oxcf->scaled_frame_width; + cm->superres_upscaled_height = oxcf->scaled_frame_height; #endif // CONFIG_FRAME_SUPERRES #if CONFIG_LOOP_RESTORATION av1_loop_restoration_precal(); @@ -3380,61 +3378,6 @@ #endif // DUMP_REF_FRAME_IMAGES } -static void loopfilter_frame(AV1_COMP *cpi, AV1_COMMON *cm) { - MACROBLOCKD *xd = &cpi->td.mb.e_mbd; - struct loopfilter *lf = &cm->lf; - if (is_lossless_requested(&cpi->oxcf)) { - lf->filter_level = 0; - } else { - struct aom_usec_timer timer; - - aom_clear_system_state(); - - aom_usec_timer_start(&timer); - - av1_pick_filter_level(cpi->source, cpi, cpi->sf.lpf_pick); - - aom_usec_timer_mark(&timer); - cpi->time_pick_lpf += aom_usec_timer_elapsed(&timer); - } - - if (lf->filter_level > 0) { -#if CONFIG_VAR_TX || CONFIG_EXT_PARTITION || CONFIG_CB4X4 - av1_loop_filter_frame(cm->frame_to_show, cm, xd, lf->filter_level, 0, 0); -#else - if (cpi->num_workers > 1) - av1_loop_filter_frame_mt(cm->frame_to_show, cm, xd->plane, - lf->filter_level, 0, 0, cpi->workers, - cpi->num_workers, &cpi->lf_row_sync); - else - av1_loop_filter_frame(cm->frame_to_show, cm, xd, lf->filter_level, 0, 0); -#endif - } -#if CONFIG_CDEF - if (is_lossless_requested(&cpi->oxcf)) { - cm->cdef_bits = 0; - cm->cdef_strengths[0] = 0; - cm->nb_cdef_strengths = 1; - } else { - // Find cm->dering_level, cm->clpf_strength_u and cm->clpf_strength_v - av1_cdef_search(cm->frame_to_show, cpi->source, cm, xd, - cpi->oxcf.speed > 0); - - // Apply the filter - av1_cdef_frame(cm->frame_to_show, cm, xd); - } -#endif -#if CONFIG_LOOP_RESTORATION - av1_pick_filter_restoration(cpi->source, cpi, cpi->sf.lpf_pick); - if (cm->rst_info[0].frame_restoration_type != RESTORE_NONE || - cm->rst_info[1].frame_restoration_type != RESTORE_NONE || - cm->rst_info[2].frame_restoration_type != RESTORE_NONE) { - av1_loop_restoration_frame(cm->frame_to_show, cm, cm->rst_info, 7, 0, NULL); - } -#endif // CONFIG_LOOP_RESTORATION - aom_extend_frame_inner_borders(cm->frame_to_show); -} - static INLINE void alloc_frame_mvs(AV1_COMMON *const cm, int buffer_idx) { RefCntBuffer *const new_fb_ptr = &cm->buffer_pool->frame_bufs[buffer_idx]; if (new_fb_ptr->mvs == NULL || new_fb_ptr->mi_rows < cm->mi_rows || @@ -3789,56 +3732,19 @@ } #endif // CONFIG_LOOP_RESTORATION -static void set_scaled_size(AV1_COMP *cpi) { - AV1_COMMON *const cm = &cpi->common; - AV1EncoderConfig *const oxcf = &cpi->oxcf; - - // TODO(afergs): Replace with call to av1_resize_pending? Could replace - // scaled_size_set as well. - // TODO(afergs): Realistically, if resize_pending is true, then the other - // conditions must already be satisfied. - // Try this first: - // av1_resize_pending && - // (DYNAMIC && (1 Pass CBR || 2 Pass VBR) - // STATIC && FIRST_FRAME) - // Really, av1_resize_pending should just reflect the above. - // TODO(afergs): Allow fixed resizing in AOM_CBR mode? - // 2 Pass VBR: Resize if fixed resize and first frame, or dynamic resize and - // a resize is pending. - // 1 Pass CBR: Resize if dynamic resize and resize pending. - if ((oxcf->pass == 2 && oxcf->rc_mode == AOM_VBR && - ((oxcf->resize_mode == RESIZE_FIXED && cm->current_video_frame == 0) || - (oxcf->resize_mode == RESIZE_DYNAMIC && av1_resize_pending(cpi)))) || - (oxcf->pass == 0 && oxcf->rc_mode == AOM_CBR && - oxcf->resize_mode == RESIZE_DYNAMIC && av1_resize_pending(cpi))) { - // TODO(afergs): This feels hacky... Should it just set? Should - // av1_set_next_scaled_size be a library function? - av1_calculate_next_scaled_size(cpi, &oxcf->scaled_frame_width, - &oxcf->scaled_frame_height); - } -} - static void set_frame_size(AV1_COMP *cpi, int width, int height) { - int ref_frame; AV1_COMMON *const cm = &cpi->common; - AV1EncoderConfig *const oxcf = &cpi->oxcf; MACROBLOCKD *const xd = &cpi->td.mb.e_mbd; + int ref_frame; if (width != cm->width || height != cm->height) { // There has been a change in the encoded frame size av1_set_size_literal(cpi, width, height); - - // TODO(agrange) Scale cpi->max_mv_magnitude if frame-size has changed. - // TODO(afergs): Make condition just (pass == 0) or (rc_mode == CBR) - - // UNLESS CBR starts allowing FIXED resizing. Then the resize - // mode will need to get checked too. - if (oxcf->pass == 0 && oxcf->rc_mode == AOM_CBR && - oxcf->resize_mode == RESIZE_DYNAMIC) - set_mv_search_params(cpi); // TODO(afergs): Needed? Caller calls after... + set_mv_search_params(cpi); } #if !CONFIG_XIPHRC - if (oxcf->pass == 2) { + if (cpi->oxcf.pass == 2) { av1_set_target_rate(cpi); } #endif @@ -3857,6 +3763,7 @@ "Failed to allocate frame buffer"); #if CONFIG_LOOP_RESTORATION + // TODO(afergs): Use cm->superres_upscaled_(width|height) set_restoration_tilesize(cm->width, cm->height, cm->rst_info); for (int i = 0; i < MAX_MB_PLANE; ++i) cm->rst_info[i].frame_restoration_type = RESTORE_NONE; @@ -3915,16 +3822,124 @@ } static void setup_frame_size(AV1_COMP *cpi) { - set_scaled_size(cpi); -#if CONFIG_FRAME_SUPERRES int encode_width; int encode_height; - av1_calculate_superres_size(cpi, &encode_width, &encode_height); - set_frame_size(cpi, encode_width, encode_height); -#else - set_frame_size(cpi, cpi->oxcf.scaled_frame_width, - cpi->oxcf.scaled_frame_height); + + av1_calculate_next_scaled_size(cpi, &encode_width, &encode_height); + +#if CONFIG_FRAME_SUPERRES + AV1_COMMON *cm = &cpi->common; + cm->superres_upscaled_width = encode_width; + cm->superres_upscaled_height = encode_height; + av1_calculate_next_superres_scale(cpi, encode_width, encode_width); + av1_calculate_superres_size(cm, &encode_width, &encode_height); #endif // CONFIG_FRAME_SUPERRES + + set_frame_size(cpi, encode_width, encode_height); +} + +#if CONFIG_FRAME_SUPERRES +static void superres_post_encode(AV1_COMP *cpi) { + AV1_COMMON *cm = &cpi->common; + + if (av1_superres_unscaled(cm)) return; + + assert(cpi->unscaled_source->y_crop_width != cm->superres_upscaled_width); + assert(cpi->unscaled_source->y_crop_height != cm->superres_upscaled_height); + + av1_superres_upscale(cm, NULL); + + // If regular resizing is occurring the source will need to be downscaled to + // match the upscaled superres resolution. Otherwise the original source is + // used. + if (av1_resize_unscaled(cm)) { + cpi->source = cpi->unscaled_source; + if (cpi->last_source != NULL) cpi->last_source = cpi->unscaled_last_source; + } else { + // Do downscale. cm->(width|height) has been updated by av1_superres_upscale + if (aom_realloc_frame_buffer( + &cpi->scaled_source, cm->superres_upscaled_width, + cm->superres_upscaled_height, cm->subsampling_x, cm->subsampling_y, +#if CONFIG_HIGHBITDEPTH + cm->use_highbitdepth, +#endif // CONFIG_HIGHBITDEPTH + AOM_BORDER_IN_PIXELS, cm->byte_alignment, NULL, NULL, NULL)) + aom_internal_error( + &cm->error, AOM_CODEC_MEM_ERROR, + "Failed to reallocate scaled source buffer for superres"); + assert(cpi->scaled_source.y_crop_width == cm->superres_upscaled_width); + assert(cpi->scaled_source.y_crop_height == cm->superres_upscaled_height); +#if CONFIG_HIGHBITDEPTH + av1_resize_and_extend_frame(cpi->unscaled_source, &cpi->scaled_source, + (int)cm->bit_depth); +#else + av1_resize_and_extend_frame(cpi->unscaled_source, &cpi->scaled_source); +#endif // CONFIG_HIGHBITDEPTH + cpi->source = &cpi->scaled_source; + } +} +#endif // CONFIG_FRAME_SUPERRES + +static void loopfilter_frame(AV1_COMP *cpi, AV1_COMMON *cm) { + MACROBLOCKD *xd = &cpi->td.mb.e_mbd; + struct loopfilter *lf = &cm->lf; + if (is_lossless_requested(&cpi->oxcf)) { + lf->filter_level = 0; + } else { + struct aom_usec_timer timer; + + aom_clear_system_state(); + + aom_usec_timer_start(&timer); + + av1_pick_filter_level(cpi->source, cpi, cpi->sf.lpf_pick); + + aom_usec_timer_mark(&timer); + cpi->time_pick_lpf += aom_usec_timer_elapsed(&timer); + } + + if (lf->filter_level > 0) { +#if CONFIG_VAR_TX || CONFIG_EXT_PARTITION || CONFIG_CB4X4 + av1_loop_filter_frame(cm->frame_to_show, cm, xd, lf->filter_level, 0, 0); +#else + if (cpi->num_workers > 1) + av1_loop_filter_frame_mt(cm->frame_to_show, cm, xd->plane, + lf->filter_level, 0, 0, cpi->workers, + cpi->num_workers, &cpi->lf_row_sync); + else + av1_loop_filter_frame(cm->frame_to_show, cm, xd, lf->filter_level, 0, 0); +#endif + } +#if CONFIG_CDEF + if (is_lossless_requested(&cpi->oxcf)) { + cm->cdef_bits = 0; + cm->cdef_strengths[0] = 0; + cm->nb_cdef_strengths = 1; + } else { + // Find cm->dering_level, cm->clpf_strength_u and cm->clpf_strength_v + av1_cdef_search(cm->frame_to_show, cpi->source, cm, xd, + cpi->oxcf.speed > 0); + + // Apply the filter + av1_cdef_frame(cm->frame_to_show, cm, xd); + } +#endif + +#if CONFIG_FRAME_SUPERRES + superres_post_encode(cpi); +#endif // CONFIG_FRAME_SUPERRES + +#if CONFIG_LOOP_RESTORATION + av1_pick_filter_restoration(cpi->source, cpi, cpi->sf.lpf_pick); + if (cm->rst_info[0].frame_restoration_type != RESTORE_NONE || + cm->rst_info[1].frame_restoration_type != RESTORE_NONE || + cm->rst_info[2].frame_restoration_type != RESTORE_NONE) { + av1_loop_restoration_frame(cm->frame_to_show, cm, cm->rst_info, 7, 0, NULL); + } +#endif // CONFIG_LOOP_RESTORATION + // TODO(debargha): Fix mv search range on encoder side + // aom_extend_frame_inner_borders(cm->frame_to_show); + aom_extend_frame_borders(cm->frame_to_show); } static void reset_use_upsampled_references(AV1_COMP *cpi) { @@ -3950,30 +3965,24 @@ aom_clear_system_state(); -#if CONFIG_FRAME_SUPERRES - // TODO(afergs): Figure out when is actually a good time to do superres - cm->superres_scale_numerator = SUPERRES_SCALE_DENOMINATOR; - // (uint8_t)(rand() % 9 + SUPERRES_SCALE_NUMERATOR_MIN); - cpi->superres_pending = cpi->oxcf.superres_enabled && 0; -#endif // CONFIG_FRAME_SUPERRES - setup_frame_size(cpi); - av1_resize_step(cpi); + assert(cm->width == cpi->scaled_source.y_crop_width); + assert(cm->height == cpi->scaled_source.y_crop_height); // For 1 pass CBR under dynamic resize mode: use faster scaling for source. // Only for 2x2 scaling for now. if (cpi->oxcf.pass == 0 && cpi->oxcf.rc_mode == AOM_CBR && cpi->oxcf.resize_mode == RESIZE_DYNAMIC && - cpi->un_scaled_source->y_width == (cm->width << 1) && - cpi->un_scaled_source->y_height == (cm->height << 1)) { - cpi->source = av1_scale_if_required_fast(cm, cpi->un_scaled_source, + cpi->unscaled_source->y_width == (cm->width << 1) && + cpi->unscaled_source->y_height == (cm->height << 1)) { + cpi->source = av1_scale_if_required_fast(cm, cpi->unscaled_source, &cpi->scaled_source); if (cpi->unscaled_last_source != NULL) cpi->last_source = av1_scale_if_required_fast( cm, cpi->unscaled_last_source, &cpi->scaled_last_source); } else { cpi->source = - av1_scale_if_required(cm, cpi->un_scaled_source, &cpi->scaled_source); + av1_scale_if_required(cm, cpi->unscaled_source, &cpi->scaled_source); if (cpi->unscaled_last_source != NULL) cpi->last_source = av1_scale_if_required(cm, cpi->unscaled_last_source, &cpi->scaled_last_source); @@ -4011,11 +4020,6 @@ // transform / motion compensation build reconstruction frame av1_encode_frame(cpi); -#if CONFIG_FRAME_SUPERRES - // TODO(afergs): Upscale the frame to show - cpi->superres_pending = 0; -#endif // CONFIG_FRAME_SUPERRES - // Update some stats from cyclic refresh, and check if we should not update // golden reference, for 1 pass CBR. if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ && cm->frame_type != KEY_FRAME && @@ -4052,11 +4056,7 @@ setup_frame_size(cpi); -#if CONFIG_FRAME_SUPERRES - if (loop_count == 0 || av1_resize_pending(cpi) || cpi->superres_pending) { -#else - if (loop_count == 0 || av1_resize_pending(cpi)) { -#endif // CONFIG_FRAME_SUPERRES + if (loop_count == 0) { set_size_dependent_vars(cpi, &q, &bottom_index, &top_index); // cpi->sf.use_upsampled_references can be different from frame to frame. @@ -4077,9 +4077,6 @@ undershoot_seen = 0; #endif - // Advance resize to next state now that updates are done - av1_resize_step(cpi); - q_low = bottom_index; q_high = top_index; @@ -4094,8 +4091,7 @@ } cpi->source = - av1_scale_if_required(cm, cpi->un_scaled_source, &cpi->scaled_source); - + av1_scale_if_required(cm, cpi->unscaled_source, &cpi->scaled_source); if (cpi->unscaled_last_source != NULL) cpi->last_source = av1_scale_if_required(cm, cpi->unscaled_last_source, &cpi->scaled_last_source); @@ -4217,8 +4213,6 @@ #if !CONFIG_XIPHRC int retries = 0; - // TODO(afergs): Replace removed recode when av1_resize_pending is true - // Frame size out of permitted range: // Update correction factor & compute new Q to try... // Frame is too large @@ -5532,7 +5526,7 @@ if ((last_source = av1_lookahead_peek(cpi->lookahead, -1)) == NULL) return -1; } - + if (cm->current_video_frame > 0) assert(last_source != NULL); // Read in the source frame. source = av1_lookahead_pop(cpi->lookahead, flush); @@ -5544,11 +5538,9 @@ check_src_altref(cpi, source); } } - if (source) { - cpi->un_scaled_source = cpi->source = + cpi->unscaled_source = cpi->source = force_src_buffer ? force_src_buffer : &source->img; - cpi->unscaled_last_source = last_source != NULL ? &last_source->img : NULL; *time_stamp = source->ts_start; @@ -5619,7 +5611,6 @@ av1_rc_get_second_pass_params(cpi); } else if (oxcf->pass == 1) { setup_frame_size(cpi); - av1_resize_step(cpi); } #endif
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h index ee1257c..70de507 100644 --- a/av1/encoder/encoder.h +++ b/av1/encoder/encoder.h
@@ -21,6 +21,7 @@ #include "av1/common/entropymode.h" #include "av1/common/thread_common.h" #include "av1/common/onyxc_int.h" +#include "av1/common/resize.h" #include "av1/encoder/aq_cyclicrefresh.h" #if CONFIG_ANS #include "aom_dsp/ans.h" @@ -372,7 +373,7 @@ YV12_BUFFER_CONFIG *source; YV12_BUFFER_CONFIG *last_source; // NULL for first frame and alt_ref frames - YV12_BUFFER_CONFIG *un_scaled_source; + YV12_BUFFER_CONFIG *unscaled_source; YV12_BUFFER_CONFIG scaled_source; YV12_BUFFER_CONFIG *unscaled_last_source; YV12_BUFFER_CONFIG scaled_last_source; @@ -601,18 +602,10 @@ TileBufferEnc tile_buffers[MAX_TILE_ROWS][MAX_TILE_COLS]; int resize_state; - int resize_scale_num; - int resize_scale_den; - int resize_next_scale_num; - int resize_next_scale_den; int resize_avg_qp; int resize_buffer_underflow; int resize_count; -#if CONFIG_FRAME_SUPERRES - int superres_pending; -#endif // CONFIG_FRAME_SUPERRES - // VARIANCE_AQ segment map refresh int vaq_refresh; @@ -831,23 +824,22 @@ ubufs[new_uidx].ref_count++; } -// Returns 1 if a resize is pending and 0 otherwise. -static INLINE int av1_resize_pending(const struct AV1_COMP *cpi) { - return cpi->resize_scale_num != cpi->resize_next_scale_num || - cpi->resize_scale_den != cpi->resize_next_scale_den; -} - // Returns 1 if a frame is unscaled and 0 otherwise. -static INLINE int av1_resize_unscaled(const struct AV1_COMP *cpi) { - return cpi->resize_scale_num == cpi->resize_scale_den; +static INLINE int av1_resize_unscaled(const AV1_COMMON *cm) { +#if CONFIG_FRAME_SUPERRES + return cm->superres_upscaled_width == cm->render_width && + cm->superres_upscaled_height == cm->render_height; +#else + return cm->width == cm->render_width && cm->height == cm->render_height; +#endif // CONFIG_FRAME_SUPERRES } -// Moves resizing to the next state. This is just setting the numerator and -// denominator to the next numerator and denominator, causing -// av1_resize_pending to subsequently return false. -static INLINE void av1_resize_step(struct AV1_COMP *cpi) { - cpi->resize_scale_num = cpi->resize_next_scale_num; - cpi->resize_scale_den = cpi->resize_next_scale_den; +static INLINE int av1_frame_unscaled(const AV1_COMMON *cm) { +#if CONFIG_FRAME_SUPERRES + return av1_superres_unscaled(cm) && av1_resize_unscaled(cm); +#else + return av1_resize_unscaled(cm); +#endif // CONFIG_FRAME_SUPERRES } #ifdef __cplusplus
diff --git a/av1/encoder/firstpass.c b/av1/encoder/firstpass.c index 7a0abba..859c60b 100644 --- a/av1/encoder/firstpass.c +++ b/av1/encoder/firstpass.c
@@ -1231,27 +1231,6 @@ } } -void av1_calculate_next_scaled_size(const AV1_COMP *cpi, - int *scaled_frame_width, - int *scaled_frame_height) { - *scaled_frame_width = - cpi->oxcf.width * cpi->resize_next_scale_num / cpi->resize_next_scale_den; - *scaled_frame_height = cpi->oxcf.height * cpi->resize_next_scale_num / - cpi->resize_next_scale_den; -} - -#if CONFIG_FRAME_SUPERRES -void av1_calculate_superres_size(const AV1_COMP *cpi, int *encoded_width, - int *encoded_height) { - *encoded_width = cpi->oxcf.scaled_frame_width * - cpi->common.superres_scale_numerator / - SUPERRES_SCALE_DENOMINATOR; - *encoded_height = cpi->oxcf.scaled_frame_height * - cpi->common.superres_scale_numerator / - SUPERRES_SCALE_DENOMINATOR; -} -#endif // CONFIG_FRAME_SUPERRES - void av1_init_second_pass(AV1_COMP *cpi) { const AV1EncoderConfig *const oxcf = &cpi->oxcf; TWO_PASS *const twopass = &cpi->twopass; @@ -2291,12 +2270,6 @@ twopass->section_intra_rating = calculate_section_intra_ratio( start_pos, twopass->stats_in_end, rc->baseline_gf_interval); } - - if (oxcf->resize_mode == RESIZE_DYNAMIC) { - // Default to starting GF groups at normal frame size. - // TODO(afergs): Make a function for this - cpi->resize_next_scale_num = cpi->resize_next_scale_den; - } } // Threshold for use of the lagging second reference frame. High second ref @@ -2638,12 +2611,6 @@ // The count of bits left is adjusted elsewhere based on real coded frame // sizes. twopass->modified_error_left -= kf_group_err; - - if (oxcf->resize_mode == RESIZE_DYNAMIC) { - // Default to normal-sized frame on keyframes. - // TODO(afergs): Make a function for this - cpi->resize_next_scale_num = cpi->resize_next_scale_den; - } } // Define the reference buffers that will be updated post encode.
diff --git a/av1/encoder/firstpass.h b/av1/encoder/firstpass.h index 4310445..983b3b5 100644 --- a/av1/encoder/firstpass.h +++ b/av1/encoder/firstpass.h
@@ -177,18 +177,6 @@ // Post encode update of the rate control parameters for 2-pass void av1_twopass_postencode_update(struct AV1_COMP *cpi); -void av1_calculate_next_scaled_size(const struct AV1_COMP *cpi, - int *scaled_frame_width, - int *scaled_frame_height); - -#if CONFIG_FRAME_SUPERRES -// This is the size after superress scaling, which could be 1:1. -// Superres scaling happens after regular downscaling. -// TODO(afergs): Limit overall reduction to 1/2 of the original size -void av1_calculate_superres_size(const struct AV1_COMP *cpi, int *encoded_width, - int *encoded_height); -#endif // CONFIG_FRAME_SUPERRES - #if CONFIG_EXT_REFS static INLINE int get_number_of_extra_arfs(int interval, int arf_pending) { if (arf_pending && MAX_EXT_ARFS > 0)
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c index 4552c67..ed6e9e6 100644 --- a/av1/encoder/ratectrl.c +++ b/av1/encoder/ratectrl.c
@@ -94,8 +94,8 @@ static int kf_low = 400; double av1_resize_rate_factor(const AV1_COMP *cpi) { - return (double)(cpi->resize_scale_den * cpi->resize_scale_den) / - (cpi->resize_scale_num * cpi->resize_scale_num); + return (double)(cpi->oxcf.width * cpi->oxcf.height) / + (cpi->common.width * cpi->common.height); } // Functions to compute the active minq lookup table entries based on a @@ -1081,7 +1081,7 @@ } // Modify active_best_quality for downscaled normal frames. - if (!av1_resize_unscaled(cpi) && !frame_is_kf_gf_arf(cpi)) { + if (!av1_frame_unscaled(cm) && !frame_is_kf_gf_arf(cpi)) { int qdelta = av1_compute_qdelta_by_rate( rc, cm->frame_type, active_best_quality, 2.0, cm->bit_depth); active_best_quality = @@ -1164,7 +1164,7 @@ rc->this_frame_target = target; // Modify frame size target when down-scaled. - if (cpi->oxcf.resize_mode == RESIZE_DYNAMIC && !av1_resize_unscaled(cpi)) + if (!av1_frame_unscaled(cm)) rc->this_frame_target = (int)(rc->this_frame_target * av1_resize_rate_factor(cpi)); @@ -1663,3 +1663,59 @@ vbr_rate_correction(cpi, &target_rate); av1_rc_set_frame_target(cpi, target_rate); } + +static unsigned int lcg_rand16(unsigned int *state) { + *state = (unsigned int)(*state * 1103515245ULL + 12345); + return *state / 65536 % 32768; +} + +void av1_calculate_next_scaled_size(AV1_COMP *cpi, int *width, int *height) { + AV1EncoderConfig *oxcf = &cpi->oxcf; + + // TODO(afergs): Get width from frame instead? + *width = oxcf->width; + *height = oxcf->height; + + if (oxcf->resize_mode == RESIZE_FIXED) { + *width = oxcf->scaled_frame_width; + *height = oxcf->scaled_frame_height; + return; + } + if (oxcf->resize_mode == RESIZE_DYNAMIC) { + // NOTE: RESIZE_DYNAMIC defaults to random now. + static unsigned int seed = 56789; + if (oxcf->pass == 2 || oxcf->pass == 0) { + int scale_num = lcg_rand16(&seed) % 4 + 13; + int scale_den = 16; + if (!(cpi->oxcf.width * scale_num / scale_den * 2 < oxcf->width || + cpi->oxcf.height * scale_num / scale_den * 2 < oxcf->height)) { + *width = cpi->oxcf.width * scale_num / scale_den; + *height = cpi->oxcf.height * scale_num / scale_den; + } + } + } +} + +#if CONFIG_FRAME_SUPERRES +#define RANDOM_SUPERRES 1 +int av1_calculate_next_superres_scale(AV1_COMP *cpi, int width, int height) { + const AV1EncoderConfig *oxcf = &cpi->oxcf; + (void)width; + (void)height; + (void)oxcf; +#if RANDOM_SUPERRES + if (cpi->common.frame_type != KEY_FRAME) { + if (oxcf->pass == 2 || oxcf->pass == 0) { + static unsigned int seed = 34567; + int new_num = lcg_rand16(&seed) % 9 + 8; + if (new_num * width / SUPERRES_SCALE_DENOMINATOR * 2 < oxcf->width || + new_num * height / SUPERRES_SCALE_DENOMINATOR * 2 < oxcf->height) + new_num = SUPERRES_SCALE_DENOMINATOR; + cpi->common.superres_scale_numerator = new_num; + return new_num; + } + } +#endif // RANDOM_SUPERRES + return 16; +} +#endif // CONFIG_FRAME_SUPERRES
diff --git a/av1/encoder/ratectrl.h b/av1/encoder/ratectrl.h index 61bb0c2..13b1555 100644 --- a/av1/encoder/ratectrl.h +++ b/av1/encoder/ratectrl.h
@@ -256,6 +256,12 @@ int av1_resize_one_pass_cbr(struct AV1_COMP *cpi); +void av1_calculate_next_scaled_size(struct AV1_COMP *cpi, int *width, + int *height); +#if CONFIG_FRAME_SUPERRES +int av1_calculate_next_superres_scale(struct AV1_COMP *cpi, int width, + int height); +#endif // CONFIG_FRAME_SUPERRES #ifdef __cplusplus } // extern "C" #endif