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
29using namespace OHOS;
30using namespace OHOS::CameraUtest;
31using namespace testing::ext;
32
33namespace {
34    const int FRAME_INTERVAL_US = 33000; // 33ms
35    const int FRAME_RUN_TIME_S = 3;      // 3s
36}
37
38void BufferManagerTest::SetUpTestCase(void)
39{
40    CAMERA_LOGD("Camera::BufferManager SetUpTestCase");
41}
42
43void BufferManagerTest::TearDownTestCase(void)
44{
45    CAMERA_LOGD("Camera::BufferManager TearDownTestCase");
46}
47
48void BufferManagerTest::SetUp(void)
49{
50    CAMERA_LOGD("Camera::BufferManager SetUp");
51}
52
53void BufferManagerTest::TearDown(void)
54{
55    CAMERA_LOGD("Camera::BufferManager TearDown..");
56}
57
58HWTEST_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());
64    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);
82    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
107    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
124HWTEST_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;
133    std::thread user1([&manager, &bufferPool1, &bufferPoolId] { bufferPool1 = manager->GetBufferPool(bufferPoolId); });
134
135    std::shared_ptr<IBufferPool> bufferPool2 = nullptr;
136    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
153HWTEST_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
191HWTEST_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
214HWTEST_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();
252    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
267HWTEST_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;
291    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;
306    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    });
315    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
344HWTEST_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
360    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
392namespace OHOS::CameraUtest {
393#ifdef CAMERA_BUILT_ON_OHOS_LITE
394bool 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
431bool 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
479void BufferManagerTest::Stream::StartInnerStream() const
480{
481    if (producer_ != nullptr) {
482        return;
483    }
484    CAMERA_LOGD("start inner buffer loop");
485    return;
486}
487
488void 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
537void 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
552void 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
594void 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
646void BufferManagerTest::Stream::StopStream()
647{
648    return;
649}
650
651std::shared_ptr<IBufferPool> BufferManagerTest::Stream::GetBufferPool() const
652{
653    return bufferPool_;
654}
655
656bool 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
667void BufferManagerTest::Pipeline::StartStream()
668{
669    running = true;
670    CollectBuffers();
671    BuildPipeline();
672    DeliverBuffer();
673
674    BufferTracking::StartTracking();
675    return;
676}
677
678bool 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
709void 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
730void 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
738void 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
760void 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
777void BufferManagerTest::Node::Connect(std::shared_ptr<Node>& nextNode)
778{
779    nextNode_ = nextNode;
780    return;
781}
782
783void BufferManagerTest::Node::Deliver(std::shared_ptr<IBuffer>& buffer)
784{
785    if (nextNode_ == nullptr) {
786        return;
787    }
788    nextNode_->Receive(buffer);
789    return;
790}
791
792void 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
800std::string BufferManagerTest::Node::GetName() const
801{
802    return name_;
803}
804
805void 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
812void BufferManagerTest::SinkNode::BindCallback(const std::function<void(std::shared_ptr<IBuffer>&)>& func)
813{
814    callback_ = func;
815    return;
816}
817
818void BufferManagerTest::SinkNode::Deliver(std::shared_ptr<IBuffer>& buffer)
819{
820    if (callback_ == nullptr) {
821        return;
822    }
823    callback_(buffer);
824    return;
825}
826
827void 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