blob: 3d6b0b1eaa9abb6dec68654c5e1161ce5d46973a [file] [log] [blame]
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001/*
2**
3** Copyright 2008, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#define LOG_TAG "CameraHardwareStub"
19#include <utils/Log.h>
20
21#include "CameraHardwareStub.h"
22#include <utils/threads.h>
23#include <fcntl.h>
24#include <sys/mman.h>
25
26#include "CannedJpeg.h"
27
28namespace android {
29
30CameraHardwareStub::CameraHardwareStub()
31 : mParameters(),
32 mHeap(0),
33 mFakeCamera(0),
34 mPreviewFrameSize(0),
35 mRawPictureCallback(0),
36 mJpegPictureCallback(0),
37 mPictureCallbackCookie(0),
38 mPreviewCallback(0),
39 mPreviewCallbackCookie(0),
40 mAutoFocusCallback(0),
41 mAutoFocusCallbackCookie(0),
42 mCurrentPreviewFrame(0)
43{
44 initDefaultParameters();
45}
46
47void CameraHardwareStub::initDefaultParameters()
48{
49 CameraParameters p;
50
51 p.setPreviewSize(176, 144);
52 p.setPreviewFrameRate(15);
53 p.setPreviewFormat("yuv422sp");
54
55 p.setPictureSize(kCannedJpegWidth, kCannedJpegHeight);
56 p.setPictureFormat("jpeg");
57
58 if (setParameters(p) != NO_ERROR) {
59 LOGE("Failed to set default parameters?!");
60 }
61}
62
63void CameraHardwareStub::initHeapLocked()
64{
65 int width, height;
66 mParameters.getPreviewSize(&width, &height);
67
68 LOGD("initHeapLocked: preview size=%dx%d", width, height);
69
70 // Note that we enforce yuv422 in setParameters().
71 int how_big = width * height * 2;
72
73 // If we are being reinitialized to the same size as before, no
74 // work needs to be done.
75 if (how_big == mPreviewFrameSize)
76 return;
77
78 mPreviewFrameSize = how_big;
79
80 // Make a new mmap'ed heap that can be shared across processes.
81 // use code below to test with pmem
82 mHeap = new MemoryHeapBase(mPreviewFrameSize * kBufferCount);
83 // Make an IMemory for each frame so that we can reuse them in callbacks.
84 for (int i = 0; i < kBufferCount; i++) {
85 mBuffers[i] = new MemoryBase(mHeap, i * mPreviewFrameSize, mPreviewFrameSize);
86 }
87
88 // Recreate the fake camera to reflect the current size.
89 delete mFakeCamera;
90 mFakeCamera = new FakeCamera(width, height);
91}
92
93CameraHardwareStub::~CameraHardwareStub()
94{
95 delete mFakeCamera;
96 mFakeCamera = 0; // paranoia
97 singleton.clear();
98}
99
100sp<IMemoryHeap> CameraHardwareStub::getPreviewHeap() const
101{
102 return mHeap;
103}
104
105// ---------------------------------------------------------------------------
106
107int CameraHardwareStub::previewThread()
108{
109 mLock.lock();
110 // the attributes below can change under our feet...
111
112 int previewFrameRate = mParameters.getPreviewFrameRate();
113
114 // Find the offset within the heap of the current buffer.
115 ssize_t offset = mCurrentPreviewFrame * mPreviewFrameSize;
116
117 sp<MemoryHeapBase> heap = mHeap;
118
119 // this assumes the internal state of fake camera doesn't change
120 // (or is thread safe)
121 FakeCamera* fakeCamera = mFakeCamera;
122
123 sp<MemoryBase> buffer = mBuffers[mCurrentPreviewFrame];
124
125 mLock.unlock();
126
127 // TODO: here check all the conditions that could go wrong
128 if (buffer != 0) {
129 // Calculate how long to wait between frames.
130 int delay = (int)(1000000.0f / float(previewFrameRate));
131
132 // This is always valid, even if the client died -- the memory
133 // is still mapped in our process.
134 void *base = heap->base();
135
136 // Fill the current frame with the fake camera.
137 uint8_t *frame = ((uint8_t *)base) + offset;
138 fakeCamera->getNextFrameAsYuv422(frame);
139
140 //LOGV("previewThread: generated frame to buffer %d", mCurrentPreviewFrame);
141
142 // Notify the client of a new frame.
143 mPreviewCallback(buffer, mPreviewCallbackCookie);
144
145 // Advance the buffer pointer.
146 mCurrentPreviewFrame = (mCurrentPreviewFrame + 1) % kBufferCount;
147
148 // Wait for it...
149 usleep(delay);
150 }
151
152 return NO_ERROR;
153}
154
155status_t CameraHardwareStub::startPreview(preview_callback cb, void* user)
156{
157 Mutex::Autolock lock(mLock);
158 if (mPreviewThread != 0) {
159 // already running
160 return INVALID_OPERATION;
161 }
162 mPreviewCallback = cb;
163 mPreviewCallbackCookie = user;
164 mPreviewThread = new PreviewThread(this);
165 return NO_ERROR;
166}
167
168void CameraHardwareStub::stopPreview()
169{
170 sp<PreviewThread> previewThread;
171
172 { // scope for the lock
173 Mutex::Autolock lock(mLock);
174 previewThread = mPreviewThread;
175 }
176
177 // don't hold the lock while waiting for the thread to quit
178 if (previewThread != 0) {
179 previewThread->requestExitAndWait();
180 }
181
182 Mutex::Autolock lock(mLock);
183 mPreviewThread.clear();
184}
185
The Android Open Source Project27629322009-01-09 17:51:23 -0800186bool CameraHardwareStub::previewEnabled() {
187 return mPreviewThread != 0;
188}
189
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700190// ---------------------------------------------------------------------------
191
192int CameraHardwareStub::beginAutoFocusThread(void *cookie)
193{
194 CameraHardwareStub *c = (CameraHardwareStub *)cookie;
195 return c->autoFocusThread();
196}
197
198int CameraHardwareStub::autoFocusThread()
199{
200 if (mAutoFocusCallback != NULL) {
201 mAutoFocusCallback(true, mAutoFocusCallbackCookie);
202 mAutoFocusCallback = NULL;
203 return NO_ERROR;
204 }
205 return UNKNOWN_ERROR;
206}
207
208status_t CameraHardwareStub::autoFocus(autofocus_callback af_cb,
209 void *user)
210{
211 Mutex::Autolock lock(mLock);
212
213 if (mAutoFocusCallback != NULL) {
214 return mAutoFocusCallback == af_cb ? NO_ERROR : INVALID_OPERATION;
215 }
216
217 mAutoFocusCallback = af_cb;
218 mAutoFocusCallbackCookie = user;
219 if (createThread(beginAutoFocusThread, this) == false)
220 return UNKNOWN_ERROR;
221 return NO_ERROR;
222}
223
224/*static*/ int CameraHardwareStub::beginPictureThread(void *cookie)
225{
226 CameraHardwareStub *c = (CameraHardwareStub *)cookie;
227 return c->pictureThread();
228}
229
230int CameraHardwareStub::pictureThread()
231{
232 if (mShutterCallback)
233 mShutterCallback(mPictureCallbackCookie);
234
235 if (mRawPictureCallback) {
236 //FIXME: use a canned YUV image!
237 // In the meantime just make another fake camera picture.
238 int w, h;
239 mParameters.getPictureSize(&w, &h);
240 sp<MemoryHeapBase> heap = new MemoryHeapBase(w * 2 * h);
241 sp<MemoryBase> mem = new MemoryBase(heap, 0, w * 2 * h);
242 FakeCamera cam(w, h);
243 cam.getNextFrameAsYuv422((uint8_t *)heap->base());
244 if (mRawPictureCallback)
245 mRawPictureCallback(mem, mPictureCallbackCookie);
246 }
247
248 if (mJpegPictureCallback) {
249 sp<MemoryHeapBase> heap = new MemoryHeapBase(kCannedJpegSize);
250 sp<MemoryBase> mem = new MemoryBase(heap, 0, kCannedJpegSize);
251 memcpy(heap->base(), kCannedJpeg, kCannedJpegSize);
252 if (mJpegPictureCallback)
253 mJpegPictureCallback(mem, mPictureCallbackCookie);
254 }
255 return NO_ERROR;
256}
257
258status_t CameraHardwareStub::takePicture(shutter_callback shutter_cb,
259 raw_callback raw_cb,
260 jpeg_callback jpeg_cb,
261 void* user)
262{
263 stopPreview();
264 mShutterCallback = shutter_cb;
265 mRawPictureCallback = raw_cb;
266 mJpegPictureCallback = jpeg_cb;
267 mPictureCallbackCookie = user;
268 if (createThread(beginPictureThread, this) == false)
269 return -1;
270 return NO_ERROR;
271}
272
273status_t CameraHardwareStub::cancelPicture(bool cancel_shutter,
274 bool cancel_raw,
275 bool cancel_jpeg)
276{
277 if (cancel_shutter) mShutterCallback = NULL;
278 if (cancel_raw) mRawPictureCallback = NULL;
279 if (cancel_jpeg) mJpegPictureCallback = NULL;
280 return NO_ERROR;
281}
282
283status_t CameraHardwareStub::dump(int fd, const Vector<String16>& args) const
284{
285 const size_t SIZE = 256;
286 char buffer[SIZE];
287 String8 result;
288 AutoMutex lock(&mLock);
289 if (mFakeCamera != 0) {
290 mFakeCamera->dump(fd, args);
291 mParameters.dump(fd, args);
292 snprintf(buffer, 255, " preview frame(%d), size (%d), running(%s)\n", mCurrentPreviewFrame, mPreviewFrameSize, mPreviewRunning?"true": "false");
293 result.append(buffer);
294 } else {
295 result.append("No camera client yet.\n");
296 }
297 write(fd, result.string(), result.size());
298 return NO_ERROR;
299}
300
301status_t CameraHardwareStub::setParameters(const CameraParameters& params)
302{
303 Mutex::Autolock lock(mLock);
304 // XXX verify params
305
306 if (strcmp(params.getPreviewFormat(), "yuv422sp") != 0) {
307 LOGE("Only yuv422sp preview is supported");
308 return -1;
309 }
310
311 if (strcmp(params.getPictureFormat(), "jpeg") != 0) {
312 LOGE("Only jpeg still pictures are supported");
313 return -1;
314 }
315
316 int w, h;
317 params.getPictureSize(&w, &h);
318 if (w != kCannedJpegWidth && h != kCannedJpegHeight) {
319 LOGE("Still picture size must be size of canned JPEG (%dx%d)",
320 kCannedJpegWidth, kCannedJpegHeight);
321 return -1;
322 }
323
324 mParameters = params;
325
326 initHeapLocked();
327
328 return NO_ERROR;
329}
330
331CameraParameters CameraHardwareStub::getParameters() const
332{
333 Mutex::Autolock lock(mLock);
334 return mParameters;
335}
336
337void CameraHardwareStub::release()
338{
339}
340
341wp<CameraHardwareInterface> CameraHardwareStub::singleton;
342
343sp<CameraHardwareInterface> CameraHardwareStub::createInstance()
344{
345 if (singleton != 0) {
346 sp<CameraHardwareInterface> hardware = singleton.promote();
347 if (hardware != 0) {
348 return hardware;
349 }
350 }
351 sp<CameraHardwareInterface> hardware(new CameraHardwareStub());
352 singleton = hardware;
353 return hardware;
354}
355
356extern "C" sp<CameraHardwareInterface> openCameraHardware()
357{
358 return CameraHardwareStub::createInstance();
359}
360
361}; // namespace android