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 return (curConfig.GetFrameRate() >= MIN_FRAME_RATE || curConfig.GetFrameRate() <= MAX_FRAME_RATE ||
80 curConfig.GetWidth() >= MIN_VIDEO_WIDTH || curConfig.GetWidth() <= MAX_VIDEO_WIDTH ||
81 curConfig.GetHeight() >= MIN_VIDEO_HEIGHT || curConfig.GetHeight() <= MAX_VIDEO_HEIGHT);
82 }
83
InitDCameraPipEvent()84 void DCameraPipelineSource::InitDCameraPipEvent()
85 {
86 DHLOGD("Init source DCamera pipeline event to asynchronously process data.");
87 eventThread_ = std::thread([this]() { this->StartEventHandler(); });
88 std::unique_lock<std::mutex> lock(eventMutex_);
89 eventCon_.wait(lock, [this] {
90 return pipeEventHandler_ != nullptr;
91 });
92 }
93
StartEventHandler()94 void DCameraPipelineSource::StartEventHandler()
95 {
96 prctl(PR_SET_NAME, PIPELINE_SRC_EVENT.c_str());
97 auto runner = AppExecFwk::EventRunner::Create(false);
98 if (runner == nullptr) {
99 DHLOGE("Creat runner failed.");
100 return;
101 }
102 {
103 std::lock_guard<std::mutex> lock(eventMutex_);
104 pipeEventHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner);
105 }
106 eventCon_.notify_one();
107 runner->Run();
108 }
109
InitDCameraPipNodes(const VideoConfigParams & sourceConfig,const VideoConfigParams & targetConfig)110 int32_t DCameraPipelineSource::InitDCameraPipNodes(const VideoConfigParams& sourceConfig,
111 const VideoConfigParams& targetConfig)
112 {
113 DHLOGD("Init source DCamera pipeline Nodes.");
114 if (piplineType_ == PipelineType::PHOTO_JPEG) {
115 DHLOGE("JPEG data process is not supported.");
116 return DCAMERA_NOT_FOUND;
117 }
118 if (pipeEventHandler_ == nullptr) {
119 DHLOGE("eventBusSource is nullptr.");
120 return DCAMERA_BAD_VALUE;
121 }
122
123 pipNodeRanks_.push_back(std::make_shared<DecodeDataProcess>(pipeEventHandler_, shared_from_this()));
124 pipNodeRanks_.push_back(std::make_shared<ScaleConvertProcess>(shared_from_this()));
125 if (pipNodeRanks_.size() == 0) {
126 DHLOGD("Creating an empty source pipeline.");
127 pipelineHead_ = nullptr;
128 return DCAMERA_BAD_VALUE;
129 }
130
131 VideoConfigParams curNodeSourceCfg = sourceConfig;
132 for (size_t i = 0; i < pipNodeRanks_.size(); i++) {
133 CHECK_AND_RETURN_RET_LOG((pipNodeRanks_[i] == nullptr), DCAMERA_BAD_VALUE, "Node is null.");
134 pipNodeRanks_[i]->SetNodeRank(i);
135 DHLOGI("DCameraPipelineSource::InitDCameraPipNodes Node %{public}zu Source Config: width %{public}d height "
136 "%{public}d format %{public}d codecType %{public}d frameRate %{public}d", i, curNodeSourceCfg.GetWidth(),
137 curNodeSourceCfg.GetHeight(), curNodeSourceCfg.GetVideoformat(), curNodeSourceCfg.GetVideoCodecType(),
138 curNodeSourceCfg.GetFrameRate());
139
140 VideoConfigParams curNodeProcessedCfg;
141 int32_t err = pipNodeRanks_[i]->InitNode(curNodeSourceCfg, targetConfig, curNodeProcessedCfg);
142 if (err != DCAMERA_OK) {
143 DHLOGE("Init source DCamera pipeline Node [%{public}zu] failed.", i);
144 return DCAMERA_INIT_ERR;
145 }
146 curNodeSourceCfg = curNodeProcessedCfg;
147
148 if (i == 0) {
149 continue;
150 }
151
152 err = pipNodeRanks_[i - 1]->SetNextNode(pipNodeRanks_[i]);
153 if (err != DCAMERA_OK) {
154 DHLOGE("Set the next node of Node [%{public}zu] failed in source pipeline.", i - 1);
155 return DCAMERA_INIT_ERR;
156 }
157 }
158 DHLOGD("All nodes have been linked in source pipeline, Target Config: "
159 "width %{public}d height %{public}d format %{public}d codecType %{public}d frameRate %{public}d",
160 targetConfig.GetWidth(), targetConfig.GetHeight(),
161 targetConfig.GetVideoformat(), targetConfig.GetVideoCodecType(), targetConfig.GetFrameRate());
162 pipelineHead_ = pipNodeRanks_[0];
163 return DCAMERA_OK;
164 }
165
ProcessData(std::vector<std::shared_ptr<DataBuffer>> & dataBuffers)166 int32_t DCameraPipelineSource::ProcessData(std::vector<std::shared_ptr<DataBuffer>>& dataBuffers)
167 {
168 DHLOGD("Process data buffers in source pipeline.");
169 if (piplineType_ == PipelineType::PHOTO_JPEG) {
170 DHLOGE("JPEG data process is not supported in source pipeline.");
171 return DCAMERA_NOT_FOUND;
172 }
173 if (pipelineHead_ == nullptr) {
174 DHLOGE("The current source pipeline node is empty. Processing failed.");
175 return DCAMERA_INIT_ERR;
176 }
177 if (dataBuffers.empty()) {
178 DHLOGE("Source Pipeline Input data buffers is empty.");
179 return DCAMERA_BAD_VALUE;
180 }
181 if (!isProcess_) {
182 DHLOGE("Source Pipeline node occurred error or start destroy.");
183 return DCAMERA_DISABLE_PROCESS;
184 }
185
186 DHLOGD("Send asynchronous event to process data in source pipeline.");
187 std::shared_ptr<PipelineConfig> pipConfigSource = std::make_shared<PipelineConfig>(piplineType_,
188 PIPELINE_OWNER, dataBuffers);
189 std::vector<std::shared_ptr<DataBuffer>> inputBuffers = pipConfigSource->GetDataBuffers();
190 if (inputBuffers.empty()) {
191 DHLOGE("Receiving process data buffers is empty in source pipeline.");
192 OnError(ERROR_PIPELINE_EVENTBUS);
193 return DCAMERA_BAD_VALUE;
194 }
195 auto sendFunc = [this, inputBuffers]() mutable {
196 int32_t ret = pipelineHead_->ProcessData(inputBuffers);
197 DHLOGD("excute ProcessData ret %{public}d.", ret);
198 };
199 CHECK_AND_RETURN_RET_LOG(pipeEventHandler_ == nullptr, DCAMERA_BAD_VALUE, "pipeEventHandler_ is nullptr.");
200 pipeEventHandler_->PostTask(sendFunc);
201 return DCAMERA_OK;
202 }
203
DestroyDataProcessPipeline()204 void DCameraPipelineSource::DestroyDataProcessPipeline()
205 {
206 DCAMERA_SYNC_TRACE(DCAMERA_SOURCE_DESTORY_PIPELINE);
207 DHLOGD("Destroy source data process pipeline start.");
208 isProcess_ = false;
209 if (pipelineHead_ != nullptr) {
210 pipelineHead_->ReleaseProcessNode();
211 pipelineHead_ = nullptr;
212 }
213 if ((pipeEventHandler_ != nullptr) && (pipeEventHandler_->GetEventRunner() != nullptr)) {
214 pipeEventHandler_->GetEventRunner()->Stop();
215 eventThread_.join();
216 }
217 pipeEventHandler_ = nullptr;
218 processListener_ = nullptr;
219 pipNodeRanks_.clear();
220 piplineType_ = PipelineType::VIDEO;
221 DHLOGD("Destroy source data process pipeline end.");
222 }
223
OnError(DataProcessErrorType errorType)224 void DCameraPipelineSource::OnError(DataProcessErrorType errorType)
225 {
226 DHLOGE("A runtime error occurred in the source pipeline.");
227 isProcess_ = false;
228 if (processListener_ == nullptr) {
229 DHLOGE("The process listener of source pipeline is empty.");
230 return;
231 }
232 processListener_->OnError(errorType);
233 }
234
OnProcessedVideoBuffer(const std::shared_ptr<DataBuffer> & videoResult)235 void DCameraPipelineSource::OnProcessedVideoBuffer(const std::shared_ptr<DataBuffer>& videoResult)
236 {
237 DHLOGD("Source pipeline output the processed video buffer.");
238 if (processListener_ == nullptr) {
239 DHLOGE("The process listener of source pipeline is empty.");
240 return;
241 }
242 processListener_->OnProcessedVideoBuffer(videoResult);
243 }
244
GetProperty(const std::string & propertyName,PropertyCarrier & propertyCarrier)245 int32_t DCameraPipelineSource::GetProperty(const std::string& propertyName, PropertyCarrier& propertyCarrier)
246 {
247 return DCAMERA_OK;
248 }
249 } // namespace DistributedHardware
250 } // namespace OHOS
251