vp9_end_to_end_test.cc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. /*
  2. * Copyright (c) 2014 The WebM project authors. All Rights Reserved.
  3. *
  4. * Use of this source code is governed by a BSD-style license
  5. * that can be found in the LICENSE file in the root of the source
  6. * tree. An additional intellectual property rights grant can be found
  7. * in the file PATENTS. All contributing project authors may
  8. * be found in the AUTHORS file in the root of the source tree.
  9. */
  10. #include "memory"
  11. #include "third_party/googletest/src/include/gtest/gtest.h"
  12. #include "test/codec_factory.h"
  13. #include "test/encode_test_driver.h"
  14. #include "test/i420_video_source.h"
  15. #include "test/util.h"
  16. #include "test/y4m_video_source.h"
  17. #include "test/yuv_video_source.h"
  18. namespace {
  19. const unsigned int kWidth = 160;
  20. const unsigned int kHeight = 90;
  21. const unsigned int kFramerate = 50;
  22. const unsigned int kFrames = 20;
  23. const int kBitrate = 500;
  24. // List of psnr thresholds for speed settings 0-7 and 5 encoding modes
  25. const double kPsnrThreshold[][5] = {
  26. { 36.0, 37.0, 37.0, 37.0, 37.0 }, { 35.0, 36.0, 36.0, 36.0, 36.0 },
  27. { 34.0, 35.0, 35.0, 35.0, 35.0 }, { 33.0, 34.0, 34.0, 34.0, 34.0 },
  28. { 32.0, 33.0, 33.0, 33.0, 33.0 }, { 28.0, 32.0, 32.0, 32.0, 32.0 },
  29. { 28.5, 31.0, 31.0, 31.0, 31.0 }, { 27.5, 30.0, 30.0, 30.0, 30.0 },
  30. };
  31. typedef struct {
  32. const char *filename;
  33. unsigned int input_bit_depth;
  34. vpx_img_fmt fmt;
  35. vpx_bit_depth_t bit_depth;
  36. unsigned int profile;
  37. } TestVideoParam;
  38. const TestVideoParam kTestVectors[] = {
  39. { "park_joy_90p_8_420.y4m", 8, VPX_IMG_FMT_I420, VPX_BITS_8, 0 },
  40. { "park_joy_90p_8_422.y4m", 8, VPX_IMG_FMT_I422, VPX_BITS_8, 1 },
  41. { "park_joy_90p_8_444.y4m", 8, VPX_IMG_FMT_I444, VPX_BITS_8, 1 },
  42. { "park_joy_90p_8_440.yuv", 8, VPX_IMG_FMT_I440, VPX_BITS_8, 1 },
  43. #if CONFIG_VP9_HIGHBITDEPTH
  44. { "park_joy_90p_10_420_20f.y4m", 10, VPX_IMG_FMT_I42016, VPX_BITS_10, 2 },
  45. { "park_joy_90p_10_422_20f.y4m", 10, VPX_IMG_FMT_I42216, VPX_BITS_10, 3 },
  46. { "park_joy_90p_10_444_20f.y4m", 10, VPX_IMG_FMT_I44416, VPX_BITS_10, 3 },
  47. { "park_joy_90p_10_440.yuv", 10, VPX_IMG_FMT_I44016, VPX_BITS_10, 3 },
  48. { "park_joy_90p_12_420_20f.y4m", 12, VPX_IMG_FMT_I42016, VPX_BITS_12, 2 },
  49. { "park_joy_90p_12_422_20f.y4m", 12, VPX_IMG_FMT_I42216, VPX_BITS_12, 3 },
  50. { "park_joy_90p_12_444_20f.y4m", 12, VPX_IMG_FMT_I44416, VPX_BITS_12, 3 },
  51. { "park_joy_90p_12_440.yuv", 12, VPX_IMG_FMT_I44016, VPX_BITS_12, 3 },
  52. #endif // CONFIG_VP9_HIGHBITDEPTH
  53. };
  54. // Encoding modes tested
  55. const libvpx_test::TestMode kEncodingModeVectors[] = {
  56. ::libvpx_test::kTwoPassGood, ::libvpx_test::kOnePassGood,
  57. ::libvpx_test::kRealTime
  58. };
  59. // Speed settings tested
  60. const int kCpuUsedVectors[] = { 1, 2, 3, 5, 6, 7 };
  61. int is_extension_y4m(const char *filename) {
  62. const char *dot = strrchr(filename, '.');
  63. if (!dot || dot == filename) {
  64. return 0;
  65. } else {
  66. return !strcmp(dot, ".y4m");
  67. }
  68. }
  69. class EndToEndTestAdaptiveRDThresh
  70. : public ::libvpx_test::EncoderTest,
  71. public ::libvpx_test::CodecTestWith2Params<int, int> {
  72. protected:
  73. EndToEndTestAdaptiveRDThresh()
  74. : EncoderTest(GET_PARAM(0)), cpu_used_start_(GET_PARAM(1)),
  75. cpu_used_end_(GET_PARAM(2)) {}
  76. virtual ~EndToEndTestAdaptiveRDThresh() {}
  77. virtual void SetUp() {
  78. InitializeConfig();
  79. SetMode(::libvpx_test::kRealTime);
  80. cfg_.g_lag_in_frames = 0;
  81. cfg_.rc_end_usage = VPX_CBR;
  82. cfg_.rc_buf_sz = 1000;
  83. cfg_.rc_buf_initial_sz = 500;
  84. cfg_.rc_buf_optimal_sz = 600;
  85. dec_cfg_.threads = 4;
  86. }
  87. virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
  88. ::libvpx_test::Encoder *encoder) {
  89. if (video->frame() == 0) {
  90. encoder->Control(VP8E_SET_CPUUSED, cpu_used_start_);
  91. encoder->Control(VP9E_SET_ROW_MT, 1);
  92. encoder->Control(VP9E_SET_TILE_COLUMNS, 2);
  93. }
  94. if (video->frame() == 100)
  95. encoder->Control(VP8E_SET_CPUUSED, cpu_used_end_);
  96. }
  97. private:
  98. int cpu_used_start_;
  99. int cpu_used_end_;
  100. };
  101. class EndToEndTestLarge
  102. : public ::libvpx_test::EncoderTest,
  103. public ::libvpx_test::CodecTestWith3Params<libvpx_test::TestMode,
  104. TestVideoParam, int> {
  105. protected:
  106. EndToEndTestLarge()
  107. : EncoderTest(GET_PARAM(0)), test_video_param_(GET_PARAM(2)),
  108. cpu_used_(GET_PARAM(3)), psnr_(0.0), nframes_(0),
  109. encoding_mode_(GET_PARAM(1)) {
  110. cyclic_refresh_ = 0;
  111. denoiser_on_ = 0;
  112. }
  113. virtual ~EndToEndTestLarge() {}
  114. virtual void SetUp() {
  115. InitializeConfig();
  116. SetMode(encoding_mode_);
  117. if (encoding_mode_ != ::libvpx_test::kRealTime) {
  118. cfg_.g_lag_in_frames = 5;
  119. cfg_.rc_end_usage = VPX_VBR;
  120. } else {
  121. cfg_.g_lag_in_frames = 0;
  122. cfg_.rc_end_usage = VPX_CBR;
  123. cfg_.rc_buf_sz = 1000;
  124. cfg_.rc_buf_initial_sz = 500;
  125. cfg_.rc_buf_optimal_sz = 600;
  126. }
  127. dec_cfg_.threads = 4;
  128. }
  129. virtual void BeginPassHook(unsigned int) {
  130. psnr_ = 0.0;
  131. nframes_ = 0;
  132. }
  133. virtual void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) {
  134. psnr_ += pkt->data.psnr.psnr[0];
  135. nframes_++;
  136. }
  137. virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
  138. ::libvpx_test::Encoder *encoder) {
  139. if (video->frame() == 0) {
  140. encoder->Control(VP9E_SET_FRAME_PARALLEL_DECODING, 1);
  141. encoder->Control(VP9E_SET_TILE_COLUMNS, 4);
  142. encoder->Control(VP8E_SET_CPUUSED, cpu_used_);
  143. if (encoding_mode_ != ::libvpx_test::kRealTime) {
  144. encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
  145. encoder->Control(VP8E_SET_ARNR_MAXFRAMES, 7);
  146. encoder->Control(VP8E_SET_ARNR_STRENGTH, 5);
  147. encoder->Control(VP8E_SET_ARNR_TYPE, 3);
  148. } else {
  149. encoder->Control(VP9E_SET_NOISE_SENSITIVITY, denoiser_on_);
  150. encoder->Control(VP9E_SET_AQ_MODE, cyclic_refresh_);
  151. }
  152. }
  153. }
  154. double GetAveragePsnr() const {
  155. if (nframes_) return psnr_ / nframes_;
  156. return 0.0;
  157. }
  158. double GetPsnrThreshold() {
  159. return kPsnrThreshold[cpu_used_][encoding_mode_];
  160. }
  161. TestVideoParam test_video_param_;
  162. int cpu_used_;
  163. int cyclic_refresh_;
  164. int denoiser_on_;
  165. private:
  166. double psnr_;
  167. unsigned int nframes_;
  168. libvpx_test::TestMode encoding_mode_;
  169. };
  170. #if CONFIG_VP9_DECODER
  171. // The test parameters control VP9D_SET_LOOP_FILTER_OPT and the number of
  172. // decoder threads.
  173. class EndToEndTestLoopFilterThreading
  174. : public ::libvpx_test::EncoderTest,
  175. public ::libvpx_test::CodecTestWith2Params<bool, int> {
  176. protected:
  177. EndToEndTestLoopFilterThreading()
  178. : EncoderTest(GET_PARAM(0)), use_loop_filter_opt_(GET_PARAM(1)) {}
  179. virtual ~EndToEndTestLoopFilterThreading() {}
  180. virtual void SetUp() {
  181. InitializeConfig();
  182. SetMode(::libvpx_test::kRealTime);
  183. cfg_.g_threads = 2;
  184. cfg_.g_lag_in_frames = 0;
  185. cfg_.rc_target_bitrate = 500;
  186. cfg_.rc_end_usage = VPX_CBR;
  187. cfg_.kf_min_dist = 1;
  188. cfg_.kf_max_dist = 1;
  189. dec_cfg_.threads = GET_PARAM(2);
  190. }
  191. virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
  192. ::libvpx_test::Encoder *encoder) {
  193. if (video->frame() == 0) {
  194. encoder->Control(VP8E_SET_CPUUSED, 8);
  195. }
  196. encoder->Control(VP9E_SET_TILE_COLUMNS, 4 - video->frame() % 5);
  197. }
  198. virtual void PreDecodeFrameHook(::libvpx_test::VideoSource *video,
  199. ::libvpx_test::Decoder *decoder) {
  200. if (video->frame() == 0) {
  201. decoder->Control(VP9D_SET_LOOP_FILTER_OPT, use_loop_filter_opt_ ? 1 : 0);
  202. }
  203. }
  204. private:
  205. const bool use_loop_filter_opt_;
  206. };
  207. #endif // CONFIG_VP9_DECODER
  208. TEST_P(EndToEndTestLarge, EndtoEndPSNRTest) {
  209. cfg_.rc_target_bitrate = kBitrate;
  210. cfg_.g_error_resilient = 0;
  211. cfg_.g_profile = test_video_param_.profile;
  212. cfg_.g_input_bit_depth = test_video_param_.input_bit_depth;
  213. cfg_.g_bit_depth = test_video_param_.bit_depth;
  214. init_flags_ = VPX_CODEC_USE_PSNR;
  215. if (cfg_.g_bit_depth > 8) init_flags_ |= VPX_CODEC_USE_HIGHBITDEPTH;
  216. std::unique_ptr<libvpx_test::VideoSource> video;
  217. if (is_extension_y4m(test_video_param_.filename)) {
  218. video.reset(new libvpx_test::Y4mVideoSource(test_video_param_.filename, 0,
  219. kFrames));
  220. } else {
  221. video.reset(new libvpx_test::YUVVideoSource(
  222. test_video_param_.filename, test_video_param_.fmt, kWidth, kHeight,
  223. kFramerate, 1, 0, kFrames));
  224. }
  225. ASSERT_TRUE(video.get() != NULL);
  226. ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
  227. const double psnr = GetAveragePsnr();
  228. EXPECT_GT(psnr, GetPsnrThreshold());
  229. }
  230. TEST_P(EndToEndTestLarge, EndtoEndPSNRDenoiserAQTest) {
  231. cfg_.rc_target_bitrate = kBitrate;
  232. cfg_.g_error_resilient = 0;
  233. cfg_.g_profile = test_video_param_.profile;
  234. cfg_.g_input_bit_depth = test_video_param_.input_bit_depth;
  235. cfg_.g_bit_depth = test_video_param_.bit_depth;
  236. init_flags_ = VPX_CODEC_USE_PSNR;
  237. cyclic_refresh_ = 3;
  238. denoiser_on_ = 1;
  239. if (cfg_.g_bit_depth > 8) init_flags_ |= VPX_CODEC_USE_HIGHBITDEPTH;
  240. std::unique_ptr<libvpx_test::VideoSource> video;
  241. if (is_extension_y4m(test_video_param_.filename)) {
  242. video.reset(new libvpx_test::Y4mVideoSource(test_video_param_.filename, 0,
  243. kFrames));
  244. } else {
  245. video.reset(new libvpx_test::YUVVideoSource(
  246. test_video_param_.filename, test_video_param_.fmt, kWidth, kHeight,
  247. kFramerate, 1, 0, kFrames));
  248. }
  249. ASSERT_TRUE(video.get() != NULL);
  250. ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
  251. const double psnr = GetAveragePsnr();
  252. EXPECT_GT(psnr, GetPsnrThreshold());
  253. }
  254. TEST_P(EndToEndTestAdaptiveRDThresh, EndtoEndAdaptiveRDThreshRowMT) {
  255. cfg_.rc_target_bitrate = kBitrate;
  256. cfg_.g_error_resilient = 0;
  257. cfg_.g_threads = 2;
  258. ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
  259. 0, 400);
  260. ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
  261. }
  262. #if CONFIG_VP9_DECODER
  263. TEST_P(EndToEndTestLoopFilterThreading, TileCountChange) {
  264. ::libvpx_test::RandomVideoSource video;
  265. video.SetSize(4096, 2160);
  266. video.set_limit(10);
  267. ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
  268. }
  269. #endif // CONFIG_VP9_DECODER
  270. VP9_INSTANTIATE_TEST_CASE(EndToEndTestLarge,
  271. ::testing::ValuesIn(kEncodingModeVectors),
  272. ::testing::ValuesIn(kTestVectors),
  273. ::testing::ValuesIn(kCpuUsedVectors));
  274. VP9_INSTANTIATE_TEST_CASE(EndToEndTestAdaptiveRDThresh,
  275. ::testing::Values(5, 6, 7), ::testing::Values(8, 9));
  276. #if CONFIG_VP9_DECODER
  277. VP9_INSTANTIATE_TEST_CASE(EndToEndTestLoopFilterThreading, ::testing::Bool(),
  278. ::testing::Range(2, 6));
  279. #endif // CONFIG_VP9_DECODER
  280. } // namespace