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