From eac344ef100e774fa14833df4dbce4700e110d8b Mon Sep 17 00:00:00 2001 From: Adrian Grange Date: Sun, 9 Jun 2013 10:10:33 -0700 Subject: [PATCH] Implement intra-coded frames Implements ability to signal and decode frames that are encoded using only intra coding modes. Only the decode side has been implemented here. Change-Id: I53ac6a8d90422cd08ba389e5236e15b45f9e93de --- vp9/common/vp9_entropy.c | 2 +- vp9/common/vp9_entropymode.c | 12 ++++++++++-- vp9/common/vp9_onyxc_int.h | 1 + vp9/decoder/vp9_decodemv.c | 4 ++-- vp9/decoder/vp9_decodframe.c | 17 +++++++++-------- vp9/encoder/vp9_bitstream.c | 7 +++++-- vp9/encoder/vp9_ratectrl.c | 2 +- 7 files changed, 29 insertions(+), 16 deletions(-) diff --git a/vp9/common/vp9_entropy.c b/vp9/common/vp9_entropy.c index 315619762..7b5273b0f 100644 --- a/vp9/common/vp9_entropy.c +++ b/vp9/common/vp9_entropy.c @@ -723,7 +723,7 @@ void vp9_adapt_coef_probs(VP9_COMMON *cm) { int count_sat; int update_factor; /* denominator 256 */ - if (cm->frame_type == KEY_FRAME) { + if ((cm->frame_type == KEY_FRAME) || cm->intra_only) { update_factor = COEF_MAX_UPDATE_FACTOR_KEY; count_sat = COEF_COUNT_SAT_KEY; } else if (cm->last_frame_type == KEY_FRAME) { diff --git a/vp9/common/vp9_entropymode.c b/vp9/common/vp9_entropymode.c index 911b5556e..8142f8669 100644 --- a/vp9/common/vp9_entropymode.c +++ b/vp9/common/vp9_entropymode.c @@ -536,8 +536,16 @@ void vp9_setup_past_independence(VP9_COMMON *cm, MACROBLOCKD *xd) { vp9_init_mode_contexts(cm); - for (i = 0; i < NUM_FRAME_CONTEXTS; i++) - vpx_memcpy(&cm->frame_contexts[i], &cm->fc, sizeof(cm->fc)); + if ((cm->frame_type == KEY_FRAME) || + cm->error_resilient_mode || (cm->reset_frame_context == 3)) { + // Reset all frame contexts. + for (i = 0; i < NUM_FRAME_CONTEXTS; ++i) + vpx_memcpy(&cm->frame_contexts[i], &cm->fc, sizeof(cm->fc)); + } else if (cm->reset_frame_context == 2) { + // Reset only the frame context specified in the frame header. + vpx_memcpy(&cm->frame_contexts[cm->frame_context_idx], &cm->fc, + sizeof(cm->fc)); + } vpx_memset(cm->prev_mip, 0, cm->mode_info_stride * (cm->mi_rows + 1) * sizeof(MODE_INFO)); diff --git a/vp9/common/vp9_onyxc_int.h b/vp9/common/vp9_onyxc_int.h index 583e50e1c..12161ca27 100644 --- a/vp9/common/vp9_onyxc_int.h +++ b/vp9/common/vp9_onyxc_int.h @@ -364,6 +364,7 @@ static void set_prev_mi(VP9_COMMON *cm) { const int use_prev_in_find_mv_refs = cm->width == cm->last_width && cm->height == cm->last_height && !cm->error_resilient_mode && + !cm->intra_only && cm->last_show_frame; // Special case: set prev_mi to NULL when the previous mode info // context cannot be used. diff --git a/vp9/decoder/vp9_decodemv.c b/vp9/decoder/vp9_decodemv.c index 99902d92a..477296b31 100644 --- a/vp9/decoder/vp9_decodemv.c +++ b/vp9/decoder/vp9_decodemv.c @@ -337,7 +337,7 @@ static INLINE COMPPREDMODE_TYPE read_comp_pred_mode(vp9_reader *r) { static void mb_mode_mv_init(VP9D_COMP *pbi, vp9_reader *r) { VP9_COMMON *const cm = &pbi->common; - if (cm->frame_type != KEY_FRAME) { + if ((cm->frame_type != KEY_FRAME) && (!cm->intra_only)) { nmv_context *const nmvc = &pbi->common.fc.nmvc; MACROBLOCKD *const xd = &pbi->mb; int i, j; @@ -816,7 +816,7 @@ void vp9_decode_mb_mode_mv(VP9D_COMP* const pbi, MODE_INFO *mi = xd->mode_info_context; MB_MODE_INFO *const mbmi = &mi->mbmi; - if (cm->frame_type == KEY_FRAME) { + if ((cm->frame_type == KEY_FRAME) || cm->intra_only) { kfread_modes(pbi, mi, mi_row, mi_col, r); } else { read_mb_modes_mv(pbi, mi, &mi->mbmi, mi_row, mi_col, r); diff --git a/vp9/decoder/vp9_decodframe.c b/vp9/decoder/vp9_decodframe.c index 1bc7696fb..21ac3987f 100644 --- a/vp9/decoder/vp9_decodframe.c +++ b/vp9/decoder/vp9_decodframe.c @@ -308,7 +308,7 @@ static void decode_atom(VP9D_COMP *pbi, MACROBLOCKD *xd, assert(mbmi->ref_frame[0] != INTRA_FRAME); - if (pbi->common.frame_type != KEY_FRAME) + if ((pbi->common.frame_type != KEY_FRAME) && (!pbi->common.intra_only)) vp9_setup_interp_filters(xd, mbmi->interp_filter, &pbi->common); // prediction @@ -1062,8 +1062,6 @@ static size_t read_uncompressed_header(VP9D_COMP *pbi, } } - vp9_setup_past_independence(cm, xd); - pbi->refresh_frame_flags = (1 << NUM_REF_FRAMES) - 1; for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i) @@ -1073,11 +1071,12 @@ static size_t read_uncompressed_header(VP9D_COMP *pbi, } else { cm->intra_only = cm->show_frame ? 0 : vp9_rb_read_bit(rb); - if (cm->error_resilient_mode) - vp9_setup_past_independence(cm, xd); + cm->reset_frame_context = cm->error_resilient_mode ? + 0 : vp9_rb_read_literal(rb, 2); if (cm->intra_only) { check_sync_code(cm, rb); + pbi->refresh_frame_flags = vp9_rb_read_literal(rb, NUM_REF_FRAMES); setup_frame_size(pbi, rb); } else { @@ -1102,17 +1101,19 @@ static size_t read_uncompressed_header(VP9D_COMP *pbi, } if (!cm->error_resilient_mode) { - cm->reset_frame_context = vp9_rb_read_literal(rb, 2); cm->refresh_frame_context = vp9_rb_read_bit(rb); cm->frame_parallel_decoding_mode = vp9_rb_read_bit(rb); } else { - cm->reset_frame_context = 0; cm->refresh_frame_context = 0; cm->frame_parallel_decoding_mode = 1; } cm->frame_context_idx = vp9_rb_read_literal(rb, NUM_FRAME_CONTEXTS_LG2); + if ((cm->frame_type == KEY_FRAME) || + cm->error_resilient_mode || cm->intra_only) + vp9_setup_past_independence(cm, xd); + setup_loopfilter(pbi, rb); setup_quantization(pbi, rb); setup_segmentation(pbi, rb); @@ -1215,7 +1216,7 @@ int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) { if (!pc->error_resilient_mode && !pc->frame_parallel_decoding_mode) { vp9_adapt_coef_probs(pc); - if (!keyframe) { + if ((!keyframe) && (!pc->intra_only)) { vp9_adapt_mode_probs(pc); vp9_adapt_mode_context(pc); vp9_adapt_nmv_probs(pc, xd->allow_high_precision_mv); diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c index 5f4aa8f75..12a11f1c1 100644 --- a/vp9/encoder/vp9_bitstream.c +++ b/vp9/encoder/vp9_bitstream.c @@ -821,7 +821,7 @@ static void write_modes_b(VP9_COMP *cpi, MODE_INFO *m, vp9_writer *bc, set_mi_row_col(&cpi->common, xd, mi_row, 1 << mi_height_log2(m->mbmi.sb_type), mi_col, 1 << mi_width_log2(m->mbmi.sb_type)); - if (cm->frame_type == KEY_FRAME) { + if ((cm->frame_type == KEY_FRAME) || cm->intra_only) { write_mb_modes_kf(cpi, m, bc, mi_row, mi_col); #ifdef ENTROPY_STATS active_section = 8; @@ -1527,8 +1527,12 @@ static void write_uncompressed_header(VP9_COMP *cpi, if (!cm->show_frame) vp9_wb_write_bit(wb, cm->intra_only); + if (!cm->error_resilient_mode) + vp9_wb_write_literal(wb, cm->reset_frame_context, 2); + if (cm->intra_only) { write_sync_code(wb); + vp9_wb_write_literal(wb, get_refresh_mask(cpi), NUM_REF_FRAMES); write_frame_size(cpi, wb); } else { @@ -1549,7 +1553,6 @@ static void write_uncompressed_header(VP9_COMP *cpi, } if (!cm->error_resilient_mode) { - vp9_wb_write_literal(wb, cm->reset_frame_context, 2); vp9_wb_write_bit(wb, cm->refresh_frame_context); vp9_wb_write_bit(wb, cm->frame_parallel_decoding_mode); } diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c index ae6c20ed9..430d3a8d6 100644 --- a/vp9/encoder/vp9_ratectrl.c +++ b/vp9/encoder/vp9_ratectrl.c @@ -206,7 +206,7 @@ void vp9_setup_key_frame(VP9_COMP *cpi) { void vp9_setup_inter_frame(VP9_COMP *cpi) { VP9_COMMON *cm = &cpi->common; MACROBLOCKD *xd = &cpi->mb.e_mbd; - if (cm->error_resilient_mode) + if (cm->error_resilient_mode || cm->intra_only) vp9_setup_past_independence(cm, xd); assert(cm->frame_context_idx < NUM_FRAME_CONTEXTS);