• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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