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