• 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, 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