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 "pipeline/pipeline.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 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
SetSource(const std::shared_ptr<IMediaDataSource> & dataSrc)77 int32_t AVMetadataHelperImpl::SetSource(const std::shared_ptr<IMediaDataSource> &dataSrc)
78 {
79 MEDIA_LOGI("0x%{public}06" PRIXPTR "SetSource dataSrc", FAKE_POINTER(this));
80 Status ret = SetSourceInternel(dataSrc);
81 CHECK_AND_RETURN_RET_LOG(ret == Status::OK, MSERR_INVALID_VAL, "Failed to call SetSourceInternel");
82
83 CHECK_AND_RETURN_RET_LOG(MetaUtils::CheckFileType(mediaDemuxer_->GetGlobalMetaInfo()),
84 MSERR_UNSUPPORT, "0x%{public}06" PRIXPTR "SetSource unsupport", FAKE_POINTER(this));
85 MEDIA_LOGI("0x%{public}06" PRIXPTR "set source success", FAKE_POINTER(this));
86 return MSERR_OK;
87 }
88
SetSourceInternel(const std::string & uri,bool isForFrameConvert)89 Status AVMetadataHelperImpl::SetSourceInternel(const std::string &uri, bool isForFrameConvert)
90 {
91 CHECK_AND_RETURN_RET_LOG(!isForFrameConvert, SetSourceForFrameConvert(uri), "SetSource for frame convert");
92 Reset();
93 mediaDemuxer_ = std::make_shared<MediaDemuxer>();
94 mediaDemuxer_->SetEnableOnlineFdCache(false);
95 mediaDemuxer_->SetPlayerId(groupId_);
96 CHECK_AND_RETURN_RET_LOG(
97 mediaDemuxer_ != nullptr, Status::ERROR_INVALID_DATA, "SetSourceInternel demuxer is nullptr");
98 if (interruptMonitor_) {
99 interruptMonitor_->RegisterListener(mediaDemuxer_);
100 interruptMonitor_->SetInterruptState(isInterruptNeeded_.load());
101 }
102 Status ret = mediaDemuxer_->SetDataSource(std::make_shared<MediaSource>(uri));
103 CHECK_AND_RETURN_RET_LOG(ret == Status::OK, ret,
104 "0x%{public}06" PRIXPTR " SetSourceInternel demuxer failed to call SetDataSource", FAKE_POINTER(this));
105 return Status::OK;
106 }
107
SetSourceForFrameConvert(const std::string & uri)108 Status AVMetadataHelperImpl::SetSourceForFrameConvert(const std::string &uri)
109 {
110 Reset();
111 isForFrameConvert_ = true;
112 conversion_ = std::make_shared<TimeAndIndexConversion>();
113 CHECK_AND_RETURN_RET_LOG(
114 conversion_ != nullptr, Status::ERROR_NO_MEMORY, "SetSourceInternel conversion_ is nullptr");
115 Status ret = conversion_->SetDataSource(std::make_shared<MediaSource>(uri));
116 CHECK_AND_RETURN_RET_LOG(ret == Status::OK, ret,
117 "0x%{public}06" PRIXPTR " SetSourceInternel conversion_ failed", FAKE_POINTER(this));
118 return Status::OK;
119 }
120
SetSourceInternel(const std::shared_ptr<IMediaDataSource> & dataSrc)121 Status AVMetadataHelperImpl::SetSourceInternel(const std::shared_ptr<IMediaDataSource> &dataSrc)
122 {
123 Reset();
124 mediaDemuxer_ = std::make_shared<MediaDemuxer>();
125 mediaDemuxer_->SetPlayerId(groupId_);
126 CHECK_AND_RETURN_RET_LOG(
127 mediaDemuxer_ != nullptr, Status::ERROR_INVALID_DATA, "SetSourceInternel demuxer is nullptr");
128 if (interruptMonitor_) {
129 interruptMonitor_->RegisterListener(mediaDemuxer_);
130 }
131 Status ret = mediaDemuxer_->SetDataSource(std::make_shared<MediaSource>(dataSrc));
132 CHECK_AND_RETURN_RET_LOG(ret == Status::OK, ret, "Failed to call SetDataSource");
133 return Status::OK;
134 }
135
ResolveMetadata(int32_t key)136 std::string AVMetadataHelperImpl::ResolveMetadata(int32_t key)
137 {
138 MEDIA_LOGI("enter ResolveMetadata with key: %{public}d", key);
139 auto res = InitMetadataCollector();
140 CHECK_AND_RETURN_RET(res == Status::OK, "");
141 return metadataCollector_->ExtractMetadata(key);
142 }
143
ResolveMetadata()144 std::unordered_map<int32_t, std::string> AVMetadataHelperImpl::ResolveMetadata()
145 {
146 MEDIA_LOGD("enter ResolveMetadata");
147 auto res = InitMetadataCollector();
148 CHECK_AND_RETURN_RET(res == Status::OK, {});
149 return metadataCollector_->ExtractMetadata();
150 }
151
FetchArtPicture()152 std::shared_ptr<AVSharedMemory> AVMetadataHelperImpl::FetchArtPicture()
153 {
154 MEDIA_LOGI("0x%{public}06" PRIXPTR " enter FetchArtPicture", FAKE_POINTER(this));
155 auto res = InitMetadataCollector();
156 CHECK_AND_RETURN_RET(res == Status::OK, nullptr);
157 return metadataCollector_->GetArtPicture();
158 }
159
GetAVMetadata()160 std::shared_ptr<Meta> AVMetadataHelperImpl::GetAVMetadata()
161 {
162 MEDIA_LOGE("enter GetAVMetadata");
163 auto res = InitMetadataCollector();
164 CHECK_AND_RETURN_RET(res == Status::OK, nullptr);
165 return metadataCollector_->GetAVMetadata();
166 }
167
FetchFrameAtTime(int64_t timeUs,int32_t option,const OutputConfiguration & param)168 std::shared_ptr<AVSharedMemory> AVMetadataHelperImpl::FetchFrameAtTime(
169 int64_t timeUs, int32_t option, const OutputConfiguration ¶m)
170 {
171 MEDIA_LOGD("enter FetchFrameAtTime");
172 auto res = InitThumbnailGenerator();
173 CHECK_AND_RETURN_RET(res == Status::OK, nullptr);
174 return thumbnailGenerator_->FetchFrameAtTime(timeUs, option, param);
175 }
176
GetTimeByFrameIndex(uint32_t index,uint64_t & time)177 int32_t AVMetadataHelperImpl::GetTimeByFrameIndex(uint32_t index, uint64_t &time)
178 {
179 CHECK_AND_RETURN_RET(!isForFrameConvert_, GetTimeForFrameConvert(index, time));
180 auto res = InitMetadataCollector();
181 CHECK_AND_RETURN_RET_LOG(res == Status::OK, MSERR_INVALID_STATE, "Create collector failed");
182 return metadataCollector_->GetTimeByFrameIndex(index, time);
183 }
184
GetFrameIndexByTime(uint64_t time,uint32_t & index)185 int32_t AVMetadataHelperImpl::GetFrameIndexByTime(uint64_t time, uint32_t &index)
186 {
187 CHECK_AND_RETURN_RET(!isForFrameConvert_, GetIndexForFrameConvert(time, index));
188 auto res = InitMetadataCollector();
189 CHECK_AND_RETURN_RET_LOG(res == Status::OK, MSERR_INVALID_STATE, "Create collector failed");
190 return metadataCollector_->GetFrameIndexByTime(time, index);
191 }
192
GetTimeForFrameConvert(uint32_t index,uint64_t & time)193 int32_t AVMetadataHelperImpl::GetTimeForFrameConvert(uint32_t index, uint64_t &time)
194 {
195 CHECK_AND_RETURN_RET_LOG(conversion_ != nullptr, MSERR_INVALID_STATE, "conversion_ is nullptr");
196 uint32_t trackIndex = 0;
197 auto res = conversion_->GetFirstVideoTrackIndex(trackIndex);
198 CHECK_AND_RETURN_RET_LOG(res == Status::OK, MSERR_UNSUPPORT_FILE, "GetFirstVideoTrackIndex failed");
199 res = conversion_->GetRelativePresentationTimeUsByIndex(trackIndex, index, time);
200 MEDIA_LOGI("trackIndex: %{public}" PRIu32 ", index: %{public}" PRIu32 ", time: %{public}" PRIu64
201 ", res: %{public}d", trackIndex, index, time, res);
202 return res == Status::OK ? MSERR_OK : MSERR_UNSUPPORT_FILE;
203 }
204
GetIndexForFrameConvert(uint64_t time,uint32_t & index)205 int32_t AVMetadataHelperImpl::GetIndexForFrameConvert(uint64_t time, uint32_t &index)
206 {
207 CHECK_AND_RETURN_RET_LOG(conversion_ != nullptr, MSERR_INVALID_STATE, "conversion_ is nullptr");
208 uint32_t trackIndex = 0;
209 auto res = conversion_->GetFirstVideoTrackIndex(trackIndex);
210 CHECK_AND_RETURN_RET_LOG(res == Status::OK, MSERR_UNSUPPORT_FILE, "GetFirstVideoTrackIndex failed");
211 res = conversion_->GetIndexByRelativePresentationTimeUs(trackIndex, time, index);
212 MEDIA_LOGI("trackIndex: %{public}" PRIu32 ", index: %{public}" PRIu32 ", time: %{public}" PRIu64
213 ", res: %{public}d", trackIndex, index, time, res);
214 return res == Status::OK ? MSERR_OK : MSERR_UNSUPPORT_FILE;
215 }
216
FetchFrameYuv(int64_t timeUs,int32_t option,const OutputConfiguration & param)217 std::shared_ptr<AVBuffer> AVMetadataHelperImpl::FetchFrameYuv(
218 int64_t timeUs, int32_t option, const OutputConfiguration ¶m)
219 {
220 MEDIA_LOGD("enter FetchFrameAtTime");
221 auto res = InitThumbnailGenerator();
222 CHECK_AND_RETURN_RET(res == Status::OK, nullptr);
223 return thumbnailGenerator_->FetchFrameYuv(timeUs, option, param);
224 }
225
Reset()226 void AVMetadataHelperImpl::Reset()
227 {
228 if (metadataCollector_ != nullptr) {
229 metadataCollector_->Reset();
230 }
231
232 if (thumbnailGenerator_ != nullptr) {
233 thumbnailGenerator_->Reset();
234 }
235
236 if (mediaDemuxer_ != nullptr) {
237 mediaDemuxer_->Reset();
238 }
239
240 isForFrameConvert_ = false;
241 }
242
Destroy()243 void AVMetadataHelperImpl::Destroy()
244 {
245 if (metadataCollector_ != nullptr) {
246 metadataCollector_->Destroy();
247 }
248
249 if (thumbnailGenerator_ != nullptr) {
250 thumbnailGenerator_->Destroy();
251 }
252
253 metadataCollector_ = nullptr;
254 thumbnailGenerator_ = nullptr;
255 PipeLineThreadPool::GetInstance().DestroyThread(groupId_);
256 if (interruptMonitor_) {
257 interruptMonitor_->DeregisterListener(mediaDemuxer_);
258 }
259 MEDIA_LOGD("0x%{public}06" PRIXPTR " Finish Destroy.", FAKE_POINTER(this));
260 }
261
InitMetadataCollector()262 Status AVMetadataHelperImpl::InitMetadataCollector()
263 {
264 CHECK_AND_RETURN_RET_LOG(
265 mediaDemuxer_ != nullptr, Status::ERROR_INVALID_STATE, "mediaDemuxer_ is nullptr");
266 if (metadataCollector_ == nullptr) {
267 metadataCollector_ = std::make_shared<AVMetaDataCollector>(mediaDemuxer_);
268 }
269 CHECK_AND_RETURN_RET_LOG(
270 metadataCollector_ != nullptr, Status::ERROR_INVALID_STATE, "Init metadata collector failed.");
271 return Status::OK;
272 }
273
InitThumbnailGenerator()274 Status AVMetadataHelperImpl::InitThumbnailGenerator()
275 {
276 CHECK_AND_RETURN_RET_LOG(
277 mediaDemuxer_ != nullptr, Status::ERROR_INVALID_STATE, "mediaDemuxer_ is nullptr");
278 if (thumbnailGenerator_ == nullptr) {
279 thumbnailGenerator_ = std::make_shared<AVThumbnailGenerator>(mediaDemuxer_);
280 CHECK_AND_RETURN_RET_LOG(
281 thumbnailGenerator_ != nullptr, Status::ERROR_INVALID_STATE, "create thumbnail generator failed.");
282 auto res = thumbnailGenerator_->Init();
283 if (res != MSERR_OK) {
284 MEDIA_LOGI("Init thumbnail generator failed");
285 thumbnailGenerator_ = nullptr;
286 return Status::ERROR_INVALID_STATE;
287 }
288 }
289 return Status::OK;
290 }
291
SetInterruptState(bool isInterruptNeeded)292 void AVMetadataHelperImpl::SetInterruptState(bool isInterruptNeeded)
293 {
294 MEDIA_LOGI("Metadata set interrupt state %{public}d", isInterruptNeeded);
295 isInterruptNeeded_ = isInterruptNeeded;
296 if (interruptMonitor_) {
297 interruptMonitor_->SetInterruptState(isInterruptNeeded);
298 }
299 }
300 } // namespace Media
301 } // namespace OHOS