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