monochrome_test.cc (8144B)
1 /* 2 * Copyright (c) 2016, Alliance for Open Media. All rights reserved. 3 * 4 * This source code is subject to the terms of the BSD 2 Clause License and 5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License 6 * was not distributed with this source code in the LICENSE file, you can 7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open 8 * Media Patent License 1.0 was not distributed with this source code in the 9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent. 10 */ 11 12 #include <climits> 13 #include <vector> 14 15 #include "gtest/gtest.h" 16 17 #include "config/aom_config.h" 18 #include "test/codec_factory.h" 19 #include "test/encode_test_driver.h" 20 #include "test/i420_video_source.h" 21 #include "test/video_source.h" 22 #include "test/util.h" 23 24 namespace { 25 26 const unsigned int kCqLevel = 18; 27 const double kMaxPsnr = 100.0; 28 29 // kPsnrThreshold represents the psnr threshold used to validate the quality of 30 // the first frame. The indices correspond to one/two-pass, allintra and 31 // realtime encoding modes. 32 const double kPsnrThreshold[3] = { 29.0, 41.5, 41.5 }; 33 34 // kPsnrFluctuation represents the maximum allowed psnr fluctuation w.r.t first 35 // frame. The indices correspond to one/two-pass, allintra and realtime 36 // encoding modes. 37 const double kPsnrFluctuation[3] = { 2.5, 0.3, 17.0 }; 38 39 class MonochromeTest 40 : public ::libaom_test::CodecTestWith3Params<libaom_test::TestMode, int, 41 int>, 42 public ::libaom_test::EncoderTest { 43 protected: 44 MonochromeTest() 45 : EncoderTest(GET_PARAM(0)), lossless_(GET_PARAM(2)), 46 frame0_psnr_y_(0.0) {} 47 48 ~MonochromeTest() override = default; 49 50 void SetUp() override { InitializeConfig(GET_PARAM(1)); } 51 52 void PreEncodeFrameHook(::libaom_test::VideoSource *video, 53 ::libaom_test::Encoder *encoder) override { 54 if (video->frame() == 0) { 55 encoder->Control(AOME_SET_CPUUSED, GET_PARAM(3)); 56 if (mode_ == ::libaom_test::kAllIntra) { 57 encoder->Control(AOME_SET_CQ_LEVEL, kCqLevel); 58 } else if (mode_ == ::libaom_test::kRealTime) { 59 encoder->Control(AOME_SET_MAX_INTRA_BITRATE_PCT, 10000); 60 } 61 if (lossless_) { 62 encoder->Control(AV1E_SET_LOSSLESS, 1); 63 } 64 } 65 } 66 67 void DecompressedFrameHook(const aom_image_t &img, 68 aom_codec_pts_t pts) override { 69 (void)pts; 70 71 // Get value of top-left corner pixel of U plane 72 int chroma_value = img.planes[AOM_PLANE_U][0]; 73 74 bool is_chroma_constant = 75 ComparePlaneToValue(img, AOM_PLANE_U, chroma_value) && 76 ComparePlaneToValue(img, AOM_PLANE_V, chroma_value); 77 78 // Chroma planes should be constant 79 EXPECT_TRUE(is_chroma_constant); 80 81 // Monochrome flag on image should be set 82 EXPECT_EQ(img.monochrome, 1); 83 84 chroma_value_list_.push_back(chroma_value); 85 } 86 87 // Returns true if all pixels on the plane are equal to value, and returns 88 // false otherwise. 89 bool ComparePlaneToValue(const aom_image_t &img, const int plane, 90 const int value) { 91 const int w = aom_img_plane_width(&img, plane); 92 const int h = aom_img_plane_height(&img, plane); 93 const uint8_t *const buf = img.planes[plane]; 94 const int stride = img.stride[plane]; 95 96 for (int r = 0; r < h; ++r) { 97 for (int c = 0; c < w; ++c) { 98 if (buf[r * stride + c] != value) return false; 99 } 100 } 101 return true; 102 } 103 104 void PSNRPktHook(const aom_codec_cx_pkt_t *pkt) override { 105 // Check average PSNR value is >= 100 db in case of lossless encoding. 106 if (lossless_) { 107 EXPECT_GE(pkt->data.psnr.psnr[0], kMaxPsnr); 108 return; 109 } 110 const int psnr_index = (mode_ == ::libaom_test::kRealTime) ? 2 111 : (mode_ == ::libaom_test::kAllIntra) ? 1 112 : 0; 113 // Check that the initial Y PSNR value is 'high enough', and check that 114 // subsequent Y PSNR values are 'close' to this initial value. 115 if (frame0_psnr_y_ == 0.0) { 116 frame0_psnr_y_ = pkt->data.psnr.psnr[1]; 117 EXPECT_GT(frame0_psnr_y_, kPsnrThreshold[psnr_index]); 118 } 119 EXPECT_NEAR(pkt->data.psnr.psnr[1], frame0_psnr_y_, 120 kPsnrFluctuation[psnr_index]); 121 } 122 123 int lossless_; 124 std::vector<int> chroma_value_list_; 125 double frame0_psnr_y_; 126 }; 127 128 #if !CONFIG_REALTIME_ONLY 129 TEST_P(MonochromeTest, TestMonochromeEncoding) { 130 ::libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 131 30, 1, 0, 5); 132 133 init_flags_ = AOM_CODEC_USE_PSNR; 134 135 cfg_.rc_buf_initial_sz = 500; 136 cfg_.rc_buf_optimal_sz = 600; 137 cfg_.rc_buf_sz = 1000; 138 cfg_.rc_min_quantizer = 2; 139 cfg_.rc_max_quantizer = 56; 140 cfg_.rc_undershoot_pct = 50; 141 cfg_.rc_overshoot_pct = 50; 142 cfg_.rc_end_usage = AOM_CBR; 143 cfg_.g_lag_in_frames = 1; 144 cfg_.kf_min_dist = cfg_.kf_max_dist = 3000; 145 // Enable dropped frames. 146 cfg_.rc_dropframe_thresh = 1; 147 // Run at low bitrate. 148 cfg_.rc_target_bitrate = 40; 149 // Set monochrome encoding flag 150 cfg_.monochrome = 1; 151 152 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 153 154 // Check that the chroma planes are equal across all frames 155 std::vector<int>::const_iterator iter = chroma_value_list_.begin(); 156 int initial_chroma_value = *iter; 157 for (; iter != chroma_value_list_.end(); ++iter) { 158 // Check that all decoded frames have the same constant chroma planes. 159 EXPECT_EQ(*iter, initial_chroma_value); 160 } 161 } 162 163 class MonochromeAllIntraTest : public MonochromeTest {}; 164 165 TEST_P(MonochromeAllIntraTest, TestMonochromeEncoding) { 166 ::libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 167 30, 1, 0, 5); 168 init_flags_ = AOM_CODEC_USE_PSNR; 169 // Set monochrome encoding flag 170 cfg_.monochrome = 1; 171 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 172 173 // Check that the chroma planes are equal across all frames 174 std::vector<int>::const_iterator iter = chroma_value_list_.begin(); 175 int initial_chroma_value = *iter; 176 for (; iter != chroma_value_list_.end(); ++iter) { 177 // Check that all decoded frames have the same constant chroma planes. 178 EXPECT_EQ(*iter, initial_chroma_value); 179 } 180 } 181 182 #endif // !CONFIG_REALTIME_ONLY 183 184 class MonochromeRealtimeTest : public MonochromeTest {}; 185 186 TEST_P(MonochromeRealtimeTest, TestMonochromeEncoding) { 187 ::libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, 188 30, 1, 0, 30); 189 init_flags_ = AOM_CODEC_USE_PSNR; 190 // Set monochrome encoding flag 191 cfg_.monochrome = 1; 192 // Run at low bitrate. 193 cfg_.rc_target_bitrate = 40; 194 cfg_.rc_buf_sz = 6000; 195 cfg_.rc_buf_initial_sz = 4000; 196 cfg_.rc_buf_optimal_sz = 5000; 197 ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); 198 199 #if CONFIG_AV1_DECODER 200 // Check that the chroma planes are equal across all frames 201 std::vector<int>::const_iterator iter = chroma_value_list_.begin(); 202 int initial_chroma_value = *iter; 203 for (; iter != chroma_value_list_.end(); ++iter) { 204 // Check that all decoded frames have the same constant chroma planes. 205 EXPECT_EQ(*iter, initial_chroma_value); 206 } 207 #endif 208 } 209 210 #if !CONFIG_REALTIME_ONLY 211 AV1_INSTANTIATE_TEST_SUITE(MonochromeTest, 212 ::testing::Values(::libaom_test::kOnePassGood, 213 ::libaom_test::kTwoPassGood), 214 ::testing::Values(0), // lossless 215 ::testing::Values(0)); // cpu_used 216 217 AV1_INSTANTIATE_TEST_SUITE(MonochromeAllIntraTest, 218 ::testing::Values(::libaom_test::kAllIntra), 219 ::testing::Values(0, 1), // lossless 220 ::testing::Values(6, 9)); // cpu_used 221 #endif // !CONFIG_REALTIME_ONLY 222 223 AV1_INSTANTIATE_TEST_SUITE(MonochromeRealtimeTest, 224 ::testing::Values(::libaom_test::kRealTime), 225 ::testing::Values(0), // lossless 226 ::testing::Values(6, 8, 10)); // cpu_used 227 228 } // namespace