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