• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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