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_manager_utest.h"
17 #include <chrono>
18 #include <iostream>
19 #include <sys/wait.h>
20 #include <unistd.h>
21 #include "buffer_adapter.h"
22 #include "buffer_allocator_utils.h"
23 #include "buffer_manager.h"
24 #include "buffer_tracking.h"
25 #include "iconsumer_surface.h"
26 #include "image_buffer.h"
27 #include "securec.h"
28
29 using namespace OHOS;
30 using namespace OHOS::CameraUtest;
31 using namespace testing::ext;
32
33 namespace {
34 const int FRAME_INTERVAL_US = 33000; // 33ms
35 const int FRAME_RUN_TIME_S = 3; // 3s
36 }
37
SetUpTestCase(void)38 void BufferManagerTest::SetUpTestCase(void)
39 {
40 CAMERA_LOGD("Camera::BufferManager SetUpTestCase");
41 }
42
TearDownTestCase(void)43 void BufferManagerTest::TearDownTestCase(void)
44 {
45 CAMERA_LOGD("Camera::BufferManager TearDownTestCase");
46 }
47
SetUp(void)48 void BufferManagerTest::SetUp(void)
49 {
50 CAMERA_LOGD("Camera::BufferManager SetUp");
51 }
52
TearDown(void)53 void BufferManagerTest::TearDown(void)
54 {
55 CAMERA_LOGD("Camera::BufferManager TearDown..");
56 }
57
58 HWTEST_F(BufferManagerTest, TestBufferQueueLoop, TestSize.Level0)
59 {
60 bool running = true;
61 #ifdef CAMERA_BUILT_ON_OHOS_LITE
62 std::shared_ptr<OHOS::Surface> consumer =
63 std::shared_ptr<OHOS::Surface>(OHOS::Surface::CreateSurface());
__anon7b5b49e50202null64 std::thread consumerThread([&consumer, &running] {
65 while (running) {
66 OHOS::SurfaceBuffer* buffer = consumer->AcquireBuffer();
67 if (buffer != nullptr) {
68 consumer->ReleaseBuffer(buffer);
69 CAMERA_LOGI("receive a buffer ...");
70 }
71 }
72 });
73 std::shared_ptr<OHOS::Surface> producer = consumer;
74 #else
75 OHOS::sptr<OHOS::IConsumerSurface> consumer = IConsumerSurface::Create();
76 sptr<IBufferConsumerListener> listener = new TestBufferConsumerListener();
77 ASSERT_NE(listener, nullptr);
78 consumer->RegisterConsumerListener(listener);
79
80 auto producer = consumer->GetProducer();
81 EXPECT_EQ(false, producer == nullptr);
__anon7b5b49e50302null82 std::thread consumerThread([&consumer, &running] {
83 int32_t flushFence = 0;
84 int64_t timestamp = 0;
85 Rect damage;
86 while (running) {
87 sptr<SurfaceBuffer> buffer = nullptr;
88 consumer->AcquireBuffer(buffer, flushFence, timestamp, damage);
89 if (buffer != nullptr) {
90 SurfaceError ret = consumer->ReleaseBuffer(buffer, -1);
91 if (ret == SURFACE_ERROR_OK) {
92 CAMERA_LOGI("receive a buffer ...");
93 }
94 }
95 }
96 });
97 #endif
98
99 // HDI impl start from here
100 auto stream = std::make_shared<BufferManagerTest::Stream>();
101 stream->Init(producer);
102 stream->StartStream();
103
104 BufferManagerTest::Pipeline pipeline;
105 pipeline.AddStream(stream);
106
__anon7b5b49e50402null107 std::thread enqueueThread([&stream, &running] {
108 while (running == true) {
109 stream->EnqueueBufferNonBlock();
110 }
111 });
112 pipeline.StartStream();
113
114 std::this_thread::sleep_for(std::chrono::seconds(10));
115 running = false;
116 enqueueThread.join();
117 pipeline.StopStream();
118 stream->StopStream();
119
120 running = false;
121 consumerThread.join();
122 }
123
124 HWTEST_F(BufferManagerTest, TestGetBufferPool, TestSize.Level0)
125 {
126 Camera::BufferManager* manager = Camera::BufferManager::GetInstance();
127 EXPECT_EQ(true, manager != nullptr);
128
129 int64_t bufferPoolId = manager->GenerateBufferPoolId();
130 EXPECT_EQ(true, bufferPoolId != 0);
131
132 std::shared_ptr<IBufferPool> bufferPool1 = nullptr;
__anon7b5b49e50502null133 std::thread user1([&manager, &bufferPool1, &bufferPoolId] { bufferPool1 = manager->GetBufferPool(bufferPoolId); });
134
135 std::shared_ptr<IBufferPool> bufferPool2 = nullptr;
__anon7b5b49e50602null136 std::thread user2([&manager, &bufferPool2, &bufferPoolId] { bufferPool2 = manager->GetBufferPool(bufferPoolId); });
137
138 user1.join();
139 user2.join();
140
141 EXPECT_EQ(true, bufferPool1 != nullptr);
142 EXPECT_EQ(true, bufferPool1 == bufferPool2);
143
144 int64_t bufferPoolId2 = manager->GenerateBufferPoolId();
145 EXPECT_EQ(true, bufferPoolId != 0);
146 std::shared_ptr<IBufferPool> bufferPool3 = manager->GetBufferPool(bufferPoolId2);
147 EXPECT_EQ(true, bufferPool1 != bufferPool3);
148
149 std::shared_ptr<IBufferPool> nullbufferPool = manager->GetBufferPool(1);
150 EXPECT_EQ(true, nullbufferPool == nullptr);
151 }
152
153 HWTEST_F(BufferManagerTest, TestHeapBuffer, TestSize.Level0)
154 {
155 Camera::BufferManager* manager = Camera::BufferManager::GetInstance();
156 EXPECT_EQ(true, manager != nullptr);
157
158 int64_t bufferPoolId = manager->GenerateBufferPoolId();
159 EXPECT_EQ(true, bufferPoolId != 0);
160
161 std::shared_ptr<IBuffer> buffer;
162 {
163 std::shared_ptr<IBufferPool> bufferPool = manager->GetBufferPool(bufferPoolId);
164 EXPECT_EQ(true, bufferPool != nullptr);
165
166 RetCode rc = bufferPool->Init(2, 1, CAMERA_USAGE_SW_WRITE_OFTEN, CAMERA_FORMAT_YCBCR_422_P, 1,
167 CAMERA_BUFFER_SOURCE_TYPE_HEAP);
168 EXPECT_EQ(true, rc == RC_OK);
169
170 buffer = bufferPool->AcquireBuffer();
171 EXPECT_EQ(true, buffer != nullptr);
172 EXPECT_EQ(true, buffer->GetVirAddress() != nullptr);
173 EXPECT_EQ(true, buffer->GetWidth() == 2);
174 EXPECT_EQ(true, buffer->GetHeight() == 1);
175 EXPECT_EQ(true, buffer->GetUsage() == CAMERA_USAGE_SW_WRITE_OFTEN);
176 EXPECT_EQ(true, buffer->GetFormat() == CAMERA_FORMAT_YCBCR_422_P);
177 EXPECT_EQ(true, buffer->GetSize() == 4);
178
179 char src[4] = {'t', 'e', 's', 't'};
180 char* dest = reinterpret_cast<char*>(buffer->GetVirAddress());
181 EXPECT_EQ(true, dest != nullptr);
182 EXPECT_EQ(true, memcpy_s(dest, sizeof(char) * 4, src, sizeof(char) * 4) == 0);
183 EXPECT_EQ(true, 0 == ::memcmp(src, dest, 4));
184
185 EXPECT_EQ(true, RC_OK == bufferPool->ReturnBuffer(buffer));
186 }
187 EXPECT_EQ(true, buffer->GetVirAddress() == nullptr);
188 }
189
190 #ifndef CAMERA_BUILT_ON_OHOS_LITE
191 HWTEST_F(BufferManagerTest, TestGrallocBuffer, TestSize.Level0)
192 {
193 Camera::BufferManager* manager = Camera::BufferManager::GetInstance();
194 EXPECT_EQ(true, manager != nullptr);
195
196 const uint32_t formatTest[] = {CAMERA_FORMAT_YCBCR_420_SP, CAMERA_FORMAT_YCRCB_420_SP,
197 CAMERA_FORMAT_YCBCR_420_P, CAMERA_FORMAT_YCRCB_420_P};
198 for (auto f : formatTest) {
199 int64_t bufferPoolId = manager->GenerateBufferPoolId();
200 EXPECT_EQ(true, bufferPoolId != 0);
201
202 std::shared_ptr<IBufferPool> bufferPool = manager->GetBufferPool(bufferPoolId);
203 EXPECT_EQ(true, bufferPool != nullptr);
204
205 RetCode rc = RC_ERROR;
206 rc = bufferPool->Init(1280, 720,
207 CAMERA_USAGE_SW_WRITE_OFTEN | CAMERA_USAGE_SW_READ_OFTEN | CAMERA_USAGE_MEM_DMA, f, 3,
208 CAMERA_BUFFER_SOURCE_TYPE_HEAP);
209 EXPECT_EQ(true, rc == RC_OK);
210 }
211 }
212 #endif
213
214 HWTEST_F(BufferManagerTest, TestInternalBufferLoop, TestSize.Level0)
215 {
216 Camera::BufferManager* manager = Camera::BufferManager::GetInstance();
217 EXPECT_EQ(true, manager != nullptr);
218 int64_t bufferPoolId = manager->GenerateBufferPoolId();
219 EXPECT_EQ(true, bufferPoolId != 0);
220 std::shared_ptr<IBufferPool> bufferPool = manager->GetBufferPool(bufferPoolId);
221 EXPECT_EQ(true, bufferPool != nullptr);
222 int count = 5;
223 RetCode rc = bufferPool->Init(1280, 720, CAMERA_USAGE_SW_WRITE_OFTEN, CAMERA_FORMAT_YCBCR_422_P, count,
224 CAMERA_BUFFER_SOURCE_TYPE_HEAP);
225 EXPECT_EQ(true, rc == RC_OK);
226 std::vector<std::shared_ptr<IBuffer>> bufferVector;
227 for (int i = 0; i < count; i++) {
228 auto buffer = bufferPool->AcquireBuffer();
229 if (buffer != nullptr) {
230 bufferVector.emplace_back(buffer);
231 }
232 }
233 EXPECT_EQ(true, 5 == bufferVector.size());
234 EXPECT_EQ(true, bufferPool->AcquireBuffer() == nullptr);
235 auto begin = std::chrono::system_clock::now();
236 auto nullBuffer = bufferPool->AcquireBuffer(1);
237 auto end = std::chrono::system_clock::now();
238 auto timeElapsed = std::chrono::duration_cast<std::chrono::microseconds>(end - begin);
239 CAMERA_LOGD("timeElapsed = %{public}d", timeElapsed.count());
240 EXPECT_EQ(true,
241 timeElapsed >= std::chrono::microseconds(1000000) && timeElapsed < std::chrono::microseconds(1100000));
242 EXPECT_EQ(true, nullBuffer == nullptr);
243 int32_t id = bufferVector[1]->GetIndex();
244 EXPECT_EQ(true, bufferPool->ReturnBuffer(bufferVector[1]) == RC_OK);
245 begin = std::chrono::system_clock::now();
246 nullBuffer = bufferPool->AcquireBuffer(1);
247 end = std::chrono::system_clock::now();
248 timeElapsed = std::chrono::duration_cast<std::chrono::microseconds>(end - begin);
249 EXPECT_EQ(true, timeElapsed < std::chrono::microseconds(1000000));
250 EXPECT_EQ(true, id == nullBuffer->GetIndex());
251 id = bufferVector[3]->GetIndex();
__anon7b5b49e50702null252 std::thread task([&bufferPool, &bufferVector] {
253 std::this_thread::sleep_for(std::chrono::seconds(5));
254 bufferPool->ReturnBuffer(bufferVector[3]);
255 });
256 begin = std::chrono::system_clock::now();
257 auto lastBuffer = bufferPool->AcquireBuffer(-1);
258 end = std::chrono::system_clock::now();
259 task.join();
260 timeElapsed = std::chrono::duration_cast<std::chrono::microseconds>(end - begin);
261 EXPECT_EQ(true, timeElapsed <= std::chrono::microseconds(5000000 + 10000) &&
262 timeElapsed >= std::chrono::microseconds(5000000 - 10000));
263 EXPECT_EQ(true, lastBuffer != nullptr);
264 EXPECT_EQ(true, id == lastBuffer->GetIndex());
265 }
266
267 HWTEST_F(BufferManagerTest, TestExternalBufferLoop, TestSize.Level0)
268 {
269 Camera::BufferManager* manager = Camera::BufferManager::GetInstance();
270 EXPECT_EQ(true, manager != nullptr);
271 int64_t bufferPoolId = manager->GenerateBufferPoolId();
272 EXPECT_EQ(true, bufferPoolId != 0);
273 std::shared_ptr<IBufferPool> bufferPool = manager->GetBufferPool(bufferPoolId);
274 EXPECT_EQ(true, bufferPool != nullptr);
275 int count = 5;
276 RetCode rc = bufferPool->Init(1280, 720, CAMERA_USAGE_SW_WRITE_OFTEN, CAMERA_FORMAT_YCBCR_422_P, count,
277 CAMERA_BUFFER_SOURCE_TYPE_EXTERNAL);
278 EXPECT_EQ(true, rc == RC_OK);
279 std::list<std::shared_ptr<IBuffer>> idleList;
280 std::list<std::shared_ptr<IBuffer>> busyList;
281 for (int i = 0; i < count; i++) {
282 std::shared_ptr<IBuffer> buffer = std::make_shared<ImageBuffer>();
283 buffer->SetIndex(i);
284 busyList.emplace_back(buffer);
285 bufferPool->AddBuffer(buffer);
286 CAMERA_LOGI("Add buffer : %{public}d", i);
287 }
288 bool running = true;
289 std::mutex lock;
290 int realFrameCount = 0;
__anon7b5b49e50802null291 std::thread dispatchBufferTask([&running, &idleList, &busyList, &bufferPool, &lock, &realFrameCount] {
292 while (running) {
293 std::lock_guard<std::mutex> l(lock);
294 if (idleList.empty()) {
295 continue;
296 }
297 auto it = idleList.begin();
298 if (RC_OK == bufferPool->AddBuffer(*it)) {
299 busyList.splice(busyList.begin(), idleList, it);
300 CAMERA_LOGI("Enq buffer : %{public}d", (*it)->GetIndex());
301 realFrameCount++;
302 }
303 }
304 });
305 std::list<std::shared_ptr<IBuffer>> inuseBufferList;
__anon7b5b49e50902null306 std::thread acquireBufferTask([&running, &bufferPool, &lock, &inuseBufferList] {
307 while (running) {
308 auto buffer = bufferPool->AcquireBuffer(2);
309 if (buffer != nullptr) {
310 std::lock_guard<std::mutex> l(lock);
311 inuseBufferList.emplace_back(buffer);
312 }
313 }
314 });
__anon7b5b49e50a02null315 std::thread returnBufferTask([&running, &lock, &inuseBufferList, &bufferPool, &busyList, &idleList] {
316 while (running) {
317 std::this_thread::sleep_for(std::chrono::microseconds(FRAME_INTERVAL_US));
318 {
319 std::lock_guard<std::mutex> l(lock);
320 if (inuseBufferList.empty()) {
321 continue;
322 }
323 auto it = inuseBufferList.begin();
324 bufferPool->ReturnBuffer(*it);
325 auto retBufferIt = std::find(busyList.begin(), busyList.end(), *it);
326 if (retBufferIt != busyList.end()) {
327 idleList.splice(idleList.end(), busyList, retBufferIt);
328 CAMERA_LOGI("Deq buffer : %{public}d", (*retBufferIt)->GetIndex());
329 }
330 inuseBufferList.erase(it);
331 }
332 }
333 });
334 std::this_thread::sleep_for(std::chrono::seconds(3));
335 running = false;
336 dispatchBufferTask.join();
337 acquireBufferTask.join();
338 returnBufferTask.join();
339 int expectFrameCount = FRAME_RUN_TIME_S * 1000 * 1000 / FRAME_INTERVAL_US;
340 CAMERA_LOGD("expectFrameCount = %{public}d, realFrameCount = %{public}d", expectFrameCount, realFrameCount);
341 EXPECT_EQ(true, realFrameCount >= expectFrameCount / 2 && realFrameCount <= expectFrameCount + 5);
342 }
343
344 HWTEST_F(BufferManagerTest, TestTrackingBufferLoop, TestSize.Level0)
345 {
346 #ifdef CAMERA_BUILT_ON_OHOS_LITE
347 std::shared_ptr<OHOS::Surface> producer = nullptr;
348 #else
349 sptr<OHOS::IBufferProducer> producer = nullptr;
350 #endif
351 // HDI impl start from here
352 bool running = true;
353 auto stream = std::make_shared<Stream>();
354 stream->Init(producer);
355 stream->StartStream();
356
357 Pipeline pipeline;
358 pipeline.AddStream(stream);
359
__anon7b5b49e50b02null360 std::thread enqueueThread([&stream, &running] {
361 while (running == true) {
362 stream->EnqueueBufferNonBlock();
363 }
364 });
365 pipeline.StartStream();
366
367 std::this_thread::sleep_for(std::chrono::seconds(3));
368 int32_t emptyCheck1 = BufferTracking::IsNodeEmpty(0, "SourceNode");
369 int32_t emptyCheck2 = BufferTracking::IsNodeEmpty(0, "SourceNode", "SinkNode");
370 BufferTraceGraph graph{};
371 BufferTracking::DumpBufferTrace(0, graph);
372 running = false;
373 enqueueThread.join();
374 pipeline.StopStream();
375 stream->StopStream();
376 EXPECT_EQ(true, emptyCheck1 == NODE_IS_NOT_EMPTY);
377 EXPECT_EQ(true, emptyCheck2 == NODE_IS_NOT_EMPTY);
378 EXPECT_EQ(true, graph.size() == 10);
379 EXPECT_EQ(true, graph.front().first == "SourceNode");
380 EXPECT_EQ(true, graph.front().second.size() == 3);
381 EXPECT_EQ(true, graph.back().first == "SinkNode");
382 EXPECT_EQ(true, graph.back().second.size() < 2);
383 for (auto it = graph.begin(); it != graph.end(); it++) {
384 CAMERA_LOGI("node [%{public}s] has buffer {", (it->first).c_str());
385 for (auto& b : it->second) {
386 CAMERA_LOGI("%{public}u, ", static_cast<uint32_t>(b.GetFrameNumber()));
387 }
388 CAMERA_LOGI("}");
389 }
390 }
391
392 namespace OHOS::CameraUtest {
393 #ifdef CAMERA_BUILT_ON_OHOS_LITE
Init(const std::shared_ptr<OHOS::Surface> & producer)394 bool BufferManagerTest::Stream::Init(const std::shared_ptr<OHOS::Surface>& producer)
395 {
396 Camera::BufferManager* manager = Camera::BufferManager::GetInstance();
397 if (manager == nullptr) {
398 return false;
399 }
400 bufferPoolId_ = manager->GenerateBufferPoolId();
401 if (bufferPoolId_ == 0) {
402 return false;
403 }
404 bufferPool_ = manager->GetBufferPool(bufferPoolId_);
405 if (bufferPool_ == nullptr) {
406 return false;
407 }
408 RetCode rc = RC_ERROR;
409 if (producer == nullptr) {
410 rc = bufferPool_->Init(width_, height_, usage_, format_, queueSize_, CAMERA_BUFFER_SOURCE_TYPE_HEAP);
411 CAMERA_LOGI("init inner buffer loop");
412 }
413 if (producer_ != nullptr) {
414 producer_->SetQueueSize(queueSize_);
415 if (producer_->GetQueueSize() != queueSize_) {
416 return false;
417 }
418 producer_->SetWidthAndHeight(width_, height_);
419 producer_->SetFormat(BufferAdapter::CameraFormatToPixelFormat(format_));
420 producer_->SetStrideAlignment(8); // 8:value of strideAlignment
421 rc = bufferPool_->Init(width_, height_, usage_, format_, queueSize_, CAMERA_BUFFER_SOURCE_TYPE_EXTERNAL);
422 CAMERA_LOGI("init external buffer loop");
423 }
424 if (rc != RC_OK) {
425 return false;
426 }
427
428 return true;
429 }
430 #else
431 bool BufferManagerTest::Stream::Init(sptr<IBufferProducer>& producer)
432 {
433 Camera::BufferManager* manager = Camera::BufferManager::GetInstance();
434 if (manager == nullptr) {
435 return false;
436 }
437 bufferPoolId_ = manager->GenerateBufferPoolId();
438 if (bufferPoolId_ == 0) {
439 return false;
440 }
441 bufferPool_ = manager->GetBufferPool(bufferPoolId_);
442 if (bufferPool_ == nullptr) {
443 return false;
444 }
445 RetCode rc = RC_ERROR;
446 if (producer == nullptr) {
447 rc = bufferPool_->Init(width_, height_, usage_, format_, queueSize_, CAMERA_BUFFER_SOURCE_TYPE_HEAP);
448 CAMERA_LOGI("init inner buffer loop");
449 }
450 if (producer != nullptr) {
451 producer_ = Surface::CreateSurfaceAsProducer(producer);
452 producer_->SetQueueSize(queueSize_);
453 if (producer_->GetQueueSize() != queueSize_) {
454 return false;
455 }
456
457 requestConfig_.width = static_cast<int32_t>(width_);
458 requestConfig_.height = static_cast<int32_t>(height_);
459 requestConfig_.strideAlignment = 8; // 8:value of strideAlignment
460 requestConfig_.format = static_cast<int32_t>(BufferAdapter::CameraFormatToPixelFormat(format_));
461 requestConfig_.usage = static_cast<int32_t>(BufferAdapter::CameraUsageToGrallocUsage(usage_));
462 requestConfig_.timeout = 0;
463 flushConfig_.damage.x = 0;
464 flushConfig_.damage.y = 0;
465 flushConfig_.damage.w = width_;
466 flushConfig_.damage.h = height_;
467 flushConfig_.timestamp = 0;
468 rc = bufferPool_->Init(width_, height_, usage_, format_, queueSize_, CAMERA_BUFFER_SOURCE_TYPE_EXTERNAL);
469 CAMERA_LOGI("init external buffer loop");
470 }
471 if (rc != RC_OK) {
472 return false;
473 }
474
475 return true;
476 }
477 #endif
478
StartInnerStream() const479 void BufferManagerTest::Stream::StartInnerStream() const
480 {
481 if (producer_ != nullptr) {
482 return;
483 }
484 CAMERA_LOGD("start inner buffer loop");
485 return;
486 }
487
StartExternalStream()488 void BufferManagerTest::Stream::StartExternalStream()
489 {
490 if (producer_ == nullptr) {
491 return;
492 }
493
494 for (uint32_t indexOfSize = 0; indexOfSize < queueSize_; indexOfSize++) {
495 #ifdef CAMERA_BUILT_ON_OHOS_LITE
496 OHOS::SurfaceBuffer *sb = nullptr;
497 sb = producer_->RequestBuffer();
498 #else
499 sptr<SurfaceBuffer> sb = nullptr;
500 SurfaceError ret = producer_->RequestBuffer(sb, releaseFence_, requestConfig_);
501 if (ret != SURFACE_ERROR_OK) {
502 continue;
503 }
504 #endif
505 if (sb == nullptr) {
506 continue;
507 }
508 CAMERA_LOGI("request a buffer ...");
509
510 std::shared_ptr<IBuffer> cameraBuffer = std::make_shared<ImageBuffer>(CAMERA_BUFFER_SOURCE_TYPE_EXTERNAL);
511 #ifdef CAMERA_BUILT_ON_OHOS_LITE
512 RetCode rc = BufferAdapter::SurfaceBufferToCameraBuffer(sb, producer_, cameraBuffer);
513 #else
514 RetCode rc = BufferAdapter::SurfaceBufferToCameraBuffer(sb, cameraBuffer);
515 #endif
516 if (rc != RC_OK) {
517 continue;
518 }
519
520 {
521 std::lock_guard<std::mutex> l(lock_);
522 bufferVec_.emplace_back(std::make_pair(sb, cameraBuffer));
523 }
524
525 if (bufferPool_ == nullptr) {
526 continue;
527 }
528 bufferPool_->AddBuffer(cameraBuffer);
529 CAMERA_LOGI("Add buffer ...");
530 }
531
532 CAMERA_LOGD("start external buffer loop");
533
534 return;
535 }
536
StartStream()537 void BufferManagerTest::Stream::StartStream()
538 {
539 if (producer_ == nullptr) {
540 StartInnerStream();
541 return;
542 }
543
544 if (producer_ != nullptr) {
545 StartExternalStream();
546 return;
547 }
548
549 return;
550 }
551
EnqueueBufferNonBlock()552 void BufferManagerTest::Stream::EnqueueBufferNonBlock()
553 {
554 if (producer_ == nullptr) {
555 return;
556 }
557
558 #ifdef CAMERA_BUILT_ON_OHOS_LITE
559 OHOS::SurfaceBuffer *sb = nullptr;
560 sb = producer_->RequestBuffer();
561 #else
562 sptr<SurfaceBuffer> sb = nullptr;
563 SurfaceError ret = producer_->RequestBuffer(sb, releaseFence_, requestConfig_);
564 if (ret != SURFACE_ERROR_OK) {
565 return;
566 }
567 #endif
568 if (sb == nullptr) {
569 return;
570 }
571
572 CAMERA_LOGD("find buffer begin ...");
573 std::shared_ptr<IBuffer> buffer = nullptr;
574 {
575 std::lock_guard<std::mutex> l(lock_);
576 auto it = std::find_if(bufferVec_.begin(), bufferVec_.end(),
577 [sb](const std::pair<OHOS::sptr<OHOS::SurfaceBuffer>, std::shared_ptr<IBuffer>>& b) {
578 return b.first == sb;
579 });
580 if (it != bufferVec_.end()) {
581 buffer = it->second;
582 }
583 }
584 if (buffer == nullptr) {
585 return;
586 }
587 CAMERA_LOGD("find buffer end ...");
588 bufferPool_->AddBuffer(buffer);
589 CAMERA_LOGD("enqueue buffer ...");
590
591 return;
592 }
593
DequeueBuffer(std::shared_ptr<IBuffer> & buffer)594 void BufferManagerTest::Stream::DequeueBuffer(std::shared_ptr<IBuffer>& buffer)
595 {
596 if (buffer == nullptr) {
597 return;
598 }
599
600 if (bufferPool_ == nullptr) {
601 return;
602 }
603
604 CAMERA_LOGD("ready to dequeue buffer ...");
605 bufferPool_->ReturnBuffer(buffer);
606
607 if (producer_ != nullptr) {
608 #ifdef CAMERA_BUILT_ON_OHOS_LITE
609 SurfaceBuffer* surfaceBuffer = nullptr;
610 #else
611 sptr<SurfaceBuffer> surfaceBuffer = nullptr;
612 #endif
613 {
614 std::lock_guard<std::mutex> l(lock_);
615 auto it = std::find_if(bufferVec_.begin(), bufferVec_.end(),
616 [buffer](const std::pair<OHOS::sptr<OHOS::SurfaceBuffer>, std::shared_ptr<IBuffer>>& b) {
617 return b.second == buffer;
618 });
619 if (it != bufferVec_.end()) {
620 surfaceBuffer = it->first;
621 }
622 }
623
624 if (surfaceBuffer == nullptr) {
625 return;
626 }
627
628 #ifdef CAMERA_BUILT_ON_OHOS_LITE
629 int32_t ret = producer_->FlushBuffer(surfaceBuffer);
630 if (ret != 0) {
631 CAMERA_LOGI("flush buffer failed ...");
632 }
633 #else
634 SurfaceError ret = producer_->FlushBuffer(surfaceBuffer, -1, flushConfig_);
635 if (ret != SURFACE_ERROR_OK) {
636 CAMERA_LOGI("flush buffer failed ...");
637 }
638 #endif
639 }
640
641 CAMERA_LOGD("dequeue buffer ...");
642
643 return;
644 }
645
StopStream()646 void BufferManagerTest::Stream::StopStream()
647 {
648 return;
649 }
650
GetBufferPool() const651 std::shared_ptr<IBufferPool> BufferManagerTest::Stream::GetBufferPool() const
652 {
653 return bufferPool_;
654 }
655
AddStream(const std::shared_ptr<Stream> & stream)656 bool BufferManagerTest::Pipeline::AddStream(const std::shared_ptr<Stream>& stream)
657 {
658 std::lock_guard<std::mutex> l(streamLock_);
659 localStream_ = std::make_shared<LocalStream>();
660 if (localStream_ == nullptr) {
661 return false;
662 }
663 localStream_->stream = stream;
664 return true;
665 }
666
StartStream()667 void BufferManagerTest::Pipeline::StartStream()
668 {
669 running = true;
670 CollectBuffers();
671 BuildPipeline();
672 DeliverBuffer();
673
674 BufferTracking::StartTracking();
675 return;
676 }
677
BuildPipeline()678 bool BufferManagerTest::Pipeline::BuildPipeline()
679 {
680 BufferTracking::AddTrackingStreamBegin(0, localStream_->stream->GetPoolId());
681 sourceNode_ = std::make_shared<SourceNode>("SourceNode");
682 if (sourceNode_ == nullptr) {
683 return false;
684 }
685 BufferTracking::AddTrackingNode(0, sourceNode_->GetName());
686 std::shared_ptr<Node> tmpNode = sourceNode_;
687 for (int i = 1; i < 9; i++) { // 9: numbers of node
688 std::string name = "node";
689 name += std::to_string(i);
690 auto n = std::make_shared<Node>(name);
691 tmpNode->Connect(n);
692 tmpNode = n;
693 BufferTracking::AddTrackingNode(0, tmpNode->GetName());
694 }
695
696 auto sinkNode = std::make_shared<SinkNode>(std::string("SinkNode"));
697 if (sinkNode == nullptr) {
698 return false;
699 }
700 sinkNode->BindCallback([this](std::shared_ptr<IBuffer>& buffer) { localStream_->stream->DequeueBuffer(buffer); });
701 std::shared_ptr<Node> node = sinkNode;
702 tmpNode->Connect(node);
703 BufferTracking::AddTrackingNode(0, sinkNode->GetName());
704 BufferTracking::AddTrackingStreamEnd(0);
705
706 return true;
707 }
708
CollectBuffers()709 void BufferManagerTest::Pipeline::CollectBuffers()
710 {
711 collectThread_ = new std::thread([this] {
712 while (running == true) {
713 auto bufferPool = localStream_->stream->GetBufferPool();
714 if (bufferPool == nullptr) {
715 continue;
716 }
717 auto buffer = bufferPool->AcquireBuffer(3); // 3:Minimum number of buffer rotation
718 if (buffer == nullptr) {
719 continue;
720 }
721
722 std::lock_guard<std::mutex> deviceL(localStream_->deviceLock);
723 localStream_->deviceBufferList.emplace_back(buffer);
724 }
725 });
726
727 return;
728 }
729
DeliverBuffer(std::shared_ptr<IBuffer> & buffer)730 void BufferManagerTest::Pipeline::DeliverBuffer(std::shared_ptr<IBuffer>& buffer)
731 {
732 buffer->SetFrameNumber(frameNumber_++);
733 CAMERA_LOGD("deliver buffer : %{public}llu", static_cast<uint64_t>(frameNumber_));
734 sourceNode_->Receive(buffer);
735 return;
736 }
737
DeliverBuffer()738 void BufferManagerTest::Pipeline::DeliverBuffer()
739 {
740 localStream_->deliverThread = new std::thread([this] {
741 while (running == true) {
742 std::this_thread::sleep_for(std::chrono::microseconds(FRAME_INTERVAL_US));
743 std::shared_ptr<IBuffer> buffer = nullptr;
744 {
745 CAMERA_LOGI("load device buffer ...");
746 std::lock_guard<std::mutex> l(localStream_->deviceLock);
747 if (localStream_->deviceBufferList.empty()) {
748 continue;
749 }
750 buffer = localStream_->deviceBufferList.front();
751 localStream_->deviceBufferList.pop_front();
752 }
753 DeliverBuffer(buffer);
754 }
755 });
756
757 return;
758 }
759
StopStream()760 void BufferManagerTest::Pipeline::StopStream()
761 {
762 running = false;
763 if (collectThread_ != nullptr) {
764 collectThread_->join();
765 }
766
767 CHECK_IF_PTR_NULL_RETURN_VOID(localStream_);
768 if (localStream_->deliverThread != nullptr) {
769 localStream_->deliverThread->join();
770 }
771
772 BufferTracking::DeleteTrackingStream(0);
773 BufferTracking::StopTracking();
774 return;
775 }
776
Connect(std::shared_ptr<Node> & nextNode)777 void BufferManagerTest::Node::Connect(std::shared_ptr<Node>& nextNode)
778 {
779 nextNode_ = nextNode;
780 return;
781 }
782
Deliver(std::shared_ptr<IBuffer> & buffer)783 void BufferManagerTest::Node::Deliver(std::shared_ptr<IBuffer>& buffer)
784 {
785 if (nextNode_ == nullptr) {
786 return;
787 }
788 nextNode_->Receive(buffer);
789 return;
790 }
791
Receive(std::shared_ptr<IBuffer> & buffer)792 void BufferManagerTest::Node::Receive(std::shared_ptr<IBuffer>& buffer)
793 {
794 CAMERA_LOGD("report buffer location to node: %{public}s", name_.c_str());
795 PIPELINE_REPORT_BUFFER_LOCATION(0, buffer->GetFrameNumber(), name_);
796 Process(buffer);
797 return;
798 }
799
GetName() const800 std::string BufferManagerTest::Node::GetName() const
801 {
802 return name_;
803 }
804
Process(std::shared_ptr<IBuffer> & buffer)805 void BufferManagerTest::Node::Process(std::shared_ptr<IBuffer>& buffer)
806 {
807 std::this_thread::sleep_for(std::chrono::microseconds(5000)); // 5000:microsecond
808 Deliver(buffer);
809 return;
810 }
811
BindCallback(const std::function<void (std::shared_ptr<IBuffer> &)> & func)812 void BufferManagerTest::SinkNode::BindCallback(const std::function<void(std::shared_ptr<IBuffer>&)>& func)
813 {
814 callback_ = func;
815 return;
816 }
817
Deliver(std::shared_ptr<IBuffer> & buffer)818 void BufferManagerTest::SinkNode::Deliver(std::shared_ptr<IBuffer>& buffer)
819 {
820 if (callback_ == nullptr) {
821 return;
822 }
823 callback_(buffer);
824 return;
825 }
826
Process(std::shared_ptr<IBuffer> & buffer)827 void BufferManagerTest::SourceNode::Process(std::shared_ptr<IBuffer>& buffer)
828 {
829 if (cacheSize_ > 0) {
830 cache_.emplace_back(buffer);
831 cacheSize_--;
832 return;
833 }
834
835 if (cache_.empty()) {
836 Deliver(buffer);
837 return;
838 }
839
840 auto b = cache_.front();
841 cache_.pop_front();
842 cache_.emplace_back(buffer);
843 Deliver(b);
844
845 return;
846 }
847 } // namespace OHOS::CameraUtest
848
849