• 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 "buffer_pool.h"
17 #include <chrono>
18 #include "buffer_adapter.h"
19 #include "image_buffer.h"
20 #include "buffer_tracking.h"
21 
22 namespace OHOS::Camera {
BufferPool()23 BufferPool::BufferPool()
24 {
25     CAMERA_LOGI("BufferPool construct");
26 }
27 
~BufferPool()28 BufferPool::~BufferPool()
29 {
30     DestroyBuffer();
31 }
32 
Init(const uint32_t width,const uint32_t height,const uint64_t usage,const uint32_t bufferFormat,const uint32_t count,const int32_t bufferSourceType)33 RetCode BufferPool::Init(const uint32_t width,
34                          const uint32_t height,
35                          const uint64_t usage,
36                          const uint32_t bufferFormat,
37                          const uint32_t count,
38                          const int32_t bufferSourceType)
39 {
40     bufferWidth_ = width;
41     bufferHeight_ = height;
42     bufferUsage_ = usage;
43     bufferFormat_ = bufferFormat;
44     bufferCount_ = count;
45     bufferSourceType_ = bufferSourceType;
46 
47     if (bufferSourceType_ == CAMERA_BUFFER_SOURCE_TYPE_EXTERNAL) {
48         CAMERA_LOGI("buffers are from external source");
49         return RC_OK;
50     }
51 
52     BufferAllocatorFactory* factory = BufferAllocatorFactory::GetInstance();
53     if (factory == nullptr) {
54         CAMERA_LOGE("buffer allocator factory is null");
55         return RC_ERROR;
56     }
57 
58     bufferAllocator_ = factory->GetBufferAllocator(bufferSourceType_);
59     if (bufferAllocator_ == nullptr) {
60         CAMERA_LOGI("can't find buffer allocator");
61         return RC_ERROR;
62     }
63 
64     if (bufferAllocator_->Init() != RC_OK) {
65         return RC_ERROR;
66     }
67 
68     return PrepareBuffer();
69 }
70 
PrepareBuffer()71 RetCode BufferPool::PrepareBuffer()
72 {
73     if (bufferSourceType_ == CAMERA_BUFFER_SOURCE_TYPE_EXTERNAL) {
74         CAMERA_LOGI("no need allocate buffer");
75         return RC_OK;
76     }
77 
78     if (bufferAllocator_ == nullptr) {
79         CAMERA_LOGE("bufferAllocator_ is nullptr");
80         return RC_ERROR;
81     }
82 
83     for (uint32_t i = 0; i < bufferCount_; i++) {
84         std::shared_ptr<IBuffer> buffer =
85             bufferAllocator_->AllocBuffer(bufferWidth_, bufferHeight_, bufferUsage_, bufferFormat_);
86         if (buffer == nullptr) {
87             CAMERA_LOGE("alloc buffer failed");
88             return RC_ERROR;
89         }
90         if (RC_OK != bufferAllocator_->MapBuffer(buffer)) {
91             CAMERA_LOGE("map buffer failed");
92             return RC_ERROR;
93         }
94         buffer->SetIndex(i);
95         buffer->SetPoolId(poolId_);
96 
97         {
98             std::unique_lock<std::mutex> l(lock_);
99             idleList_.emplace_back(buffer);
100         }
101     }
102 
103     return RC_OK;
104 }
105 
DestroyBuffer()106 RetCode BufferPool::DestroyBuffer()
107 {
108     if (bufferSourceType_ == CAMERA_BUFFER_SOURCE_TYPE_EXTERNAL) {
109         std::unique_lock<std::mutex> l(lock_);
110         idleList_.clear();
111         busyList_.clear();
112         sfBuffer_.clear();
113         sfSize_.clear();
114         return RC_OK;
115     }
116 
117     if (bufferAllocator_ == nullptr) {
118         CAMERA_LOGE("bufferAllocator_ is nullptr");
119         return RC_ERROR;
120     }
121 
122     {
123         std::unique_lock<std::mutex> l(lock_);
124 
125         for (auto it : idleList_) {
126             RetCode ret = bufferAllocator_->UnmapBuffer(it);
127             if (ret != RC_OK) {
128                 CAMERA_LOGE("unmap (%{public}d) buffer failed", it->GetIndex());
129             }
130             ret = bufferAllocator_->FreeBuffer(it);
131             if (ret != RC_OK) {
132                 CAMERA_LOGE("free (%{public}d) buffer failed", it->GetIndex());
133             }
134         }
135         idleList_.clear();
136 
137         if (busyList_.size() > 0) {
138             CAMERA_LOGE("%{public}zu buffer(s) is/are in use.", busyList_.size());
139         }
140         for (auto it : busyList_) {
141             RetCode ret = bufferAllocator_->UnmapBuffer(it);
142             if (ret != RC_OK) {
143                 CAMERA_LOGE("unmap (%{public}d) buffer failed", it->GetIndex());
144             }
145             ret = bufferAllocator_->FreeBuffer(it);
146             if (ret != RC_OK) {
147                 CAMERA_LOGE("free (%{public}d) buffer failed", it->GetIndex());
148             }
149         }
150         busyList_.clear();
151         sfBuffer_.clear();
152         sfSize_.clear();
153     }
154 
155     return RC_OK;
156 }
157 
AddBuffer(std::shared_ptr<IBuffer> & buffer)158 RetCode BufferPool::AddBuffer(std::shared_ptr<IBuffer>& buffer)
159 {
160     std::unique_lock<std::mutex> l(lock_);
161     buffer->SetPoolId(poolId_);
162     idleList_.emplace_back(buffer);
163     cv_.notify_one();
164     return RC_OK;
165 }
166 
AcquireBuffer(int timeout)167 std::shared_ptr<IBuffer> BufferPool::AcquireBuffer(int timeout)
168 {
169     std::unique_lock<std::mutex> l(lock_);
170 
171     // return buffer immediately, if idle buffer is available;
172     if (!idleList_.empty()) {
173         auto it = idleList_.begin();
174         auto buffer = *it;
175         busyList_.splice(busyList_.begin(), idleList_, it);
176         CAMERA_LOGV("acquire buffer immediately, index = %{public}d", buffer->GetIndex());
177         return *it;
178     }
179 
180     // wait all the time, till idle list is available.
181     if (timeout < 0) {
182         cv_.wait(l, [this] {
183             return !idleList_.empty() || stop_;
184             });
185         if (!idleList_.empty()) {
186             auto it = idleList_.begin();
187             auto buffer = *it;
188             busyList_.splice(busyList_.begin(), idleList_, it);
189             CAMERA_LOGV("acquire buffer wait all the time, index = %{public}d", buffer->GetIndex());
190             return *it;
191         }
192     }
193 
194     // wait for timeout, or idle list is available.
195     if (timeout > 0) {
196         if (cv_.wait_for(l, std::chrono::seconds(timeout), [this] {
197             return !idleList_.empty() || stop_;
198             }) == false) {
199             CAMERA_LOGE("wait idle buffer timeout");
200             return nullptr;
201         }
202         if (!idleList_.empty()) {
203             auto it = idleList_.begin();
204             auto buffer = *it;
205             busyList_.splice(busyList_.begin(), idleList_, it);
206             CAMERA_LOGV("acquire buffer wait %{public}ds, index = %{public}d", timeout, buffer->GetIndex());
207             return *it;
208         }
209     }
210 
211     // timeout == 0. return nullptr buffer immediately, although idle buffer is not available.
212     return nullptr;
213 }
214 
ReturnBuffer(std::shared_ptr<IBuffer> & buffer)215 RetCode BufferPool::ReturnBuffer(std::shared_ptr<IBuffer>& buffer)
216 {
217     std::unique_lock<std::mutex> l(lock_);
218 
219     auto it = std::find(busyList_.begin(), busyList_.end(), buffer);
220     if (it == busyList_.end()) {
221         CAMERA_LOGE("fatal error, busy list is empty, cannot return buffer.");
222         return RC_ERROR;
223     }
224 
225     if (bufferSourceType_ == CAMERA_BUFFER_SOURCE_TYPE_EXTERNAL) {
226         busyList_.erase(it);
227         cv_.notify_one();
228         return RC_OK;
229     }
230 
231     if (trackingId_ >= 0) {
232         POOL_REPORT_BUFFER_LOCATION(trackingId_, buffer->GetFrameNumber());
233     }
234 
235     idleList_.splice(idleList_.end(), busyList_, it);
236     cv_.notify_one();
237 
238     return RC_OK;
239 }
240 
EnableTracking(const int32_t id)241 void BufferPool::EnableTracking(const int32_t id)
242 {
243     trackingId_ = id;
244     return;
245 }
246 
SetId(const int64_t id)247 void BufferPool::SetId(const int64_t id)
248 {
249     poolId_ = id;
250 }
251 
NotifyStop()252 void BufferPool::NotifyStop()
253 {
254     std::unique_lock<std::mutex> l(lock_);
255     stop_ = true;
256     cv_.notify_all();
257 }
258 
NotifyStart()259 void BufferPool::NotifyStart()
260 {
261     std::unique_lock<std::mutex> l(lock_);
262     stop_ = false;
263     cv_.notify_all();
264 }
265 
ClearBuffers()266 void BufferPool::ClearBuffers()
267 {
268     DestroyBuffer();
269 }
270 
GetIdleBufferCount()271 uint32_t BufferPool::GetIdleBufferCount()
272 {
273     std::unique_lock<std::mutex> l(lock_);
274     return idleList_.size();
275 }
setSFBuffer(std::shared_ptr<IBuffer> & buffer)276 void BufferPool::setSFBuffer(std::shared_ptr<IBuffer>& buffer)
277 {
278     sfBuffer_.insert(std::make_pair(buffer->GetIndex(), static_cast<uint8_t *>(buffer->GetVirAddress())));
279     sfSize_.insert(std::make_pair(buffer->GetIndex(), buffer->GetSize()));
280     forkBufferId_ = buffer->GetIndex();
281 }
282 
getSFBuffer(int32_t index)283 std::map<int32_t, uint8_t*> BufferPool::getSFBuffer(int32_t index)
284 {
285     std::map<int32_t, uint8_t*> sizeVirMap;
286     auto iterMap = sfBuffer_.find(index);
287     if (iterMap == sfBuffer_.end()) {
288         CAMERA_LOGE("std::map sfBuffer_ no buffer->GetIndex()\n");
289         return sizeVirMap;
290     }
291 
292     auto iterSizeMap = sfSize_.find(index);
293     if (iterSizeMap == sfSize_.end()) {
294         CAMERA_LOGE("std::map sfSize_ no buffer->GetIndex()\n");
295         return sizeVirMap;
296     }
297     sizeVirMap[iterSizeMap->second] = iterMap->second;
298     return sizeVirMap;
299 }
300 
GetForkBufferId()301 int32_t BufferPool::GetForkBufferId()
302 {
303     return forkBufferId_;
304 }
305 
SetForkBufferId(int32_t index)306 void BufferPool::SetForkBufferId(int32_t index)
307 {
308     forkBufferId_ = index;
309 }
310 
GetIsFork()311 bool BufferPool::GetIsFork()
312 {
313     return isFork_;
314 }
315 
SetIsFork(bool isFork)316 void BufferPool::SetIsFork(bool isFork)
317 {
318     isFork_ = isFork;
319 }
320 } // namespace OHOS::Camera
321