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