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 <ui/Rect.h>
     26 #include <ui/GraphicBufferMapper.h>
     27 #include "EmulatedCameraDevice.h"
     28 #include "PreviewWindow.h"
     29 
     30 namespace android {
     31 
     32 PreviewWindow::PreviewWindow()
     33     : mPreviewWindow(NULL),
     34       mLastPreviewed(0),
     35       mPreviewFrameWidth(0),
     36       mPreviewFrameHeight(0),
     37       mPreviewEnabled(false)
     38 {
     39 }
     40 
     41 PreviewWindow::~PreviewWindow()
     42 {
     43 }
     44 
     45 /****************************************************************************
     46  * Camera API
     47  ***************************************************************************/
     48 
     49 status_t PreviewWindow::setPreviewWindow(struct preview_stream_ops* window,
     50                                          int preview_fps)
     51 {
     52     ALOGV("%s: current: %p -> new: %p", __FUNCTION__, mPreviewWindow, window);
     53 
     54     status_t res = NO_ERROR;
     55     Mutex::Autolock locker(&mObjectLock);
     56 
     57     /* Reset preview info. */
     58     mPreviewFrameWidth = mPreviewFrameHeight = 0;
     59     mPreviewAfter = 0;
     60     mLastPreviewed = 0;
     61 
     62     if (window != NULL) {
     63         /* The CPU will write each frame to the preview window buffer.
     64          * Note that we delay setting preview window buffer geometry until
     65          * frames start to come in. */
     66         res = window->set_usage(window, GRALLOC_USAGE_SW_WRITE_OFTEN);
     67         if (res == NO_ERROR) {
     68             /* Set preview frequency. */
     69             mPreviewAfter = 1000000 / preview_fps;
     70         } else {
     71             window = NULL;
     72             res = -res; // set_usage returns a negative errno.
     73             ALOGE("%s: Error setting preview window usage %d -> %s",
     74                  __FUNCTION__, res, strerror(res));
     75         }
     76     }
     77     mPreviewWindow = window;
     78 
     79     return res;
     80 }
     81 
     82 status_t PreviewWindow::startPreview()
     83 {
     84     ALOGV("%s", __FUNCTION__);
     85 
     86     Mutex::Autolock locker(&mObjectLock);
     87     mPreviewEnabled = true;
     88 
     89     return NO_ERROR;
     90 }
     91 
     92 void PreviewWindow::stopPreview()
     93 {
     94     ALOGV("%s", __FUNCTION__);
     95 
     96     Mutex::Autolock locker(&mObjectLock);
     97     mPreviewEnabled = false;
     98 }
     99 
    100 /****************************************************************************
    101  * Public API
    102  ***************************************************************************/
    103 
    104 void PreviewWindow::onNextFrameAvailable(const void* frame,
    105                                          nsecs_t timestamp,
    106                                          EmulatedCameraDevice* camera_dev)
    107 {
    108     int res;
    109     Mutex::Autolock locker(&mObjectLock);
    110 
    111     if (!isPreviewEnabled() || mPreviewWindow == NULL || !isPreviewTime()) {
    112         return;
    113     }
    114 
    115     /* Make sure that preview window dimensions are OK with the camera device */
    116     if (adjustPreviewDimensions(camera_dev)) {
    117         /* Need to set / adjust buffer geometry for the preview window.
    118          * Note that in the emulator preview window uses only RGB for pixel
    119          * formats. */
    120         ALOGV("%s: Adjusting preview windows %p geometry to %dx%d",
    121              __FUNCTION__, mPreviewWindow, mPreviewFrameWidth,
    122              mPreviewFrameHeight);
    123         res = mPreviewWindow->set_buffers_geometry(mPreviewWindow,
    124                                                    mPreviewFrameWidth,
    125                                                    mPreviewFrameHeight,
    126                                                    HAL_PIXEL_FORMAT_RGBA_8888);
    127         if (res != NO_ERROR) {
    128             ALOGE("%s: Error in set_buffers_geometry %d -> %s",
    129                  __FUNCTION__, -res, strerror(-res));
    130             return;
    131         }
    132     }
    133 
    134     /*
    135      * Push new frame to the preview window.
    136      */
    137 
    138     /* Dequeue preview window buffer for the frame. */
    139     buffer_handle_t* buffer = NULL;
    140     int stride = 0;
    141     res = mPreviewWindow->dequeue_buffer(mPreviewWindow, &buffer, &stride);
    142     if (res != NO_ERROR || buffer == NULL) {
    143         ALOGE("%s: Unable to dequeue preview window buffer: %d -> %s",
    144             __FUNCTION__, -res, strerror(-res));
    145         return;
    146     }
    147 
    148     /* Let the preview window to lock the buffer. */
    149     res = mPreviewWindow->lock_buffer(mPreviewWindow, buffer);
    150     if (res != NO_ERROR) {
    151         ALOGE("%s: Unable to lock preview window buffer: %d -> %s",
    152              __FUNCTION__, -res, strerror(-res));
    153         mPreviewWindow->cancel_buffer(mPreviewWindow, buffer);
    154         return;
    155     }
    156 
    157     /* Now let the graphics framework to lock the buffer, and provide
    158      * us with the framebuffer data address. */
    159     void* img = NULL;
    160     const Rect rect(mPreviewFrameWidth, mPreviewFrameHeight);
    161     GraphicBufferMapper& grbuffer_mapper(GraphicBufferMapper::get());
    162     res = grbuffer_mapper.lock(*buffer, GRALLOC_USAGE_SW_WRITE_OFTEN, rect, &img);
    163     if (res != NO_ERROR) {
    164         ALOGE("%s: grbuffer_mapper.lock failure: %d -> %s",
    165              __FUNCTION__, res, strerror(res));
    166         mPreviewWindow->cancel_buffer(mPreviewWindow, buffer);
    167         return;
    168     }
    169 
    170     /* Frames come in in YV12/NV12/NV21 format. Since preview window doesn't
    171      * supports those formats, we need to obtain the frame in RGB565. */
    172     res = camera_dev->getCurrentPreviewFrame(img);
    173     if (res == NO_ERROR) {
    174         /* Show it. */
    175         mPreviewWindow->set_timestamp(mPreviewWindow, timestamp);
    176         mPreviewWindow->enqueue_buffer(mPreviewWindow, buffer);
    177     } else {
    178         ALOGE("%s: Unable to obtain preview frame: %d", __FUNCTION__, res);
    179         mPreviewWindow->cancel_buffer(mPreviewWindow, buffer);
    180     }
    181     grbuffer_mapper.unlock(*buffer);
    182 }
    183 
    184 /***************************************************************************
    185  * Private API
    186  **************************************************************************/
    187 
    188 bool PreviewWindow::adjustPreviewDimensions(EmulatedCameraDevice* camera_dev)
    189 {
    190     /* Match the cached frame dimensions against the actual ones. */
    191     if (mPreviewFrameWidth == camera_dev->getFrameWidth() &&
    192         mPreviewFrameHeight == camera_dev->getFrameHeight()) {
    193         /* They match. */
    194         return false;
    195     }
    196 
    197     /* They don't match: adjust the cache. */
    198     mPreviewFrameWidth = camera_dev->getFrameWidth();
    199     mPreviewFrameHeight = camera_dev->getFrameHeight();
    200 
    201     return true;
    202 }
    203 
    204 bool PreviewWindow::isPreviewTime()
    205 {
    206     timeval cur_time;
    207     gettimeofday(&cur_time, NULL);
    208     const uint64_t cur_mks = cur_time.tv_sec * 1000000LL + cur_time.tv_usec;
    209     if ((cur_mks - mLastPreviewed) >= mPreviewAfter) {
    210         mLastPreviewed = cur_mks;
    211         return true;
    212     }
    213     return false;
    214 }
    215 
    216 }; /* namespace android */
    217