• 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  *
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 "offline_pipeline.h"
17 #include "buffer_manager.h"
18 #include "ibuffer_pool.h"
19 #include <vector>
20 
21 namespace OHOS::Camera {
OfflinePipeline()22 OfflinePipeline::OfflinePipeline() : calltimes_(0) {}
23 
~OfflinePipeline()24 OfflinePipeline::~OfflinePipeline()
25 {
26     StopProcess();
27     bufferCache_.clear();
28 }
29 
StartProcess()30 RetCode OfflinePipeline::StartProcess()
31 {
32     int origin = calltimes_.fetch_add(1);
33     if (origin != 0) {
34         // already called at most 1 time, no reenter
35         CAMERA_LOGE("Now will not start, current start %{public}d times", calltimes_.load());
36         return RC_ERROR;
37     }
38 
39     running_ = true;
40     processThread_ = new std::thread([this]() {
41         prctl(PR_SET_NAME, "offlinepipeline");
42         while (true) {
43             {
44                 std::unique_lock<std::mutex> l(queueLock_);
45                 if (running_ == false) {
46                     CAMERA_LOGD("offlinepipeline thread break");
47                     break;
48                 }
49             }
50             HandleBuffers();
51         }
52     });
53 
54     if (processThread_ == nullptr) {
55         return RC_ERROR;
56     }
57     return RC_OK;
58 }
59 
StopProcess()60 RetCode OfflinePipeline::StopProcess()
61 {
62     if (processThread_ == nullptr) {
63         CAMERA_LOGE("cannot stop.");
64         return RC_ERROR;
65     }
66     {
67         std::unique_lock<std::mutex> l(queueLock_);
68         if (running_.load() == false) {
69             return RC_OK;
70         }
71 
72         running_ = false;
73         cv_.notify_one();
74     }
75 
76     processThread_->detach();
77     delete processThread_;
78     processThread_ = nullptr;
79     return RC_OK;
80 }
81 
BindOfflineStreamCallback(std::function<void (std::shared_ptr<IBuffer> &)> & callback)82 void OfflinePipeline::BindOfflineStreamCallback(std::function<void(std::shared_ptr<IBuffer>&)>& callback)
83 {
84     std::lock_guard<std::mutex> l(cbLock_);
85     callback_ = callback;
86 
87     return;
88 }
89 
SwitchToOfflineMode()90 void OfflinePipeline::SwitchToOfflineMode()
91 {
92     offlineMode_ = true;
93 }
94 
CancelCapture(int32_t captureId)95 RetCode OfflinePipeline::CancelCapture(int32_t captureId)
96 {
97     CAMERA_LOGE("cancel capture begin");
98     if (bufferCache_.empty()) {
99         CAMERA_LOGE("cancel capture failed, capture id = %{public}d doesn't exist", captureId);
100         return RC_OK;
101     }
102 
103     std::vector<std::shared_ptr<IBuffer>> cache;
104     {
105         std::unique_lock<std::mutex> l(queueLock_);
106         auto it = std::find_if(bufferCache_.begin(), bufferCache_.end(),
107             [&captureId](const std::vector<std::shared_ptr<IBuffer>>& c) {
108                 for (auto b : c) {
109                     if (b->GetCaptureId() == captureId) {
110                         return true;
111                     }
112                 }
113                 return false;
114             });
115         if (it == bufferCache_.end()) {
116             CAMERA_LOGE("cancel capture failed, capture id = %{public}d doesn't exist", captureId);
117             return RC_OK;
118         }
119         cache = *it;
120         bufferCache_.erase(it);
121     }
122     for (auto it : cache) {
123         it->SetBufferStatus(CAMERA_BUFFER_STATUS_DROP);
124     }
125     DeliverCancelCache(cache);
126     CAMERA_LOGE("cancel capture end");
127     return RC_OK;
128 }
129 
FlushOfflineStream()130 RetCode OfflinePipeline::FlushOfflineStream()
131 {
132     if (!offlineMode_.load()) {
133         CAMERA_LOGE("can't flush in online mode");
134         return RC_ERROR;
135     }
136 
137     if (!bufferCache_.empty()) {
138         std::unique_lock<std::mutex> l(queueLock_);
139         while (!bufferCache_.empty()) {
140             auto cache = bufferCache_.front();
141             bufferCache_.pop_front();
142 
143             for (auto it : cache) {
144                 it->SetBufferStatus(CAMERA_BUFFER_STATUS_DROP);
145             }
146             DeliverCancelCache(cache);
147         }
148     }
149 
150     return RC_OK;
151 }
152 
ReceiveCache(std::vector<std::shared_ptr<IBuffer>> & buffers)153 void OfflinePipeline::ReceiveCache(std::vector<std::shared_ptr<IBuffer>>& buffers)
154 {
155     if (!buffers.empty() && buffers[0]->GetBufferStatus() != CAMERA_BUFFER_STATUS_OK) {
156         DeliverCancelCache(buffers);
157         return;
158     }
159 
160     std::unique_lock<std::mutex> l(queueLock_);
161     bufferCache_.emplace_back(buffers);
162     cv_.notify_one();
163 
164     return;
165 }
166 
HandleBuffers()167 void OfflinePipeline::HandleBuffers()
168 {
169     std::vector<std::shared_ptr<IBuffer>> buffers = {};
170     {
171         std::unique_lock<std::mutex> l(queueLock_);
172         cv_.wait(l, [this] { return !(running_.load() && bufferCache_.empty()); });
173         if (running_ == false) {
174             return;
175         }
176         buffers = bufferCache_.front();
177         bufferCache_.pop_front();
178         if (buffers.empty()) {
179             return;
180         }
181     }
182 
183     ProcessCache(buffers);
184     return;
185 }
186 
ProcessCache(std::vector<std::shared_ptr<IBuffer>> & buffers)187 void OfflinePipeline::ProcessCache(std::vector<std::shared_ptr<IBuffer>>& buffers)
188 {
189     DeliverCache(buffers);
190     return;
191 }
DeliverCacheCheck(std::vector<std::shared_ptr<IBuffer>> & buffers)192 void OfflinePipeline::DeliverCacheCheck(std::vector<std::shared_ptr<IBuffer>>& buffers)
193 {
194     for (auto it : buffers) {
195         if (it == nullptr) {
196             continue;
197         }
198         auto bufferManager = BufferManager::GetInstance();
199         if (bufferManager == nullptr) {
200             CAMERA_LOGE("can't get buffer manager");
201             continue;
202         }
203         auto bufferPool = bufferManager->GetBufferPool(it->GetPoolId());
204         if (bufferPool == nullptr) {
205             CAMERA_LOGE("can't get buffer pool");
206             return;
207         }
208         bufferPool->ReturnBuffer(it);
209     }
210 }
DeliverCache(std::vector<std::shared_ptr<IBuffer>> & buffers)211 void OfflinePipeline::DeliverCache(std::vector<std::shared_ptr<IBuffer>>& buffers)
212 {
213     DeliverCacheCheck(buffers);
214     if (offlineMode_.load()) {
215         std::shared_ptr<IBuffer> nullBuffer = nullptr;
216         DeliverOfflineBuffer(nullBuffer);
217     }
218     return;
219 }
220 
DeliverCancelCache(std::vector<std::shared_ptr<IBuffer>> & buffers)221 void OfflinePipeline::DeliverCancelCache(std::vector<std::shared_ptr<IBuffer>>& buffers)
222 {
223     DeliverCache(buffers);
224     return;
225 }
226 
DeliverOfflineBuffer(std::shared_ptr<IBuffer> & buffer)227 void OfflinePipeline::DeliverOfflineBuffer(std::shared_ptr<IBuffer>& buffer)
228 {
229     if (!offlineMode_.load()) {
230         CAMERA_LOGE("cannot deliver buffer in online mode");
231         return;
232     }
233 
234     if (callback_ == nullptr) {
235         CAMERA_LOGE("cannot deliver offline buffer, callback_ is null");
236         return;
237     }
238 
239     callback_(buffer);
240 
241     return;
242 }
243 
CacheQueueDry()244 bool OfflinePipeline::CacheQueueDry()
245 {
246     std::unique_lock<std::mutex> l(queueLock_);
247     return bufferCache_.empty();
248 }
249 
CheckOwnerOfCaptureId(int32_t captureId)250 bool OfflinePipeline::CheckOwnerOfCaptureId(int32_t captureId)
251 {
252     std::unique_lock<std::mutex> l(queueLock_);
253     for (auto it : bufferCache_) {
254         for (auto buffer : it) {
255             if (captureId == buffer->GetCaptureId()) {
256                 return true;
257             }
258         }
259     }
260     return false;
261 }
262 } // namespace OHOS::Camera
263