deltaq_mode_test.cc (7910B)
1 /* 2 * Copyright (c) 2023, 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 <cstddef> 13 #include <cstdint> 14 #include <vector> 15 16 #include "aom/aomcx.h" 17 #include "aom/aom_codec.h" 18 #include "aom/aom_encoder.h" 19 #include "aom/aom_image.h" 20 #include "config/aom_config.h" 21 #include "gtest/gtest.h" 22 23 namespace { 24 25 /* 26 Reproduces https://crbug.com/aomedia/3376. Emulates the command line: 27 28 ./aomenc --cpu-used=6 --threads=10 --cq-level=14 --passes=1 --limit=1 \ 29 --lag-in-frames=0 --end-usage=q --deltaq-mode=3 --min-q=0 --max-q=63 \ 30 -o output.av1 niklas_1280_720_30.y4m 31 */ 32 TEST(DeltaqModeTest, DeltaqMode3MultiThread) { 33 constexpr int kWidth = 1280; 34 constexpr int kHeight = 720; 35 // Dummy buffer of neutral gray samples. 36 constexpr size_t kBufferSize = kWidth * kHeight + kWidth * kHeight / 2; 37 std::vector<unsigned char> buffer(kBufferSize, 38 static_cast<unsigned char>(128)); 39 40 aom_image_t img; 41 EXPECT_EQ(&img, aom_img_wrap(&img, AOM_IMG_FMT_I420, kWidth, kHeight, 1, 42 buffer.data())); 43 44 aom_codec_iface_t *iface = aom_codec_av1_cx(); 45 aom_codec_enc_cfg_t cfg; 46 EXPECT_EQ(aom_codec_enc_config_default(iface, &cfg, AOM_USAGE_GOOD_QUALITY), 47 AOM_CODEC_OK); 48 cfg.g_w = kWidth; 49 cfg.g_h = kHeight; 50 cfg.g_threads = 10; 51 cfg.rc_end_usage = AOM_Q; 52 cfg.g_profile = 0; 53 cfg.g_bit_depth = AOM_BITS_8; 54 cfg.g_input_bit_depth = 8; 55 cfg.g_lag_in_frames = 0; 56 cfg.rc_min_quantizer = 0; 57 cfg.rc_max_quantizer = 63; 58 cfg.g_pass = AOM_RC_ONE_PASS; 59 cfg.g_limit = 1; 60 aom_codec_ctx_t enc; 61 EXPECT_EQ(aom_codec_enc_init(&enc, iface, &cfg, 0), AOM_CODEC_OK); 62 EXPECT_EQ(aom_codec_control(&enc, AOME_SET_CPUUSED, 6), AOM_CODEC_OK); 63 EXPECT_EQ(aom_codec_control(&enc, AOME_SET_CQ_LEVEL, 14), AOM_CODEC_OK); 64 EXPECT_EQ(aom_codec_control(&enc, AV1E_SET_DELTAQ_MODE, 3), AOM_CODEC_OK); 65 EXPECT_EQ(aom_codec_set_option(&enc, "passes", "1"), AOM_CODEC_OK); 66 EXPECT_EQ(aom_codec_control(&enc, AV1E_SET_COLOR_RANGE, AOM_CR_STUDIO_RANGE), 67 AOM_CODEC_OK); 68 69 EXPECT_EQ(aom_codec_encode(&enc, &img, 0, 1, 0), AOM_CODEC_OK); 70 aom_codec_iter_t iter = nullptr; 71 const aom_codec_cx_pkt_t *pkt = aom_codec_get_cx_data(&enc, &iter); 72 ASSERT_NE(pkt, nullptr); 73 EXPECT_EQ(pkt->kind, AOM_CODEC_CX_FRAME_PKT); 74 // pkt->data.frame.flags is 0x1f0011. 75 EXPECT_EQ(pkt->data.frame.flags & AOM_FRAME_IS_KEY, AOM_FRAME_IS_KEY); 76 pkt = aom_codec_get_cx_data(&enc, &iter); 77 EXPECT_EQ(pkt, nullptr); 78 79 // Flush encoder 80 EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, nullptr, 0, 1, 0)); 81 iter = nullptr; 82 pkt = aom_codec_get_cx_data(&enc, &iter); 83 EXPECT_EQ(pkt, nullptr); 84 85 EXPECT_EQ(AOM_CODEC_OK, aom_codec_destroy(&enc)); 86 } 87 88 // The implementation of multi-threading for deltaq-mode=3 in allintra 89 // mode is based on row multi-threading. 90 // The test ensures that When row mt is turned off, 91 // deltaq-mode = 3 can still properly encode and decode. 92 TEST(DeltaqModeTest, DeltaqMode3MultiThreadNoRowMT) { 93 constexpr int kWidth = 1280; 94 constexpr int kHeight = 720; 95 // Dummy buffer of neutral gray samples. 96 constexpr size_t kBufferSize = kWidth * kHeight + kWidth * kHeight / 2; 97 std::vector<unsigned char> buffer(kBufferSize, 98 static_cast<unsigned char>(128)); 99 100 aom_image_t img; 101 EXPECT_EQ(&img, aom_img_wrap(&img, AOM_IMG_FMT_I420, kWidth, kHeight, 1, 102 buffer.data())); 103 104 aom_codec_iface_t *iface = aom_codec_av1_cx(); 105 aom_codec_enc_cfg_t cfg; 106 EXPECT_EQ(aom_codec_enc_config_default(iface, &cfg, AOM_USAGE_GOOD_QUALITY), 107 AOM_CODEC_OK); 108 cfg.g_w = kWidth; 109 cfg.g_h = kHeight; 110 cfg.g_threads = 10; 111 cfg.rc_end_usage = AOM_Q; 112 cfg.g_profile = 0; 113 cfg.g_bit_depth = AOM_BITS_8; 114 cfg.g_input_bit_depth = 8; 115 cfg.g_lag_in_frames = 0; 116 cfg.rc_min_quantizer = 0; 117 cfg.rc_max_quantizer = 63; 118 cfg.g_pass = AOM_RC_ONE_PASS; 119 cfg.g_limit = 1; 120 aom_codec_ctx_t enc; 121 EXPECT_EQ(aom_codec_enc_init(&enc, iface, &cfg, 0), AOM_CODEC_OK); 122 EXPECT_EQ(aom_codec_control(&enc, AV1E_SET_ROW_MT, 0), AOM_CODEC_OK); 123 EXPECT_EQ(aom_codec_control(&enc, AOME_SET_CPUUSED, 6), AOM_CODEC_OK); 124 EXPECT_EQ(aom_codec_control(&enc, AOME_SET_CQ_LEVEL, 14), AOM_CODEC_OK); 125 EXPECT_EQ(aom_codec_control(&enc, AV1E_SET_DELTAQ_MODE, 3), AOM_CODEC_OK); 126 EXPECT_EQ(aom_codec_set_option(&enc, "passes", "1"), AOM_CODEC_OK); 127 EXPECT_EQ(aom_codec_control(&enc, AV1E_SET_COLOR_RANGE, AOM_CR_STUDIO_RANGE), 128 AOM_CODEC_OK); 129 130 EXPECT_EQ(aom_codec_encode(&enc, &img, 0, 1, 0), AOM_CODEC_OK); 131 aom_codec_iter_t iter = nullptr; 132 const aom_codec_cx_pkt_t *pkt = aom_codec_get_cx_data(&enc, &iter); 133 ASSERT_NE(pkt, nullptr); 134 EXPECT_EQ(pkt->kind, AOM_CODEC_CX_FRAME_PKT); 135 // pkt->data.frame.flags is 0x1f0011. 136 EXPECT_EQ(pkt->data.frame.flags & AOM_FRAME_IS_KEY, AOM_FRAME_IS_KEY); 137 pkt = aom_codec_get_cx_data(&enc, &iter); 138 EXPECT_EQ(pkt, nullptr); 139 140 // Flush encoder 141 EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, nullptr, 0, 1, 0)); 142 iter = nullptr; 143 pkt = aom_codec_get_cx_data(&enc, &iter); 144 EXPECT_EQ(pkt, nullptr); 145 146 EXPECT_EQ(AOM_CODEC_OK, aom_codec_destroy(&enc)); 147 } 148 149 #if CONFIG_AV1_HIGHBITDEPTH 150 // 10-bit version of the DeltaqMode3MultiThread test. 151 TEST(DeltaqModeTest, DeltaqMode3MultiThreadHighbd) { 152 constexpr int kWidth = 1280; 153 constexpr int kHeight = 720; 154 // Dummy buffer of 10-bit neutral gray samples. 155 constexpr size_t kBufferSize = kWidth * kHeight + kWidth * kHeight / 2; 156 std::vector<uint16_t> buffer(kBufferSize, 512); 157 158 aom_image_t img; 159 EXPECT_EQ(&img, 160 aom_img_wrap(&img, AOM_IMG_FMT_I42016, kWidth, kHeight, 1, 161 reinterpret_cast<unsigned char *>(buffer.data()))); 162 163 aom_codec_iface_t *iface = aom_codec_av1_cx(); 164 aom_codec_enc_cfg_t cfg; 165 EXPECT_EQ(aom_codec_enc_config_default(iface, &cfg, AOM_USAGE_GOOD_QUALITY), 166 AOM_CODEC_OK); 167 cfg.g_w = kWidth; 168 cfg.g_h = kHeight; 169 cfg.g_threads = 10; 170 cfg.rc_end_usage = AOM_Q; 171 cfg.g_profile = 0; 172 cfg.g_bit_depth = AOM_BITS_10; 173 cfg.g_input_bit_depth = 10; 174 cfg.g_lag_in_frames = 0; 175 cfg.rc_min_quantizer = 0; 176 cfg.rc_max_quantizer = 63; 177 cfg.g_pass = AOM_RC_ONE_PASS; 178 cfg.g_limit = 1; 179 aom_codec_ctx_t enc; 180 EXPECT_EQ(aom_codec_enc_init(&enc, iface, &cfg, AOM_CODEC_USE_HIGHBITDEPTH), 181 AOM_CODEC_OK); 182 EXPECT_EQ(aom_codec_control(&enc, AOME_SET_CPUUSED, 6), AOM_CODEC_OK); 183 EXPECT_EQ(aom_codec_control(&enc, AOME_SET_CQ_LEVEL, 14), AOM_CODEC_OK); 184 EXPECT_EQ(aom_codec_control(&enc, AV1E_SET_DELTAQ_MODE, 3), AOM_CODEC_OK); 185 EXPECT_EQ(aom_codec_set_option(&enc, "passes", "1"), AOM_CODEC_OK); 186 EXPECT_EQ(aom_codec_control(&enc, AV1E_SET_COLOR_RANGE, AOM_CR_STUDIO_RANGE), 187 AOM_CODEC_OK); 188 189 EXPECT_EQ(aom_codec_encode(&enc, &img, 0, 1, 0), AOM_CODEC_OK); 190 aom_codec_iter_t iter = nullptr; 191 const aom_codec_cx_pkt_t *pkt = aom_codec_get_cx_data(&enc, &iter); 192 ASSERT_NE(pkt, nullptr); 193 EXPECT_EQ(pkt->kind, AOM_CODEC_CX_FRAME_PKT); 194 // pkt->data.frame.flags is 0x1f0011. 195 EXPECT_EQ(pkt->data.frame.flags & AOM_FRAME_IS_KEY, AOM_FRAME_IS_KEY); 196 pkt = aom_codec_get_cx_data(&enc, &iter); 197 EXPECT_EQ(pkt, nullptr); 198 199 // Flush encoder 200 EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, nullptr, 0, 1, 0)); 201 iter = nullptr; 202 pkt = aom_codec_get_cx_data(&enc, &iter); 203 EXPECT_EQ(pkt, nullptr); 204 205 EXPECT_EQ(AOM_CODEC_OK, aom_codec_destroy(&enc)); 206 } 207 #endif // CONFIG_AV1_HIGHBITDEPTH 208 209 } // namespace