Don't send chroma data in monochrome mode
This is still a rather inefficient black+white encoder, since it carefully
computes some chroma data, but just doesn't write it. However, at least the
bitstream is now monochrome.
Change-Id: Ie8a89bf329e7b41441032fb0d9e9011385bc12ff
diff --git a/av1/common/onyxc_int.h b/av1/common/onyxc_int.h
index 024ad99..4199ed4 100644
--- a/av1/common/onyxc_int.h
+++ b/av1/common/onyxc_int.h
@@ -483,10 +483,6 @@
unsigned int single_tile_decoding;
#endif // CONFIG_EXT_TILE
-#if CONFIG_MONO_VIDEO
- int monochrome;
-#endif // CONFIG_MONO_VIDEO
-
#if CONFIG_DEPENDENT_HORZTILES
int dependent_horz_tiles;
int tile_group_start_row[MAX_TILE_ROWS][MAX_TILE_COLS];
@@ -1129,6 +1125,15 @@
}
#endif // CONFIG_CFL
+static INLINE int av1_num_planes(const AV1_COMMON *cm) {
+#if CONFIG_MONO_VIDEO
+ return cm->seq_params.monochrome ? 1 : MAX_MB_PLANE;
+#else
+ (void)cm;
+ return MAX_MB_PLANE;
+#endif
+}
+
static INLINE void av1_zero_above_context(AV1_COMMON *const cm,
int mi_col_start, int mi_col_end) {
const int width = mi_col_end - mi_col_start;
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c
index 29049e2..7cc9c84 100644
--- a/av1/decoder/decodeframe.c
+++ b/av1/decoder/decodeframe.c
@@ -486,8 +486,7 @@
#else
const int current_qindex = xd->current_qindex;
#endif // CONFIG_EXT_DELTA_Q
- int j;
- for (j = 0; j < MAX_MB_PLANE; ++j) {
+ for (int j = 0; j < av1_num_planes(cm); ++j) {
const int dc_delta_q =
j == 0 ? cm->y_dc_delta_q
: (j == 1 ? cm->u_dc_delta_q : cm->v_dc_delta_q);
@@ -505,14 +504,13 @@
if (mbmi->skip) av1_reset_skip_context(xd, mi_row, mi_col, bsize);
if (!is_inter_block(mbmi)) {
- int plane;
-
- for (plane = 0; plane <= 1; ++plane) {
+ const int num_planes = av1_num_planes(cm);
+ for (int plane = 0; plane < AOMMIN(2, num_planes); ++plane) {
if (mbmi->palette_mode_info.palette_size[plane])
av1_decode_palette_tokens(xd, plane, r);
}
- for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
+ for (int plane = 0; plane < num_planes; ++plane) {
const struct macroblockd_plane *const pd = &xd->plane[plane];
const TX_SIZE tx_size = av1_get_tx_size(plane, xd);
const int stepr = tx_size_high_unit[tx_size];
@@ -593,9 +591,7 @@
// Reconstruction
if (!mbmi->skip) {
int eobtotal = 0;
- int plane;
-
- for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
+ for (int plane = 0; plane < av1_num_planes(cm); ++plane) {
const struct macroblockd_plane *const pd = &xd->plane[plane];
const BLOCK_SIZE plane_bsize =
AOMMAX(BLOCK_4X4, get_plane_block_size(bsize, pd));
@@ -1008,7 +1004,7 @@
}
}
#if CONFIG_LOOP_RESTORATION
- for (int plane = 0; plane < MAX_MB_PLANE; ++plane) {
+ for (int plane = 0; plane < av1_num_planes(cm); ++plane) {
int rcol0, rcol1, rrow0, rrow1, tile_tl_idx;
if (av1_loop_restoration_corners_in_sb(cm, plane, mi_row, mi_col, bsize,
&rcol0, &rcol1, &rrow0, &rrow1,
@@ -1131,7 +1127,8 @@
#if CONFIG_INTRABC
if (cm->allow_intrabc && NO_FILTER_FOR_IBC) return;
#endif // CONFIG_INTRABC
- for (int p = 0; p < MAX_MB_PLANE; ++p) {
+ int all_none = 1, chroma_none = 1;
+ for (int p = 0; p < av1_num_planes(cm); ++p) {
RestorationInfo *rsi = &cm->rst_info[p];
if (aom_rb_read_bit(rb)) {
rsi->frame_restoration_type =
@@ -1140,10 +1137,12 @@
rsi->frame_restoration_type =
aom_rb_read_bit(rb) ? RESTORE_SWITCHABLE : RESTORE_NONE;
}
+ if (rsi->frame_restoration_type != RESTORE_NONE) {
+ all_none = 0;
+ chroma_none &= p == 0;
+ }
}
- if (cm->rst_info[0].frame_restoration_type != RESTORE_NONE ||
- cm->rst_info[1].frame_restoration_type != RESTORE_NONE ||
- cm->rst_info[2].frame_restoration_type != RESTORE_NONE) {
+ if (!all_none) {
const int qsize = RESTORATION_TILESIZE_MAX >> 2;
for (int p = 0; p < MAX_MB_PLANE; ++p)
cm->rst_info[p].restoration_unit_size = qsize;
@@ -1159,16 +1158,18 @@
cm->rst_info[p].restoration_unit_size = size;
}
- 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)) {
- cm->rst_info[1].restoration_unit_size =
- cm->rst_info[0].restoration_unit_size >> (aom_rb_read_bit(rb) * s);
- } else {
- cm->rst_info[1].restoration_unit_size =
- cm->rst_info[0].restoration_unit_size;
+ if (av1_num_planes(cm) > 1) {
+ int s = AOMMIN(cm->subsampling_x, cm->subsampling_y);
+ if (s && !chroma_none) {
+ cm->rst_info[1].restoration_unit_size =
+ cm->rst_info[0].restoration_unit_size >> (aom_rb_read_bit(rb) * s);
+ } else {
+ cm->rst_info[1].restoration_unit_size =
+ cm->rst_info[0].restoration_unit_size;
+ }
+ cm->rst_info[2].restoration_unit_size =
+ cm->rst_info[1].restoration_unit_size;
}
- cm->rst_info[2].restoration_unit_size = cm->rst_info[1].restoration_unit_size;
}
static void read_wiener_filter(int wiener_win, WienerInfo *wiener_info,
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index 95d1af7..0e785d1 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -1212,7 +1212,12 @@
}
}
- if (mbmi->uv_mode == UV_DC_PRED) {
+ const int uv_dc_pred =
+#if CONFIG_MONO_VIDEO
+ !cm->seq_params.monochrome &&
+#endif
+ mbmi->uv_mode == UV_DC_PRED;
+ if (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
@@ -2007,7 +2012,8 @@
#endif // CONFIG_DEPENDENT_HORZTILES
cm->mi_rows, cm->mi_cols);
- for (plane = 0; plane <= 1; ++plane) {
+ const int num_planes = av1_num_planes(cm);
+ for (plane = 0; plane < AOMMIN(2, num_planes); ++plane) {
const uint8_t palette_size_plane =
mbmi->palette_mode_info.palette_size[plane];
if (palette_size_plane > 0) {
@@ -2030,7 +2036,7 @@
#if !CONFIG_LV_MAP
assert(*tok < tok_end);
#endif
- for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
+ for (plane = 0; plane < num_planes; ++plane) {
if (!is_chroma_reference(mi_row, mi_col, mbmi->sb_type,
xd->plane[plane].subsampling_x,
xd->plane[plane].subsampling_y)) {
@@ -2457,7 +2463,7 @@
}
}
#if CONFIG_LOOP_RESTORATION
- for (int plane = 0; plane < MAX_MB_PLANE; ++plane) {
+ for (int plane = 0; plane < av1_num_planes(cm); ++plane) {
int rcol0, rcol1, rrow0, rrow1, tile_tl_idx;
if (av1_loop_restoration_corners_in_sb(cm, plane, mi_row, mi_col, bsize,
&rcol0, &rcol1, &rrow0, &rrow1,
@@ -2526,8 +2532,13 @@
#if CONFIG_INTRABC
if (cm->allow_intrabc && NO_FILTER_FOR_IBC) return;
#endif // CONFIG_INTRABC
- for (int p = 0; p < MAX_MB_PLANE; ++p) {
+ int all_none = 1, chroma_none = 1;
+ for (int p = 0; p < av1_num_planes(cm); ++p) {
RestorationInfo *rsi = &cm->rst_info[p];
+ if (rsi->frame_restoration_type != RESTORE_NONE) {
+ all_none = 0;
+ chroma_none &= p == 0;
+ }
switch (rsi->frame_restoration_type) {
case RESTORE_NONE:
aom_wb_write_bit(wb, 0);
@@ -2548,9 +2559,7 @@
default: assert(0);
}
}
- if (cm->rst_info[0].frame_restoration_type != RESTORE_NONE ||
- cm->rst_info[1].frame_restoration_type != RESTORE_NONE ||
- cm->rst_info[2].frame_restoration_type != RESTORE_NONE) {
+ if (!all_none) {
RestorationInfo *rsi = &cm->rst_info[0];
const int qsize = RESTORATION_TILESIZE_MAX >> 2;
const int hsize = RESTORATION_TILESIZE_MAX >> 1;
@@ -2559,23 +2568,25 @@
aom_wb_write_bit(wb, rsi->restoration_unit_size != hsize);
}
}
- 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_unit_size !=
- cm->rst_info[0].restoration_unit_size);
- assert(cm->rst_info[1].restoration_unit_size ==
- cm->rst_info[0].restoration_unit_size ||
- cm->rst_info[1].restoration_unit_size ==
- (cm->rst_info[0].restoration_unit_size >> s));
- assert(cm->rst_info[2].restoration_unit_size ==
- cm->rst_info[1].restoration_unit_size);
- } else if (!s) {
- assert(cm->rst_info[1].restoration_unit_size ==
- cm->rst_info[0].restoration_unit_size);
- assert(cm->rst_info[2].restoration_unit_size ==
- cm->rst_info[1].restoration_unit_size);
+
+ if (av1_num_planes(cm) > 1) {
+ int s = AOMMIN(cm->subsampling_x, cm->subsampling_y);
+ if (s && !chroma_none) {
+ aom_wb_write_bit(wb,
+ cm->rst_info[1].restoration_unit_size !=
+ cm->rst_info[0].restoration_unit_size);
+ assert(cm->rst_info[1].restoration_unit_size ==
+ cm->rst_info[0].restoration_unit_size ||
+ cm->rst_info[1].restoration_unit_size ==
+ (cm->rst_info[0].restoration_unit_size >> s));
+ assert(cm->rst_info[2].restoration_unit_size ==
+ cm->rst_info[1].restoration_unit_size);
+ } else if (!s) {
+ assert(cm->rst_info[1].restoration_unit_size ==
+ cm->rst_info[0].restoration_unit_size);
+ assert(cm->rst_info[2].restoration_unit_size ==
+ cm->rst_info[1].restoration_unit_size);
+ }
}
}
@@ -3658,7 +3669,6 @@
}
#if CONFIG_MONO_VIDEO
- seq_params->monochrome = cm->monochrome;
aom_wb_write_bit(wb, seq_params->monochrome);
#endif // CONFIG_MONO_VIDEO
}
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index c0d4563..74c293e 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -3608,7 +3608,8 @@
cpi->tile_tok[tile_row][tile_col] = pre_tok + tile_tok;
pre_tok = cpi->tile_tok[tile_row][tile_col];
- tile_tok = allocated_tokens(*tile_info, cm->mib_size_log2 + MI_SIZE_LOG2);
+ tile_tok = allocated_tokens(*tile_info, cm->mib_size_log2 + MI_SIZE_LOG2,
+ av1_num_planes(cm));
#if CONFIG_EXT_TILE
tile_data->allow_update_cdf = !cm->large_scale_tile;
@@ -3674,7 +3675,8 @@
cpi->tok_count[tile_row][tile_col] =
(unsigned int)(tok - cpi->tile_tok[tile_row][tile_col]);
assert(cpi->tok_count[tile_row][tile_col] <=
- allocated_tokens(*tile_info, cm->mib_size_log2 + MI_SIZE_LOG2));
+ allocated_tokens(*tile_info, cm->mib_size_log2 + MI_SIZE_LOG2,
+ av1_num_planes(cm)));
}
static void encode_tiles(AV1_COMP *cpi) {
@@ -4824,14 +4826,14 @@
const int mi_height = mi_size_high[bsize];
const int is_inter = is_inter_block(mbmi);
const BLOCK_SIZE block_size = bsize;
+ const int num_planes = av1_num_planes(cm);
if (!is_inter) {
#if CONFIG_CFL
xd->cfl->store_y = 1;
#endif // CONFIG_CFL
- int plane;
mbmi->skip = 1;
- for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
+ for (int plane = 0; plane < num_planes; ++plane) {
av1_encode_intra_block_plane((AV1_COMMON *)cm, x, block_size, plane, 1,
mi_row, mi_col);
}
@@ -4850,7 +4852,7 @@
}
if (bsize >= BLOCK_8X8) {
- for (plane = 0; plane <= 1; ++plane) {
+ for (int plane = 0; plane < AOMMIN(2, num_planes); ++plane) {
if (mbmi->palette_mode_info.palette_size[plane] > 0) {
if (!dry_run)
av1_tokenize_color_map(x, plane, 0, t, bsize, mbmi->tx_size,
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 649bfb0..e57d3d3 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -845,8 +845,8 @@
aom_free(cpi->tile_tok[0][0]);
{
- unsigned int tokens =
- get_token_alloc(cm->mb_rows, cm->mb_cols, MAX_SB_SIZE_LOG2);
+ unsigned int tokens = get_token_alloc(cm->mb_rows, cm->mb_cols,
+ MAX_SB_SIZE_LOG2, av1_num_planes(cm));
CHECK_MEM_ERROR(cm, cpi->tile_tok[0][0],
aom_calloc(tokens, sizeof(*cpi->tile_tok[0][0])));
}
@@ -5499,7 +5499,7 @@
#endif // CONFIG_EXT_TILE
#if CONFIG_MONO_VIDEO
- cm->monochrome = oxcf->monochrome;
+ cm->seq_params.monochrome = oxcf->monochrome;
#endif // CONFIG_MONO_VIDEO
#if CONFIG_XIPHRC
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index 2f72a28..b0ebd01 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -719,7 +719,7 @@
}
static INLINE unsigned int get_token_alloc(int mb_rows, int mb_cols,
- int sb_size_log2) {
+ int sb_size_log2, int num_planes) {
// Calculate the maximum number of max superblocks in the image.
const int shift = sb_size_log2 - 4;
const int sb_size = 1 << sb_size_log2;
@@ -727,10 +727,11 @@
const int sb_rows = ALIGN_POWER_OF_TWO(mb_rows, shift) >> shift;
const int sb_cols = ALIGN_POWER_OF_TWO(mb_cols, shift) >> shift;
- // For transform coefficients, assume 3 planes with no subsampling. We assume
+ // For transform coefficients, assume planes with no subsampling. We assume
// up to 1 token per pixel, and then allow a head room of 1 EOSB token per
// 4x4 block per plane, plus EOSB_TOKEN per plane.
- const int sb_coeff_toks = 3 * (sb_size_square + (sb_size_square / 16) + 1);
+ const int sb_coeff_toks =
+ num_planes * (sb_size_square + (sb_size_square / 16) + 1);
// For palette coefficients, there can be at most one palette for each 8x8
// block. If w, h are the width and height of the block, the palette has at
@@ -743,11 +744,12 @@
// Get the allocated token size for a tile. It does the same calculation as in
// the frame token allocation.
-static INLINE unsigned int allocated_tokens(TileInfo tile, int sb_size_log2) {
+static INLINE unsigned int allocated_tokens(TileInfo tile, int sb_size_log2,
+ int num_planes) {
int tile_mb_rows = (tile.mi_row_end - tile.mi_row_start + 2) >> 2;
int tile_mb_cols = (tile.mi_col_end - tile.mi_col_start + 2) >> 2;
- return get_token_alloc(tile_mb_rows, tile_mb_cols, sb_size_log2);
+ return get_token_alloc(tile_mb_rows, tile_mb_cols, sb_size_log2, num_planes);
}
#if CONFIG_TEMPMV_SIGNALING
diff --git a/av1/encoder/tokenize.c b/av1/encoder/tokenize.c
index 4bc36c9..56c169b6 100644
--- a/av1/encoder/tokenize.c
+++ b/av1/encoder/tokenize.c
@@ -647,7 +647,6 @@
TOKENEXTRA *t_backup = *t;
#endif
struct tokenize_b_args arg = { cpi, td, t, 0, allow_update_cdf };
- int plane;
if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) return;
if (mbmi->skip) {
@@ -663,7 +662,7 @@
*t = t_backup;
#endif
- for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
+ for (int plane = 0; plane < av1_num_planes(cm); ++plane) {
if (!is_chroma_reference(mi_row, mi_col, bsize,
xd->plane[plane].subsampling_x,
xd->plane[plane].subsampling_y)) {
@@ -735,10 +734,9 @@
return;
}
+ const int num_planes = av1_num_planes(&cpi->common);
if (!dry_run) {
- int plane;
-
- for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
+ for (int plane = 0; plane < num_planes; ++plane) {
if (!is_chroma_reference(mi_row, mi_col, bsize,
xd->plane[plane].subsampling_x,
xd->plane[plane].subsampling_y)) {
@@ -753,8 +751,7 @@
(*t)++;
}
} else if (dry_run == DRY_RUN_NORMAL) {
- int plane;
- for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
+ for (int plane = 0; plane < num_planes; ++plane) {
if (!is_chroma_reference(mi_row, mi_col, bsize,
xd->plane[plane].subsampling_x,
xd->plane[plane].subsampling_y))
@@ -763,8 +760,7 @@
set_entropy_context_b, &arg);
}
} else if (dry_run == DRY_RUN_COSTCOEFFS) {
- int plane;
- for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
+ for (int plane = 0; plane < num_planes; ++plane) {
if (!is_chroma_reference(mi_row, mi_col, bsize,
xd->plane[plane].subsampling_x,
xd->plane[plane].subsampling_y))