Home | History | Annotate | Download | only in libcameraservice
      1 /*
      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 
     28 namespace android {
     29 
     30 CameraHardwareStub::CameraHardwareStub()
     31                   : mParameters(),
     32                     mPreviewHeap(0),
     33                     mRawHeap(0),
     34                     mFakeCamera(0),
     35                     mPreviewFrameSize(0),
     36                     mNotifyCb(0),
     37                     mDataCb(0),
     38                     mDataCbTimestamp(0),
     39                     mCallbackCookie(0),
     40                     mMsgEnabled(0),
     41                     mCurrentPreviewFrame(0)
     42 {
     43     initDefaultParameters();
     44 }
     45 
     46 void CameraHardwareStub::initDefaultParameters()
     47 {
     48     CameraParameters p;
     49 
     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);
     54 
     55     p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, "320x240");
     56     p.setPictureSize(320, 240);
     57     p.setPictureFormat(CameraParameters::PIXEL_FORMAT_JPEG);
     58 
     59     if (setParameters(p) != NO_ERROR) {
     60         ALOGE("Failed to set default parameters?!");
     61     }
     62 }
     63 
     64 void 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 * picture_height * 3 / 2);
     70 
     71     int preview_width, preview_height;
     72     mParameters.getPreviewSize(&preview_width, &preview_height);
     73     ALOGD("initHeapLocked: preview size=%dx%d", preview_width, preview_height);
     74 
     75     // Note that we enforce yuv420sp in setParameters().
     76     int how_big = preview_width * preview_height * 3 / 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 
     98 CameraHardwareStub::~CameraHardwareStub()
     99 {
    100     delete mFakeCamera;
    101     mFakeCamera = 0; // paranoia
    102 }
    103 
    104 status_t CameraHardwareStub::setPreviewWindow(const sp<ANativeWindow>& buf)
    105 {
    106     return NO_ERROR;
    107 }
    108 
    109 sp<IMemoryHeap> CameraHardwareStub::getRawHeap() const
    110 {
    111     return mRawHeap;
    112 }
    113 
    114 void 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 
    126 void CameraHardwareStub::enableMsgType(int32_t msgType)
    127 {
    128     Mutex::Autolock lock(mLock);
    129     mMsgEnabled |= msgType;
    130 }
    131 
    132 void CameraHardwareStub::disableMsgType(int32_t msgType)
    133 {
    134     Mutex::Autolock lock(mLock);
    135     mMsgEnabled &= ~msgType;
    136 }
    137 
    138 bool CameraHardwareStub::msgTypeEnabled(int32_t msgType)
    139 {
    140     Mutex::Autolock lock(mLock);
    141     return (mMsgEnabled & msgType);
    142 }
    143 
    144 // ---------------------------------------------------------------------------
    145 
    146 int 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;
    157 
    158         // this assumes the internal state of fake camera doesn't change
    159         // (or is thread safe)
    160         FakeCamera* fakeCamera = mFakeCamera;
    161 
    162         sp<MemoryBase> buffer = mBuffers[mCurrentPreviewFrame];
    163 
    164     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));
    170 
    171         // This is always valid, even if the client died -- the memory
    172         // is still mapped in our process.
    173         void *base = heap->base();
    174 
    175         // Fill the current frame with the fake camera.
    176         uint8_t *frame = ((uint8_t *)base) + offset;
    177         fakeCamera->getNextFrameAsYuv420(frame);
    178 
    179         //ALOGV("previewThread: generated frame to buffer %d", mCurrentPreviewFrame);
    180 
    181         // Notify the client of a new frame.
    182         if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)
    183             mDataCb(CAMERA_MSG_PREVIEW_FRAME, buffer, NULL, mCallbackCookie);
    184 
    185         // 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 
    195 status_t CameraHardwareStub::startPreview()
    196 {
    197     Mutex::Autolock lock(mLock);
    198     if (mPreviewThread != 0) {
    199         // already running
    200         return INVALID_OPERATION;
    201     }
    202     mPreviewThread = new PreviewThread(this);
    203     return NO_ERROR;
    204 }
    205 
    206 void CameraHardwareStub::stopPreview()
    207 {
    208     sp<PreviewThread> previewThread;
    209 
    210     { // 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 
    224 bool CameraHardwareStub::previewEnabled() {
    225     return mPreviewThread != 0;
    226 }
    227 
    228 status_t CameraHardwareStub::startRecording()
    229 {
    230     return UNKNOWN_ERROR;
    231 }
    232 
    233 void CameraHardwareStub::stopRecording()
    234 {
    235 }
    236 
    237 bool CameraHardwareStub::recordingEnabled()
    238 {
    239     return false;
    240 }
    241 
    242 void CameraHardwareStub::releaseRecordingFrame(const sp<IMemory>& mem)
    243 {
    244 }
    245 
    246 // ---------------------------------------------------------------------------
    247 
    248 int CameraHardwareStub::beginAutoFocusThread(void *cookie)
    249 {
    250     CameraHardwareStub *c = (CameraHardwareStub *)cookie;
    251     return c->autoFocusThread();
    252 }
    253 
    254 int CameraHardwareStub::autoFocusThread()
    255 {
    256     if (mMsgEnabled & CAMERA_MSG_FOCUS)
    257         mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie);
    258     return NO_ERROR;
    259 }
    260 
    261 status_t CameraHardwareStub::autoFocus()
    262 {
    263     Mutex::Autolock lock(mLock);
    264     if (createThread(beginAutoFocusThread, this) == false)
    265         return UNKNOWN_ERROR;
    266     return NO_ERROR;
    267 }
    268 
    269 status_t CameraHardwareStub::cancelAutoFocus()
    270 {
    271     return NO_ERROR;
    272 }
    273 
    274 /*static*/ int CameraHardwareStub::beginPictureThread(void *cookie)
    275 {
    276     CameraHardwareStub *c = (CameraHardwareStub *)cookie;
    277     return c->pictureThread();
    278 }
    279 
    280 int CameraHardwareStub::pictureThread()
    281 {
    282     if (mMsgEnabled & CAMERA_MSG_SHUTTER)
    283         mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie);
    284 
    285     if (mMsgEnabled & CAMERA_MSG_RAW_IMAGE) {
    286         //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);
    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, NULL, mCallbackCookie);
    294     }
    295 
    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, NULL, mCallbackCookie);
    301     }
    302     return NO_ERROR;
    303 }
    304 
    305 status_t CameraHardwareStub::takePicture()
    306 {
    307     stopPreview();
    308     if (createThread(beginPictureThread, this) == false)
    309         return UNKNOWN_ERROR;
    310     return NO_ERROR;
    311 }
    312 
    313 status_t CameraHardwareStub::cancelPicture()
    314 {
    315     return NO_ERROR;
    316 }
    317 
    318 status_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) {
    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);
    329     } else {
    330         result.append("No camera client yet.\n");
    331     }
    332     write(fd, result.string(), result.size());
    333     return NO_ERROR;
    334 }
    335 
    336 status_t CameraHardwareStub::setParameters(const CameraParameters& params)
    337 {
    338     Mutex::Autolock lock(mLock);
    339     // XXX verify params
    340 
    341     if (strcmp(params.getPreviewFormat(),
    342         CameraParameters::PIXEL_FORMAT_YUV420SP) != 0) {
    343         ALOGE("Only yuv420sp preview is supported");
    344         return -1;
    345     }
    346 
    347     if (strcmp(params.getPictureFormat(),
    348         CameraParameters::PIXEL_FORMAT_JPEG) != 0) {
    349         ALOGE("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         ALOGE("Still picture size must be size of canned JPEG (%dx%d)",
    357              kCannedJpegWidth, kCannedJpegHeight);
    358         return -1;
    359     }
    360 
    361     mParameters = params;
    362     initHeapLocked();
    363 
    364     return NO_ERROR;
    365 }
    366 
    367 CameraParameters CameraHardwareStub::getParameters() const
    368 {
    369     Mutex::Autolock lock(mLock);
    370     return mParameters;
    371 }
    372 
    373 status_t CameraHardwareStub::sendCommand(int32_t command, int32_t arg1,
    374                                          int32_t arg2)
    375 {
    376     return BAD_VALUE;
    377 }
    378 
    379 void CameraHardwareStub::release()
    380 {
    381 }
    382 
    383 sp<CameraHardwareInterface> CameraHardwareStub::createInstance()
    384 {
    385     return new CameraHardwareStub();
    386 }
    387 
    388 static CameraInfo sCameraInfo[] = {
    389     {
    390         CAMERA_FACING_BACK,
    391         90,  /* orientation */
    392     }
    393 };
    394 
    395 extern "C" int HAL_getNumberOfCameras()
    396 {
    397     return sizeof(sCameraInfo) / sizeof(sCameraInfo[0]);
    398 }
    399 
    400 extern "C" void HAL_getCameraInfo(int cameraId, struct CameraInfo* cameraInfo)
    401 {
    402     memcpy(cameraInfo, &sCameraInfo[cameraId], sizeof(CameraInfo));
    403 }
    404 
    405 extern "C" sp<CameraHardwareInterface> HAL_openCameraHardware(int cameraId)
    406 {
    407     return CameraHardwareStub::createInstance();
    408 }
    409 
    410 }; // namespace android
    411