diff options
Diffstat (limited to 'vp9')
-rw-r--r-- | vp9/common/vp9_onyxc_int.h | 10 | ||||
-rw-r--r-- | vp9/common/vp9_thread_common.c | 185 | ||||
-rw-r--r-- | vp9/common/vp9_thread_common.h | 22 | ||||
-rw-r--r-- | vp9/decoder/vp9_decodeframe.c | 43 | ||||
-rw-r--r-- | vp9/decoder/vp9_decoder.c | 2 | ||||
-rw-r--r-- | vp9/decoder/vp9_decoder.h | 2 | ||||
-rw-r--r-- | vp9/encoder/vp9_bitstream.c | 15 | ||||
-rw-r--r-- | vp9/encoder/vp9_denoiser.c | 135 | ||||
-rw-r--r-- | vp9/encoder/vp9_denoiser.h | 14 | ||||
-rw-r--r-- | vp9/encoder/vp9_encoder.c | 84 | ||||
-rw-r--r-- | vp9/encoder/vp9_encoder.h | 21 | ||||
-rw-r--r-- | vp9/encoder/vp9_ethread.c | 38 | ||||
-rw-r--r-- | vp9/encoder/vp9_ethread.h | 4 | ||||
-rw-r--r-- | vp9/encoder/vp9_firstpass.c | 57 | ||||
-rw-r--r-- | vp9/encoder/vp9_firstpass.h | 5 | ||||
-rw-r--r-- | vp9/encoder/vp9_ratectrl.c | 27 | ||||
-rw-r--r-- | vp9/encoder/vp9_ratectrl.h | 2 | ||||
-rw-r--r-- | vp9/encoder/vp9_rdopt.c | 11 | ||||
-rw-r--r-- | vp9/encoder/vp9_svc_layercontext.c | 16 | ||||
-rw-r--r-- | vp9/encoder/vp9_svc_layercontext.h | 4 | ||||
-rw-r--r-- | vp9/vp9_cx_iface.c | 12 | ||||
-rw-r--r-- | vp9/vp9_dx_iface.c | 4 |
22 files changed, 358 insertions, 355 deletions
diff --git a/vp9/common/vp9_onyxc_int.h b/vp9/common/vp9_onyxc_int.h index e053e2ee0..690fca796 100644 --- a/vp9/common/vp9_onyxc_int.h +++ b/vp9/common/vp9_onyxc_int.h @@ -128,6 +128,8 @@ typedef struct VP9Common { int new_fb_idx; + int cur_show_frame_fb_idx; + #if CONFIG_VP9_POSTPROC YV12_BUFFER_CONFIG post_proc_buffer; YV12_BUFFER_CONFIG post_proc_buffer_int; @@ -256,10 +258,14 @@ typedef struct VP9Common { PARTITION_CONTEXT *above_seg_context; ENTROPY_CONTEXT *above_context; int above_context_alloc_cols; - - int lf_row; } VP9_COMMON; +static INLINE YV12_BUFFER_CONFIG *get_buf_frame(VP9_COMMON *cm, int index) { + if (index < 0 || index >= FRAME_BUFFERS) return NULL; + if (cm->error.error_code != VPX_CODEC_OK) return NULL; + return &cm->buffer_pool->frame_bufs[index].buf; +} + static INLINE YV12_BUFFER_CONFIG *get_ref_frame(VP9_COMMON *cm, int index) { if (index < 0 || index >= REF_FRAMES) return NULL; if (cm->ref_frame_map[index] < 0) return NULL; diff --git a/vp9/common/vp9_thread_common.c b/vp9/common/vp9_thread_common.c index dc9aa405a..d4b076645 100644 --- a/vp9/common/vp9_thread_common.c +++ b/vp9/common/vp9_thread_common.c @@ -38,11 +38,11 @@ static INLINE void sync_read(VP9LfSync *const lf_sync, int r, int c) { const int nsync = lf_sync->sync_range; if (r && !(c & (nsync - 1))) { - pthread_mutex_t *const mutex = &lf_sync->mutex_[r - 1]; + pthread_mutex_t *const mutex = &lf_sync->mutex[r - 1]; mutex_lock(mutex); while (c > lf_sync->cur_sb_col[r - 1] - nsync) { - pthread_cond_wait(&lf_sync->cond_[r - 1], mutex); + pthread_cond_wait(&lf_sync->cond[r - 1], mutex); } pthread_mutex_unlock(mutex); } @@ -69,12 +69,12 @@ static INLINE void sync_write(VP9LfSync *const lf_sync, int r, int c, } if (sig) { - mutex_lock(&lf_sync->mutex_[r]); + mutex_lock(&lf_sync->mutex[r]); lf_sync->cur_sb_col[r] = cur; - pthread_cond_signal(&lf_sync->cond_[r]); - pthread_mutex_unlock(&lf_sync->mutex_[r]); + pthread_cond_signal(&lf_sync->cond[r]); + pthread_mutex_unlock(&lf_sync->mutex[r]); } #else (void)lf_sync; @@ -229,26 +229,6 @@ void vp9_loop_filter_frame_mt(YV12_BUFFER_CONFIG *frame, VP9_COMMON *cm, workers, num_workers, lf_sync); } -void vp9_lpf_mt_init(VP9LfSync *lf_sync, VP9_COMMON *cm, int frame_filter_level, - int num_workers) { - const int sb_rows = mi_cols_aligned_to_sb(cm->mi_rows) >> MI_BLOCK_SIZE_LOG2; - - if (!frame_filter_level) return; - - if (!lf_sync->sync_range || sb_rows != lf_sync->rows || - num_workers > lf_sync->num_workers) { - vp9_loop_filter_dealloc(lf_sync); - vp9_loop_filter_alloc(lf_sync, cm, sb_rows, cm->width, num_workers); - } - - // Initialize cur_sb_col to -1 for all SB rows. - memset(lf_sync->cur_sb_col, -1, sizeof(*lf_sync->cur_sb_col) * sb_rows); - - memset(lf_sync->num_tiles_done, 0, - sizeof(*lf_sync->num_tiles_done) * sb_rows); - cm->lf_row = 0; -} - // Set up nsync by width. static INLINE int get_sync_range(int width) { // nsync numbers are picked by testing. For example, for 4k @@ -271,38 +251,19 @@ void vp9_loop_filter_alloc(VP9LfSync *lf_sync, VP9_COMMON *cm, int rows, { int i; - CHECK_MEM_ERROR(cm, lf_sync->mutex_, - vpx_malloc(sizeof(*lf_sync->mutex_) * rows)); - if (lf_sync->mutex_) { + CHECK_MEM_ERROR(cm, lf_sync->mutex, + vpx_malloc(sizeof(*lf_sync->mutex) * rows)); + if (lf_sync->mutex) { for (i = 0; i < rows; ++i) { - pthread_mutex_init(&lf_sync->mutex_[i], NULL); + pthread_mutex_init(&lf_sync->mutex[i], NULL); } } - CHECK_MEM_ERROR(cm, lf_sync->cond_, - vpx_malloc(sizeof(*lf_sync->cond_) * rows)); - if (lf_sync->cond_) { + CHECK_MEM_ERROR(cm, lf_sync->cond, + vpx_malloc(sizeof(*lf_sync->cond) * rows)); + if (lf_sync->cond) { for (i = 0; i < rows; ++i) { - pthread_cond_init(&lf_sync->cond_[i], NULL); - } - } - pthread_mutex_init(&lf_sync->lf_mutex, NULL); - - CHECK_MEM_ERROR(cm, lf_sync->recon_done_mutex, - vpx_malloc(sizeof(*lf_sync->recon_done_mutex) * rows)); - if (lf_sync->recon_done_mutex) { - int i; - for (i = 0; i < rows; ++i) { - pthread_mutex_init(&lf_sync->recon_done_mutex[i], NULL); - } - } - - CHECK_MEM_ERROR(cm, lf_sync->recon_done_cond, - vpx_malloc(sizeof(*lf_sync->recon_done_cond) * rows)); - if (lf_sync->recon_done_cond) { - int i; - for (i = 0; i < rows; ++i) { - pthread_cond_init(&lf_sync->recon_done_cond[i], NULL); + pthread_cond_init(&lf_sync->cond[i], NULL); } } } @@ -315,11 +276,6 @@ void vp9_loop_filter_alloc(VP9LfSync *lf_sync, VP9_COMMON *cm, int rows, CHECK_MEM_ERROR(cm, lf_sync->cur_sb_col, vpx_malloc(sizeof(*lf_sync->cur_sb_col) * rows)); - CHECK_MEM_ERROR(cm, lf_sync->num_tiles_done, - vpx_malloc(sizeof(*lf_sync->num_tiles_done) * - mi_cols_aligned_to_sb(cm->mi_rows) >> - MI_BLOCK_SIZE_LOG2)); - // Set up nsync. lf_sync->sync_range = get_sync_range(width); } @@ -330,130 +286,27 @@ void vp9_loop_filter_dealloc(VP9LfSync *lf_sync) { #if CONFIG_MULTITHREAD int i; - if (lf_sync->mutex_ != NULL) { + if (lf_sync->mutex != NULL) { for (i = 0; i < lf_sync->rows; ++i) { - pthread_mutex_destroy(&lf_sync->mutex_[i]); + pthread_mutex_destroy(&lf_sync->mutex[i]); } - vpx_free(lf_sync->mutex_); + vpx_free(lf_sync->mutex); } - if (lf_sync->cond_ != NULL) { - for (i = 0; i < lf_sync->rows; ++i) { - pthread_cond_destroy(&lf_sync->cond_[i]); - } - vpx_free(lf_sync->cond_); - } - if (lf_sync->recon_done_mutex != NULL) { - int i; - for (i = 0; i < lf_sync->rows; ++i) { - pthread_mutex_destroy(&lf_sync->recon_done_mutex[i]); - } - vpx_free(lf_sync->recon_done_mutex); - } - - pthread_mutex_destroy(&lf_sync->lf_mutex); - if (lf_sync->recon_done_cond != NULL) { - int i; + if (lf_sync->cond != NULL) { for (i = 0; i < lf_sync->rows; ++i) { - pthread_cond_destroy(&lf_sync->recon_done_cond[i]); + pthread_cond_destroy(&lf_sync->cond[i]); } - vpx_free(lf_sync->recon_done_cond); + vpx_free(lf_sync->cond); } #endif // CONFIG_MULTITHREAD - vpx_free(lf_sync->lfdata); vpx_free(lf_sync->cur_sb_col); - vpx_free(lf_sync->num_tiles_done); // clear the structure as the source of this call may be a resize in which // case this call will be followed by an _alloc() which may fail. vp9_zero(*lf_sync); } } -static int get_next_row(VP9_COMMON *cm, VP9LfSync *lf_sync) { - int return_val = -1; - int cur_row; - const int max_rows = cm->mi_rows; - -#if CONFIG_MULTITHREAD - const int tile_cols = 1 << cm->log2_tile_cols; - - pthread_mutex_lock(&lf_sync->lf_mutex); - if (cm->lf_row < max_rows) { - cur_row = cm->lf_row >> MI_BLOCK_SIZE_LOG2; - return_val = cm->lf_row; - cm->lf_row += MI_BLOCK_SIZE; - if (cm->lf_row < max_rows) { - /* If this is not the last row, make sure the next row is also decoded. - * This is because the intra predict has to happen before loop filter */ - cur_row += 1; - } - } - pthread_mutex_unlock(&lf_sync->lf_mutex); - - if (return_val == -1) return return_val; - - pthread_mutex_lock(&lf_sync->recon_done_mutex[cur_row]); - if (lf_sync->num_tiles_done[cur_row] < tile_cols) { - pthread_cond_wait(&lf_sync->recon_done_cond[cur_row], - &lf_sync->recon_done_mutex[cur_row]); - } - pthread_mutex_unlock(&lf_sync->recon_done_mutex[cur_row]); -#else - (void)lf_sync; - if (cm->lf_row < max_rows) { - cur_row = cm->lf_row >> MI_BLOCK_SIZE_LOG2; - return_val = cm->lf_row; - cm->lf_row += MI_BLOCK_SIZE; - if (cm->lf_row < max_rows) { - /* If this is not the last row, make sure the next row is also decoded. - * This is because the intra predict has to happen before loop filter */ - cur_row += 1; - } - } -#endif // CONFIG_MULTITHREAD - - return return_val; -} - -void vp9_loopfilter_rows(LFWorkerData *lf_data, VP9LfSync *lf_sync, - MACROBLOCKD *xd) { - int mi_row; - VP9_COMMON *cm = lf_data->cm; - - while (!xd->corrupted && (mi_row = get_next_row(cm, lf_sync)) != -1 && - mi_row < cm->mi_rows) { - lf_data->start = mi_row; - lf_data->stop = mi_row + MI_BLOCK_SIZE; - - thread_loop_filter_rows(lf_data->frame_buffer, lf_data->cm, lf_data->planes, - lf_data->start, lf_data->stop, lf_data->y_only, - lf_sync); - } -} - -void vp9_set_row(VP9LfSync *lf_sync, int num_tiles, int row, int is_last_row) { -#if CONFIG_MULTITHREAD - pthread_mutex_lock(&lf_sync->recon_done_mutex[row]); - lf_sync->num_tiles_done[row] += 1; - if (num_tiles == lf_sync->num_tiles_done[row]) { - if (is_last_row) { - /* The last 2 rows wait on the last row to be done. - * So, we have to broadcast the signal in this case. - */ - pthread_cond_broadcast(&lf_sync->recon_done_cond[row]); - } else { - pthread_cond_signal(&lf_sync->recon_done_cond[row]); - } - } - pthread_mutex_unlock(&lf_sync->recon_done_mutex[row]); -#else - (void)lf_sync; - (void)num_tiles; - (void)row; - (void)is_last_row; -#endif // CONFIG_MULTITHREAD -} - // Accumulate frame counts. void vp9_accumulate_frame_counts(FRAME_COUNTS *accum, const FRAME_COUNTS *counts, int is_dec) { diff --git a/vp9/common/vp9_thread_common.h b/vp9/common/vp9_thread_common.h index 09609f821..92f4b2d2d 100644 --- a/vp9/common/vp9_thread_common.h +++ b/vp9/common/vp9_thread_common.h @@ -24,8 +24,8 @@ struct FRAME_COUNTS; // Loopfilter row synchronization typedef struct VP9LfSyncData { #if CONFIG_MULTITHREAD - pthread_mutex_t *mutex_; - pthread_cond_t *cond_; + pthread_mutex_t *mutex; + pthread_cond_t *cond; #endif // Allocate memory to store the loop-filtered superblock index in each row. int *cur_sb_col; @@ -37,13 +37,6 @@ typedef struct VP9LfSyncData { // Row-based parallel loopfilter data LFWorkerData *lfdata; int num_workers; - -#if CONFIG_MULTITHREAD - pthread_mutex_t lf_mutex; - pthread_mutex_t *recon_done_mutex; - pthread_cond_t *recon_done_cond; -#endif - int *num_tiles_done; } VP9LfSync; // Allocate memory for loopfilter row synchronization. @@ -60,17 +53,6 @@ void vp9_loop_filter_frame_mt(YV12_BUFFER_CONFIG *frame, struct VP9Common *cm, int partial_frame, VPxWorker *workers, int num_workers, VP9LfSync *lf_sync); -// Multi-threaded loopfilter initialisations -void vp9_lpf_mt_init(VP9LfSync *lf_sync, struct VP9Common *cm, - int frame_filter_level, int num_workers); - -void vp9_loopfilter_rows(LFWorkerData *lf_data, VP9LfSync *lf_sync, - MACROBLOCKD *xd); - -void vp9_set_row(VP9LfSync *lf_sync, int num_tiles, int row, int is_last_row); - -void vp9_set_last_decoded_row(struct VP9Common *cm, int tile_col, int mi_row); - void vp9_accumulate_frame_counts(struct FRAME_COUNTS *accum, const struct FRAME_COUNTS *counts, int is_dec); diff --git a/vp9/decoder/vp9_decodeframe.c b/vp9/decoder/vp9_decodeframe.c index b38f868fb..3c17c3dc3 100644 --- a/vp9/decoder/vp9_decodeframe.c +++ b/vp9/decoder/vp9_decodeframe.c @@ -1487,11 +1487,6 @@ static int tile_worker_hook(void *arg1, void *arg2) { TileInfo *volatile tile = &tile_data->xd.tile; const int final_col = (1 << pbi->common.log2_tile_cols) - 1; const uint8_t *volatile bit_reader_end = NULL; - VP9_COMMON *cm = &pbi->common; - - LFWorkerData *lf_data = tile_data->lf_data; - VP9LfSync *lf_sync = tile_data->lf_sync; - volatile int n = tile_data->buf_start; tile_data->error_info.setjmp = 1; @@ -1524,13 +1519,6 @@ static int tile_worker_hook(void *arg1, void *arg2) { mi_col += MI_BLOCK_SIZE) { decode_partition(tile_data, pbi, mi_row, mi_col, BLOCK_64X64, 4); } - if (cm->lf.filter_level && !cm->skip_loop_filter) { - const int aligned_rows = mi_cols_aligned_to_sb(cm->mi_rows); - const int sb_rows = (aligned_rows >> MI_BLOCK_SIZE_LOG2); - const int is_last_row = (sb_rows - 1 == mi_row >> MI_BLOCK_SIZE_LOG2); - vp9_set_row(lf_sync, 1 << cm->log2_tile_cols, - mi_row >> MI_BLOCK_SIZE_LOG2, is_last_row); - } } if (buf->col == final_col) { @@ -1538,11 +1526,6 @@ static int tile_worker_hook(void *arg1, void *arg2) { } } while (!tile_data->xd.corrupted && ++n <= tile_data->buf_end); - if (!tile_data->xd.corrupted && cm->lf.filter_level && - !cm->skip_loop_filter) { - vp9_loopfilter_rows(lf_data, lf_sync, &tile_data->xd); - } - tile_data->data_end = bit_reader_end; return !tile_data->xd.corrupted; } @@ -1559,8 +1542,6 @@ static const uint8_t *decode_tiles_mt(VP9Decoder *pbi, const uint8_t *data, VP9_COMMON *const cm = &pbi->common; const VPxWorkerInterface *const winterface = vpx_get_worker_interface(); const uint8_t *bit_reader_end = NULL; - VP9LfSync *lf_row_sync = &pbi->lf_row_sync; - YV12_BUFFER_CONFIG *const new_fb = get_frame_new_buffer(cm); const int aligned_mi_cols = mi_cols_aligned_to_sb(cm->mi_cols); const int tile_cols = 1 << cm->log2_tile_cols; const int tile_rows = 1 << cm->log2_tile_rows; @@ -1587,26 +1568,12 @@ static const uint8_t *decode_tiles_mt(VP9Decoder *pbi, const uint8_t *data, } } - // Initialize LPF - if (cm->lf.filter_level && !cm->skip_loop_filter) { - vp9_lpf_mt_init(lf_row_sync, cm, cm->lf.filter_level, - pbi->num_tile_workers); - } - // Reset tile decoding hook for (n = 0; n < num_workers; ++n) { VPxWorker *const worker = &pbi->tile_workers[n]; TileWorkerData *const tile_data = &pbi->tile_worker_data[n + pbi->total_tiles]; winterface->sync(worker); - - if (cm->lf.filter_level && !cm->skip_loop_filter) { - tile_data->lf_sync = lf_row_sync; - tile_data->lf_data = &tile_data->lf_sync->lfdata[n]; - vp9_loop_filter_data_reset(tile_data->lf_data, new_fb, cm, pbi->mb.plane); - tile_data->lf_data->y_only = 0; - } - tile_data->xd = pbi->mb; tile_data->xd.counts = cm->frame_parallel_decoding_mode ? NULL : &tile_data->counts; @@ -2128,7 +2095,15 @@ void vp9_decode_frame(VP9Decoder *pbi, const uint8_t *data, if (pbi->max_threads > 1 && tile_rows == 1 && tile_cols > 1) { // Multi-threaded tile decoder *p_data_end = decode_tiles_mt(pbi, data + first_partition_size, data_end); - if (xd->corrupted) { + if (!xd->corrupted) { + if (!cm->skip_loop_filter) { + // If multiple threads are used to decode tiles, then we use those + // threads to do parallel loopfiltering. + vp9_loop_filter_frame_mt(new_fb, cm, pbi->mb.plane, cm->lf.filter_level, + 0, 0, pbi->tile_workers, pbi->num_tile_workers, + &pbi->lf_row_sync); + } + } else { vpx_internal_error(&cm->error, VPX_CODEC_CORRUPT_FRAME, "Decode failed. Frame data is corrupted."); } diff --git a/vp9/decoder/vp9_decoder.c b/vp9/decoder/vp9_decoder.c index d6eacaf44..b4d05f663 100644 --- a/vp9/decoder/vp9_decoder.c +++ b/vp9/decoder/vp9_decoder.c @@ -365,6 +365,8 @@ int vp9_receive_compressed_data(VP9Decoder *pbi, size_t size, if (cm->seg.enabled) vp9_swap_current_and_last_seg_map(cm); } + if (cm->show_frame) cm->cur_show_frame_fb_idx = cm->new_fb_idx; + // Update progress in frame parallel decode. cm->last_width = cm->width; cm->last_height = cm->height; diff --git a/vp9/decoder/vp9_decoder.h b/vp9/decoder/vp9_decoder.h index 532f5f848..5f22c00cb 100644 --- a/vp9/decoder/vp9_decoder.h +++ b/vp9/decoder/vp9_decoder.h @@ -37,8 +37,6 @@ typedef struct TileWorkerData { int buf_start, buf_end; // pbi->tile_buffers to decode, inclusive vpx_reader bit_reader; FRAME_COUNTS counts; - LFWorkerData *lf_data; - VP9LfSync *lf_sync; DECLARE_ALIGNED(16, MACROBLOCKD, xd); /* dqcoeff are shared by all the planes. So planes must be decoded serially */ DECLARE_ALIGNED(16, tran_low_t, dqcoeff[32 * 32]); diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c index 79fc160c1..21a68bf39 100644 --- a/vp9/encoder/vp9_bitstream.c +++ b/vp9/encoder/vp9_bitstream.c @@ -909,10 +909,25 @@ int vp9_get_refresh_mask(VP9_COMP *cpi) { (cpi->refresh_golden_frame << cpi->alt_fb_idx); } else { int arf_idx = cpi->alt_fb_idx; + GF_GROUP *const gf_group = &cpi->twopass.gf_group; if ((cpi->oxcf.pass == 2) && cpi->multi_arf_allowed) { const GF_GROUP *const gf_group = &cpi->twopass.gf_group; arf_idx = gf_group->arf_update_idx[gf_group->index]; } + + if (cpi->multi_layer_arf) { + for (arf_idx = 0; arf_idx < REF_FRAMES; ++arf_idx) { + if (arf_idx != cpi->alt_fb_idx && arf_idx != cpi->lst_fb_idx && + arf_idx != cpi->gld_fb_idx) { + int idx; + for (idx = 0; idx < gf_group->stack_size; ++idx) + if (arf_idx == gf_group->arf_index_stack[idx]) break; + if (idx == gf_group->stack_size) break; + } + } + } + cpi->twopass.gf_group.top_arf_idx = arf_idx; + if (cpi->use_svc && cpi->svc.use_set_ref_frame_config && cpi->svc.temporal_layering_mode == VP9E_TEMPORAL_LAYERING_MODE_BYPASS) return cpi->svc.update_buffer_slot[cpi->svc.spatial_layer_id]; diff --git a/vp9/encoder/vp9_denoiser.c b/vp9/encoder/vp9_denoiser.c index 29311c79a..ab91971a3 100644 --- a/vp9/encoder/vp9_denoiser.c +++ b/vp9/encoder/vp9_denoiser.c @@ -449,10 +449,10 @@ static void swap_frame_buffer(YV12_BUFFER_CONFIG *const dest, } void vp9_denoiser_update_frame_info( - VP9_DENOISER *denoiser, YV12_BUFFER_CONFIG src, FRAME_TYPE frame_type, - int refresh_alt_ref_frame, int refresh_golden_frame, int refresh_last_frame, - int alt_fb_idx, int gld_fb_idx, int lst_fb_idx, int resized, - int svc_refresh_denoiser_buffers, int second_spatial_layer) { + VP9_DENOISER *denoiser, YV12_BUFFER_CONFIG src, struct SVC *svc, + FRAME_TYPE frame_type, int refresh_alt_ref_frame, int refresh_golden_frame, + int refresh_last_frame, int alt_fb_idx, int gld_fb_idx, int lst_fb_idx, + int resized, int svc_refresh_denoiser_buffers, int second_spatial_layer) { const int shift = second_spatial_layer ? denoiser->num_ref_frames : 0; // Copy source into denoised reference buffers on KEY_FRAME or // if the just encoded frame was resized. For SVC, copy source if the base @@ -469,32 +469,43 @@ void vp9_denoiser_update_frame_info( return; } - // If more than one refresh occurs, must copy frame buffer. - if ((refresh_alt_ref_frame + refresh_golden_frame + refresh_last_frame) > 1) { - if (refresh_alt_ref_frame) { - copy_frame(&denoiser->running_avg_y[alt_fb_idx + 1 + shift], - &denoiser->running_avg_y[INTRA_FRAME + shift]); - } - if (refresh_golden_frame) { - copy_frame(&denoiser->running_avg_y[gld_fb_idx + 1 + shift], - &denoiser->running_avg_y[INTRA_FRAME + shift]); - } - if (refresh_last_frame) { - copy_frame(&denoiser->running_avg_y[lst_fb_idx + 1 + shift], - &denoiser->running_avg_y[INTRA_FRAME + shift]); + if (svc->temporal_layering_mode == VP9E_TEMPORAL_LAYERING_MODE_BYPASS && + svc->use_set_ref_frame_config) { + int i; + for (i = 0; i < REF_FRAMES; i++) { + if (svc->update_buffer_slot[svc->spatial_layer_id] & (1 << i)) + copy_frame(&denoiser->running_avg_y[i + 1 + shift], + &denoiser->running_avg_y[INTRA_FRAME + shift]); } } else { - if (refresh_alt_ref_frame) { - swap_frame_buffer(&denoiser->running_avg_y[alt_fb_idx + 1 + shift], - &denoiser->running_avg_y[INTRA_FRAME + shift]); - } - if (refresh_golden_frame) { - swap_frame_buffer(&denoiser->running_avg_y[gld_fb_idx + 1 + shift], - &denoiser->running_avg_y[INTRA_FRAME + shift]); - } - if (refresh_last_frame) { - swap_frame_buffer(&denoiser->running_avg_y[lst_fb_idx + 1 + shift], - &denoiser->running_avg_y[INTRA_FRAME + shift]); + // If more than one refresh occurs, must copy frame buffer. + if ((refresh_alt_ref_frame + refresh_golden_frame + refresh_last_frame) > + 1) { + if (refresh_alt_ref_frame) { + copy_frame(&denoiser->running_avg_y[alt_fb_idx + 1 + shift], + &denoiser->running_avg_y[INTRA_FRAME + shift]); + } + if (refresh_golden_frame) { + copy_frame(&denoiser->running_avg_y[gld_fb_idx + 1 + shift], + &denoiser->running_avg_y[INTRA_FRAME + shift]); + } + if (refresh_last_frame) { + copy_frame(&denoiser->running_avg_y[lst_fb_idx + 1 + shift], + &denoiser->running_avg_y[INTRA_FRAME + shift]); + } + } else { + if (refresh_alt_ref_frame) { + swap_frame_buffer(&denoiser->running_avg_y[alt_fb_idx + 1 + shift], + &denoiser->running_avg_y[INTRA_FRAME + shift]); + } + if (refresh_golden_frame) { + swap_frame_buffer(&denoiser->running_avg_y[gld_fb_idx + 1 + shift], + &denoiser->running_avg_y[INTRA_FRAME + shift]); + } + if (refresh_last_frame) { + swap_frame_buffer(&denoiser->running_avg_y[lst_fb_idx + 1 + shift], + &denoiser->running_avg_y[INTRA_FRAME + shift]); + } } } } @@ -543,26 +554,38 @@ static int vp9_denoiser_realloc_svc_helper(VP9_COMMON *cm, } int vp9_denoiser_realloc_svc(VP9_COMMON *cm, VP9_DENOISER *denoiser, - int svc_buf_shift, int refresh_alt, - int refresh_gld, int refresh_lst, int alt_fb_idx, - int gld_fb_idx, int lst_fb_idx) { + struct SVC *svc, int svc_buf_shift, + int refresh_alt, int refresh_gld, int refresh_lst, + int alt_fb_idx, int gld_fb_idx, int lst_fb_idx) { int fail = 0; - if (refresh_alt) { - // Increase the frame buffer index by 1 to map it to the buffer index in the - // denoiser. - fail = vp9_denoiser_realloc_svc_helper(cm, denoiser, - alt_fb_idx + 1 + svc_buf_shift); - if (fail) return 1; - } - if (refresh_gld) { - fail = vp9_denoiser_realloc_svc_helper(cm, denoiser, - gld_fb_idx + 1 + svc_buf_shift); - if (fail) return 1; - } - if (refresh_lst) { - fail = vp9_denoiser_realloc_svc_helper(cm, denoiser, - lst_fb_idx + 1 + svc_buf_shift); - if (fail) return 1; + if (svc->temporal_layering_mode == VP9E_TEMPORAL_LAYERING_MODE_BYPASS && + svc->use_set_ref_frame_config) { + int i; + for (i = 0; i < REF_FRAMES; i++) { + if (cm->frame_type == KEY_FRAME || + svc->update_buffer_slot[svc->spatial_layer_id] & (1 << i)) { + fail = vp9_denoiser_realloc_svc_helper(cm, denoiser, + i + 1 + svc_buf_shift); + } + } + } else { + if (refresh_alt) { + // Increase the frame buffer index by 1 to map it to the buffer index in + // the denoiser. + fail = vp9_denoiser_realloc_svc_helper(cm, denoiser, + alt_fb_idx + 1 + svc_buf_shift); + if (fail) return 1; + } + if (refresh_gld) { + fail = vp9_denoiser_realloc_svc_helper(cm, denoiser, + gld_fb_idx + 1 + svc_buf_shift); + if (fail) return 1; + } + if (refresh_lst) { + fail = vp9_denoiser_realloc_svc_helper(cm, denoiser, + lst_fb_idx + 1 + svc_buf_shift); + if (fail) return 1; + } } return 0; } @@ -740,18 +763,20 @@ void vp9_denoiser_update_ref_frame(VP9_COMP *const cpi) { svc->number_spatial_layers - svc->spatial_layer_id == 2 ? 1 : 0; // Check if we need to allocate extra buffers in the denoiser // for refreshed frames. - if (vp9_denoiser_realloc_svc( - cm, &cpi->denoiser, svc_buf_shift, cpi->refresh_alt_ref_frame, - cpi->refresh_golden_frame, cpi->refresh_last_frame, - cpi->alt_fb_idx, cpi->gld_fb_idx, cpi->lst_fb_idx)) + if (vp9_denoiser_realloc_svc(cm, &cpi->denoiser, svc, svc_buf_shift, + cpi->refresh_alt_ref_frame, + cpi->refresh_golden_frame, + cpi->refresh_last_frame, cpi->alt_fb_idx, + cpi->gld_fb_idx, cpi->lst_fb_idx)) vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR, "Failed to re-allocate denoiser for SVC"); } vp9_denoiser_update_frame_info( - &cpi->denoiser, *cpi->Source, frame_type, cpi->refresh_alt_ref_frame, - cpi->refresh_golden_frame, cpi->refresh_last_frame, cpi->alt_fb_idx, - cpi->gld_fb_idx, cpi->lst_fb_idx, cpi->resize_pending, - svc_refresh_denoiser_buffers, denoise_svc_second_layer); + &cpi->denoiser, *cpi->Source, svc, frame_type, + cpi->refresh_alt_ref_frame, cpi->refresh_golden_frame, + cpi->refresh_last_frame, cpi->alt_fb_idx, cpi->gld_fb_idx, + cpi->lst_fb_idx, cpi->resize_pending, svc_refresh_denoiser_buffers, + denoise_svc_second_layer); } } diff --git a/vp9/encoder/vp9_denoiser.h b/vp9/encoder/vp9_denoiser.h index 13f0abd6a..d2129ecf4 100644 --- a/vp9/encoder/vp9_denoiser.h +++ b/vp9/encoder/vp9_denoiser.h @@ -70,10 +70,10 @@ struct VP9_COMP; struct SVC; void vp9_denoiser_update_frame_info( - VP9_DENOISER *denoiser, YV12_BUFFER_CONFIG src, FRAME_TYPE frame_type, - int refresh_alt_ref_frame, int refresh_golden_frame, int refresh_last_frame, - int alt_fb_idx, int gld_fb_idx, int lst_fb_idx, int resized, - int svc_refresh_denoiser_buffers, int second_spatial_layer); + VP9_DENOISER *denoiser, YV12_BUFFER_CONFIG src, struct SVC *svc, + FRAME_TYPE frame_type, int refresh_alt_ref_frame, int refresh_golden_frame, + int refresh_last_frame, int alt_fb_idx, int gld_fb_idx, int lst_fb_idx, + int resized, int svc_refresh_denoiser_buffers, int second_spatial_layer); void vp9_denoiser_denoise(struct VP9_COMP *cpi, MACROBLOCK *mb, int mi_row, int mi_col, BLOCK_SIZE bs, PICK_MODE_CONTEXT *ctx, @@ -87,9 +87,9 @@ void vp9_denoiser_update_frame_stats(MODE_INFO *mi, unsigned int sse, PICK_MODE_CONTEXT *ctx); int vp9_denoiser_realloc_svc(VP9_COMMON *cm, VP9_DENOISER *denoiser, - int svc_buf_shift, int refresh_alt, - int refresh_gld, int refresh_lst, int alt_fb_idx, - int gld_fb_idx, int lst_fb_idx); + struct SVC *svc, int svc_buf_shift, + int refresh_alt, int refresh_gld, int refresh_lst, + int alt_fb_idx, int gld_fb_idx, int lst_fb_idx); int vp9_denoiser_alloc(VP9_COMMON *cm, struct SVC *svc, VP9_DENOISER *denoiser, int use_svc, int noise_sen, int width, int height, diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index 3207b1457..714c8a241 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -851,6 +851,10 @@ static void vp9_swap_mi_and_prev_mi(VP9_COMMON *cm) { // Current mip will be the prev_mip for the next frame. MODE_INFO **temp_base = cm->prev_mi_grid_base; MODE_INFO *temp = cm->prev_mip; + + // Skip update prev_mi frame in show_existing_frame mode. + if (cm->show_existing_frame) return; + cm->prev_mip = cm->mip; cm->mip = temp; @@ -3165,6 +3169,15 @@ void update_multi_arf_ref_frames(VP9_COMP *cpi) { void update_ref_frames(VP9_COMP *cpi) { VP9_COMMON *const cm = &cpi->common; BufferPool *const pool = cm->buffer_pool; + GF_GROUP *const gf_group = &cpi->twopass.gf_group; + + // Pop ARF. + if (cm->show_existing_frame) { + cpi->lst_fb_idx = cpi->alt_fb_idx; + cpi->alt_fb_idx = + stack_pop(gf_group->arf_index_stack, gf_group->stack_size); + --gf_group->stack_size; + } // At this point the new frame has been encoded. // If any buffer copy / swapping is signaled it should be done here. @@ -3192,16 +3205,25 @@ void update_ref_frames(VP9_COMP *cpi) { cpi->gld_fb_idx = tmp; } else { /* For non key/golden frames */ if (cpi->refresh_alt_ref_frame) { - int arf_idx = cpi->alt_fb_idx; + int arf_idx = gf_group->top_arf_idx; if ((cpi->oxcf.pass == 2) && cpi->multi_arf_allowed) { const GF_GROUP *const gf_group = &cpi->twopass.gf_group; arf_idx = gf_group->arf_update_idx[gf_group->index]; } + // Push new ARF into stack. + stack_push(gf_group->arf_index_stack, cpi->alt_fb_idx, + gf_group->stack_size); + ++gf_group->stack_size; + + assert(arf_idx < REF_FRAMES); + ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[arf_idx], cm->new_fb_idx); memcpy(cpi->interp_filter_selected[ALTREF_FRAME], cpi->interp_filter_selected[0], sizeof(cpi->interp_filter_selected[0])); + + cpi->alt_fb_idx = arf_idx; } if (cpi->refresh_golden_frame) { @@ -3809,6 +3831,20 @@ static void save_encode_params(VP9_COMP *cpi) { } #endif +static INLINE void set_raw_source_frame(VP9_COMP *cpi) { +#ifdef ENABLE_KF_DENOISE + if (is_spatial_denoise_enabled(cpi)) { + cpi->raw_source_frame = vp9_scale_if_required( + cm, &cpi->raw_unscaled_source, &cpi->raw_scaled_source, + (oxcf->pass == 0), EIGHTTAP, 0); + } else { + cpi->raw_source_frame = cpi->Source; + } +#else + cpi->raw_source_frame = cpi->Source; +#endif +} + static int encode_without_recode_loop(VP9_COMP *cpi, size_t *size, uint8_t *dest) { VP9_COMMON *const cm = &cpi->common; @@ -3822,7 +3858,10 @@ static int encode_without_recode_loop(VP9_COMP *cpi, size_t *size, ? cpi->svc.downsample_filter_phase[cpi->svc.spatial_layer_id] : 0; - if (cm->show_existing_frame) return 1; + if (cm->show_existing_frame) { + if (is_psnr_calc_enabled(cpi)) set_raw_source_frame(cpi); + return 1; + } // Flag to check if its valid to compute the source sad (used for // scene detection and for superblock content state in CBR mode). @@ -4101,7 +4140,10 @@ static void encode_with_recode_loop(VP9_COMP *cpi, size_t *size, int qrange_adj = 1; #endif - if (cm->show_existing_frame) return; + if (cm->show_existing_frame) { + if (is_psnr_calc_enabled(cpi)) set_raw_source_frame(cpi); + return; + } set_size_independent_vars(cpi); @@ -4913,17 +4955,18 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, size_t *size, } vp9_update_reference_frames(cpi); - for (t = TX_4X4; t <= TX_32X32; t++) - full_to_model_counts(cpi->td.counts->coef[t], - cpi->td.rd_counts.coef_counts[t]); - - if (!cm->error_resilient_mode && !cm->frame_parallel_decoding_mode) - vp9_adapt_coef_probs(cm); + if (!cm->show_existing_frame) { + for (t = TX_4X4; t <= TX_32X32; ++t) { + full_to_model_counts(cpi->td.counts->coef[t], + cpi->td.rd_counts.coef_counts[t]); + } - if (!frame_is_intra_only(cm)) { if (!cm->error_resilient_mode && !cm->frame_parallel_decoding_mode) { - vp9_adapt_mode_probs(cm); - vp9_adapt_mv_probs(cm, cm->allow_high_precision_mv); + if (!frame_is_intra_only(cm)) { + vp9_adapt_mode_probs(cm); + vp9_adapt_mv_probs(cm, cm->allow_high_precision_mv); + } + vp9_adapt_coef_probs(cm); } } @@ -4945,6 +4988,8 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, size_t *size, vp9_rc_postencode_update(cpi, *size); + *size = VPXMAX(1, *size); + #if 0 output_frame_level_debug_stats(cpi); #endif @@ -4967,7 +5012,10 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, size_t *size, cm->last_height = cm->height; // reset to normal state now that we are done. - if (!cm->show_existing_frame) cm->last_show_frame = cm->show_frame; + if (!cm->show_existing_frame) { + cm->last_show_frame = cm->show_frame; + cm->prev_frame = cm->cur_frame; + } if (cm->show_frame) { vp9_swap_mi_and_prev_mi(cm); @@ -4976,7 +5024,6 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, size_t *size, ++cm->current_video_frame; if (cpi->use_svc) vp9_inc_frame_in_layer(cpi); } - cm->prev_frame = cm->cur_frame; if (cpi->use_svc) { cpi->svc @@ -6082,9 +6129,14 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags, } } + // Clear arf index stack before group of pictures processing starts. + if (cpi->twopass.gf_group.index == 1) { + stack_init(cpi->twopass.gf_group.arf_index_stack, MAX_LAG_BUFFERS * 2); + cpi->twopass.gf_group.stack_size = 0; + } + if (arf_src_index) { assert(arf_src_index <= rc->frames_to_key); - if ((source = vp9_lookahead_peek(cpi->lookahead, arf_src_index)) != NULL) { cpi->alt_ref_source = source; @@ -6273,6 +6325,8 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags, } #endif // CONFIG_REALTIME_ONLY + if (cm->show_frame) cm->cur_show_frame_fb_idx = cm->new_fb_idx; + if (cm->refresh_frame_context) cm->frame_contexts[cm->frame_context_idx] = *cm->fc; diff --git a/vp9/encoder/vp9_encoder.h b/vp9/encoder/vp9_encoder.h index c740eada5..446e030ba 100644 --- a/vp9/encoder/vp9_encoder.h +++ b/vp9/encoder/vp9_encoder.h @@ -818,6 +818,27 @@ int vp9_set_size_literal(VP9_COMP *cpi, unsigned int width, void vp9_set_svc(VP9_COMP *cpi, int use_svc); +static INLINE int stack_pop(int *stack, int stack_size) { + int idx; + const int r = stack[0]; + for (idx = 1; idx < stack_size; ++idx) stack[idx - 1] = stack[idx]; + + return r; +} + +static INLINE int stack_top(const int *stack) { return stack[0]; } + +static INLINE void stack_push(int *stack, int new_item, int stack_size) { + int idx; + for (idx = stack_size; idx > 0; --idx) stack[idx] = stack[idx - 1]; + stack[0] = new_item; +} + +static INLINE void stack_init(int *stack, int length) { + int idx; + for (idx = 0; idx < length; ++idx) stack[idx] = -1; +} + int vp9_get_quantizer(struct VP9_COMP *cpi); static INLINE int frame_is_kf_gf_arf(const VP9_COMP *cpi) { diff --git a/vp9/encoder/vp9_ethread.c b/vp9/encoder/vp9_ethread.c index e8fc1107b..dc08ef343 100644 --- a/vp9/encoder/vp9_ethread.c +++ b/vp9/encoder/vp9_ethread.c @@ -270,19 +270,19 @@ void vp9_row_mt_sync_mem_alloc(VP9RowMTSync *row_mt_sync, VP9_COMMON *cm, { int i; - CHECK_MEM_ERROR(cm, row_mt_sync->mutex_, - vpx_malloc(sizeof(*row_mt_sync->mutex_) * rows)); - if (row_mt_sync->mutex_) { + CHECK_MEM_ERROR(cm, row_mt_sync->mutex, + vpx_malloc(sizeof(*row_mt_sync->mutex) * rows)); + if (row_mt_sync->mutex) { for (i = 0; i < rows; ++i) { - pthread_mutex_init(&row_mt_sync->mutex_[i], NULL); + pthread_mutex_init(&row_mt_sync->mutex[i], NULL); } } - CHECK_MEM_ERROR(cm, row_mt_sync->cond_, - vpx_malloc(sizeof(*row_mt_sync->cond_) * rows)); - if (row_mt_sync->cond_) { + CHECK_MEM_ERROR(cm, row_mt_sync->cond, + vpx_malloc(sizeof(*row_mt_sync->cond) * rows)); + if (row_mt_sync->cond) { for (i = 0; i < rows; ++i) { - pthread_cond_init(&row_mt_sync->cond_[i], NULL); + pthread_cond_init(&row_mt_sync->cond[i], NULL); } } } @@ -301,17 +301,17 @@ void vp9_row_mt_sync_mem_dealloc(VP9RowMTSync *row_mt_sync) { #if CONFIG_MULTITHREAD int i; - if (row_mt_sync->mutex_ != NULL) { + if (row_mt_sync->mutex != NULL) { for (i = 0; i < row_mt_sync->rows; ++i) { - pthread_mutex_destroy(&row_mt_sync->mutex_[i]); + pthread_mutex_destroy(&row_mt_sync->mutex[i]); } - vpx_free(row_mt_sync->mutex_); + vpx_free(row_mt_sync->mutex); } - if (row_mt_sync->cond_ != NULL) { + if (row_mt_sync->cond != NULL) { for (i = 0; i < row_mt_sync->rows; ++i) { - pthread_cond_destroy(&row_mt_sync->cond_[i]); + pthread_cond_destroy(&row_mt_sync->cond[i]); } - vpx_free(row_mt_sync->cond_); + vpx_free(row_mt_sync->cond); } #endif // CONFIG_MULTITHREAD vpx_free(row_mt_sync->cur_col); @@ -327,11 +327,11 @@ void vp9_row_mt_sync_read(VP9RowMTSync *const row_mt_sync, int r, int c) { const int nsync = row_mt_sync->sync_range; if (r && !(c & (nsync - 1))) { - pthread_mutex_t *const mutex = &row_mt_sync->mutex_[r - 1]; + pthread_mutex_t *const mutex = &row_mt_sync->mutex[r - 1]; pthread_mutex_lock(mutex); while (c > row_mt_sync->cur_col[r - 1] - nsync + 1) { - pthread_cond_wait(&row_mt_sync->cond_[r - 1], mutex); + pthread_cond_wait(&row_mt_sync->cond[r - 1], mutex); } pthread_mutex_unlock(mutex); } @@ -365,12 +365,12 @@ void vp9_row_mt_sync_write(VP9RowMTSync *const row_mt_sync, int r, int c, } if (sig) { - pthread_mutex_lock(&row_mt_sync->mutex_[r]); + pthread_mutex_lock(&row_mt_sync->mutex[r]); row_mt_sync->cur_col[r] = cur; - pthread_cond_signal(&row_mt_sync->cond_[r]); - pthread_mutex_unlock(&row_mt_sync->mutex_[r]); + pthread_cond_signal(&row_mt_sync->cond[r]); + pthread_mutex_unlock(&row_mt_sync->mutex[r]); } #else (void)row_mt_sync; diff --git a/vp9/encoder/vp9_ethread.h b/vp9/encoder/vp9_ethread.h index a396e621d..1a79f3175 100644 --- a/vp9/encoder/vp9_ethread.h +++ b/vp9/encoder/vp9_ethread.h @@ -33,8 +33,8 @@ typedef struct EncWorkerData { // Encoder row synchronization typedef struct VP9RowMTSyncData { #if CONFIG_MULTITHREAD - pthread_mutex_t *mutex_; - pthread_cond_t *cond_; + pthread_mutex_t *mutex; + pthread_cond_t *cond; #endif // Allocate memory to store the sb/mb block index in each row. int *cur_col; diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c index 01ac22807..38e1d37cc 100644 --- a/vp9/encoder/vp9_firstpass.c +++ b/vp9/encoder/vp9_firstpass.c @@ -2333,6 +2333,42 @@ static void define_gf_multi_arf_structure(VP9_COMP *cpi) { gf_group->brf_src_offset[frame_index] = 0; } +static void find_arf_order(GF_GROUP *gf_group, int *layer_depth, + int *index_counter, int depth, int start, int end) { + const int mid = (start + end + 1) >> 1; + const int min_frame_interval = 3; + + // Process regular P frames + if (end - start <= min_frame_interval) { + int idx; + for (idx = start; idx < end; ++idx) { + gf_group->update_type[*index_counter] = LF_UPDATE; + gf_group->arf_src_offset[*index_counter] = 0; + gf_group->rf_level[*index_counter] = INTER_NORMAL; + ++(*index_counter); + } + return; + } + + assert(abs(mid - start) > 1 && abs(mid - end) > 1); + + // Process ARF frame + layer_depth[*index_counter] = depth; + gf_group->update_type[*index_counter] = ARF_UPDATE; + gf_group->arf_src_offset[*index_counter] = mid - start; + gf_group->rf_level[*index_counter] = GF_ARF_LOW; + ++(*index_counter); + + find_arf_order(gf_group, layer_depth, index_counter, depth + 1, start, mid); + + gf_group->update_type[*index_counter] = USE_BUF_FRAME; + gf_group->arf_src_offset[*index_counter] = 0; + gf_group->rf_level[*index_counter] = INTER_NORMAL; + ++(*index_counter); + + find_arf_order(gf_group, layer_depth, index_counter, depth + 1, mid + 1, end); +} + static void define_gf_group_structure(VP9_COMP *cpi) { RATE_CONTROL *const rc = &cpi->rc; TWO_PASS *const twopass = &cpi->twopass; @@ -2343,6 +2379,7 @@ static void define_gf_group_structure(VP9_COMP *cpi) { int mid_frame_idx; unsigned char arf_buffer_indices[MAX_ACTIVE_ARFS]; int normal_frames; + int layer_depth[MAX_LAG_BUFFERS]; key_frame = cpi->common.frame_type == KEY_FRAME; @@ -2391,6 +2428,25 @@ static void define_gf_group_structure(VP9_COMP *cpi) { } } + if (rc->source_alt_ref_pending && cpi->multi_layer_arf) { + layer_depth[frame_index] = 1; + + find_arf_order(gf_group, layer_depth, &frame_index, 2, 0, + rc->baseline_gf_interval - 1); + + if (rc->source_alt_ref_pending) { + gf_group->update_type[frame_index] = OVERLAY_UPDATE; + gf_group->rf_level[frame_index] = INTER_NORMAL; + } else { + gf_group->update_type[frame_index] = GF_UPDATE; + gf_group->rf_level[frame_index] = GF_ARF_STD; + } + + (void)layer_depth; + + return; + } + // Note index of the first normal inter frame int eh group (not gf kf arf) gf_group->first_inter_index = frame_index; @@ -2399,6 +2455,7 @@ static void define_gf_group_structure(VP9_COMP *cpi) { normal_frames = rc->baseline_gf_interval - (key_frame || rc->source_alt_ref_pending); + for (i = 0; i < normal_frames; ++i) { int arf_idx = 0; if (twopass->stats_in >= twopass->stats_in_end) break; diff --git a/vp9/encoder/vp9_firstpass.h b/vp9/encoder/vp9_firstpass.h index 0a7e1adf7..e1c882df4 100644 --- a/vp9/encoder/vp9_firstpass.h +++ b/vp9/encoder/vp9_firstpass.h @@ -143,6 +143,11 @@ typedef struct { unsigned char brf_src_offset[MAX_STATIC_GF_GROUP_LENGTH + 2]; unsigned char bidir_pred_enabled[MAX_STATIC_GF_GROUP_LENGTH + 2]; int bit_allocation[MAX_STATIC_GF_GROUP_LENGTH + 2]; + + // TODO(jingning): The array size of arf_stack could be reduced. + int arf_index_stack[MAX_LAG_BUFFERS * 2]; + int top_arf_idx; + int stack_size; } GF_GROUP; typedef struct { diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c index 4e2fc3e3f..c0eafdebd 100644 --- a/vp9/encoder/vp9_ratectrl.c +++ b/vp9/encoder/vp9_ratectrl.c @@ -47,6 +47,8 @@ #define MIN_BPB_FACTOR 0.005 #define MAX_BPB_FACTOR 50 +#define FRAME_OVERHEAD_BITS 200 + #if CONFIG_VP9_HIGHBITDEPTH #define ASSIGN_MINQ_TABLE(bit_depth, name) \ do { \ @@ -210,23 +212,18 @@ int vp9_estimate_bits_at_q(FRAME_TYPE frame_type, int q, int mbs, int vp9_rc_clamp_pframe_target_size(const VP9_COMP *const cpi, int target) { const RATE_CONTROL *rc = &cpi->rc; const VP9EncoderConfig *oxcf = &cpi->oxcf; - - if (cpi->oxcf.pass != 2) { - const int min_frame_target = - VPXMAX(rc->min_frame_bandwidth, rc->avg_frame_bandwidth >> 5); - if (target < min_frame_target) target = min_frame_target; - if (cpi->refresh_golden_frame && rc->is_src_frame_alt_ref) { - // If there is an active ARF at this location use the minimum - // bits on this frame even if it is a constructed arf. - // The active maximum quantizer insures that an appropriate - // number of bits will be spent if needed for constructed ARFs. - target = min_frame_target; - } + const int min_frame_target = + VPXMAX(rc->min_frame_bandwidth, rc->avg_frame_bandwidth >> 5); + if (target < min_frame_target) target = min_frame_target; + if (cpi->refresh_golden_frame && rc->is_src_frame_alt_ref) { + // If there is an active ARF at this location use the minimum + // bits on this frame even if it is a constructed arf. + // The active maximum quantizer insures that an appropriate + // number of bits will be spent if needed for constructed ARFs. + target = min_frame_target; } - // Clip the frame target to the maximum allowed value. if (target > rc->max_frame_bandwidth) target = rc->max_frame_bandwidth; - if (oxcf->rc_max_inter_bitrate_pct) { const int max_rate = rc->avg_frame_bandwidth * oxcf->rc_max_inter_bitrate_pct / 100; @@ -2006,6 +2003,8 @@ void vp9_rc_get_svc_params(VP9_COMP *cpi) { int target = rc->avg_frame_bandwidth; int layer = LAYER_IDS_TO_IDX(svc->spatial_layer_id, svc->temporal_layer_id, svc->number_temporal_layers); + if (svc->first_spatial_layer_to_encode) + svc->layer_context[svc->temporal_layer_id].is_key_frame = 0; // Periodic key frames is based on the super-frame counter // (svc.current_superframe), also only base spatial layer is key frame. // Key frame is set for any of the following: very first frame, frame flags diff --git a/vp9/encoder/vp9_ratectrl.h b/vp9/encoder/vp9_ratectrl.h index cf37117f9..87b1ec33e 100644 --- a/vp9/encoder/vp9_ratectrl.h +++ b/vp9/encoder/vp9_ratectrl.h @@ -32,8 +32,6 @@ extern "C" { #define FIXED_GF_INTERVAL 8 // Used in some testing modes only #define ONEHALFONLY_RESIZE 0 -#define FRAME_OVERHEAD_BITS 200 - // Threshold used to define a KF group as static (e.g. a slide show). // Essentially this means that no frame in the group has more than 1% of MBs // that are not marked as coded with 0,0 motion in the first pass. diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c index cf4b5d033..025c5f8e4 100644 --- a/vp9/encoder/vp9_rdopt.c +++ b/vp9/encoder/vp9_rdopt.c @@ -3103,7 +3103,7 @@ void vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, TileDataEnc *tile_data, const int intra_cost_penalty = vp9_get_intra_cost_penalty(cpi, bsize, cm->base_qindex, cm->y_dc_delta_q); int best_skip2 = 0; - uint8_t ref_frame_skip_mask[2] = { 0 }; + uint8_t ref_frame_skip_mask[2] = { 0, 1 }; uint16_t mode_skip_mask[MAX_REF_FRAMES] = { 0 }; int mode_skip_start = sf->mode_skip_start + 1; const int *const rd_threshes = rd_opt->threshes[segment_id][bsize]; @@ -3144,7 +3144,8 @@ void vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, TileDataEnc *tile_data, for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) { x->pred_mv_sad[ref_frame] = INT_MAX; - if (cpi->ref_frame_flags & flag_list[ref_frame]) { + if ((cpi->ref_frame_flags & flag_list[ref_frame]) && + !(is_rect_partition && (ctx->skip_ref_frame_mask & (1 << ref_frame)))) { assert(get_ref_frame_buffer(cpi, ref_frame) != NULL); setup_buffer_inter(cpi, x, ref_frame, bsize, mi_row, mi_col, frame_mv[NEARESTMV], frame_mv[NEARMV], yv12_mb); @@ -3279,13 +3280,9 @@ void vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, TileDataEnc *tile_data, if (midx == mode_skip_start && best_mode_index >= 0) { switch (best_mbmode.ref_frame[0]) { case INTRA_FRAME: break; - case LAST_FRAME: - ref_frame_skip_mask[0] |= LAST_FRAME_MODE_MASK; - ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK; - break; + case LAST_FRAME: ref_frame_skip_mask[0] |= LAST_FRAME_MODE_MASK; break; case GOLDEN_FRAME: ref_frame_skip_mask[0] |= GOLDEN_FRAME_MODE_MASK; - ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK; break; case ALTREF_FRAME: ref_frame_skip_mask[0] |= ALT_REF_MODE_MASK; break; case NONE: diff --git a/vp9/encoder/vp9_svc_layercontext.c b/vp9/encoder/vp9_svc_layercontext.c index 90bc4b26d..efe647611 100644 --- a/vp9/encoder/vp9_svc_layercontext.c +++ b/vp9/encoder/vp9_svc_layercontext.c @@ -678,6 +678,7 @@ static void set_flags_and_fb_idx_bypass_via_set_ref_frame_config( VP9_COMP *const cpi) { SVC *const svc = &cpi->svc; int sl = svc->spatial_layer_id = svc->spatial_layer_to_encode; + cpi->svc.temporal_layer_id = cpi->svc.temporal_layer_id_per_spatial[sl]; cpi->ext_refresh_frame_flags_pending = 1; cpi->lst_fb_idx = svc->lst_fb_idx[sl]; cpi->gld_fb_idx = svc->gld_fb_idx[sl]; @@ -1004,11 +1005,13 @@ void vp9_svc_constrain_inter_layer_pred(VP9_COMP *const cpi) { } } } - // Check for disabling inter-layer prediction if the reference for inter-layer - // prediction (the reference that is scaled) is not the previous spatial layer - // from the same superframe, then we disable inter-layer prediction. - // Only need to check when inter_layer prediction is not set to OFF mode. - if (svc->disable_inter_layer_pred != INTER_LAYER_PRED_OFF) { + // For fixed/non-flexible SVC: check for disabling inter-layer prediction. + // If the reference for inter-layer prediction (the reference that is scaled) + // is not the previous spatial layer from the same superframe, then we disable + // inter-layer prediction. Only need to check when inter_layer prediction is + // not set to OFF mode. + if (svc->temporal_layering_mode != VP9E_TEMPORAL_LAYERING_MODE_BYPASS && + svc->disable_inter_layer_pred != INTER_LAYER_PRED_OFF) { // We only use LAST and GOLDEN for prediction in real-time mode, so we // check both here. MV_REFERENCE_FRAME ref_frame; @@ -1059,7 +1062,8 @@ void vp9_svc_assert_constraints_pattern(VP9_COMP *const cpi) { // Non-base temporal only predicts from lower temporal layer. assert(svc->fb_idx_temporal_layer_id[cpi->lst_fb_idx] < svc->temporal_layer_id); - if (svc->spatial_layer_id > 0) { + if (svc->spatial_layer_id > 0 && cpi->ref_frame_flags & VP9_GOLD_FLAG && + svc->first_spatial_layer_to_encode >= svc->spatial_layer_id - 1) { // Non-base spatial only predicts from lower spatial layer with same // temporal_id. assert(svc->fb_idx_spatial_layer_id[cpi->gld_fb_idx] == diff --git a/vp9/encoder/vp9_svc_layercontext.h b/vp9/encoder/vp9_svc_layercontext.h index b911575fc..60fb7da75 100644 --- a/vp9/encoder/vp9_svc_layercontext.h +++ b/vp9/encoder/vp9_svc_layercontext.h @@ -173,6 +173,10 @@ typedef struct SVC { uint8_t fb_idx_base[REF_FRAMES]; int use_set_ref_frame_config; + + int temporal_layer_id_per_spatial[VPX_SS_MAX_LAYERS]; + + int first_spatial_layer_to_encode; } SVC; struct VP9_COMP; diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c index 45a846459..074415b7f 100644 --- a/vp9/vp9_cx_iface.c +++ b/vp9/vp9_cx_iface.c @@ -1317,9 +1317,9 @@ static vpx_codec_err_t ctrl_get_reference(vpx_codec_alg_priv_t *ctx, vp9_ref_frame_t *const frame = va_arg(args, vp9_ref_frame_t *); if (frame != NULL) { - YV12_BUFFER_CONFIG *fb = get_ref_frame(&ctx->cpi->common, frame->idx); + const int fb_idx = ctx->cpi->common.cur_show_frame_fb_idx; + YV12_BUFFER_CONFIG *fb = get_buf_frame(&ctx->cpi->common, fb_idx); if (fb == NULL) return VPX_CODEC_ERROR; - yuvconfig2image(&frame->img, fb, NULL); return VPX_CODEC_OK; } @@ -1446,9 +1446,17 @@ static vpx_codec_err_t ctrl_set_svc_layer_id(vpx_codec_alg_priv_t *ctx, vpx_svc_layer_id_t *const data = va_arg(args, vpx_svc_layer_id_t *); VP9_COMP *const cpi = (VP9_COMP *)ctx->cpi; SVC *const svc = &cpi->svc; + int sl; svc->spatial_layer_to_encode = data->spatial_layer_id; + svc->first_spatial_layer_to_encode = data->spatial_layer_id; + // TODO(jianj): Deprecated to be removed. svc->temporal_layer_id = data->temporal_layer_id; + // Allow for setting temporal layer per spatial layer for superframe. + for (sl = 0; sl < cpi->svc.number_spatial_layers; ++sl) { + svc->temporal_layer_id_per_spatial[sl] = + data->temporal_layer_id_per_spatial[sl]; + } // Checks on valid layer_id input. if (svc->temporal_layer_id < 0 || svc->temporal_layer_id >= (int)ctx->cfg.ts_number_layers) { diff --git a/vp9/vp9_dx_iface.c b/vp9/vp9_dx_iface.c index 7f45ab28f..fdff87768 100644 --- a/vp9/vp9_dx_iface.c +++ b/vp9/vp9_dx_iface.c @@ -471,8 +471,8 @@ static vpx_codec_err_t ctrl_get_reference(vpx_codec_alg_priv_t *ctx, vp9_ref_frame_t *data = va_arg(args, vp9_ref_frame_t *); if (data) { - YV12_BUFFER_CONFIG *fb; - fb = get_ref_frame(&ctx->pbi->common, data->idx); + const int fb_idx = ctx->pbi->common.cur_show_frame_fb_idx; + YV12_BUFFER_CONFIG *fb = get_buf_frame(&ctx->pbi->common, fb_idx); if (fb == NULL) return VPX_CODEC_ERROR; yuvconfig2image(&data->img, fb, NULL); return VPX_CODEC_OK; |