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