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 */
GetMessageStrings(uint32_t msg,const char ** strings,int max)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. */
PrintMessages(uint32_t msg)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
CallbackNotifier()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
~CallbackNotifier()106 CallbackNotifier::~CallbackNotifier()
107 {
108 }
109
110 /****************************************************************************
111 * Camera API
112 ***************************************************************************/
113
setCallbacks(camera_notify_callback notify_cb,camera_data_callback data_cb,camera_data_timestamp_callback data_cb_timestamp,camera_request_memory get_memory,void * user)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
enableMessage(uint msg_type)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
disableMessage(uint msg_type)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
enableVideoRecording(int fps)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
disableVideoRecording()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
releaseRecordingFrame(const void * opaque)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
autoFocusComplete()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
storeMetaDataInBuffers(bool enable)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
cleanupCBNotifier()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
onNextFrameAvailable(nsecs_t timestamp,EmulatedCameraDevice * camera_dev)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
onCameraDeviceError(int err)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
isNewVideoFrameTime(nsecs_t timestamp)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