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