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 <log/log.h>
25 #include <media/hardware/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, 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 
onCameraDeviceError(int err)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 
isNewVideoFrameTime(nsecs_t timestamp)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