blob: a7af57c426ee8f6f8efdf5ad92e32d6729491999 [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),
36 mRawPictureCallback(0),
37 mJpegPictureCallback(0),
38 mPictureCallbackCookie(0),
39 mPreviewCallback(0),
40 mPreviewCallbackCookie(0),
41 mAutoFocusCallback(0),
42 mAutoFocusCallbackCookie(0),
43 mCurrentPreviewFrame(0)
44{
45 initDefaultParameters();
46}
47
48void CameraHardwareStub::initDefaultParameters()
49{
50 CameraParameters p;
51
52 p.setPreviewSize(176, 144);
53 p.setPreviewFrameRate(15);
54 p.setPreviewFormat("yuv422sp");
55
56 p.setPictureSize(kCannedJpegWidth, kCannedJpegHeight);
57 p.setPictureFormat("jpeg");
58
59 if (setParameters(p) != NO_ERROR) {
60 LOGE("Failed to set default parameters?!");
61 }
62}
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
85 // Make a new mmap'ed heap that can be shared across processes.
86 // 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 }
92
93 // 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
115// ---------------------------------------------------------------------------
116
117int CameraHardwareStub::previewThread()
118{
119 mLock.lock();
120 // the attributes below can change under our feet...
121
122 int previewFrameRate = mParameters.getPreviewFrameRate();
123
124 // Find the offset within the heap of the current buffer.
125 ssize_t offset = mCurrentPreviewFrame * mPreviewFrameSize;
126
127 sp<MemoryHeapBase> heap = mPreviewHeap;
128
129 // this assumes the internal state of fake camera doesn't change
130 // (or is thread safe)
131 FakeCamera* fakeCamera = mFakeCamera;
132
133 sp<MemoryBase> buffer = mBuffers[mCurrentPreviewFrame];
134
135 mLock.unlock();
136
137 // TODO: here check all the conditions that could go wrong
138 if (buffer != 0) {
139 // Calculate how long to wait between frames.
140 int delay = (int)(1000000.0f / float(previewFrameRate));
141
142 // This is always valid, even if the client died -- the memory
143 // is still mapped in our process.
144 void *base = heap->base();
145
146 // Fill the current frame with the fake camera.
147 uint8_t *frame = ((uint8_t *)base) + offset;
148 fakeCamera->getNextFrameAsYuv422(frame);
149
150 //LOGV("previewThread: generated frame to buffer %d", mCurrentPreviewFrame);
151
152 // Notify the client of a new frame.
153 mPreviewCallback(buffer, mPreviewCallbackCookie);
154
155 // Advance the buffer pointer.
156 mCurrentPreviewFrame = (mCurrentPreviewFrame + 1) % kBufferCount;
157
158 // Wait for it...
159 usleep(delay);
160 }
161
162 return NO_ERROR;
163}
164
165status_t CameraHardwareStub::startPreview(preview_callback cb, void* user)
166{
167 Mutex::Autolock lock(mLock);
168 if (mPreviewThread != 0) {
169 // already running
170 return INVALID_OPERATION;
171 }
172 mPreviewCallback = cb;
173 mPreviewCallbackCookie = user;
174 mPreviewThread = new PreviewThread(this);
175 return NO_ERROR;
176}
177
178void CameraHardwareStub::stopPreview()
179{
180 sp<PreviewThread> previewThread;
181
182 { // scope for the lock
183 Mutex::Autolock lock(mLock);
184 previewThread = mPreviewThread;
185 }
186
187 // don't hold the lock while waiting for the thread to quit
188 if (previewThread != 0) {
189 previewThread->requestExitAndWait();
190 }
191
192 Mutex::Autolock lock(mLock);
193 mPreviewThread.clear();
194}
195
196bool CameraHardwareStub::previewEnabled() {
197 return mPreviewThread != 0;
198}
199
200status_t CameraHardwareStub::startRecording(recording_callback cb, void* user)
201{
202 return UNKNOWN_ERROR;
203}
204
205void CameraHardwareStub::stopRecording()
206{
207}
208
209bool CameraHardwareStub::recordingEnabled()
210{
211 return false;
212}
213
214void CameraHardwareStub::releaseRecordingFrame(const sp<IMemory>& mem)
215{
216}
217
218// ---------------------------------------------------------------------------
219
220int CameraHardwareStub::beginAutoFocusThread(void *cookie)
221{
222 CameraHardwareStub *c = (CameraHardwareStub *)cookie;
223 return c->autoFocusThread();
224}
225
226int CameraHardwareStub::autoFocusThread()
227{
228 if (mAutoFocusCallback != NULL) {
229 mAutoFocusCallback(true, mAutoFocusCallbackCookie);
230 mAutoFocusCallback = NULL;
231 return NO_ERROR;
232 }
233 return UNKNOWN_ERROR;
234}
235
236status_t CameraHardwareStub::autoFocus(autofocus_callback af_cb,
237 void *user)
238{
239 Mutex::Autolock lock(mLock);
240
241 if (mAutoFocusCallback != NULL) {
242 return mAutoFocusCallback == af_cb ? NO_ERROR : INVALID_OPERATION;
243 }
244
245 mAutoFocusCallback = af_cb;
246 mAutoFocusCallbackCookie = user;
247 if (createThread(beginAutoFocusThread, this) == false)
248 return UNKNOWN_ERROR;
249 return NO_ERROR;
250}
251
252/*static*/ int CameraHardwareStub::beginPictureThread(void *cookie)
253{
254 CameraHardwareStub *c = (CameraHardwareStub *)cookie;
255 return c->pictureThread();
256}
257
258int CameraHardwareStub::pictureThread()
259{
260 if (mShutterCallback)
261 mShutterCallback(mPictureCallbackCookie);
262
263 if (mRawPictureCallback) {
264 //FIXME: use a canned YUV image!
265 // In the meantime just make another fake camera picture.
266 int w, h;
267 mParameters.getPictureSize(&w, &h);
268 sp<MemoryBase> mem = new MemoryBase(mRawHeap, 0, w * 2 * h);
269 FakeCamera cam(w, h);
270 cam.getNextFrameAsYuv422((uint8_t *)mRawHeap->base());
271 if (mRawPictureCallback)
272 mRawPictureCallback(mem, mPictureCallbackCookie);
273 }
274
275 if (mJpegPictureCallback) {
276 sp<MemoryHeapBase> heap = new MemoryHeapBase(kCannedJpegSize);
277 sp<MemoryBase> mem = new MemoryBase(heap, 0, kCannedJpegSize);
278 memcpy(heap->base(), kCannedJpeg, kCannedJpegSize);
279 if (mJpegPictureCallback)
280 mJpegPictureCallback(mem, mPictureCallbackCookie);
281 }
282 return NO_ERROR;
283}
284
285status_t CameraHardwareStub::takePicture(shutter_callback shutter_cb,
286 raw_callback raw_cb,
287 jpeg_callback jpeg_cb,
288 void* user)
289{
290 stopPreview();
291 mShutterCallback = shutter_cb;
292 mRawPictureCallback = raw_cb;
293 mJpegPictureCallback = jpeg_cb;
294 mPictureCallbackCookie = user;
295 if (createThread(beginPictureThread, this) == false)
296 return -1;
297 return NO_ERROR;
298}
299
300status_t CameraHardwareStub::cancelPicture(bool cancel_shutter,
301 bool cancel_raw,
302 bool cancel_jpeg)
303{
304 if (cancel_shutter) mShutterCallback = NULL;
305 if (cancel_raw) mRawPictureCallback = NULL;
306 if (cancel_jpeg) mJpegPictureCallback = NULL;
307 return NO_ERROR;
308}
309
310status_t CameraHardwareStub::dump(int fd, const Vector<String16>& args) const
311{
312 const size_t SIZE = 256;
313 char buffer[SIZE];
314 String8 result;
315 AutoMutex lock(&mLock);
316 if (mFakeCamera != 0) {
Niko Cataniac8f10f82009-03-24 20:53:55 -0700317 mFakeCamera->dump(fd);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800318 mParameters.dump(fd, args);
319 snprintf(buffer, 255, " preview frame(%d), size (%d), running(%s)\n", mCurrentPreviewFrame, mPreviewFrameSize, mPreviewRunning?"true": "false");
320 result.append(buffer);
321 } else {
322 result.append("No camera client yet.\n");
323 }
324 write(fd, result.string(), result.size());
325 return NO_ERROR;
326}
327
328status_t CameraHardwareStub::setParameters(const CameraParameters& params)
329{
330 Mutex::Autolock lock(mLock);
331 // XXX verify params
332
333 if (strcmp(params.getPreviewFormat(), "yuv422sp") != 0) {
334 LOGE("Only yuv422sp preview is supported");
335 return -1;
336 }
337
338 if (strcmp(params.getPictureFormat(), "jpeg") != 0) {
339 LOGE("Only jpeg still pictures are supported");
340 return -1;
341 }
342
343 int w, h;
344 params.getPictureSize(&w, &h);
345 if (w != kCannedJpegWidth && h != kCannedJpegHeight) {
346 LOGE("Still picture size must be size of canned JPEG (%dx%d)",
347 kCannedJpegWidth, kCannedJpegHeight);
348 return -1;
349 }
350
351 mParameters = params;
352
353 initHeapLocked();
354
355 return NO_ERROR;
356}
357
358CameraParameters CameraHardwareStub::getParameters() const
359{
360 Mutex::Autolock lock(mLock);
361 return mParameters;
362}
363
364void CameraHardwareStub::release()
365{
366}
367
368wp<CameraHardwareInterface> CameraHardwareStub::singleton;
369
370sp<CameraHardwareInterface> CameraHardwareStub::createInstance()
371{
372 if (singleton != 0) {
373 sp<CameraHardwareInterface> hardware = singleton.promote();
374 if (hardware != 0) {
375 return hardware;
376 }
377 }
378 sp<CameraHardwareInterface> hardware(new CameraHardwareStub());
379 singleton = hardware;
380 return hardware;
381}
382
383extern "C" sp<CameraHardwareInterface> openCameraHardware()
384{
385 return CameraHardwareStub::createInstance();
386}
387
388}; // namespace android