• 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 "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 &param)
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 &param)
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