diff options
Diffstat (limited to 'services/camera/libcameraservice/CameraHardwareStub.cpp')
-rw-r--r-- | services/camera/libcameraservice/CameraHardwareStub.cpp | 410 |
1 files changed, 410 insertions, 0 deletions
diff --git a/services/camera/libcameraservice/CameraHardwareStub.cpp b/services/camera/libcameraservice/CameraHardwareStub.cpp new file mode 100644 index 0000000..b3e0ee6 --- /dev/null +++ b/services/camera/libcameraservice/CameraHardwareStub.cpp @@ -0,0 +1,410 @@ +/* +** +** Copyright 2008, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#define LOG_TAG "CameraHardwareStub" +#include <utils/Log.h> + +#include "CameraHardwareStub.h" +#include <utils/threads.h> +#include <fcntl.h> +#include <sys/mman.h> + +#include "CannedJpeg.h" + +namespace android { + +CameraHardwareStub::CameraHardwareStub() + : mParameters(), + mPreviewHeap(0), + mRawHeap(0), + mFakeCamera(0), + mPreviewFrameSize(0), + mNotifyCb(0), + mDataCb(0), + mDataCbTimestamp(0), + mCallbackCookie(0), + mMsgEnabled(0), + mCurrentPreviewFrame(0) +{ + initDefaultParameters(); +} + +void CameraHardwareStub::initDefaultParameters() +{ + CameraParameters p; + + p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, "320x240"); + p.setPreviewSize(320, 240); + p.setPreviewFrameRate(15); + p.setPreviewFormat(CameraParameters::PIXEL_FORMAT_YUV420SP); + + p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, "320x240"); + p.setPictureSize(320, 240); + p.setPictureFormat(CameraParameters::PIXEL_FORMAT_JPEG); + + if (setParameters(p) != NO_ERROR) { + LOGE("Failed to set default parameters?!"); + } +} + +void CameraHardwareStub::initHeapLocked() +{ + // Create raw heap. + int picture_width, picture_height; + mParameters.getPictureSize(&picture_width, &picture_height); + mRawHeap = new MemoryHeapBase(picture_width * picture_height * 3 / 2); + + int preview_width, preview_height; + mParameters.getPreviewSize(&preview_width, &preview_height); + LOGD("initHeapLocked: preview size=%dx%d", preview_width, preview_height); + + // Note that we enforce yuv420sp in setParameters(). + int how_big = preview_width * preview_height * 3 / 2; + + // If we are being reinitialized to the same size as before, no + // work needs to be done. + if (how_big == mPreviewFrameSize) + return; + + mPreviewFrameSize = how_big; + + // Make a new mmap'ed heap that can be shared across processes. + // use code below to test with pmem + mPreviewHeap = new MemoryHeapBase(mPreviewFrameSize * kBufferCount); + // Make an IMemory for each frame so that we can reuse them in callbacks. + for (int i = 0; i < kBufferCount; i++) { + mBuffers[i] = new MemoryBase(mPreviewHeap, i * mPreviewFrameSize, mPreviewFrameSize); + } + + // Recreate the fake camera to reflect the current size. + delete mFakeCamera; + mFakeCamera = new FakeCamera(preview_width, preview_height); +} + +CameraHardwareStub::~CameraHardwareStub() +{ + delete mFakeCamera; + mFakeCamera = 0; // paranoia +} + +sp<IMemoryHeap> CameraHardwareStub::getPreviewHeap() const +{ + return mPreviewHeap; +} + +sp<IMemoryHeap> CameraHardwareStub::getRawHeap() const +{ + return mRawHeap; +} + +void CameraHardwareStub::setCallbacks(notify_callback notify_cb, + data_callback data_cb, + data_callback_timestamp data_cb_timestamp, + void* user) +{ + Mutex::Autolock lock(mLock); + mNotifyCb = notify_cb; + mDataCb = data_cb; + mDataCbTimestamp = data_cb_timestamp; + mCallbackCookie = user; +} + +void CameraHardwareStub::enableMsgType(int32_t msgType) +{ + Mutex::Autolock lock(mLock); + mMsgEnabled |= msgType; +} + +void CameraHardwareStub::disableMsgType(int32_t msgType) +{ + Mutex::Autolock lock(mLock); + mMsgEnabled &= ~msgType; +} + +bool CameraHardwareStub::msgTypeEnabled(int32_t msgType) +{ + Mutex::Autolock lock(mLock); + return (mMsgEnabled & msgType); +} + +// --------------------------------------------------------------------------- + +int CameraHardwareStub::previewThread() +{ + mLock.lock(); + // the attributes below can change under our feet... + + int previewFrameRate = mParameters.getPreviewFrameRate(); + + // Find the offset within the heap of the current buffer. + ssize_t offset = mCurrentPreviewFrame * mPreviewFrameSize; + + sp<MemoryHeapBase> heap = mPreviewHeap; + + // this assumes the internal state of fake camera doesn't change + // (or is thread safe) + FakeCamera* fakeCamera = mFakeCamera; + + sp<MemoryBase> buffer = mBuffers[mCurrentPreviewFrame]; + + mLock.unlock(); + + // TODO: here check all the conditions that could go wrong + if (buffer != 0) { + // Calculate how long to wait between frames. + int delay = (int)(1000000.0f / float(previewFrameRate)); + + // This is always valid, even if the client died -- the memory + // is still mapped in our process. + void *base = heap->base(); + + // Fill the current frame with the fake camera. + uint8_t *frame = ((uint8_t *)base) + offset; + fakeCamera->getNextFrameAsYuv420(frame); + + //LOGV("previewThread: generated frame to buffer %d", mCurrentPreviewFrame); + + // Notify the client of a new frame. + if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) + mDataCb(CAMERA_MSG_PREVIEW_FRAME, buffer, mCallbackCookie); + + // Advance the buffer pointer. + mCurrentPreviewFrame = (mCurrentPreviewFrame + 1) % kBufferCount; + + // Wait for it... + usleep(delay); + } + + return NO_ERROR; +} + +status_t CameraHardwareStub::startPreview() +{ + Mutex::Autolock lock(mLock); + if (mPreviewThread != 0) { + // already running + return INVALID_OPERATION; + } + mPreviewThread = new PreviewThread(this); + return NO_ERROR; +} + +void CameraHardwareStub::stopPreview() +{ + sp<PreviewThread> previewThread; + + { // scope for the lock + Mutex::Autolock lock(mLock); + previewThread = mPreviewThread; + } + + // don't hold the lock while waiting for the thread to quit + if (previewThread != 0) { + previewThread->requestExitAndWait(); + } + + Mutex::Autolock lock(mLock); + mPreviewThread.clear(); +} + +bool CameraHardwareStub::previewEnabled() { + return mPreviewThread != 0; +} + +status_t CameraHardwareStub::startRecording() +{ + return UNKNOWN_ERROR; +} + +void CameraHardwareStub::stopRecording() +{ +} + +bool CameraHardwareStub::recordingEnabled() +{ + return false; +} + +void CameraHardwareStub::releaseRecordingFrame(const sp<IMemory>& mem) +{ +} + +// --------------------------------------------------------------------------- + +int CameraHardwareStub::beginAutoFocusThread(void *cookie) +{ + CameraHardwareStub *c = (CameraHardwareStub *)cookie; + return c->autoFocusThread(); +} + +int CameraHardwareStub::autoFocusThread() +{ + if (mMsgEnabled & CAMERA_MSG_FOCUS) + mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie); + return NO_ERROR; +} + +status_t CameraHardwareStub::autoFocus() +{ + Mutex::Autolock lock(mLock); + if (createThread(beginAutoFocusThread, this) == false) + return UNKNOWN_ERROR; + return NO_ERROR; +} + +status_t CameraHardwareStub::cancelAutoFocus() +{ + return NO_ERROR; +} + +/*static*/ int CameraHardwareStub::beginPictureThread(void *cookie) +{ + CameraHardwareStub *c = (CameraHardwareStub *)cookie; + return c->pictureThread(); +} + +int CameraHardwareStub::pictureThread() +{ + if (mMsgEnabled & CAMERA_MSG_SHUTTER) + mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie); + + if (mMsgEnabled & CAMERA_MSG_RAW_IMAGE) { + //FIXME: use a canned YUV image! + // In the meantime just make another fake camera picture. + int w, h; + mParameters.getPictureSize(&w, &h); + sp<MemoryBase> mem = new MemoryBase(mRawHeap, 0, w * h * 3 / 2); + FakeCamera cam(w, h); + cam.getNextFrameAsYuv420((uint8_t *)mRawHeap->base()); + mDataCb(CAMERA_MSG_RAW_IMAGE, mem, mCallbackCookie); + } + + if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE) { + sp<MemoryHeapBase> heap = new MemoryHeapBase(kCannedJpegSize); + sp<MemoryBase> mem = new MemoryBase(heap, 0, kCannedJpegSize); + memcpy(heap->base(), kCannedJpeg, kCannedJpegSize); + mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, mem, mCallbackCookie); + } + return NO_ERROR; +} + +status_t CameraHardwareStub::takePicture() +{ + stopPreview(); + if (createThread(beginPictureThread, this) == false) + return UNKNOWN_ERROR; + return NO_ERROR; +} + +status_t CameraHardwareStub::cancelPicture() +{ + return NO_ERROR; +} + +status_t CameraHardwareStub::dump(int fd, const Vector<String16>& args) const +{ + const size_t SIZE = 256; + char buffer[SIZE]; + String8 result; + AutoMutex lock(&mLock); + if (mFakeCamera != 0) { + mFakeCamera->dump(fd); + mParameters.dump(fd, args); + snprintf(buffer, 255, " preview frame(%d), size (%d), running(%s)\n", mCurrentPreviewFrame, mPreviewFrameSize, mPreviewRunning?"true": "false"); + result.append(buffer); + } else { + result.append("No camera client yet.\n"); + } + write(fd, result.string(), result.size()); + return NO_ERROR; +} + +status_t CameraHardwareStub::setParameters(const CameraParameters& params) +{ + Mutex::Autolock lock(mLock); + // XXX verify params + + if (strcmp(params.getPreviewFormat(), + CameraParameters::PIXEL_FORMAT_YUV420SP) != 0) { + LOGE("Only yuv420sp preview is supported"); + return -1; + } + + if (strcmp(params.getPictureFormat(), + CameraParameters::PIXEL_FORMAT_JPEG) != 0) { + LOGE("Only jpeg still pictures are supported"); + return -1; + } + + int w, h; + params.getPictureSize(&w, &h); + if (w != kCannedJpegWidth && h != kCannedJpegHeight) { + LOGE("Still picture size must be size of canned JPEG (%dx%d)", + kCannedJpegWidth, kCannedJpegHeight); + return -1; + } + + mParameters = params; + initHeapLocked(); + + return NO_ERROR; +} + +CameraParameters CameraHardwareStub::getParameters() const +{ + Mutex::Autolock lock(mLock); + return mParameters; +} + +status_t CameraHardwareStub::sendCommand(int32_t command, int32_t arg1, + int32_t arg2) +{ + return BAD_VALUE; +} + +void CameraHardwareStub::release() +{ +} + +sp<CameraHardwareInterface> CameraHardwareStub::createInstance() +{ + return new CameraHardwareStub(); +} + +static CameraInfo sCameraInfo[] = { + { + CAMERA_FACING_BACK, + 90, /* orientation */ + } +}; + +extern "C" int HAL_getNumberOfCameras() +{ + return sizeof(sCameraInfo) / sizeof(sCameraInfo[0]); +} + +extern "C" void HAL_getCameraInfo(int cameraId, struct CameraInfo* cameraInfo) +{ + memcpy(cameraInfo, &sCameraInfo[cameraId], sizeof(CameraInfo)); +} + +extern "C" sp<CameraHardwareInterface> HAL_openCameraHardware(int cameraId) +{ + return CameraHardwareStub::createInstance(); +} + +}; // namespace android |