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