xref: /aosp_15_r20/external/libaom/test/deltaq_mode_test.cc (revision 77c1e3ccc04c968bd2bc212e87364f250e820521)
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 */
TEST(DeltaqModeTest,DeltaqMode3MultiThread)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.
TEST(DeltaqModeTest,DeltaqMode3MultiThreadNoRowMT)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.
TEST(DeltaqModeTest,DeltaqMode3MultiThreadHighbd)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
210