blob: 8b663898a06e10653e9844f6bc98333ce3cc392f [file] [log] [blame]
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001/*
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 mPreviewHeap(0),
33 mRawHeap(0),
34 mFakeCamera(0),
35 mPreviewFrameSize(0),
Benny Wong4c8fb0a2009-08-12 12:01:27 -050036 mNotifyCb(0),
37 mDataCb(0),
38 mDataCbTimestamp(0),
39 mCallbackCookie(0),
40 mMsgEnabled(0),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080041 mCurrentPreviewFrame(0)
42{
43 initDefaultParameters();
44}
45
46void CameraHardwareStub::initDefaultParameters()
47{
48 CameraParameters p;
49
Owen Lin7371ed62009-11-24 16:50:54 +080050 p.set("preview-size-values","320x240");
51 p.setPreviewSize(320, 240);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080052 p.setPreviewFrameRate(15);
53 p.setPreviewFormat("yuv422sp");
54
Owen Lin7371ed62009-11-24 16:50:54 +080055 p.set("picture-size-values", "320x240");
56 p.setPictureSize(320, 240);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080057 p.setPictureFormat("jpeg");
58
59 if (setParameters(p) != NO_ERROR) {
60 LOGE("Failed to set default parameters?!");
Owen Lin7371ed62009-11-24 16:50:54 +080061 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080062}
63
64void CameraHardwareStub::initHeapLocked()
65{
66 // Create raw heap.
67 int picture_width, picture_height;
68 mParameters.getPictureSize(&picture_width, &picture_height);
69 mRawHeap = new MemoryHeapBase(picture_width * 2 * picture_height);
70
71 int preview_width, preview_height;
72 mParameters.getPreviewSize(&preview_width, &preview_height);
73 LOGD("initHeapLocked: preview size=%dx%d", preview_width, preview_height);
74
75 // Note that we enforce yuv422 in setParameters().
76 int how_big = preview_width * preview_height * 2;
77
78 // If we are being reinitialized to the same size as before, no
79 // work needs to be done.
80 if (how_big == mPreviewFrameSize)
81 return;
82
83 mPreviewFrameSize = how_big;
84
Owen Lin7371ed62009-11-24 16:50:54 +080085 // Make a new mmap'ed heap that can be shared across processes.
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080086 // use code below to test with pmem
87 mPreviewHeap = new MemoryHeapBase(mPreviewFrameSize * kBufferCount);
88 // Make an IMemory for each frame so that we can reuse them in callbacks.
89 for (int i = 0; i < kBufferCount; i++) {
90 mBuffers[i] = new MemoryBase(mPreviewHeap, i * mPreviewFrameSize, mPreviewFrameSize);
91 }
Owen Lin7371ed62009-11-24 16:50:54 +080092
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080093 // Recreate the fake camera to reflect the current size.
94 delete mFakeCamera;
95 mFakeCamera = new FakeCamera(preview_width, preview_height);
96}
97
98CameraHardwareStub::~CameraHardwareStub()
99{
100 delete mFakeCamera;
101 mFakeCamera = 0; // paranoia
102 singleton.clear();
103}
104
105sp<IMemoryHeap> CameraHardwareStub::getPreviewHeap() const
106{
107 return mPreviewHeap;
108}
109
110sp<IMemoryHeap> CameraHardwareStub::getRawHeap() const
111{
112 return mRawHeap;
113}
114
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500115void CameraHardwareStub::setCallbacks(notify_callback notify_cb,
116 data_callback data_cb,
117 data_callback_timestamp data_cb_timestamp,
118 void* user)
119{
120 Mutex::Autolock lock(mLock);
121 mNotifyCb = notify_cb;
122 mDataCb = data_cb;
123 mDataCbTimestamp = data_cb_timestamp;
124 mCallbackCookie = user;
125}
126
127void CameraHardwareStub::enableMsgType(int32_t msgType)
128{
129 Mutex::Autolock lock(mLock);
130 mMsgEnabled |= msgType;
131}
132
133void CameraHardwareStub::disableMsgType(int32_t msgType)
134{
135 Mutex::Autolock lock(mLock);
136 mMsgEnabled &= ~msgType;
137}
138
139bool CameraHardwareStub::msgTypeEnabled(int32_t msgType)
140{
141 Mutex::Autolock lock(mLock);
142 return (mMsgEnabled & msgType);
143}
144
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800145// ---------------------------------------------------------------------------
146
147int CameraHardwareStub::previewThread()
148{
149 mLock.lock();
150 // the attributes below can change under our feet...
151
152 int previewFrameRate = mParameters.getPreviewFrameRate();
153
154 // Find the offset within the heap of the current buffer.
155 ssize_t offset = mCurrentPreviewFrame * mPreviewFrameSize;
156
157 sp<MemoryHeapBase> heap = mPreviewHeap;
Owen Lin7371ed62009-11-24 16:50:54 +0800158
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800159 // this assumes the internal state of fake camera doesn't change
160 // (or is thread safe)
161 FakeCamera* fakeCamera = mFakeCamera;
Owen Lin7371ed62009-11-24 16:50:54 +0800162
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800163 sp<MemoryBase> buffer = mBuffers[mCurrentPreviewFrame];
Owen Lin7371ed62009-11-24 16:50:54 +0800164
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800165 mLock.unlock();
166
167 // TODO: here check all the conditions that could go wrong
168 if (buffer != 0) {
169 // Calculate how long to wait between frames.
170 int delay = (int)(1000000.0f / float(previewFrameRate));
Owen Lin7371ed62009-11-24 16:50:54 +0800171
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800172 // This is always valid, even if the client died -- the memory
173 // is still mapped in our process.
174 void *base = heap->base();
Owen Lin7371ed62009-11-24 16:50:54 +0800175
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800176 // Fill the current frame with the fake camera.
177 uint8_t *frame = ((uint8_t *)base) + offset;
178 fakeCamera->getNextFrameAsYuv422(frame);
Owen Lin7371ed62009-11-24 16:50:54 +0800179
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800180 //LOGV("previewThread: generated frame to buffer %d", mCurrentPreviewFrame);
Owen Lin7371ed62009-11-24 16:50:54 +0800181
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800182 // Notify the client of a new frame.
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500183 if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)
184 mDataCb(CAMERA_MSG_PREVIEW_FRAME, buffer, mCallbackCookie);
Owen Lin7371ed62009-11-24 16:50:54 +0800185
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800186 // Advance the buffer pointer.
187 mCurrentPreviewFrame = (mCurrentPreviewFrame + 1) % kBufferCount;
188
189 // Wait for it...
190 usleep(delay);
191 }
192
193 return NO_ERROR;
194}
195
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500196status_t CameraHardwareStub::startPreview()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800197{
198 Mutex::Autolock lock(mLock);
199 if (mPreviewThread != 0) {
200 // already running
201 return INVALID_OPERATION;
202 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800203 mPreviewThread = new PreviewThread(this);
204 return NO_ERROR;
205}
206
207void CameraHardwareStub::stopPreview()
208{
209 sp<PreviewThread> previewThread;
Owen Lin7371ed62009-11-24 16:50:54 +0800210
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800211 { // scope for the lock
212 Mutex::Autolock lock(mLock);
213 previewThread = mPreviewThread;
214 }
215
216 // don't hold the lock while waiting for the thread to quit
217 if (previewThread != 0) {
218 previewThread->requestExitAndWait();
219 }
220
221 Mutex::Autolock lock(mLock);
222 mPreviewThread.clear();
223}
224
225bool CameraHardwareStub::previewEnabled() {
226 return mPreviewThread != 0;
227}
228
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500229status_t CameraHardwareStub::startRecording()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800230{
231 return UNKNOWN_ERROR;
232}
233
234void CameraHardwareStub::stopRecording()
235{
236}
237
238bool CameraHardwareStub::recordingEnabled()
239{
240 return false;
241}
242
243void CameraHardwareStub::releaseRecordingFrame(const sp<IMemory>& mem)
244{
245}
246
247// ---------------------------------------------------------------------------
248
249int CameraHardwareStub::beginAutoFocusThread(void *cookie)
250{
251 CameraHardwareStub *c = (CameraHardwareStub *)cookie;
252 return c->autoFocusThread();
253}
254
255int CameraHardwareStub::autoFocusThread()
256{
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500257 if (mMsgEnabled & CAMERA_MSG_FOCUS)
258 mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie);
259 return NO_ERROR;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800260}
261
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500262status_t CameraHardwareStub::autoFocus()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800263{
264 Mutex::Autolock lock(mLock);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800265 if (createThread(beginAutoFocusThread, this) == false)
266 return UNKNOWN_ERROR;
267 return NO_ERROR;
268}
269
Chih-Chung Chang00900eb2009-09-15 14:51:56 +0800270status_t CameraHardwareStub::cancelAutoFocus()
271{
272 return NO_ERROR;
273}
274
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800275/*static*/ int CameraHardwareStub::beginPictureThread(void *cookie)
276{
277 CameraHardwareStub *c = (CameraHardwareStub *)cookie;
278 return c->pictureThread();
279}
280
281int CameraHardwareStub::pictureThread()
282{
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500283 if (mMsgEnabled & CAMERA_MSG_SHUTTER)
284 mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800285
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500286 if (mMsgEnabled & CAMERA_MSG_RAW_IMAGE) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800287 //FIXME: use a canned YUV image!
288 // In the meantime just make another fake camera picture.
289 int w, h;
290 mParameters.getPictureSize(&w, &h);
291 sp<MemoryBase> mem = new MemoryBase(mRawHeap, 0, w * 2 * h);
292 FakeCamera cam(w, h);
293 cam.getNextFrameAsYuv422((uint8_t *)mRawHeap->base());
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500294 mDataCb(CAMERA_MSG_RAW_IMAGE, mem, mCallbackCookie);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800295 }
296
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500297 if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800298 sp<MemoryHeapBase> heap = new MemoryHeapBase(kCannedJpegSize);
299 sp<MemoryBase> mem = new MemoryBase(heap, 0, kCannedJpegSize);
300 memcpy(heap->base(), kCannedJpeg, kCannedJpegSize);
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500301 mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, mem, mCallbackCookie);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800302 }
303 return NO_ERROR;
304}
305
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500306status_t CameraHardwareStub::takePicture()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800307{
308 stopPreview();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800309 if (createThread(beginPictureThread, this) == false)
310 return -1;
311 return NO_ERROR;
312}
313
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500314status_t CameraHardwareStub::cancelPicture()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800315{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800316 return NO_ERROR;
317}
318
319status_t CameraHardwareStub::dump(int fd, const Vector<String16>& args) const
320{
321 const size_t SIZE = 256;
322 char buffer[SIZE];
323 String8 result;
324 AutoMutex lock(&mLock);
325 if (mFakeCamera != 0) {
Niko Catania3302ceb2009-03-24 20:55:36 -0700326 mFakeCamera->dump(fd);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800327 mParameters.dump(fd, args);
328 snprintf(buffer, 255, " preview frame(%d), size (%d), running(%s)\n", mCurrentPreviewFrame, mPreviewFrameSize, mPreviewRunning?"true": "false");
329 result.append(buffer);
330 } else {
331 result.append("No camera client yet.\n");
332 }
333 write(fd, result.string(), result.size());
334 return NO_ERROR;
335}
336
337status_t CameraHardwareStub::setParameters(const CameraParameters& params)
338{
339 Mutex::Autolock lock(mLock);
340 // XXX verify params
341
342 if (strcmp(params.getPreviewFormat(), "yuv422sp") != 0) {
343 LOGE("Only yuv422sp preview is supported");
344 return -1;
345 }
346
347 if (strcmp(params.getPictureFormat(), "jpeg") != 0) {
348 LOGE("Only jpeg still pictures are supported");
349 return -1;
350 }
351
352 int w, h;
353 params.getPictureSize(&w, &h);
354 if (w != kCannedJpegWidth && h != kCannedJpegHeight) {
355 LOGE("Still picture size must be size of canned JPEG (%dx%d)",
356 kCannedJpegWidth, kCannedJpegHeight);
357 return -1;
358 }
359
360 mParameters = params;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800361 initHeapLocked();
362
363 return NO_ERROR;
364}
365
366CameraParameters CameraHardwareStub::getParameters() const
367{
368 Mutex::Autolock lock(mLock);
369 return mParameters;
370}
371
Wu-cheng Lie6a550d2009-09-28 16:14:58 -0700372status_t CameraHardwareStub::sendCommand(int32_t command, int32_t arg1,
373 int32_t arg2)
374{
375 return BAD_VALUE;
376}
377
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800378void CameraHardwareStub::release()
379{
380}
381
382wp<CameraHardwareInterface> CameraHardwareStub::singleton;
383
384sp<CameraHardwareInterface> CameraHardwareStub::createInstance()
385{
386 if (singleton != 0) {
387 sp<CameraHardwareInterface> hardware = singleton.promote();
388 if (hardware != 0) {
389 return hardware;
390 }
391 }
392 sp<CameraHardwareInterface> hardware(new CameraHardwareStub());
393 singleton = hardware;
394 return hardware;
395}
396
397extern "C" sp<CameraHardwareInterface> openCameraHardware()
398{
399 return CameraHardwareStub::createInstance();
400}
401
402}; // namespace android