blob: 5e324821bbe191c20d2e0ad715fcc63025dc139b [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
Jim Shargo900ed6a2024-07-03 04:59:14 +000020#include <android/hardware_buffer.h>
Jim Shargo2e0202f2024-07-30 19:54:43 +000021#include <com_android_graphics_libgui_flags.h>
Jim Shargoc50928e2024-07-03 05:00:43 +000022#include <com_android_internal_camera_flags.h>
Jim Shargo900ed6a2024-07-03 04:59:14 +000023#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
Jim Shargoc50928e2024-07-03 05:00:43 +000037#include "../device3/Flags.h"
38
39#if USE_NEW_STREAM_SPLITTER
40#include "../device3/Camera3StreamSplitter.h"
41#else
42#include "../device3/deprecated/DeprecatedCamera3StreamSplitter.h"
43#endif // USE_NEW_STREAM_SPLITTER
44
Jim Shargo900ed6a2024-07-03 04:59:14 +000045using namespace android;
46
47namespace {
48
49uint64_t kConsumerUsage = AHARDWAREBUFFER_USAGE_CAMERA_READ;
50uint64_t kProducerUsage = AHARDWAREBUFFER_USAGE_CAMERA_READ;
51size_t kHalMaxBuffers = 3;
52uint32_t kWidth = 640;
53uint32_t kHeight = 480;
54PixelFormat kFormat = HAL_PIXEL_FORMAT_YCBCR_420_888;
55int64_t kDynamicRangeProfile = 0;
56
57std::tuple<sp<BufferItemConsumer>, sp<Surface>> createConsumerAndSurface() {
Jim Shargo2e0202f2024-07-30 19:54:43 +000058#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
59 sp<BufferItemConsumer> consumer = sp<BufferItemConsumer>::make(kConsumerUsage);
60 return {consumer, consumer->getSurface()};
61#else
Jim Shargo900ed6a2024-07-03 04:59:14 +000062 sp<IGraphicBufferProducer> producer;
63 sp<IGraphicBufferConsumer> consumer;
64 BufferQueue::createBufferQueue(&producer, &consumer);
65
66 return {sp<BufferItemConsumer>::make(consumer, kConsumerUsage), sp<Surface>::make(producer)};
Jim Shargo2e0202f2024-07-30 19:54:43 +000067#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
Jim Shargo900ed6a2024-07-03 04:59:14 +000068}
69
70class Camera3StreamSplitterTest : public testing::Test {
71 public:
Jim Shargoc50928e2024-07-03 05:00:43 +000072 void SetUp() override {
73#if USE_NEW_STREAM_SPLITTER
74 mSplitter = sp<Camera3StreamSplitter>::make();
75#else
76 mSplitter = sp<DeprecatedCamera3StreamSplitter>::make();
77#endif // USE_NEW_STREAM_SPLITTER
78 }
Jim Shargo900ed6a2024-07-03 04:59:14 +000079
80 protected:
Jim Shargoc50928e2024-07-03 05:00:43 +000081#if USE_NEW_STREAM_SPLITTER
Jim Shargo900ed6a2024-07-03 04:59:14 +000082 sp<Camera3StreamSplitter> mSplitter;
Jim Shargoc50928e2024-07-03 05:00:43 +000083#else
84 sp<DeprecatedCamera3StreamSplitter> mSplitter;
85#endif // USE_NEW_STREAM_SPLITTER
Jim Shargo900ed6a2024-07-03 04:59:14 +000086};
87
88class TestSurfaceListener : public SurfaceListener {
89 public:
90 virtual void onBufferReleased() override { mNumBuffersReleased++; }
91 virtual bool needsReleaseNotify() { return true; }
92 virtual void onBufferDetached(int) override {}
93 virtual void onBuffersDiscarded(const std::vector<sp<GraphicBuffer>>&) override {};
94
95 uint32_t mNumBuffersReleased = 0;
96};
97
98class TestConsumerListener : public BufferItemConsumer::FrameAvailableListener {
99 public:
100 TestConsumerListener(const wp<BufferItemConsumer>& consumer) : mConsumer(consumer) {}
101
102 virtual void onFrameAvailable(const BufferItem&) {
103 sp<BufferItemConsumer> consumer = mConsumer.promote();
104 EXPECT_NE(nullptr, consumer);
105
106 BufferItem item;
107 EXPECT_EQ(OK, consumer->acquireBuffer(&item, 0));
108 mNumBuffersAcquired++;
109 EXPECT_EQ(OK, consumer->releaseBuffer(item, Fence::NO_FENCE));
110 }
111 virtual void onFrameReplaced(const BufferItem&) {}
112 virtual void onFrameDequeued(const uint64_t) {}
113 virtual void onFrameCancelled(const uint64_t) {}
114 virtual void onFrameDetached(const uint64_t) {}
115
116 wp<BufferItemConsumer> mConsumer;
117 uint32_t mNumBuffersAcquired = 0;
118};
119
120} // namespace
121
Jim Shargoc50928e2024-07-03 05:00:43 +0000122TEST_F(Camera3StreamSplitterTest, WithoutSurfaces_NoBuffersConsumed) {
Jim Shargo900ed6a2024-07-03 04:59:14 +0000123 sp<Surface> consumer;
124 EXPECT_EQ(OK, mSplitter->connect({}, kConsumerUsage, kProducerUsage, kHalMaxBuffers, kWidth,
125 kHeight, kFormat, &consumer, kDynamicRangeProfile));
126
127 sp<TestSurfaceListener> surfaceListener = sp<TestSurfaceListener>::make();
Carlos Martinez Romero4383a1a2024-07-22 09:46:53 -0700128 EXPECT_EQ(OK, consumer->connect(NATIVE_WINDOW_API_CAMERA, surfaceListener, false));
Jim Shargo900ed6a2024-07-03 04:59:14 +0000129
130 sp<GraphicBuffer> buffer = new GraphicBuffer(kWidth, kHeight, kFormat, kProducerUsage);
131 EXPECT_EQ(OK, consumer->attachBuffer(buffer->getNativeBuffer()));
132 // TODO: Do this with the surface itself once the API is available.
133 EXPECT_EQ(OK,
134 ANativeWindow_queueBuffer(consumer.get(), buffer->getNativeBuffer(), /*fenceFd*/ -1));
135
136 EXPECT_EQ(0u, surfaceListener->mNumBuffersReleased);
137}
138
139TEST_F(Camera3StreamSplitterTest, TestProcessSingleBuffer) {
140 //
141 // Set up output consumers:
142 //
143 constexpr auto kSurfaceId1 = 1;
144 auto [bufferItemConsumer1, surface1] = createConsumerAndSurface();
145 sp<TestConsumerListener> consumerListener1 =
146 sp<TestConsumerListener>::make(bufferItemConsumer1);
147 bufferItemConsumer1->setFrameAvailableListener(consumerListener1);
148
149 constexpr auto kSurfaceId2 = 2;
150 auto [bufferItemConsumer2, surface2] = createConsumerAndSurface();
151 sp<TestConsumerListener> consumerListener2 =
152 sp<TestConsumerListener>::make(bufferItemConsumer2);
153 bufferItemConsumer2->setFrameAvailableListener(consumerListener2);
154
155 //
156 // Connect it to the splitter, get the input surface, and set it up:
157 //
158 sp<Surface> inputSurface;
159 EXPECT_EQ(OK, mSplitter->connect({{kSurfaceId1, surface1}, {kSurfaceId2, surface2}},
160 kConsumerUsage, kProducerUsage, kHalMaxBuffers, kWidth,
161 kHeight, kFormat, &inputSurface, kDynamicRangeProfile));
162 sp<TestSurfaceListener> surfaceListener = sp<TestSurfaceListener>::make();
Carlos Martinez Romero4383a1a2024-07-22 09:46:53 -0700163 EXPECT_EQ(OK, inputSurface->connect(NATIVE_WINDOW_API_CAMERA, surfaceListener, false));
Jim Shargo900ed6a2024-07-03 04:59:14 +0000164 // TODO: Do this with the surface itself once the API is available.
165 EXPECT_EQ(OK, inputSurface->getIGraphicBufferProducer()->allowAllocation(false));
166
167 //
168 // Create a buffer to use:
169 //
170 sp<GraphicBuffer> singleBuffer = new GraphicBuffer(kWidth, kHeight, kFormat, kProducerUsage);
171 EXPECT_NE(nullptr, singleBuffer);
172 mSplitter->attachBufferToOutputs(singleBuffer->getNativeBuffer(), {kSurfaceId1, kSurfaceId2});
173
174 //
175 // Verify that when we attach the buffer, it's processed appropriately:
176 //
177 EXPECT_EQ(OK, inputSurface->attachBuffer(singleBuffer->getNativeBuffer()));
178 EXPECT_EQ(OK, mSplitter->getOnFrameAvailableResult());
179 // TODO: Do this with the surface itself once the API is available.
180 EXPECT_EQ(OK, ANativeWindow_queueBuffer(inputSurface.get(), singleBuffer->getNativeBuffer(),
181 /*fenceFd*/ -1));
182
183 EXPECT_EQ(1u, consumerListener1->mNumBuffersAcquired);
184 EXPECT_EQ(1u, consumerListener2->mNumBuffersAcquired);
185 EXPECT_EQ(1u, surfaceListener->mNumBuffersReleased);
186}