1 /*
2 * Copyright (C) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <gtest/gtest.h>
17 #include <fstream>
18 #include <string>
19 #include <chrono>
20 #include "buffer_packer_stream.h"
21 #include "image_type.h"
22 #include "image_utils.h"
23 #include "image_source.h"
24 #include "media_errors.h"
25 #include "pixel_map.h"
26
27 using namespace testing::ext;
28 using namespace OHOS::Media;
29
30 namespace OHOS {
31 namespace Multimedia {
32 static const std::string IMAGE_INPUT_HEIF_PATH = "/data/local/tmp/image/";
33 static constexpr uint32_t MAXSIZE = 10000;
34 #define ORIGINAL_WIDTH 480
35 #define ORIGINAL_HEIGHT 360
36 class HeifYuvTest : public testing::Test {
37 public:
HeifYuvTest()38 HeifYuvTest() {}
~HeifYuvTest()39 ~HeifYuvTest() {}
40
41 void TestDecodeToSize(int width, int height);
42 uint64_t GetNowTimeMicroSeconds();
43 void DoTimeTest(std::string heifName);
44 void DecodeToFormat(std::string srcHeif, PixelFormat outfmt, int width, int height);
45 void DecodeToYuv(std::string srcHeif, PixelFormat outfmt, std::string outname, int& width, int& height);
46 };
47
TestDecodeToSize(int width,int height)48 void HeifYuvTest::TestDecodeToSize(int width, int height)
49 {
50 const char* srcHeif[] = { "test.heic", "test_hw.heic", "test-10bit-1.heic", "test-10bit-2.heic"};
51 const char* outNamePart1[] = { "test", "test_hw", "test-10bit-1", "test-10bit-2"};
52 const char* outNamePart2[] = { "-nv12.yuv", "-nv21.yuv"};
53 PixelFormat outfmt[] = { PixelFormat::NV12, PixelFormat::NV21};
54 for (uint32_t k = 0; k < sizeof(srcHeif) / sizeof(char*); k++) {
55 for (uint32_t j = 0; j < sizeof(outfmt) / sizeof(PixelFormat); j++) {
56 std::string heifPath = IMAGE_INPUT_HEIF_PATH;
57 heifPath.append(srcHeif[k]);
58 std::string outname;
59 outname.append(outNamePart1[k]);
60 outname.append(outNamePart2[j]);
61 int outWidth = width;
62 int outHeight = height;
63 DecodeToYuv(heifPath, outfmt[j], outname, outWidth, outHeight);
64 }
65 }
66 }
67
GetNowTimeMicroSeconds()68 uint64_t HeifYuvTest::GetNowTimeMicroSeconds()
69 {
70 auto now = std::chrono::system_clock::now();
71 return std::chrono::duration_cast<std::chrono::microseconds>(now.time_since_epoch()).count();
72 }
73
DecodeToFormat(std::string srcHeif,PixelFormat outfmt,int width,int height)74 void HeifYuvTest::DecodeToFormat(std::string srcHeif, PixelFormat outfmt, int width, int height)
75 {
76 uint32_t errorCode = 0;
77 SourceOptions opts;
78 opts.formatHint = "image/heif";
79 std::unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(srcHeif, opts, errorCode);
80 ASSERT_EQ(errorCode, SUCCESS);
81 ASSERT_NE(imageSource.get(), nullptr);
82 DecodeOptions decodeOpts;
83 decodeOpts.desiredPixelFormat = outfmt;
84 decodeOpts.desiredSize.width = width;
85 decodeOpts.desiredSize.height = height;
86 std::unique_ptr<PixelMap> pixelMap = imageSource->CreatePixelMap(decodeOpts, errorCode);
87 ASSERT_EQ(errorCode, SUCCESS);
88 ASSERT_NE(pixelMap.get(), nullptr);
89 ASSERT_EQ(pixelMap->GetPixelFormat(), outfmt);
90 }
91
DoTimeTest(std::string heifName)92 void HeifYuvTest::DoTimeTest(std::string heifName)
93 {
94 GTEST_LOG_(INFO) << "HeifYuvTest:DoTimeTest for: " << heifName.c_str();
95 const int testCount = 10;
96 uint64_t startTick = GetNowTimeMicroSeconds();
97 for (uint32_t k = 0; k < testCount; k++) {
98 std::string heifPath = IMAGE_INPUT_HEIF_PATH;
99 heifPath.append(heifName);
100 DecodeToFormat(heifPath, PixelFormat::RGBA_8888, 0, 0);
101 }
102 uint64_t endTick = GetNowTimeMicroSeconds();
103 uint64_t argbCost = endTick - startTick;
104 GTEST_LOG_(INFO) << "HeifYuvTest:DoTimeTest time argbCost: " << argbCost;
105
106 startTick = GetNowTimeMicroSeconds();
107 for (uint32_t k = 0; k < testCount; k++) {
108 std::string heifPath = IMAGE_INPUT_HEIF_PATH;
109 heifPath.append(heifName);
110 DecodeToFormat(heifPath, PixelFormat::NV12, 0, 0);
111 }
112 endTick = GetNowTimeMicroSeconds();
113 uint64_t nv12Cost = endTick - startTick;
114 GTEST_LOG_(INFO) << "HeifYuvTest:DoTimeTest time nv12Cost: " << nv12Cost;
115 }
116
DecodeToYuv(std::string srcHeif,PixelFormat outfmt,std::string outname,int & width,int & height)117 void HeifYuvTest::DecodeToYuv(std::string srcHeif, PixelFormat outfmt, std::string outname, int& width, int& height)
118 {
119 GTEST_LOG_(INFO) << "HeifYuvTest: request size(" << width << ", " << height << ")";
120 uint32_t errorCode = 0;
121 SourceOptions opts;
122 opts.formatHint = "image/heif";
123 std::unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(srcHeif, opts, errorCode);
124 ASSERT_EQ(errorCode, SUCCESS);
125 ASSERT_NE(imageSource.get(), nullptr);
126
127 DecodeOptions decodeOpts;
128 decodeOpts.desiredPixelFormat = outfmt;
129 decodeOpts.desiredSize.width = width;
130 decodeOpts.desiredSize.height = height;
131 std::unique_ptr<PixelMap> pixelMap = imageSource->CreatePixelMap(decodeOpts, errorCode);
132 ASSERT_EQ(errorCode, SUCCESS);
133 ASSERT_NE(pixelMap.get(), nullptr);
134 uint8_t *data = const_cast<uint8_t *>(pixelMap->GetPixels());
135 const uint8_t *buffer = nullptr;
136 uint32_t size = pixelMap->GetCapacity();
137 uint32_t maxSize = MAXSIZE;
138 BufferPackerStream bufferPackerStream(data, maxSize);
139 bool ret = bufferPackerStream.Write(buffer, size);
140 ASSERT_EQ(pixelMap->GetPixelFormat(), outfmt);
141 ASSERT_EQ(ret, false);
142 width = pixelMap->GetWidth();
143 height = pixelMap->GetHeight();
144 GTEST_LOG_(INFO) << "HeifYuvTest: ret size(" << width << ", " << height << ")";
145 std::string outpath = "/tmp/";
146 outpath.append(std::to_string(width));
147 outpath.append("-");
148 outpath.append(std::to_string(height));
149 outpath.append("-");
150 outpath.append(outname);
151 FILE* outfile = fopen(outpath.c_str(), "wb");
152 if (outfile) {
153 fwrite(data, 1, size, outfile);
154 int fret = fclose(outfile);
155 if (fret != 0) {
156 ASSERT_TRUE(false);
157 }
158 }
159 }
160
161 HWTEST_F(HeifYuvTest, HeifYuvTest001, TestSize.Level3)
162 {
163 GTEST_LOG_(INFO) << "HeifYuvTest: HeifYuvTest001 start";
164 TestDecodeToSize(ORIGINAL_WIDTH, ORIGINAL_HEIGHT);
165 GTEST_LOG_(INFO) << "HeifYuvTest: HeifYuvTest001 end";
166 }
167
168 HWTEST_F(HeifYuvTest, HeifYuvTest002, TestSize.Level3)
169 {
170 GTEST_LOG_(INFO) << "HeifYuvTest: HeifYuvTest002 start";
171 int testWidth = 510;
172 int testHeight = 460;
173 TestDecodeToSize(testWidth, testHeight);
174 GTEST_LOG_(INFO) << "HeifYuvTest: HeifYuvTest002 end";
175 }
176
177 HWTEST_F(HeifYuvTest, HeifYuvTest003, TestSize.Level3)
178 {
179 GTEST_LOG_(INFO) << "HeifYuvTest: HeifYuvTest003 start";
180 int testWidth = 380;
181 int testHeight = 211;
182 TestDecodeToSize(testWidth, testHeight);
183 GTEST_LOG_(INFO) << "HeifYuvTest: HeifYuvTest003 end";
184 }
185
186 HWTEST_F(HeifYuvTest, HeifYuvTest004, TestSize.Level3)
187 {
188 GTEST_LOG_(INFO) << "HeifYuvTest: HeifYuvTest004 start";
189 int testWidth = 100;
190 int testHeight = 100;
191 TestDecodeToSize(testWidth, testHeight);
192 GTEST_LOG_(INFO) << "HeifYuvTest: HeifYuvTest004 end";
193 }
194
195 HWTEST_F(HeifYuvTest, HeifYuvTest005, TestSize.Level3)
196 {
197 GTEST_LOG_(INFO) << "HeifYuvTest: HeifYuvTest005 start";
198 int testWidth = 2000;
199 int testHeight = 2000;
200 TestDecodeToSize(testWidth, testHeight);
201 GTEST_LOG_(INFO) << "HeifYuvTest: HeifYuvTest005 end";
202 }
203
204 HWTEST_F(HeifYuvTest, HeifYuvTest006, TestSize.Level3)
205 {
206 GTEST_LOG_(INFO) << "HeifYuvTest: HeifYuvTest006 start";
207 PixelFormat outfmt[] = { PixelFormat::NV12, PixelFormat::NV21};
208 const char* outNamePart2[] = { "-nv12.yuv", "-nv21.yuv"};
209 for (uint32_t j = 0; j < sizeof(outfmt) / sizeof(PixelFormat); j++) {
210 std::string heifPath = IMAGE_INPUT_HEIF_PATH;
211 heifPath.append("test_hw.heic");
212 std::string outname;
213 outname.append("testhw");
214 outname.append(outNamePart2[j]);
215 int outWidth = 0;
216 int outHeight = 0;
217 DecodeToYuv(heifPath, outfmt[j], outname, outWidth, outHeight);
218 }
219 GTEST_LOG_(INFO) << "HeifYuvTest: HeifYuvTest006 end";
220 }
221
222 HWTEST_F(HeifYuvTest, HeifYuvTest007, TestSize.Level3)
223 {
224 GTEST_LOG_(INFO) << "HeifYuvTest: HeifYuvTest007 start";
225 std::string heifPath = IMAGE_INPUT_HEIF_PATH;
226 heifPath.append("test.heic");
227
228 uint32_t errorCode = 0;
229 SourceOptions opts;
230 opts.formatHint = "image/heif";
231 std::unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(heifPath, opts, errorCode);
232 ASSERT_EQ(errorCode, SUCCESS);
233 ASSERT_NE(imageSource.get(), nullptr);
234 DecodeOptions decodeOpts;
235 decodeOpts.desiredPixelFormat = PixelFormat::NV12;
236 decodeOpts.desiredSize.width = 0;
237 decodeOpts.desiredSize.height = 0;
238 std::unique_ptr<PixelMap> pixelMap = imageSource->CreatePixelMap(decodeOpts, errorCode);
239 ASSERT_EQ(errorCode, SUCCESS);
240 GTEST_LOG_(INFO) << "HeifYuvTest: HeifYuvTest007 end";
241 }
242
243 HWTEST_F(HeifYuvTest, HeifYuvTest008, TestSize.Level3)
244 {
245 GTEST_LOG_(INFO) << "HeifYuvTest: HeifYuvTest008 start";
246 std::string heifPath = IMAGE_INPUT_HEIF_PATH;
247 heifPath.append("test_bad.heic");
248
249 uint32_t errorCode = 0;
250 SourceOptions opts;
251 opts.formatHint = "image/heif";
252 std::unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(heifPath, opts, errorCode);
253 ASSERT_EQ(errorCode, SUCCESS);
254 ASSERT_NE(imageSource.get(), nullptr);
255 DecodeOptions decodeOpts;
256 decodeOpts.desiredPixelFormat = PixelFormat::NV12;
257 decodeOpts.desiredSize.width = 0;
258 decodeOpts.desiredSize.height = 0;
259 std::unique_ptr<PixelMap> pixelMap = imageSource->CreatePixelMap(decodeOpts, errorCode);
260 ASSERT_NE(errorCode, SUCCESS);
261 GTEST_LOG_(INFO) << "HeifYuvTest: HeifYuvTest008 end";
262 }
263
264 HWTEST_F(HeifYuvTest, HeifYuvTest009, TestSize.Level3)
265 {
266 GTEST_LOG_(INFO) << "HeifYuvTest: HeifYuvTest009 start";
267 std::string heifPath = IMAGE_INPUT_HEIF_PATH;
268 heifPath.append("test_null.jpg");
269
270 uint32_t errorCode = 0;
271 SourceOptions opts;
272 opts.formatHint = "image/heif";
273 std::unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(heifPath, opts, errorCode);
274 ASSERT_EQ(errorCode, SUCCESS);
275 ASSERT_NE(imageSource.get(), nullptr);
276 DecodeOptions decodeOpts;
277 decodeOpts.desiredPixelFormat = PixelFormat::NV12;
278 decodeOpts.desiredSize.width = 0;
279 decodeOpts.desiredSize.height = 0;
280 std::unique_ptr<PixelMap> pixelMap = imageSource->CreatePixelMap(decodeOpts, errorCode);
281 ASSERT_NE(errorCode, SUCCESS);
282 GTEST_LOG_(INFO) << "HeifYuvTest: HeifYuvTest009 end";
283 }
284
285 HWTEST_F(HeifYuvTest, HeifYuvTest010, TestSize.Level3)
286 {
287 GTEST_LOG_(INFO) << "HeifYuvTest: HeifYuvTest010 start";
288 int testWidth = 1;
289 int testHeight = 1;
290 TestDecodeToSize(testWidth, testHeight);
291 GTEST_LOG_(INFO) << "HeifYuvTest: HeifYuvTest010 end";
292 }
293
294 HWTEST_F(HeifYuvTest, HeifYuvTest011, TestSize.Level3)
295 {
296 GTEST_LOG_(INFO) << "HeifYuvTest: HeifYuvTest011 start";
297 int testWidth = 1;
298 int testHeight = 100;
299 TestDecodeToSize(testWidth, testHeight);
300 GTEST_LOG_(INFO) << "HeifYuvTest: HeifYuvTest011 end";
301 }
302
303 HWTEST_F(HeifYuvTest, HeifYuvTest012, TestSize.Level3)
304 {
305 GTEST_LOG_(INFO) << "HeifYuvTest: HeifYuvTest012 start";
306 float scale = 0.875;
307 int outwidth = ORIGINAL_WIDTH * scale;
308 int outheight = ORIGINAL_HEIGHT * scale;
309 TestDecodeToSize(outwidth, outheight);
310 GTEST_LOG_(INFO) << "HeifYuvTest: HeifYuvTest012 end";
311 }
312
313 HWTEST_F(HeifYuvTest, HeifYuvTest013, TestSize.Level3)
314 {
315 GTEST_LOG_(INFO) << "HeifYuvTest: HeifYuvTest013 start";
316 float scalFactor = 2.5;
317 float minscale = 0.05;
318 float step = 0.01;
319 for (; scalFactor >= minscale; scalFactor -= step) {
320 std::string heifPath = IMAGE_INPUT_HEIF_PATH;
321 heifPath.append("test.heic");
322
323 uint32_t errorCode = 0;
324 SourceOptions opts;
325 opts.formatHint = "image/heif";
326 std::unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(heifPath, opts, errorCode);
327 ASSERT_EQ(errorCode, SUCCESS);
328 ASSERT_NE(imageSource.get(), nullptr);
329 DecodeOptions decodeOpts;
330 decodeOpts.desiredPixelFormat = PixelFormat::NV12;
331 decodeOpts.desiredSize.width = ORIGINAL_WIDTH * scalFactor;
332 decodeOpts.desiredSize.height = ORIGINAL_HEIGHT * scalFactor;
333 std::unique_ptr<PixelMap> pixelMap = imageSource->CreatePixelMap(decodeOpts, errorCode);
334 ASSERT_EQ(errorCode, SUCCESS);
335 }
336 GTEST_LOG_(INFO) << "HeifYuvTest: HeifYuvTest013 end";
337 }
338
339 HWTEST_F(HeifYuvTest, HeifYuvTest014, TestSize.Level3)
340 {
341 DoTimeTest("test.heic");
342 }
343
344 HWTEST_F(HeifYuvTest, HeifYuvTest015, TestSize.Level3)
345 {
346 DoTimeTest("test_hw.heic");
347 }
348
349 HWTEST_F(HeifYuvTest, HeifYuvTest016, TestSize.Level3)
350 {
351 DoTimeTest("test-10bit-1.heic");
352 }
353
354 HWTEST_F(HeifYuvTest, HeifYuvTest017, TestSize.Level3)
355 {
356 DoTimeTest("test-10bit-2.heic");
357 }
358
359 HWTEST_F(HeifYuvTest, HeifYuvTest018, TestSize.Level3)
360 {
361 GTEST_LOG_(INFO) << "HeifYuvTest: HeifYuvTest018 start";
362 uint32_t errorCode = 0;
363 SourceOptions opts;
364 std::string hw_heif_path = "/data/local/tmp/image/test_hw.heic";
365 std::unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(hw_heif_path, opts, errorCode);
366 ASSERT_EQ(errorCode, SUCCESS);
367 ASSERT_NE(imageSource.get(), nullptr);
368 DecodeOptions decodeOpts;
369 decodeOpts.desiredPixelFormat = PixelFormat::NV21;
370 std::unique_ptr<PixelMap> pixelMap = imageSource->CreatePixelMap(decodeOpts, errorCode);
371 ASSERT_EQ(errorCode, SUCCESS);
372 GTEST_LOG_(INFO) << "HeifYuvTest: HeifYuvTest018 end";
373 }
374 }
375 }