1 /*
2 * Copyright (c) 2021 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 * http://www.apache.org/licenses/LICENSE-2.0
7 * Unless required by applicable law or agreed to in writing, software
8 * distributed under the License is distributed on an "AS IS" BASIS,
9 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 * See the License for the specific language governing permissions and
11 * limitations under the License.
12 */
13
14 #include "buffer_manager.h"
15 #include "stream_pipeline_strategy.h"
16
17 namespace OHOS::Camera {
StreamPipelineStrategy(const std::shared_ptr<HostStreamMgr> & streamMgr,const std::shared_ptr<PipelineSpec> & spec)18 StreamPipelineStrategy::StreamPipelineStrategy(const std::shared_ptr<HostStreamMgr>& streamMgr,
19 const std::shared_ptr<PipelineSpec>& spec) : hostStreamMgr_(streamMgr), pipelineSpec_(spec)
20 {
21 }
22
GeneratePipelineSpec(const int32_t & mode)23 std::shared_ptr<PipelineSpec> StreamPipelineStrategy::GeneratePipelineSpec(const int32_t& mode)
24 {
25 PipelineSpec pipe {};
26 if (SelectPipelineSpec(mode, pipe) != RC_OK) {
27 return nullptr;
28 }
29 if (CombineSpecs(pipe) != RC_OK) {
30 return nullptr;
31 }
32 return pipelineSpec_;
33 }
34
ConstructKeyStrIndex(const int32_t & mode)35 std::string StreamPipelineStrategy::ConstructKeyStrIndex(const int32_t& mode)
36 {
37 std::string keyStr;
38 std::string sceneStr = CheckIdExsit(mode, G_SCENE_TABLE_PTR, G_SCENE_TABLE_SIZE);
39 if (sceneStr.empty()) {
40 CAMERA_LOGE("scene:%{public}d not supported!\n", mode);
41 return keyStr;
42 }
43 keyStr += sceneStr;
44 std::vector<int32_t> streamTypeSet;
45 hostStreamMgr_->GetStreamTypes(streamTypeSet);
46 for (const auto& it : streamTypeSet) {
47 std::string streamStr = CheckIdExsit(it, G_STREAM_TABLE_PTR, G_STREAM_TABLE_SIZE);
48 if (streamStr.empty()) {
49 CAMERA_LOGI("stream type:%{public}d not support!\n", it);
50 }
51 keyStr += "_" + streamStr;
52 }
53 return keyStr;
54 }
55
SetUpBasicOutPortFormat(const PipelineSpec & pipe,const PortInfo & info,PortFormat & format)56 RetCode StreamPipelineStrategy::SetUpBasicOutPortFormat(const PipelineSpec& pipe,
57 const PortInfo& info, PortFormat& format)
58 {
59 auto peerNode = std::find_if(pipe.nodeSpecSet_.begin(), pipe.nodeSpecSet_.end(),
60 [info](const NodeSpec& n) {
61 return info.peerPortNodeName_ == n.name_;
62 });
63 if (peerNode == pipe.nodeSpecSet_.end()) {
64 CAMERA_LOGI("config fail! node name:%{public}s not next node", info.peerPortNodeName_.c_str());
65 return RC_ERROR;
66 }
67 auto peerPort = std::find_if(peerNode->portSpecSet_.begin(), peerNode->portSpecSet_.end(),
68 [info] (const PortSpec& p) {
69 return info.peerPortName_ == p.info_.name_;
70 });
71 if (peerPort == peerNode->portSpecSet_.end()) {
72 CAMERA_LOGI("config fail! port name:%{public}s not exist", info.name_.c_str());
73 return RC_ERROR;
74 }
75
76 format = peerPort->format_;
77 return RC_OK;
78 }
79
SetUpBasicInPortFormat(const NodeSpec & nodeSpec,PortFormat & format)80 RetCode StreamPipelineStrategy::SetUpBasicInPortFormat(const NodeSpec& nodeSpec, PortFormat& format)
81 {
82 auto outPort = std::find_if(nodeSpec.portSpecSet_.begin(), nodeSpec.portSpecSet_.end(),
83 [] (const PortSpec& p) {
84 return p.info_.name_ == "out0";
85 });
86 if (outPort == nodeSpec.portSpecSet_.end()) {
87 CAMERA_LOGI("config fail! node name:%{public}s out0 not exist", nodeSpec.name_.c_str());
88 return RC_ERROR;
89 }
90 format = (*outPort).format_;
91 return RC_OK;
92 }
SetPortFormat(G_PIPELINE_SPEC_DATA_TYPE & pipeSpecPtr,const std::optional<int32_t> & typeId,int j,int k,HostStreamInfo hostStreamInfo)93 PortFormat StreamPipelineStrategy::SetPortFormat(G_PIPELINE_SPEC_DATA_TYPE &pipeSpecPtr,
94 const std::optional<int32_t>& typeId,
95 int j,
96 int k,
97 HostStreamInfo hostStreamInfo)
98 {
99 PortFormat f {
100 .w_ = hostStreamInfo.width_,
101 .h_ = hostStreamInfo.height_,
102 .streamId_ = hostStreamInfo.streamId_,
103 .format_ = hostStreamInfo.format_,
104 .usage_ = hostStreamInfo.usage_,
105 .needAllocation_ = pipeSpecPtr->nodeSpec[j].portSpec[k].needAllocation,
106 .bufferCount_ = hostStreamInfo.bufferCount_
107 };
108 (void)typeId;
109 CAMERA_LOGI("buffercount = %{public}d", f.bufferCount_);
110 return f;
111 }
112
InitPipeSpecPtr(G_PIPELINE_SPEC_DATA_TYPE & pipeSpecPtr,const std::string & keyStr)113 void StreamPipelineStrategy::InitPipeSpecPtr(G_PIPELINE_SPEC_DATA_TYPE &pipeSpecPtr, const std::string& keyStr)
114 {
115 for (int i = 0; i < G_PIPELINE_SPECS_SIZE; i++) {
116 if (G_PIPELINE_SPECS_TABLE[i].name == keyStr) {
117 pipeSpecPtr = &G_PIPELINE_SPECS_TABLE[i];
118 break;
119 }
120 }
121 }
122
SetNodeSpec(const PipelineSpec & pipe,G_PIPELINE_SPEC_DATA_TYPE & pipeSpecPtr,NodeSpec & nodeSpec,int nodeIndex,int portIndex)123 RetCode StreamPipelineStrategy::SetNodeSpec(const PipelineSpec& pipe,
124 G_PIPELINE_SPEC_DATA_TYPE& pipeSpecPtr, NodeSpec& nodeSpec, int nodeIndex, int portIndex)
125 {
126 PortInfo info {
127 .name_ = std::string(pipeSpecPtr->nodeSpec[nodeIndex].portSpec[portIndex].name),
128 .peerPortName_ = std::string(pipeSpecPtr->nodeSpec[nodeIndex].portSpec[portIndex].peerPortName),
129 .peerPortNodeName_ = std::string(pipeSpecPtr->nodeSpec[nodeIndex].portSpec[portIndex].peerPortNodeName)
130 };
131 CAMERA_LOGV("read node %{public}s", info.peerPortNodeName_.c_str());
132
133 std::optional<int32_t> typeId = GetTypeId(std::string(pipeSpecPtr->nodeSpec[nodeIndex].streamType),
134 G_STREAM_TABLE_PTR, G_STREAM_TABLE_SIZE);
135 PortFormat format {};
136
137 if (typeId) {
138 int32_t streamId = hostStreamMgr_->DesignateStreamIdForType(typeId.value());
139 HostStreamInfo hostStreamInfo = hostStreamMgr_->GetStreamInfo(streamId);
140 PortFormat f = SetPortFormat(pipeSpecPtr, typeId, nodeIndex, portIndex, hostStreamInfo);
141 if (!f.needAllocation_) {
142 f.bufferPoolId_ = static_cast<int64_t>(hostStreamInfo.bufferPoolId_);
143 }
144 format = f;
145 nodeSpec.streamId_ = hostStreamInfo.streamId_;
146 } else if (pipeSpecPtr->nodeSpec[nodeIndex].portSpec[portIndex].direction == 1) {
147 if (SetUpBasicOutPortFormat(pipe, info, format) != RC_OK) {
148 return RC_ERROR;
149 }
150 } else {
151 if (SetUpBasicInPortFormat(nodeSpec, format) != RC_OK) {
152 return RC_ERROR;
153 }
154 }
155
156 struct PortSpec portSpec {
157 .direction_ = pipeSpecPtr->nodeSpec[nodeIndex].portSpec[portIndex].direction,
158 .info_ = info,
159 .format_ = format,
160 };
161 nodeSpec.portSpecSet_.push_back(portSpec);
162
163 return RC_OK;
164 }
165
SelectPipelineSpec(const int32_t & mode,PipelineSpec & pipe)166 RetCode StreamPipelineStrategy::SelectPipelineSpec(const int32_t& mode, PipelineSpec& pipe)
167 {
168 std::string keyStr = ConstructKeyStrIndex(mode);
169 G_PIPELINE_SPEC_DATA_TYPE pipeSpecPtr = nullptr;
170 InitPipeSpecPtr(pipeSpecPtr, keyStr);
171 if (pipeSpecPtr == nullptr) {
172 CAMERA_LOGE("target pipeline spec:%{public}s not exist!\n ", keyStr.c_str());
173 return RC_ERROR;
174 }
175
176 for (int j = pipeSpecPtr->nodeSpecSize - 1; j >= 0; j--) {
177 struct NodeSpec nodeSpec {
178 .name_ = pipeSpecPtr->nodeSpec[j].name,
179 .status_ = std::string(pipeSpecPtr->nodeSpec[j].status),
180 .type_ = std::string(pipeSpecPtr->nodeSpec[j].streamType)
181 };
182 for (int k = pipeSpecPtr->nodeSpec[j].portSpecSize - 1; k >= 0; k--) {
183 if (SetNodeSpec(pipe, pipeSpecPtr, nodeSpec, j, k) != RC_OK) {
184 CAMERA_LOGI("SelectPipelineSpec failed.\n");
185 return RC_ERROR;
186 }
187 }
188 pipe.nodeSpecSet_.push_back(nodeSpec);
189 }
190 return RC_OK;
191 }
192
PrintConnection(const NodeSpec & n)193 void StreamPipelineStrategy::PrintConnection(const NodeSpec& n)
194 {
195 if (n.portSpecSet_.size() == 1 && n.portSpecSet_[0].direction_ == 0) {
196 return;
197 }
198
199 for (const auto& it : n.portSpecSet_) {
200 if (it.direction_ == 1) {
201 CAMERA_LOGI("(%{public}s)(name:%{public}s w:%{public}d h:%{public}d format:%{public}d usage:%{public}llu \
202 bufferpoolid:%{public}llu) connect to (%{public}s)(name:%{public}s) \n",
203 n.name_.c_str(), it.info_.name_.c_str(), it.format_.w_, it.format_.h_, it.format_.format_,
204 it.format_.usage_, it.format_.bufferPoolId_,
205 it.info_.peerPortNodeName_.c_str(), it.info_.peerPortName_.c_str());
206 auto nextNode = std::find_if(pipelineSpec_->nodeSpecSet_.begin(),
207 pipelineSpec_->nodeSpecSet_.end(),
208 [it](const NodeSpec& n) {
209 return n.name_ == it.info_.peerPortNodeName_;
210 });
211 if (nextNode != pipelineSpec_->nodeSpecSet_.end()) {
212 PrintConnection(*nextNode);
213 }
214 }
215 }
216 }
217
CombineSpecs(PipelineSpec & pipe)218 RetCode StreamPipelineStrategy::CombineSpecs(PipelineSpec& pipe)
219 {
220 CHECK_IF_PTR_NULL_RETURN_VALUE(pipelineSpec_, RC_ERROR);
221 CAMERA_LOGI("pipe.size = %{public}d,nodeSpecSet_.size = %{public}d", pipe.nodeSpecSet_.size(),
222 pipelineSpec_->nodeSpecSet_.size());
223 for (auto it = pipe.nodeSpecSet_.rbegin(); it != pipe.nodeSpecSet_.rend(); it++) {
224 auto node = std::find_if(pipelineSpec_->nodeSpecSet_.begin(), pipelineSpec_->nodeSpecSet_.end(),
225 [it](const NodeSpec& n) {
226 return n.name_ == (*it).name_;
227 });
228 if (node == pipelineSpec_->nodeSpecSet_.end()) {
229 CAMERA_LOGI("add node:%{public}s\n", (*it).name_.c_str());
230 pipelineSpec_->nodeSpecSet_.push_back(*it);
231 } else {
232 if (*node != *it) {
233 CAMERA_LOGI("change node:%{public}s\n", (*it).name_.c_str());
234 std::swap((*node).portSpecSet_, (*it).portSpecSet_);
235 }
236 }
237 }
238 CAMERA_LOGI("------------------------Connection Dump Begin-------------\n");
239 PrintConnection(pipelineSpec_->nodeSpecSet_[0]);
240 CAMERA_LOGI("------------------------Connection Dump End-------------\n");
241 return RC_OK;
242 }
243
Destroy(const int & streamId)244 RetCode StreamPipelineStrategy::Destroy(const int& streamId)
245 {
246 CHECK_IF_PTR_NULL_RETURN_VALUE(pipelineSpec_, RC_ERROR);
247 (void)streamId;
248 pipelineSpec_->nodeSpecSet_.clear();
249 return RC_OK;
250 }
251
Create(const std::shared_ptr<HostStreamMgr> & streamMgr)252 std::unique_ptr<StreamPipelineStrategy> StreamPipelineStrategy::Create(const std::shared_ptr<HostStreamMgr>& streamMgr)
253 {
254 std::shared_ptr<PipelineSpec> p = std::make_shared<PipelineSpec>();
255 return std::make_unique<StreamPipelineStrategy>(streamMgr, p);
256 }
257
CheckPipelineSpecExist(const int32_t mode,const std::vector<int32_t> & types)258 RetCode StreamPipelineStrategy::CheckPipelineSpecExist(const int32_t mode, const std::vector<int32_t>& types)
259 {
260 std::string sceneStr = CheckIdExsit(mode, G_SCENE_TABLE_PTR, G_SCENE_TABLE_SIZE);
261 if (sceneStr.empty()) {
262 return RC_ERROR;
263 }
264
265 std::string keyStr = "";
266 keyStr += sceneStr;
267 for (const auto it : types) {
268 std::string streamStr = CheckIdExsit(it, G_STREAM_TABLE_PTR, G_STREAM_TABLE_SIZE);
269 if (streamStr.empty()) {
270 return RC_ERROR;
271 }
272 keyStr += "_" + streamStr;
273 }
274
275 for (int i = 0; i < G_PIPELINE_SPECS_SIZE; i++) {
276 if (G_PIPELINE_SPECS_TABLE[i].name == keyStr) {
277 return RC_OK;
278 }
279 }
280
281 return RC_ERROR;
282 }
283 }
284