Commit dcb3cff5 authored by Rupert Swarbrick's avatar Rupert Swarbrick Committed by Debargha Mukherjee

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
parent dfcbfbd4
......@@ -1682,7 +1682,7 @@ static float usec_to_fps(uint64_t usec, unsigned int frames) {
}
static void test_decode(struct stream_state *stream,
enum TestDecodeFatality fatal) {
enum TestDecodeFatality fatal, int is_mono) {
aom_image_t enc_img, dec_img;
if (stream->mismatch_seen) return;
......@@ -1714,7 +1714,7 @@ static void test_decode(struct stream_state *stream,
ctx_exit_on_error(&stream->encoder, "Failed to get encoder reference frame");
ctx_exit_on_error(&stream->decoder, "Failed to get decoder reference frame");
if (!aom_compare_img(&enc_img, &dec_img)) {
if (!aom_compare_img(&enc_img, &dec_img, is_mono ? 1 : 3)) {
int y[4], u[4], v[4];
#if CONFIG_HIGHBITDEPTH
if (enc_img.fmt & AOM_IMG_FMT_HIGHBITDEPTH) {
......@@ -2132,7 +2132,8 @@ int main(int argc, const char **argv_) {
if (got_data && global.test_decode != TEST_DECODE_OFF) {
FOREACH_STREAM(stream, streams) {
test_decode(stream, global.test_decode);
test_decode(stream, global.test_decode,
stream->config.cfg.monochrome);
}
}
}
......
......@@ -483,10 +483,6 @@ typedef struct AV1Common {
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 @@ static INLINE int max_intra_block_height(const MACROBLOCKD *xd,
}
#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;
......
......@@ -486,8 +486,7 @@ static void decode_token_and_recon_block(AV1Decoder *const pbi,
#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 @@ static void decode_token_and_recon_block(AV1Decoder *const pbi,
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 @@ static void decode_token_and_recon_block(AV1Decoder *const pbi,
// 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 @@ static void decode_partition(AV1Decoder *const pbi, MACROBLOCKD *const xd,
}
}
#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 @@ static void decode_restoration_mode(AV1_COMMON *cm,
#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 @@ static void decode_restoration_mode(AV1_COMMON *cm,
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 @@ static void decode_restoration_mode(AV1_COMMON *cm,
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,
......
......@@ -1212,7 +1212,12 @@ static void write_palette_mode_info(const AV1_COMMON *cm, const MACROBLOCKD *xd,
}
}
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 @@ static void write_tokens_b(AV1_COMP *cpi, const TileInfo *const tile,
#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 @@ static void write_tokens_b(AV1_COMP *cpi, const TileInfo *const tile,
#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 @@ static void write_modes_sb(AV1_COMP *const cpi, const TileInfo *const tile,
}
}
#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 @@ static void encode_restoration_mode(AV1_COMMON *cm,
#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 @@ static void encode_restoration_mode(AV1_COMMON *cm,
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 @@ static void encode_restoration_mode(AV1_COMMON *cm,
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 @@ void write_sequence_header(AV1_COMP *cpi, struct aom_write_bit_buffer *wb) {
}
#if CONFIG_MONO_VIDEO
seq_params->monochrome = cm->monochrome;
aom_wb_write_bit(wb, seq_params->monochrome);
#endif // CONFIG_MONO_VIDEO
}
......
......@@ -3608,7 +3608,8 @@ void av1_init_tile_data(AV1_COMP *cpi) {
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 @@ void av1_encode_tile(AV1_COMP *cpi, ThreadData *td, int tile_row,
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 @@ static void encode_superblock(const AV1_COMP *const cpi, TileDataEnc *tile_data,
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 @@ static void encode_superblock(const AV1_COMP *const cpi, TileDataEnc *tile_data,
}
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,
......
......@@ -845,8 +845,8 @@ static void alloc_compressor_data(AV1_COMP *cpi) {
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 @@ static void encode_frame_to_data_rate(AV1_COMP *cpi, size_t *size,
#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
......
......@@ -719,7 +719,7 @@ static INLINE int enc_is_ref_frame_buf(AV1_COMP *cpi, RefCntBuffer *frame_buf) {
}
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 @@ static INLINE unsigned int get_token_alloc(int mb_rows, int mb_cols,
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 @@ static INLINE unsigned int get_token_alloc(int mb_rows, int mb_cols,
// 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
......
......@@ -647,7 +647,6 @@ void av1_tokenize_sb_vartx(const AV1_COMP *cpi, ThreadData *td, TOKENEXTRA **t,
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 @@ void av1_tokenize_sb_vartx(const AV1_COMP *cpi, ThreadData *td, TOKENEXTRA **t,
*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 @@ void av1_tokenize_sb(const AV1_COMP *cpi, ThreadData *td, TOKENEXTRA **t,
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 @@ void av1_tokenize_sb(const AV1_COMP *cpi, ThreadData *td, TOKENEXTRA **t,
(*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 @@ void av1_tokenize_sb(const AV1_COMP *cpi, ThreadData *td, TOKENEXTRA **t,
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))
......
......@@ -69,7 +69,8 @@ void usage_exit() {
}
static void testing_decode(aom_codec_ctx_t *encoder, aom_codec_ctx_t *decoder,
unsigned int frame_out, int *mismatch_seen) {
unsigned int frame_out, int *mismatch_seen,
int is_mono) {
aom_image_t enc_img, dec_img;
struct av1_ref_frame ref_enc, ref_dec;
......@@ -84,7 +85,7 @@ static void testing_decode(aom_codec_ctx_t *encoder, aom_codec_ctx_t *decoder,
die_codec(decoder, "Failed to get decoder reference frame");
dec_img = ref_dec.img;
if (!aom_compare_img(&enc_img, &dec_img)) {
if (!aom_compare_img(&enc_img, &dec_img, is_mono ? 1 : 3)) {
int y[4], u[4], v[4];
*mismatch_seen = 1;
......@@ -106,7 +107,8 @@ static void testing_decode(aom_codec_ctx_t *encoder, aom_codec_ctx_t *decoder,
static int encode_frame(aom_codec_ctx_t *ecodec, aom_image_t *img,
unsigned int frame_in, AvxVideoWriter *writer,
int test_decode, aom_codec_ctx_t *dcodec,
unsigned int *frame_out, int *mismatch_seen) {
unsigned int *frame_out, int *mismatch_seen,
int is_mono) {
int got_pkts = 0;
aom_codec_iter_t iter = NULL;
const aom_codec_cx_pkt_t *pkt = NULL;
......@@ -147,7 +149,7 @@ static int encode_frame(aom_codec_ctx_t *ecodec, aom_image_t *img,
// Mismatch checking
if (got_data && test_decode) {
testing_decode(ecodec, dcodec, *frame_out, mismatch_seen);
testing_decode(ecodec, dcodec, *frame_out, mismatch_seen, is_mono);
}
return got_pkts;
......@@ -287,7 +289,7 @@ int main(int argc, char **argv) {
}
encode_frame(&ecodec, &raw, frame_in, writer, test_decode, &dcodec,
&frame_out, &mismatch_seen);
&frame_out, &mismatch_seen, cfg.monochrome);
frame_in++;
if (mismatch_seen) break;
}
......@@ -295,7 +297,7 @@ int main(int argc, char **argv) {
// Flush encoder.
if (!mismatch_seen)
while (encode_frame(&ecodec, NULL, frame_in, writer, test_decode, &dcodec,
&frame_out, &mismatch_seen)) {
&frame_out, &mismatch_seen, cfg.monochrome)) {
}
printf("\n");
......
......@@ -102,12 +102,11 @@ void aom_find_mismatch(const aom_image_t *const img1,
}
int aom_compare_img(const aom_image_t *const img1,
const aom_image_t *const img2) {
const aom_image_t *const img2, int num_planes) {
uint32_t l_w = img1->d_w;
uint32_t c_w = (img1->d_w + img1->x_chroma_shift) >> img1->x_chroma_shift;
const uint32_t c_h =
(img1->d_h + img1->y_chroma_shift) >> img1->y_chroma_shift;
uint32_t i;
int match = 1;
match &= (img1->fmt == img2->fmt);
......@@ -120,20 +119,16 @@ int aom_compare_img(const aom_image_t *const img1,
}
#endif
for (i = 0; i < img1->d_h; ++i)
match &= (memcmp(img1->planes[AOM_PLANE_Y] + i * img1->stride[AOM_PLANE_Y],
img2->planes[AOM_PLANE_Y] + i * img2->stride[AOM_PLANE_Y],
l_w) == 0);
for (int plane = 0; plane < num_planes; ++plane) {
uint32_t height = plane ? c_h : img1->d_h;
uint32_t width = plane ? c_w : l_w;
for (i = 0; i < c_h; ++i)
match &= (memcmp(img1->planes[AOM_PLANE_U] + i * img1->stride[AOM_PLANE_U],
img2->planes[AOM_PLANE_U] + i * img2->stride[AOM_PLANE_U],
c_w) == 0);
for (i = 0; i < c_h; ++i)
match &= (memcmp(img1->planes[AOM_PLANE_V] + i * img1->stride[AOM_PLANE_V],
img2->planes[AOM_PLANE_V] + i * img2->stride[AOM_PLANE_V],
c_w) == 0);
for (uint32_t i = 0; i < height; ++i) {
match &=
(memcmp(img1->planes[plane] + i * img1->stride[plane],
img2->planes[plane] + i * img2->stride[plane], width) == 0);
}
}
return match;
}
......@@ -31,6 +31,6 @@ void aom_find_mismatch(const aom_image_t *const img1,
// Returns 1 if the two images match.
int aom_compare_img(const aom_image_t *const img1,
const aom_image_t *const img2);
const aom_image_t *const img2, int num_planes);
#endif // EXAMPLES_ENCODER_UTIL_H_
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment