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