• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014 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 "StreamSplitter_test"
18 //#define LOG_NDEBUG 0
19 
20 #include <gui/BufferQueue.h>
21 #include <gui/IConsumerListener.h>
22 #include <gui/ISurfaceComposer.h>
23 #include <gui/StreamSplitter.h>
24 #include <private/gui/ComposerService.h>
25 
26 #include <gtest/gtest.h>
27 
28 namespace android {
29 
30 class StreamSplitterTest : public ::testing::Test {
31 
32 protected:
StreamSplitterTest()33     StreamSplitterTest() {
34         const ::testing::TestInfo* const testInfo =
35             ::testing::UnitTest::GetInstance()->current_test_info();
36         ALOGV("Begin test: %s.%s", testInfo->test_case_name(),
37                 testInfo->name());
38     }
39 
~StreamSplitterTest()40     ~StreamSplitterTest() {
41         const ::testing::TestInfo* const testInfo =
42             ::testing::UnitTest::GetInstance()->current_test_info();
43         ALOGV("End test:   %s.%s", testInfo->test_case_name(),
44                 testInfo->name());
45     }
46 };
47 
48 struct DummyListener : public BnConsumerListener {
onFrameAvailableandroid::DummyListener49     virtual void onFrameAvailable(const BufferItem& /* item */) {}
onBuffersReleasedandroid::DummyListener50     virtual void onBuffersReleased() {}
onSidebandStreamChangedandroid::DummyListener51     virtual void onSidebandStreamChanged() {}
52 };
53 
54 class CountedAllocator : public BnGraphicBufferAlloc {
55 public:
CountedAllocator()56     CountedAllocator() : mAllocCount(0) {
57         sp<ISurfaceComposer> composer(ComposerService::getComposerService());
58         mAllocator = composer->createGraphicBufferAlloc();
59     }
60 
~CountedAllocator()61     virtual ~CountedAllocator() {}
62 
createGraphicBuffer(uint32_t w,uint32_t h,PixelFormat format,uint32_t usage,status_t * error)63     virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
64             PixelFormat format, uint32_t usage, status_t* error) {
65         ++mAllocCount;
66         sp<GraphicBuffer> buffer = mAllocator->createGraphicBuffer(w, h, format,
67                 usage, error);
68         return buffer;
69     }
70 
getAllocCount() const71     int getAllocCount() const { return mAllocCount; }
72 
73 private:
74     sp<IGraphicBufferAlloc> mAllocator;
75     int mAllocCount;
76 };
77 
TEST_F(StreamSplitterTest,OneInputOneOutput)78 TEST_F(StreamSplitterTest, OneInputOneOutput) {
79     sp<CountedAllocator> allocator(new CountedAllocator);
80 
81     sp<IGraphicBufferProducer> inputProducer;
82     sp<IGraphicBufferConsumer> inputConsumer;
83     BufferQueue::createBufferQueue(&inputProducer, &inputConsumer, allocator);
84 
85     sp<IGraphicBufferProducer> outputProducer;
86     sp<IGraphicBufferConsumer> outputConsumer;
87     BufferQueue::createBufferQueue(&outputProducer, &outputConsumer, allocator);
88     ASSERT_EQ(OK, outputConsumer->consumerConnect(new DummyListener, false));
89 
90     sp<StreamSplitter> splitter;
91     status_t status = StreamSplitter::createSplitter(inputConsumer, &splitter);
92     ASSERT_EQ(OK, status);
93     ASSERT_EQ(OK, splitter->addOutput(outputProducer));
94 
95     IGraphicBufferProducer::QueueBufferOutput qbOutput;
96     ASSERT_EQ(OK, inputProducer->connect(new DummyProducerListener,
97             NATIVE_WINDOW_API_CPU, false, &qbOutput));
98 
99     int slot;
100     sp<Fence> fence;
101     sp<GraphicBuffer> buffer;
102     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
103             inputProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
104                     GRALLOC_USAGE_SW_WRITE_OFTEN));
105     ASSERT_EQ(OK, inputProducer->requestBuffer(slot, &buffer));
106 
107     uint32_t* dataIn;
108     ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
109             reinterpret_cast<void**>(&dataIn)));
110     *dataIn = 0x12345678;
111     ASSERT_EQ(OK, buffer->unlock());
112 
113     IGraphicBufferProducer::QueueBufferInput qbInput(0, false,
114             Rect(0, 0, 1, 1), NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false,
115             Fence::NO_FENCE);
116     ASSERT_EQ(OK, inputProducer->queueBuffer(slot, qbInput, &qbOutput));
117 
118     IGraphicBufferConsumer::BufferItem item;
119     ASSERT_EQ(OK, outputConsumer->acquireBuffer(&item, 0));
120 
121     uint32_t* dataOut;
122     ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
123             reinterpret_cast<void**>(&dataOut)));
124     ASSERT_EQ(*dataOut, 0x12345678);
125     ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
126 
127     ASSERT_EQ(OK, outputConsumer->releaseBuffer(item.mBuf, item.mFrameNumber,
128             EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
129 
130     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
131             inputProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
132                     GRALLOC_USAGE_SW_WRITE_OFTEN));
133 
134     ASSERT_EQ(1, allocator->getAllocCount());
135 }
136 
TEST_F(StreamSplitterTest,OneInputMultipleOutputs)137 TEST_F(StreamSplitterTest, OneInputMultipleOutputs) {
138     const int NUM_OUTPUTS = 4;
139     sp<CountedAllocator> allocator(new CountedAllocator);
140 
141     sp<IGraphicBufferProducer> inputProducer;
142     sp<IGraphicBufferConsumer> inputConsumer;
143     BufferQueue::createBufferQueue(&inputProducer, &inputConsumer, allocator);
144 
145     sp<IGraphicBufferProducer> outputProducers[NUM_OUTPUTS] = {};
146     sp<IGraphicBufferConsumer> outputConsumers[NUM_OUTPUTS] = {};
147     for (int output = 0; output < NUM_OUTPUTS; ++output) {
148         BufferQueue::createBufferQueue(&outputProducers[output],
149                 &outputConsumers[output], allocator);
150         ASSERT_EQ(OK, outputConsumers[output]->consumerConnect(
151                     new DummyListener, false));
152     }
153 
154     sp<StreamSplitter> splitter;
155     status_t status = StreamSplitter::createSplitter(inputConsumer, &splitter);
156     ASSERT_EQ(OK, status);
157     for (int output = 0; output < NUM_OUTPUTS; ++output) {
158         ASSERT_EQ(OK, splitter->addOutput(outputProducers[output]));
159     }
160 
161     IGraphicBufferProducer::QueueBufferOutput qbOutput;
162     ASSERT_EQ(OK, inputProducer->connect(new DummyProducerListener,
163             NATIVE_WINDOW_API_CPU, false, &qbOutput));
164 
165     int slot;
166     sp<Fence> fence;
167     sp<GraphicBuffer> buffer;
168     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
169             inputProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
170                     GRALLOC_USAGE_SW_WRITE_OFTEN));
171     ASSERT_EQ(OK, inputProducer->requestBuffer(slot, &buffer));
172 
173     uint32_t* dataIn;
174     ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
175             reinterpret_cast<void**>(&dataIn)));
176     *dataIn = 0x12345678;
177     ASSERT_EQ(OK, buffer->unlock());
178 
179     IGraphicBufferProducer::QueueBufferInput qbInput(0, false,
180             Rect(0, 0, 1, 1), NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false,
181             Fence::NO_FENCE);
182     ASSERT_EQ(OK, inputProducer->queueBuffer(slot, qbInput, &qbOutput));
183 
184     for (int output = 0; output < NUM_OUTPUTS; ++output) {
185         IGraphicBufferConsumer::BufferItem item;
186         ASSERT_EQ(OK, outputConsumers[output]->acquireBuffer(&item, 0));
187 
188         uint32_t* dataOut;
189         ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
190                     reinterpret_cast<void**>(&dataOut)));
191         ASSERT_EQ(*dataOut, 0x12345678);
192         ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
193 
194         ASSERT_EQ(OK, outputConsumers[output]->releaseBuffer(item.mBuf,
195                     item.mFrameNumber, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR,
196                     Fence::NO_FENCE));
197     }
198 
199     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
200             inputProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
201                     GRALLOC_USAGE_SW_WRITE_OFTEN));
202 
203     ASSERT_EQ(1, allocator->getAllocCount());
204 }
205 
TEST_F(StreamSplitterTest,OutputAbandonment)206 TEST_F(StreamSplitterTest, OutputAbandonment) {
207     sp<IGraphicBufferProducer> inputProducer;
208     sp<IGraphicBufferConsumer> inputConsumer;
209     BufferQueue::createBufferQueue(&inputProducer, &inputConsumer);
210 
211     sp<IGraphicBufferProducer> outputProducer;
212     sp<IGraphicBufferConsumer> outputConsumer;
213     BufferQueue::createBufferQueue(&outputProducer, &outputConsumer);
214     ASSERT_EQ(OK, outputConsumer->consumerConnect(new DummyListener, false));
215 
216     sp<StreamSplitter> splitter;
217     status_t status = StreamSplitter::createSplitter(inputConsumer, &splitter);
218     ASSERT_EQ(OK, status);
219     ASSERT_EQ(OK, splitter->addOutput(outputProducer));
220 
221     IGraphicBufferProducer::QueueBufferOutput qbOutput;
222     ASSERT_EQ(OK, inputProducer->connect(new DummyProducerListener,
223             NATIVE_WINDOW_API_CPU, false, &qbOutput));
224 
225     int slot;
226     sp<Fence> fence;
227     sp<GraphicBuffer> buffer;
228     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
229             inputProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
230                     GRALLOC_USAGE_SW_WRITE_OFTEN));
231     ASSERT_EQ(OK, inputProducer->requestBuffer(slot, &buffer));
232 
233     // Abandon the output
234     outputConsumer->consumerDisconnect();
235 
236     IGraphicBufferProducer::QueueBufferInput qbInput(0, false,
237             Rect(0, 0, 1, 1), NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false,
238             Fence::NO_FENCE);
239     ASSERT_EQ(OK, inputProducer->queueBuffer(slot, qbInput, &qbOutput));
240 
241     // Input should be abandoned
242     ASSERT_EQ(NO_INIT, inputProducer->dequeueBuffer(&slot, &fence, false, 0, 0,
243             0, GRALLOC_USAGE_SW_WRITE_OFTEN));
244 }
245 
246 } // namespace android
247