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 CallbackNotifier that manages callbacks set
     19  * via set_callbacks, enable_msg_type, and disable_msg_type camera HAL API.
     20  */
     21 
     22 #define LOG_NDEBUG 0
     23 #define LOG_TAG "EmulatedCamera_CallbackNotifier"
     24 #include <cutils/log.h>
     25 #include <MetadataBufferType.h>
     26 #include "EmulatedCameraDevice.h"
     27 #include "CallbackNotifier.h"
     28 #include "JpegCompressor.h"
     29 
     30 namespace android {
     31 
     32 /* String representation of camera messages. */
     33 static const char* lCameraMessages[] =
     34 {
     35     "CAMERA_MSG_ERROR",
     36     "CAMERA_MSG_SHUTTER",
     37     "CAMERA_MSG_FOCUS",
     38     "CAMERA_MSG_ZOOM",
     39     "CAMERA_MSG_PREVIEW_FRAME",
     40     "CAMERA_MSG_VIDEO_FRAME",
     41     "CAMERA_MSG_POSTVIEW_FRAME",
     42     "CAMERA_MSG_RAW_IMAGE",
     43     "CAMERA_MSG_COMPRESSED_IMAGE",
     44     "CAMERA_MSG_RAW_IMAGE_NOTIFY",
     45     "CAMERA_MSG_PREVIEW_METADATA"
     46 };
     47 static const int lCameraMessagesNum = sizeof(lCameraMessages) / sizeof(char*);
     48 
     49 /* Builds an array of strings for the given set of messages.
     50  * Param:
     51  *  msg - Messages to get strings for,
     52  *  strings - Array where to save strings
     53  *  max - Maximum number of entries in the array.
     54  * Return:
     55  *  Number of strings saved into the 'strings' array.
     56  */
     57 static int GetMessageStrings(uint32_t msg, const char** strings, int max)
     58 {
     59     int index = 0;
     60     int out = 0;
     61     while (msg != 0 && out < max && index < lCameraMessagesNum) {
     62         while ((msg & 0x1) == 0 && index < lCameraMessagesNum) {
     63             msg >>= 1;
     64             index++;
     65         }
     66         if ((msg & 0x1) != 0 && index < lCameraMessagesNum) {
     67             strings[out] = lCameraMessages[index];
     68             out++;
     69             msg >>= 1;
     70             index++;
     71         }
     72     }
     73 
     74     return out;
     75 }
     76 
     77 /* Logs messages, enabled by the mask. */
     78 static void PrintMessages(uint32_t msg)
     79 {
     80     const char* strs[lCameraMessagesNum];
     81     const int translated = GetMessageStrings(msg, strs, lCameraMessagesNum);
     82     for (int n = 0; n < translated; n++) {
     83         ALOGV("    %s", strs[n]);
     84     }
     85 }
     86 
     87 CallbackNotifier::CallbackNotifier()
     88     : mNotifyCB(NULL),
     89       mDataCB(NULL),
     90       mDataCBTimestamp(NULL),
     91       mGetMemoryCB(NULL),
     92       mCBOpaque(NULL),
     93       mLastFrameTimestamp(0),
     94       mFrameRefreshFreq(0),
     95       mMessageEnabler(0),
     96       mJpegQuality(90),
     97       mVideoRecEnabled(false),
     98       mTakingPicture(false)
     99 {
    100 }
    101 
    102 CallbackNotifier::~CallbackNotifier()
    103 {
    104 }
    105 
    106 /****************************************************************************
    107  * Camera API
    108  ***************************************************************************/
    109 
    110 void CallbackNotifier::setCallbacks(camera_notify_callback notify_cb,
    111                                     camera_data_callback data_cb,
    112                                     camera_data_timestamp_callback data_cb_timestamp,
    113                                     camera_request_memory get_memory,
    114                                     void* user)
    115 {
    116     ALOGV("%s: %p, %p, %p, %p (%p)",
    117          __FUNCTION__, notify_cb, data_cb, data_cb_timestamp, get_memory, user);
    118 
    119     Mutex::Autolock locker(&mObjectLock);
    120     mNotifyCB = notify_cb;
    121     mDataCB = data_cb;
    122     mDataCBTimestamp = data_cb_timestamp;
    123     mGetMemoryCB = get_memory;
    124     mCBOpaque = user;
    125 }
    126 
    127 void CallbackNotifier::enableMessage(uint msg_type)
    128 {
    129     ALOGV("%s: msg_type = 0x%x", __FUNCTION__, msg_type);
    130     PrintMessages(msg_type);
    131 
    132     Mutex::Autolock locker(&mObjectLock);
    133     mMessageEnabler |= msg_type;
    134     ALOGV("**** Currently enabled messages:");
    135     PrintMessages(mMessageEnabler);
    136 }
    137 
    138 void CallbackNotifier::disableMessage(uint msg_type)
    139 {
    140     ALOGV("%s: msg_type = 0x%x", __FUNCTION__, msg_type);
    141     PrintMessages(msg_type);
    142 
    143     Mutex::Autolock locker(&mObjectLock);
    144     mMessageEnabler &= ~msg_type;
    145     ALOGV("**** Currently enabled messages:");
    146     PrintMessages(mMessageEnabler);
    147 }
    148 
    149 status_t CallbackNotifier::enableVideoRecording(int fps)
    150 {
    151     ALOGV("%s: FPS = %d", __FUNCTION__, fps);
    152 
    153     Mutex::Autolock locker(&mObjectLock);
    154     mVideoRecEnabled = true;
    155     mLastFrameTimestamp = 0;
    156     mFrameRefreshFreq = 1000000000LL / fps;
    157 
    158     return NO_ERROR;
    159 }
    160 
    161 void CallbackNotifier::disableVideoRecording()
    162 {
    163     ALOGV("%s:", __FUNCTION__);
    164 
    165     Mutex::Autolock locker(&mObjectLock);
    166     mVideoRecEnabled = false;
    167     mLastFrameTimestamp = 0;
    168     mFrameRefreshFreq = 0;
    169 }
    170 
    171 void CallbackNotifier::releaseRecordingFrame(const void* opaque)
    172 {
    173     List<camera_memory_t*>::iterator it = mCameraMemoryTs.begin();
    174     for( ; it != mCameraMemoryTs.end(); ++it ) {
    175         if ( (*it)->data == opaque ) {
    176             (*it)->release( *it );
    177             mCameraMemoryTs.erase(it);
    178             break;
    179         }
    180     }
    181 }
    182 
    183 status_t CallbackNotifier::storeMetaDataInBuffers(bool enable)
    184 {
    185     /* Return INVALID_OPERATION means HAL does not support metadata. So HAL will
    186      * return actual frame data with CAMERA_MSG_VIDEO_FRRAME. Return
    187      * INVALID_OPERATION to mean metadata is not supported. */
    188     return INVALID_OPERATION;
    189 }
    190 
    191 /****************************************************************************
    192  * Public API
    193  ***************************************************************************/
    194 
    195 void CallbackNotifier::cleanupCBNotifier()
    196 {
    197     Mutex::Autolock locker(&mObjectLock);
    198     mMessageEnabler = 0;
    199     mNotifyCB = NULL;
    200     mDataCB = NULL;
    201     mDataCBTimestamp = NULL;
    202     mGetMemoryCB = NULL;
    203     mCBOpaque = NULL;
    204     mLastFrameTimestamp = 0;
    205     mFrameRefreshFreq = 0;
    206     mJpegQuality = 90;
    207     mVideoRecEnabled = false;
    208     mTakingPicture = false;
    209 }
    210 
    211 void CallbackNotifier::onNextFrameAvailable(const void* frame,
    212                                             nsecs_t timestamp,
    213                                             EmulatedCameraDevice* camera_dev)
    214 {
    215     if (isMessageEnabled(CAMERA_MSG_VIDEO_FRAME) && isVideoRecordingEnabled() &&
    216             isNewVideoFrameTime(timestamp)) {
    217         camera_memory_t* cam_buff =
    218             mGetMemoryCB(-1, camera_dev->getFrameBufferSize(), 1, NULL);
    219         if (NULL != cam_buff && NULL != cam_buff->data) {
    220             memcpy(cam_buff->data, frame, camera_dev->getFrameBufferSize());
    221             mDataCBTimestamp(timestamp, CAMERA_MSG_VIDEO_FRAME,
    222                                cam_buff, 0, mCBOpaque);
    223 
    224             mCameraMemoryTs.push_back( cam_buff );
    225         } else {
    226             ALOGE("%s: Memory failure in CAMERA_MSG_VIDEO_FRAME", __FUNCTION__);
    227         }
    228     }
    229 
    230     if (isMessageEnabled(CAMERA_MSG_PREVIEW_FRAME)) {
    231         camera_memory_t* cam_buff =
    232             mGetMemoryCB(-1, camera_dev->getFrameBufferSize(), 1, NULL);
    233         if (NULL != cam_buff && NULL != cam_buff->data) {
    234             memcpy(cam_buff->data, frame, camera_dev->getFrameBufferSize());
    235             mDataCB(CAMERA_MSG_PREVIEW_FRAME, cam_buff, 0, NULL, mCBOpaque);
    236             cam_buff->release(cam_buff);
    237         } else {
    238             ALOGE("%s: Memory failure in CAMERA_MSG_PREVIEW_FRAME", __FUNCTION__);
    239         }
    240     }
    241 
    242     if (mTakingPicture) {
    243         /* This happens just once. */
    244         mTakingPicture = false;
    245         /* The sequence of callbacks during picture taking is:
    246          *  - CAMERA_MSG_SHUTTER
    247          *  - CAMERA_MSG_RAW_IMAGE_NOTIFY
    248          *  - CAMERA_MSG_COMPRESSED_IMAGE
    249          */
    250         if (isMessageEnabled(CAMERA_MSG_SHUTTER)) {
    251             mNotifyCB(CAMERA_MSG_SHUTTER, 0, 0, mCBOpaque);
    252         }
    253         if (isMessageEnabled(CAMERA_MSG_RAW_IMAGE_NOTIFY)) {
    254             mNotifyCB(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, mCBOpaque);
    255         }
    256         if (isMessageEnabled(CAMERA_MSG_COMPRESSED_IMAGE)) {
    257             /* Compress the frame to JPEG. Note that when taking pictures, we
    258              * have requested camera device to provide us with NV21 frames. */
    259             NV21JpegCompressor compressor;
    260             status_t res =
    261                 compressor.compressRawImage(frame, camera_dev->getFrameWidth(),
    262                                             camera_dev->getFrameHeight(),
    263                                             mJpegQuality);
    264             if (res == NO_ERROR) {
    265                 camera_memory_t* jpeg_buff =
    266                     mGetMemoryCB(-1, compressor.getCompressedSize(), 1, NULL);
    267                 if (NULL != jpeg_buff && NULL != jpeg_buff->data) {
    268                     compressor.getCompressedImage(jpeg_buff->data);
    269                     mDataCB(CAMERA_MSG_COMPRESSED_IMAGE, jpeg_buff, 0, NULL, mCBOpaque);
    270                     jpeg_buff->release(jpeg_buff);
    271                 } else {
    272                     ALOGE("%s: Memory failure in CAMERA_MSG_VIDEO_FRAME", __FUNCTION__);
    273                 }
    274             } else {
    275                 ALOGE("%s: Compression failure in CAMERA_MSG_VIDEO_FRAME", __FUNCTION__);
    276             }
    277         }
    278     }
    279 }
    280 
    281 void CallbackNotifier::onCameraDeviceError(int err)
    282 {
    283     if (isMessageEnabled(CAMERA_MSG_ERROR) && mNotifyCB != NULL) {
    284         mNotifyCB(CAMERA_MSG_ERROR, err, 0, mCBOpaque);
    285     }
    286 }
    287 
    288 /****************************************************************************
    289  * Private API
    290  ***************************************************************************/
    291 
    292 bool CallbackNotifier::isNewVideoFrameTime(nsecs_t timestamp)
    293 {
    294     Mutex::Autolock locker(&mObjectLock);
    295     if ((timestamp - mLastFrameTimestamp) >= mFrameRefreshFreq) {
    296         mLastFrameTimestamp = timestamp;
    297         return true;
    298     }
    299     return false;
    300 }
    301 
    302 }; /* namespace android */
    303