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 #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 */
GetMessageStrings(uint32_t msg,const char ** strings,int max)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. */
PrintMessages(uint32_t msg)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 ALOGV(" %s", strs[n]);
84 }
85 }
86
CallbackNotifier()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
~CallbackNotifier()102 CallbackNotifier::~CallbackNotifier()
103 {
104 }
105
106 /****************************************************************************
107 * Camera API
108 ***************************************************************************/
109
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)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 ALOGV("%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
enableMessage(uint msg_type)127 void CallbackNotifier::enableMessage(uint msg_type)
128 {
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
disableMessage(uint msg_type)138 void CallbackNotifier::disableMessage(uint msg_type)
139 {
140 ALOGV("%s: msg_type = 0x%x", __FUNCTION__, msg_type);
141 PrintMessages(msg_type);
142
143 Mutex::Autolock locker(&mObjectLock);
144 mMessageEnabler &= ~msg_type;
145 ALOGV("**** Currently enabled messages:");
146 PrintMessages(mMessageEnabler);
147 }
148
enableVideoRecording(int fps)149 status_t CallbackNotifier::enableVideoRecording(int fps)
150 {
151 ALOGV("%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
disableVideoRecording()161 void CallbackNotifier::disableVideoRecording()
162 {
163 ALOGV("%s:", __FUNCTION__);
164
165 Mutex::Autolock locker(&mObjectLock);
166 mVideoRecEnabled = false;
167 mLastFrameTimestamp = 0;
168 mFrameRefreshFreq = 0;
169 }
170
releaseRecordingFrame(const void * opaque)171 void CallbackNotifier::releaseRecordingFrame(const void* opaque)
172 {
173 List<camera_memory_t*>::iterator it = mCameraMemoryTs.begin();
174 for( ; it != mCameraMemoryTs.end(); ++it ) {
175 if ( (*it)->data == opaque ) {
176 (*it)->release( *it );
177 mCameraMemoryTs.erase(it);
178 break;
179 }
180 }
181 }
182
storeMetaDataInBuffers(bool enable)183 status_t CallbackNotifier::storeMetaDataInBuffers(bool enable)
184 {
185 // Return error if metadata is request, otherwise silently agree.
186 return enable ? INVALID_OPERATION : NO_ERROR;
187 }
188
189 /****************************************************************************
190 * Public API
191 ***************************************************************************/
192
cleanupCBNotifier()193 void CallbackNotifier::cleanupCBNotifier()
194 {
195 Mutex::Autolock locker(&mObjectLock);
196 mMessageEnabler = 0;
197 mNotifyCB = NULL;
198 mDataCB = NULL;
199 mDataCBTimestamp = NULL;
200 mGetMemoryCB = NULL;
201 mCBOpaque = NULL;
202 mLastFrameTimestamp = 0;
203 mFrameRefreshFreq = 0;
204 mJpegQuality = 90;
205 mVideoRecEnabled = false;
206 mTakingPicture = false;
207 }
208
onNextFrameAvailable(const void * frame,nsecs_t timestamp,EmulatedCameraDevice * camera_dev)209 void CallbackNotifier::onNextFrameAvailable(const void* frame,
210 nsecs_t timestamp,
211 EmulatedCameraDevice* camera_dev)
212 {
213 if (isMessageEnabled(CAMERA_MSG_VIDEO_FRAME) && isVideoRecordingEnabled() &&
214 isNewVideoFrameTime(timestamp)) {
215 camera_memory_t* cam_buff =
216 mGetMemoryCB(-1, camera_dev->getFrameBufferSize(), 1, NULL);
217 if (NULL != cam_buff && NULL != cam_buff->data) {
218 memcpy(cam_buff->data, frame, camera_dev->getFrameBufferSize());
219 mDataCBTimestamp(timestamp, CAMERA_MSG_VIDEO_FRAME,
220 cam_buff, 0, mCBOpaque);
221
222 mCameraMemoryTs.push_back( cam_buff );
223 } else {
224 ALOGE("%s: Memory failure in CAMERA_MSG_VIDEO_FRAME", __FUNCTION__);
225 }
226 }
227
228 if (isMessageEnabled(CAMERA_MSG_PREVIEW_FRAME)) {
229 camera_memory_t* cam_buff =
230 mGetMemoryCB(-1, camera_dev->getFrameBufferSize(), 1, NULL);
231 if (NULL != cam_buff && NULL != cam_buff->data) {
232 memcpy(cam_buff->data, frame, camera_dev->getFrameBufferSize());
233 mDataCB(CAMERA_MSG_PREVIEW_FRAME, cam_buff, 0, NULL, mCBOpaque);
234 cam_buff->release(cam_buff);
235 } else {
236 ALOGE("%s: Memory failure in CAMERA_MSG_PREVIEW_FRAME", __FUNCTION__);
237 }
238 }
239
240 if (mTakingPicture) {
241 /* This happens just once. */
242 mTakingPicture = false;
243 /* The sequence of callbacks during picture taking is:
244 * - CAMERA_MSG_SHUTTER
245 * - CAMERA_MSG_RAW_IMAGE_NOTIFY
246 * - CAMERA_MSG_COMPRESSED_IMAGE
247 */
248 if (isMessageEnabled(CAMERA_MSG_SHUTTER)) {
249 mNotifyCB(CAMERA_MSG_SHUTTER, 0, 0, mCBOpaque);
250 }
251 if (isMessageEnabled(CAMERA_MSG_RAW_IMAGE_NOTIFY)) {
252 mNotifyCB(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, mCBOpaque);
253 }
254 if (isMessageEnabled(CAMERA_MSG_COMPRESSED_IMAGE)) {
255 /* Compress the frame to JPEG. Note that when taking pictures, we
256 * have requested camera device to provide us with NV21 frames. */
257 NV21JpegCompressor compressor;
258 status_t res =
259 compressor.compressRawImage(frame, camera_dev->getFrameWidth(),
260 camera_dev->getFrameHeight(),
261 mJpegQuality);
262 if (res == NO_ERROR) {
263 camera_memory_t* jpeg_buff =
264 mGetMemoryCB(-1, compressor.getCompressedSize(), 1, NULL);
265 if (NULL != jpeg_buff && NULL != jpeg_buff->data) {
266 compressor.getCompressedImage(jpeg_buff->data);
267 mDataCB(CAMERA_MSG_COMPRESSED_IMAGE, jpeg_buff, 0, NULL, mCBOpaque);
268 jpeg_buff->release(jpeg_buff);
269 } else {
270 ALOGE("%s: Memory failure in CAMERA_MSG_VIDEO_FRAME", __FUNCTION__);
271 }
272 } else {
273 ALOGE("%s: Compression failure in CAMERA_MSG_VIDEO_FRAME", __FUNCTION__);
274 }
275 }
276 }
277 }
278
onCameraDeviceError(int err)279 void CallbackNotifier::onCameraDeviceError(int err)
280 {
281 if (isMessageEnabled(CAMERA_MSG_ERROR) && mNotifyCB != NULL) {
282 mNotifyCB(CAMERA_MSG_ERROR, err, 0, mCBOpaque);
283 }
284 }
285
286 /****************************************************************************
287 * Private API
288 ***************************************************************************/
289
isNewVideoFrameTime(nsecs_t timestamp)290 bool CallbackNotifier::isNewVideoFrameTime(nsecs_t timestamp)
291 {
292 Mutex::Autolock locker(&mObjectLock);
293 if ((timestamp - mLastFrameTimestamp) >= mFrameRefreshFreq) {
294 mLastFrameTimestamp = timestamp;
295 return true;
296 }
297 return false;
298 }
299
300 }; /* namespace android */
301