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
19 * set 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 "CallbackNotifier.h"
25 #include <MetadataBufferType.h>
26 #include <log/log.h>
27 #include "EmulatedCameraDevice.h"
28 #include "JpegCompressor.h"
29 #include "Exif.h"
30 #include "Thumbnail.h"
31
32 namespace android {
33
34 /* String representation of camera messages. */
35 static const char* lCameraMessages[] = {"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 static const int lCameraMessagesNum = sizeof(lCameraMessages) / sizeof(char*);
47
48 /* Builds an array of strings for the given set of messages.
49 * Param:
50 * msg - Messages to get strings for,
51 * strings - Array where to save strings
52 * max - Maximum number of entries in the array.
53 * Return:
54 * Number of strings saved into the 'strings' array.
55 */
GetMessageStrings(uint32_t msg,const char ** strings,int max)56 static int GetMessageStrings(uint32_t msg, const char** strings, int max) {
57 int index = 0;
58 int out = 0;
59 while (msg != 0 && out < max && index < lCameraMessagesNum) {
60 while ((msg & 0x1) == 0 && index < lCameraMessagesNum) {
61 msg >>= 1;
62 index++;
63 }
64 if ((msg & 0x1) != 0 && index < lCameraMessagesNum) {
65 strings[out] = lCameraMessages[index];
66 out++;
67 msg >>= 1;
68 index++;
69 }
70 }
71
72 return out;
73 }
74
75 /* Logs messages, enabled by the mask. */
PrintMessages(uint32_t msg)76 static void PrintMessages(uint32_t msg) {
77 const char* strs[lCameraMessagesNum];
78 const int translated = GetMessageStrings(msg, strs, lCameraMessagesNum);
79 for (int n = 0; n < translated; n++) {
80 ALOGV(" %s", strs[n]);
81 }
82 }
83
CallbackNotifier()84 CallbackNotifier::CallbackNotifier()
85 : mNotifyCB(NULL),
86 mDataCB(NULL),
87 mDataCBTimestamp(NULL),
88 mGetMemoryCB(NULL),
89 mCBOpaque(NULL),
90 mLastFrameTimestamp(0),
91 mFrameRefreshFreq(0),
92 mMessageEnabler(0),
93 mJpegQuality(90),
94 mVideoRecEnabled(false),
95 mTakingPicture(false) {}
96
~CallbackNotifier()97 CallbackNotifier::~CallbackNotifier() {}
98
99 /****************************************************************************
100 * Camera API
101 ***************************************************************************/
102
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)103 void CallbackNotifier::setCallbacks(
104 camera_notify_callback notify_cb, camera_data_callback data_cb,
105 camera_data_timestamp_callback data_cb_timestamp,
106 camera_request_memory get_memory, void* user) {
107 ALOGV("%s: %p, %p, %p, %p (%p)", __FUNCTION__, notify_cb, data_cb,
108 data_cb_timestamp, get_memory, user);
109
110 Mutex::Autolock locker(&mObjectLock);
111 mNotifyCB = notify_cb;
112 mDataCB = data_cb;
113 mDataCBTimestamp = data_cb_timestamp;
114 mGetMemoryCB = get_memory;
115 mCBOpaque = user;
116 }
117
enableMessage(uint msg_type)118 void CallbackNotifier::enableMessage(uint msg_type) {
119 ALOGV("%s: msg_type = 0x%x", __FUNCTION__, msg_type);
120 PrintMessages(msg_type);
121
122 Mutex::Autolock locker(&mObjectLock);
123 mMessageEnabler |= msg_type;
124 ALOGV("**** Currently enabled messages:");
125 PrintMessages(mMessageEnabler);
126 }
127
disableMessage(uint msg_type)128 void CallbackNotifier::disableMessage(uint msg_type) {
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
enableVideoRecording(int fps)138 status_t CallbackNotifier::enableVideoRecording(int fps) {
139 ALOGV("%s: FPS = %d", __FUNCTION__, fps);
140
141 Mutex::Autolock locker(&mObjectLock);
142 mVideoRecEnabled = true;
143 mLastFrameTimestamp = 0;
144 mFrameRefreshFreq = 1000000000LL / fps;
145
146 return NO_ERROR;
147 }
148
disableVideoRecording()149 void CallbackNotifier::disableVideoRecording() {
150 ALOGV("%s:", __FUNCTION__);
151
152 Mutex::Autolock locker(&mObjectLock);
153 mVideoRecEnabled = false;
154 mLastFrameTimestamp = 0;
155 mFrameRefreshFreq = 0;
156 }
157
releaseRecordingFrame(const void * opaque)158 void CallbackNotifier::releaseRecordingFrame(const void* opaque) {
159 List<camera_memory_t*>::iterator it = mCameraMemoryTs.begin();
160 for (; it != mCameraMemoryTs.end(); ++it) {
161 if ((*it)->data == opaque) {
162 (*it)->release(*it);
163 mCameraMemoryTs.erase(it);
164 break;
165 }
166 }
167 }
168
storeMetaDataInBuffers(bool enable)169 status_t CallbackNotifier::storeMetaDataInBuffers(bool enable) {
170 // Return error if metadata is request, otherwise silently agree.
171 return enable ? INVALID_OPERATION : NO_ERROR;
172 }
173
174 /****************************************************************************
175 * Public API
176 ***************************************************************************/
177
cleanupCBNotifier()178 void CallbackNotifier::cleanupCBNotifier() {
179 Mutex::Autolock locker(&mObjectLock);
180 mMessageEnabler = 0;
181 mNotifyCB = NULL;
182 mDataCB = NULL;
183 mDataCBTimestamp = NULL;
184 mGetMemoryCB = NULL;
185 mCBOpaque = NULL;
186 mLastFrameTimestamp = 0;
187 mFrameRefreshFreq = 0;
188 mJpegQuality = 90;
189 mVideoRecEnabled = false;
190 mTakingPicture = false;
191 }
192
onNextFrameAvailable(const void * frame,nsecs_t timestamp,EmulatedCameraDevice * camera_dev)193 void CallbackNotifier::onNextFrameAvailable(const void* frame,
194 nsecs_t timestamp,
195 EmulatedCameraDevice* camera_dev) {
196 if (isMessageEnabled(CAMERA_MSG_VIDEO_FRAME) && isVideoRecordingEnabled() &&
197 isNewVideoFrameTime(timestamp)) {
198 camera_memory_t* cam_buff =
199 mGetMemoryCB(-1, camera_dev->getFrameBufferSize(), 1, mCBOpaque);
200 if (NULL != cam_buff && NULL != cam_buff->data) {
201 memcpy(cam_buff->data, frame, camera_dev->getFrameBufferSize());
202 mDataCBTimestamp(timestamp, CAMERA_MSG_VIDEO_FRAME, cam_buff, 0,
203 mCBOpaque);
204
205 mCameraMemoryTs.push_back(cam_buff);
206 } else {
207 ALOGE("%s: Memory failure in CAMERA_MSG_VIDEO_FRAME", __FUNCTION__);
208 }
209 }
210
211 if (isMessageEnabled(CAMERA_MSG_PREVIEW_FRAME)) {
212 camera_memory_t* cam_buff =
213 mGetMemoryCB(-1, camera_dev->getFrameBufferSize(), 1, mCBOpaque);
214 if (NULL != cam_buff && NULL != cam_buff->data) {
215 memcpy(cam_buff->data, frame, camera_dev->getFrameBufferSize());
216 mDataCB(CAMERA_MSG_PREVIEW_FRAME, cam_buff, 0, NULL, mCBOpaque);
217 cam_buff->release(cam_buff);
218 } else {
219 ALOGE("%s: Memory failure in CAMERA_MSG_PREVIEW_FRAME", __FUNCTION__);
220 }
221 }
222
223 if (mTakingPicture) {
224 /* This happens just once. */
225 mTakingPicture = false;
226 /* The sequence of callbacks during picture taking is:
227 * - CAMERA_MSG_SHUTTER
228 * - CAMERA_MSG_RAW_IMAGE_NOTIFY
229 * - CAMERA_MSG_COMPRESSED_IMAGE
230 */
231 if (isMessageEnabled(CAMERA_MSG_SHUTTER)) {
232 mNotifyCB(CAMERA_MSG_SHUTTER, 0, 0, mCBOpaque);
233 }
234 if (isMessageEnabled(CAMERA_MSG_RAW_IMAGE_NOTIFY)) {
235 mNotifyCB(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, mCBOpaque);
236 }
237 if (isMessageEnabled(CAMERA_MSG_COMPRESSED_IMAGE)) {
238 /* Compress the frame to JPEG. Note that when taking pictures, we
239 * have requested camera device to provide us with NV21 frames. */
240 NV21JpegCompressor compressor;
241 const CameraParameters* cameraParameters = camera_dev->getCameraParameters();
242 if (cameraParameters == nullptr) {
243 ALOGE("%s: Could not get camera parameters to take picture.", __FUNCTION__);
244 return;
245 }
246
247 ExifData* exifData = createExifData(*cameraParameters);
248
249 // Create a thumbnail and place the pointer and size in the EXIF
250 // data structure. This transfers ownership to the EXIF data and
251 // the memory will be deallocated in the freeExifData call below.
252 int width = camera_dev->getFrameWidth();
253 int height = camera_dev->getFrameHeight();
254 int thumbWidth = cameraParameters->getInt(
255 CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH);
256 int thumbHeight = cameraParameters->getInt(
257 CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT);
258 if (thumbWidth > 0 && thumbHeight > 0) {
259 if (!createThumbnail(static_cast<const unsigned char*>(frame),
260 width, height, thumbWidth, thumbHeight,
261 mJpegQuality, exifData)) {
262 // Not really a fatal error, we'll just keep going
263 ALOGE("%s: Failed to create thumbnail for image",
264 __FUNCTION__);
265 }
266 }
267
268 status_t res = compressor.compressRawImage(frame, exifData, mJpegQuality, width, height);
269 if (res == NO_ERROR) {
270 camera_memory_t* jpeg_buff =
271 mGetMemoryCB(-1, compressor.getCompressedSize(), 1, mCBOpaque);
272 if (NULL != jpeg_buff && NULL != jpeg_buff->data) {
273 compressor.getCompressedImage(jpeg_buff->data);
274 mDataCB(CAMERA_MSG_COMPRESSED_IMAGE, jpeg_buff, 0, NULL, mCBOpaque);
275 jpeg_buff->release(jpeg_buff);
276 } else {
277 ALOGE("%s: Memory failure in CAMERA_MSG_VIDEO_FRAME", __FUNCTION__);
278 }
279 } else {
280 ALOGE("%s: Compression failure in CAMERA_MSG_VIDEO_FRAME",
281 __FUNCTION__);
282 }
283 freeExifData(exifData);
284 }
285 }
286 }
287
onCameraDeviceError(int err)288 void CallbackNotifier::onCameraDeviceError(int err) {
289 if (isMessageEnabled(CAMERA_MSG_ERROR) && mNotifyCB != NULL) {
290 mNotifyCB(CAMERA_MSG_ERROR, err, 0, mCBOpaque);
291 }
292 }
293
onCameraFocusAcquired()294 void CallbackNotifier::onCameraFocusAcquired() {
295 if (isMessageEnabled(CAMERA_MSG_FOCUS) && mNotifyCB != NULL) {
296 mNotifyCB(CAMERA_MSG_FOCUS, 1, 0, mCBOpaque);
297 }
298 }
299
300 /****************************************************************************
301 * Private API
302 ***************************************************************************/
303
isNewVideoFrameTime(nsecs_t timestamp)304 bool CallbackNotifier::isNewVideoFrameTime(nsecs_t timestamp) {
305 Mutex::Autolock locker(&mObjectLock);
306 if ((timestamp - mLastFrameTimestamp) >= mFrameRefreshFreq) {
307 mLastFrameTimestamp = timestamp;
308 return true;
309 }
310 return false;
311 }
312
313 }; /* namespace android */
314