• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <vector>
14 
15 #include "aom/aomcx.h"
16 #include "aom/aom_codec.h"
17 #include "aom/aom_encoder.h"
18 #include "aom/aom_image.h"
19 #include "third_party/googletest/src/googletest/include/gtest/gtest.h"
20 
21 namespace {
22 
23 // This test emulates how libavif calls libaom functions to encode a
24 // progressive AVIF image in libavif's ProgressiveTest.QualityChange test.
TEST(AVIFProgressiveTest,QualityChange)25 TEST(AVIFProgressiveTest, QualityChange) {
26   constexpr int kWidth = 256;
27   constexpr int kHeight = 256;
28   // Dummy buffer of neutral gray samples.
29   constexpr size_t kBufferSize = 3 * kWidth * kHeight;
30   std::vector<unsigned char> buffer(kBufferSize,
31                                     static_cast<unsigned char>(128));
32 
33   aom_image_t img;
34   EXPECT_EQ(&img, aom_img_wrap(&img, AOM_IMG_FMT_I444, kWidth, kHeight, 1,
35                                buffer.data()));
36 
37   aom_codec_iface_t *iface = aom_codec_av1_cx();
38   aom_codec_enc_cfg_t cfg;
39   const unsigned int usage = AOM_USAGE_GOOD_QUALITY;
40   EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_config_default(iface, &cfg, usage));
41   cfg.g_w = kWidth;
42   cfg.g_h = kHeight;
43   cfg.rc_end_usage = AOM_Q;
44   cfg.g_profile = 1;
45   cfg.g_bit_depth = AOM_BITS_8;
46   cfg.g_input_bit_depth = 8;
47   cfg.g_lag_in_frames = 0;
48   cfg.rc_min_quantizer = 50;
49   cfg.rc_max_quantizer = 50;
50   aom_codec_ctx_t enc;
51   EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_init(&enc, iface, &cfg, 0));
52   EXPECT_EQ(AOM_CODEC_OK, aom_codec_control(&enc, AOME_SET_CQ_LEVEL, 50));
53   EXPECT_EQ(AOM_CODEC_OK,
54             aom_codec_control(&enc, AOME_SET_NUMBER_SPATIAL_LAYERS, 2));
55   EXPECT_EQ(AOM_CODEC_OK, aom_codec_control(&enc, AOME_SET_CPUUSED, 6));
56   EXPECT_EQ(AOM_CODEC_OK,
57             aom_codec_control(&enc, AV1E_SET_COLOR_RANGE, AOM_CR_FULL_RANGE));
58   EXPECT_EQ(AOM_CODEC_OK,
59             aom_codec_control(&enc, AOME_SET_TUNING, AOM_TUNE_SSIM));
60 
61   // First frame (layer 0)
62   EXPECT_EQ(AOM_CODEC_OK,
63             aom_codec_control(&enc, AOME_SET_SPATIAL_LAYER_ID, 0));
64   EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, &img, 0, 1, 0));
65   aom_codec_iter_t iter = nullptr;
66   const aom_codec_cx_pkt_t *pkt = aom_codec_get_cx_data(&enc, &iter);
67   EXPECT_NE(pkt, nullptr);
68   EXPECT_EQ(pkt->kind, AOM_CODEC_CX_FRAME_PKT);
69   // pkt->data.frame.flags is 0x1f0011.
70   EXPECT_EQ(pkt->data.frame.flags & AOM_FRAME_IS_KEY, AOM_FRAME_IS_KEY);
71   pkt = aom_codec_get_cx_data(&enc, &iter);
72   EXPECT_EQ(pkt, nullptr);
73 
74   // Second frame (layer 1)
75   cfg.rc_min_quantizer = 0;
76   cfg.rc_max_quantizer = 0;
77   EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_config_set(&enc, &cfg));
78   EXPECT_EQ(AOM_CODEC_OK, aom_codec_control(&enc, AOME_SET_CQ_LEVEL, 0));
79   EXPECT_EQ(AOM_CODEC_OK, aom_codec_control(&enc, AV1E_SET_LOSSLESS, 1));
80   EXPECT_EQ(AOM_CODEC_OK,
81             aom_codec_control(&enc, AOME_SET_SPATIAL_LAYER_ID, 1));
82   aom_enc_frame_flags_t encode_flags =
83       AOM_EFLAG_NO_REF_GF | AOM_EFLAG_NO_REF_ARF | AOM_EFLAG_NO_REF_BWD |
84       AOM_EFLAG_NO_REF_ARF2 | AOM_EFLAG_NO_UPD_GF | AOM_EFLAG_NO_UPD_ARF;
85   EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, &img, 0, 1, encode_flags));
86   iter = nullptr;
87   pkt = aom_codec_get_cx_data(&enc, &iter);
88   EXPECT_NE(pkt, nullptr);
89   EXPECT_EQ(pkt->kind, AOM_CODEC_CX_FRAME_PKT);
90   // pkt->data.frame.flags is 0.
91   EXPECT_EQ(pkt->data.frame.flags & AOM_FRAME_IS_KEY, 0u);
92   pkt = aom_codec_get_cx_data(&enc, &iter);
93   EXPECT_EQ(pkt, nullptr);
94 
95   // Flush encoder
96   EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, nullptr, 0, 1, 0));
97   iter = nullptr;
98   pkt = aom_codec_get_cx_data(&enc, &iter);
99   EXPECT_EQ(pkt, nullptr);
100 
101   EXPECT_EQ(AOM_CODEC_OK, aom_codec_destroy(&enc));
102 }
103 
104 // This test emulates how libavif calls libaom functions to encode a
105 // progressive AVIF image in libavif's ProgressiveTest.DimensionChange test.
TEST(AVIFProgressiveTest,DimensionChange)106 TEST(AVIFProgressiveTest, DimensionChange) {
107   constexpr int kWidth = 256;
108   constexpr int kHeight = 256;
109   // Dummy buffer of neutral gray samples.
110   constexpr size_t kBufferSize = 3 * kWidth * kHeight;
111   std::vector<unsigned char> buffer(kBufferSize,
112                                     static_cast<unsigned char>(128));
113 
114   aom_image_t img;
115   EXPECT_EQ(&img, aom_img_wrap(&img, AOM_IMG_FMT_I444, kWidth, kHeight, 1,
116                                buffer.data()));
117 
118   aom_codec_iface_t *iface = aom_codec_av1_cx();
119   aom_codec_enc_cfg_t cfg;
120   const unsigned int usage = AOM_USAGE_GOOD_QUALITY;
121   EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_config_default(iface, &cfg, usage));
122   cfg.g_w = kWidth;
123   cfg.g_h = kHeight;
124   cfg.rc_end_usage = AOM_Q;
125   cfg.g_profile = 1;
126   cfg.g_bit_depth = AOM_BITS_8;
127   cfg.g_input_bit_depth = 8;
128   cfg.g_lag_in_frames = 0;
129   cfg.rc_min_quantizer = 0;
130   cfg.rc_max_quantizer = 0;
131   aom_codec_ctx_t enc;
132   EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_init(&enc, iface, &cfg, 0));
133   EXPECT_EQ(AOM_CODEC_OK, aom_codec_control(&enc, AOME_SET_CQ_LEVEL, 0));
134   EXPECT_EQ(AOM_CODEC_OK, aom_codec_control(&enc, AV1E_SET_LOSSLESS, 1));
135   EXPECT_EQ(AOM_CODEC_OK,
136             aom_codec_control(&enc, AOME_SET_NUMBER_SPATIAL_LAYERS, 2));
137   EXPECT_EQ(AOM_CODEC_OK, aom_codec_control(&enc, AOME_SET_CPUUSED, 6));
138   EXPECT_EQ(AOM_CODEC_OK,
139             aom_codec_control(&enc, AV1E_SET_COLOR_RANGE, AOM_CR_FULL_RANGE));
140   EXPECT_EQ(AOM_CODEC_OK,
141             aom_codec_control(&enc, AOME_SET_TUNING, AOM_TUNE_SSIM));
142 
143   // First frame (layer 0)
144   EXPECT_EQ(AOM_CODEC_OK,
145             aom_codec_control(&enc, AOME_SET_SPATIAL_LAYER_ID, 0));
146   aom_scaling_mode_t scaling_mode = { AOME_ONETWO, AOME_ONETWO };
147   EXPECT_EQ(AOM_CODEC_OK,
148             aom_codec_control(&enc, AOME_SET_SCALEMODE, &scaling_mode));
149   EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, &img, 0, 1, 0));
150   aom_codec_iter_t iter = nullptr;
151   const aom_codec_cx_pkt_t *pkt = aom_codec_get_cx_data(&enc, &iter);
152   EXPECT_NE(pkt, nullptr);
153   EXPECT_EQ(pkt->kind, AOM_CODEC_CX_FRAME_PKT);
154   // pkt->data.frame.flags is 0x1f0011.
155   EXPECT_EQ(pkt->data.frame.flags & AOM_FRAME_IS_KEY, AOM_FRAME_IS_KEY);
156   pkt = aom_codec_get_cx_data(&enc, &iter);
157   EXPECT_EQ(pkt, nullptr);
158 
159   // Second frame (layer 1)
160   EXPECT_EQ(AOM_CODEC_OK,
161             aom_codec_control(&enc, AOME_SET_SPATIAL_LAYER_ID, 1));
162   aom_enc_frame_flags_t encode_flags =
163       AOM_EFLAG_NO_REF_GF | AOM_EFLAG_NO_REF_ARF | AOM_EFLAG_NO_REF_BWD |
164       AOM_EFLAG_NO_REF_ARF2 | AOM_EFLAG_NO_UPD_GF | AOM_EFLAG_NO_UPD_ARF;
165   EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, &img, 0, 1, encode_flags));
166   iter = nullptr;
167   pkt = aom_codec_get_cx_data(&enc, &iter);
168   EXPECT_NE(pkt, nullptr);
169   EXPECT_EQ(pkt->kind, AOM_CODEC_CX_FRAME_PKT);
170   // pkt->data.frame.flags is 0.
171   EXPECT_EQ(pkt->data.frame.flags & AOM_FRAME_IS_KEY, 0u);
172   pkt = aom_codec_get_cx_data(&enc, &iter);
173   EXPECT_EQ(pkt, nullptr);
174 
175   // Flush encoder
176   EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, nullptr, 0, 1, 0));
177   iter = nullptr;
178   pkt = aom_codec_get_cx_data(&enc, &iter);
179   EXPECT_EQ(pkt, nullptr);
180 
181   EXPECT_EQ(AOM_CODEC_OK, aom_codec_destroy(&enc));
182 }
183 
184 }  // namespace
185