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, NULL); 243 if (NULL != cam_buff && NULL != cam_buff->data) { 244 camera_dev->getCurrentFrame(cam_buff->data, V4L2_PIX_FMT_YUV420); 245 mDataCBTimestamp(timestamp, CAMERA_MSG_VIDEO_FRAME, 246 cam_buff, 0, mCBOpaque); 247 mCameraMemoryTs.push_back( cam_buff ); 248 } else { 249 ALOGE("%s: Memory failure in CAMERA_MSG_VIDEO_FRAME", __FUNCTION__); 250 } 251 } 252 253 if (isMessageEnabled(CAMERA_MSG_PREVIEW_FRAME)) { 254 camera_memory_t* cam_buff = 255 mGetMemoryCB(-1, camera_dev->getFrameBufferSize(), 1, NULL); 256 if (NULL != cam_buff && NULL != cam_buff->data) { 257 camera_dev->getCurrentFrame(cam_buff->data, 258 camera_dev->getOriginalPixelFormat()); 259 mDataCB(CAMERA_MSG_PREVIEW_FRAME, cam_buff, 0, NULL, mCBOpaque); 260 cam_buff->release(cam_buff); 261 } else { 262 ALOGE("%s: Memory failure in CAMERA_MSG_PREVIEW_FRAME", __FUNCTION__); 263 } 264 } 265 266 if (mTakingPicture) { 267 /* This happens just once. */ 268 mTakingPicture = false; 269 /* The sequence of callbacks during picture taking is: 270 * - CAMERA_MSG_SHUTTER 271 * - CAMERA_MSG_RAW_IMAGE_NOTIFY 272 * - CAMERA_MSG_COMPRESSED_IMAGE 273 */ 274 if (isMessageEnabled(CAMERA_MSG_SHUTTER)) { 275 mNotifyCB(CAMERA_MSG_SHUTTER, 0, 0, mCBOpaque); 276 } 277 if (isMessageEnabled(CAMERA_MSG_RAW_IMAGE_NOTIFY)) { 278 mNotifyCB(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, mCBOpaque); 279 } 280 if (isMessageEnabled(CAMERA_MSG_COMPRESSED_IMAGE)) { 281 // Create EXIF data from the camera parameters, this includes things 282 // like EXIF default fields, a timestamp and GPS information. 283 ExifData* exifData = createExifData(mCameraParameters); 284 285 // Hold the frame lock while accessing the current frame to prevent 286 // concurrent modifications. Then create our JPEG from that frame. 287 EmulatedCameraDevice::FrameLock lock(*camera_dev); 288 const void* frame = camera_dev->getCurrentFrame(); 289 290 // Create a thumbnail and place the pointer and size in the EXIF 291 // data structure. This transfers ownership to the EXIF data and 292 // the memory will be deallocated in the freeExifData call below. 293 int width = camera_dev->getFrameWidth(); 294 int height = camera_dev->getFrameHeight(); 295 int thumbWidth = mCameraParameters.getInt( 296 CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH); 297 int thumbHeight = mCameraParameters.getInt( 298 CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT); 299 if (thumbWidth > 0 && thumbHeight > 0) { 300 if (!createThumbnail(static_cast<const unsigned char*>(frame), 301 width, height, thumbWidth, thumbHeight, 302 mJpegQuality, exifData)) { 303 // Not really a fatal error, we'll just keep going 304 ALOGE("%s: Failed to create thumbnail for image", 305 __FUNCTION__); 306 } 307 } 308 309 /* Compress the frame to JPEG. Note that when taking pictures, we 310 * have requested camera device to provide us with NV21 frames. */ 311 NV21JpegCompressor compressor; 312 status_t res = compressor.compressRawImage(frame, width, height, 313 mJpegQuality, exifData); 314 if (res == NO_ERROR) { 315 camera_memory_t* jpeg_buff = 316 mGetMemoryCB(-1, compressor.getCompressedSize(), 1, NULL); 317 if (NULL != jpeg_buff && NULL != jpeg_buff->data) { 318 compressor.getCompressedImage(jpeg_buff->data); 319 mDataCB(CAMERA_MSG_COMPRESSED_IMAGE, jpeg_buff, 0, NULL, mCBOpaque); 320 jpeg_buff->release(jpeg_buff); 321 } else { 322 ALOGE("%s: Memory failure in CAMERA_MSG_VIDEO_FRAME", __FUNCTION__); 323 } 324 } else { 325 ALOGE("%s: Compression failure in CAMERA_MSG_VIDEO_FRAME", __FUNCTION__); 326 } 327 // The EXIF data has been consumed, free it 328 freeExifData(exifData); 329 } 330 } 331 } 332 333 void CallbackNotifier::onCameraDeviceError(int err) 334 { 335 if (isMessageEnabled(CAMERA_MSG_ERROR) && mNotifyCB != NULL) { 336 mNotifyCB(CAMERA_MSG_ERROR, err, 0, mCBOpaque); 337 } 338 } 339 340 /**************************************************************************** 341 * Private API 342 ***************************************************************************/ 343 344 bool CallbackNotifier::isNewVideoFrameTime(nsecs_t timestamp) 345 { 346 Mutex::Autolock locker(&mObjectLock); 347 if ((timestamp - mLastFrameTimestamp) >= mFrameRefreshFreq) { 348 mLastFrameTimestamp = timestamp; 349 return true; 350 } 351 return false; 352 } 353 354 }; /* namespace android */ 355