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());
__anon003b7ddb0202null63 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);
__anon003b7ddb0302null80 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
__anon003b7ddb0402null105 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;
__anon003b7ddb0502null131 std::thread user1([&manager, &bufferPool1, &bufferPoolId] { bufferPool1 = manager->GetBufferPool(bufferPoolId); });
132
133 std::shared_ptr<IBufferPool> bufferPool2 = nullptr;
__anon003b7ddb0602null134 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 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();
__anon003b7ddb0702null250 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;
__anon003b7ddb0802null289 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;
__anon003b7ddb0902null304 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 });
__anon003b7ddb0a02null313 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
__anon003b7ddb0b02null358 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(std::shared_ptr<OHOS::Surface> & producer)392 bool BufferManagerTest::Stream::Init(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 for (auto& it : bufferVec_) {
575 if (it.first == sb) {
576 buffer = it.second;
577 break;
578 }
579 }
580 }
581 if (buffer == nullptr) {
582 return;
583 }
584 std::cout << "find buffer end ..." << std::endl;
585 bufferPool_->AddBuffer(buffer);
586 std::cout << "enqueue buffer ..." << std::endl;
587
588 return;
589 }
590
DequeueBuffer(std::shared_ptr<IBuffer> & buffer)591 void BufferManagerTest::Stream::DequeueBuffer(std::shared_ptr<IBuffer>& buffer)
592 {
593 if (buffer == nullptr) {
594 return;
595 }
596
597 if (bufferPool_ == nullptr) {
598 return;
599 }
600
601 std::cout << "ready to dequeue buffer ..." << std::endl;
602 bufferPool_->ReturnBuffer(buffer);
603
604 if (producer_ != nullptr) {
605 #ifdef CAMERA_BUILT_ON_OHOS_LITE
606 SurfaceBuffer* surfaceBuffer = nullptr;
607 #else
608 sptr<SurfaceBuffer> surfaceBuffer = nullptr;
609 #endif
610 {
611 std::lock_guard<std::mutex> l(lock_);
612 for (auto& it : bufferVec_) {
613 if (it.second == buffer) {
614 surfaceBuffer = it.first;
615 break;
616 }
617 }
618 }
619
620 if (surfaceBuffer == nullptr) {
621 return;
622 }
623
624 #ifdef CAMERA_BUILT_ON_OHOS_LITE
625 int32_t ret = producer_->FlushBuffer(surfaceBuffer);
626 if (ret != 0) {
627 std::cout << "flush buffer failed ..." << std::endl;
628 }
629 #else
630 SurfaceError ret = producer_->FlushBuffer(surfaceBuffer, -1, flushConfig_);
631 if (ret != SURFACE_ERROR_OK) {
632 std::cout << "flush buffer failed ..." << std::endl;
633 }
634 #endif
635 }
636
637 std::cout << "dequeue buffer ..." << std::endl;
638
639 return;
640 }
641
StopStream()642 void BufferManagerTest::Stream::StopStream()
643 {
644 return;
645 }
646
GetBufferPool() const647 std::shared_ptr<IBufferPool> BufferManagerTest::Stream::GetBufferPool() const
648 {
649 return bufferPool_;
650 }
651
AddStream(std::shared_ptr<Stream> & stream)652 bool BufferManagerTest::Pipeline::AddStream(std::shared_ptr<Stream>& stream)
653 {
654 std::lock_guard<std::mutex> l(streamLock_);
655 localStream_ = std::make_shared<LocalStream>();
656 if (localStream_ == nullptr) {
657 return false;
658 }
659 localStream_->stream = stream;
660 return true;
661 }
662
StartStream()663 void BufferManagerTest::Pipeline::StartStream()
664 {
665 running = true;
666 CollectBuffers();
667 BuildPipeline();
668 DeliverBuffer();
669
670 BufferTracking::StartTracking();
671 return;
672 }
673
BuildPipeline()674 bool BufferManagerTest::Pipeline::BuildPipeline()
675 {
676 BufferTracking::AddTrackingStreamBegin(0, localStream_->stream->GetPoolId());
677 sourceNode_ = std::make_shared<SourceNode>("SourceNode");
678 if (sourceNode_ == nullptr) {
679 return false;
680 }
681 BufferTracking::AddTrackingNode(0, sourceNode_->GetName());
682 std::shared_ptr<Node> tmpNode = sourceNode_;
683 for (int i = 1; i < 9; i++) { // 9: numbers of node
684 std::string name = "node";
685 name += std::to_string(i);
686 auto n = std::make_shared<Node>(name);
687 tmpNode->Connect(n);
688 tmpNode = n;
689 BufferTracking::AddTrackingNode(0, tmpNode->GetName());
690 }
691
692 auto sinkNode = std::make_shared<SinkNode>(std::string("SinkNode"));
693 if (sinkNode == nullptr) {
694 return false;
695 }
696 sinkNode->BindCallback([this](std::shared_ptr<IBuffer>& buffer) { localStream_->stream->DequeueBuffer(buffer); });
697 std::shared_ptr<Node> node = sinkNode;
698 tmpNode->Connect(node);
699 BufferTracking::AddTrackingNode(0, sinkNode->GetName());
700 BufferTracking::AddTrackingStreamEnd(0);
701
702 return true;
703 }
704
CollectBuffers()705 void BufferManagerTest::Pipeline::CollectBuffers()
706 {
707 collectThread_ = new std::thread([this] {
708 while (running == true) {
709 auto bufferPool = localStream_->stream->GetBufferPool();
710 if (bufferPool == nullptr) {
711 continue;
712 }
713 auto buffer = bufferPool->AcquireBuffer(3); // 3:Minimum number of buffer rotation
714 if (buffer == nullptr) {
715 continue;
716 }
717
718 std::lock_guard<std::mutex> deviceL(localStream_->deviceLock);
719 localStream_->deviceBufferList.emplace_back(buffer);
720 }
721 });
722
723 return;
724 }
725
DeliverBuffer(std::shared_ptr<IBuffer> & buffer)726 void BufferManagerTest::Pipeline::DeliverBuffer(std::shared_ptr<IBuffer>& buffer)
727 {
728 buffer->SetFrameNumber(frameNumber_++);
729 std::cout << "deliver buffer : " << static_cast<uint64_t>(frameNumber_) << std::endl;
730 sourceNode_->Receive(buffer);
731 return;
732 }
733
DeliverBuffer()734 void BufferManagerTest::Pipeline::DeliverBuffer()
735 {
736 localStream_->deliverThread = new std::thread([this] {
737 while (running == true) {
738 std::this_thread::sleep_for(std::chrono::microseconds(FRAME_INTERVAL_US));
739 std::shared_ptr<IBuffer> buffer = nullptr;
740 {
741 std::cout << "load device buffer ..." << std::endl;
742 std::lock_guard<std::mutex> l(localStream_->deviceLock);
743 if (localStream_->deviceBufferList.empty()) {
744 continue;
745 }
746 buffer = localStream_->deviceBufferList.front();
747 localStream_->deviceBufferList.pop_front();
748 }
749 DeliverBuffer(buffer);
750 }
751 });
752
753 return;
754 }
755
StopStream()756 void BufferManagerTest::Pipeline::StopStream()
757 {
758 running = false;
759 collectThread_->join();
760
761 localStream_->deliverThread->join();
762
763 BufferTracking::DeleteTrackingStream(0);
764 BufferTracking::StopTracking();
765 return;
766 }
767
Connect(std::shared_ptr<Node> & nextNode)768 void BufferManagerTest::Node::Connect(std::shared_ptr<Node>& nextNode)
769 {
770 nextNode_ = nextNode;
771 return;
772 }
773
Deliver(std::shared_ptr<IBuffer> & buffer)774 void BufferManagerTest::Node::Deliver(std::shared_ptr<IBuffer>& buffer)
775 {
776 if (nextNode_ == nullptr) {
777 return;
778 }
779 nextNode_->Receive(buffer);
780 return;
781 }
782
Receive(std::shared_ptr<IBuffer> & buffer)783 void BufferManagerTest::Node::Receive(std::shared_ptr<IBuffer>& buffer)
784 {
785 std::cout << "report buffer location to node: " << name_ << std::endl;
786 PIPELINE_REPORT_BUFFER_LOCATION(0, buffer->GetFrameNumber(), name_);
787 Process(buffer);
788 return;
789 }
790
GetName() const791 std::string BufferManagerTest::Node::GetName() const
792 {
793 return name_;
794 }
795
Process(std::shared_ptr<IBuffer> & buffer)796 void BufferManagerTest::Node::Process(std::shared_ptr<IBuffer>& buffer)
797 {
798 std::this_thread::sleep_for(std::chrono::microseconds(5000)); // 5000:microsecond
799 Deliver(buffer);
800 return;
801 }
802
BindCallback(const std::function<void (std::shared_ptr<IBuffer> &)> & func)803 void BufferManagerTest::SinkNode::BindCallback(const std::function<void(std::shared_ptr<IBuffer>&)>& func)
804 {
805 callback_ = func;
806 return;
807 }
808
Deliver(std::shared_ptr<IBuffer> & buffer)809 void BufferManagerTest::SinkNode::Deliver(std::shared_ptr<IBuffer>& buffer)
810 {
811 if (callback_ == nullptr) {
812 return;
813 }
814 callback_(buffer);
815 return;
816 }
817
Process(std::shared_ptr<IBuffer> & buffer)818 void BufferManagerTest::SourceNode::Process(std::shared_ptr<IBuffer>& buffer)
819 {
820 if (cacheSize_ > 0) {
821 cache_.emplace_back(buffer);
822 cacheSize_--;
823 return;
824 }
825
826 if (cache_.empty()) {
827 Deliver(buffer);
828 return;
829 }
830
831 auto b = cache_.front();
832 cache_.pop_front();
833 cache_.emplace_back(buffer);
834 Deliver(b);
835
836 return;
837 }
838 } // namespace OHOS::CameraUtest
839
840