Home | History | Annotate | Download | only in camera
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /*
     18  * Contains implementation of a class PreviewWindow that encapsulates
     19  * functionality of a preview window set via set_preview_window camera HAL API.
     20  */
     21 
     22 #define LOG_NDEBUG 0
     23 #define LOG_TAG "EmulatedCamera_Preview"
     24 #include <cutils/log.h>
     25 #include "EmulatedCameraDevice.h"
     26 #include "PreviewWindow.h"
     27 #include "GrallocModule.h"
     28 
     29 namespace android {
     30 
     31 PreviewWindow::PreviewWindow()
     32     : mPreviewWindow(NULL),
     33       mPreviewFrameWidth(0),
     34       mPreviewFrameHeight(0),
     35       mPreviewEnabled(false)
     36 {
     37 }
     38 
     39 PreviewWindow::~PreviewWindow()
     40 {
     41 }
     42 
     43 /****************************************************************************
     44  * Camera API
     45  ***************************************************************************/
     46 
     47 status_t PreviewWindow::setPreviewWindow(struct preview_stream_ops* window,
     48                                          int preview_fps)
     49 {
     50     ALOGV("%s: current: %p -> new: %p", __FUNCTION__, mPreviewWindow, window);
     51 
     52     status_t res = NO_ERROR;
     53     Mutex::Autolock locker(&mObjectLock);
     54 
     55     /* Reset preview info. */
     56     mPreviewFrameWidth = mPreviewFrameHeight = 0;
     57 
     58     if (window != NULL) {
     59         /* The CPU will write each frame to the preview window buffer.
     60          * Note that we delay setting preview window buffer geometry until
     61          * frames start to come in. */
     62         res = window->set_usage(window, GRALLOC_USAGE_SW_WRITE_OFTEN);
     63         if (res != NO_ERROR) {
     64             window = NULL;
     65             res = -res; // set_usage returns a negative errno.
     66             ALOGE("%s: Error setting preview window usage %d -> %s",
     67                  __FUNCTION__, res, strerror(res));
     68         }
     69     }
     70     mPreviewWindow = window;
     71 
     72     return res;
     73 }
     74 
     75 status_t PreviewWindow::startPreview()
     76 {
     77     ALOGV("%s", __FUNCTION__);
     78 
     79     Mutex::Autolock locker(&mObjectLock);
     80     mPreviewEnabled = true;
     81 
     82     return NO_ERROR;
     83 }
     84 
     85 void PreviewWindow::stopPreview()
     86 {
     87     ALOGV("%s", __FUNCTION__);
     88 
     89     Mutex::Autolock locker(&mObjectLock);
     90     mPreviewEnabled = false;
     91 }
     92 
     93 /****************************************************************************
     94  * Public API
     95  ***************************************************************************/
     96 
     97 void PreviewWindow::onNextFrameAvailable(nsecs_t timestamp,
     98                                          EmulatedCameraDevice* camera_dev)
     99 {
    100     int res;
    101     Mutex::Autolock locker(&mObjectLock);
    102 
    103     if (!isPreviewEnabled() || mPreviewWindow == NULL) {
    104         return;
    105     }
    106 
    107     /* Make sure that preview window dimensions are OK with the camera device */
    108     if (adjustPreviewDimensions(camera_dev)) {
    109         /* Need to set / adjust buffer geometry for the preview window.
    110          * Note that in the emulator preview window uses only RGB for pixel
    111          * formats. */
    112         ALOGV("%s: Adjusting preview windows %p geometry to %dx%d",
    113              __FUNCTION__, mPreviewWindow, mPreviewFrameWidth,
    114              mPreviewFrameHeight);
    115         res = mPreviewWindow->set_buffers_geometry(mPreviewWindow,
    116                                                    mPreviewFrameWidth,
    117                                                    mPreviewFrameHeight,
    118                                                    HAL_PIXEL_FORMAT_RGBA_8888);
    119         if (res != NO_ERROR) {
    120             ALOGE("%s: Error in set_buffers_geometry %d -> %s",
    121                  __FUNCTION__, -res, strerror(-res));
    122             return;
    123         }
    124     }
    125 
    126     /*
    127      * Push new frame to the preview window.
    128      */
    129 
    130     /* Dequeue preview window buffer for the frame. */
    131     buffer_handle_t* buffer = NULL;
    132     int stride = 0;
    133     res = mPreviewWindow->dequeue_buffer(mPreviewWindow, &buffer, &stride);
    134     if (res != NO_ERROR || buffer == NULL) {
    135         ALOGE("%s: Unable to dequeue preview window buffer: %d -> %s",
    136             __FUNCTION__, -res, strerror(-res));
    137         return;
    138     }
    139 
    140     /* Let the preview window to lock the buffer. */
    141     res = mPreviewWindow->lock_buffer(mPreviewWindow, buffer);
    142     if (res != NO_ERROR) {
    143         ALOGE("%s: Unable to lock preview window buffer: %d -> %s",
    144              __FUNCTION__, -res, strerror(-res));
    145         mPreviewWindow->cancel_buffer(mPreviewWindow, buffer);
    146         return;
    147     }
    148 
    149     /* Now let the graphics framework to lock the buffer, and provide
    150      * us with the framebuffer data address. */
    151     void* img = NULL;
    152     res = GrallocModule::getInstance().lock(
    153         *buffer, GRALLOC_USAGE_SW_WRITE_OFTEN,
    154         0, 0, mPreviewFrameWidth, mPreviewFrameHeight, &img);
    155     if (res != NO_ERROR) {
    156         ALOGE("%s: gralloc.lock failure: %d -> %s",
    157              __FUNCTION__, res, strerror(res));
    158         mPreviewWindow->cancel_buffer(mPreviewWindow, buffer);
    159         return;
    160     }
    161 
    162     int64_t frame_timestamp = 0L;
    163     /* Frames come in in YV12/NV12/NV21 format. Since preview window doesn't
    164      * supports those formats, we need to obtain the frame in RGB565. */
    165     res = camera_dev->getCurrentPreviewFrame(img, &frame_timestamp);
    166     if (res == NO_ERROR) {
    167         /* Show it. */
    168         mPreviewWindow->set_timestamp(mPreviewWindow,
    169                                       frame_timestamp != 0L ? frame_timestamp : timestamp);
    170         mPreviewWindow->enqueue_buffer(mPreviewWindow, buffer);
    171     } else {
    172         ALOGE("%s: Unable to obtain preview frame: %d", __FUNCTION__, res);
    173         mPreviewWindow->cancel_buffer(mPreviewWindow, buffer);
    174     }
    175     GrallocModule::getInstance().unlock(*buffer);
    176 }
    177 
    178 /***************************************************************************
    179  * Private API
    180  **************************************************************************/
    181 
    182 bool PreviewWindow::adjustPreviewDimensions(EmulatedCameraDevice* camera_dev)
    183 {
    184     /* Match the cached frame dimensions against the actual ones. */
    185     if (mPreviewFrameWidth == camera_dev->getFrameWidth() &&
    186         mPreviewFrameHeight == camera_dev->getFrameHeight()) {
    187         /* They match. */
    188         return false;
    189     }
    190 
    191     /* They don't match: adjust the cache. */
    192     mPreviewFrameWidth = camera_dev->getFrameWidth();
    193     mPreviewFrameHeight = camera_dev->getFrameHeight();
    194 
    195     return true;
    196 }
    197 
    198 }; /* namespace android */
    199