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