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 &params) {
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 &params) {
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