1 /*
2 * Copyright (c) 2021-2024 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 "dcamera_pipeline_source.h"
17
18 #include "dcamera_hitrace_adapter.h"
19 #include "distributed_hardware_log.h"
20 #include "distributed_camera_constants.h"
21 #include "decode_data_process.h"
22 #include "fps_controller_process.h"
23 #include "scale_convert_process.h"
24 #include <sys/prctl.h>
25
26 namespace OHOS {
27 namespace DistributedHardware {
28 const std::string DCameraPipelineSource::PIPELINE_OWNER = "Source";
29
~DCameraPipelineSource()30 DCameraPipelineSource::~DCameraPipelineSource()
31 {
32 if (isProcess_) {
33 DHLOGD("~DCameraPipelineSource : Destroy source data process pipeline.");
34 DestroyDataProcessPipeline();
35 }
36 }
37
CreateDataProcessPipeline(PipelineType piplineType,const VideoConfigParams & sourceConfig,const VideoConfigParams & targetConfig,const std::shared_ptr<DataProcessListener> & listener)38 int32_t DCameraPipelineSource::CreateDataProcessPipeline(PipelineType piplineType,
39 const VideoConfigParams& sourceConfig, const VideoConfigParams& targetConfig,
40 const std::shared_ptr<DataProcessListener>& listener)
41 {
42 DCAMERA_SYNC_TRACE(DCAMERA_SOURCE_CREATE_PIPELINE);
43 DHLOGD("Create source data process pipeline.");
44 switch (piplineType) {
45 case PipelineType::VIDEO:
46 if (!(IsInRange(sourceConfig) && IsInRange(targetConfig))) {
47 DHLOGE("Source config or target config of source pipeline are invalid.");
48 return DCAMERA_BAD_VALUE;
49 }
50 break;
51 default:
52 DHLOGE("JPEG or other pipeline type are not supported in source pipeline.");
53 return DCAMERA_NOT_FOUND;
54 }
55 if (listener == nullptr) {
56 DHLOGE("The process listener of source pipeline is empty.");
57 return DCAMERA_BAD_VALUE;
58 }
59
60 if (pipelineHead_ != nullptr) {
61 DHLOGD("The source pipeline already exists.");
62 return DCAMERA_OK;
63 }
64
65 InitDCameraPipEvent();
66 int32_t err = InitDCameraPipNodes(sourceConfig, targetConfig);
67 if (err != DCAMERA_OK) {
68 DestroyDataProcessPipeline();
69 return err;
70 }
71 piplineType_ = piplineType;
72 processListener_ = listener;
73 isProcess_ = true;
74 return DCAMERA_OK;
75 }
76
IsInRange(const VideoConfigParams & curConfig)77 bool DCameraPipelineSource::IsInRange(const VideoConfigParams& curConfig)
78 {
79 bool isWidthValid = (curConfig.GetWidth() >= MIN_VIDEO_WIDTH && curConfig.GetWidth() <= MAX_VIDEO_WIDTH);
80 bool isHeightValid = (curConfig.GetHeight() >= MIN_VIDEO_HEIGHT && curConfig.GetHeight() <= MAX_VIDEO_HEIGHT);
81 bool isFrameRateValid = (curConfig.GetFrameRate() >= MIN_FRAME_RATE && curConfig.GetFrameRate() <= MAX_FRAME_RATE);
82 return isWidthValid && isHeightValid && isFrameRateValid;
83 }
84
InitDCameraPipEvent()85 void DCameraPipelineSource::InitDCameraPipEvent()
86 {
87 DHLOGD("Init source DCamera pipeline event to asynchronously process data.");
88 eventThread_ = std::thread([this]() { this->StartEventHandler(); });
89 std::unique_lock<std::mutex> lock(eventMutex_);
90 eventCon_.wait(lock, [this] {
91 return pipeEventHandler_ != nullptr;
92 });
93 }
94
StartEventHandler()95 void DCameraPipelineSource::StartEventHandler()
96 {
97 prctl(PR_SET_NAME, PIPELINE_SRC_EVENT.c_str());
98 auto runner = AppExecFwk::EventRunner::Create(false);
99 if (runner == nullptr) {
100 DHLOGE("Creat runner failed.");
101 return;
102 }
103 {
104 std::lock_guard<std::mutex> lock(eventMutex_);
105 pipeEventHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner);
106 }
107 eventCon_.notify_one();
108 runner->Run();
109 }
110
InitDCameraPipNodes(const VideoConfigParams & sourceConfig,const VideoConfigParams & targetConfig)111 int32_t DCameraPipelineSource::InitDCameraPipNodes(const VideoConfigParams& sourceConfig,
112 const VideoConfigParams& targetConfig)
113 {
114 DHLOGD("Init source DCamera pipeline Nodes.");
115 if (piplineType_ == PipelineType::PHOTO_JPEG) {
116 DHLOGE("JPEG data process is not supported.");
117 return DCAMERA_NOT_FOUND;
118 }
119 if (pipeEventHandler_ == nullptr) {
120 DHLOGE("eventBusSource is nullptr.");
121 return DCAMERA_BAD_VALUE;
122 }
123
124 pipNodeRanks_.push_back(std::make_shared<DecodeDataProcess>(pipeEventHandler_, shared_from_this()));
125 pipNodeRanks_.push_back(std::make_shared<ScaleConvertProcess>(shared_from_this()));
126 if (pipNodeRanks_.size() == 0) {
127 DHLOGD("Creating an empty source pipeline.");
128 pipelineHead_ = nullptr;
129 return DCAMERA_BAD_VALUE;
130 }
131
132 VideoConfigParams curNodeSourceCfg = sourceConfig;
133 for (size_t i = 0; i < pipNodeRanks_.size(); i++) {
134 CHECK_AND_RETURN_RET_LOG((pipNodeRanks_[i] == nullptr), DCAMERA_BAD_VALUE, "Node is null.");
135 pipNodeRanks_[i]->SetNodeRank(i);
136 DHLOGI("DCameraPipelineSource::InitDCameraPipNodes Node %{public}zu Source Config: width %{public}d height "
137 "%{public}d format %{public}d codecType %{public}d frameRate %{public}d", i, curNodeSourceCfg.GetWidth(),
138 curNodeSourceCfg.GetHeight(), curNodeSourceCfg.GetVideoformat(), curNodeSourceCfg.GetVideoCodecType(),
139 curNodeSourceCfg.GetFrameRate());
140
141 VideoConfigParams curNodeProcessedCfg;
142 int32_t err = pipNodeRanks_[i]->InitNode(curNodeSourceCfg, targetConfig, curNodeProcessedCfg);
143 if (err != DCAMERA_OK) {
144 DHLOGE("Init source DCamera pipeline Node [%{public}zu] failed.", i);
145 return DCAMERA_INIT_ERR;
146 }
147 curNodeSourceCfg = curNodeProcessedCfg;
148
149 if (i == 0) {
150 continue;
151 }
152
153 err = pipNodeRanks_[i - 1]->SetNextNode(pipNodeRanks_[i]);
154 if (err != DCAMERA_OK) {
155 DHLOGE("Set the next node of Node [%{public}zu] failed in source pipeline.", i - 1);
156 return DCAMERA_INIT_ERR;
157 }
158 }
159 DHLOGD("All nodes have been linked in source pipeline, Target Config: "
160 "width %{public}d height %{public}d format %{public}d codecType %{public}d frameRate %{public}d",
161 targetConfig.GetWidth(), targetConfig.GetHeight(),
162 targetConfig.GetVideoformat(), targetConfig.GetVideoCodecType(), targetConfig.GetFrameRate());
163 pipelineHead_ = pipNodeRanks_[0];
164 return DCAMERA_OK;
165 }
166
ProcessData(std::vector<std::shared_ptr<DataBuffer>> & dataBuffers)167 int32_t DCameraPipelineSource::ProcessData(std::vector<std::shared_ptr<DataBuffer>>& dataBuffers)
168 {
169 DHLOGD("Process data buffers in source pipeline.");
170 if (piplineType_ == PipelineType::PHOTO_JPEG) {
171 DHLOGE("JPEG data process is not supported in source pipeline.");
172 return DCAMERA_NOT_FOUND;
173 }
174 if (pipelineHead_ == nullptr) {
175 DHLOGE("The current source pipeline node is empty. Processing failed.");
176 return DCAMERA_INIT_ERR;
177 }
178 if (dataBuffers.empty()) {
179 DHLOGE("Source Pipeline Input data buffers is empty.");
180 return DCAMERA_BAD_VALUE;
181 }
182 if (!isProcess_) {
183 DHLOGE("Source Pipeline node occurred error or start destroy.");
184 return DCAMERA_DISABLE_PROCESS;
185 }
186
187 DHLOGD("Send asynchronous event to process data in source pipeline.");
188 std::shared_ptr<PipelineConfig> pipConfigSource = std::make_shared<PipelineConfig>(piplineType_,
189 PIPELINE_OWNER, dataBuffers);
190 std::vector<std::shared_ptr<DataBuffer>> inputBuffers = pipConfigSource->GetDataBuffers();
191 if (inputBuffers.empty()) {
192 DHLOGE("Receiving process data buffers is empty in source pipeline.");
193 OnError(ERROR_PIPELINE_EVENTBUS);
194 return DCAMERA_BAD_VALUE;
195 }
196 auto sendFunc = [this, inputBuffers]() mutable {
197 int32_t ret = pipelineHead_->ProcessData(inputBuffers);
198 DHLOGD("excute ProcessData ret %{public}d.", ret);
199 };
200 CHECK_AND_RETURN_RET_LOG(pipeEventHandler_ == nullptr, DCAMERA_BAD_VALUE, "pipeEventHandler_ is nullptr.");
201 pipeEventHandler_->PostTask(sendFunc);
202 return DCAMERA_OK;
203 }
204
DestroyDataProcessPipeline()205 void DCameraPipelineSource::DestroyDataProcessPipeline()
206 {
207 DCAMERA_SYNC_TRACE(DCAMERA_SOURCE_DESTORY_PIPELINE);
208 DHLOGD("Destroy source data process pipeline start.");
209 isProcess_ = false;
210 if (pipelineHead_ != nullptr) {
211 pipelineHead_->ReleaseProcessNode();
212 pipelineHead_ = nullptr;
213 }
214 if ((pipeEventHandler_ != nullptr) && (pipeEventHandler_->GetEventRunner() != nullptr)) {
215 pipeEventHandler_->GetEventRunner()->Stop();
216 eventThread_.join();
217 }
218 pipeEventHandler_ = nullptr;
219 processListener_ = nullptr;
220 pipNodeRanks_.clear();
221 piplineType_ = PipelineType::VIDEO;
222 DHLOGD("Destroy source data process pipeline end.");
223 }
224
OnError(DataProcessErrorType errorType)225 void DCameraPipelineSource::OnError(DataProcessErrorType errorType)
226 {
227 DHLOGE("A runtime error occurred in the source pipeline.");
228 isProcess_ = false;
229 if (processListener_ == nullptr) {
230 DHLOGE("The process listener of source pipeline is empty.");
231 return;
232 }
233 processListener_->OnError(errorType);
234 }
235
OnProcessedVideoBuffer(const std::shared_ptr<DataBuffer> & videoResult)236 void DCameraPipelineSource::OnProcessedVideoBuffer(const std::shared_ptr<DataBuffer>& videoResult)
237 {
238 DHLOGD("Source pipeline output the processed video buffer.");
239 if (processListener_ == nullptr) {
240 DHLOGE("The process listener of source pipeline is empty.");
241 return;
242 }
243 processListener_->OnProcessedVideoBuffer(videoResult);
244 }
245
GetProperty(const std::string & propertyName,PropertyCarrier & propertyCarrier)246 int32_t DCameraPipelineSource::GetProperty(const std::string& propertyName, PropertyCarrier& propertyCarrier)
247 {
248 return DCAMERA_OK;
249 }
250 } // namespace DistributedHardware
251 } // namespace OHOS
252