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