3 ** Copyright 2008, The Android Open Source Project
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
9 ** http://www.apache.org/licenses/LICENSE-2.0
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.
18 #define LOG_TAG "CameraHardwareStub"
19 #include <utils/Log.h>
21 #include "CameraHardwareStub.h"
22 #include <utils/threads.h>
26 #include "CannedJpeg.h"
30 CameraHardwareStub::CameraHardwareStub()
41 mCurrentPreviewFrame(0)
43 initDefaultParameters();
46 void CameraHardwareStub::initDefaultParameters()
50 p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, "320x240");
51 p.setPreviewSize(320, 240);
52 p.setPreviewFrameRate(15);
53 p.setPreviewFormat(CameraParameters::PIXEL_FORMAT_YUV420SP);
55 p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, "320x240");
56 p.setPictureSize(320, 240);
57 p.setPictureFormat(CameraParameters::PIXEL_FORMAT_JPEG);
59 if (setParameters(p) != NO_ERROR) {
60 LOGE("Failed to set default parameters?!");
64 void CameraHardwareStub::initHeapLocked()
67 int picture_width, picture_height;
68 mParameters.getPictureSize(&picture_width, &picture_height);
69 mRawHeap = new MemoryHeapBase(picture_width * picture_height * 3 / 2);
71 int preview_width, preview_height;
72 mParameters.getPreviewSize(&preview_width, &preview_height);
73 LOGD("initHeapLocked: preview size=%dx%d", preview_width, preview_height);
75 // Note that we enforce yuv420sp in setParameters().
76 int how_big = preview_width * preview_height * 3 / 2;
78 // If we are being reinitialized to the same size as before, no
79 // work needs to be done.
80 if (how_big == mPreviewFrameSize)
83 mPreviewFrameSize = how_big;
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);
93 // Recreate the fake camera to reflect the current size.
95 mFakeCamera = new FakeCamera(preview_width, preview_height);
98 CameraHardwareStub::~CameraHardwareStub()
101 mFakeCamera = 0; // paranoia
104 sp<IMemoryHeap> CameraHardwareStub::getPreviewHeap() const
109 sp<IMemoryHeap> CameraHardwareStub::getRawHeap() const
114 void CameraHardwareStub::setCallbacks(notify_callback notify_cb,
115 data_callback data_cb,
116 data_callback_timestamp data_cb_timestamp,
119 Mutex::Autolock lock(mLock);
120 mNotifyCb = notify_cb;
122 mDataCbTimestamp = data_cb_timestamp;
123 mCallbackCookie = user;
126 void CameraHardwareStub::enableMsgType(int32_t msgType)
128 Mutex::Autolock lock(mLock);
129 mMsgEnabled |= msgType;
132 void CameraHardwareStub::disableMsgType(int32_t msgType)
134 Mutex::Autolock lock(mLock);
135 mMsgEnabled &= ~msgType;
138 bool CameraHardwareStub::msgTypeEnabled(int32_t msgType)
140 Mutex::Autolock lock(mLock);
141 return (mMsgEnabled & msgType);
144 // ---------------------------------------------------------------------------
146 int CameraHardwareStub::previewThread()
149 // the attributes below can change under our feet...
151 int previewFrameRate = mParameters.getPreviewFrameRate();
153 // Find the offset within the heap of the current buffer.
154 ssize_t offset = mCurrentPreviewFrame * mPreviewFrameSize;
156 sp<MemoryHeapBase> heap = mPreviewHeap;
158 // this assumes the internal state of fake camera doesn't change
159 // (or is thread safe)
160 FakeCamera* fakeCamera = mFakeCamera;
162 sp<MemoryBase> buffer = mBuffers[mCurrentPreviewFrame];
166 // TODO: here check all the conditions that could go wrong
168 // Calculate how long to wait between frames.
169 int delay = (int)(1000000.0f / float(previewFrameRate));
171 // This is always valid, even if the client died -- the memory
172 // is still mapped in our process.
173 void *base = heap->base();
175 // Fill the current frame with the fake camera.
176 uint8_t *frame = ((uint8_t *)base) + offset;
177 fakeCamera->getNextFrameAsYuv420(frame);
179 //LOGV("previewThread: generated frame to buffer %d", mCurrentPreviewFrame);
181 // Notify the client of a new frame.
182 if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)
183 mDataCb(CAMERA_MSG_PREVIEW_FRAME, buffer, mCallbackCookie);
185 // Advance the buffer pointer.
186 mCurrentPreviewFrame = (mCurrentPreviewFrame + 1) % kBufferCount;
195 status_t CameraHardwareStub::startPreview()
197 Mutex::Autolock lock(mLock);
198 if (mPreviewThread != 0) {
200 return INVALID_OPERATION;
202 mPreviewThread = new PreviewThread(this);
206 void CameraHardwareStub::stopPreview()
208 sp<PreviewThread> previewThread;
210 { // scope for the lock
211 Mutex::Autolock lock(mLock);
212 previewThread = mPreviewThread;
215 // don't hold the lock while waiting for the thread to quit
216 if (previewThread != 0) {
217 previewThread->requestExitAndWait();
220 Mutex::Autolock lock(mLock);
221 mPreviewThread.clear();
224 bool CameraHardwareStub::previewEnabled() {
225 return mPreviewThread != 0;
228 status_t CameraHardwareStub::startRecording()
230 return UNKNOWN_ERROR;
233 void CameraHardwareStub::stopRecording()
237 bool CameraHardwareStub::recordingEnabled()
242 void CameraHardwareStub::releaseRecordingFrame(const sp<IMemory>& mem)
246 // ---------------------------------------------------------------------------
248 int CameraHardwareStub::beginAutoFocusThread(void *cookie)
250 CameraHardwareStub *c = (CameraHardwareStub *)cookie;
251 return c->autoFocusThread();
254 int CameraHardwareStub::autoFocusThread()
256 if (mMsgEnabled & CAMERA_MSG_FOCUS)
257 mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie);
261 status_t CameraHardwareStub::autoFocus()
263 Mutex::Autolock lock(mLock);
264 if (createThread(beginAutoFocusThread, this) == false)
265 return UNKNOWN_ERROR;
269 status_t CameraHardwareStub::cancelAutoFocus()
274 /*static*/ int CameraHardwareStub::beginPictureThread(void *cookie)
276 CameraHardwareStub *c = (CameraHardwareStub *)cookie;
277 return c->pictureThread();
280 int CameraHardwareStub::pictureThread()
282 if (mMsgEnabled & CAMERA_MSG_SHUTTER)
283 mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie);
285 if (mMsgEnabled & CAMERA_MSG_RAW_IMAGE) {
286 //FIXME: use a canned YUV image!
287 // In the meantime just make another fake camera picture.
289 mParameters.getPictureSize(&w, &h);
290 sp<MemoryBase> mem = new MemoryBase(mRawHeap, 0, w * h * 3 / 2);
291 FakeCamera cam(w, h);
292 cam.getNextFrameAsYuv420((uint8_t *)mRawHeap->base());
293 mDataCb(CAMERA_MSG_RAW_IMAGE, mem, mCallbackCookie);
296 if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE) {
297 sp<MemoryHeapBase> heap = new MemoryHeapBase(kCannedJpegSize);
298 sp<MemoryBase> mem = new MemoryBase(heap, 0, kCannedJpegSize);
299 memcpy(heap->base(), kCannedJpeg, kCannedJpegSize);
300 mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, mem, mCallbackCookie);
305 status_t CameraHardwareStub::takePicture()
308 if (createThread(beginPictureThread, this) == false)
309 return UNKNOWN_ERROR;
313 status_t CameraHardwareStub::cancelPicture()
318 status_t CameraHardwareStub::dump(int fd, const Vector<String16>& args) const
320 const size_t SIZE = 256;
323 AutoMutex lock(&mLock);
324 if (mFakeCamera != 0) {
325 mFakeCamera->dump(fd);
326 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);
330 result.append("No camera client yet.\n");
332 write(fd, result.string(), result.size());
336 status_t CameraHardwareStub::setParameters(const CameraParameters& params)
338 Mutex::Autolock lock(mLock);
341 if (strcmp(params.getPreviewFormat(),
342 CameraParameters::PIXEL_FORMAT_YUV420SP) != 0) {
343 LOGE("Only yuv420sp preview is supported");
347 if (strcmp(params.getPictureFormat(),
348 CameraParameters::PIXEL_FORMAT_JPEG) != 0) {
349 LOGE("Only jpeg still pictures are supported");
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);
361 mParameters = params;
367 CameraParameters CameraHardwareStub::getParameters() const
369 Mutex::Autolock lock(mLock);
373 status_t CameraHardwareStub::sendCommand(int32_t command, int32_t arg1,
379 void CameraHardwareStub::release()
383 sp<CameraHardwareInterface> CameraHardwareStub::createInstance()
385 return new CameraHardwareStub();
388 static CameraInfo sCameraInfo[] = {
391 90, /* orientation */
395 extern "C" int HAL_getNumberOfCameras()
397 return sizeof(sCameraInfo) / sizeof(sCameraInfo[0]);
400 extern "C" void HAL_getCameraInfo(int cameraId, struct CameraInfo* cameraInfo)
402 memcpy(cameraInfo, &sCameraInfo[cameraId], sizeof(CameraInfo));
405 extern "C" sp<CameraHardwareInterface> HAL_openCameraHardware(int cameraId)
407 return CameraHardwareStub::createInstance();
410 }; // namespace android