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