• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 #define MLOG_TAG "Scanner"
16 
17 #include "metadata_extractor.h"
18 
19 #include <fcntl.h>
20 #include "hitrace_meter.h"
21 #include "media_log.h"
22 #include "medialibrary_db_const.h"
23 #include "medialibrary_errno.h"
24 #include "medialibrary_tracer.h"
25 
26 namespace OHOS {
27 namespace Media {
28 using namespace std;
29 
30 template <class Type>
stringToNum(const string & str)31 static Type stringToNum(const string &str)
32 {
33     std::istringstream iss(str);
34     Type num;
35     iss >> num;
36     return num;
37 }
38 
convertTimeStr2TimeStamp(string & timeStr)39 static time_t convertTimeStr2TimeStamp(string &timeStr)
40 {
41     struct tm timeinfo;
42     strptime(timeStr.c_str(), "%Y-%m-%d %H:%M:%S",  &timeinfo);
43     time_t timeStamp = mktime(&timeinfo);
44     return timeStamp;
45 }
46 
ExtractImageMetadata(std::unique_ptr<Metadata> & data)47 int32_t MetadataExtractor::ExtractImageMetadata(std::unique_ptr<Metadata> &data)
48 {
49     uint32_t err = 0;
50 
51     SourceOptions opts;
52     opts.formatHint = "image/" + data->GetFileExtension();
53     std::unique_ptr<ImageSource> imageSource =
54         ImageSource::CreateImageSource(data->GetFilePath(), opts, err);
55     if (err != 0 || imageSource == nullptr) {
56         MEDIA_ERR_LOG("Failed to obtain image source, err = %{public}d", err);
57         return E_OK;
58     }
59 
60     ImageInfo imageInfo;
61     err = imageSource->GetImageInfo(0, imageInfo);
62     if (err == 0) {
63         data->SetFileWidth(imageInfo.size.width);
64         data->SetFileHeight(imageInfo.size.height);
65     } else {
66         MEDIA_ERR_LOG("Failed to get image info, err = %{public}d", err);
67     }
68 
69     string propertyStr;
70     int64_t int64TempMeta = 0;
71     err = imageSource->GetImagePropertyString(0, MEDIA_DATA_IMAGE_DATE_TIME_ORIGINAL, propertyStr);
72     if (err == 0) {
73         int64TempMeta = convertTimeStr2TimeStamp(propertyStr);
74         if (int64TempMeta < 0) {
75             data->SetDateTaken(data->GetFileDateModified());
76         } else {
77             data->SetDateTaken(int64TempMeta);
78         }
79     } else {
80         // use modified time as date taken time when date taken not set
81         data->SetDateTaken(data->GetFileDateModified());
82     }
83 
84     int32_t intTempMeta = 0;
85     err = imageSource->GetImagePropertyInt(0, MEDIA_DATA_IMAGE_ORIENTATION, intTempMeta);
86     if (err == 0) {
87         data->SetOrientation(intTempMeta);
88     }
89 
90     double dbleTempMeta = -1;
91     err = imageSource->GetImagePropertyString(0, MEDIA_DATA_IMAGE_GPS_LONGITUDE, propertyStr);
92     if (err == 0) {
93         dbleTempMeta = stringToNum<double>(propertyStr);
94         data->SetLongitude(dbleTempMeta);
95     }
96 
97     err = imageSource->GetImagePropertyString(0, MEDIA_DATA_IMAGE_GPS_LATITUDE, propertyStr);
98     if (err == 0) {
99         dbleTempMeta = stringToNum<double>(propertyStr);
100         data->SetLatitude(dbleTempMeta);
101     }
102 
103     return E_OK;
104 }
105 
FillExtractedMetadata(const std::unordered_map<int32_t,std::string> & resultMap,std::unique_ptr<Metadata> & data)106 void MetadataExtractor::FillExtractedMetadata(const std::unordered_map<int32_t, std::string> &resultMap,
107     std::unique_ptr<Metadata> &data)
108 {
109     string strTemp;
110     int32_t intTempMeta;
111     int64_t int64TempMeta;
112 
113     strTemp = resultMap.at(AV_KEY_ALBUM);
114     if (strTemp != "") {
115         data->SetAlbum(strTemp);
116     }
117 
118     strTemp = resultMap.at(AV_KEY_ARTIST);
119     if (strTemp != "") {
120         data->SetFileArtist(strTemp);
121     }
122 
123     strTemp = resultMap.at(AV_KEY_DURATION);
124     if (strTemp != "") {
125         intTempMeta = stringToNum<int32_t>(strTemp);
126         data->SetFileDuration(intTempMeta);
127     }
128 
129     strTemp = resultMap.at(AV_KEY_VIDEO_HEIGHT);
130     if (strTemp != "") {
131         intTempMeta = stringToNum<int32_t>(strTemp);
132         data->SetFileHeight(intTempMeta);
133     }
134 
135     strTemp = resultMap.at(AV_KEY_VIDEO_WIDTH);
136     if (strTemp != "") {
137         intTempMeta = stringToNum<int32_t>(strTemp);
138         data->SetFileWidth(intTempMeta);
139     }
140 
141     strTemp = resultMap.at(AV_KEY_MIME_TYPE);
142     if (strTemp != "") {
143         data->SetFileMimeType(strTemp);
144     }
145 
146     strTemp = resultMap.at(AV_KEY_DATE_TIME_FORMAT);
147     if (strTemp != "") {
148         int64TempMeta = convertTimeStr2TimeStamp(strTemp);
149         if (int64TempMeta < 0) {
150             data->SetDateTaken(data->GetFileDateModified());
151         } else {
152             data->SetDateTaken(int64TempMeta);
153         }
154     } else {
155         // use modified time as date taken time when date taken not set
156         data->SetDateTaken(data->GetFileDateModified());
157     }
158 
159     strTemp = resultMap.at(AV_KEY_VIDEO_ORIENTATION);
160     if (strTemp == "") {
161         intTempMeta = 0;
162     } else {
163         intTempMeta = stringToNum<int32_t>(strTemp);
164     }
165     data->SetOrientation(intTempMeta);
166 
167     strTemp = resultMap.at(AV_KEY_TITLE);
168     if (!strTemp.empty()) {
169         data->SetFileTitle(strTemp);
170     }
171 }
172 
ExtractAVMetadata(std::unique_ptr<Metadata> & data)173 int32_t MetadataExtractor::ExtractAVMetadata(std::unique_ptr<Metadata> &data)
174 {
175     MediaLibraryTracer tracer;
176     tracer.Start("ExtractAVMetadata");
177 
178     tracer.Start("CreateAVMetadataHelper");
179     std::shared_ptr<AVMetadataHelper> avMetadataHelper = AVMetadataHelperFactory::CreateAVMetadataHelper();
180     tracer.Finish();
181     if (avMetadataHelper == nullptr) {
182         MEDIA_ERR_LOG("AV metadata helper is null");
183         return E_AVMETADATA;
184     }
185 
186     string filePath = data->GetFilePath();
187     if(filePath.empty()){
188         MEDIA_ERR_LOG("AV metadata file path is empty");
189         return E_AVMETADATA;
190     }
191 
192     int32_t fd = open(filePath.c_str(), O_RDONLY);
193     if (fd <= 0) {
194         MEDIA_ERR_LOG("Open file descriptor failed, errno = %{public}d", errno);
195         return E_SYSCALL;
196     }
197 
198     struct stat64 st;
199     if (fstat64(fd, &st) != 0) {
200         MEDIA_ERR_LOG("Get file state failed for the given fd");
201         (void)close(fd);
202         return E_SYSCALL;
203     }
204 
205     tracer.Start("avMetadataHelper->SetSource");
206     int32_t err = avMetadataHelper->SetSource(fd, 0, static_cast<int64_t>(st.st_size), AV_META_USAGE_META_ONLY);
207     tracer.Finish();
208     if (err != 0) {
209         MEDIA_ERR_LOG("SetSource failed for the given file descriptor, err = %{public}d", err);
210         (void)close(fd);
211         return E_AVMETADATA;
212     } else {
213         tracer.Start("avMetadataHelper->ResolveMetadata");
214         std::unordered_map<int32_t, std::string> resultMap = avMetadataHelper->ResolveMetadata();
215         tracer.Finish();
216         if (!resultMap.empty()) {
217             FillExtractedMetadata(resultMap, data);
218         }
219     }
220 
221     (void)close(fd);
222 
223     return E_OK;
224 }
225 
Extract(std::unique_ptr<Metadata> & data)226 int32_t MetadataExtractor::Extract(std::unique_ptr<Metadata> &data)
227 {
228     if (data->GetFileMediaType() == MEDIA_TYPE_IMAGE) {
229         return ExtractImageMetadata(data);
230     } else {
231         return ExtractAVMetadata(data);
232     }
233 }
234 } // namespace Media
235 } // namespace OHOS
236