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 <media/stagefright/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 LOGV(" %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 LOGV("%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 LOGV("%s: msg_type = 0x%x", __FUNCTION__, msg_type); 130 PrintMessages(msg_type); 131 132 Mutex::Autolock locker(&mObjectLock); 133 mMessageEnabler |= msg_type; 134 LOGV("**** Currently enabled messages:"); 135 PrintMessages(mMessageEnabler); 136 } 137 138 void CallbackNotifier::disableMessage(uint msg_type) 139 { 140 LOGV("%s: msg_type = 0x%x", __FUNCTION__, msg_type); 141 PrintMessages(msg_type); 142 143 Mutex::Autolock locker(&mObjectLock); 144 mMessageEnabler &= ~msg_type; 145 LOGV("**** Currently enabled messages:"); 146 PrintMessages(mMessageEnabler); 147 } 148 149 status_t CallbackNotifier::enableVideoRecording(int fps) 150 { 151 LOGV("%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 LOGV("%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 /* We don't really have anything to release here, since we report video 174 * frames by copying them directly to the camera memory. */ 175 } 176 177 status_t CallbackNotifier::storeMetaDataInBuffers(bool enable) 178 { 179 /* Return INVALID_OPERATION means HAL does not support metadata. So HAL will 180 * return actual frame data with CAMERA_MSG_VIDEO_FRRAME. Return 181 * INVALID_OPERATION to mean metadata is not supported. */ 182 return INVALID_OPERATION; 183 } 184 185 /**************************************************************************** 186 * Public API 187 ***************************************************************************/ 188 189 void CallbackNotifier::cleanupCBNotifier() 190 { 191 Mutex::Autolock locker(&mObjectLock); 192 mMessageEnabler = 0; 193 mNotifyCB = NULL; 194 mDataCB = NULL; 195 mDataCBTimestamp = NULL; 196 mGetMemoryCB = NULL; 197 mCBOpaque = NULL; 198 mLastFrameTimestamp = 0; 199 mFrameRefreshFreq = 0; 200 mJpegQuality = 90; 201 mVideoRecEnabled = false; 202 mTakingPicture = false; 203 } 204 205 void CallbackNotifier::onNextFrameAvailable(const void* frame, 206 nsecs_t timestamp, 207 EmulatedCameraDevice* camera_dev) 208 { 209 if (isMessageEnabled(CAMERA_MSG_VIDEO_FRAME) && isVideoRecordingEnabled() && 210 isNewVideoFrameTime(timestamp)) { 211 camera_memory_t* cam_buff = 212 mGetMemoryCB(-1, camera_dev->getFrameBufferSize(), 1, NULL); 213 if (NULL != cam_buff && NULL != cam_buff->data) { 214 memcpy(cam_buff->data, frame, camera_dev->getFrameBufferSize()); 215 mDataCBTimestamp(timestamp, CAMERA_MSG_VIDEO_FRAME, 216 cam_buff, 0, mCBOpaque); 217 } else { 218 LOGE("%s: Memory failure in CAMERA_MSG_VIDEO_FRAME", __FUNCTION__); 219 } 220 } 221 222 if (isMessageEnabled(CAMERA_MSG_PREVIEW_FRAME)) { 223 camera_memory_t* cam_buff = 224 mGetMemoryCB(-1, camera_dev->getFrameBufferSize(), 1, NULL); 225 if (NULL != cam_buff && NULL != cam_buff->data) { 226 memcpy(cam_buff->data, frame, camera_dev->getFrameBufferSize()); 227 mDataCB(CAMERA_MSG_PREVIEW_FRAME, cam_buff, 0, NULL, mCBOpaque); 228 cam_buff->release(cam_buff); 229 } else { 230 LOGE("%s: Memory failure in CAMERA_MSG_PREVIEW_FRAME", __FUNCTION__); 231 } 232 } 233 234 if (mTakingPicture) { 235 /* This happens just once. */ 236 mTakingPicture = false; 237 /* The sequence of callbacks during picture taking is: 238 * - CAMERA_MSG_SHUTTER 239 * - CAMERA_MSG_RAW_IMAGE_NOTIFY 240 * - CAMERA_MSG_COMPRESSED_IMAGE 241 */ 242 if (isMessageEnabled(CAMERA_MSG_SHUTTER)) { 243 mNotifyCB(CAMERA_MSG_SHUTTER, 0, 0, mCBOpaque); 244 } 245 if (isMessageEnabled(CAMERA_MSG_RAW_IMAGE_NOTIFY)) { 246 mNotifyCB(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, mCBOpaque); 247 } 248 if (isMessageEnabled(CAMERA_MSG_COMPRESSED_IMAGE)) { 249 /* Compress the frame to JPEG. Note that when taking pictures, we 250 * have requested camera device to provide us with NV21 frames. */ 251 NV21JpegCompressor compressor; 252 status_t res = 253 compressor.compressRawImage(frame, camera_dev->getFrameWidth(), 254 camera_dev->getFrameHeight(), 255 mJpegQuality); 256 if (res == NO_ERROR) { 257 camera_memory_t* jpeg_buff = 258 mGetMemoryCB(-1, compressor.getCompressedSize(), 1, NULL); 259 if (NULL != jpeg_buff && NULL != jpeg_buff->data) { 260 compressor.getCompressedImage(jpeg_buff->data); 261 mDataCB(CAMERA_MSG_COMPRESSED_IMAGE, jpeg_buff, 0, NULL, mCBOpaque); 262 jpeg_buff->release(jpeg_buff); 263 } else { 264 LOGE("%s: Memory failure in CAMERA_MSG_VIDEO_FRAME", __FUNCTION__); 265 } 266 } else { 267 LOGE("%s: Compression failure in CAMERA_MSG_VIDEO_FRAME", __FUNCTION__); 268 } 269 } 270 } 271 } 272 273 void CallbackNotifier::onCameraDeviceError(int err) 274 { 275 if (isMessageEnabled(CAMERA_MSG_ERROR) && mNotifyCB != NULL) { 276 mNotifyCB(CAMERA_MSG_ERROR, err, 0, mCBOpaque); 277 } 278 } 279 280 /**************************************************************************** 281 * Private API 282 ***************************************************************************/ 283 284 bool CallbackNotifier::isNewVideoFrameTime(nsecs_t timestamp) 285 { 286 Mutex::Autolock locker(&mObjectLock); 287 if ((timestamp - mLastFrameTimestamp) >= mFrameRefreshFreq) { 288 mLastFrameTimestamp = timestamp; 289 return true; 290 } 291 return false; 292 } 293 294 }; /* namespace android */ 295