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