blob: 1ddf42a199d32031a033df2bfff0681cf316d2f5 [file] [log] [blame]
Jim Shargo900ed6a2024-07-03 04:59:14 +00001/*
2 * Copyright (C) 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "Camera3StreamSplitterTest"
18// #define LOG_NDEBUG 0
19
20#include "../device3/Camera3StreamSplitter.h"
21
22#include <android/hardware_buffer.h>
23#include <gui/BufferItemConsumer.h>
24#include <gui/IGraphicBufferConsumer.h>
25#include <gui/IGraphicBufferProducer.h>
26#include <gui/Surface.h>
27#include <ui/Fence.h>
28#include <ui/GraphicBuffer.h>
29#include <ui/GraphicBufferAllocator.h>
30#include <ui/PixelFormat.h>
31
32#include <system/window.h>
33#include <vndk/window.h>
34
35#include <gtest/gtest.h>
36
37using namespace android;
38
39namespace {
40
41uint64_t kConsumerUsage = AHARDWAREBUFFER_USAGE_CAMERA_READ;
42uint64_t kProducerUsage = AHARDWAREBUFFER_USAGE_CAMERA_READ;
43size_t kHalMaxBuffers = 3;
44uint32_t kWidth = 640;
45uint32_t kHeight = 480;
46PixelFormat kFormat = HAL_PIXEL_FORMAT_YCBCR_420_888;
47int64_t kDynamicRangeProfile = 0;
48
49std::tuple<sp<BufferItemConsumer>, sp<Surface>> createConsumerAndSurface() {
50 sp<IGraphicBufferProducer> producer;
51 sp<IGraphicBufferConsumer> consumer;
52 BufferQueue::createBufferQueue(&producer, &consumer);
53
54 return {sp<BufferItemConsumer>::make(consumer, kConsumerUsage), sp<Surface>::make(producer)};
55}
56
57class Camera3StreamSplitterTest : public testing::Test {
58 public:
59 void SetUp() override { mSplitter = sp<Camera3StreamSplitter>::make(); }
60
61 protected:
62 sp<Camera3StreamSplitter> mSplitter;
63};
64
65class TestSurfaceListener : public SurfaceListener {
66 public:
67 virtual void onBufferReleased() override { mNumBuffersReleased++; }
68 virtual bool needsReleaseNotify() { return true; }
69 virtual void onBufferDetached(int) override {}
70 virtual void onBuffersDiscarded(const std::vector<sp<GraphicBuffer>>&) override {};
71
72 uint32_t mNumBuffersReleased = 0;
73};
74
75class TestConsumerListener : public BufferItemConsumer::FrameAvailableListener {
76 public:
77 TestConsumerListener(const wp<BufferItemConsumer>& consumer) : mConsumer(consumer) {}
78
79 virtual void onFrameAvailable(const BufferItem&) {
80 sp<BufferItemConsumer> consumer = mConsumer.promote();
81 EXPECT_NE(nullptr, consumer);
82
83 BufferItem item;
84 EXPECT_EQ(OK, consumer->acquireBuffer(&item, 0));
85 mNumBuffersAcquired++;
86 EXPECT_EQ(OK, consumer->releaseBuffer(item, Fence::NO_FENCE));
87 }
88 virtual void onFrameReplaced(const BufferItem&) {}
89 virtual void onFrameDequeued(const uint64_t) {}
90 virtual void onFrameCancelled(const uint64_t) {}
91 virtual void onFrameDetached(const uint64_t) {}
92
93 wp<BufferItemConsumer> mConsumer;
94 uint32_t mNumBuffersAcquired = 0;
95};
96
97} // namespace
98
99TEST_F(Camera3StreamSplitterTest, TestWithoutSurfaces_NoBuffersConsumed) {
100 sp<Surface> consumer;
101 EXPECT_EQ(OK, mSplitter->connect({}, kConsumerUsage, kProducerUsage, kHalMaxBuffers, kWidth,
102 kHeight, kFormat, &consumer, kDynamicRangeProfile));
103
104 sp<TestSurfaceListener> surfaceListener = sp<TestSurfaceListener>::make();
105 EXPECT_EQ(OK, consumer->connect(NATIVE_WINDOW_API_CAMERA, false, surfaceListener));
106
107 sp<GraphicBuffer> buffer = new GraphicBuffer(kWidth, kHeight, kFormat, kProducerUsage);
108 EXPECT_EQ(OK, consumer->attachBuffer(buffer->getNativeBuffer()));
109 // TODO: Do this with the surface itself once the API is available.
110 EXPECT_EQ(OK,
111 ANativeWindow_queueBuffer(consumer.get(), buffer->getNativeBuffer(), /*fenceFd*/ -1));
112
113 EXPECT_EQ(0u, surfaceListener->mNumBuffersReleased);
114}
115
116TEST_F(Camera3StreamSplitterTest, TestProcessSingleBuffer) {
117 //
118 // Set up output consumers:
119 //
120 constexpr auto kSurfaceId1 = 1;
121 auto [bufferItemConsumer1, surface1] = createConsumerAndSurface();
122 sp<TestConsumerListener> consumerListener1 =
123 sp<TestConsumerListener>::make(bufferItemConsumer1);
124 bufferItemConsumer1->setFrameAvailableListener(consumerListener1);
125
126 constexpr auto kSurfaceId2 = 2;
127 auto [bufferItemConsumer2, surface2] = createConsumerAndSurface();
128 sp<TestConsumerListener> consumerListener2 =
129 sp<TestConsumerListener>::make(bufferItemConsumer2);
130 bufferItemConsumer2->setFrameAvailableListener(consumerListener2);
131
132 //
133 // Connect it to the splitter, get the input surface, and set it up:
134 //
135 sp<Surface> inputSurface;
136 EXPECT_EQ(OK, mSplitter->connect({{kSurfaceId1, surface1}, {kSurfaceId2, surface2}},
137 kConsumerUsage, kProducerUsage, kHalMaxBuffers, kWidth,
138 kHeight, kFormat, &inputSurface, kDynamicRangeProfile));
139 sp<TestSurfaceListener> surfaceListener = sp<TestSurfaceListener>::make();
140 EXPECT_EQ(OK, inputSurface->connect(NATIVE_WINDOW_API_CAMERA, false, surfaceListener));
141 // TODO: Do this with the surface itself once the API is available.
142 EXPECT_EQ(OK, inputSurface->getIGraphicBufferProducer()->allowAllocation(false));
143
144 //
145 // Create a buffer to use:
146 //
147 sp<GraphicBuffer> singleBuffer = new GraphicBuffer(kWidth, kHeight, kFormat, kProducerUsage);
148 EXPECT_NE(nullptr, singleBuffer);
149 mSplitter->attachBufferToOutputs(singleBuffer->getNativeBuffer(), {kSurfaceId1, kSurfaceId2});
150
151 //
152 // Verify that when we attach the buffer, it's processed appropriately:
153 //
154 EXPECT_EQ(OK, inputSurface->attachBuffer(singleBuffer->getNativeBuffer()));
155 EXPECT_EQ(OK, mSplitter->getOnFrameAvailableResult());
156 // TODO: Do this with the surface itself once the API is available.
157 EXPECT_EQ(OK, ANativeWindow_queueBuffer(inputSurface.get(), singleBuffer->getNativeBuffer(),
158 /*fenceFd*/ -1));
159
160 EXPECT_EQ(1u, consumerListener1->mNumBuffersAcquired);
161 EXPECT_EQ(1u, consumerListener2->mNumBuffersAcquired);
162 EXPECT_EQ(1u, surfaceListener->mNumBuffersReleased);
163}