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