Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright (C) 2011 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_NDEBUG 0
     18 #define LOG_TAG "SurfaceMediaSource_test"
     19 
     20 #include <gtest/gtest.h>
     21 #include <utils/String8.h>
     22 #include <utils/Errors.h>
     23 #include <fcntl.h>
     24 #include <unistd.h>
     25 
     26 #include <GLES2/gl2.h>
     27 
     28 #include <media/stagefright/SurfaceMediaSource.h>
     29 #include <media/mediarecorder.h>
     30 
     31 #include <ui/GraphicBuffer.h>
     32 #include <gui/Surface.h>
     33 #include <gui/ISurfaceComposer.h>
     34 #include <gui/Surface.h>
     35 #include <gui/SurfaceComposerClient.h>
     36 
     37 #include <binder/ProcessState.h>
     38 #include <ui/FramebufferNativeWindow.h>
     39 
     40 #include <media/stagefright/foundation/ADebug.h>
     41 #include <media/stagefright/MediaBufferGroup.h>
     42 #include <media/stagefright/MediaDefs.h>
     43 #include <media/stagefright/MetaData.h>
     44 #include <media/stagefright/OMXClient.h>
     45 #include <media/stagefright/OMXCodec.h>
     46 #include <OMX_Component.h>
     47 
     48 #include "DummyRecorder.h"
     49 
     50 
     51 namespace android {
     52 
     53 class GLTest : public ::testing::Test {
     54 protected:
     55 
     56     GLTest():
     57             mEglDisplay(EGL_NO_DISPLAY),
     58             mEglSurface(EGL_NO_SURFACE),
     59             mEglContext(EGL_NO_CONTEXT) {
     60     }
     61 
     62     virtual void SetUp() {
     63         ALOGV("GLTest::SetUp()");
     64         mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
     65         ASSERT_EQ(EGL_SUCCESS, eglGetError());
     66         ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay);
     67 
     68         EGLint majorVersion;
     69         EGLint minorVersion;
     70         EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion));
     71         ASSERT_EQ(EGL_SUCCESS, eglGetError());
     72         RecordProperty("EglVersionMajor", majorVersion);
     73         RecordProperty("EglVersionMajor", minorVersion);
     74 
     75         EGLint numConfigs = 0;
     76         EXPECT_TRUE(eglChooseConfig(mEglDisplay, getConfigAttribs(), &mGlConfig,
     77                 1, &numConfigs));
     78         ASSERT_EQ(EGL_SUCCESS, eglGetError());
     79 
     80         char* displaySecsEnv = getenv("GLTEST_DISPLAY_SECS");
     81         if (displaySecsEnv != NULL) {
     82             mDisplaySecs = atoi(displaySecsEnv);
     83             if (mDisplaySecs < 0) {
     84                 mDisplaySecs = 0;
     85             }
     86         } else {
     87             mDisplaySecs = 0;
     88         }
     89 
     90         if (mDisplaySecs > 0) {
     91             mComposerClient = new SurfaceComposerClient;
     92             ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
     93 
     94             mSurfaceControl = mComposerClient->createSurface(
     95                     String8("Test Surface"),
     96                     getSurfaceWidth(), getSurfaceHeight(),
     97                     PIXEL_FORMAT_RGB_888, 0);
     98 
     99             ASSERT_TRUE(mSurfaceControl != NULL);
    100             ASSERT_TRUE(mSurfaceControl->isValid());
    101 
    102             SurfaceComposerClient::openGlobalTransaction();
    103             ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7FFFFFFF));
    104             ASSERT_EQ(NO_ERROR, mSurfaceControl->show());
    105             SurfaceComposerClient::closeGlobalTransaction();
    106 
    107             sp<ANativeWindow> window = mSurfaceControl->getSurface();
    108             mEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
    109                     window.get(), NULL);
    110         } else {
    111             ALOGV("No actual display. Choosing EGLSurface based on SurfaceMediaSource");
    112             sp<IGraphicBufferProducer> sms = (new SurfaceMediaSource(
    113                     getSurfaceWidth(), getSurfaceHeight()))->getBufferQueue();
    114             sp<Surface> stc = new Surface(sms);
    115             sp<ANativeWindow> window = stc;
    116 
    117             mEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
    118                     window.get(), NULL);
    119         }
    120         ASSERT_EQ(EGL_SUCCESS, eglGetError());
    121         ASSERT_NE(EGL_NO_SURFACE, mEglSurface);
    122 
    123         mEglContext = eglCreateContext(mEglDisplay, mGlConfig, EGL_NO_CONTEXT,
    124                 getContextAttribs());
    125         ASSERT_EQ(EGL_SUCCESS, eglGetError());
    126         ASSERT_NE(EGL_NO_CONTEXT, mEglContext);
    127 
    128         EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
    129                 mEglContext));
    130         ASSERT_EQ(EGL_SUCCESS, eglGetError());
    131 
    132         EGLint w, h;
    133         EXPECT_TRUE(eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &w));
    134         ASSERT_EQ(EGL_SUCCESS, eglGetError());
    135         EXPECT_TRUE(eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &h));
    136         ASSERT_EQ(EGL_SUCCESS, eglGetError());
    137         RecordProperty("EglSurfaceWidth", w);
    138         RecordProperty("EglSurfaceHeight", h);
    139 
    140         glViewport(0, 0, w, h);
    141         ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
    142     }
    143 
    144     virtual void TearDown() {
    145         // Display the result
    146         if (mDisplaySecs > 0 && mEglSurface != EGL_NO_SURFACE) {
    147             eglSwapBuffers(mEglDisplay, mEglSurface);
    148             sleep(mDisplaySecs);
    149         }
    150 
    151         if (mComposerClient != NULL) {
    152             mComposerClient->dispose();
    153         }
    154         if (mEglContext != EGL_NO_CONTEXT) {
    155             eglDestroyContext(mEglDisplay, mEglContext);
    156         }
    157         if (mEglSurface != EGL_NO_SURFACE) {
    158             eglDestroySurface(mEglDisplay, mEglSurface);
    159         }
    160         if (mEglDisplay != EGL_NO_DISPLAY) {
    161             eglTerminate(mEglDisplay);
    162         }
    163         ASSERT_EQ(EGL_SUCCESS, eglGetError());
    164     }
    165 
    166     virtual EGLint const* getConfigAttribs() {
    167         ALOGV("GLTest getConfigAttribs");
    168         static EGLint sDefaultConfigAttribs[] = {
    169             EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
    170             EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
    171             EGL_RED_SIZE, 8,
    172             EGL_GREEN_SIZE, 8,
    173             EGL_BLUE_SIZE, 8,
    174             EGL_ALPHA_SIZE, 8,
    175             EGL_DEPTH_SIZE, 16,
    176             EGL_STENCIL_SIZE, 8,
    177             EGL_NONE };
    178 
    179         return sDefaultConfigAttribs;
    180     }
    181 
    182     virtual EGLint const* getContextAttribs() {
    183         static EGLint sDefaultContextAttribs[] = {
    184             EGL_CONTEXT_CLIENT_VERSION, 2,
    185             EGL_NONE };
    186 
    187         return sDefaultContextAttribs;
    188     }
    189 
    190     virtual EGLint getSurfaceWidth() {
    191         return 512;
    192     }
    193 
    194     virtual EGLint getSurfaceHeight() {
    195         return 512;
    196     }
    197 
    198     void loadShader(GLenum shaderType, const char* pSource, GLuint* outShader) {
    199         GLuint shader = glCreateShader(shaderType);
    200         ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
    201         if (shader) {
    202             glShaderSource(shader, 1, &pSource, NULL);
    203             ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
    204             glCompileShader(shader);
    205             ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
    206             GLint compiled = 0;
    207             glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
    208             ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
    209             if (!compiled) {
    210                 GLint infoLen = 0;
    211                 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
    212                 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
    213                 if (infoLen) {
    214                     char* buf = (char*) malloc(infoLen);
    215                     if (buf) {
    216                         glGetShaderInfoLog(shader, infoLen, NULL, buf);
    217                         printf("Shader compile log:\n%s\n", buf);
    218                         free(buf);
    219                         FAIL();
    220                     }
    221                 } else {
    222                     char* buf = (char*) malloc(0x1000);
    223                     if (buf) {
    224                         glGetShaderInfoLog(shader, 0x1000, NULL, buf);
    225                         printf("Shader compile log:\n%s\n", buf);
    226                         free(buf);
    227                         FAIL();
    228                     }
    229                 }
    230                 glDeleteShader(shader);
    231                 shader = 0;
    232             }
    233         }
    234         ASSERT_TRUE(shader != 0);
    235         *outShader = shader;
    236     }
    237 
    238     void createProgram(const char* pVertexSource, const char* pFragmentSource,
    239             GLuint* outPgm) {
    240         GLuint vertexShader, fragmentShader;
    241         {
    242             SCOPED_TRACE("compiling vertex shader");
    243             loadShader(GL_VERTEX_SHADER, pVertexSource, &vertexShader);
    244             if (HasFatalFailure()) {
    245                 return;
    246             }
    247         }
    248         {
    249             SCOPED_TRACE("compiling fragment shader");
    250             loadShader(GL_FRAGMENT_SHADER, pFragmentSource, &fragmentShader);
    251             if (HasFatalFailure()) {
    252                 return;
    253             }
    254         }
    255 
    256         GLuint program = glCreateProgram();
    257         ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
    258         if (program) {
    259             glAttachShader(program, vertexShader);
    260             ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
    261             glAttachShader(program, fragmentShader);
    262             ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
    263             glLinkProgram(program);
    264             GLint linkStatus = GL_FALSE;
    265             glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
    266             if (linkStatus != GL_TRUE) {
    267                 GLint bufLength = 0;
    268                 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
    269                 if (bufLength) {
    270                     char* buf = (char*) malloc(bufLength);
    271                     if (buf) {
    272                         glGetProgramInfoLog(program, bufLength, NULL, buf);
    273                         printf("Program link log:\n%s\n", buf);
    274                         free(buf);
    275                         FAIL();
    276                     }
    277                 }
    278                 glDeleteProgram(program);
    279                 program = 0;
    280             }
    281         }
    282         glDeleteShader(vertexShader);
    283         glDeleteShader(fragmentShader);
    284         ASSERT_TRUE(program != 0);
    285         *outPgm = program;
    286     }
    287 
    288     static int abs(int value) {
    289         return value > 0 ? value : -value;
    290     }
    291 
    292     ::testing::AssertionResult checkPixel(int x, int y, int r,
    293             int g, int b, int a, int tolerance=2) {
    294         GLubyte pixel[4];
    295         String8 msg;
    296         glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
    297         GLenum err = glGetError();
    298         if (err != GL_NO_ERROR) {
    299             msg += String8::format("error reading pixel: %#x", err);
    300             while ((err = glGetError()) != GL_NO_ERROR) {
    301                 msg += String8::format(", %#x", err);
    302             }
    303             fprintf(stderr, "pixel check failure: %s\n", msg.string());
    304             return ::testing::AssertionFailure(
    305                     ::testing::Message(msg.string()));
    306         }
    307         if (r >= 0 && abs(r - int(pixel[0])) > tolerance) {
    308             msg += String8::format("r(%d isn't %d)", pixel[0], r);
    309         }
    310         if (g >= 0 && abs(g - int(pixel[1])) > tolerance) {
    311             if (!msg.isEmpty()) {
    312                 msg += " ";
    313             }
    314             msg += String8::format("g(%d isn't %d)", pixel[1], g);
    315         }
    316         if (b >= 0 && abs(b - int(pixel[2])) > tolerance) {
    317             if (!msg.isEmpty()) {
    318                 msg += " ";
    319             }
    320             msg += String8::format("b(%d isn't %d)", pixel[2], b);
    321         }
    322         if (a >= 0 && abs(a - int(pixel[3])) > tolerance) {
    323             if (!msg.isEmpty()) {
    324                 msg += " ";
    325             }
    326             msg += String8::format("a(%d isn't %d)", pixel[3], a);
    327         }
    328         if (!msg.isEmpty()) {
    329             fprintf(stderr, "pixel check failure: %s\n", msg.string());
    330             return ::testing::AssertionFailure(
    331                     ::testing::Message(msg.string()));
    332         } else {
    333             return ::testing::AssertionSuccess();
    334         }
    335     }
    336 
    337     int mDisplaySecs;
    338     sp<SurfaceComposerClient> mComposerClient;
    339     sp<SurfaceControl> mSurfaceControl;
    340 
    341     EGLDisplay mEglDisplay;
    342     EGLSurface mEglSurface;
    343     EGLContext mEglContext;
    344     EGLConfig  mGlConfig;
    345 };
    346 
    347 ///////////////////////////////////////////////////////////////////////
    348 //    Class for  the NON-GL tests
    349 ///////////////////////////////////////////////////////////////////////
    350 class SurfaceMediaSourceTest : public ::testing::Test {
    351 public:
    352 
    353     SurfaceMediaSourceTest( ): mYuvTexWidth(176), mYuvTexHeight(144) { }
    354     void oneBufferPass(int width, int height );
    355     void oneBufferPassNoFill(int width, int height );
    356     static void fillYV12Buffer(uint8_t* buf, int w, int h, int stride) ;
    357     static void fillYV12BufferRect(uint8_t* buf, int w, int h,
    358                         int stride, const android_native_rect_t& rect) ;
    359 protected:
    360 
    361     virtual void SetUp() {
    362         android::ProcessState::self()->startThreadPool();
    363         mSMS = new SurfaceMediaSource(mYuvTexWidth, mYuvTexHeight);
    364 
    365         // Manual cast is required to avoid constructor ambiguity
    366         mSTC = new Surface(static_cast<sp<IGraphicBufferProducer> >( mSMS->getBufferQueue()));
    367         mANW = mSTC;
    368     }
    369 
    370     virtual void TearDown() {
    371         mSMS.clear();
    372         mSTC.clear();
    373         mANW.clear();
    374     }
    375 
    376     const int mYuvTexWidth;
    377     const int mYuvTexHeight;
    378 
    379     sp<SurfaceMediaSource> mSMS;
    380     sp<Surface> mSTC;
    381     sp<ANativeWindow> mANW;
    382 };
    383 
    384 ///////////////////////////////////////////////////////////////////////
    385 //    Class for  the GL tests
    386 ///////////////////////////////////////////////////////////////////////
    387 class SurfaceMediaSourceGLTest : public GLTest {
    388 public:
    389 
    390     SurfaceMediaSourceGLTest( ): mYuvTexWidth(176), mYuvTexHeight(144) { }
    391     virtual EGLint const* getConfigAttribs();
    392     void oneBufferPassGL(int num = 0);
    393     static sp<MediaRecorder> setUpMediaRecorder(int fileDescriptor, int videoSource,
    394         int outputFormat, int videoEncoder, int width, int height, int fps);
    395 protected:
    396 
    397     virtual void SetUp() {
    398         ALOGV("SMS-GLTest::SetUp()");
    399         android::ProcessState::self()->startThreadPool();
    400         mSMS = new SurfaceMediaSource(mYuvTexWidth, mYuvTexHeight);
    401         mSTC = new Surface(static_cast<sp<IGraphicBufferProducer> >( mSMS->getBufferQueue()));
    402         mANW = mSTC;
    403 
    404         // Doing the setup related to the GL Side
    405         GLTest::SetUp();
    406     }
    407 
    408     virtual void TearDown() {
    409         mSMS.clear();
    410         mSTC.clear();
    411         mANW.clear();
    412         GLTest::TearDown();
    413     }
    414 
    415     void setUpEGLSurfaceFromMediaRecorder(sp<MediaRecorder>& mr);
    416 
    417     const int mYuvTexWidth;
    418     const int mYuvTexHeight;
    419 
    420     sp<SurfaceMediaSource> mSMS;
    421     sp<Surface> mSTC;
    422     sp<ANativeWindow> mANW;
    423 };
    424 
    425 /////////////////////////////////////////////////////////////////////
    426 // Methods in SurfaceMediaSourceGLTest
    427 /////////////////////////////////////////////////////////////////////
    428 EGLint const* SurfaceMediaSourceGLTest::getConfigAttribs() {
    429         ALOGV("SurfaceMediaSourceGLTest getConfigAttribs");
    430     static EGLint sDefaultConfigAttribs[] = {
    431         EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
    432         EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
    433         EGL_RED_SIZE, 8,
    434         EGL_GREEN_SIZE, 8,
    435         EGL_BLUE_SIZE, 8,
    436         EGL_RECORDABLE_ANDROID, EGL_TRUE,
    437         EGL_NONE };
    438 
    439     return sDefaultConfigAttribs;
    440 }
    441 
    442 // One pass of dequeuing and queuing a GLBuffer
    443 void SurfaceMediaSourceGLTest::oneBufferPassGL(int num) {
    444     int d = num % 50;
    445     float f = 0.2f; // 0.1f * d;
    446 
    447     glClearColor(0, 0.3, 0, 0.6);
    448     glClear(GL_COLOR_BUFFER_BIT);
    449 
    450     glEnable(GL_SCISSOR_TEST);
    451     glScissor(4 + d, 4 + d, 4, 4);
    452     glClearColor(1.0 - f, f, f, 1.0);
    453     glClear(GL_COLOR_BUFFER_BIT);
    454 
    455     glScissor(24 + d, 48 + d, 4, 4);
    456     glClearColor(f, 1.0 - f, f, 1.0);
    457     glClear(GL_COLOR_BUFFER_BIT);
    458 
    459     glScissor(37 + d, 17 + d, 4, 4);
    460     glClearColor(f, f, 1.0 - f, 1.0);
    461     glClear(GL_COLOR_BUFFER_BIT);
    462 
    463     // The following call dequeues and queues the buffer
    464     eglSwapBuffers(mEglDisplay, mEglSurface);
    465     ASSERT_EQ(EGL_SUCCESS, eglGetError());
    466     glDisable(GL_SCISSOR_TEST);
    467 }
    468 
    469 // Set up the MediaRecorder which runs in the same process as mediaserver
    470 sp<MediaRecorder> SurfaceMediaSourceGLTest::setUpMediaRecorder(int fd, int videoSource,
    471         int outputFormat, int videoEncoder, int width, int height, int fps) {
    472     sp<MediaRecorder> mr = new MediaRecorder();
    473     mr->setVideoSource(videoSource);
    474     mr->setOutputFormat(outputFormat);
    475     mr->setVideoEncoder(videoEncoder);
    476     mr->setOutputFile(fd, 0, 0);
    477     mr->setVideoSize(width, height);
    478     mr->setVideoFrameRate(fps);
    479     mr->prepare();
    480     ALOGV("Starting MediaRecorder...");
    481     CHECK_EQ((status_t)OK, mr->start());
    482     return mr;
    483 }
    484 
    485 // query the mediarecorder for a surfacemeidasource and create an egl surface with that
    486 void SurfaceMediaSourceGLTest::setUpEGLSurfaceFromMediaRecorder(sp<MediaRecorder>& mr) {
    487     sp<IGraphicBufferProducer> iST = mr->querySurfaceMediaSourceFromMediaServer();
    488     mSTC = new Surface(iST);
    489     mANW = mSTC;
    490 
    491     if (mEglSurface != EGL_NO_SURFACE) {
    492         EXPECT_TRUE(eglDestroySurface(mEglDisplay, mEglSurface));
    493         mEglSurface = EGL_NO_SURFACE;
    494     }
    495     mEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
    496                                 mANW.get(), NULL);
    497     ASSERT_EQ(EGL_SUCCESS, eglGetError());
    498     ASSERT_NE(EGL_NO_SURFACE, mEglSurface) ;
    499 
    500     EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
    501             mEglContext));
    502     ASSERT_EQ(EGL_SUCCESS, eglGetError());
    503 }
    504 
    505 
    506 /////////////////////////////////////////////////////////////////////
    507 // Methods in SurfaceMediaSourceTest
    508 /////////////////////////////////////////////////////////////////////
    509 
    510 // One pass of dequeuing and queuing the buffer. Fill it in with
    511 // cpu YV12 buffer
    512 void SurfaceMediaSourceTest::oneBufferPass(int width, int height ) {
    513     ANativeWindowBuffer* anb;
    514     ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), &anb));
    515     ASSERT_TRUE(anb != NULL);
    516 
    517 
    518     // Fill the buffer with the a checkerboard pattern
    519     uint8_t* img = NULL;
    520     sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
    521     buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
    522     SurfaceMediaSourceTest::fillYV12Buffer(img, width, height, buf->getStride());
    523     buf->unlock();
    524 
    525     ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer(),
    526             -1));
    527 }
    528 
    529 // Dequeuing and queuing the buffer without really filling it in.
    530 void SurfaceMediaSourceTest::oneBufferPassNoFill(int width, int height ) {
    531     ANativeWindowBuffer* anb;
    532     ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), &anb));
    533     ASSERT_TRUE(anb != NULL);
    534 
    535     // We do not fill the buffer in. Just queue it back.
    536     sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
    537     ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer(),
    538             -1));
    539 }
    540 
    541 // Fill a YV12 buffer with a multi-colored checkerboard pattern
    542 void SurfaceMediaSourceTest::fillYV12Buffer(uint8_t* buf, int w, int h, int stride) {
    543     const int blockWidth = w > 16 ? w / 16 : 1;
    544     const int blockHeight = h > 16 ? h / 16 : 1;
    545     const int yuvTexOffsetY = 0;
    546     int yuvTexStrideY = stride;
    547     int yuvTexOffsetV = yuvTexStrideY * h;
    548     int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf;
    549     int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * h/2;
    550     int yuvTexStrideU = yuvTexStrideV;
    551     for (int x = 0; x < w; x++) {
    552         for (int y = 0; y < h; y++) {
    553             int parityX = (x / blockWidth) & 1;
    554             int parityY = (y / blockHeight) & 1;
    555             unsigned char intensity = (parityX ^ parityY) ? 63 : 191;
    556             buf[yuvTexOffsetY + (y * yuvTexStrideY) + x] = intensity;
    557             if (x < w / 2 && y < h / 2) {
    558                 buf[yuvTexOffsetU + (y * yuvTexStrideU) + x] = intensity;
    559                 if (x * 2 < w / 2 && y * 2 < h / 2) {
    560                     buf[yuvTexOffsetV + (y*2 * yuvTexStrideV) + x*2 + 0] =
    561                     buf[yuvTexOffsetV + (y*2 * yuvTexStrideV) + x*2 + 1] =
    562                     buf[yuvTexOffsetV + ((y*2+1) * yuvTexStrideV) + x*2 + 0] =
    563                     buf[yuvTexOffsetV + ((y*2+1) * yuvTexStrideV) + x*2 + 1] =
    564                         intensity;
    565                 }
    566             }
    567         }
    568     }
    569 }
    570 
    571 // Fill a YV12 buffer with red outside a given rectangle and green inside it.
    572 void SurfaceMediaSourceTest::fillYV12BufferRect(uint8_t* buf, int w,
    573                   int h, int stride, const android_native_rect_t& rect) {
    574     const int yuvTexOffsetY = 0;
    575     int yuvTexStrideY = stride;
    576     int yuvTexOffsetV = yuvTexStrideY * h;
    577     int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf;
    578     int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * h/2;
    579     int yuvTexStrideU = yuvTexStrideV;
    580     for (int x = 0; x < w; x++) {
    581         for (int y = 0; y < h; y++) {
    582             bool inside = rect.left <= x && x < rect.right &&
    583                     rect.top <= y && y < rect.bottom;
    584             buf[yuvTexOffsetY + (y * yuvTexStrideY) + x] = inside ? 240 : 64;
    585             if (x < w / 2 && y < h / 2) {
    586                 bool inside = rect.left <= 2*x && 2*x < rect.right &&
    587                         rect.top <= 2*y && 2*y < rect.bottom;
    588                 buf[yuvTexOffsetU + (y * yuvTexStrideU) + x] = 16;
    589                 buf[yuvTexOffsetV + (y * yuvTexStrideV) + x] =
    590                                                 inside ? 16 : 255;
    591             }
    592         }
    593     }
    594 }  ///////// End of class SurfaceMediaSourceTest
    595 
    596 ///////////////////////////////////////////////////////////////////
    597 // Class to imitate the recording     /////////////////////////////
    598 // ////////////////////////////////////////////////////////////////
    599 struct SimpleDummyRecorder {
    600         sp<MediaSource> mSource;
    601 
    602         SimpleDummyRecorder
    603                 (const sp<MediaSource> &source): mSource(source) {}
    604 
    605         status_t start() { return mSource->start();}
    606         status_t stop()  { return mSource->stop();}
    607 
    608         // fakes reading from a media source
    609         status_t readFromSource() {
    610             MediaBuffer *buffer;
    611             status_t err = mSource->read(&buffer);
    612             if (err != OK) {
    613                 return err;
    614             }
    615             buffer->release();
    616             buffer = NULL;
    617             return OK;
    618         }
    619 };
    620 ///////////////////////////////////////////////////////////////////
    621 //           TESTS
    622 // SurfaceMediaSourceTest class contains tests that fill the buffers
    623 // using the cpu calls
    624 // SurfaceMediaSourceGLTest class contains tests that fill the buffers
    625 // using the GL calls.
    626 // TODO: None of the tests actually verify the encoded images.. so at this point,
    627 // these are mostly functionality tests + visual inspection
    628 //////////////////////////////////////////////////////////////////////
    629 
    630 // Just pass one buffer from the native_window to the SurfaceMediaSource
    631 // Dummy Encoder
    632 static int testId = 1;
    633 TEST_F(SurfaceMediaSourceTest, DISABLED_DummyEncodingFromCpuFilledYV12BufferNpotOneBufferPass) {
    634     ALOGV("Test # %d", testId++);
    635     ALOGV("Testing OneBufferPass ******************************");
    636 
    637     ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
    638             HAL_PIXEL_FORMAT_YV12));
    639     oneBufferPass(mYuvTexWidth, mYuvTexHeight);
    640 }
    641 
    642 // Pass the buffer with the wrong height and weight and should not be accepted
    643 // Dummy Encoder
    644 TEST_F(SurfaceMediaSourceTest, DISABLED_DummyEncodingFromCpuFilledYV12BufferNpotWrongSizeBufferPass) {
    645     ALOGV("Test # %d", testId++);
    646     ALOGV("Testing Wrong size BufferPass ******************************");
    647 
    648     // setting the client side buffer size different than the server size
    649     ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
    650              10, 10));
    651     ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
    652             HAL_PIXEL_FORMAT_YV12));
    653 
    654     ANativeWindowBuffer* anb;
    655 
    656     // Note: make sure we get an ERROR back when dequeuing!
    657     ASSERT_NE(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), &anb));
    658 }
    659 
    660 // pass multiple buffers from the native_window the SurfaceMediaSource
    661 // Dummy Encoder
    662 TEST_F(SurfaceMediaSourceTest,  DISABLED_DummyEncodingFromCpuFilledYV12BufferNpotMultiBufferPass) {
    663     ALOGV("Test # %d", testId++);
    664     ALOGV("Testing MultiBufferPass, Dummy Recorder *********************");
    665     ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
    666             HAL_PIXEL_FORMAT_YV12));
    667 
    668     SimpleDummyRecorder writer(mSMS);
    669     writer.start();
    670 
    671     int32_t nFramesCount = 0;
    672     while (nFramesCount < 300) {
    673         oneBufferPass(mYuvTexWidth, mYuvTexHeight);
    674 
    675         ASSERT_EQ(NO_ERROR, writer.readFromSource());
    676 
    677         nFramesCount++;
    678     }
    679     writer.stop();
    680 }
    681 
    682 // Delayed pass of multiple buffers from the native_window the SurfaceMediaSource
    683 // Dummy Encoder
    684 TEST_F(SurfaceMediaSourceTest,  DummyLagEncodingFromCpuFilledYV12BufferNpotMultiBufferPass) {
    685     ALOGV("Test # %d", testId++);
    686     ALOGV("Testing MultiBufferPass, Dummy Recorder Lagging **************");
    687 
    688     ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
    689             HAL_PIXEL_FORMAT_YV12));
    690 
    691     SimpleDummyRecorder writer(mSMS);
    692     writer.start();
    693 
    694     int32_t nFramesCount = 1;
    695     const int FRAMES_LAG = SurfaceMediaSource::MIN_UNDEQUEUED_BUFFERS;
    696 
    697     while (nFramesCount <= 300) {
    698         ALOGV("Frame: %d", nFramesCount);
    699         oneBufferPass(mYuvTexWidth, mYuvTexHeight);
    700         // Forcing the writer to lag behind a few frames
    701         if (nFramesCount > FRAMES_LAG) {
    702             ASSERT_EQ(NO_ERROR, writer.readFromSource());
    703         }
    704         nFramesCount++;
    705     }
    706     writer.stop();
    707 }
    708 
    709 // pass multiple buffers from the native_window the SurfaceMediaSource
    710 // A dummy writer (MULTITHREADED) is used to simulate actual MPEG4Writer
    711 TEST_F(SurfaceMediaSourceTest, DummyThreadedEncodingFromCpuFilledYV12BufferNpotMultiBufferPass) {
    712     ALOGV("Test # %d", testId++);
    713     ALOGV("Testing MultiBufferPass, Dummy Recorder Multi-Threaded **********");
    714     ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
    715             HAL_PIXEL_FORMAT_YV12));
    716 
    717     DummyRecorder writer(mSMS);
    718     writer.start();
    719 
    720     int32_t nFramesCount = 0;
    721     while (nFramesCount <= 300) {
    722         ALOGV("Frame: %d", nFramesCount);
    723         oneBufferPass(mYuvTexWidth, mYuvTexHeight);
    724 
    725         nFramesCount++;
    726     }
    727     writer.stop();
    728 }
    729 
    730 // Test to examine actual encoding using mediarecorder
    731 // We use the mediaserver to create a mediarecorder and send
    732 // it back to us. So SurfaceMediaSource lives in the same process
    733 // as the mediaserver.
    734 // Very close to the actual camera, except that the
    735 // buffers are filled and queueud by the CPU instead of GL.
    736 TEST_F(SurfaceMediaSourceTest, DISABLED_EncodingFromCpuYV12BufferNpotWriteMediaServer) {
    737     ALOGV("Test # %d", testId++);
    738     ALOGV("************** Testing the whole pipeline with actual MediaRecorder ***********");
    739     ALOGV("************** SurfaceMediaSource is same process as mediaserver    ***********");
    740 
    741     const char *fileName = "/sdcard/outputSurfEncMSource.mp4";
    742     int fd = open(fileName, O_RDWR | O_CREAT, 0744);
    743     if (fd < 0) {
    744         ALOGE("ERROR: Could not open the the file %s, fd = %d !!", fileName, fd);
    745     }
    746     CHECK(fd >= 0);
    747 
    748     sp<MediaRecorder> mr = SurfaceMediaSourceGLTest::setUpMediaRecorder(fd,
    749             VIDEO_SOURCE_GRALLOC_BUFFER,
    750             OUTPUT_FORMAT_MPEG_4, VIDEO_ENCODER_H264, mYuvTexWidth,
    751             mYuvTexHeight, 30);
    752     // get the reference to the surfacemediasource living in
    753     // mediaserver that is created by stagefrightrecorder
    754     sp<IGraphicBufferProducer> iST = mr->querySurfaceMediaSourceFromMediaServer();
    755     mSTC = new Surface(iST);
    756     mANW = mSTC;
    757     ASSERT_EQ(NO_ERROR, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
    758     ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
    759                                                 HAL_PIXEL_FORMAT_YV12));
    760 
    761     int32_t nFramesCount = 0;
    762     while (nFramesCount <= 300) {
    763         oneBufferPassNoFill(mYuvTexWidth, mYuvTexHeight);
    764         nFramesCount++;
    765         ALOGV("framesCount = %d", nFramesCount);
    766     }
    767 
    768     ASSERT_EQ(NO_ERROR, native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_CPU));
    769     ALOGV("Stopping MediaRecorder...");
    770     CHECK_EQ((status_t)OK, mr->stop());
    771     mr.clear();
    772     close(fd);
    773 }
    774 
    775 //////////////////////////////////////////////////////////////////////
    776 // GL tests
    777 /////////////////////////////////////////////////////////////////////
    778 
    779 // Test to examine whether we can choose the Recordable Android GLConfig
    780 // DummyRecorder used- no real encoding here
    781 TEST_F(SurfaceMediaSourceGLTest, ChooseAndroidRecordableEGLConfigDummyWriter) {
    782     ALOGV("Test # %d", testId++);
    783     ALOGV("Verify creating a surface w/ right config + dummy writer*********");
    784 
    785     mSMS = new SurfaceMediaSource(mYuvTexWidth, mYuvTexHeight);
    786     mSTC = new Surface(static_cast<sp<IGraphicBufferProducer> >( mSMS->getBufferQueue()));
    787     mANW = mSTC;
    788 
    789     DummyRecorder writer(mSMS);
    790     writer.start();
    791 
    792     if (mEglSurface != EGL_NO_SURFACE) {
    793         EXPECT_TRUE(eglDestroySurface(mEglDisplay, mEglSurface));
    794         mEglSurface = EGL_NO_SURFACE;
    795     }
    796 
    797     mEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
    798                                 mANW.get(), NULL);
    799     ASSERT_EQ(EGL_SUCCESS, eglGetError());
    800     ASSERT_NE(EGL_NO_SURFACE, mEglSurface) ;
    801 
    802     EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
    803             mEglContext));
    804     ASSERT_EQ(EGL_SUCCESS, eglGetError());
    805 
    806     int32_t nFramesCount = 0;
    807     while (nFramesCount <= 300) {
    808         oneBufferPassGL();
    809         nFramesCount++;
    810         ALOGV("framesCount = %d", nFramesCount);
    811     }
    812 
    813     EXPECT_TRUE(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
    814             EGL_NO_CONTEXT));
    815     ASSERT_EQ(EGL_SUCCESS, eglGetError());
    816     eglDestroySurface(mEglDisplay, mEglSurface);
    817     mEglSurface = EGL_NO_SURFACE;
    818 
    819     writer.stop();
    820 }
    821 // Test to examine whether we can render GL buffers in to the surface
    822 // created with the native window handle
    823 TEST_F(SurfaceMediaSourceGLTest, RenderingToRecordableEGLSurfaceWorks) {
    824     ALOGV("Test # %d", testId++);
    825     ALOGV("RenderingToRecordableEGLSurfaceWorks *********************");
    826     // Do the producer side of things
    827     glClearColor(0.6, 0.6, 0.6, 0.6);
    828     glClear(GL_COLOR_BUFFER_BIT);
    829 
    830     glEnable(GL_SCISSOR_TEST);
    831     glScissor(4, 4, 4, 4);
    832     glClearColor(1.0, 0.0, 0.0, 1.0);
    833     glClear(GL_COLOR_BUFFER_BIT);
    834 
    835     glScissor(24, 48, 4, 4);
    836     glClearColor(0.0, 1.0, 0.0, 1.0);
    837     glClear(GL_COLOR_BUFFER_BIT);
    838 
    839     glScissor(37, 17, 4, 4);
    840     glClearColor(0.0, 0.0, 1.0, 1.0);
    841     glClear(GL_COLOR_BUFFER_BIT);
    842 
    843     EXPECT_TRUE(checkPixel( 0,  0, 153, 153, 153, 153));
    844     EXPECT_TRUE(checkPixel(63,  0, 153, 153, 153, 153));
    845     EXPECT_TRUE(checkPixel(63, 63, 153, 153, 153, 153));
    846     EXPECT_TRUE(checkPixel( 0, 63, 153, 153, 153, 153));
    847 
    848     EXPECT_TRUE(checkPixel( 4,  7, 255,   0,   0, 255));
    849     EXPECT_TRUE(checkPixel(25, 51,   0, 255,   0, 255));
    850     EXPECT_TRUE(checkPixel(40, 19,   0,   0, 255, 255));
    851     EXPECT_TRUE(checkPixel(29, 51, 153, 153, 153, 153));
    852     EXPECT_TRUE(checkPixel( 5, 32, 153, 153, 153, 153));
    853     EXPECT_TRUE(checkPixel(13,  8, 153, 153, 153, 153));
    854     EXPECT_TRUE(checkPixel(46,  3, 153, 153, 153, 153));
    855     EXPECT_TRUE(checkPixel(30, 33, 153, 153, 153, 153));
    856     EXPECT_TRUE(checkPixel( 6, 52, 153, 153, 153, 153));
    857     EXPECT_TRUE(checkPixel(55, 33, 153, 153, 153, 153));
    858     EXPECT_TRUE(checkPixel(16, 29, 153, 153, 153, 153));
    859     EXPECT_TRUE(checkPixel( 1, 30, 153, 153, 153, 153));
    860     EXPECT_TRUE(checkPixel(41, 37, 153, 153, 153, 153));
    861     EXPECT_TRUE(checkPixel(46, 29, 153, 153, 153, 153));
    862     EXPECT_TRUE(checkPixel(15, 25, 153, 153, 153, 153));
    863     EXPECT_TRUE(checkPixel( 3, 52, 153, 153, 153, 153));
    864 }
    865 
    866 // Test to examine the actual encoding with GL buffers
    867 // Actual encoder, Actual GL Buffers Filled SurfaceMediaSource
    868 // The same pattern is rendered every frame
    869 TEST_F(SurfaceMediaSourceGLTest, EncodingFromGLRgbaSameImageEachBufNpotWrite) {
    870     ALOGV("Test # %d", testId++);
    871     ALOGV("************** Testing the whole pipeline with actual Recorder ***********");
    872     ALOGV("************** GL Filling the buffers ***********");
    873     // Note: No need to set the colorformat for the buffers. The colorformat is
    874     // in the GRAlloc buffers itself.
    875 
    876     const char *fileName = "/sdcard/outputSurfEncMSourceGL.mp4";
    877     int fd = open(fileName, O_RDWR | O_CREAT, 0744);
    878     if (fd < 0) {
    879         ALOGE("ERROR: Could not open the the file %s, fd = %d !!", fileName, fd);
    880     }
    881     CHECK(fd >= 0);
    882 
    883     sp<MediaRecorder> mr = setUpMediaRecorder(fd, VIDEO_SOURCE_GRALLOC_BUFFER,
    884             OUTPUT_FORMAT_MPEG_4, VIDEO_ENCODER_H264, mYuvTexWidth, mYuvTexHeight, 30);
    885 
    886     // get the reference to the surfacemediasource living in
    887     // mediaserver that is created by stagefrightrecorder
    888     setUpEGLSurfaceFromMediaRecorder(mr);
    889 
    890     int32_t nFramesCount = 0;
    891     while (nFramesCount <= 300) {
    892         oneBufferPassGL();
    893         nFramesCount++;
    894         ALOGV("framesCount = %d", nFramesCount);
    895     }
    896 
    897     EXPECT_TRUE(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
    898             EGL_NO_CONTEXT));
    899     ASSERT_EQ(EGL_SUCCESS, eglGetError());
    900     eglDestroySurface(mEglDisplay, mEglSurface);
    901     mEglSurface = EGL_NO_SURFACE;
    902 
    903     ALOGV("Stopping MediaRecorder...");
    904     CHECK_EQ((status_t)OK, mr->stop());
    905     mr.clear();
    906     close(fd);
    907 }
    908 
    909 // Test to examine the actual encoding from the GL Buffers
    910 // Actual encoder, Actual GL Buffers Filled SurfaceMediaSource
    911 // A different pattern is rendered every frame
    912 TEST_F(SurfaceMediaSourceGLTest, EncodingFromGLRgbaDiffImageEachBufNpotWrite) {
    913     ALOGV("Test # %d", testId++);
    914     ALOGV("************** Testing the whole pipeline with actual Recorder ***********");
    915     ALOGV("************** Diff GL Filling the buffers ***********");
    916     // Note: No need to set the colorformat for the buffers. The colorformat is
    917     // in the GRAlloc buffers itself.
    918 
    919     const char *fileName = "/sdcard/outputSurfEncMSourceGLDiff.mp4";
    920     int fd = open(fileName, O_RDWR | O_CREAT, 0744);
    921     if (fd < 0) {
    922         ALOGE("ERROR: Could not open the the file %s, fd = %d !!", fileName, fd);
    923     }
    924     CHECK(fd >= 0);
    925 
    926     sp<MediaRecorder> mr = setUpMediaRecorder(fd, VIDEO_SOURCE_GRALLOC_BUFFER,
    927             OUTPUT_FORMAT_MPEG_4, VIDEO_ENCODER_H264, mYuvTexWidth, mYuvTexHeight, 30);
    928 
    929     // get the reference to the surfacemediasource living in
    930     // mediaserver that is created by stagefrightrecorder
    931     setUpEGLSurfaceFromMediaRecorder(mr);
    932 
    933     int32_t nFramesCount = 0;
    934     while (nFramesCount <= 300) {
    935         oneBufferPassGL(nFramesCount);
    936         nFramesCount++;
    937         ALOGV("framesCount = %d", nFramesCount);
    938     }
    939 
    940     EXPECT_TRUE(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
    941             EGL_NO_CONTEXT));
    942     ASSERT_EQ(EGL_SUCCESS, eglGetError());
    943     eglDestroySurface(mEglDisplay, mEglSurface);
    944     mEglSurface = EGL_NO_SURFACE;
    945 
    946     ALOGV("Stopping MediaRecorder...");
    947     CHECK_EQ((status_t)OK, mr->stop());
    948     mr.clear();
    949     close(fd);
    950 }
    951 } // namespace android
    952