1 /*
2 * Copyright (C) 2023 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_collector.h"
17
18 #include <string>
19
20 #include "avmetadatahelper.h"
21 #include "buffer/avsharedmemorybase.h"
22 #include "media_log.h"
23 #include "meta/video_types.h"
24 #include "meta/any.h"
25 #include "time_format_utils.h"
26
27 namespace {
28 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_METADATA, "AVMetaDataCollector" };
29 } // namespace
30
31 namespace OHOS {
32 namespace Media {
33 const int32_t FRAME_RATE_UNIT_MULTIPLE = 100; // the unit of frame rate is frames per 100s
34 static constexpr int PICTURE_MAX_SIZE = 1024 * 1024;
35 static constexpr int SECOND_DEVIDE_MS = 1000;
36 const int32_t NUMBER_OF_CHARACTERS_IN_VALID_VIDEOROTATEORIENTATIONTYPE = 2;
37
38 static const std::unordered_map<Plugins::FileType, std::string> fileTypeMap = {
39 { Plugins::FileType::UNKNOW, "uknown" },
40 { Plugins::FileType::MP4, "mp4" },
41 { Plugins::FileType::MPEGTS, "mpeg" },
42 { Plugins::FileType::MKV, "mkv" },
43 { Plugins::FileType::AMR, "amr" },
44 { Plugins::FileType::AAC, "aac-adts" },
45 { Plugins::FileType::MP3, "mpeg" },
46 { Plugins::FileType::FLAC, "flac" },
47 { Plugins::FileType::OGG, "ogg" },
48 { Plugins::FileType::M4A, "mp4" },
49 { Plugins::FileType::WAV, "wav" },
50 { Plugins::FileType::MOV, "mov" },
51 { Plugins::FileType::AVI, "avi" },
52 { Plugins::FileType::MPEGPS, "mpg" }
53 };
54
55 static const std::unordered_map<Plugins::VideoOrientationType, int32_t> videoOrientationTypeMap = {
56 { Plugins::VideoOrientationType::ROTATE_NONE, VideoRotateOrientationType::TOP_LEFT },
57 { Plugins::VideoOrientationType::ROTATE_90, VideoRotateOrientationType::LEFT_BOTTOM },
58 { Plugins::VideoOrientationType::ROTATE_180, VideoRotateOrientationType::BOTTOM_RIGHT },
59 { Plugins::VideoOrientationType::ROTATE_270, VideoRotateOrientationType::RIGHT_TOP },
60 { Plugins::VideoOrientationType::FLIP_H, VideoRotateOrientationType::TOP_RIGHT },
61 { Plugins::VideoOrientationType::FLIP_V, VideoRotateOrientationType::BOTTOM_LEFT },
62 { Plugins::VideoOrientationType::FLIP_H_ROT90, VideoRotateOrientationType::LEFT_TOP },
63 { Plugins::VideoOrientationType::FLIP_V_ROT90, VideoRotateOrientationType::RIGHT_BOTTOM },
64 { Plugins::VideoOrientationType::FLIP_H_ROT180, VideoRotateOrientationType::BOTTOM_LEFT },
65 { Plugins::VideoOrientationType::FLIP_V_ROT180, VideoRotateOrientationType::TOP_RIGHT },
66 { Plugins::VideoOrientationType::FLIP_H_ROT270, VideoRotateOrientationType::RIGHT_BOTTOM },
67 { Plugins::VideoOrientationType::FLIP_V_ROT270, VideoRotateOrientationType::LEFT_TOP },
68 };
69
70 static const std::unordered_map<int32_t, std::string> AVMETA_KEY_TO_X_MAP = {
71 { AV_KEY_ALBUM, Tag::MEDIA_ALBUM },
72 { AV_KEY_ALBUM_ARTIST, Tag::MEDIA_ALBUM_ARTIST },
73 { AV_KEY_ARTIST, Tag::MEDIA_ARTIST },
74 { AV_KEY_AUTHOR, Tag::MEDIA_AUTHOR },
75 { AV_KEY_COMPOSER, Tag::MEDIA_COMPOSER },
76 { AV_KEY_DATE_TIME, Tag::MEDIA_DATE },
77 { AV_KEY_DATE_TIME_FORMAT, Tag::MEDIA_CREATION_TIME },
78 { AV_KEY_DURATION, Tag::MEDIA_DURATION },
79 { AV_KEY_GENRE, Tag::MEDIA_GENRE },
80 { AV_KEY_HAS_AUDIO, Tag::MEDIA_HAS_AUDIO },
81 { AV_KEY_HAS_VIDEO, Tag::MEDIA_HAS_VIDEO },
82 { AV_KEY_MIME_TYPE, Tag::MIME_TYPE },
83 { AV_KEY_NUM_TRACKS, Tag::MEDIA_TRACK_COUNT },
84 { AV_KEY_SAMPLE_RATE, Tag::AUDIO_SAMPLE_RATE },
85 { AV_KEY_TITLE, Tag::MEDIA_TITLE },
86 { AV_KEY_VIDEO_HEIGHT, Tag::VIDEO_HEIGHT },
87 { AV_KEY_VIDEO_WIDTH, Tag::VIDEO_WIDTH },
88 { AV_KEY_VIDEO_ORIENTATION, Tag::VIDEO_ROTATION },
89 { AV_KEY_VIDEO_ROTATE_ORIENTATION, Tag::VIDEO_ORIENTATION_TYPE },
90 { AV_KEY_VIDEO_IS_HDR_VIVID, Tag::VIDEO_IS_HDR_VIVID },
91 { AV_KEY_LOCATION_LONGITUDE, Tag::MEDIA_LONGITUDE},
92 { AV_KEY_LOCATION_LATITUDE, Tag::MEDIA_LATITUDE},
93 { AV_KEY_CUSTOMINFO, "customInfo"},
94 { AV_KEY_DATE_TIME_ISO8601, "ISO8601 time"},
95 };
96
AVMetaDataCollector(std::shared_ptr<MediaDemuxer> & mediaDemuxer)97 AVMetaDataCollector::AVMetaDataCollector(std::shared_ptr<MediaDemuxer> &mediaDemuxer) : mediaDemuxer_(mediaDemuxer)
98 {
99 MEDIA_LOGD("enter ctor, instance: 0x%{public}06" PRIXPTR "", FAKE_POINTER(this));
100 }
101
~AVMetaDataCollector()102 AVMetaDataCollector::~AVMetaDataCollector()
103 {
104 MEDIA_LOGD("enter dtor, instance: 0x%{public}06" PRIXPTR "", FAKE_POINTER(this));
105 }
106
ExtractMetadata()107 std::unordered_map<int32_t, std::string> AVMetaDataCollector::ExtractMetadata()
108 {
109 if (collectedMeta_.size() != 0) {
110 return collectedMeta_;
111 }
112 const std::shared_ptr<Meta> globalInfo = mediaDemuxer_->GetGlobalMetaInfo();
113 const std::vector<std::shared_ptr<Meta>> trackInfos = mediaDemuxer_->GetStreamMetaInfo();
114 collectedMeta_ = GetMetadata(globalInfo, trackInfos);
115 return collectedMeta_;
116 }
117
GetVideoTrackId(uint32_t & trackId)118 Status AVMetaDataCollector::GetVideoTrackId(uint32_t &trackId)
119 {
120 if (hasVideo_) {
121 trackId = videoTrackId_;
122 return Status::OK;
123 }
124 const std::vector<std::shared_ptr<Meta>> trackInfos = mediaDemuxer_->GetStreamMetaInfo();
125 size_t trackCount = trackInfos.size();
126 CHECK_AND_RETURN_RET_LOG(trackCount > 0, Status::ERROR_INVALID_DATA, "GetTargetTrackInfo trackCount is invalid");
127 for (size_t index = 0; index < trackCount; index++) {
128 std::string trackMime = "";
129 if (!(trackInfos[index]->GetData(Tag::MIME_TYPE, trackMime))) {
130 continue;
131 }
132 if (trackMime.find("video/") == 0) {
133 videoTrackId_ = index;
134 trackId = index;
135 hasVideo_ = true;
136 return Status::OK;
137 }
138 }
139 return Status::ERROR_INVALID_DATA;
140 }
141
GetAudioTrackInfo(const std::shared_ptr<Meta> & trackInfo,const std::string & mime,size_t index)142 void AVMetaDataCollector::GetAudioTrackInfo(const std::shared_ptr<Meta> &trackInfo,
143 const std::string& mime, size_t index)
144 {
145 MEDIA_LOGD("GetAudioTrackInfo in");
146 Format audioTrackInfo {};
147 audioTrackInfo.PutIntValue("track_index", static_cast<int32_t>(index));
148 audioTrackInfo.PutIntValue("track_type", static_cast<int32_t>(Plugins::MediaType::AUDIO));
149 audioTrackInfo.PutStringValue("codec_mime", mime);
150 int32_t audioChannels = 0;
151 trackInfo->GetData(Tag::AUDIO_CHANNEL_COUNT, audioChannels);
152 audioTrackInfo.PutIntValue("channel_count", audioChannels);
153 int32_t audioSampleRate = 0;
154 trackInfo->GetData(Tag::AUDIO_SAMPLE_RATE, audioSampleRate);
155 audioTrackInfo.PutIntValue("sample_rate", audioSampleRate);
156 trackInfoVec_.emplace_back(std::move(audioTrackInfo));
157 }
158
GetVideoTrackInfo(const std::shared_ptr<Meta> & trackInfo,const std::string & mime,size_t index)159 void AVMetaDataCollector::GetVideoTrackInfo(const std::shared_ptr<Meta> &trackInfo,
160 const std::string& mime, size_t index)
161 {
162 MEDIA_LOGD("GetVideoTrackInfo in");
163 Format videoTrackInfo {};
164 videoTrackInfo.PutIntValue("track_index", index);
165 videoTrackInfo.PutIntValue("track_type", static_cast<int32_t>(Plugins::MediaType::VIDEO));
166 videoTrackInfo.PutStringValue("codec_mime", mime);
167 int32_t width = GetSarVideoWidth(trackInfo);
168 videoTrackInfo.PutIntValue("width", width);
169 int32_t height = GetSarVideoHeight(trackInfo);
170 videoTrackInfo.PutIntValue("height", height);
171 double frameRate = 0;
172 if (trackInfo->GetData(Tag::VIDEO_FRAME_RATE, frameRate)) {
173 videoTrackInfo.PutDoubleValue("frame_rate", frameRate * FRAME_RATE_UNIT_MULTIPLE);
174 }
175 bool isHdr = false;
176 trackInfo->GetData(Tag::VIDEO_IS_HDR_VIVID, isHdr);
177 videoTrackInfo.PutIntValue("hdr_type", static_cast<int32_t>(isHdr));
178 trackInfoVec_.emplace_back(std::move(videoTrackInfo));
179 }
180
GetSubtitleTrackInfo(const std::shared_ptr<Meta> & trackInfo,const std::string & mime,size_t index)181 void AVMetaDataCollector::GetSubtitleTrackInfo(const std::shared_ptr<Meta> &trackInfo,
182 const std::string& mime, size_t index)
183 {
184 (void)trackInfo;
185 (void)mime;
186 MEDIA_LOGD("GetSubtitleTrackInfo in");
187 Format subtitleTrackInfo {};
188 subtitleTrackInfo.PutIntValue("track_index", index);
189 subtitleTrackInfo.PutIntValue("track_type", static_cast<int32_t>(Plugins::MediaType::SUBTITLE));
190 trackInfoVec_.emplace_back(std::move(subtitleTrackInfo));
191 }
192
GetOtherTrackInfo(const std::shared_ptr<Meta> & trackInfo,size_t index)193 void AVMetaDataCollector::GetOtherTrackInfo(const std::shared_ptr<Meta> &trackInfo, size_t index)
194 {
195 MEDIA_LOGD("GetOtherTrackInfo in");
196 Format otherTrackInfo {};
197 otherTrackInfo.PutIntValue("track_index", index);
198 Plugins::MediaType mediaType = Plugins::MediaType::UNKNOWN;
199 trackInfo->GetData(Tag::MEDIA_TYPE, mediaType);
200 otherTrackInfo.PutIntValue("track_type", static_cast<int32_t>(mediaType));
201 trackInfoVec_.emplace_back(std::move(otherTrackInfo));
202 }
203
GetSarVideoWidth(std::shared_ptr<Meta> trackInfo) const204 int32_t AVMetaDataCollector::GetSarVideoWidth(std::shared_ptr<Meta> trackInfo) const
205 {
206 int32_t width = 0;
207 trackInfo->GetData(Tag::VIDEO_WIDTH, width);
208 double videoSar = 0;
209 bool ret = trackInfo->GetData(Tag::VIDEO_SAR, videoSar);
210 if (ret && videoSar < 1) {
211 width = static_cast<int32_t>(width * videoSar);
212 }
213 return width;
214 }
215
GetSarVideoHeight(std::shared_ptr<Meta> trackInfo) const216 int32_t AVMetaDataCollector::GetSarVideoHeight(std::shared_ptr<Meta> trackInfo) const
217 {
218 int32_t height = 0;
219 trackInfo->GetData(Tag::VIDEO_HEIGHT, height);
220 double videoSar = 0;
221 bool ret = trackInfo->GetData(Tag::VIDEO_SAR, videoSar);
222 if (ret && videoSar > 1) {
223 height = static_cast<int32_t>(height / videoSar);
224 }
225 return height;
226 }
227
IsVideoMime(const std::string & mime) const228 bool AVMetaDataCollector::IsVideoMime(const std::string& mime) const
229 {
230 return mime.find("video/") == 0;
231 }
232
IsAudioMime(const std::string & mime) const233 bool AVMetaDataCollector::IsAudioMime(const std::string& mime) const
234 {
235 return mime.find("audio/") == 0;
236 }
237
IsSubtitleMime(const std::string & mime) const238 bool AVMetaDataCollector::IsSubtitleMime(const std::string& mime) const
239 {
240 return mime == "application/x-subrip" || mime == "text/vtt";
241 }
242
GetAVMetadata()243 std::shared_ptr<Meta> AVMetaDataCollector::GetAVMetadata()
244 {
245 if (collectedAVMetaData_ != nullptr) {
246 return collectedAVMetaData_;
247 }
248 collectedAVMetaData_ = std::make_shared<Meta>();
249 trackInfoVec_.clear();
250 ExtractMetadata();
251 CHECK_AND_RETURN_RET_LOG(collectedMeta_.size() != 0, nullptr, "globalInfo or trackInfos are invalid.");
252 for (const auto &[avKey, value] : collectedMeta_) {
253 if (avKey == AV_KEY_LOCATION_LATITUDE || avKey == AV_KEY_LOCATION_LONGITUDE) {
254 continue;
255 }
256 if (avKey == AV_KEY_VIDEO_IS_HDR_VIVID) {
257 int32_t hdr;
258 if (value == "yes") {
259 hdr = static_cast<int32_t>(HdrType::AV_HDR_TYPE_VIVID);
260 } else {
261 hdr = static_cast<int32_t>(HdrType::AV_HDR_TYPE_NONE);
262 }
263 collectedAVMetaData_->SetData("hdrType", hdr);
264 continue;
265 }
266 auto iter = g_MetadataCodeMap.find(avKey);
267 if (iter != g_MetadataCodeMap.end()) {
268 collectedAVMetaData_->SetData(iter->second, value);
269 }
270 }
271
272 customInfo_ = mediaDemuxer_->GetUserMeta();
273 if (customInfo_ == nullptr) {
274 MEDIA_LOGW("No valid user data");
275 } else {
276 if (AVMETA_KEY_TO_X_MAP.find(AV_KEY_CUSTOMINFO) != AVMETA_KEY_TO_X_MAP.end()) {
277 collectedAVMetaData_->SetData(AVMETA_KEY_TO_X_MAP.find(AV_KEY_CUSTOMINFO)->second, customInfo_);
278 }
279 }
280 collectedAVMetaData_->SetData("tracks", trackInfoVec_);
281 return collectedAVMetaData_;
282 }
283
ExtractMetadata(int32_t key)284 std::string AVMetaDataCollector::ExtractMetadata(int32_t key)
285 {
286 auto metadata = GetAVMetadata();
287 CHECK_AND_RETURN_RET_LOG(collectedMeta_.size() != 0, "", "Failed to call ExtractMetadata");
288
289 auto it = collectedMeta_.find(key);
290 if (it == collectedMeta_.end() || it->second.empty()) {
291 MEDIA_LOGE("The specified metadata %{public}d cannot be obtained from the specified stream.", key);
292 return "";
293 }
294 return collectedMeta_[key];
295 }
296
GetMetadata(const std::shared_ptr<Meta> & globalInfo,const std::vector<std::shared_ptr<Meta>> & trackInfos)297 std::unordered_map<int32_t, std::string> AVMetaDataCollector::GetMetadata(
298 const std::shared_ptr<Meta> &globalInfo, const std::vector<std::shared_ptr<Meta>> &trackInfos)
299 {
300 CHECK_AND_RETURN_RET_LOG(
301 globalInfo != nullptr && trackInfos.size() != 0, {}, "globalInfo or trackInfos are invalid.");
302
303 Metadata metadata;
304 ConvertToAVMeta(globalInfo, metadata);
305
306 int32_t imageTrackCount = 0;
307 size_t trackCount = trackInfos.size();
308 bool isFirstVideoTrack = true;
309 for (size_t index = 0; index < trackCount; index++) {
310 std::shared_ptr<Meta> meta = trackInfos[index];
311 CHECK_AND_RETURN_RET_LOG(meta != nullptr, metadata.tbl_, "meta is invalid, index: %zu", index);
312
313 // skip the image track
314 std::string mime;
315 meta->Get<Tag::MIME_TYPE>(mime);
316 int32_t imageTypeLength = 5;
317 if (mime.substr(0, imageTypeLength).compare("image") == 0) {
318 MEDIA_LOGI("0x%{public}06" PRIXPTR " skip image track", FAKE_POINTER(this));
319 ++imageTrackCount;
320 continue;
321 }
322 InitTracksInfoVector(meta, index);
323 if (mime.find("video") == 0) {
324 if (!isFirstVideoTrack) {
325 continue;
326 }
327 isFirstVideoTrack = false;
328 }
329 Plugins::MediaType mediaType;
330 CHECK_AND_CONTINUE(meta->GetData(Tag::MEDIA_TYPE, mediaType));
331 ConvertToAVMeta(meta, metadata);
332 }
333 FormatAVMeta(metadata, imageTrackCount, globalInfo);
334 auto it = metadata.tbl_.begin();
335 while (it != metadata.tbl_.end()) {
336 MEDIA_LOGD("metadata tbl, key: %{public}d, keyName: %{public}s, val: %{public}s", it->first,
337 AVMETA_KEY_TO_X_MAP.find(it->first)->second.c_str(), it->second.c_str());
338 it++;
339 }
340 return metadata.tbl_;
341 }
342
InitTracksInfoVector(const std::shared_ptr<Meta> & meta,size_t index)343 void AVMetaDataCollector::InitTracksInfoVector(const std::shared_ptr<Meta> &meta, size_t index)
344 {
345 Plugins::MediaType mediaType;
346 bool hasMediaType = meta->GetData(Tag::MEDIA_TYPE, mediaType);
347 if (hasMediaType && mediaType == Plugins::MediaType::AUXILIARY) {
348 GetOtherTrackInfo(meta, index);
349 return;
350 }
351 std::string mime = "";
352 meta->GetData(Tag::MIME_TYPE, mime);
353 if (IsAudioMime(mime)) {
354 GetAudioTrackInfo(meta, mime, index);
355 } else if (IsVideoMime(mime)) {
356 GetVideoTrackInfo(meta, mime, index);
357 } else if (IsSubtitleMime(mime)) {
358 GetSubtitleTrackInfo(meta, mime, index);
359 } else {
360 GetOtherTrackInfo(meta, index);
361 }
362 }
363
GetArtPicture()364 std::shared_ptr<AVSharedMemory> AVMetaDataCollector::GetArtPicture()
365 {
366 MEDIA_LOGI("0x%{public}06" PRIXPTR " GetArtPicture In", FAKE_POINTER(this));
367
368 if (collectedArtPicture_ != nullptr) {
369 return collectedArtPicture_;
370 }
371 const std::vector<std::shared_ptr<Meta>> trackInfos = mediaDemuxer_->GetStreamMetaInfo();
372 size_t trackCount = trackInfos.size();
373 for (size_t index = 0; index < trackCount; index++) {
374 std::shared_ptr<Meta> meta = trackInfos[index];
375 if (meta == nullptr) {
376 MEDIA_LOGW("meta is invalid, index: %zu", index);
377 continue;
378 }
379
380 std::vector<uint8_t> coverAddr;
381 auto mapIt = meta->Find(Tag::MEDIA_COVER);
382 if (mapIt == meta->end()) {
383 continue;
384 }
385 if (Any::IsSameTypeWith<std::vector<uint8_t>>(mapIt->second)) {
386 coverAddr = AnyCast<std::vector<uint8_t>>(mapIt->second);
387 }
388 CHECK_AND_RETURN_RET_LOG(!(coverAddr.size() == 0 || static_cast<int>(coverAddr.size()) > PICTURE_MAX_SIZE),
389 nullptr, "InvalidArtPictureSize %zu", coverAddr.size());
390 uint8_t *addr = coverAddr.data();
391 size_t size = coverAddr.size();
392 auto artPicMem =
393 AVSharedMemoryBase::CreateFromLocal(static_cast<int32_t>(size), AVSharedMemory::FLAGS_READ_ONLY, "artpic");
394 if (artPicMem == nullptr) {
395 MEDIA_LOGE("artPicMem is nullptr");
396 return nullptr;
397 }
398 errno_t rc = memcpy_s(artPicMem->GetBase(), static_cast<size_t>(artPicMem->GetSize()), addr, size);
399 if (rc != EOK) {
400 MEDIA_LOGE("memcpy_s failed, trackCount no %{public}zu", index);
401 return nullptr;
402 }
403 collectedArtPicture_ = artPicMem;
404 return collectedArtPicture_;
405 }
406 MEDIA_LOGE("GetArtPicture Failed");
407 return nullptr;
408 }
409
GetTimeByFrameIndex(uint32_t index,uint64_t & timeUs)410 int32_t AVMetaDataCollector::GetTimeByFrameIndex(uint32_t index, uint64_t &timeUs)
411 {
412 uint32_t trackId = 0;
413 CHECK_AND_RETURN_RET_LOG(GetVideoTrackId(trackId) == Status::OK, MSERR_UNSUPPORT_FILE, "No video track!");
414 CHECK_AND_RETURN_RET_LOG(mediaDemuxer_->GetRelativePresentationTimeUsByIndex(trackId, index, timeUs) == Status::OK,
415 MSERR_UNSUPPORT_FILE, "Get time by frame failed");
416 return MSERR_OK;
417 }
418
GetFrameIndexByTime(uint64_t timeUs,uint32_t & index)419 int32_t AVMetaDataCollector::GetFrameIndexByTime(uint64_t timeUs, uint32_t &index)
420 {
421 uint32_t trackId = 0;
422 CHECK_AND_RETURN_RET_LOG(GetVideoTrackId(trackId) == Status::OK, MSERR_UNSUPPORT_FILE, "No video track!");
423 CHECK_AND_RETURN_RET_LOG(mediaDemuxer_->GetIndexByRelativePresentationTimeUs(trackId, timeUs, index) == Status::OK,
424 MSERR_UNSUPPORT_FILE, "Get frame by time failed");
425 return MSERR_OK;
426 }
427
ConvertToAVMeta(const std::shared_ptr<Meta> & innerMeta,Metadata & avmeta) const428 void AVMetaDataCollector::ConvertToAVMeta(const std::shared_ptr<Meta> &innerMeta, Metadata &avmeta) const
429 {
430 for (const auto &[avKey, innerKey] : AVMETA_KEY_TO_X_MAP) {
431 if (innerKey.compare("customInfo") == 0) {
432 continue;
433 }
434 if (!SetStringByValueType(innerMeta, avmeta, avKey, innerKey)) {
435 break;
436 }
437 SetEmptyStringIfNoData(avmeta, avKey);
438 }
439 }
440
FormatAVMeta(Metadata & avmeta,int32_t imageTrackCount,const std::shared_ptr<Meta> & globalInfo)441 void AVMetaDataCollector::FormatAVMeta(
442 Metadata &avmeta, int32_t imageTrackCount, const std::shared_ptr<Meta> &globalInfo)
443 {
444 std::string str = avmeta.GetMeta(AV_KEY_NUM_TRACKS);
445 if (!str.empty()) {
446 avmeta.SetMeta(AV_KEY_NUM_TRACKS, std::to_string(std::stoi(str) - imageTrackCount));
447 }
448 FormatMimeType(avmeta, globalInfo);
449 FormatDateTime(avmeta, globalInfo);
450 FormatVideoRotateOrientation(avmeta);
451 }
452
FormatMimeType(Metadata & avmeta,const std::shared_ptr<Meta> & globalInfo)453 void AVMetaDataCollector::FormatMimeType(Metadata &avmeta, const std::shared_ptr<Meta> &globalInfo)
454 {
455 Plugins::FileType fileType = Plugins::FileType::UNKNOW;
456 globalInfo->GetData(Tag::MEDIA_FILE_TYPE, fileType);
457 CHECK_AND_RETURN_LOG(fileType != Plugins::FileType::UNKNOW, "unknown file type");
458 if (fileTypeMap.find(fileType) == fileTypeMap.end()) {
459 return;
460 }
461 if (avmeta.GetMeta(AV_KEY_HAS_VIDEO).compare("yes") == 0) {
462 avmeta.SetMeta(AV_KEY_MIME_TYPE, "video/" + fileTypeMap.at(fileType));
463 return;
464 }
465 if (avmeta.GetMeta(AV_KEY_HAS_AUDIO).compare("yes") == 0) {
466 avmeta.SetMeta(AV_KEY_MIME_TYPE, "audio/" + fileTypeMap.at(fileType));
467 }
468 }
469
FormatDateTime(Metadata & avmeta,const std::shared_ptr<Meta> & globalInfo)470 void AVMetaDataCollector::FormatDateTime(Metadata &avmeta, const std::shared_ptr<Meta> &globalInfo)
471 {
472 std::string date;
473 std::string creationTime;
474 globalInfo->GetData(Tag::MEDIA_DATE, date);
475 globalInfo->GetData(Tag::MEDIA_CREATION_TIME, creationTime);
476 std::string formattedDateTime;
477 if (!date.empty()) {
478 formattedDateTime = TimeFormatUtils::FormatDateTimeByTimeZone(date);
479 avmeta.SetMeta(AV_KEY_DATE_TIME_ISO8601, date);
480 } else if (!creationTime.empty()) {
481 formattedDateTime = TimeFormatUtils::FormatDateTimeByTimeZone(creationTime);
482 avmeta.SetMeta(AV_KEY_DATE_TIME_ISO8601, creationTime);
483 }
484 avmeta.SetMeta(AV_KEY_DATE_TIME, formattedDateTime);
485 avmeta.SetMeta(AV_KEY_DATE_TIME_FORMAT,
486 formattedDateTime.compare(date) != 0 ? formattedDateTime : TimeFormatUtils::FormatDataTimeByString(date));
487 }
488
FormatVideoRotateOrientation(Metadata & avmeta)489 void AVMetaDataCollector::FormatVideoRotateOrientation(Metadata &avmeta)
490 {
491 std::string videoRotateOrientationType = avmeta.GetMeta(AV_KEY_VIDEO_ROTATE_ORIENTATION);
492 MEDIA_LOGI("VideoRotateOrientationType is %{public}s", videoRotateOrientationType.c_str());
493 int32_t videoRotateOrientationTypeRet = Plugins::VideoOrientationType::ROTATE_NONE;
494 if (videoRotateOrientationType.size() > NUMBER_OF_CHARACTERS_IN_VALID_VIDEOROTATEORIENTATIONTYPE ||
495 !IsAllDigits(videoRotateOrientationType)) {
496 MEDIA_LOGE("videoRotateOrientationType is invalid");
497 avmeta.SetMeta(AV_KEY_VIDEO_ROTATE_ORIENTATION, std::to_string(VideoRotateOrientationType::TOP_LEFT));
498 return;
499 }
500 videoRotateOrientationTypeRet = std::stoi(videoRotateOrientationType);
501 Plugins::VideoOrientationType videoOrientationType =
502 static_cast<Plugins::VideoOrientationType>(videoRotateOrientationTypeRet);
503 auto it = videoOrientationTypeMap.find(videoOrientationType);
504 CHECK_AND_RETURN_LOG(it != videoOrientationTypeMap.end(),
505 "can't find mapped videoOrientationType name in videoOrientationTypeMap");
506 avmeta.SetMeta(AV_KEY_VIDEO_ROTATE_ORIENTATION, std::to_string(it->second));
507 }
508
IsAllDigits(const std::string & str)509 bool AVMetaDataCollector::IsAllDigits(const std::string& str)
510 {
511 if (str.empty()) {
512 return false;
513 }
514 return std::all_of(str.begin(), str.end(), [](char c) {
515 return c >= '0' && c <= '9';
516 });
517 }
518
SetEmptyStringIfNoData(Metadata & avmeta,int32_t avKey) const519 void AVMetaDataCollector::SetEmptyStringIfNoData(Metadata &avmeta, int32_t avKey) const
520 {
521 if (!avmeta.HasMeta(avKey)) {
522 avmeta.SetMeta(avKey, "");
523 }
524 }
525
SetStringByValueType(const std::shared_ptr<Meta> & innerMeta,Metadata & avmeta,int32_t avKey,std::string innerKey) const526 bool AVMetaDataCollector::SetStringByValueType(const std::shared_ptr<Meta> &innerMeta,
527 Metadata &avmeta, int32_t avKey, std::string innerKey) const
528 {
529 Any type = OHOS::Media::GetDefaultAnyValue(innerKey);
530 if (Any::IsSameTypeWith<int32_t>(type)) {
531 int32_t intVal;
532 if (innerMeta->GetData(innerKey, intVal) && intVal != 0) {
533 avmeta.SetMeta(avKey, std::to_string(intVal));
534 }
535 } else if (Any::IsSameTypeWith<std::string>(type)) {
536 std::string strVal;
537 if (innerMeta->GetData(innerKey, strVal)) {
538 avmeta.SetMeta(avKey, strVal);
539 }
540 } else if (Any::IsSameTypeWith<Plugins::VideoRotation>(type)) {
541 Plugins::VideoRotation rotation;
542 if (innerMeta->GetData(innerKey, rotation)) {
543 avmeta.SetMeta(avKey, std::to_string(rotation));
544 }
545 } else if (Any::IsSameTypeWith<Plugins::VideoOrientationType>(type)) {
546 Plugins::VideoOrientationType orientation;
547 if (innerMeta->GetData(innerKey, orientation)) {
548 avmeta.SetMeta(avKey, std::to_string(orientation));
549 }
550 } else if (Any::IsSameTypeWith<int64_t>(type)) {
551 int64_t duration;
552 if (innerMeta->GetData(innerKey, duration)) {
553 avmeta.SetMeta(avKey, std::to_string(duration / SECOND_DEVIDE_MS));
554 }
555 } else if (Any::IsSameTypeWith<bool>(type)) {
556 bool isTrue;
557 if (innerMeta->GetData(innerKey, isTrue)) {
558 avmeta.SetMeta(avKey, isTrue ? "yes" : "");
559 }
560 } else if (Any::IsSameTypeWith<float>(type)) {
561 float value;
562 if (innerMeta->GetData(innerKey, value) && collectedAVMetaData_ != nullptr) {
563 collectedAVMetaData_->SetData(innerKey, value);
564 }
565 } else {
566 MEDIA_LOGE("not found type matched with innerKey: %{public}s", innerKey.c_str());
567 return false;
568 }
569 return true;
570 }
571
Reset()572 void AVMetaDataCollector::Reset()
573 {
574 mediaDemuxer_->Reset();
575 collectedMeta_.clear();
576 videoTrackId_ = 0;
577 hasVideo_ = false;
578 collectedArtPicture_ = nullptr;
579 }
580
Destroy()581 void AVMetaDataCollector::Destroy()
582 {
583 mediaDemuxer_ = nullptr;
584 }
585 } // namespace Media
586 } // namespace OHOS