1 #ifndef CAMERA_TEST_BUFFER_QUEUE_H 2 #define CAMERA_TEST_BUFFER_QUEUE_H 3 4 #ifdef ANDROID_API_JB_OR_LATER 5 6 #include <gui/Surface.h> 7 #include <gui/GLConsumer.h> 8 #include <gui/SurfaceComposerClient.h> 9 10 #include "camera_test.h" 11 12 #define CAMHAL_LOGV ALOGV 13 #define CAMHAL_LOGE ALOGE 14 #define PRINTOVER(arg...) ALOGD(#arg) 15 #define LOG_FUNCTION_NAME ALOGD("%d: %s() ENTER", __LINE__, __FUNCTION__); 16 #define LOG_FUNCTION_NAME_EXIT ALOGD("%d: %s() EXIT", __LINE__, __FUNCTION__); 17 18 using namespace android; 19 20 class FrameConsumer : public BufferQueue::ProxyConsumerListener { 21 public: FrameConsumer()22 FrameConsumer(): 23 BufferQueue::ProxyConsumerListener(NULL), mPendingFrames(0) { 24 } 25 ~FrameConsumer()26 virtual ~FrameConsumer() { 27 onFrameAvailable(); 28 } 29 waitForFrame()30 void waitForFrame() { 31 Mutex::Autolock lock(mMutex); 32 while (mPendingFrames == 0) { 33 mCondition.wait(mMutex); 34 } 35 mPendingFrames--; 36 } 37 onFrameAvailable()38 virtual void onFrameAvailable() { 39 Mutex::Autolock lock(mMutex); 40 mPendingFrames++; 41 mCondition.signal(); 42 } 43 onBuffersReleased()44 virtual void onBuffersReleased() {} 45 46 int mPendingFrames; 47 Mutex mMutex; 48 Condition mCondition; 49 }; 50 51 class BQ_BufferSourceThread : public BufferSourceThread { 52 public: BQ_BufferSourceThread(int tex_id,sp<Camera> camera)53 BQ_BufferSourceThread(int tex_id, sp<Camera> camera) : BufferSourceThread(camera) { 54 mBufferQueue = new BufferQueue(true, 1); 55 mFW = new FrameConsumer(); 56 mBufferQueue->setSynchronousMode(true); 57 mBufferQueue->consumerConnect(mFW); 58 mCamera->setBufferSource(NULL, mBufferQueue); 59 } ~BQ_BufferSourceThread()60 virtual ~BQ_BufferSourceThread() { 61 mCamera->releaseBufferSource(NULL, mBufferQueue); 62 } 63 threadLoop()64 virtual bool threadLoop() { 65 sp<GraphicBuffer> graphic_buffer; 66 BufferQueue::BufferItem item; 67 68 mFW->waitForFrame(); 69 if (!mDestroying) { 70 status_t status; 71 status = mBufferQueue->acquireBuffer(&item, 0); 72 if (status == BufferQueue::NO_BUFFER_AVAILABLE) { 73 // no buffer to handle, return and we'll try again 74 return true; 75 } 76 printf("=== Metadata for buffer %d ===\n", mCounter); 77 if (item.mGraphicBuffer != NULL) { 78 unsigned int slot = item.mBuf; 79 // For whatever reason, BufferQueue only gives us the graphic buffer 80 // the first time we acquire it. We are expected to hold a reference to 81 // it there after... 82 mBufferSlots[slot].mGraphicBuffer = item.mGraphicBuffer; 83 mBufferSlots[slot].mCrop = item.mCrop; 84 } 85 showMetadata(item.mMetadata); 86 printf("\n"); 87 graphic_buffer = mBufferSlots[item.mBuf].mGraphicBuffer; 88 mDeferThread->add(graphic_buffer, item.mCrop, mCounter++, item.mBuf); 89 restartCapture(); 90 return true; 91 } 92 return false; 93 } 94 requestExit()95 virtual void requestExit() { 96 Thread::requestExit(); 97 98 mDestroying = true; 99 mFW->onFrameAvailable(); 100 } 101 setBuffer(android::ShotParameters & params)102 virtual void setBuffer(android::ShotParameters ¶ms) { 103 { 104 String8 id = mBufferQueue->getId(); 105 106 if (!id.isEmpty()) { 107 params.set(KEY_TAP_OUT_SURFACES, id); 108 } else { 109 params.remove(KEY_TAP_OUT_SURFACES); 110 } 111 } 112 } 113 onHandled(sp<GraphicBuffer> & gbuf,unsigned int slot)114 virtual void onHandled(sp<GraphicBuffer> &gbuf, unsigned int slot) { 115 mBufferQueue->releaseBuffer(slot, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR); 116 } 117 118 private: 119 sp<BufferQueue> mBufferQueue; 120 sp<FrameConsumer> mFW; 121 BufferQueue::BufferItem mBufferSlots[BufferQueue::NUM_BUFFER_SLOTS]; 122 }; 123 124 class BQ_BufferSourceInput : public BufferSourceInput { 125 public: BQ_BufferSourceInput(int tex_id,sp<Camera> camera)126 BQ_BufferSourceInput(int tex_id, sp<Camera> camera) : 127 BufferSourceInput(camera), mTexId(tex_id) { 128 mBufferQueue = new BufferQueue(true, 1); 129 sp<IGraphicBufferProducer> bufferProducer = mBufferQueue; 130 mWindowTapIn = new Surface(bufferProducer); 131 mCamera->setBufferSource(mBufferQueue, NULL); 132 } ~BQ_BufferSourceInput()133 virtual ~BQ_BufferSourceInput() { 134 mCamera->releaseBufferSource(mBufferQueue, NULL); 135 } 136 setInput(buffer_info_t bufinfo,const char * format,android::ShotParameters & params)137 virtual void setInput(buffer_info_t bufinfo, const char *format, android::ShotParameters ¶ms) { 138 mBufferQueue->setDefaultBufferSize(bufinfo.width, bufinfo.height); 139 BufferSourceInput::setInput(bufinfo, format, params); 140 { 141 String8 id = mBufferQueue->getId(); 142 143 if (!id.isEmpty()) { 144 params.set(KEY_TAP_IN_SURFACE, id); 145 } else { 146 params.remove(KEY_TAP_IN_SURFACE); 147 } 148 } 149 } 150 151 private: 152 sp<BufferQueue> mBufferQueue; 153 int mTexId; 154 }; 155 #endif // ANDROID_API_JB_OR_LATER 156 #endif // CAMERA_TEST_BUFFER_QUEUE_H 157