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 "avmetadatahelper_impl.h"
17
18 #include "common/media_source.h"
19 #include "media_errors.h"
20 #include "media_log.h"
21 #include "media_description.h"
22 #include "meta_utils.h"
23 #include "uri_helper.h"
24 #include "pipeline/pipeline.h"
25 #include "osal/task/pipeline_threadpool.h"
26 #include "pts_and_index_conversion.h"
27
28 namespace {
29 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_METADATA, "AVMetadataHelperImpl" };
30 }
31
32 namespace OHOS {
33 namespace Media {
OnError(MediaAVCodec::AVCodecErrorType errorType,int32_t errorCode)34 void AVMetadataHelperImpl::OnError(MediaAVCodec::AVCodecErrorType errorType, int32_t errorCode)
35 {
36 MEDIA_LOGE("OnError errorType:%{public}d, errorCode:%{public}d", static_cast<int32_t>(errorType), errorCode);
37 stopProcessing_ = true;
38 }
39
AVMetadataHelperImpl()40 AVMetadataHelperImpl::AVMetadataHelperImpl()
41 {
42 MEDIA_LOGD("Constructor, instance: 0x%{public}06" PRIXPTR "", FAKE_POINTER(this));
43 groupId_ = std::string("AVMeta_") + std::to_string(Pipeline::Pipeline::GetNextPipelineId());
44 }
45
~AVMetadataHelperImpl()46 AVMetadataHelperImpl::~AVMetadataHelperImpl()
47 {
48 MEDIA_LOGD("Destructor, instance: 0x%{public}06" PRIXPTR "", FAKE_POINTER(this));
49 Destroy();
50 }
51
SetSource(const std::string & uri,int32_t usage)52 int32_t AVMetadataHelperImpl::SetSource(const std::string &uri, int32_t usage)
53 {
54 UriHelper uriHelper(uri);
55 if (uriHelper.UriType() != UriHelper::URI_TYPE_FILE && uriHelper.UriType() != UriHelper::URI_TYPE_FD) {
56 MEDIA_LOGE("Unsupported uri type : %{private}s", uri.c_str());
57 return MSERR_UNSUPPORT;
58 }
59
60 MEDIA_LOGD("0x%{public}06" PRIXPTR " SetSource uri: %{private}s, type:%{public}d", FAKE_POINTER(this), uri.c_str(),
61 uriHelper.UriType());
62
63 auto ret = SetSourceInternel(uri, usage == AVMetadataUsage::AV_META_USAGE_FRAME_INDEX_CONVERT);
64 CHECK_AND_RETURN_RET_LOG(usage != AVMetadataUsage::AV_META_USAGE_FRAME_INDEX_CONVERT, static_cast<int32_t>(ret),
65 "ret = %{public}d", static_cast<int32_t>(ret));
66 CHECK_AND_RETURN_RET_LOG(ret == Status::OK, MSERR_INVALID_VAL,
67 "0x%{public}06" PRIXPTR " Failed to call SetSourceInternel", FAKE_POINTER(this));
68 CHECK_AND_RETURN_RET_LOG(MetaUtils::CheckFileType(mediaDemuxer_->GetGlobalMetaInfo()),
69 MSERR_UNSUPPORT, "0x%{public}06" PRIXPTR "SetSource unsupport", FAKE_POINTER(this));
70 return MSERR_OK;
71 }
72
SetSource(const std::shared_ptr<IMediaDataSource> & dataSrc)73 int32_t AVMetadataHelperImpl::SetSource(const std::shared_ptr<IMediaDataSource> &dataSrc)
74 {
75 MEDIA_LOGI("0x%{public}06" PRIXPTR "SetSource dataSrc", FAKE_POINTER(this));
76 Status ret = SetSourceInternel(dataSrc);
77 CHECK_AND_RETURN_RET_LOG(ret == Status::OK, MSERR_INVALID_VAL, "Failed to call SetSourceInternel");
78
79 CHECK_AND_RETURN_RET_LOG(MetaUtils::CheckFileType(mediaDemuxer_->GetGlobalMetaInfo()),
80 MSERR_UNSUPPORT, "0x%{public}06" PRIXPTR "SetSource unsupport", FAKE_POINTER(this));
81 MEDIA_LOGI("0x%{public}06" PRIXPTR "set source success", FAKE_POINTER(this));
82 return MSERR_OK;
83 }
84
SetSourceInternel(const std::string & uri,bool isForFrameConvert)85 Status AVMetadataHelperImpl::SetSourceInternel(const std::string &uri, bool isForFrameConvert)
86 {
87 CHECK_AND_RETURN_RET_LOG(!isForFrameConvert, SetSourceForFrameConvert(uri), "SetSource for frame convert");
88 Reset();
89 mediaDemuxer_ = std::make_shared<MediaDemuxer>();
90 mediaDemuxer_->SetEnableOnlineFdCache(false);
91 mediaDemuxer_->SetInterruptState(isInterruptNeeded_.load());
92 mediaDemuxer_->SetPlayerId(groupId_);
93 CHECK_AND_RETURN_RET_LOG(
94 mediaDemuxer_ != nullptr, Status::ERROR_INVALID_DATA, "SetSourceInternel demuxer is nullptr");
95 Status ret = mediaDemuxer_->SetDataSource(std::make_shared<MediaSource>(uri));
96 CHECK_AND_RETURN_RET_LOG(ret == Status::OK, ret,
97 "0x%{public}06" PRIXPTR " SetSourceInternel demuxer failed to call SetDataSource", FAKE_POINTER(this));
98 return Status::OK;
99 }
100
SetSourceForFrameConvert(const std::string & uri)101 Status AVMetadataHelperImpl::SetSourceForFrameConvert(const std::string &uri)
102 {
103 Reset();
104 isForFrameConvert_ = true;
105 conversion_ = std::make_shared<TimeAndIndexConversion>();
106 CHECK_AND_RETURN_RET_LOG(
107 conversion_ != nullptr, Status::ERROR_NO_MEMORY, "SetSourceInternel conversion_ is nullptr");
108 Status ret = conversion_->SetDataSource(std::make_shared<MediaSource>(uri));
109 CHECK_AND_RETURN_RET_LOG(ret == Status::OK, ret,
110 "0x%{public}06" PRIXPTR " SetSourceInternel conversion_ failed", FAKE_POINTER(this));
111 return Status::OK;
112 }
113
SetSourceInternel(const std::shared_ptr<IMediaDataSource> & dataSrc)114 Status AVMetadataHelperImpl::SetSourceInternel(const std::shared_ptr<IMediaDataSource> &dataSrc)
115 {
116 Reset();
117 mediaDemuxer_ = std::make_shared<MediaDemuxer>();
118 mediaDemuxer_->SetPlayerId(groupId_);
119 CHECK_AND_RETURN_RET_LOG(
120 mediaDemuxer_ != nullptr, Status::ERROR_INVALID_DATA, "SetSourceInternel demuxer is nullptr");
121 Status ret = mediaDemuxer_->SetDataSource(std::make_shared<MediaSource>(dataSrc));
122 CHECK_AND_RETURN_RET_LOG(ret == Status::OK, ret, "Failed to call SetDataSource");
123 return Status::OK;
124 }
125
ResolveMetadata(int32_t key)126 std::string AVMetadataHelperImpl::ResolveMetadata(int32_t key)
127 {
128 MEDIA_LOGI("enter ResolveMetadata with key: %{public}d", key);
129 auto res = InitMetadataCollector();
130 CHECK_AND_RETURN_RET(res == Status::OK, "");
131 return metadataCollector_->ExtractMetadata(key);
132 }
133
ResolveMetadata()134 std::unordered_map<int32_t, std::string> AVMetadataHelperImpl::ResolveMetadata()
135 {
136 MEDIA_LOGD("enter ResolveMetadata");
137 auto res = InitMetadataCollector();
138 CHECK_AND_RETURN_RET(res == Status::OK, {});
139 return metadataCollector_->ExtractMetadata();
140 }
141
FetchArtPicture()142 std::shared_ptr<AVSharedMemory> AVMetadataHelperImpl::FetchArtPicture()
143 {
144 MEDIA_LOGI("0x%{public}06" PRIXPTR " enter FetchArtPicture", FAKE_POINTER(this));
145 auto res = InitMetadataCollector();
146 CHECK_AND_RETURN_RET(res == Status::OK, nullptr);
147 return metadataCollector_->GetArtPicture();
148 }
149
GetAVMetadata()150 std::shared_ptr<Meta> AVMetadataHelperImpl::GetAVMetadata()
151 {
152 MEDIA_LOGE("enter GetAVMetadata");
153 auto res = InitMetadataCollector();
154 CHECK_AND_RETURN_RET(res == Status::OK, nullptr);
155 return metadataCollector_->GetAVMetadata();
156 }
157
FetchFrameAtTime(int64_t timeUs,int32_t option,const OutputConfiguration & param)158 std::shared_ptr<AVSharedMemory> AVMetadataHelperImpl::FetchFrameAtTime(
159 int64_t timeUs, int32_t option, const OutputConfiguration ¶m)
160 {
161 MEDIA_LOGD("enter FetchFrameAtTime");
162 auto res = InitThumbnailGenerator();
163 CHECK_AND_RETURN_RET(res == Status::OK, nullptr);
164 return thumbnailGenerator_->FetchFrameAtTime(timeUs, option, param);
165 }
166
GetTimeByFrameIndex(uint32_t index,uint64_t & time)167 int32_t AVMetadataHelperImpl::GetTimeByFrameIndex(uint32_t index, uint64_t &time)
168 {
169 CHECK_AND_RETURN_RET(!isForFrameConvert_, GetTimeForFrameConvert(index, time));
170 auto res = InitMetadataCollector();
171 CHECK_AND_RETURN_RET_LOG(res == Status::OK, MSERR_INVALID_STATE, "Create collector failed");
172 return metadataCollector_->GetTimeByFrameIndex(index, time);
173 }
174
GetFrameIndexByTime(uint64_t time,uint32_t & index)175 int32_t AVMetadataHelperImpl::GetFrameIndexByTime(uint64_t time, uint32_t &index)
176 {
177 CHECK_AND_RETURN_RET(!isForFrameConvert_, GetIndexForFrameConvert(time, index));
178 auto res = InitMetadataCollector();
179 CHECK_AND_RETURN_RET_LOG(res == Status::OK, MSERR_INVALID_STATE, "Create collector failed");
180 return metadataCollector_->GetFrameIndexByTime(time, index);
181 }
182
GetTimeForFrameConvert(uint32_t index,uint64_t & time)183 int32_t AVMetadataHelperImpl::GetTimeForFrameConvert(uint32_t index, uint64_t &time)
184 {
185 CHECK_AND_RETURN_RET_LOG(conversion_ != nullptr, MSERR_INVALID_STATE, "conversion_ is nullptr");
186 uint32_t trackIndex = 0;
187 auto res = conversion_->GetFirstVideoTrackIndex(trackIndex);
188 CHECK_AND_RETURN_RET_LOG(res == Status::OK, MSERR_UNSUPPORT_FILE, "GetFirstVideoTrackIndex failed");
189 res = conversion_->GetRelativePresentationTimeUsByIndex(trackIndex, index, time);
190 MEDIA_LOGI("trackIndex: %{public}" PRIu32 ", index: %{public}" PRIu32 ", time: %{public}" PRIu64
191 ", res: %{public}d", trackIndex, index, time, res);
192 return res == Status::OK ? MSERR_OK : MSERR_UNSUPPORT_FILE;
193 }
194
GetIndexForFrameConvert(uint64_t time,uint32_t & index)195 int32_t AVMetadataHelperImpl::GetIndexForFrameConvert(uint64_t time, uint32_t &index)
196 {
197 CHECK_AND_RETURN_RET_LOG(conversion_ != nullptr, MSERR_INVALID_STATE, "conversion_ is nullptr");
198 uint32_t trackIndex = 0;
199 auto res = conversion_->GetFirstVideoTrackIndex(trackIndex);
200 CHECK_AND_RETURN_RET_LOG(res == Status::OK, MSERR_UNSUPPORT_FILE, "GetFirstVideoTrackIndex failed");
201 res = conversion_->GetIndexByRelativePresentationTimeUs(trackIndex, time, index);
202 MEDIA_LOGI("trackIndex: %{public}" PRIu32 ", index: %{public}" PRIu32 ", time: %{public}" PRIu64
203 ", res: %{public}d", trackIndex, index, time, res);
204 return res == Status::OK ? MSERR_OK : MSERR_UNSUPPORT_FILE;
205 }
206
FetchFrameYuv(int64_t timeUs,int32_t option,const OutputConfiguration & param)207 std::shared_ptr<AVBuffer> AVMetadataHelperImpl::FetchFrameYuv(
208 int64_t timeUs, int32_t option, const OutputConfiguration ¶m)
209 {
210 MEDIA_LOGD("enter FetchFrameAtTime");
211 auto res = InitThumbnailGenerator();
212 CHECK_AND_RETURN_RET(res == Status::OK, nullptr);
213 return thumbnailGenerator_->FetchFrameYuv(timeUs, option, param);
214 }
215
Reset()216 void AVMetadataHelperImpl::Reset()
217 {
218 if (metadataCollector_ != nullptr) {
219 metadataCollector_->Reset();
220 }
221
222 if (thumbnailGenerator_ != nullptr) {
223 thumbnailGenerator_->Reset();
224 }
225
226 if (mediaDemuxer_ != nullptr) {
227 mediaDemuxer_->Reset();
228 }
229
230 isForFrameConvert_ = false;
231 }
232
Destroy()233 void AVMetadataHelperImpl::Destroy()
234 {
235 if (metadataCollector_ != nullptr) {
236 metadataCollector_->Destroy();
237 }
238
239 if (thumbnailGenerator_ != nullptr) {
240 thumbnailGenerator_->Destroy();
241 }
242
243 metadataCollector_ = nullptr;
244 thumbnailGenerator_ = nullptr;
245 PipeLineThreadPool::GetInstance().DestroyThread(groupId_);
246 MEDIA_LOGD("0x%{public}06" PRIXPTR " Finish Destroy.", FAKE_POINTER(this));
247 }
248
InitMetadataCollector()249 Status AVMetadataHelperImpl::InitMetadataCollector()
250 {
251 CHECK_AND_RETURN_RET_LOG(
252 mediaDemuxer_ != nullptr, Status::ERROR_INVALID_STATE, "mediaDemuxer_ is nullptr");
253 if (metadataCollector_ == nullptr) {
254 metadataCollector_ = std::make_shared<AVMetaDataCollector>(mediaDemuxer_);
255 }
256 CHECK_AND_RETURN_RET_LOG(
257 metadataCollector_ != nullptr, Status::ERROR_INVALID_STATE, "Init metadata collector failed.");
258 return Status::OK;
259 }
260
InitThumbnailGenerator()261 Status AVMetadataHelperImpl::InitThumbnailGenerator()
262 {
263 CHECK_AND_RETURN_RET_LOG(
264 mediaDemuxer_ != nullptr, Status::ERROR_INVALID_STATE, "mediaDemuxer_ is nullptr");
265 if (thumbnailGenerator_ == nullptr) {
266 thumbnailGenerator_ = std::make_shared<AVThumbnailGenerator>(mediaDemuxer_);
267 }
268 CHECK_AND_RETURN_RET_LOG(
269 thumbnailGenerator_ != nullptr, Status::ERROR_INVALID_STATE, "Init thumbnail generator failed.");
270 return Status::OK;
271 }
272
SetInterruptState(bool isInterruptNeeded)273 void AVMetadataHelperImpl::SetInterruptState(bool isInterruptNeeded)
274 {
275 MEDIA_LOGI("Metadata set interrupt state %{public}d", isInterruptNeeded);
276 isInterruptNeeded_ = isInterruptNeeded;
277 CHECK_AND_RETURN(mediaDemuxer_ != nullptr);
278 mediaDemuxer_->SetInterruptState(isInterruptNeeded);
279 }
280 } // namespace Media
281 } // namespace OHOS