diff options
Diffstat (limited to 'third_party/aom/av1/encoder/bitstream.c')
-rw-r--r-- | third_party/aom/av1/encoder/bitstream.c | 2446 |
1 files changed, 1710 insertions, 736 deletions
diff --git a/third_party/aom/av1/encoder/bitstream.c b/third_party/aom/av1/encoder/bitstream.c index 2e0abc186..08f605f10 100644 --- a/third_party/aom/av1/encoder/bitstream.c +++ b/third_party/aom/av1/encoder/bitstream.c @@ -14,9 +14,9 @@ #include <stdio.h> #include "aom/aom_encoder.h" -#include "aom_dsp/bitwriter_buffer.h" #include "aom_dsp/aom_dsp_common.h" #include "aom_dsp/binary_codes_writer.h" +#include "aom_dsp/bitwriter_buffer.h" #include "aom_mem/aom_mem.h" #include "aom_ports/mem_ops.h" #include "aom_ports/system_state.h" @@ -40,9 +40,6 @@ #include "av1/common/seg_common.h" #include "av1/common/tile_common.h" -#if CONFIG_ANS -#include "aom_dsp/buf_ans.h" -#endif // CONFIG_ANS #if CONFIG_LV_MAP #include "av1/encoder/encodetxb.h" #endif // CONFIG_LV_MAP @@ -50,9 +47,9 @@ #include "av1/encoder/cost.h" #include "av1/encoder/encodemv.h" #include "av1/encoder/mcomp.h" -#if CONFIG_PALETTE && CONFIG_PALETTE_DELTA_ENCODING +#if CONFIG_PALETTE_DELTA_ENCODING #include "av1/encoder/palette.h" -#endif // CONFIG_PALETTE && CONFIG_PALETTE_DELTA_ENCODING +#endif // CONFIG_PALETTE_DELTA_ENCODING #include "av1/encoder/segmentation.h" #include "av1/encoder/subexp.h" #include "av1/encoder/tokenize.h" @@ -62,12 +59,13 @@ #define ENC_MISMATCH_DEBUG 0 -#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF +#if CONFIG_COMPOUND_SINGLEREF static struct av1_token inter_singleref_comp_mode_encodings[INTER_SINGLEREF_COMP_MODES]; -#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF +#endif // CONFIG_COMPOUND_SINGLEREF -#if CONFIG_EXT_INTRA || CONFIG_FILTER_INTRA || CONFIG_PALETTE +// TODO(anybody) : remove this flag when PVQ supports pallete coding tool +#if !CONFIG_PVQ || CONFIG_EXT_INTRA static INLINE void write_uniform(aom_writer *w, int n, int v) { const int l = get_unsigned_bits(n); const int m = (1 << l) - n; @@ -79,63 +77,47 @@ static INLINE void write_uniform(aom_writer *w, int n, int v) { aom_write_literal(w, (v - m) & 1, 1); } } -#endif // CONFIG_EXT_INTRA || CONFIG_FILTER_INTRA || CONFIG_PALETTE +#endif // !CONFIG_PVQ || CONFIG_EXT_INTRA -#if CONFIG_EXT_TX -static struct av1_token ext_tx_inter_encodings[EXT_TX_SETS_INTER][TX_TYPES]; -static struct av1_token ext_tx_intra_encodings[EXT_TX_SETS_INTRA][TX_TYPES]; -#else -static struct av1_token ext_tx_encodings[TX_TYPES]; -#endif // CONFIG_EXT_TX #if CONFIG_EXT_INTRA #if CONFIG_INTRA_INTERP static struct av1_token intra_filter_encodings[INTRA_FILTERS]; #endif // CONFIG_INTRA_INTERP #endif // CONFIG_EXT_INTRA -#if CONFIG_EXT_INTER #if CONFIG_INTERINTRA static struct av1_token interintra_mode_encodings[INTERINTRA_MODES]; #endif #if CONFIG_COMPOUND_SEGMENT || CONFIG_WEDGE static struct av1_token compound_type_encodings[COMPOUND_TYPES]; #endif // CONFIG_COMPOUND_SEGMENT || CONFIG_WEDGE -#endif // CONFIG_EXT_INTER -#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION -#if CONFIG_NCOBMC_ADAPT_WEIGHT -static struct av1_token ncobmc_mode_encodings[MAX_NCOBMC_MODES]; -#endif -#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION #if CONFIG_LOOP_RESTORATION static struct av1_token switchable_restore_encodings[RESTORE_SWITCHABLE_TYPES]; +static void loop_restoration_write_sb_coeffs(const AV1_COMMON *const cm, + MACROBLOCKD *xd, + aom_writer *const w, int plane, + int rtile_idx); #endif // CONFIG_LOOP_RESTORATION -static void write_uncompressed_header(AV1_COMP *cpi, - struct aom_write_bit_buffer *wb); +#if CONFIG_OBU +static void write_uncompressed_header_obu(AV1_COMP *cpi, + struct aom_write_bit_buffer *wb); +#else +static void write_uncompressed_header_frame(AV1_COMP *cpi, + struct aom_write_bit_buffer *wb); +#endif + static uint32_t write_compressed_header(AV1_COMP *cpi, uint8_t *data); + +#if !CONFIG_OBU || CONFIG_EXT_TILE static int remux_tiles(const AV1_COMMON *const cm, uint8_t *dst, const uint32_t data_size, const uint32_t max_tile_size, const uint32_t max_tile_col_size, int *const tile_size_bytes, int *const tile_col_size_bytes); - +#endif void av1_encode_token_init(void) { -#if CONFIG_EXT_TX - int s; -#endif // CONFIG_EXT_TX -#if CONFIG_EXT_TX - for (s = 1; s < EXT_TX_SETS_INTER; ++s) { - av1_tokens_from_tree(ext_tx_inter_encodings[s], av1_ext_tx_inter_tree[s]); - } - for (s = 1; s < EXT_TX_SETS_INTRA; ++s) { - av1_tokens_from_tree(ext_tx_intra_encodings[s], av1_ext_tx_intra_tree[s]); - } -#else - av1_tokens_from_tree(ext_tx_encodings, av1_ext_tx_tree); -#endif // CONFIG_EXT_TX - #if CONFIG_EXT_INTRA && CONFIG_INTRA_INTERP av1_tokens_from_tree(intra_filter_encodings, av1_intra_filter_tree); #endif // CONFIG_EXT_INTRA && CONFIG_INTRA_INTERP -#if CONFIG_EXT_INTER #if CONFIG_INTERINTRA av1_tokens_from_tree(interintra_mode_encodings, av1_interintra_mode_tree); #endif // CONFIG_INTERINTRA @@ -146,35 +128,10 @@ void av1_encode_token_init(void) { #if CONFIG_COMPOUND_SEGMENT || CONFIG_WEDGE av1_tokens_from_tree(compound_type_encodings, av1_compound_type_tree); #endif // CONFIG_COMPOUND_SEGMENT || CONFIG_WEDGE -#endif // CONFIG_EXT_INTER -#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION -#if CONFIG_NCOBMC_ADAPT_WEIGHT - av1_tokens_from_tree(ncobmc_mode_encodings, av1_ncobmc_mode_tree); -#endif -#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION #if CONFIG_LOOP_RESTORATION av1_tokens_from_tree(switchable_restore_encodings, av1_switchable_restore_tree); #endif // CONFIG_LOOP_RESTORATION - - /* This hack is necessary when CONFIG_DUAL_FILTER is enabled because the five - SWITCHABLE_FILTERS are not consecutive, e.g., 0, 1, 2, 3, 4, when doing - an in-order traversal of the av1_switchable_interp_tree structure. */ - av1_indices_from_tree(av1_switchable_interp_ind, av1_switchable_interp_inv, - av1_switchable_interp_tree); -/* This hack is necessary because the four TX_TYPES are not consecutive, - e.g., 0, 1, 2, 3, when doing an in-order traversal of the av1_ext_tx_tree - structure. */ -#if CONFIG_EXT_TX - for (s = 1; s < EXT_TX_SETS_INTRA; ++s) - av1_indices_from_tree(av1_ext_tx_intra_ind[s], av1_ext_tx_intra_inv[s], - av1_ext_tx_intra_tree[s]); - for (s = 1; s < EXT_TX_SETS_INTER; ++s) - av1_indices_from_tree(av1_ext_tx_inter_ind[s], av1_ext_tx_inter_inv[s], - av1_ext_tx_inter_tree[s]); -#else - av1_indices_from_tree(av1_ext_tx_ind, av1_ext_tx_inv, av1_ext_tx_tree); -#endif } static void write_intra_mode_kf(const AV1_COMMON *cm, FRAME_CONTEXT *frame_ctx, @@ -184,7 +141,7 @@ static void write_intra_mode_kf(const AV1_COMMON *cm, FRAME_CONTEXT *frame_ctx, #if CONFIG_INTRABC assert(!is_intrabc_block(&mi->mbmi)); #endif // CONFIG_INTRABC - aom_write_symbol(w, av1_intra_mode_ind[mode], + aom_write_symbol(w, mode, get_y_mode_cdf(frame_ctx, mi, above_mi, left_mi, block), INTRA_MODES); (void)cm; @@ -234,16 +191,12 @@ static void write_drl_idx(FRAME_CONTEXT *ec_ctx, const MB_MODE_INFO *mbmi, assert(mbmi->ref_mv_idx < 3); -#if CONFIG_EXT_INTER #if CONFIG_COMPOUND_SINGLEREF if (mbmi->mode == NEWMV || mbmi->mode == NEW_NEWMV || mbmi->mode == SR_NEW_NEWMV) { #else // !CONFIG_COMPOUND_SINGLEREF if (mbmi->mode == NEWMV || mbmi->mode == NEW_NEWMV) { #endif // CONFIG_COMPOUND_SINGLEREF -#else // !CONFIG_EXT_INTER - if (mbmi->mode == NEWMV) { -#endif // CONFIG_EXT_INTER int idx; for (idx = 0; idx < 2; ++idx) { if (mbmi_ext->ref_mv_count[ref_frame_type] > idx + 1) { @@ -282,7 +235,6 @@ static void write_drl_idx(FRAME_CONTEXT *ec_ctx, const MB_MODE_INFO *mbmi, } } -#if CONFIG_EXT_INTER static void write_inter_compound_mode(AV1_COMMON *cm, MACROBLOCKD *xd, aom_writer *w, PREDICTION_MODE mode, const int16_t mode_ctx) { @@ -305,30 +257,12 @@ static void write_inter_singleref_comp_mode(MACROBLOCKD *xd, aom_writer *w, inter_singleref_comp_cdf, INTER_SINGLEREF_COMP_MODES); } #endif // CONFIG_COMPOUND_SINGLEREF -#endif // CONFIG_EXT_INTER static void encode_unsigned_max(struct aom_write_bit_buffer *wb, int data, int max) { aom_wb_write_literal(wb, data, get_unsigned_bits(max)); } -#if CONFIG_NCOBMC_ADAPT_WEIGHT -static void prob_diff_update(const aom_tree_index *tree, - aom_prob probs[/*n - 1*/], - const unsigned int counts[/* n */], int n, - int probwt, aom_writer *w) { - int i; - unsigned int branch_ct[32][2]; - - // Assuming max number of probabilities <= 32 - assert(n <= 32); - - av1_tree_probs_from_distribution(tree, branch_ct, counts); - for (i = 0; i < n - 1; ++i) - av1_cond_prob_diff_update(w, &probs[i], branch_ct[i], probwt); -} -#endif - #if CONFIG_VAR_TX static void write_tx_size_vartx(const AV1_COMMON *cm, MACROBLOCKD *xd, const MB_MODE_INFO *mbmi, TX_SIZE tx_size, @@ -381,7 +315,7 @@ static void write_tx_size_vartx(const AV1_COMMON *cm, MACROBLOCKD *xd, aom_write(w, 1, cm->fc->txfm_partition_prob[ctx]); #endif - if (tx_size == TX_8X8) { + if (sub_txs == TX_4X4) { txfm_partition_update(xd->above_txfm_context + blk_col, xd->left_txfm_context + blk_row, sub_txs, tx_size); return; @@ -406,7 +340,7 @@ static void update_txfm_partition_probs(AV1_COMMON *cm, aom_writer *w, counts->txfm_partition[k], probwt); } #endif // CONFIG_NEW_MULTISYMBOL -#endif +#endif // CONFIG_VAR_TX static void write_selected_tx_size(const AV1_COMMON *cm, const MACROBLOCKD *xd, aom_writer *w) { @@ -414,17 +348,12 @@ static void write_selected_tx_size(const AV1_COMMON *cm, const MACROBLOCKD *xd, const BLOCK_SIZE bsize = mbmi->sb_type; FRAME_CONTEXT *ec_ctx = xd->tile_ctx; (void)cm; -// For sub8x8 blocks the tx_size symbol does not need to be sent -#if CONFIG_CB4X4 && (CONFIG_VAR_TX || CONFIG_EXT_TX) && CONFIG_RECT_TX - if (bsize > BLOCK_4X4) { -#else - if (bsize >= BLOCK_8X8) { -#endif + if (block_signals_txsize(bsize)) { const TX_SIZE tx_size = mbmi->tx_size; const int is_inter = is_inter_block(mbmi); const int tx_size_ctx = get_tx_size_context(xd); - const int tx_size_cat = is_inter ? inter_tx_size_cat_lookup[bsize] - : intra_tx_size_cat_lookup[bsize]; + const int32_t tx_size_cat = is_inter ? inter_tx_size_cat_lookup[bsize] + : intra_tx_size_cat_lookup[bsize]; const TX_SIZE coded_tx_size = txsize_sqr_up_map[tx_size]; const int depth = tx_size_to_depth(coded_tx_size); #if CONFIG_EXT_TX && CONFIG_RECT_TX @@ -435,9 +364,14 @@ static void write_selected_tx_size(const AV1_COMMON *cm, const MACROBLOCKD *xd, tx_size_cat + 2); #if CONFIG_RECT_TX_EXT && (CONFIG_EXT_TX || CONFIG_VAR_TX) if (is_quarter_tx_allowed(xd, mbmi, is_inter) && tx_size != coded_tx_size) +#if CONFIG_NEW_MULTISYMBOL + aom_write_symbol(w, tx_size == quarter_txsize_lookup[bsize], + cm->fc->quarter_tx_size_cdf, 2); +#else aom_write(w, tx_size == quarter_txsize_lookup[bsize], cm->fc->quarter_tx_size_prob); #endif +#endif } } @@ -496,14 +430,12 @@ static void write_motion_mode(const AV1_COMMON *cm, MACROBLOCKD *xd, const MODE_INFO *mi, aom_writer *w) { const MB_MODE_INFO *mbmi = &mi->mbmi; -#if CONFIG_NCOBMC_ADAPT_WEIGHT - MOTION_MODE last_motion_mode_allowed = - motion_mode_allowed_wrapper(0, -#if CONFIG_GLOBAL_MOTION - 0, cm->global_motion, -#endif // CONFIG_GLOBAL_MOTION - mi); -#else +#if !CONFIG_GLOBAL_MOTION + // The cm parameter is only used with global_motion or with + // motion_var and warped_motion. In other cases, explicitly ignore + // it to avoid a compiler warning. + (void)cm; +#endif MOTION_MODE last_motion_mode_allowed = motion_mode_allowed( #if CONFIG_GLOBAL_MOTION 0, cm->global_motion, @@ -512,9 +444,18 @@ static void write_motion_mode(const AV1_COMMON *cm, MACROBLOCKD *xd, xd, #endif mi); -#endif // CONFIG_NCOBMC_ADAPT_WEIGHT if (last_motion_mode_allowed == SIMPLE_TRANSLATION) return; #if CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION +#if CONFIG_NCOBMC_ADAPT_WEIGHT + if (last_motion_mode_allowed == NCOBMC_ADAPT_WEIGHT) { + aom_write_symbol(w, mbmi->motion_mode, + xd->tile_ctx->ncobmc_cdf[mbmi->sb_type], + OBMC_FAMILY_MODES); + } else if (last_motion_mode_allowed == OBMC_CAUSAL) { + aom_write_symbol(w, mbmi->motion_mode == OBMC_CAUSAL, + xd->tile_ctx->obmc_cdf[mbmi->sb_type], 2); + } else { +#else if (last_motion_mode_allowed == OBMC_CAUSAL) { #if CONFIG_NEW_MULTISYMBOL aom_write_symbol(w, mbmi->motion_mode == OBMC_CAUSAL, @@ -524,6 +465,7 @@ static void write_motion_mode(const AV1_COMMON *cm, MACROBLOCKD *xd, cm->fc->obmc_prob[mbmi->sb_type]); #endif } else { +#endif // CONFIG_NCOBMC_ADAPT_WEIGHT #endif // CONFIG_MOTION_VAR && CONFIG_WARPED_MOTION aom_write_symbol(w, mbmi->motion_mode, xd->tile_ctx->motion_mode_cdf[mbmi->sb_type], @@ -540,30 +482,16 @@ static void write_ncobmc_mode(MACROBLOCKD *xd, const MODE_INFO *mi, ADAPT_OVERLAP_BLOCK ao_block = adapt_overlap_block_lookup[mbmi->sb_type]; if (mbmi->motion_mode != NCOBMC_ADAPT_WEIGHT) return; -#ifndef TRAINING_WEIGHTS aom_write_symbol(w, mbmi->ncobmc_mode[0], xd->tile_ctx->ncobmc_mode_cdf[ao_block], MAX_NCOBMC_MODES); if (mi_size_wide[mbmi->sb_type] != mi_size_high[mbmi->sb_type]) { aom_write_symbol(w, mbmi->ncobmc_mode[1], xd->tile_ctx->ncobmc_mode_cdf[ao_block], MAX_NCOBMC_MODES); } -#else - int block; - for (block = 0; block < 4; ++block) - aom_write_symbol(w, mbmi->ncobmc_mode[0][block], - xd->tile_ctx->ncobmc_mode_cdf[ao_block], MAX_NCOBMC_MODES); - if (mi_size_wide[mbmi->sb_type] != mi_size_high[mbmi->sb_type]) { - for (block = 0; block < 4; ++block) - aom_write_symbol(w, mbmi->ncobmc_mode[1][block], - xd->tile_ctx->ncobmc_mode_cdf[ao_block], - MAX_NCOBMC_MODES); - } -#endif } #endif #endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION -#if CONFIG_DELTA_Q static void write_delta_qindex(const AV1_COMMON *cm, const MACROBLOCKD *xd, int delta_qindex, aom_writer *w) { int sign = delta_qindex < 0; @@ -579,7 +507,7 @@ static void write_delta_qindex(const AV1_COMMON *cm, const MACROBLOCKD *xd, if (!smallval) { rem_bits = OD_ILOG_NZ(abs - 1) - 1; thr = (1 << rem_bits) + 1; - aom_write_literal(w, rem_bits, 3); + aom_write_literal(w, rem_bits - 1, 3); aom_write_literal(w, abs - thr, rem_bits); } if (abs > 0) { @@ -589,6 +517,9 @@ static void write_delta_qindex(const AV1_COMMON *cm, const MACROBLOCKD *xd, #if CONFIG_EXT_DELTA_Q static void write_delta_lflevel(const AV1_COMMON *cm, const MACROBLOCKD *xd, +#if CONFIG_LOOPFILTER_LEVEL + int lf_id, +#endif int delta_lflevel, aom_writer *w) { int sign = delta_lflevel < 0; int abs = sign ? -delta_lflevel : delta_lflevel; @@ -597,13 +528,24 @@ static void write_delta_lflevel(const AV1_COMMON *cm, const MACROBLOCKD *xd, FRAME_CONTEXT *ec_ctx = xd->tile_ctx; (void)cm; +#if CONFIG_LOOPFILTER_LEVEL + if (cm->delta_lf_multi) { + assert(lf_id >= 0 && lf_id < FRAME_LF_COUNT); + aom_write_symbol(w, AOMMIN(abs, DELTA_LF_SMALL), + ec_ctx->delta_lf_multi_cdf[lf_id], DELTA_LF_PROBS + 1); + } else { + aom_write_symbol(w, AOMMIN(abs, DELTA_LF_SMALL), ec_ctx->delta_lf_cdf, + DELTA_LF_PROBS + 1); + } +#else aom_write_symbol(w, AOMMIN(abs, DELTA_LF_SMALL), ec_ctx->delta_lf_cdf, DELTA_LF_PROBS + 1); +#endif // CONFIG_LOOPFILTER_LEVEL if (!smallval) { rem_bits = OD_ILOG_NZ(abs - 1) - 1; thr = (1 << rem_bits) + 1; - aom_write_literal(w, rem_bits, 3); + aom_write_literal(w, rem_bits - 1, 3); aom_write_literal(w, abs - thr, rem_bits); } if (abs > 0) { @@ -611,7 +553,6 @@ static void write_delta_lflevel(const AV1_COMMON *cm, const MACROBLOCKD *xd, } } #endif // CONFIG_EXT_DELTA_Q -#endif // CONFIG_DELTA_Q #if !CONFIG_NEW_MULTISYMBOL static void update_skip_probs(AV1_COMMON *cm, aom_writer *w, @@ -625,20 +566,21 @@ static void update_skip_probs(AV1_COMMON *cm, aom_writer *w, } #endif -#if CONFIG_PALETTE -static void pack_palette_tokens(aom_writer *w, const TOKENEXTRA **tp, int n, - int num) { +// TODO(anybody) : remove this flag when PVQ supports pallete coding tool +#if !CONFIG_PVQ +static void pack_map_tokens(aom_writer *w, const TOKENEXTRA **tp, int n, + int num) { const TOKENEXTRA *p = *tp; write_uniform(w, n, p->token); // The first color index. ++p; --num; for (int i = 0; i < num; ++i) { - aom_write_symbol(w, p->token, p->palette_cdf, n); + aom_write_symbol(w, p->token, p->color_map_cdf, n); ++p; } *tp = p; } -#endif // CONFIG_PALETTE +#endif // !CONFIG_PVQ #if !CONFIG_PVQ #if CONFIG_SUPERTX @@ -667,6 +609,7 @@ static void update_supertx_probs(AV1_COMMON *cm, int probwt, aom_writer *w) { } #endif // CONFIG_SUPERTX +#if !CONFIG_LV_MAP #if CONFIG_NEW_MULTISYMBOL static INLINE void write_coeff_extra(const aom_cdf_prob *const *cdf, int val, int n, aom_writer *w) { @@ -693,12 +636,14 @@ static INLINE void write_coeff_extra(const aom_prob *pb, int value, aom_write_record(w, bb, pb[index], token_stats); } } -#endif +#endif // CONFIG_NEW_MULTISYMBOL -#if !CONFIG_LV_MAP static void pack_mb_tokens(aom_writer *w, const TOKENEXTRA **tp, const TOKENEXTRA *const stop, aom_bit_depth_t bit_depth, const TX_SIZE tx_size, +#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK + TX_TYPE tx_type, int is_inter, +#endif // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK TOKEN_STATS *token_stats) { const TOKENEXTRA *p = *tp; #if CONFIG_VAR_TX @@ -706,6 +651,17 @@ static void pack_mb_tokens(aom_writer *w, const TOKENEXTRA **tp, const int seg_eob = tx_size_2d[tx_size]; #endif +#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK + if (tx_type == MRC_DCT && ((is_inter && SIGNAL_MRC_MASK_INTER) || + (!is_inter && SIGNAL_MRC_MASK_INTRA))) { + int rows = tx_size_high[tx_size]; + int cols = tx_size_wide[tx_size]; + assert(tx_size == TX_32X32); + assert(p < stop); + pack_map_tokens(w, &p, 2, rows * cols); + } +#endif // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK + while (p < stop && p->token != EOSB_TOKEN) { const int token = p->token; const int eob_val = p->eob_val; @@ -949,6 +905,10 @@ static void pack_txb_tokens(aom_writer *w, const TOKENEXTRA **tp, TX_SIZE plane_tx_size; const int max_blocks_high = max_block_high(xd, plane_bsize, plane); const int max_blocks_wide = max_block_wide(xd, plane_bsize, plane); +#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK + TX_TYPE tx_type = av1_get_tx_type(plane ? PLANE_TYPE_UV : PLANE_TYPE_Y, xd, + blk_row, blk_col, block, tx_size); +#endif // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK if (blk_row >= max_blocks_high || blk_col >= max_blocks_wide) return; @@ -960,7 +920,11 @@ static void pack_txb_tokens(aom_writer *w, const TOKENEXTRA **tp, TOKEN_STATS tmp_token_stats; init_token_stats(&tmp_token_stats); #if !CONFIG_PVQ - pack_mb_tokens(w, tp, tok_end, bit_depth, tx_size, &tmp_token_stats); + pack_mb_tokens(w, tp, tok_end, bit_depth, tx_size, +#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK + tx_type, is_inter_block(mbmi), +#endif // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK + &tmp_token_stats); #else pack_pvq_tokens(w, x, xd, plane, bsize, tx_size); #endif @@ -1020,9 +984,13 @@ static void write_segment_id(aom_writer *w, const struct segmentation *seg, #if CONFIG_NEW_MULTISYMBOL #define WRITE_REF_BIT(bname, pname) \ aom_write_symbol(w, bname, av1_get_pred_cdf_##pname(cm, xd), 2) +#define WRITE_REF_BIT2(bname, pname) \ + aom_write_symbol(w, bname, av1_get_pred_cdf_##pname(xd), 2) #else #define WRITE_REF_BIT(bname, pname) \ aom_write(w, bname, av1_get_pred_prob_##pname(cm, xd)) +#define WRITE_REF_BIT2(bname, pname) \ + aom_write(w, bname, av1_get_pred_prob_##pname(cm, xd)) #endif // This function encodes the reference frame @@ -1042,14 +1010,12 @@ static void write_ref_frames(const AV1_COMMON *cm, const MACROBLOCKD *xd, // does the feature use compound prediction or not // (if not specified at the frame/segment level) if (cm->reference_mode == REFERENCE_MODE_SELECT) { -#if !SUB8X8_COMP_REF - if (mbmi->sb_type != BLOCK_4X4) -#endif + if (is_comp_ref_allowed(mbmi->sb_type)) #if CONFIG_NEW_MULTISYMBOL aom_write_symbol(w, is_compound, av1_get_reference_mode_cdf(cm, xd), 2); #else - aom_write(w, is_compound, av1_get_reference_mode_prob(cm, xd)); -#endif + aom_write(w, is_compound, av1_get_reference_mode_prob(cm, xd)); +#endif // CONFIG_NEW_MULTISYMBOL } else { assert((!is_compound) == (cm->reference_mode == SINGLE_REFERENCE)); } @@ -1064,7 +1030,12 @@ static void write_ref_frames(const AV1_COMMON *cm, const MACROBLOCKD *xd, if ((L_OR_L2(cm) || L3_OR_G(cm)) && BWD_OR_ALT(cm)) if (L_AND_L2(cm) || L_AND_L3(cm) || L_AND_G(cm) || BWD_AND_ALT(cm)) #endif // CONFIG_VAR_REFS - aom_write(w, comp_ref_type, av1_get_comp_reference_type_prob(cm, xd)); +#if CONFIG_NEW_MULTISYMBOL + aom_write_symbol(w, comp_ref_type, + av1_get_comp_reference_type_cdf(xd), 2); +#else + aom_write(w, comp_ref_type, av1_get_comp_reference_type_prob(cm, xd)); +#endif #if CONFIG_VAR_REFS else assert(comp_ref_type == BIDIR_COMP_REFERENCE); @@ -1081,7 +1052,7 @@ static void write_ref_frames(const AV1_COMMON *cm, const MACROBLOCKD *xd, #if CONFIG_VAR_REFS if ((L_AND_L2(cm) || L_AND_L3(cm) || L_AND_G(cm)) && BWD_AND_ALT(cm)) #endif // CONFIG_VAR_REFS - aom_write(w, bit, av1_get_pred_prob_uni_comp_ref_p(cm, xd)); + WRITE_REF_BIT2(bit, uni_comp_ref_p); if (!bit) { assert(mbmi->ref_frame[0] == LAST_FRAME); @@ -1090,14 +1061,13 @@ static void write_ref_frames(const AV1_COMMON *cm, const MACROBLOCKD *xd, #endif // CONFIG_VAR_REFS const int bit1 = mbmi->ref_frame[1] == LAST3_FRAME || mbmi->ref_frame[1] == GOLDEN_FRAME; - aom_write(w, bit1, av1_get_pred_prob_uni_comp_ref_p1(cm, xd)); - + WRITE_REF_BIT2(bit1, uni_comp_ref_p1); if (bit1) { #if CONFIG_VAR_REFS if (L_AND_L3(cm) && L_AND_G(cm)) { #endif // CONFIG_VAR_REFS const int bit2 = mbmi->ref_frame[1] == GOLDEN_FRAME; - aom_write(w, bit2, av1_get_pred_prob_uni_comp_ref_p2(cm, xd)); + WRITE_REF_BIT2(bit2, uni_comp_ref_p2); #if CONFIG_VAR_REFS } #endif // CONFIG_VAR_REFS @@ -1147,11 +1117,20 @@ static void write_ref_frames(const AV1_COMMON *cm, const MACROBLOCKD *xd, } #if CONFIG_VAR_REFS - // Test need to explicitly code (BWD) vs (ALT) branch node in tree - if (BWD_AND_ALT(cm)) { + // Test need to explicitly code (BWD,ALT2) vs (ALT) branch node in tree + if (BWD_OR_ALT2(cm) && ALTREF_IS_VALID(cm)) { #endif // CONFIG_VAR_REFS const int bit_bwd = mbmi->ref_frame[1] == ALTREF_FRAME; WRITE_REF_BIT(bit_bwd, comp_bwdref_p); + + if (!bit_bwd) { +#if CONFIG_VAR_REFS + // Test need to explicitly code (BWD,ALT2) vs (ALT) branch node in + // tree + if (BWD_AND_ALT2(cm)) +#endif // CONFIG_VAR_REFS + WRITE_REF_BIT(mbmi->ref_frame[1] == ALTREF2_FRAME, comp_bwdref_p1); + } #if CONFIG_VAR_REFS } #endif // CONFIG_VAR_REFS @@ -1162,22 +1141,31 @@ static void write_ref_frames(const AV1_COMMON *cm, const MACROBLOCKD *xd, #endif // CONFIG_EXT_REFS } else { #if CONFIG_EXT_REFS - const int bit0 = (mbmi->ref_frame[0] == ALTREF_FRAME || - mbmi->ref_frame[0] == BWDREF_FRAME); + const int bit0 = (mbmi->ref_frame[0] <= ALTREF_FRAME && + mbmi->ref_frame[0] >= BWDREF_FRAME); #if CONFIG_VAR_REFS - // Test need to explicitly code (L,L2,L3,G) vs (BWD,ALT) branch node in - // tree - if ((L_OR_L2(cm) || L3_OR_G(cm)) && BWD_OR_ALT(cm)) + // Test need to explicitly code (L,L2,L3,G) vs (BWD,ALT2,ALT) branch node + // in tree + if ((L_OR_L2(cm) || L3_OR_G(cm)) && + (BWD_OR_ALT2(cm) || ALTREF_IS_VALID(cm))) #endif // CONFIG_VAR_REFS WRITE_REF_BIT(bit0, single_ref_p1); if (bit0) { #if CONFIG_VAR_REFS - // Test need to explicitly code (BWD) vs (ALT) branch node in tree - if (BWD_AND_ALT(cm)) { + // Test need to explicitly code (BWD,ALT2) vs (ALT) branch node in tree + if (BWD_OR_ALT2(cm) && ALTREF_IS_VALID(cm)) { #endif // CONFIG_VAR_REFS const int bit1 = mbmi->ref_frame[0] == ALTREF_FRAME; WRITE_REF_BIT(bit1, single_ref_p2); + + if (!bit1) { +#if CONFIG_VAR_REFS + // Test need to explicitly code (BWD) vs (ALT2) branch node in tree + if (BWD_AND_ALT2(cm)) +#endif // CONFIG_VAR_REFS + WRITE_REF_BIT(mbmi->ref_frame[0] == ALTREF2_FRAME, single_ref_p6); + } #if CONFIG_VAR_REFS } #endif // CONFIG_VAR_REFS @@ -1231,11 +1219,7 @@ static void write_filter_intra_mode_info(const AV1_COMMON *const cm, const MB_MODE_INFO *const mbmi, int mi_row, int mi_col, aom_writer *w) { - if (mbmi->mode == DC_PRED -#if CONFIG_PALETTE - && mbmi->palette_mode_info.palette_size[0] == 0 -#endif // CONFIG_PALETTE - ) { + if (mbmi->mode == DC_PRED && mbmi->palette_mode_info.palette_size[0] == 0) { aom_write(w, mbmi->filter_intra_mode_info.use_filter_intra_mode[0], cm->fc->filter_intra_probs[0]); if (mbmi->filter_intra_mode_info.use_filter_intra_mode[0]) { @@ -1256,11 +1240,8 @@ static void write_filter_intra_mode_info(const AV1_COMMON *const cm, (void)mi_col; #endif // CONFIG_CB4X4 - if (mbmi->uv_mode == UV_DC_PRED -#if CONFIG_PALETTE - && mbmi->palette_mode_info.palette_size[1] == 0 -#endif // CONFIG_PALETTE - ) { + if (mbmi->uv_mode == UV_DC_PRED && + mbmi->palette_mode_info.palette_size[1] == 0) { aom_write(w, mbmi->filter_intra_mode_info.use_filter_intra_mode[1], cm->fc->filter_intra_probs[1]); if (mbmi->filter_intra_mode_info.use_filter_intra_mode[1]) { @@ -1312,16 +1293,9 @@ static void write_mb_interp_filter(AV1_COMP *cpi, const MACROBLOCKD *xd, FRAME_CONTEXT *ec_ctx = xd->tile_ctx; if (!av1_is_interp_needed(xd)) { -#if CONFIG_DUAL_FILTER - for (int i = 0; i < 4; ++i) - assert(mbmi->interp_filter[i] == (cm->interp_filter == SWITCHABLE - ? EIGHTTAP_REGULAR - : cm->interp_filter)); -#else - assert(mbmi->interp_filter == (cm->interp_filter == SWITCHABLE - ? EIGHTTAP_REGULAR - : cm->interp_filter)); -#endif // CONFIG_DUAL_FILTER + assert(mbmi->interp_filters == + av1_broadcast_interp_filter( + av1_unswitchable_filter(cm->interp_filter))); return; } if (cm->interp_filter == SWITCHABLE) { @@ -1332,26 +1306,28 @@ static void write_mb_interp_filter(AV1_COMP *cpi, const MACROBLOCKD *xd, (mbmi->ref_frame[1] > INTRA_FRAME && has_subpel_mv_component(xd->mi[0], xd, dir + 2))) { const int ctx = av1_get_pred_context_switchable_interp(xd, dir); - aom_write_symbol(w, av1_switchable_interp_ind[mbmi->interp_filter[dir]], - ec_ctx->switchable_interp_cdf[ctx], + InterpFilter filter = + av1_extract_interp_filter(mbmi->interp_filters, dir); + aom_write_symbol(w, filter, ec_ctx->switchable_interp_cdf[ctx], SWITCHABLE_FILTERS); - ++cpi->interp_filter_selected[0][mbmi->interp_filter[dir]]; + ++cpi->interp_filter_selected[0][filter]; } else { - assert(mbmi->interp_filter[dir] == EIGHTTAP_REGULAR); + assert(av1_extract_interp_filter(mbmi->interp_filters, dir) == + EIGHTTAP_REGULAR); } } #else { const int ctx = av1_get_pred_context_switchable_interp(xd); - aom_write_symbol(w, av1_switchable_interp_ind[mbmi->interp_filter], - ec_ctx->switchable_interp_cdf[ctx], SWITCHABLE_FILTERS); - ++cpi->interp_filter_selected[0][mbmi->interp_filter]; + InterpFilter filter = av1_extract_interp_filter(mbmi->interp_filters, 0); + aom_write_symbol(w, filter, ec_ctx->switchable_interp_cdf[ctx], + SWITCHABLE_FILTERS); + ++cpi->interp_filter_selected[0][filter]; } #endif // CONFIG_DUAL_FILTER } } -#if CONFIG_PALETTE #if CONFIG_PALETTE_DELTA_ENCODING // Transmit color values with delta encoding. Write the first value as // literal, and the deltas between each value and the previous one. "min_val" is @@ -1392,10 +1368,8 @@ static void write_palette_colors_y(const MACROBLOCKD *const xd, const PALETTE_MODE_INFO *const pmi, int bit_depth, aom_writer *w) { const int n = pmi->palette_size[0]; - const MODE_INFO *const above_mi = xd->above_mi; - const MODE_INFO *const left_mi = xd->left_mi; uint16_t color_cache[2 * PALETTE_MAX_SIZE]; - const int n_cache = av1_get_palette_cache(above_mi, left_mi, 0, color_cache); + const int n_cache = av1_get_palette_cache(xd, 0, color_cache); int out_cache_colors[PALETTE_MAX_SIZE]; uint8_t cache_color_found[2 * PALETTE_MAX_SIZE]; const int n_out_cache = @@ -1421,10 +1395,8 @@ static void write_palette_colors_uv(const MACROBLOCKD *const xd, const uint16_t *colors_u = pmi->palette_colors + PALETTE_MAX_SIZE; const uint16_t *colors_v = pmi->palette_colors + 2 * PALETTE_MAX_SIZE; // U channel colors. - const MODE_INFO *const above_mi = xd->above_mi; - const MODE_INFO *const left_mi = xd->left_mi; uint16_t color_cache[2 * PALETTE_MAX_SIZE]; - const int n_cache = av1_get_palette_cache(above_mi, left_mi, 1, color_cache); + const int n_cache = av1_get_palette_cache(xd, 1, color_cache); int out_cache_colors[PALETTE_MAX_SIZE]; uint8_t cache_color_found[2 * PALETTE_MAX_SIZE]; const int n_out_cache = av1_index_color_cache( @@ -1484,6 +1456,9 @@ static void write_palette_mode_info(const AV1_COMMON *cm, const MACROBLOCKD *xd, const BLOCK_SIZE bsize = mbmi->sb_type; const PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info; + assert(bsize >= BLOCK_8X8 && bsize <= BLOCK_LARGEST); + const int block_palette_idx = bsize - BLOCK_8X8; + if (mbmi->mode == DC_PRED) { const int n = pmi->palette_size[0]; int palette_y_mode_ctx = 0; @@ -1495,12 +1470,19 @@ static void write_palette_mode_info(const AV1_COMMON *cm, const MACROBLOCKD *xd, palette_y_mode_ctx += (left_mi->mbmi.palette_mode_info.palette_size[0] > 0); } +#if CONFIG_NEW_MULTISYMBOL + aom_write_symbol( + w, n > 0, + xd->tile_ctx->palette_y_mode_cdf[block_palette_idx][palette_y_mode_ctx], + 2); +#else aom_write( w, n > 0, - av1_default_palette_y_mode_prob[bsize - BLOCK_8X8][palette_y_mode_ctx]); + av1_default_palette_y_mode_prob[block_palette_idx][palette_y_mode_ctx]); +#endif if (n > 0) { aom_write_symbol(w, n - PALETTE_MIN_SIZE, - xd->tile_ctx->palette_y_size_cdf[bsize - BLOCK_8X8], + xd->tile_ctx->palette_y_size_cdf[block_palette_idx], PALETTE_SIZES); #if CONFIG_PALETTE_DELTA_ENCODING write_palette_colors_y(xd, pmi, cm->bit_depth, w); @@ -1516,10 +1498,15 @@ static void write_palette_mode_info(const AV1_COMMON *cm, const MACROBLOCKD *xd, if (mbmi->uv_mode == UV_DC_PRED) { const int n = pmi->palette_size[1]; const int palette_uv_mode_ctx = (pmi->palette_size[0] > 0); +#if CONFIG_NEW_MULTISYMBOL + aom_write_symbol(w, n > 0, + xd->tile_ctx->palette_uv_mode_cdf[palette_uv_mode_ctx], 2); +#else aom_write(w, n > 0, av1_default_palette_uv_mode_prob[palette_uv_mode_ctx]); +#endif if (n > 0) { aom_write_symbol(w, n - PALETTE_MIN_SIZE, - xd->tile_ctx->palette_uv_size_cdf[bsize - BLOCK_8X8], + xd->tile_ctx->palette_uv_size_cdf[block_palette_idx], PALETTE_SIZES); #if CONFIG_PALETTE_DELTA_ENCODING write_palette_colors_uv(xd, pmi, cm->bit_depth, w); @@ -1538,7 +1525,6 @@ static void write_palette_mode_info(const AV1_COMMON *cm, const MACROBLOCKD *xd, } } } -#endif // CONFIG_PALETTE void av1_write_tx_type(const AV1_COMMON *const cm, const MACROBLOCKD *xd, #if CONFIG_SUPERTX @@ -1583,25 +1569,64 @@ void av1_write_tx_type(const AV1_COMMON *const cm, const MACROBLOCKD *xd, !supertx_enabled && #endif // CONFIG_SUPERTX !segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) { +#if CONFIG_MRC_TX + if (tx_type == MRC_DCT) + assert(mbmi->valid_mrc_mask && "Invalid MRC mask"); +#endif // CONFIG_MRC_TX + const TxSetType tx_set_type = get_ext_tx_set_type( + tx_size, bsize, is_inter, cm->reduced_tx_set_used); const int eset = get_ext_tx_set(tx_size, bsize, is_inter, cm->reduced_tx_set_used); // eset == 0 should correspond to a set with only DCT_DCT and there // is no need to send the tx_type assert(eset > 0); + assert(av1_ext_tx_used[tx_set_type][tx_type]); +#if !CONFIG_LGT_FROM_PRED if (is_inter) { - assert(ext_tx_used_inter[eset][tx_type]); - aom_write_symbol(w, av1_ext_tx_inter_ind[eset][tx_type], + aom_write_symbol(w, av1_ext_tx_ind[tx_set_type][tx_type], ec_ctx->inter_ext_tx_cdf[eset][square_tx_size], - ext_tx_cnt_inter[eset]); + av1_num_ext_tx_set[tx_set_type]); } else if (ALLOW_INTRA_EXT_TX) { - assert(ext_tx_used_intra[eset][tx_type]); aom_write_symbol( - w, av1_ext_tx_intra_ind[eset][tx_type], + w, av1_ext_tx_ind[tx_set_type][tx_type], ec_ctx->intra_ext_tx_cdf[eset][square_tx_size][mbmi->mode], - ext_tx_cnt_intra[eset]); + av1_num_ext_tx_set[tx_set_type]); } - } #else + // only signal tx_type when lgt is not allowed or not selected + if (is_inter) { + if (LGT_FROM_PRED_INTER) { + if (is_lgt_allowed(mbmi->mode, tx_size) && !cm->reduced_tx_set_used) + aom_write(w, mbmi->use_lgt, ec_ctx->inter_lgt_prob[square_tx_size]); + if (!mbmi->use_lgt) + aom_write_symbol(w, av1_ext_tx_ind[tx_set_type][tx_type], + ec_ctx->inter_ext_tx_cdf[eset][square_tx_size], + av1_num_ext_tx_set[tx_set_type]); + } else { + aom_write_symbol(w, av1_ext_tx_ind[tx_set_type][tx_type], + ec_ctx->inter_ext_tx_cdf[eset][square_tx_size], + av1_num_ext_tx_set[tx_set_type]); + } + } else if (ALLOW_INTRA_EXT_TX) { + if (LGT_FROM_PRED_INTRA) { + if (is_lgt_allowed(mbmi->mode, tx_size) && !cm->reduced_tx_set_used) + aom_write(w, mbmi->use_lgt, + ec_ctx->intra_lgt_prob[square_tx_size][mbmi->mode]); + if (!mbmi->use_lgt) + aom_write_symbol( + w, av1_ext_tx_ind[tx_set_type][tx_type], + ec_ctx->intra_ext_tx_cdf[eset][square_tx_size][mbmi->mode], + av1_num_ext_tx_set[tx_set_type]); + } else { + aom_write_symbol( + w, av1_ext_tx_ind[tx_set_type][tx_type], + ec_ctx->intra_ext_tx_cdf[eset][square_tx_size][mbmi->mode], + av1_num_ext_tx_set[tx_set_type]); + } + } +#endif // CONFIG_LGT_FROM_PRED + } +#else // CONFIG_EXT_TX if (tx_size < TX_32X32 && ((!cm->seg.enabled && cm->base_qindex > 0) || (cm->seg.enabled && xd->qindex[mbmi->segment_id] > 0)) && @@ -1627,36 +1652,32 @@ void av1_write_tx_type(const AV1_COMMON *const cm, const MACROBLOCKD *xd, static void write_intra_mode(FRAME_CONTEXT *frame_ctx, BLOCK_SIZE bsize, PREDICTION_MODE mode, aom_writer *w) { - aom_write_symbol(w, av1_intra_mode_ind[mode], - frame_ctx->y_mode_cdf[size_group_lookup[bsize]], + aom_write_symbol(w, mode, frame_ctx->y_mode_cdf[size_group_lookup[bsize]], INTRA_MODES); } static void write_intra_uv_mode(FRAME_CONTEXT *frame_ctx, UV_PREDICTION_MODE uv_mode, PREDICTION_MODE y_mode, aom_writer *w) { - aom_write_symbol(w, av1_intra_mode_ind[get_uv_mode(uv_mode)], - frame_ctx->uv_mode_cdf[y_mode], UV_INTRA_MODES); +#if !CONFIG_CFL + uv_mode = get_uv_mode(uv_mode); +#endif + aom_write_symbol(w, uv_mode, frame_ctx->uv_mode_cdf[y_mode], UV_INTRA_MODES); } #if CONFIG_CFL -static void write_cfl_alphas(FRAME_CONTEXT *const frame_ctx, int ind, - const CFL_SIGN_TYPE signs[CFL_SIGNS], - aom_writer *w) { - // Check for uninitialized signs - if (cfl_alpha_codes[ind][CFL_PRED_U] == 0) - assert(signs[CFL_PRED_U] == CFL_SIGN_POS); - if (cfl_alpha_codes[ind][CFL_PRED_V] == 0) - assert(signs[CFL_PRED_V] == CFL_SIGN_POS); - - // Write a symbol representing a combination of alpha Cb and alpha Cr. - aom_write_symbol(w, ind, frame_ctx->cfl_alpha_cdf, CFL_ALPHABET_SIZE); - - // Signs are only signaled for nonzero codes. - if (cfl_alpha_codes[ind][CFL_PRED_U] != 0) - aom_write_bit(w, signs[CFL_PRED_U]); - if (cfl_alpha_codes[ind][CFL_PRED_V] != 0) - aom_write_bit(w, signs[CFL_PRED_V]); +static void write_cfl_alphas(FRAME_CONTEXT *const ec_ctx, int idx, + int joint_sign, aom_writer *w) { + aom_write_symbol(w, joint_sign, ec_ctx->cfl_sign_cdf, CFL_JOINT_SIGNS); + // Magnitudes are only signaled for nonzero codes. + if (CFL_SIGN_U(joint_sign) != CFL_SIGN_ZERO) { + aom_cdf_prob *cdf_u = ec_ctx->cfl_alpha_cdf[CFL_CONTEXT_U(joint_sign)]; + aom_write_symbol(w, CFL_IDX_U(idx), cdf_u, CFL_ALPHABET_SIZE); + } + if (CFL_SIGN_V(joint_sign) != CFL_SIGN_ZERO) { + aom_cdf_prob *cdf_v = ec_ctx->cfl_alpha_cdf[CFL_CONTEXT_V(joint_sign)]; + aom_write_symbol(w, CFL_IDX_V(idx), cdf_v, CFL_ALPHABET_SIZE); + } } #endif @@ -1715,7 +1736,6 @@ static void pack_inter_mode_mvs(AV1_COMP *cpi, const int mi_row, #else skip = write_skip(cm, xd, segment_id, mi, w); #endif // CONFIG_SUPERTX -#if CONFIG_DELTA_Q if (cm->delta_q_present_flag) { int super_block_upper_left = ((mi_row & MAX_MIB_MASK) == 0) && ((mi_col & MAX_MIB_MASK) == 0); @@ -1726,6 +1746,25 @@ static void pack_inter_mode_mvs(AV1_COMP *cpi, const int mi_row, write_delta_qindex(cm, xd, reduced_delta_qindex, w); xd->prev_qindex = mbmi->current_q_index; #if CONFIG_EXT_DELTA_Q +#if CONFIG_LOOPFILTER_LEVEL + if (cm->delta_lf_present_flag) { + if (cm->delta_lf_multi) { + for (int lf_id = 0; lf_id < FRAME_LF_COUNT; ++lf_id) { + int reduced_delta_lflevel = + (mbmi->curr_delta_lf[lf_id] - xd->prev_delta_lf[lf_id]) / + cm->delta_lf_res; + write_delta_lflevel(cm, xd, lf_id, reduced_delta_lflevel, w); + xd->prev_delta_lf[lf_id] = mbmi->curr_delta_lf[lf_id]; + } + } else { + int reduced_delta_lflevel = + (mbmi->current_delta_lf_from_base - xd->prev_delta_lf_from_base) / + cm->delta_lf_res; + write_delta_lflevel(cm, xd, -1, reduced_delta_lflevel, w); + xd->prev_delta_lf_from_base = mbmi->current_delta_lf_from_base; + } + } +#else if (cm->delta_lf_present_flag) { int reduced_delta_lflevel = (mbmi->current_delta_lf_from_base - xd->prev_delta_lf_from_base) / @@ -1733,10 +1772,10 @@ static void pack_inter_mode_mvs(AV1_COMP *cpi, const int mi_row, write_delta_lflevel(cm, xd, reduced_delta_lflevel, w); xd->prev_delta_lf_from_base = mbmi->current_delta_lf_from_base; } +#endif // CONFIG_LOOPFILTER_LEVEL #endif // CONFIG_EXT_DELTA_Q } } -#endif #if CONFIG_SUPERTX if (!supertx_enabled) @@ -1744,14 +1783,10 @@ static void pack_inter_mode_mvs(AV1_COMP *cpi, const int mi_row, write_is_inter(cm, xd, mbmi->segment_id, w, is_inter); if (cm->tx_mode == TX_MODE_SELECT && -#if CONFIG_CB4X4 && (CONFIG_VAR_TX || CONFIG_RECT_TX) -#if CONFIG_RECT_TX - bsize > BLOCK_4X4 && -#else +#if CONFIG_CB4X4 && CONFIG_VAR_TX && !CONFIG_RECT_TX (bsize >= BLOCK_8X8 || (bsize > BLOCK_4X4 && is_inter)) && -#endif // CONFIG_RECT_TX #else - bsize >= BLOCK_8X8 && + block_signals_txsize(bsize) && #endif #if CONFIG_SUPERTX !supertx_enabled && @@ -1759,23 +1794,30 @@ static void pack_inter_mode_mvs(AV1_COMP *cpi, const int mi_row, !(is_inter && skip) && !xd->lossless[segment_id]) { #if CONFIG_VAR_TX if (is_inter) { // This implies skip flag is 0. - const TX_SIZE max_tx_size = get_vartx_max_txsize(mbmi, bsize); + const TX_SIZE max_tx_size = get_vartx_max_txsize(mbmi, bsize, 0); const int bh = tx_size_high_unit[max_tx_size]; const int bw = tx_size_wide_unit[max_tx_size]; const int width = block_size_wide[bsize] >> tx_size_wide_log2[0]; const int height = block_size_high[bsize] >> tx_size_wide_log2[0]; + int init_depth = + (height != width) ? RECT_VARTX_DEPTH_INIT : SQR_VARTX_DEPTH_INIT; int idx, idy; for (idy = 0; idy < height; idy += bh) for (idx = 0; idx < width; idx += bw) - write_tx_size_vartx(cm, xd, mbmi, max_tx_size, height != width, idy, - idx, w); + write_tx_size_vartx(cm, xd, mbmi, max_tx_size, init_depth, idy, idx, + w); #if CONFIG_RECT_TX_EXT if (is_quarter_tx_allowed(xd, mbmi, is_inter_block(mbmi)) && quarter_txsize_lookup[bsize] != max_tx_size && (mbmi->tx_size == quarter_txsize_lookup[bsize] || mbmi->tx_size == max_tx_size)) { +#if CONFIG_NEW_MULTISYMBOL + aom_write_symbol(w, mbmi->tx_size != max_tx_size, + cm->fc->quarter_tx_size_cdf, 2); +#else aom_write(w, mbmi->tx_size != max_tx_size, cm->fc->quarter_tx_size_prob); +#endif } #endif } else { @@ -1812,7 +1854,7 @@ static void pack_inter_mode_mvs(AV1_COMP *cpi, const int mi_row, #endif // CONFIG_CB4X4 #if CONFIG_CFL - if (mbmi->uv_mode == UV_DC_PRED) { + if (mbmi->uv_mode == UV_CFL_PRED) { write_cfl_alphas(ec_ctx, mbmi->cfl_alpha_idx, mbmi->cfl_alpha_signs, w); } #endif @@ -1824,10 +1866,8 @@ static void pack_inter_mode_mvs(AV1_COMP *cpi, const int mi_row, #if CONFIG_EXT_INTRA write_intra_angle_info(xd, ec_ctx, w); #endif // CONFIG_EXT_INTRA -#if CONFIG_PALETTE - if (bsize >= BLOCK_8X8 && cm->allow_screen_content_tools) + if (av1_allow_palette(cm->allow_screen_content_tools, bsize)) write_palette_mode_info(cm, xd, mi, w); -#endif // CONFIG_PALETTE #if CONFIG_FILTER_INTRA if (bsize >= BLOCK_8X8 || unify_bsize) write_filter_intra_mode_info(cm, xd, mbmi, mi_row, mi_col, w); @@ -1836,16 +1876,15 @@ static void pack_inter_mode_mvs(AV1_COMP *cpi, const int mi_row, int16_t mode_ctx; write_ref_frames(cm, xd, w); -#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF +#if CONFIG_COMPOUND_SINGLEREF if (!segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME)) { // NOTE: Handle single ref comp mode if (!is_compound) aom_write(w, is_inter_singleref_comp_mode(mode), av1_get_inter_mode_prob(cm, xd)); } -#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF +#endif // CONFIG_COMPOUND_SINGLEREF -#if CONFIG_EXT_INTER #if CONFIG_COMPOUND_SINGLEREF if (is_compound || is_inter_singleref_comp_mode(mode)) #else // !CONFIG_COMPOUND_SINGLEREF @@ -1853,7 +1892,6 @@ static void pack_inter_mode_mvs(AV1_COMP *cpi, const int mi_row, #endif // CONFIG_COMPOUND_SINGLEREF mode_ctx = mbmi_ext->compound_mode_context[mbmi->ref_frame[0]]; else -#endif // CONFIG_EXT_INTER mode_ctx = av1_mode_context_analyzer(mbmi_ext->mode_context, mbmi->ref_frame, bsize, -1); @@ -1861,7 +1899,6 @@ static void pack_inter_mode_mvs(AV1_COMP *cpi, const int mi_row, // If segment skip is not enabled code the mode. if (!segfeature_active(seg, segment_id, SEG_LVL_SKIP)) { if (bsize >= BLOCK_8X8 || unify_bsize) { -#if CONFIG_EXT_INTER if (is_inter_compound_mode(mode)) write_inter_compound_mode(cm, xd, w, mode, mode_ctx); #if CONFIG_COMPOUND_SINGLEREF @@ -1869,18 +1906,13 @@ static void pack_inter_mode_mvs(AV1_COMP *cpi, const int mi_row, write_inter_singleref_comp_mode(xd, w, mode, mode_ctx); #endif // CONFIG_COMPOUND_SINGLEREF else if (is_inter_singleref_mode(mode)) -#endif // CONFIG_EXT_INTER write_inter_mode(w, mode, ec_ctx, mode_ctx); -#if CONFIG_EXT_INTER if (mode == NEWMV || mode == NEW_NEWMV || #if CONFIG_COMPOUND_SINGLEREF mbmi->mode == SR_NEW_NEWMV || #endif // CONFIG_COMPOUND_SINGLEREF have_nearmv_in_inter_mode(mode)) -#else // !CONFIG_EXT_INTER - if (mode == NEARMV || mode == NEWMV) -#endif // CONFIG_EXT_INTER write_drl_idx(ec_ctx, mbmi, mbmi_ext, w); else assert(mbmi->ref_mv_idx == 0); @@ -1903,23 +1935,15 @@ static void pack_inter_mode_mvs(AV1_COMP *cpi, const int mi_row, for (idx = 0; idx < 2; idx += num_4x4_w) { const int j = idy * 2 + idx; const PREDICTION_MODE b_mode = mi->bmi[j].as_mode; -#if CONFIG_EXT_INTER if (!is_compound) -#endif // CONFIG_EXT_INTER mode_ctx = av1_mode_context_analyzer(mbmi_ext->mode_context, mbmi->ref_frame, bsize, j); -#if CONFIG_EXT_INTER if (is_inter_compound_mode(b_mode)) write_inter_compound_mode(cm, xd, w, b_mode, mode_ctx); else if (is_inter_singleref_mode(b_mode)) -#endif // CONFIG_EXT_INTER write_inter_mode(w, b_mode, ec_ctx, mode_ctx); -#if CONFIG_EXT_INTER if (b_mode == NEWMV || b_mode == NEW_NEWMV) { -#else - if (b_mode == NEWMV) { -#endif // CONFIG_EXT_INTER for (ref = 0; ref < 1 + is_compound; ++ref) { int8_t rf_type = av1_ref_frame_type(mbmi->ref_frame); int nmv_ctx = av1_nmv_ctx(mbmi_ext->ref_mv_count[rf_type], @@ -1927,16 +1951,9 @@ static void pack_inter_mode_mvs(AV1_COMP *cpi, const int mi_row, mbmi->ref_mv_idx); nmv_context *nmvc = &ec_ctx->nmvc[nmv_ctx]; av1_encode_mv(cpi, w, &mi->bmi[j].as_mv[ref].as_mv, -#if CONFIG_EXT_INTER - &mi->bmi[j].ref_mv[ref].as_mv, -#else - &mi->bmi[j].pred_mv[ref].as_mv, -#endif // CONFIG_EXT_INTER - nmvc, allow_hp); + &mi->bmi[j].ref_mv[ref].as_mv, nmvc, allow_hp); } - } -#if CONFIG_EXT_INTER - else if (b_mode == NEAREST_NEWMV || b_mode == NEAR_NEWMV) { + } else if (b_mode == NEAREST_NEWMV || b_mode == NEAR_NEWMV) { int8_t rf_type = av1_ref_frame_type(mbmi->ref_frame); int nmv_ctx = av1_nmv_ctx(mbmi_ext->ref_mv_count[rf_type], mbmi_ext->ref_mv_stack[rf_type], 1, @@ -1953,15 +1970,10 @@ static void pack_inter_mode_mvs(AV1_COMP *cpi, const int mi_row, av1_encode_mv(cpi, w, &mi->bmi[j].as_mv[0].as_mv, &mi->bmi[j].ref_mv[0].as_mv, nmvc, allow_hp); } -#endif // CONFIG_EXT_INTER } } } else { -#if CONFIG_EXT_INTER if (mode == NEWMV || mode == NEW_NEWMV) { -#else - if (mode == NEWMV) { -#endif // CONFIG_EXT_INTER int_mv ref_mv; for (ref = 0; ref < 1 + is_compound; ++ref) { int8_t rf_type = av1_ref_frame_type(mbmi->ref_frame); @@ -1973,7 +1985,6 @@ static void pack_inter_mode_mvs(AV1_COMP *cpi, const int mi_row, av1_encode_mv(cpi, w, &mbmi->mv[ref].as_mv, &ref_mv.as_mv, nmvc, allow_hp); } -#if CONFIG_EXT_INTER } else if (mode == NEAREST_NEWMV || mode == NEAR_NEWMV) { int8_t rf_type = av1_ref_frame_type(mbmi->ref_frame); int nmv_ctx = @@ -2008,11 +2019,10 @@ static void pack_inter_mode_mvs(AV1_COMP *cpi, const int mi_row, av1_encode_mv(cpi, w, &mbmi->mv[1].as_mv, &ref_mv.as_mv, nmvc, allow_hp); #endif // CONFIG_COMPOUND_SINGLEREF -#endif // CONFIG_EXT_INTER } } -#if CONFIG_EXT_INTER && CONFIG_INTERINTRA +#if CONFIG_INTERINTRA if (cpi->common.reference_mode != COMPOUND_REFERENCE && #if CONFIG_SUPERTX !supertx_enabled && @@ -2045,22 +2055,18 @@ static void pack_inter_mode_mvs(AV1_COMP *cpi, const int mi_row, } } } -#endif // CONFIG_EXT_INTER && CONFIG_INTERINTRA +#endif // CONFIG_INTERINTRA #if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION #if CONFIG_SUPERTX if (!supertx_enabled) #endif // CONFIG_SUPERTX -#if CONFIG_EXT_INTER - if (mbmi->ref_frame[1] != INTRA_FRAME) -#endif // CONFIG_EXT_INTER - write_motion_mode(cm, xd, mi, w); + if (mbmi->ref_frame[1] != INTRA_FRAME) write_motion_mode(cm, xd, mi, w); #if CONFIG_NCOBMC_ADAPT_WEIGHT write_ncobmc_mode(xd, mi, w); #endif #endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION -#if CONFIG_EXT_INTER if ( #if CONFIG_COMPOUND_SINGLEREF is_inter_anyref_comp_mode(mbmi->mode) && @@ -2074,10 +2080,16 @@ static void pack_inter_mode_mvs(AV1_COMP *cpi, const int mi_row, is_any_masked_compound_used(bsize)) { #if CONFIG_COMPOUND_SEGMENT || CONFIG_WEDGE if (cm->allow_masked_compound) { - aom_write_symbol(w, mbmi->interinter_compound_type, - ec_ctx->compound_type_cdf[bsize], COMPOUND_TYPES); +#if CONFIG_WEDGE && CONFIG_COMPOUND_SEGMENT + if (!is_interinter_compound_used(COMPOUND_WEDGE, bsize)) + aom_write_bit(w, mbmi->interinter_compound_type == COMPOUND_AVERAGE); + else +#endif // CONFIG_WEDGE && CONFIG_COMPOUND_SEGMENT + aom_write_symbol(w, mbmi->interinter_compound_type, + ec_ctx->compound_type_cdf[bsize], COMPOUND_TYPES); #if CONFIG_WEDGE - if (mbmi->interinter_compound_type == COMPOUND_WEDGE) { + if (is_interinter_compound_used(COMPOUND_WEDGE, bsize) && + mbmi->interinter_compound_type == COMPOUND_WEDGE) { aom_write_literal(w, mbmi->wedge_index, get_wedge_bits_lookup(bsize)); aom_write_bit(w, mbmi->wedge_sign); } @@ -2090,7 +2102,6 @@ static void pack_inter_mode_mvs(AV1_COMP *cpi, const int mi_row, } #endif // CONFIG_COMPOUND_SEGMENT || CONFIG_WEDGE } -#endif // CONFIG_EXT_INTER #if CONFIG_DUAL_FILTER || CONFIG_WARPED_MOTION || CONFIG_GLOBAL_MOTION write_mb_interp_filter(cpi, xd, w); @@ -2106,12 +2117,7 @@ static void pack_inter_mode_mvs(AV1_COMP *cpi, const int mi_row, #endif // !CONFIG_TXK_SEL } -static void write_mb_modes_kf(AV1_COMMON *cm, -#if CONFIG_DELTA_Q - MACROBLOCKD *xd, -#else - const MACROBLOCKD *xd, -#endif // CONFIG_DELTA_Q +static void write_mb_modes_kf(AV1_COMMON *cm, MACROBLOCKD *xd, #if CONFIG_INTRABC const MB_MODE_INFO_EXT *mbmi_ext, #endif // CONFIG_INTRABC @@ -2135,7 +2141,6 @@ static void write_mb_modes_kf(AV1_COMMON *cm, if (seg->update_map) write_segment_id(w, seg, segp, mbmi->segment_id); -#if CONFIG_DELTA_Q const int skip = write_skip(cm, xd, mbmi->segment_id, mi, w); if (cm->delta_q_present_flag) { int super_block_upper_left = @@ -2147,6 +2152,25 @@ static void write_mb_modes_kf(AV1_COMMON *cm, write_delta_qindex(cm, xd, reduced_delta_qindex, w); xd->prev_qindex = mbmi->current_q_index; #if CONFIG_EXT_DELTA_Q +#if CONFIG_LOOPFILTER_LEVEL + if (cm->delta_lf_present_flag) { + if (cm->delta_lf_multi) { + for (int lf_id = 0; lf_id < FRAME_LF_COUNT; ++lf_id) { + int reduced_delta_lflevel = + (mbmi->curr_delta_lf[lf_id] - xd->prev_delta_lf[lf_id]) / + cm->delta_lf_res; + write_delta_lflevel(cm, xd, lf_id, reduced_delta_lflevel, w); + xd->prev_delta_lf[lf_id] = mbmi->curr_delta_lf[lf_id]; + } + } else { + int reduced_delta_lflevel = + (mbmi->current_delta_lf_from_base - xd->prev_delta_lf_from_base) / + cm->delta_lf_res; + write_delta_lflevel(cm, xd, -1, reduced_delta_lflevel, w); + xd->prev_delta_lf_from_base = mbmi->current_delta_lf_from_base; + } + } +#else if (cm->delta_lf_present_flag) { int reduced_delta_lflevel = (mbmi->current_delta_lf_from_base - xd->prev_delta_lf_from_base) / @@ -2154,29 +2178,19 @@ static void write_mb_modes_kf(AV1_COMMON *cm, write_delta_lflevel(cm, xd, reduced_delta_lflevel, w); xd->prev_delta_lf_from_base = mbmi->current_delta_lf_from_base; } +#endif // CONFIG_LOOPFILTER_LEVEL #endif // CONFIG_EXT_DELTA_Q } } -#else - write_skip(cm, xd, mbmi->segment_id, mi, w); -#endif int enable_tx_size = cm->tx_mode == TX_MODE_SELECT && -#if CONFIG_CB4X4 && (CONFIG_VAR_TX || CONFIG_RECT_TX) -#if CONFIG_RECT_TX - bsize > BLOCK_4X4 && -#else - bsize >= BLOCK_8X8 && -#endif // CONFIG_RECT_TX -#else - bsize >= BLOCK_8X8 && -#endif + block_signals_txsize(bsize) && !xd->lossless[mbmi->segment_id]; #if CONFIG_INTRABC - if (bsize >= BLOCK_8X8 && cm->allow_screen_content_tools) { + if (av1_allow_intrabc(bsize, cm)) { int use_intrabc = is_intrabc_block(mbmi); - aom_write(w, use_intrabc, ec_ctx->intrabc_prob); + aom_write_symbol(w, use_intrabc, ec_ctx->intrabc_cdf, 2); if (use_intrabc) { assert(mbmi->mode == DC_PRED); assert(mbmi->uv_mode == UV_DC_PRED); @@ -2221,7 +2235,7 @@ static void write_mb_modes_kf(AV1_COMMON *cm, #endif // CONFIG_CB4X4 #if CONFIG_CFL - if (mbmi->uv_mode == UV_DC_PRED) { + if (mbmi->uv_mode == UV_CFL_PRED) { write_cfl_alphas(ec_ctx, mbmi->cfl_alpha_idx, mbmi->cfl_alpha_signs, w); } #endif @@ -2232,10 +2246,8 @@ static void write_mb_modes_kf(AV1_COMMON *cm, #if CONFIG_EXT_INTRA write_intra_angle_info(xd, ec_ctx, w); #endif // CONFIG_EXT_INTRA -#if CONFIG_PALETTE - if (bsize >= BLOCK_8X8 && cm->allow_screen_content_tools) + if (av1_allow_palette(cm->allow_screen_content_tools, bsize)) write_palette_mode_info(cm, xd, mi, w); -#endif // CONFIG_PALETTE #if CONFIG_FILTER_INTRA if (bsize >= BLOCK_8X8 || unify_bsize) write_filter_intra_mode_info(cm, xd, mbmi, mi_row, mi_col, w); @@ -2312,7 +2324,7 @@ static void enc_dump_logs(AV1_COMP *cpi, int mi_row, int mi_col) { m = xd->mi[0]; if (is_inter_block(&m->mbmi)) { #define FRAME_TO_CHECK 1 - if (cm->current_video_frame == FRAME_TO_CHECK /* && cm->show_frame == 1*/) { + if (cm->current_video_frame == FRAME_TO_CHECK && cm->show_frame == 1) { const MB_MODE_INFO *const mbmi = &m->mbmi; const BLOCK_SIZE bsize = mbmi->sb_type; @@ -2331,21 +2343,6 @@ static void enc_dump_logs(AV1_COMP *cpi, int mi_row, int mi_col) { #endif // CONFIG_COMPOUND_SINGLEREF mv[1].as_int = 0; } - int interp_ctx[2] = { -1 }; - int interp_filter[2] = { cm->interp_filter }; - if (cm->interp_filter == SWITCHABLE) { - int dir; - for (dir = 0; dir < 2; ++dir) { - if (has_subpel_mv_component(xd->mi[0], xd, dir) || - (mbmi->ref_frame[1] > INTRA_FRAME && - has_subpel_mv_component(xd->mi[0], xd, dir + 2))) { - interp_ctx[dir] = av1_get_pred_context_switchable_interp(xd, dir); - interp_filter[dir] = mbmi->interp_filter[dir]; - } else { - interp_filter[dir] = EIGHTTAP_REGULAR; - } - } - } MACROBLOCK *const x = &cpi->td.mb; const MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext; @@ -2373,13 +2370,11 @@ static void enc_dump_logs(AV1_COMP *cpi, int mi_row, int mi_col) { "Frame=%d, (mi_row,mi_col)=(%d,%d), mode=%d, bsize=%d, " "show_frame=%d, mv[0]=(%d,%d), mv[1]=(%d,%d), ref[0]=%d, " "ref[1]=%d, motion_mode=%d, inter_mode_ctx=%d, mode_ctx=%d, " - "interp_ctx=(%d,%d), interp_filter=(%d,%d), newmv_ctx=%d, " - "zeromv_ctx=%d, refmv_ctx=%d\n", + "newmv_ctx=%d, zeromv_ctx=%d, refmv_ctx=%d\n", cm->current_video_frame, mi_row, mi_col, mbmi->mode, bsize, cm->show_frame, mv[0].as_mv.row, mv[0].as_mv.col, mv[1].as_mv.row, mv[1].as_mv.col, mbmi->ref_frame[0], mbmi->ref_frame[1], mbmi->motion_mode, mbmi_ext->mode_context[ref_frame_type], mode_ctx, - interp_ctx[0], interp_ctx[1], interp_filter[0], interp_filter[1], newmv_ctx, zeromv_ctx, refmv_ctx); } } @@ -2400,7 +2395,7 @@ static void write_mbmi_b(AV1_COMP *cpi, const TileInfo *const tile, m = xd->mi[0]; assert(m->mbmi.sb_type <= cm->sb_size || - (m->mbmi.sb_type >= BLOCK_4X16 && m->mbmi.sb_type <= BLOCK_32X8)); + (m->mbmi.sb_type >= BLOCK_SIZES && m->mbmi.sb_type < BLOCK_SIZES_ALL)); bh = mi_size_high[m->mbmi.sb_type]; bw = mi_size_wide[m->mbmi.sb_type]; @@ -2431,14 +2426,13 @@ static void write_mbmi_b(AV1_COMP *cpi, const TileInfo *const tile, // up if they are scaled. has_subpel_mv_component is in turn needed by // write_switchable_interp_filter, which is called by pack_inter_mode_mvs. set_ref_ptrs(cm, xd, m->mbmi.ref_frame[0], m->mbmi.ref_frame[1]); -#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF +#if CONFIG_COMPOUND_SINGLEREF if (!has_second_ref(&m->mbmi) && is_inter_singleref_comp_mode(m->mbmi.mode)) xd->block_refs[1] = xd->block_refs[0]; -#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF +#endif // CONFIG_COMPOUND_SINGLEREF #endif // CONFIG_DUAL_FILTER || CONFIG_WARPED_MOTION #if ENC_MISMATCH_DEBUG - // NOTE(zoeliu): For debug enc_dump_logs(cpi, mi_row, mi_col); #endif // ENC_MISMATCH_DEBUG @@ -2469,7 +2463,7 @@ static void write_tokens_b(AV1_COMP *cpi, const TileInfo *const tile, xd->mi = cm->mi_grid_visible + mi_offset; assert(mbmi->sb_type <= cm->sb_size || - (mbmi->sb_type >= BLOCK_4X16 && mbmi->sb_type <= BLOCK_32X8)); + (mbmi->sb_type >= BLOCK_SIZES && mbmi->sb_type < BLOCK_SIZES_ALL)); bh = mi_size_high[mbmi->sb_type]; bw = mi_size_wide[mbmi->sb_type]; @@ -2481,7 +2475,8 @@ static void write_tokens_b(AV1_COMP *cpi, const TileInfo *const tile, #endif // CONFIG_DEPENDENT_HORZTILES cm->mi_rows, cm->mi_cols); -#if CONFIG_PALETTE +// TODO(anybody) : remove this flag when PVQ supports pallete coding tool +#if !CONFIG_PVQ for (plane = 0; plane <= 1; ++plane) { const uint8_t palette_size_plane = mbmi->palette_mode_info.palette_size[plane]; @@ -2494,11 +2489,13 @@ static void write_tokens_b(AV1_COMP *cpi, const TileInfo *const tile, av1_get_block_dimensions(mbmi->sb_type, plane, xd, NULL, NULL, &rows, &cols); assert(*tok < tok_end); - pack_palette_tokens(w, tok, palette_size_plane, rows * cols); + pack_map_tokens(w, tok, palette_size_plane, rows * cols); +#if !CONFIG_LV_MAP assert(*tok < tok_end + mbmi->skip); +#endif // !CONFIG_LV_MAP } } -#endif // CONFIG_PALETTE +#endif // !CONFIG_PVQ #if CONFIG_COEF_INTERLEAVE if (!mbmi->skip) { @@ -2585,7 +2582,9 @@ static void write_tokens_b(AV1_COMP *cpi, const TileInfo *const tile, if (!is_chroma_reference(mi_row, mi_col, mbmi->sb_type, xd->plane[plane].subsampling_x, xd->plane[plane].subsampling_y)) { +#if !CONFIG_LV_MAP (*tok)++; +#endif // !CONFIG_LV_MAP continue; } #endif @@ -2620,12 +2619,15 @@ static void write_tokens_b(AV1_COMP *cpi, const TileInfo *const tile, mu_blocks_high = AOMMIN(num_4x4_h, mu_blocks_high); if (is_inter_block(mbmi)) { - const TX_SIZE max_tx_size = get_vartx_max_txsize(mbmi, plane_bsize); + const TX_SIZE max_tx_size = get_vartx_max_txsize( + mbmi, plane_bsize, pd->subsampling_x || pd->subsampling_y); int block = 0; const int step = tx_size_wide_unit[max_tx_size] * tx_size_high_unit[max_tx_size]; const int bkw = tx_size_wide_unit[max_tx_size]; const int bkh = tx_size_high_unit[max_tx_size]; + assert(bkw <= mu_blocks_wide); + assert(bkh <= mu_blocks_high); for (row = 0; row < num_4x4_h; row += mu_blocks_high) { const int unit_height = AOMMIN(mu_blocks_high + row, num_4x4_h); for (col = 0; col < num_4x4_w; col += mu_blocks_wide) { @@ -2673,7 +2675,15 @@ static void write_tokens_b(AV1_COMP *cpi, const TileInfo *const tile, for (blk_row = row; blk_row < unit_height; blk_row += bkh) { for (blk_col = col; blk_col < unit_width; blk_col += bkw) { #if !CONFIG_PVQ +#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK + TX_TYPE tx_type = + av1_get_tx_type(plane ? PLANE_TYPE_UV : PLANE_TYPE_Y, xd, + blk_row, blk_col, 0, tx); +#endif // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK pack_mb_tokens(w, tok, tok_end, cm->bit_depth, tx, +#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK + tx_type, is_inter_block(mbmi), +#endif // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK &token_stats); #else pack_pvq_tokens(w, x, xd, plane, bsize, tx); @@ -2692,8 +2702,16 @@ static void write_tokens_b(AV1_COMP *cpi, const TileInfo *const tile, #if CONFIG_LV_MAP (void)tx; av1_write_coeffs_mb(cm, x, w, plane); -#else // CONFIG_LV_MAP - pack_mb_tokens(w, tok, tok_end, cm->bit_depth, tx, &token_stats); +#else // CONFIG_LV_MAP +#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK + TX_TYPE tx_type = av1_get_tx_type(plane ? PLANE_TYPE_UV : PLANE_TYPE_Y, + xd, blk_row, blk_col, 0, tx); +#endif // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK + pack_mb_tokens(w, tok, tok_end, cm->bit_depth, tx, +#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK + tx_type, is_inter_block(mbmi), +#endif // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK + &token_stats); #endif // CONFIG_LV_MAP #else @@ -2718,7 +2736,7 @@ static void write_tokens_b(AV1_COMP *cpi, const TileInfo *const tile, #endif // CONFIG_COEF_INTERLEAVE } -#if CONFIG_MOTION_VAR && (CONFIG_NCOBMC || CONFIG_NCOBMC_ADAPT_WEIGHT) +#if CONFIG_MOTION_VAR && NC_MODE_INFO static void write_tokens_sb(AV1_COMP *cpi, const TileInfo *const tile, aom_writer *w, const TOKENEXTRA **tok, const TOKENEXTRA *const tok_end, int mi_row, @@ -2765,6 +2783,9 @@ static void write_tokens_sb(AV1_COMP *cpi, const TileInfo *const tile, subsize); break; #if CONFIG_EXT_PARTITION_TYPES +#if CONFIG_EXT_PARTITION_TYPES_AB +#error NC_MODE_INFO+MOTION_VAR not yet supported for new HORZ/VERT_AB partitions +#endif case PARTITION_HORZ_A: write_tokens_b(cpi, tile, w, tok, tok_end, mi_row, mi_col); write_tokens_b(cpi, tile, w, tok, tok_end, mi_row, mi_col + hbs); @@ -2804,7 +2825,8 @@ static void write_modes_b(AV1_COMP *cpi, const TileInfo *const tile, supertx_enabled, #endif mi_row, mi_col); -#if CONFIG_MOTION_VAR && (CONFIG_NCOBMC || CONFIG_NCOBMC_ADAPT_WEIGHT) + +#if CONFIG_MOTION_VAR && NC_MODE_INFO (void)tok; (void)tok_end; #else @@ -2829,13 +2851,6 @@ static void write_partition(const AV1_COMMON *const cm, #endif bsize) : 0; -#if CONFIG_UNPOISON_PARTITION_CTX - const aom_prob *const probs = - ctx < PARTITION_CONTEXTS ? cm->fc->partition_prob[ctx] : NULL; -#else - const aom_prob *const probs = cm->fc->partition_prob[ctx]; -#endif - FRAME_CONTEXT *ec_ctx = xd->tile_ctx; (void)cm; @@ -2843,19 +2858,26 @@ static void write_partition(const AV1_COMMON *const cm, if (has_rows && has_cols) { #if CONFIG_EXT_PARTITION_TYPES - if (bsize <= BLOCK_8X8) - aom_write_symbol(w, p, ec_ctx->partition_cdf[ctx], PARTITION_TYPES); - else - aom_write_symbol(w, p, ec_ctx->partition_cdf[ctx], EXT_PARTITION_TYPES); + const int num_partition_types = + (mi_width_log2_lookup[bsize] > mi_width_log2_lookup[BLOCK_8X8]) + ? EXT_PARTITION_TYPES + : PARTITION_TYPES; #else - aom_write_symbol(w, p, ec_ctx->partition_cdf[ctx], PARTITION_TYPES); -#endif // CONFIG_EXT_PARTITION_TYPES + const int num_partition_types = PARTITION_TYPES; +#endif + aom_write_symbol(w, p, ec_ctx->partition_cdf[ctx], num_partition_types); } else if (!has_rows && has_cols) { assert(p == PARTITION_SPLIT || p == PARTITION_HORZ); - aom_write(w, p == PARTITION_SPLIT, probs[1]); + assert(bsize > BLOCK_8X8); + aom_cdf_prob cdf[2]; + partition_gather_vert_alike(cdf, ec_ctx->partition_cdf[ctx]); + aom_write_cdf(w, p == PARTITION_SPLIT, cdf, 2); } else if (has_rows && !has_cols) { assert(p == PARTITION_SPLIT || p == PARTITION_VERT); - aom_write(w, p == PARTITION_SPLIT, probs[2]); + assert(bsize > BLOCK_8X8); + aom_cdf_prob cdf[2]; + partition_gather_horz_alike(cdf, ec_ctx->partition_cdf[ctx]); + aom_write_cdf(w, p == PARTITION_SPLIT, cdf, 2); } else { assert(p == PARTITION_SPLIT); } @@ -2885,7 +2907,10 @@ static void write_modes_sb(AV1_COMP *const cpi, const TileInfo *const tile, #if CONFIG_EXT_PARTITION_TYPES const int quarter_step = mi_size_wide[bsize] / 4; int i; -#endif +#if CONFIG_EXT_PARTITION_TYPES_AB + const int qbs = mi_size_wide[bsize] / 4; +#endif // CONFIG_EXT_PARTITION_TYPES_AB +#endif // CONFIG_EXT_PARTITION_TYPES const PARTITION_TYPE partition = get_partition(cm, mi_row, mi_col, bsize); const BLOCK_SIZE subsize = get_subsize(bsize, partition); #if CONFIG_CB4X4 @@ -2899,7 +2924,6 @@ static void write_modes_sb(AV1_COMP *const cpi, const TileInfo *const tile, MB_MODE_INFO *mbmi; const int pack_token = !supertx_enabled; TX_SIZE supertx_size; - int plane; #endif if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) return; @@ -2959,6 +2983,42 @@ static void write_modes_sb(AV1_COMP *const cpi, const TileInfo *const tile, mi_row + hbs, mi_col + hbs, subsize); break; #if CONFIG_EXT_PARTITION_TYPES +#if CONFIG_EXT_PARTITION_TYPES_AB + case PARTITION_HORZ_A: + write_modes_b_wrapper(cpi, tile, w, tok, tok_end, supertx_enabled, + mi_row, mi_col); + write_modes_b_wrapper(cpi, tile, w, tok, tok_end, supertx_enabled, + mi_row + qbs, mi_col); + write_modes_b_wrapper(cpi, tile, w, tok, tok_end, supertx_enabled, + mi_row + hbs, mi_col); + break; + case PARTITION_HORZ_B: + write_modes_b_wrapper(cpi, tile, w, tok, tok_end, supertx_enabled, + mi_row, mi_col); + write_modes_b_wrapper(cpi, tile, w, tok, tok_end, supertx_enabled, + mi_row + hbs, mi_col); + if (mi_row + 3 * qbs < cm->mi_rows) + write_modes_b_wrapper(cpi, tile, w, tok, tok_end, supertx_enabled, + mi_row + 3 * qbs, mi_col); + break; + case PARTITION_VERT_A: + write_modes_b_wrapper(cpi, tile, w, tok, tok_end, supertx_enabled, + mi_row, mi_col); + write_modes_b_wrapper(cpi, tile, w, tok, tok_end, supertx_enabled, + mi_row, mi_col + qbs); + write_modes_b_wrapper(cpi, tile, w, tok, tok_end, supertx_enabled, + mi_row, mi_col + hbs); + break; + case PARTITION_VERT_B: + write_modes_b_wrapper(cpi, tile, w, tok, tok_end, supertx_enabled, + mi_row, mi_col); + write_modes_b_wrapper(cpi, tile, w, tok, tok_end, supertx_enabled, + mi_row, mi_col + hbs); + if (mi_col + 3 * qbs < cm->mi_cols) + write_modes_b_wrapper(cpi, tile, w, tok, tok_end, supertx_enabled, + mi_row, mi_col + 3 * qbs); + break; +#else case PARTITION_HORZ_A: write_modes_b_wrapper(cpi, tile, w, tok, tok_end, supertx_enabled, mi_row, mi_col); @@ -2991,6 +3051,7 @@ static void write_modes_sb(AV1_COMP *const cpi, const TileInfo *const tile, write_modes_b_wrapper(cpi, tile, w, tok, tok_end, supertx_enabled, mi_row + hbs, mi_col + hbs); break; +#endif case PARTITION_HORZ_4: for (i = 0; i < 4; ++i) { int this_mi_row = mi_row + i * quarter_step; @@ -3039,10 +3100,12 @@ static void write_modes_sb(AV1_COMP *const cpi, const TileInfo *const tile, !skip) { const int eset = get_ext_tx_set(supertx_size, bsize, 1, cm->reduced_tx_set_used); + const int tx_set_type = + get_ext_tx_set_type(supertx_size, bsize, 1, cm->reduced_tx_set_used); if (eset > 0) { - aom_write_symbol(w, av1_ext_tx_inter_ind[eset][mbmi->tx_type], + aom_write_symbol(w, av1_ext_tx_ind[tx_set_type][mbmi->tx_type], ec_ctx->inter_ext_tx_cdf[eset][supertx_size], - ext_tx_cnt_inter[eset]); + av1_num_ext_tx_set[tx_set_type]); } } #else @@ -3054,7 +3117,11 @@ static void write_modes_sb(AV1_COMP *const cpi, const TileInfo *const tile, if (!skip) { assert(*tok < tok_end); - for (plane = 0; plane < MAX_MB_PLANE; ++plane) { + for (int plane = 0; plane < MAX_MB_PLANE; ++plane) { +#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK + TX_TYPE tx_type = av1_get_tx_type(plane ? PLANE_TYPE_UV : PLANE_TYPE_Y, + xd, blk_row, blk_col, block, tx_size); +#endif // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK const struct macroblockd_plane *const pd = &xd->plane[plane]; const int mbmi_txb_size = txsize_to_bsize[mbmi->tx_size]; const BLOCK_SIZE plane_bsize = get_plane_block_size(mbmi_txb_size, pd); @@ -3073,7 +3140,11 @@ static void write_modes_sb(AV1_COMP *const cpi, const TileInfo *const tile, token_stats.cost = 0; for (row = 0; row < max_blocks_high; row += stepr) for (col = 0; col < max_blocks_wide; col += stepc) - pack_mb_tokens(w, tok, tok_end, cm->bit_depth, tx, &token_stats); + pack_mb_tokens(w, tok, tok_end, cm->bit_depth, tx, +#if CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK + tx_type, is_inter_block(mbmi), +#endif // CONFIG_MRC_TX && SIGNAL_ANY_MRC_MASK + &token_stats); assert(*tok < tok_end && (*tok)->token == EOSB_TOKEN); (*tok)++; } @@ -3096,6 +3167,61 @@ static void write_modes_sb(AV1_COMP *const cpi, const TileInfo *const tile, update_partition_context(xd, mi_row, mi_col, subsize, bsize); #endif // CONFIG_EXT_PARTITION_TYPES +#if CONFIG_LPF_SB + // send filter level for each superblock (64x64) + if (bsize == cm->sb_size) { + if (mi_row == 0 && mi_col == 0) { + aom_write_literal(w, cm->mi_grid_visible[0]->mbmi.filt_lvl, 6); + cm->mi_grid_visible[0]->mbmi.reuse_sb_lvl = 0; + cm->mi_grid_visible[0]->mbmi.delta = 0; + cm->mi_grid_visible[0]->mbmi.sign = 0; + } else { + int prev_mi_row, prev_mi_col; + if (mi_col - MAX_MIB_SIZE < 0) { + prev_mi_row = mi_row - MAX_MIB_SIZE; + prev_mi_col = mi_col; + } else { + prev_mi_row = mi_row; + prev_mi_col = mi_col - MAX_MIB_SIZE; + } + MB_MODE_INFO *curr_mbmi = + &cm->mi_grid_visible[mi_row * cm->mi_stride + mi_col]->mbmi; + MB_MODE_INFO *prev_mbmi = + &cm->mi_grid_visible[prev_mi_row * cm->mi_stride + prev_mi_col]->mbmi; + + const uint8_t curr_lvl = curr_mbmi->filt_lvl; + const uint8_t prev_lvl = prev_mbmi->filt_lvl; + + const int reuse_prev_lvl = curr_lvl == prev_lvl; + const int reuse_ctx = prev_mbmi->reuse_sb_lvl; + curr_mbmi->reuse_sb_lvl = reuse_prev_lvl; + aom_write_symbol(w, reuse_prev_lvl, + xd->tile_ctx->lpf_reuse_cdf[reuse_ctx], 2); + + if (reuse_prev_lvl) { + curr_mbmi->delta = 0; + curr_mbmi->sign = 0; + } else { + const unsigned int delta = abs(curr_lvl - prev_lvl) / LPF_STEP; + const int delta_ctx = prev_mbmi->delta; + curr_mbmi->delta = delta; + aom_write_symbol(w, delta, xd->tile_ctx->lpf_delta_cdf[delta_ctx], + DELTA_RANGE); + + if (delta) { + const int sign = curr_lvl > prev_lvl; + const int sign_ctx = prev_mbmi->sign; + curr_mbmi->sign = sign; + aom_write_symbol(w, sign, + xd->tile_ctx->lpf_sign_cdf[reuse_ctx][sign_ctx], 2); + } else { + curr_mbmi->sign = 0; + } + } + } + } +#endif + #if CONFIG_CDEF if (bsize == cm->sb_size && cm->cdef_bits != 0 && !cm->all_lossless) { int width_step = mi_size_wide[BLOCK_64X64]; @@ -3109,14 +3235,30 @@ static void write_modes_sb(AV1_COMP *const cpi, const TileInfo *const tile, width += width_step) { if (!sb_all_skip(cm, mi_row + height, mi_col + width)) aom_write_literal( - w, cm->mi_grid_visible[(mi_row + height) * cm->mi_stride + - (mi_col + width)] - ->mbmi.cdef_strength, + w, + cm->mi_grid_visible[(mi_row + height) * cm->mi_stride + + (mi_col + width)] + ->mbmi.cdef_strength, cm->cdef_bits); } } } #endif +#if CONFIG_LOOP_RESTORATION + for (int plane = 0; plane < MAX_MB_PLANE; ++plane) { + int rcol0, rcol1, rrow0, rrow1, nhtiles; + if (av1_loop_restoration_corners_in_sb(cm, plane, mi_row, mi_col, bsize, + &rcol0, &rcol1, &rrow0, &rrow1, + &nhtiles)) { + for (int rrow = rrow0; rrow < rrow1; ++rrow) { + for (int rcol = rcol0; rcol < rcol1; ++rcol) { + int rtile_idx = rcol + rrow * nhtiles; + loop_restoration_write_sb_coeffs(cm, xd, w, plane, rtile_idx); + } + } + } + } +#endif } static void write_modes(AV1_COMP *const cpi, const TileInfo *const tile, @@ -3141,16 +3283,18 @@ static void write_modes(AV1_COMP *const cpi, const TileInfo *const tile, #if CONFIG_PVQ assert(cpi->td.mb.pvq_q->curr_pos == 0); #endif -#if CONFIG_DELTA_Q if (cpi->common.delta_q_present_flag) { xd->prev_qindex = cpi->common.base_qindex; #if CONFIG_EXT_DELTA_Q if (cpi->common.delta_lf_present_flag) { +#if CONFIG_LOOPFILTER_LEVEL + for (int lf_id = 0; lf_id < FRAME_LF_COUNT; ++lf_id) + xd->prev_delta_lf[lf_id] = 0; +#endif // CONFIG_LOOPFILTER_LEVEL xd->prev_delta_lf_from_base = 0; } #endif // CONFIG_EXT_DELTA_Q } -#endif for (mi_row = mi_row_start; mi_row < mi_row_end; mi_row += cm->mib_size) { av1_zero_left_context(xd); @@ -3158,7 +3302,7 @@ static void write_modes(AV1_COMP *const cpi, const TileInfo *const tile, for (mi_col = mi_col_start; mi_col < mi_col_end; mi_col += cm->mib_size) { write_modes_sb_wrapper(cpi, tile, w, tok, tok_end, 0, mi_row, mi_col, cm->sb_size); -#if CONFIG_MOTION_VAR && (CONFIG_NCOBMC || CONFIG_NCOBMC_ADAPT_WEIGHT) +#if CONFIG_MOTION_VAR && NC_MODE_INFO write_tokens_sb(cpi, tile, w, tok, tok_end, mi_row, mi_col, cm->sb_size); #endif } @@ -3224,8 +3368,9 @@ static void encode_restoration_mode(AV1_COMMON *cm, int s = AOMMIN(cm->subsampling_x, cm->subsampling_y); if (s && (cm->rst_info[1].frame_restoration_type != RESTORE_NONE || cm->rst_info[2].frame_restoration_type != RESTORE_NONE)) { - aom_wb_write_bit(wb, cm->rst_info[1].restoration_tilesize != - cm->rst_info[0].restoration_tilesize); + aom_wb_write_bit(wb, + cm->rst_info[1].restoration_tilesize != + cm->rst_info[0].restoration_tilesize); assert(cm->rst_info[1].restoration_tilesize == cm->rst_info[0].restoration_tilesize || cm->rst_info[1].restoration_tilesize == @@ -3240,13 +3385,17 @@ static void encode_restoration_mode(AV1_COMMON *cm, } } -static void write_wiener_filter(WienerInfo *wiener_info, +static void write_wiener_filter(int wiener_win, WienerInfo *wiener_info, WienerInfo *ref_wiener_info, aom_writer *wb) { - aom_write_primitive_refsubexpfin( - wb, WIENER_FILT_TAP0_MAXV - WIENER_FILT_TAP0_MINV + 1, - WIENER_FILT_TAP0_SUBEXP_K, - ref_wiener_info->vfilter[0] - WIENER_FILT_TAP0_MINV, - wiener_info->vfilter[0] - WIENER_FILT_TAP0_MINV); + if (wiener_win == WIENER_WIN) + aom_write_primitive_refsubexpfin( + wb, WIENER_FILT_TAP0_MAXV - WIENER_FILT_TAP0_MINV + 1, + WIENER_FILT_TAP0_SUBEXP_K, + ref_wiener_info->vfilter[0] - WIENER_FILT_TAP0_MINV, + wiener_info->vfilter[0] - WIENER_FILT_TAP0_MINV); + else + assert(wiener_info->vfilter[0] == 0 && + wiener_info->vfilter[WIENER_WIN - 1] == 0); aom_write_primitive_refsubexpfin( wb, WIENER_FILT_TAP1_MAXV - WIENER_FILT_TAP1_MINV + 1, WIENER_FILT_TAP1_SUBEXP_K, @@ -3257,11 +3406,15 @@ static void write_wiener_filter(WienerInfo *wiener_info, WIENER_FILT_TAP2_SUBEXP_K, ref_wiener_info->vfilter[2] - WIENER_FILT_TAP2_MINV, wiener_info->vfilter[2] - WIENER_FILT_TAP2_MINV); - aom_write_primitive_refsubexpfin( - wb, WIENER_FILT_TAP0_MAXV - WIENER_FILT_TAP0_MINV + 1, - WIENER_FILT_TAP0_SUBEXP_K, - ref_wiener_info->hfilter[0] - WIENER_FILT_TAP0_MINV, - wiener_info->hfilter[0] - WIENER_FILT_TAP0_MINV); + if (wiener_win == WIENER_WIN) + aom_write_primitive_refsubexpfin( + wb, WIENER_FILT_TAP0_MAXV - WIENER_FILT_TAP0_MINV + 1, + WIENER_FILT_TAP0_SUBEXP_K, + ref_wiener_info->hfilter[0] - WIENER_FILT_TAP0_MINV, + wiener_info->hfilter[0] - WIENER_FILT_TAP0_MINV); + else + assert(wiener_info->hfilter[0] == 0 && + wiener_info->hfilter[WIENER_WIN - 1] == 0); aom_write_primitive_refsubexpfin( wb, WIENER_FILT_TAP1_MAXV - WIENER_FILT_TAP1_MINV + 1, WIENER_FILT_TAP1_SUBEXP_K, @@ -3290,99 +3443,63 @@ static void write_sgrproj_filter(SgrprojInfo *sgrproj_info, memcpy(ref_sgrproj_info, sgrproj_info, sizeof(*sgrproj_info)); } -static void encode_restoration(AV1_COMMON *cm, aom_writer *wb) { - int i, p; -#if CONFIG_FRAME_SUPERRES - const int width = cm->superres_upscaled_width; - const int height = cm->superres_upscaled_height; -#else - const int width = cm->width; - const int height = cm->height; -#endif // CONFIG_FRAME_SUPERRES - const int ntiles = - av1_get_rest_ntiles(width, height, cm->rst_info[0].restoration_tilesize, - NULL, NULL, NULL, NULL); - WienerInfo ref_wiener_info; - SgrprojInfo ref_sgrproj_info; - set_default_wiener(&ref_wiener_info); - set_default_sgrproj(&ref_sgrproj_info); - const int ntiles_uv = av1_get_rest_ntiles( - ROUND_POWER_OF_TWO(width, cm->subsampling_x), - ROUND_POWER_OF_TWO(height, cm->subsampling_y), - cm->rst_info[1].restoration_tilesize, NULL, NULL, NULL, NULL); - RestorationInfo *rsi = &cm->rst_info[0]; - if (rsi->frame_restoration_type != RESTORE_NONE) { - if (rsi->frame_restoration_type == RESTORE_SWITCHABLE) { - // RESTORE_SWITCHABLE - for (i = 0; i < ntiles; ++i) { - av1_write_token( - wb, av1_switchable_restore_tree, cm->fc->switchable_restore_prob, - &switchable_restore_encodings[rsi->restoration_type[i]]); - if (rsi->restoration_type[i] == RESTORE_WIENER) { - write_wiener_filter(&rsi->wiener_info[i], &ref_wiener_info, wb); - } else if (rsi->restoration_type[i] == RESTORE_SGRPROJ) { - write_sgrproj_filter(&rsi->sgrproj_info[i], &ref_sgrproj_info, wb); - } - } - } else if (rsi->frame_restoration_type == RESTORE_WIENER) { - for (i = 0; i < ntiles; ++i) { - aom_write(wb, rsi->restoration_type[i] != RESTORE_NONE, - RESTORE_NONE_WIENER_PROB); - if (rsi->restoration_type[i] != RESTORE_NONE) { - write_wiener_filter(&rsi->wiener_info[i], &ref_wiener_info, wb); - } - } - } else if (rsi->frame_restoration_type == RESTORE_SGRPROJ) { - for (i = 0; i < ntiles; ++i) { - aom_write(wb, rsi->restoration_type[i] != RESTORE_NONE, - RESTORE_NONE_SGRPROJ_PROB); - if (rsi->restoration_type[i] != RESTORE_NONE) { - write_sgrproj_filter(&rsi->sgrproj_info[i], &ref_sgrproj_info, wb); - } - } +static void loop_restoration_write_sb_coeffs(const AV1_COMMON *const cm, + MACROBLOCKD *xd, + aom_writer *const w, int plane, + int rtile_idx) { + const RestorationInfo *rsi = cm->rst_info + plane; + if (rsi->frame_restoration_type == RESTORE_NONE) return; + + const int wiener_win = (plane > 0) ? WIENER_WIN_CHROMA : WIENER_WIN; + WienerInfo *wiener_info = xd->wiener_info + plane; + SgrprojInfo *sgrproj_info = xd->sgrproj_info + plane; + + if (rsi->frame_restoration_type == RESTORE_SWITCHABLE) { + assert(plane == 0); + av1_write_token( + w, av1_switchable_restore_tree, cm->fc->switchable_restore_prob, + &switchable_restore_encodings[rsi->restoration_type[rtile_idx]]); + if (rsi->restoration_type[rtile_idx] == RESTORE_WIENER) { + write_wiener_filter(wiener_win, &rsi->wiener_info[rtile_idx], wiener_info, + w); + } else if (rsi->restoration_type[rtile_idx] == RESTORE_SGRPROJ) { + write_sgrproj_filter(&rsi->sgrproj_info[rtile_idx], sgrproj_info, w); } - } - for (p = 1; p < MAX_MB_PLANE; ++p) { - set_default_wiener(&ref_wiener_info); - set_default_sgrproj(&ref_sgrproj_info); - rsi = &cm->rst_info[p]; - if (rsi->frame_restoration_type == RESTORE_WIENER) { - for (i = 0; i < ntiles_uv; ++i) { - if (ntiles_uv > 1) - aom_write(wb, rsi->restoration_type[i] != RESTORE_NONE, - RESTORE_NONE_WIENER_PROB); - if (rsi->restoration_type[i] != RESTORE_NONE) { - write_wiener_filter(&rsi->wiener_info[i], &ref_wiener_info, wb); - } - } - } else if (rsi->frame_restoration_type == RESTORE_SGRPROJ) { - for (i = 0; i < ntiles_uv; ++i) { - if (ntiles_uv > 1) - aom_write(wb, rsi->restoration_type[i] != RESTORE_NONE, - RESTORE_NONE_SGRPROJ_PROB); - if (rsi->restoration_type[i] != RESTORE_NONE) { - write_sgrproj_filter(&rsi->sgrproj_info[i], &ref_sgrproj_info, wb); - } - } - } else if (rsi->frame_restoration_type != RESTORE_NONE) { - assert(0); + } else if (rsi->frame_restoration_type == RESTORE_WIENER) { + aom_write(w, rsi->restoration_type[rtile_idx] != RESTORE_NONE, + RESTORE_NONE_WIENER_PROB); + if (rsi->restoration_type[rtile_idx] != RESTORE_NONE) { + write_wiener_filter(wiener_win, &rsi->wiener_info[rtile_idx], wiener_info, + w); + } + } else if (rsi->frame_restoration_type == RESTORE_SGRPROJ) { + aom_write(w, rsi->restoration_type[rtile_idx] != RESTORE_NONE, + RESTORE_NONE_SGRPROJ_PROB); + if (rsi->restoration_type[rtile_idx] != RESTORE_NONE) { + write_sgrproj_filter(&rsi->sgrproj_info[rtile_idx], sgrproj_info, w); } } } + #endif // CONFIG_LOOP_RESTORATION static void encode_loopfilter(AV1_COMMON *cm, struct aom_write_bit_buffer *wb) { int i; struct loopfilter *lf = &cm->lf; - // Encode the loop filter level and type - aom_wb_write_literal(wb, lf->filter_level, 6); -#if CONFIG_UV_LVL - if (lf->filter_level > 0) { +// Encode the loop filter level and type +#if !CONFIG_LPF_SB +#if CONFIG_LOOPFILTER_LEVEL + aom_wb_write_literal(wb, lf->filter_level[0], 6); + aom_wb_write_literal(wb, lf->filter_level[1], 6); + if (lf->filter_level[0] || lf->filter_level[1]) { aom_wb_write_literal(wb, lf->filter_level_u, 6); aom_wb_write_literal(wb, lf->filter_level_v, 6); } -#endif +#else + aom_wb_write_literal(wb, lf->filter_level, 6); +#endif // CONFIG_LOOPFILTER_LEVEL +#endif // CONFIG_LPF_SB aom_wb_write_literal(wb, lf->sharpness_level, 3); // Write out loop filter deltas applied at the MB level based on mode or @@ -3418,12 +3535,18 @@ static void encode_loopfilter(AV1_COMMON *cm, struct aom_write_bit_buffer *wb) { #if CONFIG_CDEF static void encode_cdef(const AV1_COMMON *cm, struct aom_write_bit_buffer *wb) { int i; - aom_wb_write_literal(wb, cm->cdef_dering_damping - 5, 1); - aom_wb_write_literal(wb, cm->cdef_clpf_damping - 3, 2); +#if CONFIG_CDEF_SINGLEPASS + aom_wb_write_literal(wb, cm->cdef_pri_damping - 3, 2); + assert(cm->cdef_pri_damping == cm->cdef_sec_damping); +#else + aom_wb_write_literal(wb, cm->cdef_pri_damping - 5, 1); + aom_wb_write_literal(wb, cm->cdef_sec_damping - 3, 2); +#endif aom_wb_write_literal(wb, cm->cdef_bits, 2); for (i = 0; i < cm->nb_cdef_strengths; i++) { aom_wb_write_literal(wb, cm->cdef_strengths[i], CDEF_STRENGTH_BITS); - aom_wb_write_literal(wb, cm->cdef_uv_strengths[i], CDEF_STRENGTH_BITS); + if (cm->subsampling_x == cm->subsampling_y) + aom_wb_write_literal(wb, cm->cdef_uv_strengths[i], CDEF_STRENGTH_BITS); } } #endif @@ -3564,6 +3687,72 @@ static void fix_interp_filter(AV1_COMMON *cm, FRAME_COUNTS *counts) { } } +#if CONFIG_MAX_TILE + +// Same function as write_uniform but writing to uncompresses header wb +static void wb_write_uniform(struct aom_write_bit_buffer *wb, int n, int v) { + const int l = get_unsigned_bits(n); + const int m = (1 << l) - n; + if (l == 0) return; + if (v < m) { + aom_wb_write_literal(wb, v, l - 1); + } else { + aom_wb_write_literal(wb, m + ((v - m) >> 1), l - 1); + aom_wb_write_literal(wb, (v - m) & 1, 1); + } +} + +static void write_tile_info_max_tile(const AV1_COMMON *const cm, + struct aom_write_bit_buffer *wb) { + int width_mi = ALIGN_POWER_OF_TWO(cm->mi_cols, MAX_MIB_SIZE_LOG2); + int height_mi = ALIGN_POWER_OF_TWO(cm->mi_rows, MAX_MIB_SIZE_LOG2); + int width_sb = width_mi >> MAX_MIB_SIZE_LOG2; + int height_sb = height_mi >> MAX_MIB_SIZE_LOG2; + int size_sb, i; + + aom_wb_write_bit(wb, cm->uniform_tile_spacing_flag); + + if (cm->uniform_tile_spacing_flag) { + // Uniform spaced tiles with power-of-two number of rows and columns + // tile columns + int ones = cm->log2_tile_cols - cm->min_log2_tile_cols; + while (ones--) { + aom_wb_write_bit(wb, 1); + } + if (cm->log2_tile_cols < cm->max_log2_tile_cols) { + aom_wb_write_bit(wb, 0); + } + + // rows + ones = cm->log2_tile_rows - cm->min_log2_tile_rows; + while (ones--) { + aom_wb_write_bit(wb, 1); + } + if (cm->log2_tile_rows < cm->max_log2_tile_rows) { + aom_wb_write_bit(wb, 0); + } + } else { + // Explicit tiles with configurable tile widths and heights + // columns + for (i = 0; i < cm->tile_cols; i++) { + size_sb = cm->tile_col_start_sb[i + 1] - cm->tile_col_start_sb[i]; + wb_write_uniform(wb, AOMMIN(width_sb, MAX_TILE_WIDTH_SB), size_sb - 1); + width_sb -= size_sb; + } + assert(width_sb == 0); + + // rows + for (i = 0; i < cm->tile_rows; i++) { + size_sb = cm->tile_row_start_sb[i + 1] - cm->tile_row_start_sb[i]; + wb_write_uniform(wb, AOMMIN(height_sb, cm->max_tile_height_sb), + size_sb - 1); + height_sb -= size_sb; + } + assert(height_sb == 0); + } +} +#endif + static void write_tile_info(const AV1_COMMON *const cm, struct aom_write_bit_buffer *wb) { #if CONFIG_EXT_TILE @@ -3596,20 +3785,25 @@ static void write_tile_info(const AV1_COMMON *const cm, #endif // CONFIG_EXT_PARTITION } else { #endif // CONFIG_EXT_TILE - int min_log2_tile_cols, max_log2_tile_cols, ones; - av1_get_tile_n_bits(cm->mi_cols, &min_log2_tile_cols, &max_log2_tile_cols); - // columns - ones = cm->log2_tile_cols - min_log2_tile_cols; - while (ones--) aom_wb_write_bit(wb, 1); +#if CONFIG_MAX_TILE + write_tile_info_max_tile(cm, wb); +#else + int min_log2_tile_cols, max_log2_tile_cols, ones; + av1_get_tile_n_bits(cm->mi_cols, &min_log2_tile_cols, &max_log2_tile_cols); - if (cm->log2_tile_cols < max_log2_tile_cols) aom_wb_write_bit(wb, 0); + // columns + ones = cm->log2_tile_cols - min_log2_tile_cols; + while (ones--) aom_wb_write_bit(wb, 1); - // rows - aom_wb_write_bit(wb, cm->log2_tile_rows != 0); - if (cm->log2_tile_rows != 0) aom_wb_write_bit(wb, cm->log2_tile_rows != 1); + if (cm->log2_tile_cols < max_log2_tile_cols) aom_wb_write_bit(wb, 0); + + // rows + aom_wb_write_bit(wb, cm->log2_tile_rows != 0); + if (cm->log2_tile_rows != 0) aom_wb_write_bit(wb, cm->log2_tile_rows != 1); +#endif #if CONFIG_DEPENDENT_HORZTILES - if (cm->log2_tile_rows != 0) aom_wb_write_bit(wb, cm->dependent_horz_tiles); + if (cm->tile_rows > 1) aom_wb_write_bit(wb, cm->dependent_horz_tiles); #endif #if CONFIG_EXT_TILE } @@ -3620,10 +3814,30 @@ static void write_tile_info(const AV1_COMMON *const cm, #endif // CONFIG_LOOPFILTERING_ACROSS_TILES } -static int get_refresh_mask(AV1_COMP *cpi) { +#if CONFIG_EXT_REFS +#if USE_GF16_MULTI_LAYER +static int get_refresh_mask_gf16(AV1_COMP *cpi) { int refresh_mask = 0; + if (cpi->refresh_last_frame || cpi->refresh_golden_frame || + cpi->refresh_bwd_ref_frame || cpi->refresh_alt2_ref_frame || + cpi->refresh_alt_ref_frame) { + assert(cpi->refresh_fb_idx >= 0 && cpi->refresh_fb_idx < REF_FRAMES); + refresh_mask |= (1 << cpi->refresh_fb_idx); + } + + return refresh_mask; +} +#endif // USE_GF16_MULTI_LAYER +#endif // CONFIG_EXT_REFS + +static int get_refresh_mask(AV1_COMP *cpi) { + int refresh_mask = 0; #if CONFIG_EXT_REFS +#if USE_GF16_MULTI_LAYER + if (cpi->rc.baseline_gf_interval == 16) return get_refresh_mask_gf16(cpi); +#endif // USE_GF16_MULTI_LAYER + // NOTE(zoeliu): When LAST_FRAME is to get refreshed, the decoder will be // notified to get LAST3_FRAME refreshed and then the virtual indexes for all // the 3 LAST reference frames will be updated accordingly, i.e.: @@ -3634,13 +3848,10 @@ static int get_refresh_mask(AV1_COMP *cpi) { // LAST3_FRAME. refresh_mask |= (cpi->refresh_last_frame << cpi->lst_fb_idxes[LAST_REF_FRAMES - 1]); - if (cpi->rc.is_bwd_ref_frame && cpi->num_extra_arfs) { - // We have swapped the virtual indices - refresh_mask |= (cpi->refresh_bwd_ref_frame << cpi->arf_map[0]); - } else { - refresh_mask |= (cpi->refresh_bwd_ref_frame << cpi->bwd_fb_idx); - } -#else + + refresh_mask |= (cpi->refresh_bwd_ref_frame << cpi->bwd_fb_idx); + refresh_mask |= (cpi->refresh_alt2_ref_frame << cpi->alt2_fb_idx); +#else // !CONFIG_EXT_REFS refresh_mask |= (cpi->refresh_last_frame << cpi->lst_fb_idx); #endif // CONFIG_EXT_REFS @@ -3658,9 +3869,8 @@ static int get_refresh_mask(AV1_COMP *cpi) { return refresh_mask | (cpi->refresh_golden_frame << cpi->alt_fb_idx); } else { #if CONFIG_EXT_REFS - const GF_GROUP *const gf_group = &cpi->twopass.gf_group; - int arf_idx = cpi->arf_map[gf_group->arf_update_idx[gf_group->index]]; -#else + const int arf_idx = cpi->alt_fb_idx; +#else // !CONFIG_EXT_REFS int arf_idx = cpi->alt_fb_idx; if ((cpi->oxcf.pass == 2) && cpi->multi_arf_allowed) { const GF_GROUP *const gf_group = &cpi->twopass.gf_group; @@ -3725,15 +3935,12 @@ static INLINE int find_identical_tile( } #endif // CONFIG_EXT_TILE +#if !CONFIG_OBU || CONFIG_EXT_TILE static uint32_t write_tiles(AV1_COMP *const cpi, uint8_t *const dst, unsigned int *max_tile_size, unsigned int *max_tile_col_size) { const AV1_COMMON *const cm = &cpi->common; -#if CONFIG_ANS - struct BufAnsCoder *buf_ans = &cpi->buf_ans; -#else aom_writer mode_bc; -#endif // CONFIG_ANS int tile_row, tile_col; TOKENEXTRA *(*const tok_buffers)[MAX_TILE_COLS] = cpi->tile_tok; TileBufferEnc(*const tile_buffers)[MAX_TILE_COLS] = cpi->tile_buffers; @@ -3744,7 +3951,7 @@ static uint32_t write_tiles(AV1_COMP *const cpi, uint8_t *const dst, const int have_tiles = tile_cols * tile_rows > 1; struct aom_write_bit_buffer wb = { dst, 0 }; const int n_log2_tiles = cm->log2_tile_rows + cm->log2_tile_cols; - uint32_t comp_hdr_size; + uint32_t compressed_hdr_size; // Fixed size tile groups for the moment const int num_tg_hdrs = cm->num_tg; const int tg_size = @@ -3759,7 +3966,6 @@ static uint32_t write_tiles(AV1_COMP *const cpi, uint8_t *const dst, int tile_size_bytes = 4; int tile_col_size_bytes; uint32_t uncompressed_hdr_size = 0; - struct aom_write_bit_buffer comp_hdr_len_wb; struct aom_write_bit_buffer tg_params_wb; struct aom_write_bit_buffer tile_size_bytes_wb; uint32_t saved_offset; @@ -3806,19 +4012,14 @@ static uint32_t write_tiles(AV1_COMP *const cpi, uint8_t *const dst, cpi->td.mb.pvq_q = &this_tile->pvq_q; cpi->td.mb.daala_enc.state.adapt = &this_tile->tctx.pvq_context; #endif // CONFIG_PVQ -#if !CONFIG_ANS +#if CONFIG_ANS + mode_bc.size = 1 << cpi->common.ans_window_size_log2; +#endif aom_start_encode(&mode_bc, buf->data + data_offset); write_modes(cpi, &tile_info, &mode_bc, &tok, tok_end); assert(tok == tok_end); aom_stop_encode(&mode_bc); tile_size = mode_bc.pos; -#else - buf_ans_write_init(buf_ans, buf->data + data_offset); - write_modes(cpi, &tile_info, buf_ans, &tok, tok_end); - assert(tok == tok_end); - aom_buf_ans_flush(buf_ans); - tile_size = buf_ans_write_end(buf_ans); -#endif // !CONFIG_ANS #if CONFIG_PVQ cpi->td.mb.pvq_q = NULL; #endif @@ -3866,7 +4067,7 @@ static uint32_t write_tiles(AV1_COMP *const cpi, uint8_t *const dst, } } else { #endif // CONFIG_EXT_TILE - write_uncompressed_header(cpi, &wb); + write_uncompressed_header_frame(cpi, &wb); #if CONFIG_EXT_REFS if (cm->show_existing_frame) { @@ -3887,14 +4088,22 @@ static uint32_t write_tiles(AV1_COMP *const cpi, uint8_t *const dst, aom_wb_overwrite_literal(&wb, (1 << n_log2_tiles) - 1, n_log2_tiles); } - /* Write a placeholder for the compressed header length */ - comp_hdr_len_wb = wb; - aom_wb_write_literal(&wb, 0, 16); + if (!use_compressed_header(cm)) { + uncompressed_hdr_size = aom_wb_bytes_written(&wb); + compressed_hdr_size = 0; + } else { + /* Write a placeholder for the compressed header length */ + struct aom_write_bit_buffer comp_hdr_len_wb = wb; + aom_wb_write_literal(&wb, 0, 16); + + uncompressed_hdr_size = aom_wb_bytes_written(&wb); + compressed_hdr_size = + write_compressed_header(cpi, dst + uncompressed_hdr_size); + aom_wb_overwrite_literal(&comp_hdr_len_wb, (int)(compressed_hdr_size), + 16); + } - uncompressed_hdr_size = aom_wb_bytes_written(&wb); - comp_hdr_size = write_compressed_header(cpi, dst + uncompressed_hdr_size); - aom_wb_overwrite_literal(&comp_hdr_len_wb, (int)(comp_hdr_size), 16); - hdr_size = uncompressed_hdr_size + comp_hdr_size; + hdr_size = uncompressed_hdr_size + compressed_hdr_size; total_size += hdr_size; for (tile_row = 0; tile_row < tile_rows; tile_row++) { @@ -3938,7 +4147,7 @@ static uint32_t write_tiles(AV1_COMP *const cpi, uint8_t *const dst, // Copy compressed header memmove(dst + old_total_size + uncompressed_hdr_size, dst + uncompressed_hdr_size, - comp_hdr_size * sizeof(uint8_t)); + compressed_hdr_size * sizeof(uint8_t)); total_size += hdr_size; tile_count = 1; curr_tg_data_size = hdr_size + tile_size + 4; @@ -3957,7 +4166,7 @@ static uint32_t write_tiles(AV1_COMP *const cpi, uint8_t *const dst, // Copy compressed header memmove(dst + total_size + uncompressed_hdr_size, dst + uncompressed_hdr_size, - comp_hdr_size * sizeof(uint8_t)); + compressed_hdr_size * sizeof(uint8_t)); total_size += hdr_size; tile_count = 0; curr_tg_data_size = hdr_size; @@ -3982,22 +4191,24 @@ static uint32_t write_tiles(AV1_COMP *const cpi, uint8_t *const dst, cpi->td.mb.daala_enc.state.adapt = &this_tile->tctx.pvq_context; #endif // CONFIG_PVQ #if CONFIG_ANS - buf_ans_write_init(buf_ans, dst + total_size); - write_modes(cpi, &tile_info, buf_ans, &tok, tok_end); - assert(tok == tok_end); - aom_buf_ans_flush(buf_ans); - tile_size = buf_ans_write_end(buf_ans); -#else - aom_start_encode(&mode_bc, dst + total_size); - write_modes(cpi, &tile_info, &mode_bc, &tok, tok_end); + mode_bc.size = 1 << cpi->common.ans_window_size_log2; +#endif // CONFIG_ANS +#if CONFIG_LOOP_RESTORATION + for (int p = 0; p < MAX_MB_PLANE; ++p) { + set_default_wiener(cpi->td.mb.e_mbd.wiener_info + p); + set_default_sgrproj(cpi->td.mb.e_mbd.sgrproj_info + p); + } +#endif // CONFIG_LOOP_RESTORATION + + aom_start_encode(&mode_bc, dst + total_size); + write_modes(cpi, &tile_info, &mode_bc, &tok, tok_end); #if !CONFIG_LV_MAP #if !CONFIG_PVQ - assert(tok == tok_end); + assert(tok == tok_end); #endif // !CONFIG_PVQ #endif // !CONFIG_LV_MAP - aom_stop_encode(&mode_bc); - tile_size = mode_bc.pos; -#endif // CONFIG_ANS + aom_stop_encode(&mode_bc); + tile_size = mode_bc.pos; #if CONFIG_PVQ cpi->td.mb.pvq_q = NULL; #endif @@ -4018,18 +4229,20 @@ static uint32_t write_tiles(AV1_COMP *const cpi, uint8_t *const dst, } // Write the final tile group size if (n_log2_tiles) { - aom_wb_overwrite_literal(&tg_params_wb, (1 << n_log2_tiles) - tile_count, - n_log2_tiles); + aom_wb_overwrite_literal( + &tg_params_wb, (tile_cols * tile_rows) - tile_count, n_log2_tiles); aom_wb_overwrite_literal(&tg_params_wb, tile_count - 1, n_log2_tiles); } // Remux if possible. TODO (Thomas Davies): do this for more than one tile // group if (have_tiles && tg_count == 1) { - int data_size = total_size - (uncompressed_hdr_size + comp_hdr_size); - data_size = remux_tiles(cm, dst + uncompressed_hdr_size + comp_hdr_size, - data_size, *max_tile_size, *max_tile_col_size, - &tile_size_bytes, &tile_col_size_bytes); - total_size = data_size + uncompressed_hdr_size + comp_hdr_size; + int data_size = + total_size - (uncompressed_hdr_size + compressed_hdr_size); + data_size = + remux_tiles(cm, dst + uncompressed_hdr_size + compressed_hdr_size, + data_size, *max_tile_size, *max_tile_col_size, + &tile_size_bytes, &tile_col_size_bytes); + total_size = data_size + uncompressed_hdr_size + compressed_hdr_size; aom_wb_overwrite_literal(&tile_size_bytes_wb, tile_size_bytes - 1, 2); } @@ -4038,6 +4251,7 @@ static uint32_t write_tiles(AV1_COMP *const cpi, uint8_t *const dst, #endif // CONFIG_EXT_TILE return (uint32_t)total_size; } +#endif static void write_render_size(const AV1_COMMON *cm, struct aom_write_bit_buffer *wb) { @@ -4053,12 +4267,12 @@ static void write_render_size(const AV1_COMMON *cm, static void write_superres_scale(const AV1_COMMON *const cm, struct aom_write_bit_buffer *wb) { // First bit is whether to to scale or not - if (cm->superres_scale_numerator == SCALE_DENOMINATOR) { + if (cm->superres_scale_denominator == SCALE_NUMERATOR) { aom_wb_write_bit(wb, 0); // no scaling } else { aom_wb_write_bit(wb, 1); // scaling, write scale factor aom_wb_write_literal( - wb, cm->superres_scale_numerator - SUPERRES_SCALE_NUMERATOR_MIN, + wb, cm->superres_scale_denominator - SUPERRES_SCALE_DENOMINATOR_MIN, SUPERRES_SCALE_BITS); } } @@ -4109,12 +4323,6 @@ static void write_frame_size_with_refs(AV1_COMP *cpi, if (!found) write_frame_size(cm, wb); } -static void write_sync_code(struct aom_write_bit_buffer *wb) { - aom_wb_write_literal(wb, AV1_SYNC_CODE_0, 8); - aom_wb_write_literal(wb, AV1_SYNC_CODE_1, 8); - aom_wb_write_literal(wb, AV1_SYNC_CODE_2, 8); -} - static void write_profile(BITSTREAM_PROFILE profile, struct aom_write_bit_buffer *wb) { switch (profile) { @@ -4161,11 +4369,9 @@ static void write_bitdepth_colorspace_sampling( } #if CONFIG_REFERENCE_BUFFER -void write_sequence_header( -#if CONFIG_EXT_TILE - AV1_COMMON *const cm, -#endif // CONFIG_EXT_TILE - SequenceHeader *seq_params) { +void write_sequence_header(AV1_COMMON *const cm, + struct aom_write_bit_buffer *wb) { + SequenceHeader *seq_params = &cm->seq_params; /* Placeholder for actually writing to the bitstream */ seq_params->frame_id_numbers_present_flag = #if CONFIG_EXT_TILE @@ -4174,10 +4380,29 @@ void write_sequence_header( FRAME_ID_NUMBERS_PRESENT_FLAG; seq_params->frame_id_length_minus7 = FRAME_ID_LENGTH_MINUS7; seq_params->delta_frame_id_length_minus2 = DELTA_FRAME_ID_LENGTH_MINUS2; + + aom_wb_write_bit(wb, seq_params->frame_id_numbers_present_flag); + if (seq_params->frame_id_numbers_present_flag) { + aom_wb_write_literal(wb, seq_params->frame_id_length_minus7, 4); + aom_wb_write_literal(wb, seq_params->delta_frame_id_length_minus2, 4); + } +} +#endif // CONFIG_REFERENCE_BUFFER + +static void write_sb_size(const AV1_COMMON *cm, + struct aom_write_bit_buffer *wb) { + (void)cm; + (void)wb; + assert(cm->mib_size == mi_size_wide[cm->sb_size]); + assert(cm->mib_size == 1 << cm->mib_size_log2); +#if CONFIG_EXT_PARTITION + assert(cm->sb_size == BLOCK_128X128 || cm->sb_size == BLOCK_64X64); + aom_wb_write_bit(wb, cm->sb_size == BLOCK_128X128 ? 1 : 0); +#else + assert(cm->sb_size == BLOCK_64X64); +#endif // CONFIG_EXT_PARTITION } -#endif -#if CONFIG_EXT_INTER static void write_compound_tools(const AV1_COMMON *cm, struct aom_write_bit_buffer *wb) { (void)cm; @@ -4201,22 +4426,129 @@ static void write_compound_tools(const AV1_COMMON *cm, } #endif // CONFIG_WEDGE || CONFIG_COMPOUND_SEGMENT } -#endif // CONFIG_EXT_INTER -static void write_uncompressed_header(AV1_COMP *cpi, - struct aom_write_bit_buffer *wb) { - AV1_COMMON *const cm = &cpi->common; - MACROBLOCKD *const xd = &cpi->td.mb.e_mbd; +#if CONFIG_GLOBAL_MOTION +static void write_global_motion_params(const WarpedMotionParams *params, + const WarpedMotionParams *ref_params, + struct aom_write_bit_buffer *wb, + int allow_hp) { + TransformationType type = params->wmtype; + int trans_bits; + int trans_prec_diff; -#if CONFIG_REFERENCE_BUFFER - /* TODO: Move outside frame loop or inside key-frame branch */ - write_sequence_header( -#if CONFIG_EXT_TILE - cm, -#endif // CONFIG_EXT_TILE - &cpi->seq_params); + aom_wb_write_bit(wb, type != IDENTITY); + if (type != IDENTITY) { +#if GLOBAL_TRANS_TYPES > 4 + aom_wb_write_literal(wb, type - 1, GLOBAL_TYPE_BITS); +#else + aom_wb_write_bit(wb, type == ROTZOOM); + if (type != ROTZOOM) aom_wb_write_bit(wb, type == TRANSLATION); +#endif // GLOBAL_TRANS_TYPES > 4 + } + + switch (type) { + case HOMOGRAPHY: + case HORTRAPEZOID: + case VERTRAPEZOID: + if (type != HORTRAPEZOID) + aom_wb_write_signed_primitive_refsubexpfin( + wb, GM_ROW3HOMO_MAX + 1, SUBEXPFIN_K, + (ref_params->wmmat[6] >> GM_ROW3HOMO_PREC_DIFF), + (params->wmmat[6] >> GM_ROW3HOMO_PREC_DIFF)); + if (type != VERTRAPEZOID) + aom_wb_write_signed_primitive_refsubexpfin( + wb, GM_ROW3HOMO_MAX + 1, SUBEXPFIN_K, + (ref_params->wmmat[7] >> GM_ROW3HOMO_PREC_DIFF), + (params->wmmat[7] >> GM_ROW3HOMO_PREC_DIFF)); + // fallthrough intended + case AFFINE: + case ROTZOOM: + aom_wb_write_signed_primitive_refsubexpfin( + wb, GM_ALPHA_MAX + 1, SUBEXPFIN_K, + (ref_params->wmmat[2] >> GM_ALPHA_PREC_DIFF) - + (1 << GM_ALPHA_PREC_BITS), + (params->wmmat[2] >> GM_ALPHA_PREC_DIFF) - (1 << GM_ALPHA_PREC_BITS)); + if (type != VERTRAPEZOID) + aom_wb_write_signed_primitive_refsubexpfin( + wb, GM_ALPHA_MAX + 1, SUBEXPFIN_K, + (ref_params->wmmat[3] >> GM_ALPHA_PREC_DIFF), + (params->wmmat[3] >> GM_ALPHA_PREC_DIFF)); + if (type >= AFFINE) { + if (type != HORTRAPEZOID) + aom_wb_write_signed_primitive_refsubexpfin( + wb, GM_ALPHA_MAX + 1, SUBEXPFIN_K, + (ref_params->wmmat[4] >> GM_ALPHA_PREC_DIFF), + (params->wmmat[4] >> GM_ALPHA_PREC_DIFF)); + aom_wb_write_signed_primitive_refsubexpfin( + wb, GM_ALPHA_MAX + 1, SUBEXPFIN_K, + (ref_params->wmmat[5] >> GM_ALPHA_PREC_DIFF) - + (1 << GM_ALPHA_PREC_BITS), + (params->wmmat[5] >> GM_ALPHA_PREC_DIFF) - + (1 << GM_ALPHA_PREC_BITS)); + } + // fallthrough intended + case TRANSLATION: + trans_bits = (type == TRANSLATION) ? GM_ABS_TRANS_ONLY_BITS - !allow_hp + : GM_ABS_TRANS_BITS; + trans_prec_diff = (type == TRANSLATION) + ? GM_TRANS_ONLY_PREC_DIFF + !allow_hp + : GM_TRANS_PREC_DIFF; + aom_wb_write_signed_primitive_refsubexpfin( + wb, (1 << trans_bits) + 1, SUBEXPFIN_K, + (ref_params->wmmat[0] >> trans_prec_diff), + (params->wmmat[0] >> trans_prec_diff)); + aom_wb_write_signed_primitive_refsubexpfin( + wb, (1 << trans_bits) + 1, SUBEXPFIN_K, + (ref_params->wmmat[1] >> trans_prec_diff), + (params->wmmat[1] >> trans_prec_diff)); + break; + case IDENTITY: break; + default: assert(0); + } +} + +static void write_global_motion(AV1_COMP *cpi, + struct aom_write_bit_buffer *wb) { + AV1_COMMON *const cm = &cpi->common; + int frame; + for (frame = LAST_FRAME; frame <= ALTREF_FRAME; ++frame) { + const WarpedMotionParams *ref_params = + cm->error_resilient_mode ? &default_warp_params + : &cm->prev_frame->global_motion[frame]; + write_global_motion_params(&cm->global_motion[frame], ref_params, wb, + cm->allow_high_precision_mv); + // TODO(sarahparker, debargha): The logic in the commented out code below + // does not work currently and causes mismatches when resize is on. + // Fix it before turning the optimization back on. + /* + YV12_BUFFER_CONFIG *ref_buf = get_ref_frame_buffer(cpi, frame); + if (cpi->source->y_crop_width == ref_buf->y_crop_width && + cpi->source->y_crop_height == ref_buf->y_crop_height) { + write_global_motion_params(&cm->global_motion[frame], + &cm->prev_frame->global_motion[frame], wb, + cm->allow_high_precision_mv); + } else { + assert(cm->global_motion[frame].wmtype == IDENTITY && + "Invalid warp type for frames of different resolutions"); + } + */ + /* + printf("Frame %d/%d: Enc Ref %d: %d %d %d %d\n", + cm->current_video_frame, cm->show_frame, frame, + cm->global_motion[frame].wmmat[0], + cm->global_motion[frame].wmmat[1], cm->global_motion[frame].wmmat[2], + cm->global_motion[frame].wmmat[3]); + */ + } +} #endif +#if !CONFIG_OBU +static void write_uncompressed_header_frame(AV1_COMP *cpi, + struct aom_write_bit_buffer *wb) { + AV1_COMMON *const cm = &cpi->common; + MACROBLOCKD *const xd = &cpi->td.mb.e_mbd; + aom_wb_write_literal(wb, AOM_FRAME_MARKER, 2); write_profile(cm->profile, wb); @@ -4244,8 +4576,8 @@ static void write_uncompressed_header(AV1_COMP *cpi, aom_wb_write_literal(wb, cpi->existing_fb_idx_to_show, 3); #if CONFIG_REFERENCE_BUFFER - if (cpi->seq_params.frame_id_numbers_present_flag) { - int frame_id_len = cpi->seq_params.frame_id_length_minus7 + 7; + if (cm->seq_params.frame_id_numbers_present_flag) { + int frame_id_len = cm->seq_params.frame_id_length_minus7 + 7; int display_frame_id = cm->ref_frame_id[cpi->existing_fb_idx_to_show]; aom_wb_write_literal(wb, display_frame_id, frame_id_len); /* Add a zero byte to prevent emulation of superframe marker */ @@ -4253,7 +4585,7 @@ static void write_uncompressed_header(AV1_COMP *cpi, /* Consider to have this logic only one place */ aom_wb_write_literal(wb, 0, 8); } -#endif +#endif // CONFIG_REFERENCE_BUFFER return; } else { @@ -4265,33 +4597,46 @@ static void write_uncompressed_header(AV1_COMP *cpi, aom_wb_write_bit(wb, cm->frame_type); aom_wb_write_bit(wb, cm->show_frame); + if (cm->frame_type != KEY_FRAME) + if (!cm->show_frame) aom_wb_write_bit(wb, cm->intra_only); aom_wb_write_bit(wb, cm->error_resilient_mode); + if (frame_is_intra_only(cm)) { +#if CONFIG_REFERENCE_BUFFER + write_sequence_header(cm, wb); +#endif // CONFIG_REFERENCE_BUFFER + } #if CONFIG_REFERENCE_BUFFER cm->invalid_delta_frame_id_minus1 = 0; - if (cpi->seq_params.frame_id_numbers_present_flag) { - int frame_id_len = cpi->seq_params.frame_id_length_minus7 + 7; + if (cm->seq_params.frame_id_numbers_present_flag) { + int frame_id_len = cm->seq_params.frame_id_length_minus7 + 7; aom_wb_write_literal(wb, cm->current_frame_id, frame_id_len); } -#endif - +#endif // CONFIG_REFERENCE_BUFFER if (cm->frame_type == KEY_FRAME) { - write_sync_code(wb); write_bitdepth_colorspace_sampling(cm, wb); write_frame_size(cm, wb); + write_sb_size(cm, wb); + #if CONFIG_ANS && ANS_MAX_SYMBOLS assert(cpi->common.ans_window_size_log2 >= 8); assert(cpi->common.ans_window_size_log2 < 24); aom_wb_write_literal(wb, cpi->common.ans_window_size_log2 - 8, 4); #endif // CONFIG_ANS && ANS_MAX_SYMBOLS -#if CONFIG_PALETTE || CONFIG_INTRABC aom_wb_write_bit(wb, cm->allow_screen_content_tools); -#endif // CONFIG_PALETTE || CONFIG_INTRABC +#if CONFIG_AMVR + if (cm->allow_screen_content_tools) { + if (cm->seq_mv_precision_level == 2) { + aom_wb_write_bit(wb, 1); + } else { + aom_wb_write_bit(wb, 0); + aom_wb_write_bit(wb, cm->seq_mv_precision_level == 0); + } + } +#endif } else { - if (!cm->show_frame) aom_wb_write_bit(wb, cm->intra_only); -#if CONFIG_PALETTE || CONFIG_INTRABC if (cm->intra_only) aom_wb_write_bit(wb, cm->allow_screen_content_tools); -#endif // CONFIG_PALETTE || CONFIG_INTRABC +#if !CONFIG_NO_FRAME_CONTEXT_SIGNALING if (!cm->error_resilient_mode) { if (cm->intra_only) { aom_wb_write_bit(wb, @@ -4304,13 +4649,12 @@ static void write_uncompressed_header(AV1_COMP *cpi, cm->reset_frame_context == RESET_FRAME_CONTEXT_ALL); } } - +#endif #if CONFIG_EXT_REFS cpi->refresh_frame_mask = get_refresh_mask(cpi); #endif // CONFIG_EXT_REFS if (cm->intra_only) { - write_sync_code(wb); write_bitdepth_colorspace_sampling(cm, wb); #if CONFIG_EXT_REFS @@ -4346,12 +4690,14 @@ static void write_uncompressed_header(AV1_COMP *cpi, assert(get_ref_frame_map_idx(cpi, ref_frame) != INVALID_IDX); aom_wb_write_literal(wb, get_ref_frame_map_idx(cpi, ref_frame), REF_FRAMES_LOG2); +#if !CONFIG_FRAME_SIGN_BIAS aom_wb_write_bit(wb, cm->ref_frame_sign_bias[ref_frame]); +#endif // !CONFIG_FRAME_SIGN_BIAS #if CONFIG_REFERENCE_BUFFER - if (cpi->seq_params.frame_id_numbers_present_flag) { + if (cm->seq_params.frame_id_numbers_present_flag) { int i = get_ref_frame_map_idx(cpi, ref_frame); - int frame_id_len = cpi->seq_params.frame_id_length_minus7 + 7; - int diff_len = cpi->seq_params.delta_frame_id_length_minus2 + 2; + int frame_id_len = cm->seq_params.frame_id_length_minus7 + 7; + int diff_len = cm->seq_params.delta_frame_id_length_minus2 + 2; int delta_frame_id_minus1 = ((cm->current_frame_id - cm->ref_frame_id[i] + (1 << frame_id_len)) % @@ -4362,8 +4708,24 @@ static void write_uncompressed_header(AV1_COMP *cpi, cm->invalid_delta_frame_id_minus1 = 1; aom_wb_write_literal(wb, delta_frame_id_minus1, diff_len); } -#endif +#endif // CONFIG_REFERENCE_BUFFER + } + +#if CONFIG_FRAME_SIGN_BIAS +#define FRAME_SIGN_BIAS_DEBUG 0 +#if FRAME_SIGN_BIAS_DEBUG + { + printf("\n\nENCODER: Frame=%d, show_frame=%d:", cm->current_video_frame, + cm->show_frame); + for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) { + printf(" sign_bias[%d]=%d", ref_frame, + cm->ref_frame_sign_bias[ref_frame]); + } + printf("\n"); } +#endif // FRAME_SIGN_BIAS_DEBUG +#undef FRAME_SIGN_BIAS_DEBUG +#endif // CONFIG_FRAME_SIGN_BIAS #if CONFIG_FRAME_SIZE if (cm->error_resilient_mode == 0) { @@ -4375,42 +4737,55 @@ static void write_uncompressed_header(AV1_COMP *cpi, write_frame_size_with_refs(cpi, wb); #endif +#if CONFIG_AMVR + if (cm->seq_mv_precision_level == 2) { + aom_wb_write_bit(wb, cm->cur_frame_mv_precision_level == 0); + } +#endif aom_wb_write_bit(wb, cm->allow_high_precision_mv); fix_interp_filter(cm, cpi->td.counts); write_frame_interp_filter(cm->interp_filter, wb); #if CONFIG_TEMPMV_SIGNALING - if (!cm->error_resilient_mode) { + if (frame_might_use_prev_frame_mvs(cm)) { aom_wb_write_bit(wb, cm->use_prev_frame_mvs); } #endif } } -#if CONFIG_REFERENCE_BUFFER - cm->refresh_mask = cm->frame_type == KEY_FRAME ? 0xFF : get_refresh_mask(cpi); +#if CONFIG_FRAME_MARKER + if (cm->show_frame == 0) { + int arf_offset = AOMMIN( + (MAX_GF_INTERVAL - 1), + cpi->twopass.gf_group.arf_src_offset[cpi->twopass.gf_group.index]); +#if CONFIG_EXT_REFS + int brf_offset = + cpi->twopass.gf_group.brf_src_offset[cpi->twopass.gf_group.index]; + + arf_offset = AOMMIN((MAX_GF_INTERVAL - 1), arf_offset + brf_offset); +#endif + aom_wb_write_literal(wb, arf_offset, 4); + } #endif +#if CONFIG_REFERENCE_BUFFER + if (cm->seq_params.frame_id_numbers_present_flag) { + cm->refresh_mask = + cm->frame_type == KEY_FRAME ? 0xFF : get_refresh_mask(cpi); + } +#endif // CONFIG_REFERENCE_BUFFER + if (!cm->error_resilient_mode) { aom_wb_write_bit( wb, cm->refresh_frame_context == REFRESH_FRAME_CONTEXT_FORWARD); } - +#if !CONFIG_NO_FRAME_CONTEXT_SIGNALING aom_wb_write_literal(wb, cm->frame_context_idx, FRAME_CONTEXTS_LOG2); - - assert(cm->mib_size == mi_size_wide[cm->sb_size]); - assert(cm->mib_size == 1 << cm->mib_size_log2); -#if CONFIG_EXT_PARTITION - assert(cm->sb_size == BLOCK_128X128 || cm->sb_size == BLOCK_64X64); - aom_wb_write_bit(wb, cm->sb_size == BLOCK_128X128 ? 1 : 0); -#else - assert(cm->sb_size == BLOCK_64X64); -#endif // CONFIG_EXT_PARTITION - +#endif encode_loopfilter(cm, wb); encode_quantization(cm, wb); encode_segmentation(cm, xd, wb); -#if CONFIG_DELTA_Q { int i; struct segmentation *const seg = &cm->seg; @@ -4434,12 +4809,16 @@ static void write_uncompressed_header(AV1_COMP *cpi, if (cm->delta_lf_present_flag) { aom_wb_write_literal(wb, OD_ILOG_NZ(cm->delta_lf_res) - 1, 2); xd->prev_delta_lf_from_base = 0; +#if CONFIG_LOOPFILTER_LEVEL + aom_wb_write_bit(wb, cm->delta_lf_multi); + for (int lf_id = 0; lf_id < FRAME_LF_COUNT; ++lf_id) + xd->prev_delta_lf[lf_id] = 0; +#endif // CONFIG_LOOPFILTER_LEVEL } #endif // CONFIG_EXT_DELTA_Q } } } -#endif #if CONFIG_CDEF if (!cm->all_lossless) { encode_cdef(cm, wb); @@ -4461,113 +4840,372 @@ static void write_uncompressed_header(AV1_COMP *cpi, if (!use_hybrid_pred) aom_wb_write_bit(wb, use_compound_pred); #endif // !CONFIG_REF_ADAPT } -#if CONFIG_EXT_INTER write_compound_tools(cm, wb); -#endif // CONFIG_EXT_INTER #if CONFIG_EXT_TX aom_wb_write_bit(wb, cm->reduced_tx_set_used); #endif // CONFIG_EXT_TX - write_tile_info(cm, wb); -} +#if CONFIG_ADAPT_SCAN + aom_wb_write_bit(wb, cm->use_adapt_scan); +#endif #if CONFIG_GLOBAL_MOTION -static void write_global_motion_params(WarpedMotionParams *params, - WarpedMotionParams *ref_params, - aom_writer *w, int allow_hp) { - TransformationType type = params->wmtype; - int trans_bits; - int trans_prec_diff; - aom_write_bit(w, type != IDENTITY); - if (type != IDENTITY) aom_write_literal(w, type - 1, GLOBAL_TYPE_BITS); + if (!frame_is_intra_only(cm)) write_global_motion(cpi, wb); +#endif // CONFIG_GLOBAL_MOTION - switch (type) { - case HOMOGRAPHY: - case HORTRAPEZOID: - case VERTRAPEZOID: - if (type != HORTRAPEZOID) - aom_write_signed_primitive_refsubexpfin( - w, GM_ROW3HOMO_MAX + 1, SUBEXPFIN_K, - (ref_params->wmmat[6] >> GM_ROW3HOMO_PREC_DIFF), - (params->wmmat[6] >> GM_ROW3HOMO_PREC_DIFF)); - if (type != VERTRAPEZOID) - aom_write_signed_primitive_refsubexpfin( - w, GM_ROW3HOMO_MAX + 1, SUBEXPFIN_K, - (ref_params->wmmat[7] >> GM_ROW3HOMO_PREC_DIFF), - (params->wmmat[7] >> GM_ROW3HOMO_PREC_DIFF)); - // fallthrough intended - case AFFINE: - case ROTZOOM: - aom_write_signed_primitive_refsubexpfin( - w, GM_ALPHA_MAX + 1, SUBEXPFIN_K, - (ref_params->wmmat[2] >> GM_ALPHA_PREC_DIFF) - - (1 << GM_ALPHA_PREC_BITS), - (params->wmmat[2] >> GM_ALPHA_PREC_DIFF) - (1 << GM_ALPHA_PREC_BITS)); - if (type != VERTRAPEZOID) - aom_write_signed_primitive_refsubexpfin( - w, GM_ALPHA_MAX + 1, SUBEXPFIN_K, - (ref_params->wmmat[3] >> GM_ALPHA_PREC_DIFF), - (params->wmmat[3] >> GM_ALPHA_PREC_DIFF)); - if (type >= AFFINE) { - if (type != HORTRAPEZOID) - aom_write_signed_primitive_refsubexpfin( - w, GM_ALPHA_MAX + 1, SUBEXPFIN_K, - (ref_params->wmmat[4] >> GM_ALPHA_PREC_DIFF), - (params->wmmat[4] >> GM_ALPHA_PREC_DIFF)); - aom_write_signed_primitive_refsubexpfin( - w, GM_ALPHA_MAX + 1, SUBEXPFIN_K, - (ref_params->wmmat[5] >> GM_ALPHA_PREC_DIFF) - - (1 << GM_ALPHA_PREC_BITS), - (params->wmmat[5] >> GM_ALPHA_PREC_DIFF) - - (1 << GM_ALPHA_PREC_BITS)); - } - // fallthrough intended - case TRANSLATION: - trans_bits = (type == TRANSLATION) ? GM_ABS_TRANS_ONLY_BITS - !allow_hp - : GM_ABS_TRANS_BITS; - trans_prec_diff = (type == TRANSLATION) - ? GM_TRANS_ONLY_PREC_DIFF + !allow_hp - : GM_TRANS_PREC_DIFF; - aom_write_signed_primitive_refsubexpfin( - w, (1 << trans_bits) + 1, SUBEXPFIN_K, - (ref_params->wmmat[0] >> trans_prec_diff), - (params->wmmat[0] >> trans_prec_diff)); - aom_write_signed_primitive_refsubexpfin( - w, (1 << trans_bits) + 1, SUBEXPFIN_K, - (ref_params->wmmat[1] >> trans_prec_diff), - (params->wmmat[1] >> trans_prec_diff)); - break; - case IDENTITY: break; - default: assert(0); - } + write_tile_info(cm, wb); } -static void write_global_motion(AV1_COMP *cpi, aom_writer *w) { +#else +// New function based on HLS R18 +static void write_uncompressed_header_obu(AV1_COMP *cpi, + struct aom_write_bit_buffer *wb) { AV1_COMMON *const cm = &cpi->common; - int frame; - YV12_BUFFER_CONFIG *ref_buf; - for (frame = LAST_FRAME; frame <= ALTREF_FRAME; ++frame) { - ref_buf = get_ref_frame_buffer(cpi, frame); - if (cpi->source->y_crop_width == ref_buf->y_crop_width && - cpi->source->y_crop_height == ref_buf->y_crop_height) { - write_global_motion_params(&cm->global_motion[frame], - &cm->prev_frame->global_motion[frame], w, - cm->allow_high_precision_mv); + MACROBLOCKD *const xd = &cpi->td.mb.e_mbd; + +#if CONFIG_EXT_TILE + aom_wb_write_literal(wb, cm->large_scale_tile, 1); +#endif // CONFIG_EXT_TILE + +#if CONFIG_EXT_REFS + // NOTE: By default all coded frames to be used as a reference + cm->is_reference_frame = 1; + + if (cm->show_existing_frame) { + RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs; + const int frame_to_show = cm->ref_frame_map[cpi->existing_fb_idx_to_show]; + + if (frame_to_show < 0 || frame_bufs[frame_to_show].ref_count < 1) { + aom_internal_error(&cm->error, AOM_CODEC_UNSUP_BITSTREAM, + "Buffer %d does not contain a reconstructed frame", + frame_to_show); + } + ref_cnt_fb(frame_bufs, &cm->new_fb_idx, frame_to_show); + + aom_wb_write_bit(wb, 1); // show_existing_frame + aom_wb_write_literal(wb, cpi->existing_fb_idx_to_show, 3); + +#if CONFIG_REFERENCE_BUFFER + if (cm->seq_params.frame_id_numbers_present_flag) { + int frame_id_len = cm->seq_params.frame_id_length_minus7 + 7; + int display_frame_id = cm->ref_frame_id[cpi->existing_fb_idx_to_show]; + aom_wb_write_literal(wb, display_frame_id, frame_id_len); + /* Add a zero byte to prevent emulation of superframe marker */ + /* Same logic as when when terminating the entropy coder */ + /* Consider to have this logic only one place */ + aom_wb_write_literal(wb, 0, 8); + } +#endif // CONFIG_REFERENCE_BUFFER + + return; + } else { +#endif // CONFIG_EXT_REFS + aom_wb_write_bit(wb, 0); // show_existing_frame +#if CONFIG_EXT_REFS + } +#endif // CONFIG_EXT_REFS + + cm->frame_type = cm->intra_only ? INTRA_ONLY_FRAME : cm->frame_type; + aom_wb_write_literal(wb, cm->frame_type, 2); + + if (cm->intra_only) cm->frame_type = INTRA_ONLY_FRAME; + + aom_wb_write_bit(wb, cm->show_frame); + aom_wb_write_bit(wb, cm->error_resilient_mode); + +#if CONFIG_REFERENCE_BUFFER + cm->invalid_delta_frame_id_minus1 = 0; + if (cm->seq_params.frame_id_numbers_present_flag) { + int frame_id_len = cm->seq_params.frame_id_length_minus7 + 7; + aom_wb_write_literal(wb, cm->current_frame_id, frame_id_len); + } +#endif // CONFIG_REFERENCE_BUFFER + if (cm->frame_type == KEY_FRAME) { + write_frame_size(cm, wb); + write_sb_size(cm, wb); + +#if CONFIG_ANS && ANS_MAX_SYMBOLS + assert(cpi->common.ans_window_size_log2 >= 8); + assert(cpi->common.ans_window_size_log2 < 24); + aom_wb_write_literal(wb, cpi->common.ans_window_size_log2 - 8, 4); +#endif // CONFIG_ANS && ANS_MAX_SYMBOLS + aom_wb_write_bit(wb, cm->allow_screen_content_tools); +#if CONFIG_AMVR + if (cm->allow_screen_content_tools) { + if (cm->seq_mv_precision_level == 2) { + aom_wb_write_bit(wb, 1); + } else { + aom_wb_write_bit(wb, 0); + aom_wb_write_bit(wb, cm->seq_mv_precision_level == 0); + } + } +#endif + } else if (cm->frame_type == INTRA_ONLY_FRAME) { + if (cm->intra_only) aom_wb_write_bit(wb, cm->allow_screen_content_tools); +#if !CONFIG_NO_FRAME_CONTEXT_SIGNALING + if (!cm->error_resilient_mode) { + if (cm->intra_only) { + aom_wb_write_bit(wb, + cm->reset_frame_context == RESET_FRAME_CONTEXT_ALL); + } + } +#endif +#if CONFIG_EXT_REFS + cpi->refresh_frame_mask = get_refresh_mask(cpi); +#endif // CONFIG_EXT_REFS + + if (cm->intra_only) { +#if CONFIG_EXT_REFS + aom_wb_write_literal(wb, cpi->refresh_frame_mask, REF_FRAMES); +#else + aom_wb_write_literal(wb, get_refresh_mask(cpi), REF_FRAMES); +#endif // CONFIG_EXT_REFS + write_frame_size(cm, wb); + +#if CONFIG_ANS && ANS_MAX_SYMBOLS + assert(cpi->common.ans_window_size_log2 >= 8); + assert(cpi->common.ans_window_size_log2 < 24); + aom_wb_write_literal(wb, cpi->common.ans_window_size_log2 - 8, 4); +#endif // CONFIG_ANS && ANS_MAX_SYMBOLS + } + } else if (cm->frame_type == INTER_FRAME) { + MV_REFERENCE_FRAME ref_frame; +#if !CONFIG_NO_FRAME_CONTEXT_SIGNALING + if (!cm->error_resilient_mode) { + aom_wb_write_bit(wb, cm->reset_frame_context != RESET_FRAME_CONTEXT_NONE); + if (cm->reset_frame_context != RESET_FRAME_CONTEXT_NONE) + aom_wb_write_bit(wb, + cm->reset_frame_context == RESET_FRAME_CONTEXT_ALL); + } +#endif + +#if CONFIG_EXT_REFS + cpi->refresh_frame_mask = get_refresh_mask(cpi); + aom_wb_write_literal(wb, cpi->refresh_frame_mask, REF_FRAMES); +#else + aom_wb_write_literal(wb, get_refresh_mask(cpi), REF_FRAMES); +#endif // CONFIG_EXT_REFS + +#if CONFIG_EXT_REFS + if (!cpi->refresh_frame_mask) { + // NOTE: "cpi->refresh_frame_mask == 0" indicates that the coded frame + // will not be used as a reference + cm->is_reference_frame = 0; + } +#endif // CONFIG_EXT_REFS + + for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) { + assert(get_ref_frame_map_idx(cpi, ref_frame) != INVALID_IDX); + aom_wb_write_literal(wb, get_ref_frame_map_idx(cpi, ref_frame), + REF_FRAMES_LOG2); +#if !CONFIG_FRAME_SIGN_BIAS + aom_wb_write_bit(wb, cm->ref_frame_sign_bias[ref_frame]); +#endif // !CONFIG_FRAME_SIGN_BIAS +#if CONFIG_REFERENCE_BUFFER + if (cm->seq_params.frame_id_numbers_present_flag) { + int i = get_ref_frame_map_idx(cpi, ref_frame); + int frame_id_len = cm->seq_params.frame_id_length_minus7 + 7; + int diff_len = cm->seq_params.delta_frame_id_length_minus2 + 2; + int delta_frame_id_minus1 = + ((cm->current_frame_id - cm->ref_frame_id[i] + + (1 << frame_id_len)) % + (1 << frame_id_len)) - + 1; + if (delta_frame_id_minus1 < 0 || + delta_frame_id_minus1 >= (1 << diff_len)) + cm->invalid_delta_frame_id_minus1 = 1; + aom_wb_write_literal(wb, delta_frame_id_minus1, diff_len); + } +#endif // CONFIG_REFERENCE_BUFFER + } + +#if CONFIG_FRAME_SIZE + if (cm->error_resilient_mode == 0) { + write_frame_size_with_refs(cpi, wb); } else { - assert(cm->global_motion[frame].wmtype == IDENTITY && - "Invalid warp type for frames of different resolutions"); + write_frame_size(cm, wb); } - /* - printf("Frame %d/%d: Enc Ref %d (used %d): %d %d %d %d\n", - cm->current_video_frame, cm->show_frame, frame, - cpi->global_motion_used[frame], cm->global_motion[frame].wmmat[0], - cm->global_motion[frame].wmmat[1], cm->global_motion[frame].wmmat[2], - cm->global_motion[frame].wmmat[3]); - */ +#else + write_frame_size_with_refs(cpi, wb); +#endif + +#if CONFIG_AMVR + if (cm->seq_mv_precision_level == 2) { + aom_wb_write_bit(wb, cm->cur_frame_mv_precision_level == 0); + } +#endif + aom_wb_write_bit(wb, cm->allow_high_precision_mv); + + fix_interp_filter(cm, cpi->td.counts); + write_frame_interp_filter(cm->interp_filter, wb); +#if CONFIG_TEMPMV_SIGNALING + if (frame_might_use_prev_frame_mvs(cm)) { + aom_wb_write_bit(wb, cm->use_prev_frame_mvs); + } +#endif + } else if (cm->frame_type == S_FRAME) { + MV_REFERENCE_FRAME ref_frame; + +#if !CONFIG_NO_FRAME_CONTEXT_SIGNALING + if (!cm->error_resilient_mode) { + aom_wb_write_bit(wb, cm->reset_frame_context != RESET_FRAME_CONTEXT_NONE); + if (cm->reset_frame_context != RESET_FRAME_CONTEXT_NONE) + aom_wb_write_bit(wb, + cm->reset_frame_context == RESET_FRAME_CONTEXT_ALL); + } +#endif + +#if CONFIG_EXT_REFS + if (!cpi->refresh_frame_mask) { + // NOTE: "cpi->refresh_frame_mask == 0" indicates that the coded frame + // will not be used as a reference + cm->is_reference_frame = 0; + } +#endif // CONFIG_EXT_REFS + + for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) { + assert(get_ref_frame_map_idx(cpi, ref_frame) != INVALID_IDX); + aom_wb_write_literal(wb, get_ref_frame_map_idx(cpi, ref_frame), + REF_FRAMES_LOG2); + assert(cm->ref_frame_sign_bias[ref_frame] == 0); +#if CONFIG_REFERENCE_BUFFER + if (cm->seq_params.frame_id_numbers_present_flag) { + int i = get_ref_frame_map_idx(cpi, ref_frame); + int frame_id_len = cm->seq_params.frame_id_length_minus7 + 7; + int diff_len = cm->seq_params.delta_frame_id_length_minus2 + 2; + int delta_frame_id_minus1 = + ((cm->current_frame_id - cm->ref_frame_id[i] + + (1 << frame_id_len)) % + (1 << frame_id_len)) - + 1; + if (delta_frame_id_minus1 < 0 || + delta_frame_id_minus1 >= (1 << diff_len)) + cm->invalid_delta_frame_id_minus1 = 1; + aom_wb_write_literal(wb, delta_frame_id_minus1, diff_len); + } +#endif // CONFIG_REFERENCE_BUFFER + } + +#if CONFIG_FRAME_SIZE + if (cm->error_resilient_mode == 0) { + write_frame_size_with_refs(cpi, wb); + } else { + write_frame_size(cm, wb); + } +#else + write_frame_size_with_refs(cpi, wb); +#endif + + aom_wb_write_bit(wb, cm->allow_high_precision_mv); + + fix_interp_filter(cm, cpi->td.counts); + write_frame_interp_filter(cm->interp_filter, wb); +#if CONFIG_TEMPMV_SIGNALING + if (frame_might_use_prev_frame_mvs(cm)) { + aom_wb_write_bit(wb, cm->use_prev_frame_mvs); + } +#endif + } + +#if CONFIG_MFMV + if (cm->show_frame == 0) { + int arf_offset = AOMMIN( + (MAX_GF_INTERVAL - 1), + cpi->twopass.gf_group.arf_src_offset[cpi->twopass.gf_group.index]); +#if CONFIG_EXT_REFS + int brf_offset = + cpi->twopass.gf_group.brf_src_offset[cpi->twopass.gf_group.index]; + + arf_offset = AOMMIN((MAX_GF_INTERVAL - 1), arf_offset + brf_offset); +#endif + aom_wb_write_literal(wb, arf_offset, 4); + } +#endif + +#if CONFIG_REFERENCE_BUFFER + if (cm->seq_params.frame_id_numbers_present_flag) { + cm->refresh_mask = + cm->frame_type == KEY_FRAME ? 0xFF : get_refresh_mask(cpi); + } +#endif // CONFIG_REFERENCE_BUFFER + + if (!cm->error_resilient_mode) { + aom_wb_write_bit( + wb, cm->refresh_frame_context == REFRESH_FRAME_CONTEXT_FORWARD); + } +#if !CONFIG_NO_FRAME_CONTEXT_SIGNALING + aom_wb_write_literal(wb, cm->frame_context_idx, FRAME_CONTEXTS_LOG2); +#endif + encode_loopfilter(cm, wb); + encode_quantization(cm, wb); + encode_segmentation(cm, xd, wb); + { + int i; + struct segmentation *const seg = &cm->seg; + int segment_quantizer_active = 0; + for (i = 0; i < MAX_SEGMENTS; i++) { + if (segfeature_active(seg, i, SEG_LVL_ALT_Q)) { + segment_quantizer_active = 1; + } + } + + if (cm->delta_q_present_flag) + assert(segment_quantizer_active == 0 && cm->base_qindex > 0); + if (segment_quantizer_active == 0 && cm->base_qindex > 0) { + aom_wb_write_bit(wb, cm->delta_q_present_flag); + if (cm->delta_q_present_flag) { + aom_wb_write_literal(wb, OD_ILOG_NZ(cm->delta_q_res) - 1, 2); + xd->prev_qindex = cm->base_qindex; +#if CONFIG_EXT_DELTA_Q + assert(seg->abs_delta == SEGMENT_DELTADATA); + aom_wb_write_bit(wb, cm->delta_lf_present_flag); + if (cm->delta_lf_present_flag) { + aom_wb_write_literal(wb, OD_ILOG_NZ(cm->delta_lf_res) - 1, 2); +#if CONFIG_LOOPFILTER_LEVEL + for (int lf_id = 0; lf_id < FRAME_LF_COUNT; ++lf_id) + xd->prev_delta_lf[lf_id] = 0; +#endif // CONFIG_LOOPFILTER_LEVEL + xd->prev_delta_lf_from_base = 0; + } +#endif // CONFIG_EXT_DELTA_Q + } + } + } +#if CONFIG_CDEF + if (!cm->all_lossless) { + encode_cdef(cm, wb); } -} #endif +#if CONFIG_LOOP_RESTORATION + encode_restoration_mode(cm, wb); +#endif // CONFIG_LOOP_RESTORATION + write_tx_mode(cm, &cm->tx_mode, wb); + + if (cpi->allow_comp_inter_inter) { + const int use_hybrid_pred = cm->reference_mode == REFERENCE_MODE_SELECT; +#if !CONFIG_REF_ADAPT + const int use_compound_pred = cm->reference_mode != SINGLE_REFERENCE; +#endif // !CONFIG_REF_ADAPT + + aom_wb_write_bit(wb, use_hybrid_pred); +#if !CONFIG_REF_ADAPT + if (!use_hybrid_pred) aom_wb_write_bit(wb, use_compound_pred); +#endif // !CONFIG_REF_ADAPT + } + write_compound_tools(cm, wb); + +#if CONFIG_EXT_TX + aom_wb_write_bit(wb, cm->reduced_tx_set_used); +#endif // CONFIG_EXT_TX + +#if CONFIG_GLOBAL_MOTION + if (!frame_is_intra_only(cm)) write_global_motion(cpi, wb); +#endif // CONFIG_GLOBAL_MOTION + + write_tile_info(cm, wb); +} +#endif // CONFIG_OBU static uint32_t write_compressed_header(AV1_COMP *cpi, uint8_t *data) { AV1_COMMON *const cm = &cpi->common; @@ -4587,19 +5225,13 @@ static uint32_t write_compressed_header(AV1_COMP *cpi, uint8_t *data) { (void)i; (void)fc; -#if CONFIG_ANS - int header_size; - header_bc = &cpi->buf_ans; - buf_ans_write_init(header_bc, data); -#else aom_writer real_header_bc; header_bc = &real_header_bc; - aom_start_encode(header_bc, data); +#if CONFIG_ANS + header_bc->size = 1 << cpi->common.ans_window_size_log2; #endif + aom_start_encode(header_bc, data); -#if CONFIG_LOOP_RESTORATION - encode_restoration(cm, header_bc); -#endif // CONFIG_LOOP_RESTORATION #if CONFIG_RECT_TX_EXT && (CONFIG_EXT_TX || CONFIG_VAR_TX) if (cm->tx_mode == TX_MODE_SELECT) av1_cond_prob_diff_update(header_bc, &cm->fc->quarter_tx_size_prob, @@ -4610,27 +5242,18 @@ static uint32_t write_compressed_header(AV1_COMP *cpi, uint8_t *data) { #endif // CONFIG_LV_MAP #if CONFIG_VAR_TX && !CONFIG_NEW_MULTISYMBOL - update_txfm_partition_probs(cm, header_bc, counts, probwt); + if (cm->tx_mode == TX_MODE_SELECT) + update_txfm_partition_probs(cm, header_bc, counts, probwt); #endif #if !CONFIG_NEW_MULTISYMBOL update_skip_probs(cm, header_bc, counts); #endif - if (frame_is_intra_only(cm)) { - av1_copy(cm->fc->kf_y_cdf, av1_kf_y_mode_cdf); - -#if CONFIG_INTRABC - if (cm->allow_screen_content_tools) { - av1_cond_prob_diff_update(header_bc, &fc->intrabc_prob, - cm->counts.intrabc, probwt); - } -#endif - } else { + if (!frame_is_intra_only(cm)) { #if !CONFIG_NEW_MULTISYMBOL update_inter_mode_probs(cm, header_bc, counts); #endif -#if CONFIG_EXT_INTER #if CONFIG_INTERINTRA if (cm->reference_mode != COMPOUND_REFERENCE && cm->allow_interintra_compound) { @@ -4656,17 +5279,6 @@ static uint32_t write_compressed_header(AV1_COMP *cpi, uint8_t *data) { #endif // CONFIG_WEDGE && CONFIG_NEW_MULTISYMBOL } #endif // CONFIG_INTERINTRA -#endif // CONFIG_EXT_INTER - -#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION -#if CONFIG_NCOBMC_ADAPT_WEIGHT - for (i = ADAPT_OVERLAP_BLOCK_8X8; i < ADAPT_OVERLAP_BLOCKS; ++i) { - prob_diff_update(av1_ncobmc_mode_tree, fc->ncobmc_mode_prob[i], - counts->ncobmc_mode[i], MAX_NCOBMC_MODES, probwt, - header_bc); - } -#endif -#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION #if !CONFIG_NEW_MULTISYMBOL for (i = 0; i < INTRA_INTER_CONTEXTS; i++) @@ -4724,11 +5336,11 @@ static uint32_t write_compressed_header(AV1_COMP *cpi, uint8_t *data) { } #endif // CONFIG_NEW_MULTISYMBOL -#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF +#if CONFIG_COMPOUND_SINGLEREF for (i = 0; i < COMP_INTER_MODE_CONTEXTS; i++) av1_cond_prob_diff_update(header_bc, &fc->comp_inter_mode_prob[i], counts->comp_inter_mode[i], probwt); -#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF +#endif // CONFIG_COMPOUND_SINGLEREF #if !CONFIG_NEW_MULTISYMBOL av1_write_nmv_probs(cm, cm->allow_high_precision_mv, header_bc, counts->mv); @@ -4736,22 +5348,13 @@ static uint32_t write_compressed_header(AV1_COMP *cpi, uint8_t *data) { #if CONFIG_SUPERTX if (!xd->lossless[0]) update_supertx_probs(cm, probwt, header_bc); #endif // CONFIG_SUPERTX -#if CONFIG_GLOBAL_MOTION - write_global_motion(cpi, header_bc); -#endif // CONFIG_GLOBAL_MOTION } -#if CONFIG_ANS - aom_buf_ans_flush(header_bc); - header_size = buf_ans_write_end(header_bc); - assert(header_size <= 0xffff); - return header_size; -#else aom_stop_encode(header_bc); assert(header_bc->pos <= 0xffff); return header_bc->pos; -#endif // CONFIG_ANS } +#if !CONFIG_OBU || CONFIG_EXT_TILE static int choose_size_bytes(uint32_t size, int spare_msbs) { // Choose the number of bytes required to represent size, without // using the 'spare_msbs' number of most significant bits. @@ -4781,6 +5384,7 @@ static void mem_put_varsize(uint8_t *const dst, const int sz, const int val) { default: assert(0 && "Invalid size"); break; } } + static int remux_tiles(const AV1_COMMON *const cm, uint8_t *dst, const uint32_t data_size, const uint32_t max_tile_size, const uint32_t max_tile_col_size, @@ -4889,14 +5493,334 @@ static int remux_tiles(const AV1_COMMON *const cm, uint8_t *dst, return wpos; } } +#endif + +#if CONFIG_OBU +static uint32_t write_obu_header(OBU_TYPE obu_type, int obu_extension, + uint8_t *const dst) { + struct aom_write_bit_buffer wb = { dst, 0 }; + uint32_t size = 0; + + aom_wb_write_literal(&wb, (int)obu_type, 5); + aom_wb_write_literal(&wb, 0, 2); + aom_wb_write_literal(&wb, obu_extension ? 1 : 0, 1); + if (obu_extension) { + aom_wb_write_literal(&wb, obu_extension & 0xFF, 8); + } + + size = aom_wb_bytes_written(&wb); + return size; +} + +static uint32_t write_temporal_delimiter_obu() { return 0; } + +static uint32_t write_sequence_header_obu(AV1_COMP *cpi, uint8_t *const dst) { + AV1_COMMON *const cm = &cpi->common; + SequenceHeader *const seq_params = &cm->seq_params; + struct aom_write_bit_buffer wb = { dst, 0 }; + uint32_t size = 0; + + write_profile(cm->profile, &wb); + + aom_wb_write_literal(&wb, 0, 4); + + seq_params->frame_id_numbers_present_flag = FRAME_ID_NUMBERS_PRESENT_FLAG; + aom_wb_write_literal(&wb, seq_params->frame_id_numbers_present_flag, 1); + if (seq_params->frame_id_numbers_present_flag) { + seq_params->frame_id_length_minus7 = FRAME_ID_LENGTH_MINUS7; + seq_params->delta_frame_id_length_minus2 = DELTA_FRAME_ID_LENGTH_MINUS2; + aom_wb_write_literal(&wb, seq_params->frame_id_length_minus7, 4); + aom_wb_write_literal(&wb, seq_params->delta_frame_id_length_minus2, 4); + } + + // color_config + write_bitdepth_colorspace_sampling(cm, &wb); + + size = aom_wb_bytes_written(&wb); + return size; +} + +static uint32_t write_frame_header_obu(AV1_COMP *cpi, uint8_t *const dst) { + AV1_COMMON *const cm = &cpi->common; + struct aom_write_bit_buffer wb = { dst, 0 }; + uint32_t total_size = 0; + uint32_t compressed_hdr_size, uncompressed_hdr_size; + + write_uncompressed_header_obu(cpi, &wb); + + if (cm->show_existing_frame) { + total_size = aom_wb_bytes_written(&wb); + return total_size; + } + + // write the tile length code (Always 4 bytes for now) + aom_wb_write_literal(&wb, 3, 2); + + if (!use_compressed_header(cm)) { + uncompressed_hdr_size = aom_wb_bytes_written(&wb); + compressed_hdr_size = 0; + } else { + // placeholder for the compressed header length + struct aom_write_bit_buffer compr_hdr_len_wb = wb; + aom_wb_write_literal(&wb, 0, 16); + + uncompressed_hdr_size = aom_wb_bytes_written(&wb); + compressed_hdr_size = + write_compressed_header(cpi, dst + uncompressed_hdr_size); + aom_wb_overwrite_literal(&compr_hdr_len_wb, (int)(compressed_hdr_size), 16); + } + + total_size = uncompressed_hdr_size + compressed_hdr_size; + return total_size; +} + +static uint32_t write_tile_group_header(uint8_t *const dst, int startTile, + int endTile, int tiles_log2) { + struct aom_write_bit_buffer wb = { dst, 0 }; + uint32_t size = 0; + + aom_wb_write_literal(&wb, startTile, tiles_log2); + aom_wb_write_literal(&wb, endTile, tiles_log2); + + size = aom_wb_bytes_written(&wb); + return size; +} + +static uint32_t write_tiles_in_tg_obus(AV1_COMP *const cpi, uint8_t *const dst, + unsigned int *max_tile_size, + unsigned int *max_tile_col_size, + uint8_t *const frame_header_obu_location, + uint32_t frame_header_obu_size, + int insert_frame_header_obu_flag) { + const AV1_COMMON *const cm = &cpi->common; + aom_writer mode_bc; + int tile_row, tile_col; + TOKENEXTRA *(*const tok_buffers)[MAX_TILE_COLS] = cpi->tile_tok; + TileBufferEnc(*const tile_buffers)[MAX_TILE_COLS] = cpi->tile_buffers; + uint32_t total_size = 0; + const int tile_cols = cm->tile_cols; + const int tile_rows = cm->tile_rows; + unsigned int tile_size = 0; + const int n_log2_tiles = cm->log2_tile_rows + cm->log2_tile_cols; + // Fixed size tile groups for the moment + const int num_tg_hdrs = cm->num_tg; + const int tg_size = +#if CONFIG_EXT_TILE + (cm->large_scale_tile) + ? 1 + : +#endif // CONFIG_EXT_TILE + (tile_rows * tile_cols + num_tg_hdrs - 1) / num_tg_hdrs; + int tile_count = 0; + int curr_tg_data_size = 0; + uint8_t *data = dst; + int new_tg = 1; +#if CONFIG_EXT_TILE + const int have_tiles = tile_cols * tile_rows > 1; +#endif + + *max_tile_size = 0; + *max_tile_col_size = 0; + +#if CONFIG_EXT_TILE + if (cm->large_scale_tile) { + for (tile_col = 0; tile_col < tile_cols; tile_col++) { + TileInfo tile_info; + const int is_last_col = (tile_col == tile_cols - 1); + const uint32_t col_offset = total_size; + + av1_tile_set_col(&tile_info, cm, tile_col); + + // The last column does not have a column header + if (!is_last_col) total_size += 4; + + for (tile_row = 0; tile_row < tile_rows; tile_row++) { + TileBufferEnc *const buf = &tile_buffers[tile_row][tile_col]; + const TOKENEXTRA *tok = tok_buffers[tile_row][tile_col]; + const TOKENEXTRA *tok_end = tok + cpi->tok_count[tile_row][tile_col]; + const int data_offset = have_tiles ? 4 : 0; + const int tile_idx = tile_row * tile_cols + tile_col; + TileDataEnc *this_tile = &cpi->tile_data[tile_idx]; + av1_tile_set_row(&tile_info, cm, tile_row); + + buf->data = dst + total_size; + + // Is CONFIG_EXT_TILE = 1, every tile in the row has a header, + // even for the last one, unless no tiling is used at all. + total_size += data_offset; + // Initialise tile context from the frame context + this_tile->tctx = *cm->fc; + cpi->td.mb.e_mbd.tile_ctx = &this_tile->tctx; +#if CONFIG_PVQ + cpi->td.mb.pvq_q = &this_tile->pvq_q; + cpi->td.mb.daala_enc.state.adapt = &this_tile->tctx.pvq_context; +#endif // CONFIG_PVQ +#if CONFIG_ANS + mode_bc.size = 1 << cpi->common.ans_window_size_log2; +#endif + aom_start_encode(&mode_bc, buf->data + data_offset); + write_modes(cpi, &tile_info, &mode_bc, &tok, tok_end); + assert(tok == tok_end); + aom_stop_encode(&mode_bc); + tile_size = mode_bc.pos; +#if CONFIG_PVQ + cpi->td.mb.pvq_q = NULL; +#endif + buf->size = tile_size; + + // Record the maximum tile size we see, so we can compact headers later. + *max_tile_size = AOMMAX(*max_tile_size, tile_size); + + if (have_tiles) { + // tile header: size of this tile, or copy offset + uint32_t tile_header = tile_size; + const int tile_copy_mode = + ((AOMMAX(cm->tile_width, cm->tile_height) << MI_SIZE_LOG2) <= 256) + ? 1 + : 0; + + // If tile_copy_mode = 1, check if this tile is a copy tile. + // Very low chances to have copy tiles on the key frames, so don't + // search on key frames to reduce unnecessary search. + if (cm->frame_type != KEY_FRAME && tile_copy_mode) { + const int idendical_tile_offset = + find_identical_tile(tile_row, tile_col, tile_buffers); + + if (idendical_tile_offset > 0) { + tile_size = 0; + tile_header = idendical_tile_offset | 0x80; + tile_header <<= 24; + } + } + + mem_put_le32(buf->data, tile_header); + } + + total_size += tile_size; + } + + if (!is_last_col) { + uint32_t col_size = total_size - col_offset - 4; + mem_put_le32(dst + col_offset, col_size); + + // If it is not final packing, record the maximum tile column size we + // see, otherwise, check if the tile size is out of the range. + *max_tile_col_size = AOMMAX(*max_tile_col_size, col_size); + } + } + } else { +#endif // CONFIG_EXT_TILE + + for (tile_row = 0; tile_row < tile_rows; tile_row++) { + TileInfo tile_info; + const int is_last_row = (tile_row == tile_rows - 1); + av1_tile_set_row(&tile_info, cm, tile_row); + + for (tile_col = 0; tile_col < tile_cols; tile_col++) { + const int tile_idx = tile_row * tile_cols + tile_col; + TileBufferEnc *const buf = &tile_buffers[tile_row][tile_col]; + TileDataEnc *this_tile = &cpi->tile_data[tile_idx]; + const TOKENEXTRA *tok = tok_buffers[tile_row][tile_col]; + const TOKENEXTRA *tok_end = tok + cpi->tok_count[tile_row][tile_col]; + const int is_last_col = (tile_col == tile_cols - 1); + const int is_last_tile = is_last_col && is_last_row; + int is_last_tile_in_tg = 0; + + if (new_tg) { + if (insert_frame_header_obu_flag && tile_idx) { + // insert a copy of frame header OBU (including 4-byte size), + // except before the first tile group + data = dst + total_size; + memmove(data, frame_header_obu_location, frame_header_obu_size); + total_size += frame_header_obu_size; + } + data = dst + total_size; + // A new tile group begins at this tile. Write the obu header and + // tile group header + curr_tg_data_size = write_obu_header(OBU_TILE_GROUP, 0, data + 4); + if (n_log2_tiles) + curr_tg_data_size += write_tile_group_header( + data + curr_tg_data_size + 4, tile_idx, + AOMMIN(tile_idx + tg_size - 1, tile_cols * tile_rows - 1), + n_log2_tiles); + total_size += curr_tg_data_size + 4; + new_tg = 0; + tile_count = 0; + } + tile_count++; + av1_tile_set_col(&tile_info, cm, tile_col); + + if (tile_count == tg_size || tile_idx == (tile_cols * tile_rows - 1)) { + is_last_tile_in_tg = 1; + new_tg = 1; + } else { + is_last_tile_in_tg = 0; + } + +#if CONFIG_DEPENDENT_HORZTILES + av1_tile_set_tg_boundary(&tile_info, cm, tile_row, tile_col); +#endif + buf->data = dst + total_size; + + // The last tile of the tile group does not have a header. + if (!is_last_tile_in_tg) total_size += 4; + + // Initialise tile context from the frame context + this_tile->tctx = *cm->fc; + cpi->td.mb.e_mbd.tile_ctx = &this_tile->tctx; +#if CONFIG_PVQ + cpi->td.mb.pvq_q = &this_tile->pvq_q; + cpi->td.mb.daala_enc.state.adapt = &this_tile->tctx.pvq_context; +#endif // CONFIG_PVQ +#if CONFIG_ANS + mode_bc.size = 1 << cpi->common.ans_window_size_log2; +#endif // CONFIG_ANS + aom_start_encode(&mode_bc, dst + total_size); + write_modes(cpi, &tile_info, &mode_bc, &tok, tok_end); +#if !CONFIG_LV_MAP +#if !CONFIG_PVQ + assert(tok == tok_end); +#endif // !CONFIG_PVQ +#endif // !CONFIG_LV_MAP + aom_stop_encode(&mode_bc); + tile_size = mode_bc.pos; +#if CONFIG_PVQ + cpi->td.mb.pvq_q = NULL; +#endif + assert(tile_size > 0); + + curr_tg_data_size += (tile_size + (is_last_tile_in_tg ? 0 : 4)); + buf->size = tile_size; + + if (!is_last_tile) { + *max_tile_size = AOMMAX(*max_tile_size, tile_size); + } + if (!is_last_tile_in_tg) { + // size of this tile + mem_put_le32(buf->data, tile_size); + } else { + // write current tile group size + mem_put_le32(data, curr_tg_data_size); + } + + total_size += tile_size; + } + } +#if CONFIG_EXT_TILE + } +#endif // CONFIG_EXT_TILE + return (uint32_t)total_size; +} + +#endif void av1_pack_bitstream(AV1_COMP *const cpi, uint8_t *dst, size_t *size) { uint8_t *data = dst; uint32_t data_size; #if CONFIG_EXT_TILE AV1_COMMON *const cm = &cpi->common; - uint32_t compressed_header_size = 0; - uint32_t uncompressed_header_size; + uint32_t compressed_hdr_size = 0; + uint32_t uncompressed_hdr_size; struct aom_write_bit_buffer saved_wb; struct aom_write_bit_buffer wb = { data, 0 }; const int have_tiles = cm->tile_cols * cm->tile_rows > 1; @@ -4905,15 +5829,59 @@ void av1_pack_bitstream(AV1_COMP *const cpi, uint8_t *dst, size_t *size) { #endif // CONFIG_EXT_TILE unsigned int max_tile_size; unsigned int max_tile_col_size; +#if CONFIG_OBU +#if !CONFIG_EXT_TILE + AV1_COMMON *const cm = &cpi->common; +#endif + uint32_t obu_size; + uint8_t *frame_header_location; + uint32_t frame_header_size; +#endif #if CONFIG_BITSTREAM_DEBUG bitstream_queue_reset_write(); #endif +#if CONFIG_OBU + // write temporal delimiter obu, preceded by 4-byte size + obu_size = write_obu_header(OBU_TD, 0, data + 4); + obu_size += write_temporal_delimiter_obu(/*data + 4 + obu_size*/); + mem_put_le32(data, obu_size); + data += obu_size + 4; + + // write sequence header obu if KEY_FRAME, preceded by 4-byte size + if (cm->frame_type == KEY_FRAME) { + obu_size = write_obu_header(OBU_SEQUENCE_HEADER, 0, data + 4); + obu_size += write_sequence_header_obu(cpi, data + 4 + obu_size); + mem_put_le32(data, obu_size); + data += obu_size + 4; + } + + // write frame header obu, preceded by 4-byte size + frame_header_location = data + 4; + obu_size = write_obu_header(OBU_FRAME_HEADER, 0, frame_header_location); + frame_header_size = write_frame_header_obu(cpi, data + 4 + obu_size); + obu_size += frame_header_size; + mem_put_le32(data, obu_size); + data += obu_size + 4; + + if (cm->show_existing_frame) { + data_size = 0; + } else { + // Each tile group obu will be preceded by 4-byte size of the tile group + // obu + data_size = + write_tiles_in_tg_obus(cpi, data, &max_tile_size, &max_tile_col_size, + frame_header_location - 4, obu_size + 4, + 1 /* cm->error_resilient_mode */); + } + +#endif + #if CONFIG_EXT_TILE if (cm->large_scale_tile) { // Write the uncompressed header - write_uncompressed_header(cpi, &wb); + write_uncompressed_header_frame(cpi, &wb); #if CONFIG_EXT_REFS if (cm->show_existing_frame) { @@ -4934,23 +5902,29 @@ void av1_pack_bitstream(AV1_COMP *const cpi, uint8_t *dst, size_t *size) { // Number of bytes in tile size - 1 aom_wb_write_literal(&wb, 0, 2); } - // Size of compressed header - aom_wb_write_literal(&wb, 0, 16); - - uncompressed_header_size = (uint32_t)aom_wb_bytes_written(&wb); - data += uncompressed_header_size; - aom_clear_system_state(); - - // Write the compressed header - compressed_header_size = write_compressed_header(cpi, data); - data += compressed_header_size; + if (!use_compressed_header(cm)) { + uncompressed_hdr_size = (uint32_t)aom_wb_bytes_written(&wb); + aom_clear_system_state(); + compressed_hdr_size = 0; + } else { + // Size of compressed header + aom_wb_write_literal(&wb, 0, 16); + uncompressed_hdr_size = (uint32_t)aom_wb_bytes_written(&wb); + aom_clear_system_state(); + // Write the compressed header + compressed_hdr_size = + write_compressed_header(cpi, data + uncompressed_hdr_size); + } + data += uncompressed_hdr_size + compressed_hdr_size; // Write the encoded tile data data_size = write_tiles(cpi, data, &max_tile_size, &max_tile_col_size); } else { #endif // CONFIG_EXT_TILE +#if !CONFIG_OBU data_size = write_tiles(cpi, data, &max_tile_size, &max_tile_col_size); +#endif #if CONFIG_EXT_TILE } #endif // CONFIG_EXT_TILE @@ -4972,9 +5946,9 @@ void av1_pack_bitstream(AV1_COMP *const cpi, uint8_t *dst, size_t *size) { assert(tile_size_bytes >= 1 && tile_size_bytes <= 4); aom_wb_write_literal(&saved_wb, tile_size_bytes - 1, 2); } - // TODO(jbb): Figure out what to do if compressed_header_size > 16 bits. - assert(compressed_header_size <= 0xffff); - aom_wb_write_literal(&saved_wb, compressed_header_size, 16); + // TODO(jbb): Figure out what to do if compressed_hdr_size > 16 bits. + assert(compressed_hdr_size <= 0xffff); + aom_wb_write_literal(&saved_wb, compressed_hdr_size, 16); } else { #endif // CONFIG_EXT_TILE data += data_size; |