1 /*
2 * Copyright (c) 2025 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 "cj_avmetadataextractor.h"
17 #include "media_log.h"
18 #include "pixel_map_impl.h"
19
20 namespace {
21 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_METADATA, "CJAVMetadataExtractorImpl" };
22 }
23
24 namespace OHOS {
25 namespace Media {
26
CreateCString(std::string value,char ** result)27 bool CreateCString(std::string value, char** result)
28 {
29 *result = static_cast<char *>(malloc((value.size() + 1) * sizeof(char)));
30 if (*result == nullptr) {
31 return false;
32 }
33 if (memcpy_s(*result, value.size() + 1, value.c_str(), value.size()) != 0) {
34 MEDIA_LOGE("Failed to create string.");
35 free(*result);
36 return false;
37 }
38 (*result)[value.size()] = 0;
39 return true;
40 }
41
CreateMapPair(std::string key,std::string value,char ** keyPtr,char ** valuePtr)42 bool CreateMapPair(std::string key, std::string value, char** keyPtr, char** valuePtr)
43 {
44 bool ret = CreateCString(key, keyPtr);
45 CHECK_AND_RETURN_RET_LOG(ret, ret, "Create map key failed, key %{public}s", key.c_str());
46 ret = CreateCString(value, valuePtr);
47 if (ret == false) {
48 free(*keyPtr);
49 }
50 return ret;
51 }
52
CreateCustomInfo(std::shared_ptr<Meta> & meta,CCustomInfo & info)53 bool CreateCustomInfo(std::shared_ptr<Meta>& meta, CCustomInfo& info)
54 {
55 bool ret = true;
56 int64_t index = 0;
57 for (auto iter = meta->begin(); iter != meta->end(); iter++) { index++; }
58 info.size = index;
59 if (index == 0) {
60 return false;
61 }
62
63 info.key = static_cast<char **>(malloc(index * sizeof(char*)));
64 if (info.key == nullptr) {
65 info.size = 0;
66 return false;
67 }
68 info.value = static_cast<char **>(malloc(index * sizeof(char*)));
69 if (info.value == nullptr) {
70 free(info.key);
71 info.size = 0;
72 return false;
73 }
74 index = 0;
75 for (auto iter = meta->begin(); iter != meta->end(); iter++) {
76 AnyValueType type = meta->GetValueType(iter->first);
77 CHECK_AND_CONTINUE_LOG(type == AnyValueType::STRING, "key %{public}s is not string", iter->first.c_str());
78 std::string sValue;
79 ret = meta->GetData(iter->first, sValue);
80 CHECK_AND_CONTINUE_LOG(ret, "GetData failed, key %{public}s", iter->first.c_str());
81 ret = CreateMapPair(iter->first, sValue, &(info.key[index]), &(info.value[index]));
82 CHECK_AND_CONTINUE_LOG(ret, "Create data failed, key %{public}s", iter->first.c_str());
83 index++;
84 }
85 return true;
86 }
87
CreateLocation(std::shared_ptr<Meta> & meta,CLocation & loc,std::string key)88 bool CreateLocation(std::shared_ptr<Meta>& meta, CLocation& loc, std::string key)
89 {
90 bool ret = true;
91 float dValue;
92 ret = meta->GetData(key, dValue);
93 CHECK_AND_RETURN_RET_LOG(ret, ret, "GetData failed, key %{public}s", key.c_str());
94 if (key == "latitude") {
95 loc.latitude = dValue;
96 }
97 if (key == "longitude") {
98 loc.longitude = dValue;
99 }
100 return ret;
101 }
102
SetHdrType(std::shared_ptr<Meta> & meta,std::string key,CAVMetadata & result)103 bool SetHdrType(std::shared_ptr<Meta>& meta, std::string key, CAVMetadata& result)
104 {
105 bool ret = true;
106 int32_t value;
107 ret = meta->GetData(key, value);
108 CHECK_AND_RETURN_RET_LOG(ret, ret, "GetData failed, key %{public}s", key.c_str());
109 result.hdrType = value;
110 return ret;
111 }
112
CAVMetadataGetStrValue(CAVMetadata & data,const std::string key)113 char** CAVMetadataGetStrValue(CAVMetadata& data, const std::string key)
114 {
115 char** ret = nullptr;
116 if (key == "album") { ret = &(data.album); }
117 if (key == "albumArtist") { ret = &(data.albumArtist); }
118 if (key == "artist") { ret = &(data.artist); }
119 if (key == "author") { ret = &(data.author); }
120 if (key == "dateTime") { ret = &(data.dateTime); }
121 if (key == "dateTimeFormat") { ret = &(data.dateTimeFormat); }
122 if (key == "composer") { ret = &(data.composer); }
123 if (key == "duration") { ret = &(data.duration); }
124 if (key == "genre") { ret = &(data.genre); }
125 if (key == "hasAudio") { ret = &(data.hasAudio); }
126 if (key == "hasVideo") { ret = &(data.hasVideo); }
127 if (key == "mimeType") { ret = &(data.mimeType); }
128 if (key == "trackCount") { ret = &(data.trackCount); }
129 if (key == "sampleRate") { ret = &(data.sampleRate); }
130 if (key == "title") { ret = &(data.title); }
131 if (key == "videoHeight") { ret = &(data.videoHeight); }
132 if (key == "videoWidth") { ret = &(data.videoWidth); }
133 if (key == "videoOrientation") { ret = &(data.videoOrientation); }
134 return ret;
135 }
136
SetMetadata(std::shared_ptr<Meta> & meta,std::string key,CAVMetadata & result)137 bool SetMetadata(std::shared_ptr<Meta>& meta, std::string key, CAVMetadata& result)
138 {
139 bool ret = true;
140 std::string sValue;
141 ret = meta->GetData(key, sValue);
142 CHECK_AND_RETURN_RET_LOG(ret, ret, "GetData failed, key %{public}s", key.c_str());
143 auto ptr = CAVMetadataGetStrValue(result, key);
144 if (ptr == nullptr) {
145 MEDIA_LOGE("GetValue failed, key %{public}s", key.c_str());
146 return false;
147 }
148 CHECK_AND_RETURN_RET_LOG(CreateCString(sValue, ptr), false,
149 "Failed to set value, key %{public}s", key.c_str());
150 return ret;
151 }
152
ConvertMemToPixelMap(std::shared_ptr<AVSharedMemory> sharedMemory)153 static std::unique_ptr<PixelMap> ConvertMemToPixelMap(std::shared_ptr<AVSharedMemory> sharedMemory)
154 {
155 CHECK_AND_RETURN_RET_LOG(sharedMemory != nullptr, nullptr, "SharedMem is nullptr");
156 MEDIA_LOGI("FetchArtPicture size: %{public}d", sharedMemory->GetSize());
157 SourceOptions sourceOptions;
158 uint32_t errorCode = 0;
159 std::unique_ptr<ImageSource> imageSource =
160 ImageSource::CreateImageSource(sharedMemory->GetBase(), sharedMemory->GetSize(), sourceOptions, errorCode);
161 CHECK_AND_RETURN_RET_LOG(imageSource != nullptr, nullptr, "Failed to create imageSource.");
162 DecodeOptions decodeOptions;
163 std::unique_ptr<PixelMap> pixelMap = imageSource->CreatePixelMap(decodeOptions, errorCode);
164 CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, nullptr, "Failed to decode imageSource");
165 return pixelMap;
166 }
167
InitAVMetadata(CAVMetadata * data)168 void InitAVMetadata(CAVMetadata* data)
169 {
170 data->album = nullptr;
171 data->albumArtist = nullptr;
172 data->artist = nullptr;
173 data->author = nullptr;
174 data->dateTime = nullptr;
175 data->dateTimeFormat = nullptr;
176 data->composer = nullptr;
177 data->duration = nullptr;
178 data->genre = nullptr;
179 data->hasAudio = nullptr;
180 data->hasVideo = nullptr;
181 data->mimeType = nullptr;
182 data->trackCount = nullptr;
183 data->sampleRate = nullptr;
184 data->title = nullptr;
185 data->videoHeight = nullptr;
186 data->videoWidth = nullptr;
187 data->videoOrientation = nullptr;
188 data->hdrType = 0;
189 data->location.latitude = 0.0;
190 data->location.longitude = 0.0;
191 data->customInfo.key = nullptr;
192 data->customInfo.value = nullptr;
193 data->customInfo.size = 0;
194 }
195
Create()196 sptr<CJAVMetadataExtractorImpl> CJAVMetadataExtractorImpl::Create()
197 {
198 auto instance = FFI::FFIData::Create<CJAVMetadataExtractorImpl>();
199 if (instance == nullptr) {
200 MEDIA_LOGE("Failed to new CJAVMetadataExtractorImpl");
201 return nullptr;
202 }
203 instance->helper_ = AVMetadataHelperFactory::CreateAVMetadataHelper();
204 if (instance->helper_ == nullptr) {
205 MEDIA_LOGE("Failed to CreateMetadataHelper");
206 FFI::FFIData::Release(instance->GetID());
207 return nullptr;
208 }
209 return instance;
210 }
211
CJAVMetadataExtractorImpl()212 CJAVMetadataExtractorImpl::CJAVMetadataExtractorImpl()
213 {
214 MEDIA_LOGI("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
215 }
216
~CJAVMetadataExtractorImpl()217 CJAVMetadataExtractorImpl::~CJAVMetadataExtractorImpl()
218 {
219 MEDIA_LOGI("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
220 }
221
FetchMetadata(CAVMetadata * data)222 int32_t CJAVMetadataExtractorImpl::FetchMetadata(CAVMetadata* data)
223 {
224 bool ret = true;
225 if (data == nullptr) {
226 return MSERR_INVALID_VAL;
227 }
228 InitAVMetadata(data);
229 if (state_ != HelperState::HELPER_STATE_RUNNABLE) {
230 MEDIA_LOGE("Current state is not runnable, can't fetchFrame.");
231 return MSERR_EXT_API9_OPERATE_NOT_PERMIT;
232 }
233 auto metadata = helper_->GetAVMetadata();
234 for (const auto &key : g_Metadata) {
235 if (metadata->Find(key) == metadata->end()) {
236 MEDIA_LOGE("failed to find key: %{public}s", key.c_str());
237 continue;
238 }
239 MEDIA_LOGI("success to find key: %{public}s", key.c_str());
240 if (key == "latitude" || key == "longitude") {
241 ret = CreateLocation(metadata, data->location, key);
242 CHECK_AND_CONTINUE_LOG(ret, "GetData failed, key %{public}s", key.c_str());
243 continue;
244 }
245 if (key == "hdrType") {
246 ret = SetHdrType(metadata, key, *data);
247 CHECK_AND_CONTINUE_LOG(ret, "GetData failed, key hdrType");
248 continue;
249 }
250 if (key == "customInfo") {
251 std::shared_ptr<Meta> customData = std::make_shared<Meta>();
252 ret = metadata->GetData(key, customData);
253 CHECK_AND_CONTINUE_LOG(ret, "GetData failed, key %{public}s", key.c_str());
254 ret = CreateCustomInfo(customData, data->customInfo);
255 continue;
256 }
257 ret = SetMetadata(metadata, key, *data);
258 CHECK_AND_CONTINUE_LOG(ret, "GetData failed, key %{public}s", key.c_str());
259 }
260 return MSERR_OK;
261 }
262
FetchAlbumCover()263 int64_t CJAVMetadataExtractorImpl::FetchAlbumCover()
264 {
265 if (state_ != HelperState::HELPER_STATE_RUNNABLE) {
266 MEDIA_LOGE("Current state is not runnable, can't fetchFrame.");
267 return 0;
268 }
269 auto sharedMemory = helper_->FetchArtPicture();
270 auto pixelMap = ConvertMemToPixelMap(sharedMemory);
271 if (pixelMap == nullptr) {
272 MEDIA_LOGE("Failed to fetchAlbumCover.");
273 return 0;
274 }
275 auto result = FFI::FFIData::Create<PixelMapImpl>(move(pixelMap));
276 if (result == nullptr) {
277 return 0;
278 }
279 return result->GetID();
280 }
281
SetAVFileDescriptor(CAVFileDescriptor file)282 int32_t CJAVMetadataExtractorImpl::SetAVFileDescriptor(CAVFileDescriptor file)
283 {
284 fileDescriptor_.fd = file.fd;
285 fileDescriptor_.offset = file.offset;
286 fileDescriptor_.length = file.length;
287 MEDIA_LOGD("get fd argument, fd = %{public}d, offset = %{public}" PRIi64 ", size = %{public}" PRIi64 "",
288 fileDescriptor_.fd, fileDescriptor_.offset, fileDescriptor_.length);
289 auto res = helper_->SetSource(fileDescriptor_.fd, fileDescriptor_.offset, fileDescriptor_.length);
290 state_ = res == MSERR_OK ? HelperState::HELPER_STATE_RUNNABLE : HelperState::HELPER_ERROR;
291 return MSERR_OK;
292 }
293
GetAVFileDescriptor(CAVFileDescriptor * file)294 int32_t CJAVMetadataExtractorImpl::GetAVFileDescriptor(CAVFileDescriptor* file)
295 {
296 if (file == nullptr) {
297 return MSERR_INVALID_VAL;
298 }
299 file->fd = fileDescriptor_.fd;
300 file->offset = fileDescriptor_.offset;
301 file->length = fileDescriptor_.length;
302 return MSERR_OK;
303 }
304
SetAVDataSrcDescriptor(CAVDataSrcDescriptor data)305 int32_t CJAVMetadataExtractorImpl::SetAVDataSrcDescriptor(CAVDataSrcDescriptor data)
306 {
307 if (state_ != HelperState::HELPER_STATE_IDLE) {
308 MEDIA_LOGE("Has set source once, unsupport set again.");
309 return MSERR_OK;
310 }
311 if (helper_ == nullptr) {
312 MEDIA_LOGE("Invalid CJAVMetadataExtractorImpl.");
313 return MSERR_UNKNOWN;
314 }
315 dataSrcDescriptor_.fileSize = data.fileSize;
316 if (dataSrcDescriptor_.fileSize <= 0) {
317 return MSERR_OK;
318 }
319 MEDIA_LOGI("Recvive filesize is %{public}" PRId64 "", dataSrcDescriptor_.fileSize);
320 dataSrcDescriptor_.callback = data.callback;
321 dataSrcCb_ = std::make_shared<CJHelperDataSourceCallback>(dataSrcDescriptor_.fileSize);
322 const std::string callbackName = "readAt";
323 if (dataSrcCb_->SaveCallbackReference(callbackName, dataSrcDescriptor_.callback) != MSERR_OK) {
324 MEDIA_LOGE("Set callback failed.");
325 return MSERR_UNKNOWN;
326 }
327 auto res = helper_->SetSource(dataSrcCb_);
328 state_ = res == MSERR_OK ? HelperState::HELPER_STATE_RUNNABLE : HelperState::HELPER_ERROR;
329 MEDIA_LOGI("SetAVDataSrcDescriptor Out");
330 return MSERR_OK;
331 }
332
GetAVDataSrcDescriptor(CAVDataSrcDescriptor * data)333 int32_t CJAVMetadataExtractorImpl::GetAVDataSrcDescriptor(CAVDataSrcDescriptor* data)
334 {
335 if (data == nullptr) {
336 return MSERR_INVALID_VAL;
337 }
338 dataSrcCb_->GetSize(dataSrcDescriptor_.fileSize);
339 dataSrcCb_->GetCallbackId(dataSrcDescriptor_.callback);
340 data->fileSize = dataSrcDescriptor_.fileSize;
341 data->callback = dataSrcDescriptor_.callback;
342 return MSERR_OK;
343 }
344
Release()345 void CJAVMetadataExtractorImpl::Release()
346 {
347 if (state_ == HelperState::HELPER_STATE_RELEASED) {
348 MEDIA_LOGE("Has released once, can't release again.");
349 return;
350 }
351 if (dataSrcCb_ != nullptr) {
352 dataSrcCb_->ClearCallbackReference();
353 dataSrcCb_ = nullptr;
354 }
355 helper_->Release();
356 }
357
358 } // namespace Media
359 } // namespace OHOS
360