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