| #ifndef CAMERA_TEST_SURFACE_TEXTURE_H |
| #define CAMERA_TEST_SURFACE_TEXTURE_H |
| |
| #include "camera_test.h" |
| |
| #ifdef ANDROID_API_JB_OR_LATER |
| #include <gui/Surface.h> |
| #include <gui/GLConsumer.h> |
| #include <gui/SurfaceComposerClient.h> |
| #else |
| #include <surfaceflinger/Surface.h> |
| #include <surfaceflinger/ISurface.h> |
| #include <surfaceflinger/ISurfaceComposer.h> |
| #include <surfaceflinger/ISurfaceComposerClient.h> |
| #include <surfaceflinger/SurfaceComposerClient.h> |
| #endif |
| |
| #ifdef ANDROID_API_JB_OR_LATER |
| # define CAMHAL_LOGV ALOGV |
| # define CAMHAL_LOGE ALOGE |
| # define PRINTOVER(arg...) ALOGD(#arg) |
| # define LOG_FUNCTION_NAME ALOGD("%d: %s() ENTER", __LINE__, __FUNCTION__); |
| # define LOG_FUNCTION_NAME_EXIT ALOGD("%d: %s() EXIT", __LINE__, __FUNCTION__); |
| #else |
| # define CAMHAL_LOGV LOGV |
| # define CAMHAL_LOGE LOGE |
| # define PRINTOVER(arg...) LOGD(#arg) |
| # define LOG_FUNCTION_NAME LOGD("%d: %s() ENTER", __LINE__, __FUNCTION__); |
| # define LOG_FUNCTION_NAME_EXIT LOGD("%d: %s() EXIT", __LINE__, __FUNCTION__); |
| #endif |
| |
| using namespace android; |
| |
| class FrameWaiter : public android::GLConsumer::FrameAvailableListener { |
| public: |
| FrameWaiter(): |
| mPendingFrames(0) { |
| } |
| |
| virtual ~FrameWaiter() { |
| onFrameAvailable(); |
| } |
| |
| void waitForFrame() { |
| Mutex::Autolock lock(mMutex); |
| while (mPendingFrames == 0) { |
| mCondition.wait(mMutex); |
| } |
| mPendingFrames--; |
| } |
| |
| virtual void onFrameAvailable() { |
| Mutex::Autolock lock(mMutex); |
| mPendingFrames++; |
| mCondition.signal(); |
| } |
| |
| int mPendingFrames; |
| Mutex mMutex; |
| Condition mCondition; |
| }; |
| |
| class GLSurface { |
| public: |
| |
| GLSurface(): |
| mEglDisplay(EGL_NO_DISPLAY), |
| mEglSurface(EGL_NO_SURFACE), |
| mEglContext(EGL_NO_CONTEXT) { |
| } |
| |
| virtual ~GLSurface() {} |
| |
| void initialize(int display); |
| void deinit(); |
| void loadShader(GLenum shaderType, const char* pSource, GLuint* outShader); |
| void createProgram(const char* pVertexSource, const char* pFragmentSource, |
| GLuint* outPgm); |
| |
| private: |
| EGLint const* getConfigAttribs(); |
| EGLint const* getContextAttribs(); |
| |
| protected: |
| sp<SurfaceComposerClient> mComposerClient; |
| sp<SurfaceControl> mSurfaceControl; |
| |
| EGLDisplay mEglDisplay; |
| EGLSurface mEglSurface; |
| EGLContext mEglContext; |
| EGLConfig mGlConfig; |
| }; |
| |
| class SurfaceTextureBase { |
| public: |
| virtual ~SurfaceTextureBase() {} |
| |
| void initialize(int tex_id, EGLenum tex_target = EGL_NONE); |
| void deinit(); |
| void getId(const char **name); |
| |
| virtual sp<GLConsumer> getST(); |
| |
| protected: |
| sp<GLConsumer> mST; |
| sp<Surface> mSTC; |
| sp<ANativeWindow> mANW; |
| int mTexId; |
| }; |
| |
| class SurfaceTextureGL : public GLSurface, public SurfaceTextureBase { |
| public: |
| virtual ~SurfaceTextureGL() {} |
| |
| void initialize(int display, int tex_id); |
| void deinit(); |
| |
| // drawTexture draws the GLConsumer over the entire GL viewport. |
| void drawTexture(); |
| |
| private: |
| GLuint mPgm; |
| GLint mPositionHandle; |
| GLint mTexSamplerHandle; |
| GLint mTexMatrixHandle; |
| }; |
| |
| class ST_BufferSourceThread : public BufferSourceThread { |
| public: |
| ST_BufferSourceThread(int tex_id, sp<Camera> camera) : BufferSourceThread(camera) { |
| mSurfaceTextureBase = new SurfaceTextureBase(); |
| mSurfaceTextureBase->initialize(tex_id); |
| mSurfaceTexture = mSurfaceTextureBase->getST(); |
| mSurfaceTexture->setSynchronousMode(true); |
| mFW = new FrameWaiter(); |
| mSurfaceTexture->setFrameAvailableListener(mFW); |
| #ifndef ANDROID_API_JB_OR_LATER |
| mCamera->setBufferSource(NULL, mSurfaceTexture); |
| #endif |
| } |
| virtual ~ST_BufferSourceThread() { |
| #ifndef ANDROID_API_JB_OR_LATER |
| mCamera->releaseBufferSource(NULL, mSurfaceTexture); |
| #endif |
| mSurfaceTextureBase->deinit(); |
| delete mSurfaceTextureBase; |
| } |
| |
| virtual bool threadLoop() { |
| sp<GraphicBuffer> graphic_buffer; |
| |
| mFW->waitForFrame(); |
| if (!mDestroying) { |
| float mtx[16] = {0.0}; |
| mSurfaceTexture->updateTexImage(); |
| printf("=== Metadata for buffer %d ===\n", mCounter); |
| #ifndef ANDROID_API_JB_OR_LATER |
| showMetadata(mSurfaceTexture->getMetadata()); |
| #endif |
| printf("\n"); |
| graphic_buffer = mSurfaceTexture->getCurrentBuffer(); |
| mSurfaceTexture->getTransformMatrix(mtx); |
| Rect crop = getCrop(graphic_buffer, mtx); |
| |
| mDeferThread->add(graphic_buffer, crop, mCounter++); |
| restartCapture(); |
| return true; |
| } |
| return false; |
| } |
| |
| virtual void requestExit() { |
| Thread::requestExit(); |
| |
| mDestroying = true; |
| mFW->onFrameAvailable(); |
| } |
| |
| virtual void setBuffer(android::ShotParameters ¶ms) { |
| { |
| const char* id = NULL; |
| |
| mSurfaceTextureBase->getId(&id); |
| |
| if (id) { |
| params.set(KEY_TAP_OUT_SURFACES, id); |
| } else { |
| params.remove(KEY_TAP_OUT_SURFACES); |
| } |
| } |
| } |
| |
| private: |
| SurfaceTextureBase *mSurfaceTextureBase; |
| sp<GLConsumer> mSurfaceTexture; |
| sp<FrameWaiter> mFW; |
| }; |
| |
| class ST_BufferSourceInput : public BufferSourceInput { |
| public: |
| ST_BufferSourceInput(int tex_id, sp<Camera> camera) : |
| BufferSourceInput(camera), mTexId(tex_id) { |
| mSurfaceTexture = new SurfaceTextureBase(); |
| sp<GLConsumer> surface_texture; |
| mSurfaceTexture->initialize(mTexId); |
| surface_texture = mSurfaceTexture->getST(); |
| surface_texture->setSynchronousMode(true); |
| |
| mWindowTapIn = new Surface(surface_texture); |
| #ifndef ANDROID_API_JB_OR_LATER |
| mCamera->setBufferSource(mSurfaceTexture->getST(), NULL); |
| #else |
| mCamera->setBufferSource(mSurfaceTexture->getST()->getBufferQueue(), NULL); |
| #endif |
| } |
| virtual ~ST_BufferSourceInput() { |
| #ifndef ANDROID_API_JB_OR_LATER |
| mCamera->releaseBufferSource(mSurfaceTexture->getST(), NULL); |
| #else |
| mCamera->releaseBufferSource(mSurfaceTexture->getST()->getBufferQueue(), NULL); |
| #endif |
| delete mSurfaceTexture; |
| } |
| |
| virtual void setInput(buffer_info_t bufinfo, const char *format) { |
| android::ShotParameters params; |
| mSurfaceTexture->getST()->setDefaultBufferSize(bufinfo.width, bufinfo.height); |
| BufferSourceInput::setInput(bufinfo, format, params); |
| } |
| |
| private: |
| int mTexId; |
| SurfaceTextureBase *mSurfaceTexture; |
| }; |
| |
| #endif |