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