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 #undef min
     28 #undef max
     29 #include "CallbackNotifier.h"
     30 #include "Exif.h"
     31 #include "JpegCompressor.h"
     32 #include "Thumbnail.h"
     33 
     34 namespace android {
     35 
     36 /* String representation of camera messages. */
     37 static const char* lCameraMessages[] =
     38 {
     39     "CAMERA_MSG_ERROR",
     40     "CAMERA_MSG_SHUTTER",
     41     "CAMERA_MSG_FOCUS",
     42     "CAMERA_MSG_ZOOM",
     43     "CAMERA_MSG_PREVIEW_FRAME",
     44     "CAMERA_MSG_VIDEO_FRAME",
     45     "CAMERA_MSG_POSTVIEW_FRAME",
     46     "CAMERA_MSG_RAW_IMAGE",
     47     "CAMERA_MSG_COMPRESSED_IMAGE",
     48     "CAMERA_MSG_RAW_IMAGE_NOTIFY",
     49     "CAMERA_MSG_PREVIEW_METADATA"
     50 };
     51 static const int lCameraMessagesNum = sizeof(lCameraMessages) / sizeof(char*);
     52 
     53 /* Builds an array of strings for the given set of messages.
     54  * Param:
     55  *  msg - Messages to get strings for,
     56  *  strings - Array where to save strings
     57  *  max - Maximum number of entries in the array.
     58  * Return:
     59  *  Number of strings saved into the 'strings' array.
     60  */
     61 static int GetMessageStrings(uint32_t msg, const char** strings, int max)
     62 {
     63     int index = 0;
     64     int out = 0;
     65     while (msg != 0 && out < max && index < lCameraMessagesNum) {
     66         while ((msg & 0x1) == 0 && index < lCameraMessagesNum) {
     67             msg >>= 1;
     68             index++;
     69         }
     70         if ((msg & 0x1) != 0 && index < lCameraMessagesNum) {
     71             strings[out] = lCameraMessages[index];
     72             out++;
     73             msg >>= 1;
     74             index++;
     75         }
     76     }
     77 
     78     return out;
     79 }
     80 
     81 /* Logs messages, enabled by the mask. */
     82 static void PrintMessages(uint32_t msg)
     83 {
     84     const char* strs[lCameraMessagesNum];
     85     const int translated = GetMessageStrings(msg, strs, lCameraMessagesNum);
     86     for (int n = 0; n < translated; n++) {
     87         ALOGV("    %s", strs[n]);
     88     }
     89 }
     90 
     91 CallbackNotifier::CallbackNotifier()
     92     : mNotifyCB(NULL),
     93       mDataCB(NULL),
     94       mDataCBTimestamp(NULL),
     95       mGetMemoryCB(NULL),
     96       mCBOpaque(NULL),
     97       mLastFrameTimestamp(0),
     98       mFrameRefreshFreq(0),
     99       mMessageEnabler(0),
    100       mJpegQuality(90),
    101       mVideoRecEnabled(false),
    102       mTakingPicture(false)
    103 {
    104 }
    105 
    106 CallbackNotifier::~CallbackNotifier()
    107 {
    108 }
    109 
    110 /****************************************************************************
    111  * Camera API
    112  ***************************************************************************/
    113 
    114 void CallbackNotifier::setCallbacks(camera_notify_callback notify_cb,
    115                                     camera_data_callback data_cb,
    116                                     camera_data_timestamp_callback data_cb_timestamp,
    117                                     camera_request_memory get_memory,
    118                                     void* user)
    119 {
    120     ALOGV("%s: %p, %p, %p, %p (%p)",
    121          __FUNCTION__, notify_cb, data_cb, data_cb_timestamp, get_memory, user);
    122 
    123     Mutex::Autolock locker(&mObjectLock);
    124     mNotifyCB = notify_cb;
    125     mDataCB = data_cb;
    126     mDataCBTimestamp = data_cb_timestamp;
    127     mGetMemoryCB = get_memory;
    128     mCBOpaque = user;
    129 }
    130 
    131 void CallbackNotifier::enableMessage(uint msg_type)
    132 {
    133     ALOGV("%s: msg_type = 0x%x", __FUNCTION__, msg_type);
    134     PrintMessages(msg_type);
    135 
    136     Mutex::Autolock locker(&mObjectLock);
    137     mMessageEnabler |= msg_type;
    138     ALOGV("**** Currently enabled messages:");
    139     PrintMessages(mMessageEnabler);
    140 }
    141 
    142 void CallbackNotifier::disableMessage(uint msg_type)
    143 {
    144     ALOGV("%s: msg_type = 0x%x", __FUNCTION__, msg_type);
    145     PrintMessages(msg_type);
    146 
    147     Mutex::Autolock locker(&mObjectLock);
    148     mMessageEnabler &= ~msg_type;
    149     ALOGV("**** Currently enabled messages:");
    150     PrintMessages(mMessageEnabler);
    151 }
    152 
    153 status_t CallbackNotifier::enableVideoRecording(int fps)
    154 {
    155     ALOGV("%s: FPS = %d", __FUNCTION__, fps);
    156 
    157     Mutex::Autolock locker(&mObjectLock);
    158     mVideoRecEnabled = true;
    159     mLastFrameTimestamp = 0;
    160     mFrameRefreshFreq = 1000000000LL / fps;
    161 
    162     return NO_ERROR;
    163 }
    164 
    165 void CallbackNotifier::disableVideoRecording()
    166 {
    167     ALOGV("%s:", __FUNCTION__);
    168 
    169     Mutex::Autolock locker(&mObjectLock);
    170     mVideoRecEnabled = false;
    171     mLastFrameTimestamp = 0;
    172     mFrameRefreshFreq = 0;
    173 }
    174 
    175 void CallbackNotifier::releaseRecordingFrame(const void* opaque)
    176 {
    177     List<camera_memory_t*>::iterator it = mCameraMemoryTs.begin();
    178     for( ; it != mCameraMemoryTs.end(); ++it ) {
    179         if ( (*it)->data == opaque ) {
    180             (*it)->release( *it );
    181             mCameraMemoryTs.erase(it);
    182             break;
    183         }
    184     }
    185 }
    186 
    187 void CallbackNotifier::autoFocusComplete() {
    188     // Even though we don't support auto-focus we are expected to send a fake
    189     // success message according to the documentation.
    190     // https://developer.android.com/reference/android/hardware/Camera.AutoFocusCallback.html
    191     mNotifyCB(CAMERA_MSG_FOCUS, true, 0, mCBOpaque);
    192 }
    193 
    194 status_t CallbackNotifier::storeMetaDataInBuffers(bool enable)
    195 {
    196     // Return error if metadata is request, otherwise silently agree.
    197     return enable ? INVALID_OPERATION : NO_ERROR;
    198 }
    199 
    200 /****************************************************************************
    201  * Public API
    202  ***************************************************************************/
    203 
    204 void CallbackNotifier::cleanupCBNotifier()
    205 {
    206     Mutex::Autolock locker(&mObjectLock);
    207     mMessageEnabler = 0;
    208     mNotifyCB = NULL;
    209     mDataCB = NULL;
    210     mDataCBTimestamp = NULL;
    211     mGetMemoryCB = NULL;
    212     mCBOpaque = NULL;
    213     mLastFrameTimestamp = 0;
    214     mFrameRefreshFreq = 0;
    215     mJpegQuality = 90;
    216     mVideoRecEnabled = false;
    217     mTakingPicture = false;
    218 }
    219 
    220 void CallbackNotifier::onNextFrameAvailable(nsecs_t timestamp,
    221                                             EmulatedCameraDevice* camera_dev)
    222 {
    223     if (isMessageEnabled(CAMERA_MSG_VIDEO_FRAME) && isVideoRecordingEnabled() &&
    224             isNewVideoFrameTime(timestamp)) {
    225         // This is the path for video frames, the format used here is not
    226         // exposed to external users so it can be whatever the camera and the
    227         // encoder can agree upon. The emulator system images use software
    228         // encoders that expect a YUV420 format but the camera parameter
    229         // constants cannot represent this. The closest we have is YV12 which is
    230         // YVU420. So we produce YV12 frames so that we can serve those through
    231         // the preview callback below and then we convert from YV12 to YUV420
    232         // here. This is a pretty cheap conversion in most cases since we have
    233         // to copy the frame here anyway. In the best (and most common) cases
    234         // the conversion is just copying the U and V parts of the frame in
    235         // different order. A slightly more expensive case is when the YV12
    236         // frame has padding to ensure that rows are aligned to 16-byte
    237         // boundaries. The YUV420 format expected by the encoders do not have
    238         // this alignment so it has to be removed. This way the encoder gets the
    239         // format it expects and the preview callback (or data callback) below
    240         // gets the format that is configured in camera parameters.
    241         const size_t frameSize = camera_dev->getVideoFrameBufferSize();
    242         camera_memory_t* cam_buff = mGetMemoryCB(-1, frameSize, 1, mCBOpaque);
    243         if (NULL != cam_buff && NULL != cam_buff->data) {
    244             int64_t frame_timestamp = 0L;
    245             camera_dev->getCurrentFrame(cam_buff->data, V4L2_PIX_FMT_YUV420,
    246                                         &frame_timestamp);
    247             mDataCBTimestamp(frame_timestamp != 0L ? frame_timestamp : timestamp,
    248                              CAMERA_MSG_VIDEO_FRAME, cam_buff, 0, mCBOpaque);
    249             mCameraMemoryTs.push_back( cam_buff );
    250         } else {
    251             ALOGE("%s: Memory failure in CAMERA_MSG_VIDEO_FRAME", __FUNCTION__);
    252         }
    253     }
    254 
    255     if (isMessageEnabled(CAMERA_MSG_PREVIEW_FRAME)) {
    256         camera_memory_t* cam_buff =
    257             mGetMemoryCB(-1, camera_dev->getFrameBufferSize(), 1, mCBOpaque);
    258         if (NULL != cam_buff && NULL != cam_buff->data) {
    259             int64_t frame_timestamp = 0L;
    260             camera_dev->getCurrentFrame(cam_buff->data,
    261                                         camera_dev->getOriginalPixelFormat(),
    262                                         &frame_timestamp);
    263             mDataCB(CAMERA_MSG_PREVIEW_FRAME, cam_buff, 0, NULL, mCBOpaque);
    264             cam_buff->release(cam_buff);
    265         } else {
    266             ALOGE("%s: Memory failure in CAMERA_MSG_PREVIEW_FRAME", __FUNCTION__);
    267         }
    268     }
    269 
    270     if (mTakingPicture) {
    271         /* This happens just once. */
    272         mTakingPicture = false;
    273         /* The sequence of callbacks during picture taking is:
    274          *  - CAMERA_MSG_SHUTTER
    275          *  - CAMERA_MSG_RAW_IMAGE_NOTIFY
    276          *  - CAMERA_MSG_COMPRESSED_IMAGE
    277          */
    278         if (isMessageEnabled(CAMERA_MSG_SHUTTER)) {
    279             mNotifyCB(CAMERA_MSG_SHUTTER, 0, 0, mCBOpaque);
    280         }
    281         if (isMessageEnabled(CAMERA_MSG_RAW_IMAGE_NOTIFY)) {
    282             mNotifyCB(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, mCBOpaque);
    283         }
    284         if (isMessageEnabled(CAMERA_MSG_COMPRESSED_IMAGE)) {
    285             // Create EXIF data from the camera parameters, this includes things
    286             // like EXIF default fields, a timestamp and GPS information.
    287             ExifData* exifData = createExifData(mCameraParameters);
    288 
    289             // Hold the frame lock while accessing the current frame to prevent
    290             // concurrent modifications. Then create our JPEG from that frame.
    291             EmulatedCameraDevice::FrameLock lock(*camera_dev);
    292             const void* frame = camera_dev->getCurrentFrame();
    293 
    294             // Create a thumbnail and place the pointer and size in the EXIF
    295             // data structure. This transfers ownership to the EXIF data and
    296             // the memory will be deallocated in the freeExifData call below.
    297             int width = camera_dev->getFrameWidth();
    298             int height = camera_dev->getFrameHeight();
    299             int thumbWidth = mCameraParameters.getInt(
    300                     CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH);
    301             int thumbHeight = mCameraParameters.getInt(
    302                     CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT);
    303             if (thumbWidth > 0 && thumbHeight > 0) {
    304                 if (!createThumbnail(static_cast<const unsigned char*>(frame),
    305                                      width, height, thumbWidth, thumbHeight,
    306                                      mJpegQuality, exifData)) {
    307                     // Not really a fatal error, we'll just keep going
    308                     ALOGE("%s: Failed to create thumbnail for image",
    309                           __FUNCTION__);
    310                 }
    311             }
    312 
    313             /* Compress the frame to JPEG. Note that when taking pictures, we
    314              * have requested camera device to provide us with NV21 frames. */
    315             NV21JpegCompressor compressor;
    316             status_t res = compressor.compressRawImage(frame, width, height,
    317                                                        mJpegQuality, exifData);
    318             if (res == NO_ERROR) {
    319                 camera_memory_t* jpeg_buff =
    320                     mGetMemoryCB(-1, compressor.getCompressedSize(), 1, mCBOpaque);
    321                 if (NULL != jpeg_buff && NULL != jpeg_buff->data) {
    322                     compressor.getCompressedImage(jpeg_buff->data);
    323                     mDataCB(CAMERA_MSG_COMPRESSED_IMAGE, jpeg_buff, 0, NULL, mCBOpaque);
    324                     jpeg_buff->release(jpeg_buff);
    325                 } else {
    326                     ALOGE("%s: Memory failure in CAMERA_MSG_VIDEO_FRAME", __FUNCTION__);
    327                 }
    328             } else {
    329                 ALOGE("%s: Compression failure in CAMERA_MSG_VIDEO_FRAME", __FUNCTION__);
    330             }
    331             // The EXIF data has been consumed, free it
    332             freeExifData(exifData);
    333         }
    334     }
    335 }
    336 
    337 void CallbackNotifier::onCameraDeviceError(int err)
    338 {
    339     if (isMessageEnabled(CAMERA_MSG_ERROR) && mNotifyCB != NULL) {
    340         mNotifyCB(CAMERA_MSG_ERROR, err, 0, mCBOpaque);
    341     }
    342 }
    343 
    344 /****************************************************************************
    345  * Private API
    346  ***************************************************************************/
    347 
    348 bool CallbackNotifier::isNewVideoFrameTime(nsecs_t timestamp)
    349 {
    350     Mutex::Autolock locker(&mObjectLock);
    351     if ((timestamp - mLastFrameTimestamp) >= mFrameRefreshFreq) {
    352         mLastFrameTimestamp = timestamp;
    353         return true;
    354     }
    355     return false;
    356 }
    357 
    358 }; /* namespace android */
    359