• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 "avmetadata_mock.h"
17 #include <fcntl.h>
18 #include "gtest/gtest.h"
19 #include "media_errors.h"
20 
21 using namespace OHOS;
22 using namespace OHOS::Media;
23 using namespace AVMetadataTestParam;
24 namespace OHOS {
25 namespace Media {
AVMetadataMock()26 AVMetadataMock::AVMetadataMock()
27 {
28 }
29 
~AVMetadataMock()30 AVMetadataMock::~AVMetadataMock()
31 {
32 }
33 
CreateAVMetadataHelper()34 bool AVMetadataMock::CreateAVMetadataHelper()
35 {
36     UNITTEST_INFO_LOG("%s", __FUNCTION__);
37     avMetadataHelper_ = AVMetadataHelperFactory::CreateAVMetadataHelper();
38     if (avMetadataHelper_ == nullptr) {
39         return false;
40     }
41     return true;
42 }
43 
SetSource(const std::string & uri,int32_t usage)44 int32_t AVMetadataMock::SetSource(const std::string &uri, int32_t usage)
45 {
46     UNITTEST_INFO_LOG("%s %s", __FUNCTION__, uri.c_str());
47     return avMetadataHelper_->SetSource(uri, usage);
48 }
49 
SetSource(const std::string & path,int64_t offset,int64_t size,int32_t usage)50 int32_t AVMetadataMock::SetSource(const std::string &path, int64_t offset, int64_t size, int32_t usage)
51 {
52     UNITTEST_INFO_LOG("%s %s", __FUNCTION__, path.c_str());
53     std::string rawFile = path.substr(strlen("file://"));
54     int32_t fd = open(rawFile.c_str(), O_RDONLY);
55     if (fd <= 0) {
56         std::cout << "Open file failed" << std::endl;
57         return -1;
58     }
59 
60     struct stat64 st;
61     if (fstat64(fd, &st) != 0) {
62         std::cout << "Get file state failed" << std::endl;
63         (void)close(fd);
64         return -1;
65     }
66     int64_t length = static_cast<int64_t>(st.st_size);
67     if (size > 0) {
68         length = size;
69     }
70     int32_t ret = avMetadataHelper_->SetSource(fd, offset, length, usage);
71     if (ret != 0) {
72         (void)close(fd);
73         return -1;
74     }
75 
76     (void)close(fd);
77     return ret;
78 }
79 
PrintMetadata()80 void AVMetadataMock::PrintMetadata()
81 {
82     UNITTEST_INFO_LOG("%s", __FUNCTION__);
83     auto resultMetas = avMetadataHelper_->ResolveMetadata();
84     for (const auto &[key, value]: resultMetas) {
85         std::string prettyValue = value;
86         if (key == AV_KEY_DURATION) {
87             int64_t resultDuration = 0;
88             AVMetadataTestBase::GetInstance().StrToInt64(value, resultDuration);
89             prettyValue = AVMetadataTestBase::GetInstance().GetPrettyDuration(resultDuration);
90         }
91         if (AVMETA_KEY_TO_STRING_MAP.count(key) != 0) {
92             UNITTEST_INFO_LOG("key %s: value %s", AVMETA_KEY_TO_STRING_MAP.at(key).data(), prettyValue.c_str());
93         } else {
94             UNITTEST_INFO_LOG("key %d: value %s", key, prettyValue.c_str());
95         }
96     }
97 }
98 
ResolveMetadata()99 std::unordered_map<int32_t, std::string> AVMetadataMock::ResolveMetadata()
100 {
101     UNITTEST_INFO_LOG("%s", __FUNCTION__);
102     return avMetadataHelper_->ResolveMetadata();
103 }
104 
ResolveMetadata(int32_t key)105 std::string AVMetadataMock::ResolveMetadata(int32_t key)
106 {
107     UNITTEST_INFO_LOG("%s(%d)", __FUNCTION__, key);
108     return avMetadataHelper_->ResolveMetadata(key);
109 }
110 
FetchFrameAtTime(int64_t timeUs,int32_t option,PixelMapParams param)111 std::shared_ptr<PixelMap> AVMetadataMock::FetchFrameAtTime(int64_t timeUs, int32_t option, PixelMapParams param)
112 {
113     UNITTEST_INFO_LOG("%s", __FUNCTION__);
114     return avMetadataHelper_->FetchFrameAtTime(timeUs, option, param);
115 }
116 
FetchArtPicture()117 std::shared_ptr<AVSharedMemory> AVMetadataMock::FetchArtPicture()
118 {
119     UNITTEST_INFO_LOG("%s", __FUNCTION__);
120     return avMetadataHelper_->FetchArtPicture();
121 }
122 
Release()123 void AVMetadataMock::Release()
124 {
125     UNITTEST_INFO_LOG("%s", __FUNCTION__);
126     return avMetadataHelper_->Release();
127 }
128 
129 // only valid for little-endian order.
RGB565ToRGB888(const unsigned short * rgb565Buf,int rgb565Size,unsigned char * rgb888Buf,int rgb888Size)130 int32_t AVMetadataMock::RGB565ToRGB888(const unsigned short *rgb565Buf, int rgb565Size,
131     unsigned char *rgb888Buf, int rgb888Size)
132 {
133     if (rgb565Buf == nullptr || rgb565Size <= 0 || rgb888Buf == nullptr || rgb888Size <= 0) {
134         return -1;
135     }
136 
137     if (rgb888Size < rgb565Size * RGB888_PIXEL_BYTES) {
138         return -1;
139     }
140 
141     for (int i = 0; i < rgb565Size; i++) {
142         rgb888Buf[i * RGB888_PIXEL_BYTES + R_INDEX] = (rgb565Buf[i] & RGB565_MASK_RED);
143         rgb888Buf[i * RGB888_PIXEL_BYTES + G_INDEX] = (rgb565Buf[i] & RGB565_MASK_GREEN) >> SHIFT_5_BIT;
144         rgb888Buf[i * RGB888_PIXEL_BYTES + B_INDEX] = (rgb565Buf[i] & RGB565_MASK_BLUE) >> SHIFT_11_BIT;
145         rgb888Buf[i * RGB888_PIXEL_BYTES + R_INDEX] <<= SHIFT_3_BIT;
146         rgb888Buf[i * RGB888_PIXEL_BYTES + G_INDEX] <<= SHIFT_2_BIT;
147         rgb888Buf[i * RGB888_PIXEL_BYTES + B_INDEX] <<= SHIFT_3_BIT;
148     }
149 
150     return 0;
151 }
152 
FrameToFile(std::shared_ptr<PixelMap> frame,const char * fileName,int64_t timeUs,int32_t queryOption)153 void AVMetadataMock::FrameToFile(std::shared_ptr<PixelMap> frame,
154     const char *fileName, int64_t timeUs, int32_t queryOption)
155 {
156     const uint8_t *data = frame->GetPixels();
157     EXPECT_NE(data, nullptr);
158     int32_t bufferSize = frame->GetByteCount();
159     const uint8_t MAX_FILE_PATH_LENGTH = 255;
160     char filePath[MAX_FILE_PATH_LENGTH];
161     if (access("/data/test/ThumbnailBak", 0) != F_OK) {
162         mkdir("/data/test/ThumbnailBak", 0777);  // 0777 is the file permission.
163     }
164     auto ret = sprintf_s(filePath, MAX_FILE_PATH_LENGTH,
165         "/data/test/ThumbnailBak/%s_time_%" PRIi64 "_option_%d_width_%d_height_%d_color_%d.pixel",
166         fileName, timeUs, queryOption, frame->GetWidth(), frame->GetHeight(), frame->GetPixelFormat());
167     if (ret <= 0) {
168         std::cout << "generate file path failed" << std::endl;
169         return;
170     }
171     FILE *desFile = fopen(filePath, "wb");
172     ASSERT_NE(desFile, nullptr);
173     int64_t dstBufferSize = fwrite(data, bufferSize, 1, desFile);
174     EXPECT_EQ(dstBufferSize, 1);
175     (void)fclose(desFile);
176 }
177 
SurfaceToFile(std::shared_ptr<AVSharedMemory> frame,const char * fileName)178 void AVMetadataMock::SurfaceToFile(std::shared_ptr<AVSharedMemory> frame,
179     const char *fileName)
180 {
181     const uint8_t *data = frame->GetBase();
182     EXPECT_NE(data, nullptr);
183     int32_t bufferSize = frame->GetSize();
184     uint32_t flag = frame->GetFlags();
185     const uint8_t MAX_FILE_PATH_LENGTH = 255;
186     char filePath[MAX_FILE_PATH_LENGTH];
187     if (access("/data/test/SurfaceBak", 0) != F_OK) {
188         mkdir("/data/test/SurfaceBak", 0777); // permission 0777
189     }
190     auto ret = sprintf_s(filePath, MAX_FILE_PATH_LENGTH, "/data/test/SurfaceBak/%s.pixel", fileName);
191     if (ret <= 0) {
192         std::cout << "generate file path failed, flag:" << flag << std::endl;
193         return;
194     }
195     FILE *desFile = fopen(filePath, "wb");
196     ASSERT_NE(desFile, nullptr);
197     int64_t dstBufferSize = fwrite(data, bufferSize, 1, desFile);
198     EXPECT_EQ(dstBufferSize, 1);
199     (void)fclose(desFile);
200 }
201 
FrameToJpeg(std::shared_ptr<PixelMap> frame,const char * fileName,int64_t timeUs,int32_t queryOption)202 void AVMetadataMock::FrameToJpeg(std::shared_ptr<PixelMap> frame,
203     const char *fileName, int64_t timeUs, int32_t queryOption)
204 {
205     const uint8_t MAX_FILE_PATH_LENGTH = 255;
206     char filePath[MAX_FILE_PATH_LENGTH];
207     if (access("/data/test/ThumbnailBak", 0) != F_OK) {
208         mkdir("/data/test/ThumbnailBak", 0777); // permission 0777
209     }
210     auto ret = sprintf_s(filePath, MAX_FILE_PATH_LENGTH,
211         "/data/test/ThumbnailBak/%s_time_%" PRIi64 "_option_%d_width_%d_height_%d_color_%d.jpg",
212         fileName, timeUs, queryOption, frame->GetWidth(), frame->GetHeight(), frame->GetPixelFormat());
213     if (ret <= 0) {
214         std::cout << "generate file path failed" << std::endl;
215         return;
216     }
217     if (frame->GetPixelFormat() == PixelFormat::RGB_565) {
218         uint32_t rgb888Size = (frame->GetByteCount() / RGB565_PIXEL_BYTES) * RGB888_PIXEL_BYTES;
219         if (rgb888Size <= 0) {
220             std::cout << "invalid rgb888Size" << std::endl;
221             return;
222         }
223         uint8_t *rgb888 = new (std::nothrow) uint8_t[rgb888Size];
224         if (rgb888 == nullptr) {
225             std::cout << "alloc mem failed" << std::endl;
226             return;
227         }
228         const uint16_t *rgb565Data = reinterpret_cast<const uint16_t *>(frame->GetPixels());
229         ret = RGB565ToRGB888(rgb565Data, frame->GetByteCount() / RGB565_PIXEL_BYTES, rgb888, rgb888Size);
230         if (ret != 0) {
231             std::cout << "convert rgb565 to rgb888 failed" << std::endl;
232             delete [] rgb888;
233             return;
234         }
235         delete [] rgb888;
236     } else if (frame->GetPixelFormat() == PixelFormat::RGB_888) {
237         return;
238     } else {
239         std::cout << "invalid pixel format" << std::endl;
240         return;
241     }
242     if (ret != 0) {
243         std::cout << "pack image failed" << std::endl;
244     }
245     std::cout << "save to " << filePath << std::endl;
246 }
247 
AVMetadataTestBase()248 AVMetadataTestBase::AVMetadataTestBase()
249 {
250 }
251 
~AVMetadataTestBase()252 AVMetadataTestBase::~AVMetadataTestBase()
253 {
254 }
255 
StrToInt64(const std::string & str,int64_t & value)256 bool AVMetadataTestBase::StrToInt64(const std::string &str, int64_t &value)
257 {
258     if (str.empty() || (!isdigit(str.front()) && (str.front() != '-'))) {
259         return false;
260     }
261 
262     char *end = nullptr;
263     errno = 0;
264     auto addr = str.c_str();
265     auto result = strtoll(addr, &end, 10); /* 10 means decimal */
266     if (result == 0) {
267         return false;
268     }
269     if ((end == addr) || (end[0] != '\0') || (errno == ERANGE)) {
270         UNITTEST_INFO_LOG("call StrToInt func false,  input str is: %s!", str.c_str());
271         return false;
272     }
273 
274     value = result;
275     return true;
276 }
277 
CompareMetadata(int32_t key,const std::string & result,const std::string & expected)278 bool AVMetadataTestBase::CompareMetadata(int32_t key, const std::string &result, const std::string &expected)
279 {
280     std::string keyStr = (AVMETA_KEY_TO_STRING_MAP.count(key) == 0) ?
281         std::string(AVMETA_KEY_TO_STRING_MAP.at(key)) : std::to_string(key);
282 
283     do {
284         if (key == AV_KEY_DURATION) {
285             int64_t resultDuration = 0;
286             int64_t expectedDuration = 0;
287             if (result.compare(expected) == 0) {
288                 return true;
289             }
290             if (!StrToInt64(result, resultDuration) || !StrToInt64(expected, expectedDuration)) {
291                 break;
292             }
293             if (std::abs(resultDuration - expectedDuration) > 1000) { // max allowed time margin is 1000ms
294                 break;
295             }
296         } else {
297             if (result.compare(expected) != 0) {
298                 break;
299             }
300         }
301         return true;
302     } while (0);
303 
304     UNITTEST_INFO_LOG(">>>>>>>>>>>>>>>>>>>>>>>>>>[resolve failed] key = %s, result = %s, expected = %s",
305         keyStr.c_str(), result.c_str(), expected.c_str());
306     return false;
307 }
308 
CompareMetadata(const std::unordered_map<int32_t,std::string> & result,const std::unordered_map<int32_t,std::string> & expected)309 bool AVMetadataTestBase::CompareMetadata(const std::unordered_map<int32_t, std::string> &result,
310     const std::unordered_map<int32_t, std::string> &expected)
311 {
312     std::string resultValue;
313     bool success = true;
314 
315     for (const auto &[key, expectedValue] : expected) {
316         if (result.count(key) == 0) {
317             resultValue = "";
318         } else {
319             resultValue = result.at(key);
320         }
321 
322         success = success && CompareMetadata(key, resultValue, expectedValue);
323     }
324 
325     return success;
326 }
327 
GetPrettyDuration(int64_t duration)328 std::string AVMetadataTestBase::GetPrettyDuration(int64_t duration) // ms
329 {
330     static const int32_t msPerSec = 1000;
331     static const int32_t msPerMin = 60 * msPerSec;
332     static const int32_t msPerHour = 60 * msPerMin;
333 
334     int64_t hour = duration / msPerHour;
335     int64_t min = (duration % msPerHour) / msPerMin;
336     int64_t sec = (duration % msPerMin) / msPerSec;
337     int64_t milliSec = duration % msPerSec;
338 
339     std::ostringstream oss;
340     oss << std::setfill('0')
341         << std::setw(2) << hour << ":" // Set the width of the output field to 2 for hour.
342         << std::setw(2) << min << ":"  // Set the width of the output field to 2 for min.
343         << std::setw(2) << sec << "."  // Set the width of the output field to 2 for sec.
344         << std::setw(3) << milliSec;   // Set the width of the output field to 3 for milliSec.
345 
346     return oss.str();
347 }
348 } // namespace Media
349 } // namespace OHOS