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 28namespace android { 29 30class StreamSplitterTest : public ::testing::Test { 31 32protected: 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 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 48struct DummyListener : public BnConsumerListener { 49 virtual void onFrameAvailable(const BufferItem& /* item */) {} 50 virtual void onBuffersReleased() {} 51 virtual void onSidebandStreamChanged() {} 52}; 53 54class CountedAllocator : public BnGraphicBufferAlloc { 55public: 56 CountedAllocator() : mAllocCount(0) { 57 sp<ISurfaceComposer> composer(ComposerService::getComposerService()); 58 mAllocator = composer->createGraphicBufferAlloc(); 59 } 60 61 virtual ~CountedAllocator() {} 62 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 71 int getAllocCount() const { return mAllocCount; } 72 73private: 74 sp<IGraphicBufferAlloc> mAllocator; 75 int mAllocCount; 76}; 77 78TEST_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 137TEST_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 206TEST_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