• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 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 "CpuConsumer_test"
18 //#define LOG_NDEBUG 0
19 //#define LOG_NNDEBUG 0
20 
21 #ifdef LOG_NNDEBUG
22 #define ALOGVV(...) ALOGV(__VA_ARGS__)
23 #else
24 #define ALOGVV(...) ((void)0)
25 #endif
26 
27 #include <gtest/gtest.h>
28 #include <gui/CpuConsumer.h>
29 #include <gui/SurfaceTextureClient.h>
30 #include <ui/GraphicBuffer.h>
31 #include <utils/String8.h>
32 #include <utils/Thread.h>
33 #include <utils/Mutex.h>
34 #include <utils/Condition.h>
35 
36 #include <ui/FramebufferNativeWindow.h>
37 
38 namespace android {
39 
40 struct CpuConsumerTestParams {
41     uint32_t width;
42     uint32_t height;
43     int maxLockedBuffers;
44     PixelFormat format;
45 };
46 
operator <<(::std::ostream & os,const CpuConsumerTestParams & p)47 ::std::ostream& operator<<(::std::ostream& os, const CpuConsumerTestParams& p) {
48     return os << "[ (" << p.width << ", " << p.height << "), B:"
49               << p.maxLockedBuffers << ", F:0x"
50               << ::std::hex << p.format << "]";
51 }
52 
53 class CpuConsumerTest : public ::testing::TestWithParam<CpuConsumerTestParams> {
54 protected:
55 
SetUp()56     virtual void SetUp() {
57         const ::testing::TestInfo* const test_info =
58                 ::testing::UnitTest::GetInstance()->current_test_info();
59         CpuConsumerTestParams params = GetParam();
60         ALOGV("** Starting test %s (%d x %d, %d, 0x%x)",
61                 test_info->name(),
62                 params.width, params.height,
63                 params.maxLockedBuffers, params.format);
64         mCC = new CpuConsumer(params.maxLockedBuffers);
65         String8 name("CpuConsumer_Under_Test");
66         mCC->setName(name);
67         mSTC = new SurfaceTextureClient(mCC->getProducerInterface());
68         mANW = mSTC;
69     }
70 
TearDown()71     virtual void TearDown() {
72         mANW.clear();
73         mSTC.clear();
74         mCC.clear();
75     }
76 
77     class FrameWaiter : public CpuConsumer::FrameAvailableListener {
78     public:
FrameWaiter()79         FrameWaiter():
80                 mPendingFrames(0) {
81         }
82 
waitForFrame()83         void waitForFrame() {
84             Mutex::Autolock lock(mMutex);
85             while (mPendingFrames == 0) {
86                 mCondition.wait(mMutex);
87             }
88             mPendingFrames--;
89         }
90 
onFrameAvailable()91         virtual void onFrameAvailable() {
92             Mutex::Autolock lock(mMutex);
93             mPendingFrames++;
94             mCondition.signal();
95         }
96 
97         int mPendingFrames;
98         Mutex mMutex;
99         Condition mCondition;
100     };
101 
102     // Note that SurfaceTexture will lose the notifications
103     // onBuffersReleased and onFrameAvailable as there is currently
104     // no way to forward the events.  This DisconnectWaiter will not let the
105     // disconnect finish until finishDisconnect() is called.  It will
106     // also block until a disconnect is called
107     class DisconnectWaiter : public BufferQueue::ConsumerListener {
108     public:
DisconnectWaiter()109         DisconnectWaiter () :
110             mWaitForDisconnect(false),
111             mPendingFrames(0) {
112         }
113 
waitForFrame()114         void waitForFrame() {
115             Mutex::Autolock lock(mMutex);
116             while (mPendingFrames == 0) {
117                 mFrameCondition.wait(mMutex);
118             }
119             mPendingFrames--;
120         }
121 
onFrameAvailable()122         virtual void onFrameAvailable() {
123             Mutex::Autolock lock(mMutex);
124             mPendingFrames++;
125             mFrameCondition.signal();
126         }
127 
onBuffersReleased()128         virtual void onBuffersReleased() {
129             Mutex::Autolock lock(mMutex);
130             while (!mWaitForDisconnect) {
131                 mDisconnectCondition.wait(mMutex);
132             }
133         }
134 
finishDisconnect()135         void finishDisconnect() {
136             Mutex::Autolock lock(mMutex);
137             mWaitForDisconnect = true;
138             mDisconnectCondition.signal();
139         }
140 
141     private:
142         Mutex mMutex;
143 
144         bool mWaitForDisconnect;
145         Condition mDisconnectCondition;
146 
147         int mPendingFrames;
148         Condition mFrameCondition;
149     };
150 
151     sp<CpuConsumer> mCC;
152     sp<SurfaceTextureClient> mSTC;
153     sp<ANativeWindow> mANW;
154 };
155 
156 #define ASSERT_NO_ERROR(err, msg) \
157     ASSERT_EQ(NO_ERROR, err) << msg << strerror(-err)
158 
checkPixel(const CpuConsumer::LockedBuffer & buf,uint32_t x,uint32_t y,uint32_t r,uint32_t g,uint32_t b)159 void checkPixel(const CpuConsumer::LockedBuffer &buf,
160         uint32_t x, uint32_t y, uint32_t r, uint32_t g, uint32_t b) {
161     // Ignores components that don't exist for given pixel
162     switch(buf.format) {
163         case HAL_PIXEL_FORMAT_RAW_SENSOR: {
164             String8 msg;
165             uint16_t *bPtr = (uint16_t*)buf.data;
166             bPtr += y * buf.stride + x;
167             // GRBG Bayer mosaic; only check the matching channel
168             switch( ((y & 1) << 1) | (x & 1) ) {
169                 case 0: // G
170                 case 3: // G
171                     EXPECT_EQ(g, *bPtr);
172                     break;
173                 case 1: // R
174                     EXPECT_EQ(r, *bPtr);
175                     break;
176                 case 2: // B
177                     EXPECT_EQ(b, *bPtr);
178                     break;
179             }
180             break;
181         }
182         default: {
183             ADD_FAILURE() << "Unknown format for check:" << buf.format;
184             break;
185         }
186     }
187 }
188 
189 // Fill a YV12 buffer with a multi-colored checkerboard pattern
190 void fillYV12Buffer(uint8_t* buf, int w, int h, int stride);
191 
192 // Fill a RAW sensor buffer with a multi-colored checkerboard pattern.
193 // Assumes GRBG mosaic ordering. Result should be a grid in a 2x2 pattern
194 // of [ R, B; G, W]
fillBayerRawBuffer(uint8_t * buf,int w,int h,int stride)195 void fillBayerRawBuffer(uint8_t* buf, int w, int h, int stride) {
196     ALOGVV("fillBayerRawBuffer: %p with %d x %d, stride %d", buf, w, h ,stride);
197     // Blocks need to be even-width/height, aim for 8-wide otherwise
198     const int blockWidth = (w > 16 ? w / 8 : 2) & ~0x1;
199     const int blockHeight = (h > 16 ? h / 8 : 2) & ~0x1;
200     for (int y = 0; y < h; y+=2) {
201         uint16_t *bPtr1 = ((uint16_t*)buf) + stride*y;
202         uint16_t *bPtr2 = bPtr1 + stride;
203         for (int x = 0; x < w; x+=2) {
204             int blockX = (x / blockWidth ) & 1;
205             int blockY = (y / blockHeight) & 1;
206             unsigned short r = (blockX == blockY) ? 1000 : 200;
207             unsigned short g = blockY ? 1000: 200;
208             unsigned short b = blockX ? 1000: 200;
209             // GR row
210             *bPtr1++ = g;
211             *bPtr1++ = r;
212             // BG row
213             *bPtr2++ = b;
214             *bPtr2++ = g;
215         }
216     }
217 
218 }
219 
checkBayerRawBuffer(const CpuConsumer::LockedBuffer & buf)220 void checkBayerRawBuffer(const CpuConsumer::LockedBuffer &buf) {
221     uint32_t w = buf.width;
222     uint32_t h = buf.height;
223     const int blockWidth = (w > 16 ? w / 8 : 2) & ~0x1;
224     const int blockHeight = (h > 16 ? h / 8 : 2) & ~0x1;
225     const int blockRows = h / blockHeight;
226     const int blockCols = w / blockWidth;
227 
228     // Top-left square is red
229     checkPixel(buf, 0, 0, 1000, 200, 200);
230     checkPixel(buf, 1, 0, 1000, 200, 200);
231     checkPixel(buf, 0, 1, 1000, 200, 200);
232     checkPixel(buf, 1, 1, 1000, 200, 200);
233 
234     // One-right square is blue
235     checkPixel(buf, blockWidth,     0, 200, 200, 1000);
236     checkPixel(buf, blockWidth + 1, 0, 200, 200, 1000);
237     checkPixel(buf, blockWidth,     1, 200, 200, 1000);
238     checkPixel(buf, blockWidth + 1, 1, 200, 200, 1000);
239 
240     // One-down square is green
241     checkPixel(buf, 0, blockHeight, 200, 1000, 200);
242     checkPixel(buf, 1, blockHeight, 200, 1000, 200);
243     checkPixel(buf, 0, blockHeight + 1, 200, 1000, 200);
244     checkPixel(buf, 1, blockHeight + 1, 200, 1000, 200);
245 
246     // One-diag square is white
247     checkPixel(buf, blockWidth,     blockHeight, 1000, 1000, 1000);
248     checkPixel(buf, blockWidth + 1, blockHeight, 1000, 1000, 1000);
249     checkPixel(buf, blockWidth,     blockHeight + 1, 1000, 1000, 1000);
250     checkPixel(buf, blockWidth + 1, blockHeight + 1, 1000, 1000, 1000);
251 
252     // Test bottom-right pixel
253     const int maxBlockX = ((w-1) / blockWidth) & 0x1;
254     const int maxBlockY = ((w-1) / blockHeight) & 0x1;
255     unsigned short maxR = (maxBlockX == maxBlockY) ? 1000 : 200;
256     unsigned short maxG = maxBlockY ? 1000: 200;
257     unsigned short maxB = maxBlockX ? 1000: 200;
258     checkPixel(buf, w-1, h-1, maxR, maxG, maxB);
259 }
260 
261 void fillYV12BufferRect(uint8_t* buf, int w, int h, int stride,
262         const android_native_rect_t& rect);
263 
264 void fillRGBA8Buffer(uint8_t* buf, int w, int h, int stride);
265 
266 void fillRGBA8BufferSolid(uint8_t* buf, int w, int h, int stride, uint8_t r,
267         uint8_t g, uint8_t b, uint8_t a);
268 
269 // Configures the ANativeWindow producer-side interface based on test parameters
configureANW(const sp<ANativeWindow> & anw,const CpuConsumerTestParams & params,int maxBufferSlack)270 void configureANW(const sp<ANativeWindow>& anw,
271         const CpuConsumerTestParams& params,
272         int maxBufferSlack) {
273     status_t err;
274     err = native_window_set_buffers_geometry(anw.get(),
275             params.width, params.height, params.format);
276     ASSERT_NO_ERROR(err, "set_buffers_geometry error: ");
277 
278     err = native_window_set_usage(anw.get(),
279             GRALLOC_USAGE_SW_WRITE_OFTEN);
280     ASSERT_NO_ERROR(err, "set_usage error: ");
281 
282     int minUndequeuedBuffers;
283     err = anw.get()->query(anw.get(),
284             NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
285             &minUndequeuedBuffers);
286     ASSERT_NO_ERROR(err, "query error: ");
287 
288     ALOGVV("Setting buffer count to %d",
289             maxBufferSlack + 1 + minUndequeuedBuffers);
290     err = native_window_set_buffer_count(anw.get(),
291             maxBufferSlack + 1 + minUndequeuedBuffers);
292     ASSERT_NO_ERROR(err, "set_buffer_count error: ");
293 
294 }
295 
296 // Produce one frame of image data; assumes format and resolution configuration
297 // is already done.
produceOneFrame(const sp<ANativeWindow> & anw,const CpuConsumerTestParams & params,int64_t timestamp,uint32_t * stride)298 void produceOneFrame(const sp<ANativeWindow>& anw,
299         const CpuConsumerTestParams& params,
300         int64_t timestamp, uint32_t *stride) {
301     status_t err;
302     ANativeWindowBuffer* anb;
303     ALOGVV("Dequeue buffer from %p", anw.get());
304     err = native_window_dequeue_buffer_and_wait(anw.get(), &anb);
305     ASSERT_NO_ERROR(err, "dequeueBuffer error: ");
306 
307     ASSERT_TRUE(anb != NULL);
308 
309     sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
310 
311     *stride = buf->getStride();
312     uint8_t* img = NULL;
313 
314     ALOGVV("Lock buffer from %p for write", anw.get());
315     err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
316     ASSERT_NO_ERROR(err, "lock error: ");
317 
318     switch (params.format) {
319         case HAL_PIXEL_FORMAT_YV12:
320             fillYV12Buffer(img, params.width, params.height, *stride);
321             break;
322         case HAL_PIXEL_FORMAT_RAW_SENSOR:
323             fillBayerRawBuffer(img, params.width, params.height, buf->getStride());
324             break;
325         default:
326             FAIL() << "Unknown pixel format under test!";
327             break;
328     }
329     ALOGVV("Unlock buffer from %p", anw.get());
330     err = buf->unlock();
331     ASSERT_NO_ERROR(err, "unlock error: ");
332 
333     ALOGVV("Set timestamp to %p", anw.get());
334     err = native_window_set_buffers_timestamp(anw.get(), timestamp);
335     ASSERT_NO_ERROR(err, "set_buffers_timestamp error: ");
336 
337     ALOGVV("Queue buffer to %p", anw.get());
338     err = anw->queueBuffer(anw.get(), buf->getNativeBuffer(), -1);
339     ASSERT_NO_ERROR(err, "queueBuffer error:");
340 };
341 
342 // This test is disabled because the HAL_PIXEL_FORMAT_RAW_SENSOR format is not
343 // supported on all devices.
TEST_P(CpuConsumerTest,DISABLED_FromCpuSingle)344 TEST_P(CpuConsumerTest, DISABLED_FromCpuSingle) {
345     status_t err;
346     CpuConsumerTestParams params = GetParam();
347 
348     // Set up
349 
350     ASSERT_NO_FATAL_FAILURE(configureANW(mANW, params, 1));
351 
352     // Produce
353 
354     const int64_t time = 12345678L;
355     uint32_t stride;
356     ASSERT_NO_FATAL_FAILURE(produceOneFrame(mANW, params, time,
357                     &stride));
358 
359     // Consume
360 
361     CpuConsumer::LockedBuffer b;
362     err = mCC->lockNextBuffer(&b);
363     ASSERT_NO_ERROR(err, "getNextBuffer error: ");
364 
365     ASSERT_TRUE(b.data != NULL);
366     EXPECT_EQ(params.width,  b.width);
367     EXPECT_EQ(params.height, b.height);
368     EXPECT_EQ(params.format, b.format);
369     EXPECT_EQ(stride, b.stride);
370     EXPECT_EQ(time, b.timestamp);
371 
372     checkBayerRawBuffer(b);
373     mCC->unlockBuffer(b);
374 }
375 
376 // This test is disabled because the HAL_PIXEL_FORMAT_RAW_SENSOR format is not
377 // supported on all devices.
TEST_P(CpuConsumerTest,DISABLED_FromCpuManyInQueue)378 TEST_P(CpuConsumerTest, DISABLED_FromCpuManyInQueue) {
379     status_t err;
380     CpuConsumerTestParams params = GetParam();
381 
382     const int numInQueue = 5;
383     // Set up
384 
385     ASSERT_NO_FATAL_FAILURE(configureANW(mANW, params, numInQueue));
386 
387     // Produce
388 
389     const int64_t time[numInQueue] = { 1L, 2L, 3L, 4L, 5L};
390     uint32_t stride[numInQueue];
391 
392     for (int i = 0; i < numInQueue; i++) {
393         ALOGV("Producing frame %d", i);
394         ASSERT_NO_FATAL_FAILURE(produceOneFrame(mANW, params, time[i],
395                         &stride[i]));
396     }
397 
398     // Consume
399 
400     for (int i = 0; i < numInQueue; i++) {
401         ALOGV("Consuming frame %d", i);
402         CpuConsumer::LockedBuffer b;
403         err = mCC->lockNextBuffer(&b);
404         ASSERT_NO_ERROR(err, "getNextBuffer error: ");
405 
406         ASSERT_TRUE(b.data != NULL);
407         EXPECT_EQ(params.width,  b.width);
408         EXPECT_EQ(params.height, b.height);
409         EXPECT_EQ(params.format, b.format);
410         EXPECT_EQ(stride[i], b.stride);
411         EXPECT_EQ(time[i], b.timestamp);
412 
413         checkBayerRawBuffer(b);
414 
415         mCC->unlockBuffer(b);
416     }
417 }
418 
419 // This test is disabled because the HAL_PIXEL_FORMAT_RAW_SENSOR format is not
420 // supported on all devices.
TEST_P(CpuConsumerTest,DISABLED_FromCpuLockMax)421 TEST_P(CpuConsumerTest, DISABLED_FromCpuLockMax) {
422     status_t err;
423     CpuConsumerTestParams params = GetParam();
424 
425     // Set up
426 
427     ASSERT_NO_FATAL_FAILURE(configureANW(mANW, params, params.maxLockedBuffers + 1));
428 
429     // Produce
430 
431     const int64_t time = 1234L;
432     uint32_t stride;
433 
434     for (int i = 0; i < params.maxLockedBuffers + 1; i++) {
435         ALOGV("Producing frame %d", i);
436         ASSERT_NO_FATAL_FAILURE(produceOneFrame(mANW, params, time,
437                         &stride));
438     }
439 
440     // Consume
441 
442     CpuConsumer::LockedBuffer *b = new CpuConsumer::LockedBuffer[params.maxLockedBuffers];
443     for (int i = 0; i < params.maxLockedBuffers; i++) {
444         ALOGV("Locking frame %d", i);
445         err = mCC->lockNextBuffer(&b[i]);
446         ASSERT_NO_ERROR(err, "getNextBuffer error: ");
447 
448         ASSERT_TRUE(b[i].data != NULL);
449         EXPECT_EQ(params.width,  b[i].width);
450         EXPECT_EQ(params.height, b[i].height);
451         EXPECT_EQ(params.format, b[i].format);
452         EXPECT_EQ(stride, b[i].stride);
453         EXPECT_EQ(time, b[i].timestamp);
454 
455         checkBayerRawBuffer(b[i]);
456     }
457 
458     ALOGV("Locking frame %d (too many)", params.maxLockedBuffers);
459     CpuConsumer::LockedBuffer bTooMuch;
460     err = mCC->lockNextBuffer(&bTooMuch);
461     ASSERT_TRUE(err == INVALID_OPERATION) << "Allowing too many locks";
462 
463     ALOGV("Unlocking frame 0");
464     err = mCC->unlockBuffer(b[0]);
465     ASSERT_NO_ERROR(err, "Could not unlock buffer 0: ");
466 
467     ALOGV("Locking frame %d (should work now)", params.maxLockedBuffers);
468     err = mCC->lockNextBuffer(&bTooMuch);
469     ASSERT_NO_ERROR(err, "Did not allow new lock after unlock");
470 
471     ASSERT_TRUE(bTooMuch.data != NULL);
472     EXPECT_EQ(params.width,  bTooMuch.width);
473     EXPECT_EQ(params.height, bTooMuch.height);
474     EXPECT_EQ(params.format, bTooMuch.format);
475     EXPECT_EQ(stride, bTooMuch.stride);
476     EXPECT_EQ(time, bTooMuch.timestamp);
477 
478     checkBayerRawBuffer(bTooMuch);
479 
480     ALOGV("Unlocking extra buffer");
481     err = mCC->unlockBuffer(bTooMuch);
482     ASSERT_NO_ERROR(err, "Could not unlock extra buffer: ");
483 
484     ALOGV("Locking frame %d (no more available)", params.maxLockedBuffers + 1);
485     err = mCC->lockNextBuffer(&b[0]);
486     ASSERT_EQ(BAD_VALUE, err) << "Not out of buffers somehow";
487 
488     for (int i = 1; i < params.maxLockedBuffers; i++) {
489         mCC->unlockBuffer(b[i]);
490     }
491 
492     delete[] b;
493 
494 }
495 
496 CpuConsumerTestParams rawTestSets[] = {
497     { 512,   512, 1, HAL_PIXEL_FORMAT_RAW_SENSOR},
498     { 512,   512, 3, HAL_PIXEL_FORMAT_RAW_SENSOR},
499     { 2608, 1960, 1, HAL_PIXEL_FORMAT_RAW_SENSOR},
500     { 2608, 1960, 3, HAL_PIXEL_FORMAT_RAW_SENSOR},
501     { 100,   100, 1, HAL_PIXEL_FORMAT_RAW_SENSOR},
502     { 100,   100, 3, HAL_PIXEL_FORMAT_RAW_SENSOR}
503 };
504 
505 INSTANTIATE_TEST_CASE_P(RawTests,
506         CpuConsumerTest,
507         ::testing::ValuesIn(rawTestSets));
508 
509 } // namespace android
510