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