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