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 
26 namespace {
27 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_METADATA, "AVMetadataHelperImpl" };
28 }
29 
30 namespace OHOS {
31 namespace Media {
OnError(MediaAVCodec::AVCodecErrorType errorType, int32_t errorCode)32 void AVMetadataHelperImpl::OnError(MediaAVCodec::AVCodecErrorType errorType, int32_t errorCode)
33 {
34     MEDIA_LOGE("OnError errorType:%{public}d, errorCode:%{public}d", static_cast<int32_t>(errorType), errorCode);
35     stopProcessing_ = true;
36 }
37 
AVMetadataHelperImpl()38 AVMetadataHelperImpl::AVMetadataHelperImpl()
39 {
40     MEDIA_LOGD("Constructor, instance: 0x%{public}06" PRIXPTR "", FAKE_POINTER(this));
41     groupId_ = std::string("AVMeta_") + std::to_string(OHOS::Media::Pipeline::Pipeline::GetNextPipelineId());
42 }
43 
~AVMetadataHelperImpl()44 AVMetadataHelperImpl::~AVMetadataHelperImpl()
45 {
46     MEDIA_LOGD("Destructor, instance: 0x%{public}06" PRIXPTR "", FAKE_POINTER(this));
47     Destroy();
48 }
49 
SetSource(const std::string &uri, int32_t )50 int32_t AVMetadataHelperImpl::SetSource(const std::string &uri, int32_t /* usage */)
51 {
52     UriHelper uriHelper(uri);
53     if (uriHelper.UriType() != UriHelper::URI_TYPE_FILE && uriHelper.UriType() != UriHelper::URI_TYPE_FD) {
54         MEDIA_LOGE("Unsupported uri type : %{private}s", uri.c_str());
55         return MSERR_UNSUPPORT;
56     }
57 
58     MEDIA_LOGD("0x%{public}06" PRIXPTR " SetSource uri: %{private}s, type:%{public}d", FAKE_POINTER(this), uri.c_str(),
59         uriHelper.UriType());
60 
61     auto ret = SetSourceInternel(uri);
62     CHECK_AND_RETURN_RET_LOG(ret == Status::OK, MSERR_INVALID_VAL,
63         "0x%{public}06" PRIXPTR " Failed to call SetSourceInternel", FAKE_POINTER(this));
64     CHECK_AND_RETURN_RET_LOG(MetaUtils::CheckFileType(mediaDemuxer_->GetGlobalMetaInfo()),
65         MSERR_UNSUPPORT, "0x%{public}06" PRIXPTR "SetSource unsupport", FAKE_POINTER(this));
66     return MSERR_OK;
67 }
68 
SetSource(const std::shared_ptr<IMediaDataSource> &dataSrc)69 int32_t AVMetadataHelperImpl::SetSource(const std::shared_ptr<IMediaDataSource> &dataSrc)
70 {
71     MEDIA_LOGI("0x%{public}06" PRIXPTR "SetSource dataSrc", FAKE_POINTER(this));
72     Status ret = SetSourceInternel(dataSrc);
73     CHECK_AND_RETURN_RET_LOG(ret == Status::OK, MSERR_INVALID_VAL, "Failed to call SetSourceInternel");
74 
75     CHECK_AND_RETURN_RET_LOG(MetaUtils::CheckFileType(mediaDemuxer_->GetGlobalMetaInfo()),
76         MSERR_UNSUPPORT, "0x%{public}06" PRIXPTR "SetSource unsupport", FAKE_POINTER(this));
77     MEDIA_LOGI("0x%{public}06" PRIXPTR "set source success", FAKE_POINTER(this));
78     return MSERR_OK;
79 }
80 
SetSourceInternel(const std::string &uri)81 Status AVMetadataHelperImpl::SetSourceInternel(const std::string &uri)
82 {
83     Reset();
84     mediaDemuxer_ = std::make_shared<MediaDemuxer>();
85     mediaDemuxer_->SetEnableOnlineFdCache(false);
86     mediaDemuxer_->SetInterruptState(isInterruptNeeded_.load());
87     mediaDemuxer_->SetPlayerId(groupId_);
88     CHECK_AND_RETURN_RET_LOG(
89         mediaDemuxer_ != nullptr, Status::ERROR_INVALID_DATA, "SetSourceInternel demuxer is nullptr");
90     Status ret = mediaDemuxer_->SetDataSource(std::make_shared<MediaSource>(uri));
91     CHECK_AND_RETURN_RET_LOG(ret == Status::OK, ret,
92         "0x%{public}06" PRIXPTR " SetSourceInternel demuxer failed to call SetDataSource", FAKE_POINTER(this));
93     return Status::OK;
94 }
95 
SetSourceInternel(const std::shared_ptr<IMediaDataSource> &dataSrc)96 Status AVMetadataHelperImpl::SetSourceInternel(const std::shared_ptr<IMediaDataSource> &dataSrc)
97 {
98     Reset();
99     mediaDemuxer_ = std::make_shared<MediaDemuxer>();
100     mediaDemuxer_->SetEnableOnlineFdCache(false);
101     mediaDemuxer_->SetPlayerId(groupId_);
102     CHECK_AND_RETURN_RET_LOG(
103         mediaDemuxer_ != nullptr, Status::ERROR_INVALID_DATA, "SetSourceInternel demuxer is nullptr");
104     Status ret = mediaDemuxer_->SetDataSource(std::make_shared<MediaSource>(dataSrc));
105     CHECK_AND_RETURN_RET_LOG(ret == Status::OK, ret, "Failed to call SetDataSource");
106     return Status::OK;
107 }
108 
ResolveMetadata(int32_t key)109 std::string AVMetadataHelperImpl::ResolveMetadata(int32_t key)
110 {
111     MEDIA_LOGI("enter ResolveMetadata with key: %{public}d", key);
112     auto res = InitMetadataCollector();
113     CHECK_AND_RETURN_RET(res == Status::OK, "");
114     return metadataCollector_->ExtractMetadata(key);
115 }
116 
ResolveMetadata()117 std::unordered_map<int32_t, std::string> AVMetadataHelperImpl::ResolveMetadata()
118 {
119     MEDIA_LOGD("enter ResolveMetadata");
120     auto res = InitMetadataCollector();
121     CHECK_AND_RETURN_RET(res == Status::OK, {});
122     return metadataCollector_->ExtractMetadata();
123 }
124 
FetchArtPicture()125 std::shared_ptr<AVSharedMemory> AVMetadataHelperImpl::FetchArtPicture()
126 {
127     MEDIA_LOGI("0x%{public}06" PRIXPTR " enter FetchArtPicture", FAKE_POINTER(this));
128     auto res = InitMetadataCollector();
129     CHECK_AND_RETURN_RET(res == Status::OK, nullptr);
130     return metadataCollector_->GetArtPicture();
131 }
132 
GetAVMetadata()133 std::shared_ptr<Meta> AVMetadataHelperImpl::GetAVMetadata()
134 {
135     MEDIA_LOGE("enter GetAVMetadata");
136     auto res = InitMetadataCollector();
137     CHECK_AND_RETURN_RET(res == Status::OK, nullptr);
138     return metadataCollector_->GetAVMetadata();
139 }
140 
FetchFrameAtTime( int64_t timeUs, int32_t option, const OutputConfiguration &param)141 std::shared_ptr<AVSharedMemory> AVMetadataHelperImpl::FetchFrameAtTime(
142     int64_t timeUs, int32_t option, const OutputConfiguration &param)
143 {
144     MEDIA_LOGD("enter FetchFrameAtTime");
145     auto res = InitThumbnailGenerator();
146     CHECK_AND_RETURN_RET(res == Status::OK, nullptr);
147     return thumbnailGenerator_->FetchFrameAtTime(timeUs, option, param);
148 }
149 
FetchFrameYuv( int64_t timeUs, int32_t option, const OutputConfiguration &param)150 std::shared_ptr<AVBuffer> AVMetadataHelperImpl::FetchFrameYuv(
151     int64_t timeUs, int32_t option, const OutputConfiguration &param)
152 {
153     MEDIA_LOGD("enter FetchFrameAtTime");
154     auto res = InitThumbnailGenerator();
155     CHECK_AND_RETURN_RET(res == Status::OK, nullptr);
156     return thumbnailGenerator_->FetchFrameYuv(timeUs, option, param);
157 }
158 
GetTimeByFrameIndex(uint32_t index, uint64_t &time)159 int32_t AVMetadataHelperImpl::GetTimeByFrameIndex(uint32_t index, uint64_t &time)
160 {
161     auto res = InitMetadataCollector();
162     CHECK_AND_RETURN_RET_LOG(res == Status::OK, MSERR_INVALID_STATE, "Create collector failed");
163     return metadataCollector_->GetTimeByFrameIndex(index, time);
164 }
165 
GetFrameIndexByTime(uint64_t time, uint32_t &index)166 int32_t AVMetadataHelperImpl::GetFrameIndexByTime(uint64_t time, uint32_t &index)
167 {
168     auto res = InitMetadataCollector();
169     CHECK_AND_RETURN_RET_LOG(res == Status::OK, MSERR_INVALID_STATE, "Create collector failed");
170     return metadataCollector_->GetFrameIndexByTime(time, index);
171 }
172 
Reset()173 void AVMetadataHelperImpl::Reset()
174 {
175     if (metadataCollector_ != nullptr) {
176         metadataCollector_->Reset();
177     }
178 
179     if (thumbnailGenerator_ != nullptr) {
180         thumbnailGenerator_->Reset();
181     }
182 
183     if (mediaDemuxer_ != nullptr) {
184         mediaDemuxer_->Reset();
185     }
186 }
187 
Destroy()188 void AVMetadataHelperImpl::Destroy()
189 {
190     if (metadataCollector_ != nullptr) {
191         metadataCollector_->Destroy();
192     }
193 
194     if (thumbnailGenerator_ != nullptr) {
195         thumbnailGenerator_->Destroy();
196     }
197 
198     metadataCollector_ = nullptr;
199     thumbnailGenerator_ = nullptr;
200     PipeLineThreadPool::GetInstance().DestroyThread(groupId_);
201     MEDIA_LOGD("0x%{public}06" PRIXPTR " Finish Destroy.", FAKE_POINTER(this));
202 }
203 
InitMetadataCollector()204 Status AVMetadataHelperImpl::InitMetadataCollector()
205 {
206     if (metadataCollector_ == nullptr) {
207         metadataCollector_ = std::make_shared<AVMetaDataCollector>(mediaDemuxer_);
208     }
209     CHECK_AND_RETURN_RET_LOG(
210         metadataCollector_ != nullptr, Status::ERROR_INVALID_STATE, "Init metadata collector failed.");
211     return Status::OK;
212 }
213 
InitThumbnailGenerator()214 Status AVMetadataHelperImpl::InitThumbnailGenerator()
215 {
216     if (thumbnailGenerator_ == nullptr) {
217         thumbnailGenerator_ = std::make_shared<AVThumbnailGenerator>(mediaDemuxer_);
218     }
219     CHECK_AND_RETURN_RET_LOG(
220         thumbnailGenerator_ != nullptr, Status::ERROR_INVALID_STATE, "Init thumbnail generator failed.");
221     return Status::OK;
222 }
223 
SetInterruptState(bool isInterruptNeeded)224 void AVMetadataHelperImpl::SetInterruptState(bool isInterruptNeeded)
225 {
226     MEDIA_LOGI("Metadata set interrupt state %{public}d", isInterruptNeeded);
227     isInterruptNeeded_ = isInterruptNeeded;
228     CHECK_AND_RETURN(mediaDemuxer_ != nullptr);
229     mediaDemuxer_->SetInterruptState(isInterruptNeeded);
230 }
231 }  // namespace Media
232 }  // namespace OHOS