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 "osal/task/pipeline_threadpool.h"
25 #include "pts_and_index_conversion.h"
26
27 namespace {
28 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_METADATA, "AVMetadataHelperImpl" };
29 }
30
31 namespace OHOS {
32 namespace Media {
OnError(MediaAVCodec::AVCodecErrorType errorType,int32_t errorCode)33 void AVMetadataHelperImpl::OnError(MediaAVCodec::AVCodecErrorType errorType, int32_t errorCode)
34 {
35 MEDIA_LOGE("OnError errorType:%{public}d, errorCode:%{public}d", static_cast<int32_t>(errorType), errorCode);
36 stopProcessing_ = true;
37 }
38
AVMetadataHelperImpl(int32_t appUid,int32_t appPid,uint32_t appTokenId,std::string appName)39 AVMetadataHelperImpl::AVMetadataHelperImpl(int32_t appUid, int32_t appPid, uint32_t appTokenId,
40 std::string appName) : appUid_(appUid), appPid_(appPid), appTokenId_(appTokenId), appName_(appName)
41 {
42 MEDIA_LOGD("Constructor, instance: 0x%{public}06" PRIXPTR "", FAKE_POINTER(this));
43 groupId_ = std::string("AVMeta_") + std::to_string(OHOS::Media::Pipeline::Pipeline::GetNextPipelineId());
44 interruptMonitor_ = std::make_shared<InterruptMonitor>();
45 if (interruptMonitor_ == nullptr) {
46 MEDIA_LOGE("fail to allocate memory for InterruptMonitor");
47 }
48 }
49
~AVMetadataHelperImpl()50 AVMetadataHelperImpl::~AVMetadataHelperImpl()
51 {
52 MEDIA_LOGD("Destructor, instance: 0x%{public}06" PRIXPTR "", FAKE_POINTER(this));
53 Destroy();
54 }
55
SetSource(const std::string & uri,int32_t usage)56 int32_t AVMetadataHelperImpl::SetSource(const std::string &uri, int32_t usage)
57 {
58 UriHelper uriHelper(uri);
59 if (uriHelper.UriType() != UriHelper::URI_TYPE_FILE && uriHelper.UriType() != UriHelper::URI_TYPE_FD) {
60 MEDIA_LOGE("Unsupported uri type : %{private}s", uri.c_str());
61 return MSERR_UNSUPPORT;
62 }
63
64 MEDIA_LOGD("0x%{public}06" PRIXPTR " SetSource uri: %{private}s, type:%{public}d", FAKE_POINTER(this), uri.c_str(),
65 uriHelper.UriType());
66
67 auto ret = SetSourceInternel(uri, usage == AVMetadataUsage::AV_META_USAGE_FRAME_INDEX_CONVERT);
68 CHECK_AND_RETURN_RET_LOG(usage != AVMetadataUsage::AV_META_USAGE_FRAME_INDEX_CONVERT, static_cast<int32_t>(ret),
69 "ret = %{public}d", static_cast<int32_t>(ret));
70 CHECK_AND_RETURN_RET_LOG(ret == Status::OK, MSERR_INVALID_VAL,
71 "0x%{public}06" PRIXPTR " Failed to call SetSourceInternel", FAKE_POINTER(this));
72 CHECK_AND_RETURN_RET_LOG(MetaUtils::CheckFileType(mediaDemuxer_->GetGlobalMetaInfo()),
73 MSERR_UNSUPPORT, "0x%{public}06" PRIXPTR "SetSource unsupport", FAKE_POINTER(this));
74 return MSERR_OK;
75 }
76
SetAVMetadataCaller(AVMetadataCaller caller)77 int32_t AVMetadataHelperImpl::SetAVMetadataCaller(AVMetadataCaller caller)
78 {
79 metadataCaller_ = caller;
80 MEDIA_LOGI("0x%{public}06" PRIXPTR " SetAVMetadataCaller caller: %{public}d", FAKE_POINTER(this),
81 static_cast<int32_t>(metadataCaller_));
82 return MSERR_OK;
83 }
84
SetUrlSource(const std::string & uri,const std::map<std::string,std::string> & header)85 int32_t AVMetadataHelperImpl::SetUrlSource(const std::string &uri, const std::map<std::string, std::string> &header)
86 {
87 MEDIA_LOGD("0x%{public}06" PRIXPTR " SetUrlSource uri: %{private}s", FAKE_POINTER(this), uri.c_str());
88
89 auto ret = SetSourceInternel(uri, header);
90 CHECK_AND_RETURN_RET_LOG(ret == Status::OK, MSERR_INVALID_VAL,
91 "0x%{public}06" PRIXPTR " Failed to call SetSourceInternel", FAKE_POINTER(this));
92 CHECK_AND_RETURN_RET_LOG(MetaUtils::CheckFileType(mediaDemuxer_->GetGlobalMetaInfo()),
93 MSERR_UNSUPPORT, "0x%{public}06" PRIXPTR "SetSource unsupport", FAKE_POINTER(this));
94 CHECK_AND_RETURN_RET_LOG(!mediaDemuxer_->IsSeekToTimeSupported(),
95 MSERR_UNSUPPORT, "0x%{public}06" PRIXPTR " hls/dash unsupport", FAKE_POINTER(this));
96 CHECK_AND_RETURN_RET_LOG(GetDurationMs() > 0,
97 MSERR_UNSUPPORT, "0x%{public}06" PRIXPTR " live stream unsupport", FAKE_POINTER(this));
98 return MSERR_OK;
99 }
100
GetDurationMs()101 int64_t AVMetadataHelperImpl::GetDurationMs()
102 {
103 CHECK_AND_RETURN_RET_LOG(mediaDemuxer_ != nullptr,
104 Plugins::HST_TIME_NONE, "Get media duration failed, demuxer is not ready");
105 int64_t duration = 0;
106 CHECK_AND_RETURN_RET_LOG(mediaDemuxer_->GetDuration(duration),
107 Plugins::HST_TIME_NONE, "Get media duration failed");
108 CHECK_AND_RETURN_RET_NOLOG(duration > 0, Plugins::HST_TIME_NONE);
109 return Plugins::HstTime2Us(duration);
110 }
111
SetSource(const std::shared_ptr<IMediaDataSource> & dataSrc)112 int32_t AVMetadataHelperImpl::SetSource(const std::shared_ptr<IMediaDataSource> &dataSrc)
113 {
114 MEDIA_LOGI("0x%{public}06" PRIXPTR "SetSource dataSrc", FAKE_POINTER(this));
115 Status ret = SetSourceInternel(dataSrc);
116 CHECK_AND_RETURN_RET_LOG(ret == Status::OK, MSERR_INVALID_VAL, "Failed to call SetSourceInternel");
117
118 CHECK_AND_RETURN_RET_LOG(MetaUtils::CheckFileType(mediaDemuxer_->GetGlobalMetaInfo()),
119 MSERR_UNSUPPORT, "0x%{public}06" PRIXPTR "SetSource unsupport", FAKE_POINTER(this));
120 MEDIA_LOGI("0x%{public}06" PRIXPTR "set source success", FAKE_POINTER(this));
121 return MSERR_OK;
122 }
123
SetSourceInternel(const std::string & uri,bool isForFrameConvert)124 Status AVMetadataHelperImpl::SetSourceInternel(const std::string &uri, bool isForFrameConvert)
125 {
126 CHECK_AND_RETURN_RET_LOG(!isForFrameConvert, SetSourceForFrameConvert(uri), "SetSource for frame convert");
127 Reset();
128 mediaDemuxer_ = std::make_shared<MediaDemuxer>();
129 CHECK_AND_RETURN_RET_LOG(
130 mediaDemuxer_ != nullptr, Status::ERROR_INVALID_DATA, "SetSourceInternel demuxer is nullptr");
131 mediaDemuxer_->SetEnableOnlineFdCache(false);
132 mediaDemuxer_->SetPlayerId(groupId_);
133 if (interruptMonitor_) {
134 interruptMonitor_->RegisterListener(mediaDemuxer_);
135 interruptMonitor_->SetInterruptState(isInterruptNeeded_.load());
136 }
137 Status ret = mediaDemuxer_->SetDataSource(std::make_shared<MediaSource>(uri));
138 CHECK_AND_RETURN_RET_LOG(ret == Status::OK, ret,
139 "0x%{public}06" PRIXPTR " SetSourceInternel demuxer failed to call SetDataSource", FAKE_POINTER(this));
140 return Status::OK;
141 }
142
SetSourceForFrameConvert(const std::string & uri)143 Status AVMetadataHelperImpl::SetSourceForFrameConvert(const std::string &uri)
144 {
145 Reset();
146 isForFrameConvert_ = true;
147 conversion_ = std::make_shared<TimeAndIndexConversion>();
148 CHECK_AND_RETURN_RET_LOG(
149 conversion_ != nullptr, Status::ERROR_NO_MEMORY, "SetSourceInternel conversion_ is nullptr");
150 Status ret = conversion_->SetDataSource(std::make_shared<MediaSource>(uri));
151 CHECK_AND_RETURN_RET_LOG(ret == Status::OK, ret,
152 "0x%{public}06" PRIXPTR " SetSourceInternel conversion_ failed", FAKE_POINTER(this));
153 return Status::OK;
154 }
155
SetSourceInternel(const std::shared_ptr<IMediaDataSource> & dataSrc)156 Status AVMetadataHelperImpl::SetSourceInternel(const std::shared_ptr<IMediaDataSource> &dataSrc)
157 {
158 Reset();
159 mediaDemuxer_ = std::make_shared<MediaDemuxer>();
160 CHECK_AND_RETURN_RET_LOG(
161 mediaDemuxer_ != nullptr, Status::ERROR_INVALID_DATA, "SetSourceInternel demuxer is nullptr");
162 mediaDemuxer_->SetEnableOnlineFdCache(false);
163 mediaDemuxer_->SetPlayerId(groupId_);
164 if (interruptMonitor_) {
165 interruptMonitor_->RegisterListener(mediaDemuxer_);
166 }
167 Status ret = mediaDemuxer_->SetDataSource(std::make_shared<MediaSource>(dataSrc));
168 CHECK_AND_RETURN_RET_LOG(ret == Status::OK, ret, "Failed to call SetDataSource");
169 return Status::OK;
170 }
171
SetSourceInternel(const std::string & uri,const std::map<std::string,std::string> & header)172 Status AVMetadataHelperImpl::SetSourceInternel(const std::string &uri,
173 const std::map<std::string, std::string> &header)
174 {
175 Reset();
176 mediaDemuxer_ = std::make_shared<MediaDemuxer>();
177 CHECK_AND_RETURN_RET_LOG(
178 mediaDemuxer_ != nullptr, Status::ERROR_INVALID_DATA, "SetSourceInternel demuxer is nullptr");
179 mediaDemuxer_->SetPlayerId(groupId_);
180 if (interruptMonitor_) {
181 interruptMonitor_->RegisterListener(mediaDemuxer_);
182 interruptMonitor_->SetInterruptState(isInterruptNeeded_.load());
183 }
184 Status ret = Status::OK;
185 if (!header.empty()) {
186 MEDIA_LOGI("DoSetSource header");
187 ret = mediaDemuxer_->SetDataSource(std::make_shared<MediaSource>(uri, header));
188 } else {
189 MEDIA_LOGI("DoSetSource url");
190 ret = mediaDemuxer_->SetDataSource(std::make_shared<MediaSource>(uri));
191 }
192 CHECK_AND_RETURN_RET_LOG(ret == Status::OK, ret,
193 "0x%{public}06" PRIXPTR " SetSourceInternel demuxer failed to call SetDataSource", FAKE_POINTER(this));
194 return Status::OK;
195 }
196
ResolveMetadata(int32_t key)197 std::string AVMetadataHelperImpl::ResolveMetadata(int32_t key)
198 {
199 MEDIA_LOGI("enter ResolveMetadata with key: %{public}d", key);
200 auto res = InitMetadataCollector();
201 CHECK_AND_RETURN_RET(res == Status::OK, "");
202 return metadataCollector_->ExtractMetadata(key);
203 }
204
ResolveMetadata()205 std::unordered_map<int32_t, std::string> AVMetadataHelperImpl::ResolveMetadata()
206 {
207 MEDIA_LOGD("enter ResolveMetadata");
208 auto res = InitMetadataCollector();
209 CHECK_AND_RETURN_RET(res == Status::OK, {});
210 return metadataCollector_->ExtractMetadata();
211 }
212
FetchArtPicture()213 std::shared_ptr<AVSharedMemory> AVMetadataHelperImpl::FetchArtPicture()
214 {
215 MEDIA_LOGI("0x%{public}06" PRIXPTR " enter FetchArtPicture", FAKE_POINTER(this));
216 auto res = InitMetadataCollector();
217 CHECK_AND_RETURN_RET(res == Status::OK, nullptr);
218 return metadataCollector_->GetArtPicture();
219 }
220
GetAVMetadata()221 std::shared_ptr<Meta> AVMetadataHelperImpl::GetAVMetadata()
222 {
223 MEDIA_LOGE("enter GetAVMetadata");
224 auto res = InitMetadataCollector();
225 CHECK_AND_RETURN_RET(res == Status::OK, nullptr);
226 return metadataCollector_->GetAVMetadata();
227 }
228
FetchFrameAtTime(int64_t timeUs,int32_t option,const OutputConfiguration & param)229 std::shared_ptr<AVSharedMemory> AVMetadataHelperImpl::FetchFrameAtTime(
230 int64_t timeUs, int32_t option, const OutputConfiguration ¶m)
231 {
232 MEDIA_LOGD("enter FetchFrameAtTime");
233 auto res = InitThumbnailGenerator();
234 CHECK_AND_RETURN_RET(res == Status::OK, nullptr);
235 return thumbnailGenerator_->FetchFrameAtTime(timeUs, option, param);
236 }
237
FetchFrameYuv(int64_t timeUs,int32_t option,const OutputConfiguration & param)238 std::shared_ptr<AVBuffer> AVMetadataHelperImpl::FetchFrameYuv(
239 int64_t timeUs, int32_t option, const OutputConfiguration ¶m)
240 {
241 MEDIA_LOGD("enter FetchFrameAtTime");
242 auto res = InitThumbnailGenerator();
243 CHECK_AND_RETURN_RET_NOLOG(res == Status::OK, nullptr);
244 std::shared_ptr<AVBuffer> avBuffer = thumbnailGenerator_->FetchFrameYuv(timeUs, option, param);
245 CHECK_AND_RETURN_RET_NOLOG(metadataCaller_ != AVMetadataCaller::AV_METADATA_EXTRACTOR || avBuffer == nullptr ||
246 !(avBuffer->flag_ & (uint32_t)(AVBufferFlag::EOS)), nullptr);
247 return avBuffer;
248 }
249
GetTimeByFrameIndex(uint32_t index,uint64_t & time)250 int32_t AVMetadataHelperImpl::GetTimeByFrameIndex(uint32_t index, uint64_t &time)
251 {
252 CHECK_AND_RETURN_RET(!isForFrameConvert_, GetTimeForFrameConvert(index, time));
253 auto res = InitMetadataCollector();
254 CHECK_AND_RETURN_RET_LOG(res == Status::OK, MSERR_INVALID_STATE, "Create collector failed");
255 return metadataCollector_->GetTimeByFrameIndex(index, time);
256 }
257
GetFrameIndexByTime(uint64_t time,uint32_t & index)258 int32_t AVMetadataHelperImpl::GetFrameIndexByTime(uint64_t time, uint32_t &index)
259 {
260 CHECK_AND_RETURN_RET(!isForFrameConvert_, GetIndexForFrameConvert(time, index));
261 auto res = InitMetadataCollector();
262 CHECK_AND_RETURN_RET_LOG(res == Status::OK, MSERR_INVALID_STATE, "Create collector failed");
263 return metadataCollector_->GetFrameIndexByTime(time, index);
264 }
265
GetTimeForFrameConvert(uint32_t index,uint64_t & time)266 int32_t AVMetadataHelperImpl::GetTimeForFrameConvert(uint32_t index, uint64_t &time)
267 {
268 CHECK_AND_RETURN_RET_LOG(conversion_ != nullptr, MSERR_INVALID_STATE, "conversion_ is nullptr");
269 uint32_t trackIndex = 0;
270 auto res = conversion_->GetFirstVideoTrackIndex(trackIndex);
271 CHECK_AND_RETURN_RET_LOG(res == Status::OK, MSERR_UNSUPPORT_FILE, "GetFirstVideoTrackIndex failed");
272 res = conversion_->GetRelativePresentationTimeUsByIndex(trackIndex, index, time);
273 MEDIA_LOGI("trackIndex: %{public}" PRIu32 ", index: %{public}" PRIu32 ", time: %{public}" PRIu64
274 ", res: %{public}d", trackIndex, index, time, res);
275 return res == Status::OK ? MSERR_OK : MSERR_UNSUPPORT_FILE;
276 }
277
GetIndexForFrameConvert(uint64_t time,uint32_t & index)278 int32_t AVMetadataHelperImpl::GetIndexForFrameConvert(uint64_t time, uint32_t &index)
279 {
280 CHECK_AND_RETURN_RET_LOG(conversion_ != nullptr, MSERR_INVALID_STATE, "conversion_ is nullptr");
281 uint32_t trackIndex = 0;
282 auto res = conversion_->GetFirstVideoTrackIndex(trackIndex);
283 CHECK_AND_RETURN_RET_LOG(res == Status::OK, MSERR_UNSUPPORT_FILE, "GetFirstVideoTrackIndex failed");
284 res = conversion_->GetIndexByRelativePresentationTimeUs(trackIndex, time, index);
285 MEDIA_LOGI("trackIndex: %{public}" PRIu32 ", index: %{public}" PRIu32 ", time: %{public}" PRIu64
286 ", res: %{public}d", trackIndex, index, time, res);
287 return res == Status::OK ? MSERR_OK : MSERR_UNSUPPORT_FILE;
288 }
289
Reset()290 void AVMetadataHelperImpl::Reset()
291 {
292 if (metadataCollector_ != nullptr) {
293 metadataCollector_->Reset();
294 }
295
296 if (thumbnailGenerator_ != nullptr) {
297 thumbnailGenerator_->Reset();
298 }
299
300 if (mediaDemuxer_ != nullptr) {
301 mediaDemuxer_->Reset();
302 }
303
304 isForFrameConvert_ = false;
305 }
306
Destroy()307 void AVMetadataHelperImpl::Destroy()
308 {
309 if (metadataCollector_ != nullptr) {
310 metadataCollector_->Destroy();
311 }
312
313 if (thumbnailGenerator_ != nullptr) {
314 thumbnailGenerator_->Destroy();
315 }
316
317 metadataCollector_ = nullptr;
318 thumbnailGenerator_ = nullptr;
319 PipeLineThreadPool::GetInstance().DestroyThread(groupId_);
320 if (interruptMonitor_) {
321 interruptMonitor_->DeregisterListener(mediaDemuxer_);
322 }
323 MEDIA_LOGD("0x%{public}06" PRIXPTR " Finish Destroy.", FAKE_POINTER(this));
324 }
325
InitMetadataCollector()326 Status AVMetadataHelperImpl::InitMetadataCollector()
327 {
328 CHECK_AND_RETURN_RET_LOG(
329 mediaDemuxer_ != nullptr, Status::ERROR_INVALID_STATE, "mediaDemuxer_ is nullptr");
330 if (metadataCollector_ == nullptr) {
331 metadataCollector_ = std::make_shared<AVMetaDataCollector>(mediaDemuxer_);
332 }
333 CHECK_AND_RETURN_RET_LOG(
334 metadataCollector_ != nullptr, Status::ERROR_INVALID_STATE, "Init metadata collector failed.");
335 return Status::OK;
336 }
337
InitThumbnailGenerator()338 Status AVMetadataHelperImpl::InitThumbnailGenerator()
339 {
340 CHECK_AND_RETURN_RET_LOG(
341 mediaDemuxer_ != nullptr, Status::ERROR_INVALID_STATE, "mediaDemuxer_ is nullptr");
342 if (thumbnailGenerator_ == nullptr) {
343 thumbnailGenerator_ = std::make_shared<AVThumbnailGenerator>(mediaDemuxer_, appUid_, appPid_, appTokenId_, 0);
344 CHECK_AND_RETURN_RET_LOG(
345 thumbnailGenerator_ != nullptr, Status::ERROR_INVALID_STATE, "create thumbnail generator failed.");
346 auto res = thumbnailGenerator_->Init();
347 if (res != MSERR_OK) {
348 MEDIA_LOGI("Init thumbnail generator failed");
349 thumbnailGenerator_ = nullptr;
350 return Status::ERROR_INVALID_STATE;
351 }
352 thumbnailGenerator_->SetClientBundleName(appName_);
353 }
354 return Status::OK;
355 }
356
SetInterruptState(bool isInterruptNeeded)357 void AVMetadataHelperImpl::SetInterruptState(bool isInterruptNeeded)
358 {
359 MEDIA_LOGI("Metadata set interrupt state %{public}d", isInterruptNeeded);
360 isInterruptNeeded_ = isInterruptNeeded;
361 if (interruptMonitor_) {
362 interruptMonitor_->SetInterruptState(isInterruptNeeded);
363 }
364 }
365 } // namespace Media
366 } // namespace OHOS