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 }