summaryrefslogtreecommitdiff
path: root/vp9
diff options
context:
space:
mode:
Diffstat (limited to 'vp9')
-rw-r--r--vp9/common/vp9_onyxc_int.h10
-rw-r--r--vp9/common/vp9_thread_common.c185
-rw-r--r--vp9/common/vp9_thread_common.h22
-rw-r--r--vp9/decoder/vp9_decodeframe.c43
-rw-r--r--vp9/decoder/vp9_decoder.c2
-rw-r--r--vp9/decoder/vp9_decoder.h2
-rw-r--r--vp9/encoder/vp9_bitstream.c15
-rw-r--r--vp9/encoder/vp9_denoiser.c135
-rw-r--r--vp9/encoder/vp9_denoiser.h14
-rw-r--r--vp9/encoder/vp9_encoder.c84
-rw-r--r--vp9/encoder/vp9_encoder.h21
-rw-r--r--vp9/encoder/vp9_ethread.c38
-rw-r--r--vp9/encoder/vp9_ethread.h4
-rw-r--r--vp9/encoder/vp9_firstpass.c57
-rw-r--r--vp9/encoder/vp9_firstpass.h5
-rw-r--r--vp9/encoder/vp9_ratectrl.c27
-rw-r--r--vp9/encoder/vp9_ratectrl.h2
-rw-r--r--vp9/encoder/vp9_rdopt.c11
-rw-r--r--vp9/encoder/vp9_svc_layercontext.c16
-rw-r--r--vp9/encoder/vp9_svc_layercontext.h4
-rw-r--r--vp9/vp9_cx_iface.c12
-rw-r--r--vp9/vp9_dx_iface.c4
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;