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].need_allocation,
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
SelectPipelineSpec(const int32_t & mode,PipelineSpec & pipe)123 RetCode StreamPipelineStrategy::SelectPipelineSpec(const int32_t& mode, PipelineSpec& pipe)
124 {
125 std::string keyStr = ConstructKeyStrIndex(mode);
126 G_PIPELINE_SPEC_DATA_TYPE pipeSpecPtr = nullptr;
127 InitPipeSpecPtr(pipeSpecPtr, keyStr);
128 if (pipeSpecPtr == nullptr) {
129 CAMERA_LOGE("target pipeline spec:%{public}s not exist!\n ", keyStr.c_str());
130 return RC_ERROR;
131 }
132
133 for (int j = pipeSpecPtr->nodeSpecSize - 1; j >= 0; j--) {
134 struct NodeSpec nodeSpec {
135 .name_ = pipeSpecPtr->nodeSpec[j].name,
136 .status_ = std::string(pipeSpecPtr->nodeSpec[j].status),
137 .type_ = std::string(pipeSpecPtr->nodeSpec[j].stream_type)
138 };
139 for (int k = pipeSpecPtr->nodeSpec[j].portSpecSize - 1; k >= 0; k--) {
140 PortInfo info {
141 .name_ = std::string(pipeSpecPtr->nodeSpec[j].portSpec[k].name),
142 .peerPortName_ = std::string(pipeSpecPtr->nodeSpec[j].portSpec[k].peer_port_name),
143 .peerPortNodeName_ = std::string(pipeSpecPtr->nodeSpec[j].portSpec[k].peer_port_node_name)
144 };
145 CAMERA_LOGV("read node %{public}s", info.peerPortNodeName_.c_str());
146
147 std::optional<int32_t> typeId = GetTypeId(std::string(pipeSpecPtr->nodeSpec[j].stream_type),
148 G_STREAM_TABLE_PTR, G_STREAM_TABLE_SIZE);
149 PortFormat format {};
150
151 if (typeId) {
152 int32_t streamId = hostStreamMgr_->DesignateStreamIdForType(typeId.value());
153 HostStreamInfo hostStreamInfo = hostStreamMgr_->GetStreamInfo(streamId);
154 PortFormat f = SetPortFormat(pipeSpecPtr, typeId, j, k, hostStreamInfo);
155 if (!f.needAllocation_) {
156 f.bufferPoolId_ =
157 static_cast<int64_t>(hostStreamInfo.bufferPoolId_);
158 }
159 format = f;
160 nodeSpec.streamId_ = hostStreamInfo.streamId_;
161 } else if (pipeSpecPtr->nodeSpec[j].portSpec[k].direction == 1) {
162 if (SetUpBasicOutPortFormat(pipe, info, format) != RC_OK) {
163 return RC_ERROR;
164 }
165 } else {
166 if (SetUpBasicInPortFormat(nodeSpec, format) != RC_OK) {
167 return RC_ERROR;
168 }
169 }
170 struct PortSpec portSpec {
171 .direction_ = pipeSpecPtr->nodeSpec[j].portSpec[k].direction,
172 .info_ = info,
173 .format_ = format,
174 };
175 nodeSpec.portSpecSet_.push_back(portSpec);
176 }
177 pipe.nodeSpecSet_.push_back(nodeSpec);
178 }
179 return RC_OK;
180 }
181
PrintConnection(const NodeSpec & n)182 void StreamPipelineStrategy::PrintConnection(const NodeSpec& n)
183 {
184 if (n.portSpecSet_.size() == 1 && n.portSpecSet_[0].direction_ == 0) {
185 return;
186 }
187
188 for (const auto& it : n.portSpecSet_) {
189 if (it.direction_ == 1) {
190 CAMERA_LOGI("(%{public}s)(name:%{public}s w:%{public}d h:%{public}d format:%{public}d usage:%{public}llu \
191 bufferpoolid:%{public}llu) connect to (%{public}s)(name:%{public}s) \n",
192 n.name_.c_str(), it.info_.name_.c_str(), it.format_.w_, it.format_.h_, it.format_.format_,
193 it.format_.usage_, it.format_.bufferPoolId_,
194 it.info_.peerPortNodeName_.c_str(), it.info_.peerPortName_.c_str());
195 auto nextNode = std::find_if(pipelineSpec_->nodeSpecSet_.begin(),
196 pipelineSpec_->nodeSpecSet_.end(),
197 [it](const NodeSpec& n) {
198 return n.name_ == it.info_.peerPortNodeName_;
199 });
200 if (nextNode != pipelineSpec_->nodeSpecSet_.end()) {
201 PrintConnection(*nextNode);
202 }
203 }
204 }
205 }
206
CombineSpecs(PipelineSpec & pipe)207 RetCode StreamPipelineStrategy::CombineSpecs(PipelineSpec& pipe)
208 {
209 CHECK_IF_PTR_NULL_RETURN_VALUE(pipelineSpec_, RC_ERROR);
210 CAMERA_LOGI("pipe.size = %{public}d,nodeSpecSet_.size = %{public}d", pipe.nodeSpecSet_.size(),
211 pipelineSpec_->nodeSpecSet_.size());
212 for (auto it = pipe.nodeSpecSet_.rbegin(); it != pipe.nodeSpecSet_.rend(); it++) {
213 auto node = std::find_if(pipelineSpec_->nodeSpecSet_.begin(), pipelineSpec_->nodeSpecSet_.end(),
214 [it](const NodeSpec& n) {
215 return n.name_ == (*it).name_;
216 });
217 if (node == pipelineSpec_->nodeSpecSet_.end()) {
218 CAMERA_LOGI("add node:%{public}s\n", (*it).name_.c_str());
219 pipelineSpec_->nodeSpecSet_.push_back(*it);
220 } else {
221 if (*node != *it) {
222 CAMERA_LOGI("change node:%{public}s\n", (*it).name_.c_str());
223 std::swap((*node).portSpecSet_, (*it).portSpecSet_);
224 }
225 }
226 }
227 CAMERA_LOGI("------------------------Connection Dump Begin-------------\n");
228 PrintConnection(pipelineSpec_->nodeSpecSet_[0]);
229 CAMERA_LOGI("------------------------Connection Dump End-------------\n");
230 return RC_OK;
231 }
232
Destroy(const int & streamId)233 RetCode StreamPipelineStrategy::Destroy(const int& streamId)
234 {
235 CHECK_IF_PTR_NULL_RETURN_VALUE(pipelineSpec_, RC_ERROR);
236 (void)streamId;
237 pipelineSpec_->nodeSpecSet_.clear();
238 return RC_OK;
239 }
240
Create(const std::shared_ptr<HostStreamMgr> & streamMgr)241 std::unique_ptr<StreamPipelineStrategy> StreamPipelineStrategy::Create(const std::shared_ptr<HostStreamMgr>& streamMgr)
242 {
243 std::shared_ptr<PipelineSpec> p = std::make_shared<PipelineSpec>();
244 return std::make_unique<StreamPipelineStrategy>(streamMgr, p);
245 }
246
CheckPipelineSpecExist(const int32_t mode,const std::vector<int32_t> & types)247 RetCode StreamPipelineStrategy::CheckPipelineSpecExist(const int32_t mode, const std::vector<int32_t>& types)
248 {
249 std::string sceneStr = CheckIdExsit(mode, G_SCENE_TABLE_PTR, G_SCENE_TABLE_SIZE);
250 if (sceneStr.empty()) {
251 return RC_ERROR;
252 }
253
254 std::string keyStr = "";
255 keyStr += sceneStr;
256 for (const auto it : types) {
257 std::string streamStr = CheckIdExsit(it, G_STREAM_TABLE_PTR, G_STREAM_TABLE_SIZE);
258 if (streamStr.empty()) {
259 return RC_ERROR;
260 }
261 keyStr += "_" + streamStr;
262 }
263
264 for (int i = 0; i < G_PIPELINE_SPECS_SIZE; i++) {
265 if (G_PIPELINE_SPECS_TABLE[i].name == keyStr) {
266 return RC_OK;
267 }
268 }
269
270 return RC_ERROR;
271 }
272 }
273