blob: 8558fddf6c19b4a07bab0e88d25e109d29f05a14 [file] [log] [blame]
The Android Open Source Project9066cfe2009-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 Wongda83f462009-08-12 12:01:27 -050036 mNotifyCb(0),
37 mDataCb(0),
38 mDataCbTimestamp(0),
39 mCallbackCookie(0),
40 mMsgEnabled(0),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041 mCurrentPreviewFrame(0)
42{
43 initDefaultParameters();
44}
45
46void CameraHardwareStub::initDefaultParameters()
47{
48 CameraParameters p;
49
Chih-Chung Change25cc652010-05-06 16:36:58 +080050 p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, "320x240");
Owen Lind82f4522009-11-24 16:50:54 +080051 p.setPreviewSize(320, 240);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052 p.setPreviewFrameRate(15);
Chih-Chung Change25cc652010-05-06 16:36:58 +080053 p.setPreviewFormat(CameraParameters::PIXEL_FORMAT_YUV420SP);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054
Chih-Chung Change25cc652010-05-06 16:36:58 +080055 p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, "320x240");
Owen Lind82f4522009-11-24 16:50:54 +080056 p.setPictureSize(320, 240);
Chih-Chung Change25cc652010-05-06 16:36:58 +080057 p.setPictureFormat(CameraParameters::PIXEL_FORMAT_JPEG);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058
59 if (setParameters(p) != NO_ERROR) {
60 LOGE("Failed to set default parameters?!");
Owen Lind82f4522009-11-24 16:50:54 +080061 }
The Android Open Source Project9066cfe2009-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);
Chih-Chung Change25cc652010-05-06 16:36:58 +080069 mRawHeap = new MemoryHeapBase(picture_width * picture_height * 3 / 2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070
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
Chih-Chung Change25cc652010-05-06 16:36:58 +080075 // Note that we enforce yuv420sp in setParameters().
76 int how_big = preview_width * preview_height * 3 / 2;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077
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 Lind82f4522009-11-24 16:50:54 +080085 // Make a new mmap'ed heap that can be shared across processes.
The Android Open Source Project9066cfe2009-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 Lind82f4522009-11-24 16:50:54 +080092
The Android Open Source Project9066cfe2009-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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102}
103
Jamie Gennisc8536d192010-08-23 17:23:08 -0700104status_t CameraHardwareStub::setPreviewWindow(const sp<ANativeWindow>& buf)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105{
Jamie Gennisc8536d192010-08-23 17:23:08 -0700106 return NO_ERROR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107}
108
109sp<IMemoryHeap> CameraHardwareStub::getRawHeap() const
110{
111 return mRawHeap;
112}
113
Benny Wongda83f462009-08-12 12:01:27 -0500114void CameraHardwareStub::setCallbacks(notify_callback notify_cb,
115 data_callback data_cb,
116 data_callback_timestamp data_cb_timestamp,
117 void* user)
118{
119 Mutex::Autolock lock(mLock);
120 mNotifyCb = notify_cb;
121 mDataCb = data_cb;
122 mDataCbTimestamp = data_cb_timestamp;
123 mCallbackCookie = user;
124}
125
126void CameraHardwareStub::enableMsgType(int32_t msgType)
127{
128 Mutex::Autolock lock(mLock);
129 mMsgEnabled |= msgType;
130}
131
132void CameraHardwareStub::disableMsgType(int32_t msgType)
133{
134 Mutex::Autolock lock(mLock);
135 mMsgEnabled &= ~msgType;
136}
137
138bool CameraHardwareStub::msgTypeEnabled(int32_t msgType)
139{
140 Mutex::Autolock lock(mLock);
141 return (mMsgEnabled & msgType);
142}
143
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800144// ---------------------------------------------------------------------------
145
146int CameraHardwareStub::previewThread()
147{
148 mLock.lock();
149 // the attributes below can change under our feet...
150
151 int previewFrameRate = mParameters.getPreviewFrameRate();
152
153 // Find the offset within the heap of the current buffer.
154 ssize_t offset = mCurrentPreviewFrame * mPreviewFrameSize;
155
156 sp<MemoryHeapBase> heap = mPreviewHeap;
Owen Lind82f4522009-11-24 16:50:54 +0800157
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800158 // this assumes the internal state of fake camera doesn't change
159 // (or is thread safe)
160 FakeCamera* fakeCamera = mFakeCamera;
Owen Lind82f4522009-11-24 16:50:54 +0800161
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162 sp<MemoryBase> buffer = mBuffers[mCurrentPreviewFrame];
Owen Lind82f4522009-11-24 16:50:54 +0800163
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800164 mLock.unlock();
165
166 // TODO: here check all the conditions that could go wrong
167 if (buffer != 0) {
168 // Calculate how long to wait between frames.
169 int delay = (int)(1000000.0f / float(previewFrameRate));
Owen Lind82f4522009-11-24 16:50:54 +0800170
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800171 // This is always valid, even if the client died -- the memory
172 // is still mapped in our process.
173 void *base = heap->base();
Owen Lind82f4522009-11-24 16:50:54 +0800174
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800175 // Fill the current frame with the fake camera.
176 uint8_t *frame = ((uint8_t *)base) + offset;
Chih-Chung Change25cc652010-05-06 16:36:58 +0800177 fakeCamera->getNextFrameAsYuv420(frame);
Owen Lind82f4522009-11-24 16:50:54 +0800178
Steve Block71f2cf12011-10-20 11:56:00 +0100179 //ALOGV("previewThread: generated frame to buffer %d", mCurrentPreviewFrame);
Owen Lind82f4522009-11-24 16:50:54 +0800180
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800181 // Notify the client of a new frame.
Benny Wongda83f462009-08-12 12:01:27 -0500182 if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)
Wu-cheng Lif0d6a482011-07-28 05:30:59 +0800183 mDataCb(CAMERA_MSG_PREVIEW_FRAME, buffer, NULL, mCallbackCookie);
Owen Lind82f4522009-11-24 16:50:54 +0800184
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800185 // Advance the buffer pointer.
186 mCurrentPreviewFrame = (mCurrentPreviewFrame + 1) % kBufferCount;
187
188 // Wait for it...
189 usleep(delay);
190 }
191
192 return NO_ERROR;
193}
194
Benny Wongda83f462009-08-12 12:01:27 -0500195status_t CameraHardwareStub::startPreview()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800196{
197 Mutex::Autolock lock(mLock);
198 if (mPreviewThread != 0) {
199 // already running
200 return INVALID_OPERATION;
201 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 mPreviewThread = new PreviewThread(this);
203 return NO_ERROR;
204}
205
206void CameraHardwareStub::stopPreview()
207{
208 sp<PreviewThread> previewThread;
Owen Lind82f4522009-11-24 16:50:54 +0800209
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800210 { // scope for the lock
211 Mutex::Autolock lock(mLock);
212 previewThread = mPreviewThread;
213 }
214
215 // don't hold the lock while waiting for the thread to quit
216 if (previewThread != 0) {
217 previewThread->requestExitAndWait();
218 }
219
220 Mutex::Autolock lock(mLock);
221 mPreviewThread.clear();
222}
223
224bool CameraHardwareStub::previewEnabled() {
225 return mPreviewThread != 0;
226}
227
Benny Wongda83f462009-08-12 12:01:27 -0500228status_t CameraHardwareStub::startRecording()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229{
230 return UNKNOWN_ERROR;
231}
232
233void CameraHardwareStub::stopRecording()
234{
235}
236
237bool CameraHardwareStub::recordingEnabled()
238{
239 return false;
240}
241
242void CameraHardwareStub::releaseRecordingFrame(const sp<IMemory>& mem)
243{
244}
245
246// ---------------------------------------------------------------------------
247
248int CameraHardwareStub::beginAutoFocusThread(void *cookie)
249{
250 CameraHardwareStub *c = (CameraHardwareStub *)cookie;
251 return c->autoFocusThread();
252}
253
254int CameraHardwareStub::autoFocusThread()
255{
Benny Wongda83f462009-08-12 12:01:27 -0500256 if (mMsgEnabled & CAMERA_MSG_FOCUS)
257 mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie);
258 return NO_ERROR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800259}
260
Benny Wongda83f462009-08-12 12:01:27 -0500261status_t CameraHardwareStub::autoFocus()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800262{
263 Mutex::Autolock lock(mLock);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264 if (createThread(beginAutoFocusThread, this) == false)
265 return UNKNOWN_ERROR;
266 return NO_ERROR;
267}
268
Chih-Chung Chang244f8c22009-09-15 14:51:56 +0800269status_t CameraHardwareStub::cancelAutoFocus()
270{
271 return NO_ERROR;
272}
273
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800274/*static*/ int CameraHardwareStub::beginPictureThread(void *cookie)
275{
276 CameraHardwareStub *c = (CameraHardwareStub *)cookie;
277 return c->pictureThread();
278}
279
280int CameraHardwareStub::pictureThread()
281{
Benny Wongda83f462009-08-12 12:01:27 -0500282 if (mMsgEnabled & CAMERA_MSG_SHUTTER)
283 mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800284
Benny Wongda83f462009-08-12 12:01:27 -0500285 if (mMsgEnabled & CAMERA_MSG_RAW_IMAGE) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286 //FIXME: use a canned YUV image!
287 // In the meantime just make another fake camera picture.
288 int w, h;
289 mParameters.getPictureSize(&w, &h);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800290 sp<MemoryBase> mem = new MemoryBase(mRawHeap, 0, w * h * 3 / 2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800291 FakeCamera cam(w, h);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800292 cam.getNextFrameAsYuv420((uint8_t *)mRawHeap->base());
Wu-cheng Lif0d6a482011-07-28 05:30:59 +0800293 mDataCb(CAMERA_MSG_RAW_IMAGE, mem, NULL, mCallbackCookie);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800294 }
295
Benny Wongda83f462009-08-12 12:01:27 -0500296 if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800297 sp<MemoryHeapBase> heap = new MemoryHeapBase(kCannedJpegSize);
298 sp<MemoryBase> mem = new MemoryBase(heap, 0, kCannedJpegSize);
299 memcpy(heap->base(), kCannedJpeg, kCannedJpegSize);
Wu-cheng Lif0d6a482011-07-28 05:30:59 +0800300 mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, mem, NULL, mCallbackCookie);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800301 }
302 return NO_ERROR;
303}
304
Benny Wongda83f462009-08-12 12:01:27 -0500305status_t CameraHardwareStub::takePicture()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800306{
307 stopPreview();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800308 if (createThread(beginPictureThread, this) == false)
Chih-Chung Change25cc652010-05-06 16:36:58 +0800309 return UNKNOWN_ERROR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800310 return NO_ERROR;
311}
312
Benny Wongda83f462009-08-12 12:01:27 -0500313status_t CameraHardwareStub::cancelPicture()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800314{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800315 return NO_ERROR;
316}
317
318status_t CameraHardwareStub::dump(int fd, const Vector<String16>& args) const
319{
320 const size_t SIZE = 256;
321 char buffer[SIZE];
322 String8 result;
323 AutoMutex lock(&mLock);
324 if (mFakeCamera != 0) {
Niko Catania28275602009-03-24 20:55:36 -0700325 mFakeCamera->dump(fd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800326 mParameters.dump(fd, args);
327 snprintf(buffer, 255, " preview frame(%d), size (%d), running(%s)\n", mCurrentPreviewFrame, mPreviewFrameSize, mPreviewRunning?"true": "false");
328 result.append(buffer);
329 } else {
330 result.append("No camera client yet.\n");
331 }
332 write(fd, result.string(), result.size());
333 return NO_ERROR;
334}
335
336status_t CameraHardwareStub::setParameters(const CameraParameters& params)
337{
338 Mutex::Autolock lock(mLock);
339 // XXX verify params
340
Chih-Chung Change25cc652010-05-06 16:36:58 +0800341 if (strcmp(params.getPreviewFormat(),
342 CameraParameters::PIXEL_FORMAT_YUV420SP) != 0) {
343 LOGE("Only yuv420sp preview is supported");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800344 return -1;
345 }
346
Chih-Chung Change25cc652010-05-06 16:36:58 +0800347 if (strcmp(params.getPictureFormat(),
348 CameraParameters::PIXEL_FORMAT_JPEG) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800349 LOGE("Only jpeg still pictures are supported");
350 return -1;
351 }
352
353 int w, h;
354 params.getPictureSize(&w, &h);
355 if (w != kCannedJpegWidth && h != kCannedJpegHeight) {
356 LOGE("Still picture size must be size of canned JPEG (%dx%d)",
357 kCannedJpegWidth, kCannedJpegHeight);
358 return -1;
359 }
360
361 mParameters = params;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800362 initHeapLocked();
363
364 return NO_ERROR;
365}
366
367CameraParameters CameraHardwareStub::getParameters() const
368{
369 Mutex::Autolock lock(mLock);
370 return mParameters;
371}
372
Wu-cheng Li36f68b82009-09-28 16:14:58 -0700373status_t CameraHardwareStub::sendCommand(int32_t command, int32_t arg1,
374 int32_t arg2)
375{
376 return BAD_VALUE;
377}
378
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800379void CameraHardwareStub::release()
380{
381}
382
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800383sp<CameraHardwareInterface> CameraHardwareStub::createInstance()
384{
Chih-Chung Change25cc652010-05-06 16:36:58 +0800385 return new CameraHardwareStub();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800386}
387
Chih-Chung Changb8bb78f2010-06-10 13:32:16 +0800388static CameraInfo sCameraInfo[] = {
389 {
390 CAMERA_FACING_BACK,
391 90, /* orientation */
392 }
393};
394
395extern "C" int HAL_getNumberOfCameras()
396{
397 return sizeof(sCameraInfo) / sizeof(sCameraInfo[0]);
398}
399
400extern "C" void HAL_getCameraInfo(int cameraId, struct CameraInfo* cameraInfo)
401{
402 memcpy(cameraInfo, &sCameraInfo[cameraId], sizeof(CameraInfo));
403}
404
405extern "C" sp<CameraHardwareInterface> HAL_openCameraHardware(int cameraId)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800406{
407 return CameraHardwareStub::createInstance();
408}
409
410}; // namespace android