1 /* Copyright (c) 2012-2013, The Linux Foundataion. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 *     * Redistributions of source code must retain the above copyright
7 *       notice, this list of conditions and the following disclaimer.
8 *     * Redistributions in binary form must reproduce the above
9 *       copyright notice, this list of conditions and the following
10 *       disclaimer in the documentation and/or other materials provided
11 *       with the distribution.
12 *     * Neither the name of The Linux Foundation nor the names of its
13 *       contributors may be used to endorse or promote products derived
14 *       from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29 
30 #define LOG_TAG "QCamera2HWI"
31 
32 #include <fcntl.h>
33 #include <utils/Errors.h>
34 #include <utils/Timers.h>
35 #include "QCamera2HWI.h"
36 
37 namespace qcamera {
38 
39 /*===========================================================================
40  * FUNCTION   : zsl_channel_cb
41  *
42  * DESCRIPTION: helper function to handle ZSL superbuf callback directly from
43  *              mm-camera-interface
44  *
45  * PARAMETERS :
46  *   @recvd_frame : received super buffer
47  *   @userdata    : user data ptr
48  *
49  * RETURN    : None
50  *
51  * NOTE      : recvd_frame will be released after this call by caller, so if
52  *             async operation needed for recvd_frame, it's our responsibility
53  *             to save a copy for this variable to be used later.
54  *==========================================================================*/
zsl_channel_cb(mm_camera_super_buf_t * recvd_frame,void * userdata)55 void QCamera2HardwareInterface::zsl_channel_cb(mm_camera_super_buf_t *recvd_frame,
56                                                void *userdata)
57 {
58     ALOGD("[KPI Perf] %s: E",__func__);
59     QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata;
60     if (pme == NULL ||
61         pme->mCameraHandle == NULL ||
62         pme->mCameraHandle->camera_handle != recvd_frame->camera_handle){
63        ALOGE("%s: camera obj not valid", __func__);
64        return;
65     }
66 
67     QCameraChannel *pChannel = pme->m_channels[QCAMERA_CH_TYPE_ZSL];
68     if (pChannel == NULL ||
69         pChannel->getMyHandle() != recvd_frame->ch_id) {
70         ALOGE("%s: ZSL channel doesn't exist, return here", __func__);
71         return;
72     }
73 
74     // save a copy for the superbuf
75     mm_camera_super_buf_t* frame =
76                (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
77     if (frame == NULL) {
78         ALOGE("%s: Error allocating memory to save received_frame structure.", __func__);
79         pChannel->bufDone(recvd_frame);
80         return;
81     }
82     *frame = *recvd_frame;
83 
84     // send to postprocessor
85     pme->m_postprocessor.processData(frame);
86 
87     ALOGD("[KPI Perf] %s: X", __func__);
88 }
89 
90 /*===========================================================================
91  * FUNCTION   : capture_channel_cb_routine
92  *
93  * DESCRIPTION: helper function to handle snapshot superbuf callback directly from
94  *              mm-camera-interface
95  *
96  * PARAMETERS :
97  *   @recvd_frame : received super buffer
98  *   @userdata    : user data ptr
99  *
100  * RETURN    : None
101  *
102  * NOTE      : recvd_frame will be released after this call by caller, so if
103  *             async operation needed for recvd_frame, it's our responsibility
104  *             to save a copy for this variable to be used later.
105 *==========================================================================*/
capture_channel_cb_routine(mm_camera_super_buf_t * recvd_frame,void * userdata)106 void QCamera2HardwareInterface::capture_channel_cb_routine(mm_camera_super_buf_t *recvd_frame,
107                                                            void *userdata)
108 {
109     ALOGD("[KPI Perf] %s: E", __func__);
110     QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata;
111     if (pme == NULL ||
112         pme->mCameraHandle == NULL ||
113         pme->mCameraHandle->camera_handle != recvd_frame->camera_handle){
114         ALOGE("%s: camera obj not valid", __func__);
115         // simply free super frame
116         free(recvd_frame);
117         return;
118     }
119 
120     QCameraChannel *pChannel = pme->m_channels[QCAMERA_CH_TYPE_CAPTURE];
121     if (pChannel == NULL ||
122         pChannel->getMyHandle() != recvd_frame->ch_id) {
123         ALOGE("%s: Capture channel doesn't exist, return here", __func__);
124         return;
125     }
126 
127     // save a copy for the superbuf
128     mm_camera_super_buf_t* frame =
129                (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
130     if (frame == NULL) {
131         ALOGE("%s: Error allocating memory to save received_frame structure.", __func__);
132         pChannel->bufDone(recvd_frame);
133         return;
134     }
135     *frame = *recvd_frame;
136 
137     // send to postprocessor
138     pme->m_postprocessor.processData(frame);
139 
140 /* START of test register face image for face authentication */
141 #ifdef QCOM_TEST_FACE_REGISTER_FACE
142     static uint8_t bRunFaceReg = 1;
143 
144     if (bRunFaceReg > 0) {
145         // find snapshot frame
146         QCameraStream *main_stream = NULL;
147         mm_camera_buf_def_t *main_frame = NULL;
148         for (int i = 0; i < recvd_frame->num_bufs; i++) {
149             QCameraStream *pStream =
150                 pChannel->getStreamByHandle(recvd_frame->bufs[i]->stream_id);
151             if (pStream != NULL) {
152                 if (pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
153                     pStream->isTypeOf(CAM_STREAM_TYPE_NON_ZSL_SNAPSHOT)) {
154                     main_stream = pStream;
155                     main_frame = recvd_frame->bufs[i];
156                     break;
157                 }
158             }
159         }
160         if (main_stream != NULL && main_frame != NULL) {
161             int32_t faceId = -1;
162             cam_pp_offline_src_config_t config;
163             memset(&config, 0, sizeof(cam_pp_offline_src_config_t));
164             config.num_of_bufs = 1;
165             main_stream->getFormat(config.input_fmt);
166             main_stream->getFrameDimension(config.input_dim);
167             main_stream->getFrameOffset(config.input_buf_planes.plane_info);
168             ALOGD("DEBUG: registerFaceImage E");
169             int32_t rc = pme->registerFaceImage(main_frame->buffer, &config, faceId);
170             ALOGD("DEBUG: registerFaceImage X, ret=%d, faceId=%d", rc, faceId);
171             bRunFaceReg = 0;
172         }
173     }
174 
175 #endif
176 /* END of test register face image for face authentication */
177 
178     ALOGD("[KPI Perf] %s: X", __func__);
179 }
180 
181 /*===========================================================================
182  * FUNCTION   : postproc_channel_cb_routine
183  *
184  * DESCRIPTION: helper function to handle postprocess superbuf callback directly from
185  *              mm-camera-interface
186  *
187  * PARAMETERS :
188  *   @recvd_frame : received super buffer
189  *   @userdata    : user data ptr
190  *
191  * RETURN    : None
192  *
193  * NOTE      : recvd_frame will be released after this call by caller, so if
194  *             async operation needed for recvd_frame, it's our responsibility
195  *             to save a copy for this variable to be used later.
196 *==========================================================================*/
postproc_channel_cb_routine(mm_camera_super_buf_t * recvd_frame,void * userdata)197 void QCamera2HardwareInterface::postproc_channel_cb_routine(mm_camera_super_buf_t *recvd_frame,
198                                                             void *userdata)
199 {
200     ALOGD("[KPI Perf] %s: E", __func__);
201     QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata;
202     if (pme == NULL ||
203         pme->mCameraHandle == NULL ||
204         pme->mCameraHandle->camera_handle != recvd_frame->camera_handle){
205         ALOGE("%s: camera obj not valid", __func__);
206         // simply free super frame
207         free(recvd_frame);
208         return;
209     }
210 
211     // save a copy for the superbuf
212     mm_camera_super_buf_t* frame =
213                (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
214     if (frame == NULL) {
215         ALOGE("%s: Error allocating memory to save received_frame structure.", __func__);
216         return;
217     }
218     *frame = *recvd_frame;
219 
220     // send to postprocessor
221     pme->m_postprocessor.processPPData(frame);
222 
223     ALOGD("[KPI Perf] %s: X", __func__);
224 }
225 
226 /*===========================================================================
227  * FUNCTION   : preview_stream_cb_routine
228  *
229  * DESCRIPTION: helper function to handle preview frame from preview stream in
230  *              normal case with display.
231  *
232  * PARAMETERS :
233  *   @super_frame : received super buffer
234  *   @stream      : stream object
235  *   @userdata    : user data ptr
236  *
237  * RETURN    : None
238  *
239  * NOTE      : caller passes the ownership of super_frame, it's our
240  *             responsibility to free super_frame once it's done. The new
241  *             preview frame will be sent to display, and an older frame
242  *             will be dequeued from display and needs to be returned back
243  *             to kernel for future use.
244  *==========================================================================*/
preview_stream_cb_routine(mm_camera_super_buf_t * super_frame,QCameraStream * stream,void * userdata)245 void QCamera2HardwareInterface::preview_stream_cb_routine(mm_camera_super_buf_t *super_frame,
246                                                           QCameraStream * stream,
247                                                           void *userdata)
248 {
249     ALOGD("[KPI Perf] %s : BEGIN", __func__);
250     int err = NO_ERROR;
251     QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata;
252     QCameraGrallocMemory *memory = (QCameraGrallocMemory *)super_frame->bufs[0]->mem_info;
253 
254     if (pme == NULL) {
255         ALOGE("%s: Invalid hardware object", __func__);
256         free(super_frame);
257         return;
258     }
259     if (memory == NULL) {
260         ALOGE("%s: Invalid memory object", __func__);
261         free(super_frame);
262         return;
263     }
264 
265     mm_camera_buf_def_t *frame = super_frame->bufs[0];
266     if (NULL == frame) {
267         ALOGE("%s: preview frame is NLUL", __func__);
268         free(super_frame);
269         return;
270     }
271 
272     if (!pme->needProcessPreviewFrame()) {
273         ALOGE("%s: preview is not running, no need to process", __func__);
274         stream->bufDone(frame->buf_idx);
275         free(super_frame);
276         return;
277     }
278 
279     if (pme->needDebugFps()) {
280         pme->debugShowPreviewFPS();
281     }
282 
283     int idx = frame->buf_idx;
284     pme->dumpFrameToFile(frame->buffer, frame->frame_len,
285                          frame->frame_idx, QCAMERA_DUMP_FRM_PREVIEW);
286 
287     // Display the buffer.
288     int dequeuedIdx = memory->displayBuffer(idx);
289     if (dequeuedIdx < 0 || dequeuedIdx >= memory->getCnt()) {
290         ALOGD("%s: Invalid dequeued buffer index %d from display",
291               __func__, dequeuedIdx);
292     } else {
293         // Return dequeued buffer back to driver
294         err = stream->bufDone(dequeuedIdx);
295         if ( err < 0) {
296             ALOGE("stream bufDone failed %d", err);
297         }
298     }
299 
300     // Handle preview data callback
301     if (pme->mDataCb != NULL && pme->msgTypeEnabledWithLock(CAMERA_MSG_PREVIEW_FRAME) > 0) {
302         camera_memory_t *previewMem = NULL;
303         camera_memory_t *data = NULL;
304         int previewBufSize;
305         cam_dimension_t preview_dim;
306         cam_format_t previewFmt;
307         stream->getFrameDimension(preview_dim);
308         stream->getFormat(previewFmt);
309 
310         /* The preview buffer size in the callback should be (width*height*bytes_per_pixel)
311          * As all preview formats we support, use 12 bits per pixel, buffer size = previewWidth * previewHeight * 3/2.
312          * We need to put a check if some other formats are supported in future. */
313         if ((previewFmt == CAM_FORMAT_YUV_420_NV21) ||
314             (previewFmt == CAM_FORMAT_YUV_420_NV12) ||
315             (previewFmt == CAM_FORMAT_YUV_420_YV12)) {
316             if(previewFmt == CAM_FORMAT_YUV_420_YV12) {
317                 previewBufSize = ((preview_dim.width+15)/16) * 16 * preview_dim.height +
318                                  ((preview_dim.width/2+15)/16) * 16* preview_dim.height;
319                 } else {
320                     previewBufSize = preview_dim.width * preview_dim.height * 3/2;
321                 }
322             if(previewBufSize != memory->getSize(idx)) {
323                 previewMem = pme->mGetMemory(memory->getFd(idx),
324                            previewBufSize, 1, pme->mCallbackCookie);
325                 if (!previewMem || !previewMem->data) {
326                     ALOGE("%s: mGetMemory failed.\n", __func__);
327                 } else {
328                     data = previewMem;
329                 }
330             } else
331                 data = memory->getMemory(idx, false);
332         } else {
333             data = memory->getMemory(idx, false);
334             ALOGE("%s: Invalid preview format, buffer size in preview callback may be wrong.", __func__);
335         }
336         qcamera_callback_argm_t cbArg;
337         memset(&cbArg, 0, sizeof(qcamera_callback_argm_t));
338         cbArg.cb_type = QCAMERA_DATA_CALLBACK;
339         cbArg.msg_type = CAMERA_MSG_PREVIEW_FRAME;
340         cbArg.data = data;
341         if ( previewMem ) {
342             cbArg.user_data = previewMem;
343             cbArg.release_cb = releaseCameraMemory;
344         }
345         cbArg.cookie = pme;
346         pme->m_cbNotifier.notifyCallback(cbArg);
347     }
348 
349     free(super_frame);
350     ALOGD("[KPI Perf] %s : END", __func__);
351     return;
352 }
353 
354 /*===========================================================================
355  * FUNCTION   : nodisplay_preview_stream_cb_routine
356  *
357  * DESCRIPTION: helper function to handle preview frame from preview stream in
358  *              no-display case
359  *
360  * PARAMETERS :
361  *   @super_frame : received super buffer
362  *   @stream      : stream object
363  *   @userdata    : user data ptr
364  *
365  * RETURN    : None
366  *
367  * NOTE      : caller passes the ownership of super_frame, it's our
368  *             responsibility to free super_frame once it's done.
369  *==========================================================================*/
nodisplay_preview_stream_cb_routine(mm_camera_super_buf_t * super_frame,QCameraStream * stream,void * userdata)370 void QCamera2HardwareInterface::nodisplay_preview_stream_cb_routine(
371                                                           mm_camera_super_buf_t *super_frame,
372                                                           QCameraStream *stream,
373                                                           void * userdata)
374 {
375     ALOGD("[KPI Perf] %s E",__func__);
376     QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata;
377     if (pme == NULL ||
378         pme->mCameraHandle == NULL ||
379         pme->mCameraHandle->camera_handle != super_frame->camera_handle){
380         ALOGE("%s: camera obj not valid", __func__);
381         // simply free super frame
382         free(super_frame);
383         return;
384     }
385     mm_camera_buf_def_t *frame = super_frame->bufs[0];
386     if (NULL == frame) {
387         ALOGE("%s: preview frame is NLUL", __func__);
388         free(super_frame);
389         return;
390     }
391 
392     if (!pme->needProcessPreviewFrame()) {
393         ALOGD("%s: preview is not running, no need to process", __func__);
394         stream->bufDone(frame->buf_idx);
395         free(super_frame);
396         return;
397     }
398 
399     if (pme->needDebugFps()) {
400         pme->debugShowPreviewFPS();
401     }
402 
403     QCameraMemory *previewMemObj = (QCameraMemory *)frame->mem_info;
404     camera_memory_t *preview_mem = NULL;
405     if (previewMemObj != NULL) {
406         preview_mem = previewMemObj->getMemory(frame->buf_idx, false);
407     }
408     if (NULL != previewMemObj && NULL != preview_mem) {
409         pme->dumpFrameToFile(frame->buffer, frame->frame_len,
410                              frame->frame_idx, QCAMERA_DUMP_FRM_PREVIEW);
411 
412         if (pme->needProcessPreviewFrame() &&
413             pme->mDataCb != NULL &&
414             pme->msgTypeEnabledWithLock(CAMERA_MSG_PREVIEW_FRAME) > 0 ) {
415             qcamera_callback_argm_t cbArg;
416             memset(&cbArg, 0, sizeof(qcamera_callback_argm_t));
417             cbArg.cb_type = QCAMERA_DATA_CALLBACK;
418             cbArg.msg_type = CAMERA_MSG_PREVIEW_FRAME;
419             cbArg.data = preview_mem;
420             int user_data = frame->buf_idx;
421             cbArg.user_data = ( void * ) user_data;
422             cbArg.cookie = stream;
423             cbArg.release_cb = returnStreamBuffer;
424             pme->m_cbNotifier.notifyCallback(cbArg);
425         } else {
426             stream->bufDone(frame->buf_idx);
427         }
428     }
429     free(super_frame);
430     ALOGD("[KPI Perf] %s X",__func__);
431 }
432 
433 /*===========================================================================
434  * FUNCTION   : postview_stream_cb_routine
435  *
436  * DESCRIPTION: helper function to handle post frame from postview stream
437  *
438  * PARAMETERS :
439  *   @super_frame : received super buffer
440  *   @stream      : stream object
441  *   @userdata    : user data ptr
442  *
443  * RETURN    : None
444  *
445  * NOTE      : caller passes the ownership of super_frame, it's our
446  *             responsibility to free super_frame once it's done.
447  *==========================================================================*/
postview_stream_cb_routine(mm_camera_super_buf_t * super_frame,QCameraStream * stream,void * userdata)448 void QCamera2HardwareInterface::postview_stream_cb_routine(mm_camera_super_buf_t *super_frame,
449                                                            QCameraStream *stream,
450                                                            void *userdata)
451 {
452     int err = NO_ERROR;
453     QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata;
454     QCameraGrallocMemory *memory = (QCameraGrallocMemory *)super_frame->bufs[0]->mem_info;
455 
456     if (pme == NULL) {
457         ALOGE("%s: Invalid hardware object", __func__);
458         free(super_frame);
459         return;
460     }
461     if (memory == NULL) {
462         ALOGE("%s: Invalid memory object", __func__);
463         free(super_frame);
464         return;
465     }
466 
467     ALOGD("[KPI Perf] %s : BEGIN", __func__);
468 
469     mm_camera_buf_def_t *frame = super_frame->bufs[0];
470     if (NULL == frame) {
471         ALOGE("%s: preview frame is NLUL", __func__);
472         free(super_frame);
473         return;
474     }
475 
476     QCameraMemory *memObj = (QCameraMemory *)frame->mem_info;
477     if (NULL != memObj) {
478         pme->dumpFrameToFile(frame->buffer, frame->frame_len,
479                              frame->frame_idx, QCAMERA_DUMP_FRM_THUMBNAIL);
480     }
481 
482     // Display the buffer.
483     int dequeuedIdx = memory->displayBuffer(frame->buf_idx);
484     if (dequeuedIdx < 0 || dequeuedIdx >= memory->getCnt()) {
485         ALOGD("%s: Invalid dequeued buffer index %d",
486               __func__, dequeuedIdx);
487         free(super_frame);
488         return;
489     }
490 
491     // Return dequeued buffer back to driver
492     err = stream->bufDone(dequeuedIdx);
493     if ( err < 0) {
494         ALOGE("stream bufDone failed %d", err);
495     }
496 
497     free(super_frame);
498     ALOGD("[KPI Perf] %s : END", __func__);
499     return;
500 }
501 
502 /*===========================================================================
503  * FUNCTION   : video_stream_cb_routine
504  *
505  * DESCRIPTION: helper function to handle video frame from video stream
506  *
507  * PARAMETERS :
508  *   @super_frame : received super buffer
509  *   @stream      : stream object
510  *   @userdata    : user data ptr
511  *
512  * RETURN    : None
513  *
514  * NOTE      : caller passes the ownership of super_frame, it's our
515  *             responsibility to free super_frame once it's done. video
516  *             frame will be sent to video encoder. Once video encoder is
517  *             done with the video frame, it will call another API
518  *             (release_recording_frame) to return the frame back
519  *==========================================================================*/
video_stream_cb_routine(mm_camera_super_buf_t * super_frame,QCameraStream *,void * userdata)520 void QCamera2HardwareInterface::video_stream_cb_routine(mm_camera_super_buf_t *super_frame,
521                                                         QCameraStream */*stream*/,
522                                                         void *userdata)
523 {
524     ALOGD("[KPI Perf] %s : BEGIN", __func__);
525     QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata;
526     if (pme == NULL ||
527         pme->mCameraHandle == NULL ||
528         pme->mCameraHandle->camera_handle != super_frame->camera_handle){
529         ALOGE("%s: camera obj not valid", __func__);
530         // simply free super frame
531         free(super_frame);
532         return;
533     }
534     mm_camera_buf_def_t *frame = super_frame->bufs[0];
535 
536     if (pme->needDebugFps()) {
537         pme->debugShowVideoFPS();
538     }
539 
540     ALOGE("%s: Stream(%d), Timestamp: %ld %ld",
541           __func__,
542           frame->stream_id,
543           frame->ts.tv_sec,
544           frame->ts.tv_nsec);
545 
546     nsecs_t timeStamp = nsecs_t(frame->ts.tv_sec) * 1000000000LL + frame->ts.tv_nsec;
547     ALOGE("Send Video frame to services/encoder TimeStamp : %lld", timeStamp);
548     QCameraMemory *videoMemObj = (QCameraMemory *)frame->mem_info;
549     camera_memory_t *video_mem = NULL;
550     if (NULL != videoMemObj) {
551         video_mem = videoMemObj->getMemory(frame->buf_idx, (pme->mStoreMetaDataInFrame > 0)? true : false);
552     }
553     if (NULL != videoMemObj && NULL != video_mem) {
554         pme->dumpFrameToFile(frame->buffer, frame->frame_len,
555                              frame->frame_idx, QCAMERA_DUMP_FRM_VIDEO);
556         if ((pme->mDataCbTimestamp != NULL) &&
557             pme->msgTypeEnabledWithLock(CAMERA_MSG_VIDEO_FRAME) > 0) {
558             qcamera_callback_argm_t cbArg;
559             memset(&cbArg, 0, sizeof(qcamera_callback_argm_t));
560             cbArg.cb_type = QCAMERA_DATA_TIMESTAMP_CALLBACK;
561             cbArg.msg_type = CAMERA_MSG_VIDEO_FRAME;
562             cbArg.data = video_mem;
563             cbArg.timestamp = timeStamp;
564             pme->m_cbNotifier.notifyCallback(cbArg);
565         }
566     }
567     free(super_frame);
568     ALOGD("[KPI Perf] %s : END", __func__);
569 }
570 
571 /*===========================================================================
572  * FUNCTION   : snapshot_stream_cb_routine
573  *
574  * DESCRIPTION: helper function to handle snapshot frame from snapshot stream
575  *
576  * PARAMETERS :
577  *   @super_frame : received super buffer
578  *   @stream      : stream object
579  *   @userdata    : user data ptr
580  *
581  * RETURN    : None
582  *
583  * NOTE      : caller passes the ownership of super_frame, it's our
584  *             responsibility to free super_frame once it's done. For
585  *             snapshot, it need to send to postprocessor for jpeg
586  *             encoding, therefore the ownership of super_frame will be
587  *             hand to postprocessor.
588  *==========================================================================*/
snapshot_stream_cb_routine(mm_camera_super_buf_t * super_frame,QCameraStream *,void * userdata)589 void QCamera2HardwareInterface::snapshot_stream_cb_routine(mm_camera_super_buf_t *super_frame,
590                                                            QCameraStream * /*stream*/,
591                                                            void *userdata)
592 {
593     ALOGD("[KPI Perf] %s: E", __func__);
594     QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata;
595     if (pme == NULL ||
596         pme->mCameraHandle == NULL ||
597         pme->mCameraHandle->camera_handle != super_frame->camera_handle){
598         ALOGE("%s: camera obj not valid", __func__);
599         // simply free super frame
600         free(super_frame);
601         return;
602     }
603 
604     pme->m_postprocessor.processData(super_frame);
605 
606     ALOGD("[KPI Perf] %s: X", __func__);
607 }
608 
609 /*===========================================================================
610  * FUNCTION   : raw_stream_cb_routine
611  *
612  * DESCRIPTION: helper function to handle raw dump frame from raw stream
613  *
614  * PARAMETERS :
615  *   @super_frame : received super buffer
616  *   @stream      : stream object
617  *   @userdata    : user data ptr
618  *
619  * RETURN    : None
620  *
621  * NOTE      : caller passes the ownership of super_frame, it's our
622  *             responsibility to free super_frame once it's done. For raw
623  *             frame, there is no need to send to postprocessor for jpeg
624  *             encoding. this function will play shutter and send the data
625  *             callback to upper layer. Raw frame buffer will be returned
626  *             back to kernel, and frame will be free after use.
627  *==========================================================================*/
raw_stream_cb_routine(mm_camera_super_buf_t * super_frame,QCameraStream *,void * userdata)628 void QCamera2HardwareInterface::raw_stream_cb_routine(mm_camera_super_buf_t * super_frame,
629                                                       QCameraStream * /*stream*/,
630                                                       void * userdata)
631 {
632     ALOGD("[KPI Perf] %s : BEGIN", __func__);
633     QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata;
634     if (pme == NULL ||
635         pme->mCameraHandle == NULL ||
636         pme->mCameraHandle->camera_handle != super_frame->camera_handle){
637         ALOGE("%s: camera obj not valid", __func__);
638         // simply free super frame
639         free(super_frame);
640         return;
641     }
642 
643     pme->m_postprocessor.processRawData(super_frame);
644     ALOGD("[KPI Perf] %s : END", __func__);
645 }
646 
647 /*===========================================================================
648  * FUNCTION   : metadata_stream_cb_routine
649  *
650  * DESCRIPTION: helper function to handle metadata frame from metadata stream
651  *
652  * PARAMETERS :
653  *   @super_frame : received super buffer
654  *   @stream      : stream object
655  *   @userdata    : user data ptr
656  *
657  * RETURN    : None
658  *
659  * NOTE      : caller passes the ownership of super_frame, it's our
660  *             responsibility to free super_frame once it's done. Metadata
661  *             could have valid entries for face detection result or
662  *             histogram statistics information.
663  *==========================================================================*/
metadata_stream_cb_routine(mm_camera_super_buf_t * super_frame,QCameraStream * stream,void * userdata)664 void QCamera2HardwareInterface::metadata_stream_cb_routine(mm_camera_super_buf_t * super_frame,
665                                                            QCameraStream * stream,
666                                                            void * userdata)
667 {
668     ALOGV("[KPI Perf] %s : BEGIN", __func__);
669     QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata;
670     if (pme == NULL ||
671         pme->mCameraHandle == NULL ||
672         pme->mCameraHandle->camera_handle != super_frame->camera_handle){
673         ALOGE("%s: camera obj not valid", __func__);
674         // simply free super frame
675         free(super_frame);
676         return;
677     }
678 
679     mm_camera_buf_def_t *frame = super_frame->bufs[0];
680     cam_metadata_info_t *pMetaData = (cam_metadata_info_t *)frame->buffer;
681 
682     if (pMetaData->is_faces_valid) {
683         if (pMetaData->faces_data.num_faces_detected > MAX_ROI) {
684             ALOGE("%s: Invalid number of faces %d",
685                 __func__, pMetaData->faces_data.num_faces_detected);
686         } else {
687             // process face detection result
688             ALOGD("[KPI Perf] %s: Number of faces detected %d",__func__,pMetaData->faces_data.num_faces_detected);
689             pme->processFaceDetectionResult(&pMetaData->faces_data);
690         }
691     }
692 
693     if (pMetaData->is_stats_valid) {
694         // process histogram statistics info
695         pme->processHistogramStats(pMetaData->stats_data);
696     }
697 
698     if (pMetaData->is_focus_valid) {
699         // process focus info
700         qcamera_sm_internal_evt_payload_t *payload =
701             (qcamera_sm_internal_evt_payload_t *)malloc(sizeof(qcamera_sm_internal_evt_payload_t));
702         if (NULL != payload) {
703             memset(payload, 0, sizeof(qcamera_sm_internal_evt_payload_t));
704             payload->evt_type = QCAMERA_INTERNAL_EVT_FOCUS_UPDATE;
705             payload->focus_data = pMetaData->focus_data;
706             int32_t rc = pme->processEvt(QCAMERA_SM_EVT_EVT_INTERNAL, payload);
707             if (rc != NO_ERROR) {
708                 ALOGE("%s: processEVt failed", __func__);
709                 free(payload);
710                 payload = NULL;
711 
712             }
713         } else {
714             ALOGE("%s: No memory for qcamera_sm_internal_evt_payload_t", __func__);
715         }
716     }
717 
718     if (pMetaData->is_crop_valid) {
719         if (pMetaData->crop_data.num_of_streams > MAX_NUM_STREAMS) {
720             ALOGE("%s: Invalid num_of_streams %d in crop_data", __func__,
721                 pMetaData->crop_data.num_of_streams);
722         } else {
723             pme->processZoomEvent(pMetaData->crop_data);
724         }
725     }
726 
727     if (pMetaData->is_prep_snapshot_done_valid) {
728         qcamera_sm_internal_evt_payload_t *payload =
729             (qcamera_sm_internal_evt_payload_t *)malloc(sizeof(qcamera_sm_internal_evt_payload_t));
730         if (NULL != payload) {
731             memset(payload, 0, sizeof(qcamera_sm_internal_evt_payload_t));
732             payload->evt_type = QCAMERA_INTERNAL_EVT_PREP_SNAPSHOT_DONE;
733             payload->prep_snapshot_state = pMetaData->prep_snapshot_done_state;
734             int32_t rc = pme->processEvt(QCAMERA_SM_EVT_EVT_INTERNAL, payload);
735             if (rc != NO_ERROR) {
736                 ALOGE("%s: processEVt failed", __func__);
737                 free(payload);
738                 payload = NULL;
739 
740             }
741         } else {
742             ALOGE("%s: No memory for qcamera_sm_internal_evt_payload_t", __func__);
743         }
744     }
745 
746     stream->bufDone(frame->buf_idx);
747     free(super_frame);
748 
749     ALOGV("[KPI Perf] %s : END", __func__);
750 }
751 
752 /*===========================================================================
753  * FUNCTION   : reprocess_stream_cb_routine
754  *
755  * DESCRIPTION: helper function to handle reprocess frame from reprocess stream
756                 (after reprocess, e.g., ZSL snapshot frame after WNR if
757  *              WNR is enabled)
758  *
759  * PARAMETERS :
760  *   @super_frame : received super buffer
761  *   @stream      : stream object
762  *   @userdata    : user data ptr
763  *
764  * RETURN    : None
765  *
766  * NOTE      : caller passes the ownership of super_frame, it's our
767  *             responsibility to free super_frame once it's done. In this
768  *             case, reprocessed frame need to be passed to postprocessor
769  *             for jpeg encoding.
770  *==========================================================================*/
reprocess_stream_cb_routine(mm_camera_super_buf_t * super_frame,QCameraStream *,void * userdata)771 void QCamera2HardwareInterface::reprocess_stream_cb_routine(mm_camera_super_buf_t * super_frame,
772                                                             QCameraStream * /*stream*/,
773                                                             void * userdata)
774 {
775     ALOGD("[KPI Perf] %s: E", __func__);
776     QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata;
777     if (pme == NULL ||
778         pme->mCameraHandle == NULL ||
779         pme->mCameraHandle->camera_handle != super_frame->camera_handle){
780         ALOGE("%s: camera obj not valid", __func__);
781         // simply free super frame
782         free(super_frame);
783         return;
784     }
785 
786     pme->m_postprocessor.processPPData(super_frame);
787 
788     ALOGD("[KPI Perf] %s: X", __func__);
789 }
790 
791 /*===========================================================================
792  * FUNCTION   : dumpFrameToFile
793  *
794  * DESCRIPTION: helper function to dump frame into file for debug purpose.
795  *
796  * PARAMETERS :
797  *    @data : data ptr
798  *    @size : length of data buffer
799  *    @index : identifier for data
800  *    @dump_type : type of the frame to be dumped. Only such
801  *                 dump type is enabled, the frame will be
802  *                 dumped into a file.
803  *
804  * RETURN     : None
805  *==========================================================================*/
dumpFrameToFile(const void * data,uint32_t size,int index,int dump_type)806 void QCamera2HardwareInterface::dumpFrameToFile(const void *data,
807                                                 uint32_t size,
808                                                 int index,
809                                                 int dump_type)
810 {
811     char value[PROPERTY_VALUE_MAX];
812     property_get("persist.camera.dumpimg", value, "0");
813     int32_t enabled = atoi(value);
814     int frm_num = 0;
815     uint32_t skip_mode = 0;
816 
817     char buf[32];
818     cam_dimension_t dim;
819     memset(buf, 0, sizeof(buf));
820     memset(&dim, 0, sizeof(dim));
821 
822     if(enabled & QCAMERA_DUMP_FRM_MASK_ALL) {
823         if((enabled & dump_type) && data) {
824             frm_num = ((enabled & 0xffff0000) >> 16);
825             if(frm_num == 0) {
826                 frm_num = 10; //default 10 frames
827             }
828             if(frm_num > 256) {
829                 frm_num = 256; //256 buffers cycle around
830             }
831             skip_mode = ((enabled & 0x0000ff00) >> 8);
832             if(skip_mode == 0) {
833                 skip_mode = 1; //no-skip
834             }
835 
836             if( mDumpSkipCnt % skip_mode == 0) {
837                 if((frm_num == 256) && (mDumpFrmCnt >= frm_num)) {
838                     // reset frame count if cycling
839                     mDumpFrmCnt = 0;
840                 }
841                 if (mDumpFrmCnt >= 0 && mDumpFrmCnt <= frm_num) {
842                     switch (dump_type) {
843                     case QCAMERA_DUMP_FRM_PREVIEW:
844                         {
845                             mParameters.getStreamDimension(CAM_STREAM_TYPE_PREVIEW, dim);
846                             snprintf(buf, sizeof(buf), "/data/%dp_%dx%d_%d.yuv",
847                                      mDumpFrmCnt, dim.width, dim.height, index);
848                         }
849                         break;
850                     case QCAMERA_DUMP_FRM_THUMBNAIL:
851                         {
852                         mParameters.getStreamDimension(CAM_STREAM_TYPE_POSTVIEW, dim);
853                         snprintf(buf, sizeof(buf), "/data/%dt_%dx%d_%d.yuv",
854                                  mDumpFrmCnt, dim.width, dim.height, index);
855                         }
856                         break;
857                     case QCAMERA_DUMP_FRM_SNAPSHOT:
858                         {
859                             if (mParameters.isZSLMode())
860                                 mParameters.getStreamDimension(CAM_STREAM_TYPE_SNAPSHOT, dim);
861                             else
862                                 mParameters.getStreamDimension(CAM_STREAM_TYPE_NON_ZSL_SNAPSHOT, dim);
863                             snprintf(buf, sizeof(buf), "/data/%ds_%dx%d_%d.yuv",
864                                      mDumpFrmCnt, dim.width, dim.height, index);
865                         }
866                     break;
867                     case QCAMERA_DUMP_FRM_VIDEO:
868                         {
869                             mParameters.getStreamDimension(CAM_STREAM_TYPE_VIDEO, dim);
870                             snprintf(buf, sizeof(buf), "/data/%dv_%dx%d_%d.yuv",
871                                      mDumpFrmCnt, dim.width, dim.height, index);
872                         }
873                         break;
874                     case QCAMERA_DUMP_FRM_RAW:
875                         {
876                             mParameters.getStreamDimension(CAM_STREAM_TYPE_RAW, dim);
877                             snprintf(buf, sizeof(buf), "/data/%dr_%dx%d_%d.yuv",
878                                      mDumpFrmCnt, dim.width, dim.height, index);
879                         }
880                         break;
881                     case QCAMERA_DUMP_FRM_JPEG:
882                         {
883                             if (mParameters.isZSLMode())
884                                 mParameters.getStreamDimension(CAM_STREAM_TYPE_SNAPSHOT, dim);
885                             else
886                                 mParameters.getStreamDimension(CAM_STREAM_TYPE_NON_ZSL_SNAPSHOT, dim);
887                             snprintf(buf, sizeof(buf), "/data/%dj_%dx%d_%d.yuv",
888                                      mDumpFrmCnt, dim.width, dim.height, index);
889                         }
890                         break;
891                     default:
892                         ALOGE("%s: Not supported for dumping stream type %d",
893                               __func__, dump_type);
894                         return;
895                     }
896 
897                     ALOGD("dump %s size =%d, data = %p", buf, size, data);
898                     int file_fd = open(buf, O_RDWR | O_CREAT, 0777);
899                     if (file_fd > 0) {
900                         int written_len = write(file_fd, data, size);
901                         ALOGD("%s: written number of bytes %d\n", __func__, written_len);
902                         close(file_fd);
903                     } else {
904                         ALOGE("%s: fail t open file for image dumping", __func__);
905                     }
906                     mDumpFrmCnt++;
907                 }
908             }
909             mDumpSkipCnt++;
910         }
911     } else {
912         mDumpFrmCnt = 0;
913     }
914 }
915 
916 /*===========================================================================
917  * FUNCTION   : debugShowVideoFPS
918  *
919  * DESCRIPTION: helper function to log video frame FPS for debug purpose.
920  *
921  * PARAMETERS : None
922  *
923  * RETURN     : None
924  *==========================================================================*/
debugShowVideoFPS()925 void QCamera2HardwareInterface::debugShowVideoFPS()
926 {
927     static int n_vFrameCount = 0;
928     static int n_vLastFrameCount = 0;
929     static nsecs_t n_vLastFpsTime = 0;
930     static float n_vFps = 0;
931     n_vFrameCount++;
932     nsecs_t now = systemTime();
933     nsecs_t diff = now - n_vLastFpsTime;
934     if (diff > ms2ns(250)) {
935         n_vFps =  ((n_vFrameCount - n_vLastFrameCount) * float(s2ns(1))) / diff;
936         ALOGE("Video Frames Per Second: %.4f", n_vFps);
937         n_vLastFpsTime = now;
938         n_vLastFrameCount = n_vFrameCount;
939     }
940 }
941 
942 /*===========================================================================
943  * FUNCTION   : debugShowPreviewFPS
944  *
945  * DESCRIPTION: helper function to log preview frame FPS for debug purpose.
946  *
947  * PARAMETERS : None
948  *
949  * RETURN     : None
950  *==========================================================================*/
debugShowPreviewFPS()951 void QCamera2HardwareInterface::debugShowPreviewFPS()
952 {
953     static int n_pFrameCount = 0;
954     static int n_pLastFrameCount = 0;
955     static nsecs_t n_pLastFpsTime = 0;
956     static float n_pFps = 0;
957     n_pFrameCount++;
958     nsecs_t now = systemTime();
959     nsecs_t diff = now - n_pLastFpsTime;
960     if (diff > ms2ns(250)) {
961         n_pFps =  ((n_pFrameCount - n_pLastFrameCount) * float(s2ns(1))) / diff;
962         ALOGE("Preview Frames Per Second: %.4f", n_pFps);
963         n_pLastFpsTime = now;
964         n_pLastFrameCount = n_pFrameCount;
965     }
966 }
967 
968 /*===========================================================================
969  * FUNCTION   : ~QCameraCbNotifier
970  *
971  * DESCRIPTION: Destructor for exiting the callback context.
972  *
973  * PARAMETERS : None
974  *
975  * RETURN     : None
976  *==========================================================================*/
~QCameraCbNotifier()977 QCameraCbNotifier::~QCameraCbNotifier()
978 {
979     mProcTh.exit();
980 }
981 
982 /*===========================================================================
983  * FUNCTION   : releaseNotifications
984  *
985  * DESCRIPTION: callback for releasing data stored in the callback queue.
986  *
987  * PARAMETERS :
988  *   @data      : data to be released
989  *   @user_data : context data
990  *
991  * RETURN     : None
992  *==========================================================================*/
releaseNotifications(void * data,void * user_data)993 void QCameraCbNotifier::releaseNotifications(void *data, void *user_data)
994 {
995     qcamera_callback_argm_t *arg = ( qcamera_callback_argm_t * ) data;
996 
997     if ( ( NULL != arg ) && ( NULL != user_data ) ) {
998         if ( arg->release_cb ) {
999             arg->release_cb(arg->user_data, arg->cookie);
1000         }
1001     }
1002 }
1003 
1004 /*===========================================================================
1005  * FUNCTION   : matchSnapshotNotifications
1006  *
1007  * DESCRIPTION: matches snapshot data callbacks
1008  *
1009  * PARAMETERS :
1010  *   @data      : data to match
1011  *   @user_data : context data
1012  *
1013  * RETURN     : bool match
1014  *              true - match found
1015  *              false- match not found
1016  *==========================================================================*/
matchSnapshotNotifications(void * data,void *)1017 bool QCameraCbNotifier::matchSnapshotNotifications(void *data,
1018                                                    void */*user_data*/)
1019 {
1020     qcamera_callback_argm_t *arg = ( qcamera_callback_argm_t * ) data;
1021     if ( NULL != arg ) {
1022         if ( QCAMERA_DATA_SNAPSHOT_CALLBACK == arg->cb_type ) {
1023             return true;
1024         }
1025     }
1026 
1027     return false;
1028 }
1029 
1030 /*===========================================================================
1031  * FUNCTION   : cbNotifyRoutine
1032  *
1033  * DESCRIPTION: callback thread which interfaces with the upper layers
1034  *              given input commands.
1035  *
1036  * PARAMETERS :
1037  *   @data    : context data
1038  *
1039  * RETURN     : None
1040  *==========================================================================*/
cbNotifyRoutine(void * data)1041 void * QCameraCbNotifier::cbNotifyRoutine(void * data)
1042 {
1043     int running = 1;
1044     int ret;
1045     QCameraCbNotifier *pme = (QCameraCbNotifier *)data;
1046     QCameraCmdThread *cmdThread = &pme->mProcTh;
1047     uint8_t isSnapshotActive = FALSE;
1048     uint32_t numOfSnapshotExpected = 0;
1049     uint32_t numOfSnapshotRcvd = 0;
1050 
1051     ALOGV("%s: E", __func__);
1052     do {
1053         do {
1054             ret = cam_sem_wait(&cmdThread->cmd_sem);
1055             if (ret != 0 && errno != EINVAL) {
1056                 ALOGV("%s: cam_sem_wait error (%s)",
1057                            __func__, strerror(errno));
1058                 return NULL;
1059             }
1060         } while (ret != 0);
1061 
1062         camera_cmd_type_t cmd = cmdThread->getCmd();
1063         ALOGV("%s: get cmd %d", __func__, cmd);
1064         switch (cmd) {
1065         case CAMERA_CMD_TYPE_START_DATA_PROC:
1066             {
1067                 isSnapshotActive = TRUE;
1068                 numOfSnapshotExpected = pme->mParent->numOfSnapshotsExpected();
1069                 numOfSnapshotRcvd = 0;
1070             }
1071             break;
1072         case CAMERA_CMD_TYPE_STOP_DATA_PROC:
1073             {
1074                 pme->mDataQ.flushNodes(matchSnapshotNotifications);
1075                 isSnapshotActive = FALSE;
1076 
1077                 numOfSnapshotExpected = 0;
1078                 numOfSnapshotRcvd = 0;
1079             }
1080             break;
1081         case CAMERA_CMD_TYPE_DO_NEXT_JOB:
1082             {
1083                 qcamera_callback_argm_t *cb =
1084                     (qcamera_callback_argm_t *)pme->mDataQ.dequeue();
1085                 if (NULL != cb) {
1086                     ALOGV("%s: cb type %d received",
1087                           __func__,
1088                           cb->cb_type);
1089 
1090                     if (pme->mParent->msgTypeEnabledWithLock(cb->msg_type)) {
1091                         switch (cb->cb_type) {
1092                         case QCAMERA_NOTIFY_CALLBACK:
1093                             {
1094                                 if (cb->msg_type == CAMERA_MSG_FOCUS) {
1095                                     ALOGD("[KPI Perf] %s : sending focus evt to app", __func__);
1096                                 }
1097                                 if (pme->mNotifyCb) {
1098                                     pme->mNotifyCb(cb->msg_type,
1099                                                   cb->ext1,
1100                                                   cb->ext2,
1101                                                   pme->mCallbackCookie);
1102                                 } else {
1103                                     ALOGE("%s : notify callback not set!",
1104                                           __func__);
1105                                 }
1106                             }
1107                             break;
1108                         case QCAMERA_DATA_CALLBACK:
1109                             {
1110                                 if (pme->mDataCb) {
1111                                     pme->mDataCb(cb->msg_type,
1112                                                  cb->data,
1113                                                  cb->index,
1114                                                  cb->metadata,
1115                                                  pme->mCallbackCookie);
1116                                 } else {
1117                                     ALOGE("%s : data callback not set!",
1118                                           __func__);
1119                                 }
1120                             }
1121                             break;
1122                         case QCAMERA_DATA_TIMESTAMP_CALLBACK:
1123                             {
1124                                 if(pme->mDataCbTimestamp) {
1125                                     pme->mDataCbTimestamp(cb->timestamp,
1126                                                           cb->msg_type,
1127                                                           cb->data,
1128                                                           cb->index,
1129                                                           pme->mCallbackCookie);
1130                                 } else {
1131                                     ALOGE("%s:data cb with tmp not set!",
1132                                           __func__);
1133                                 }
1134                             }
1135                             break;
1136                         case QCAMERA_DATA_SNAPSHOT_CALLBACK:
1137                             {
1138                                 if (TRUE == isSnapshotActive && pme->mDataCb ) {
1139                                     numOfSnapshotRcvd++;
1140                                     if (numOfSnapshotExpected > 0 &&
1141                                         numOfSnapshotExpected == numOfSnapshotRcvd) {
1142                                         // notify HWI that snapshot is done
1143                                         pme->mParent->processSyncEvt(QCAMERA_SM_EVT_SNAPSHOT_DONE,
1144                                                                      NULL);
1145                                     }
1146                                     pme->mDataCb(cb->msg_type,
1147                                                  cb->data,
1148                                                  cb->index,
1149                                                  cb->metadata,
1150                                                  pme->mCallbackCookie);
1151                                 }
1152                             }
1153                             break;
1154                         default:
1155                             {
1156                                 ALOGE("%s : invalid cb type %d",
1157                                       __func__,
1158                                       cb->cb_type);
1159                             }
1160                             break;
1161                         };
1162                     } else {
1163                         ALOGE("%s : cb message type %d not enabled!",
1164                               __func__,
1165                               cb->msg_type);
1166                     }
1167                     if ( cb->release_cb ) {
1168                         cb->release_cb(cb->user_data, cb->cookie);
1169                     }
1170                     delete cb;
1171                 } else {
1172                     ALOGE("%s: invalid cb type passed", __func__);
1173                 }
1174             }
1175             break;
1176         case CAMERA_CMD_TYPE_EXIT:
1177             {
1178                 pme->mDataQ.flush();
1179                 running = 0;
1180             }
1181             break;
1182         default:
1183             break;
1184         }
1185     } while (running);
1186     ALOGV("%s: X", __func__);
1187 
1188     return NULL;
1189 }
1190 
1191 /*===========================================================================
1192  * FUNCTION   : notifyCallback
1193  *
1194  * DESCRIPTION: Enqueus pending callback notifications for the upper layers.
1195  *
1196  * PARAMETERS :
1197  *   @cbArgs  : callback arguments
1198  *
1199  * RETURN     : int32_t type of status
1200  *              NO_ERROR  -- success
1201  *              none-zero failure code
1202  *==========================================================================*/
notifyCallback(qcamera_callback_argm_t & cbArgs)1203 int32_t QCameraCbNotifier::notifyCallback(qcamera_callback_argm_t &cbArgs)
1204 {
1205     qcamera_callback_argm_t *cbArg = new qcamera_callback_argm_t();
1206     if (NULL == cbArg) {
1207         ALOGE("%s: no mem for qcamera_callback_argm_t", __func__);
1208         return NO_MEMORY;
1209     }
1210     memset(cbArg, 0, sizeof(qcamera_callback_argm_t));
1211     *cbArg = cbArgs;
1212 
1213     if (mDataQ.enqueue((void *)cbArg)) {
1214         mProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
1215     } else {
1216         ALOGE("%s: Error adding cb data into queue", __func__);
1217         delete cbArg;
1218         return UNKNOWN_ERROR;
1219     }
1220 
1221     return NO_ERROR;
1222 }
1223 
1224 /*===========================================================================
1225  * FUNCTION   : setCallbacks
1226  *
1227  * DESCRIPTION: Initializes the callback functions, which would be used for
1228  *              communication with the upper layers and launches the callback
1229  *              context in which the callbacks will occur.
1230  *
1231  * PARAMETERS :
1232  *   @notifyCb          : notification callback
1233  *   @dataCb            : data callback
1234  *   @dataCbTimestamp   : data with timestamp callback
1235  *   @callbackCookie    : callback context data
1236  *
1237  * RETURN     : None
1238  *==========================================================================*/
setCallbacks(camera_notify_callback notifyCb,camera_data_callback dataCb,camera_data_timestamp_callback dataCbTimestamp,void * callbackCookie)1239 void QCameraCbNotifier::setCallbacks(camera_notify_callback notifyCb,
1240                                      camera_data_callback dataCb,
1241                                      camera_data_timestamp_callback dataCbTimestamp,
1242                                      void *callbackCookie)
1243 {
1244     if ( ( NULL == mNotifyCb ) &&
1245          ( NULL == mDataCb ) &&
1246          ( NULL == mDataCbTimestamp ) &&
1247          ( NULL == mCallbackCookie ) ) {
1248         mNotifyCb = notifyCb;
1249         mDataCb = dataCb;
1250         mDataCbTimestamp = dataCbTimestamp;
1251         mCallbackCookie = callbackCookie;
1252         mProcTh.launch(cbNotifyRoutine, this);
1253     } else {
1254         ALOGE("%s : Camera callback notifier already initialized!",
1255               __func__);
1256     }
1257 }
1258 
1259 /*===========================================================================
1260  * FUNCTION   : startSnapshots
1261  *
1262  * DESCRIPTION: Enables snapshot mode
1263  *
1264  * PARAMETERS : None
1265  *
1266  * RETURN     : int32_t type of status
1267  *              NO_ERROR  -- success
1268  *              none-zero failure code
1269  *==========================================================================*/
startSnapshots()1270 int32_t QCameraCbNotifier::startSnapshots()
1271 {
1272     return mProcTh.sendCmd(CAMERA_CMD_TYPE_START_DATA_PROC, FALSE, TRUE);
1273 }
1274 
1275 /*===========================================================================
1276  * FUNCTION   : stopSnapshots
1277  *
1278  * DESCRIPTION: Disables snapshot processing mode
1279  *
1280  * PARAMETERS : None
1281  *
1282  * RETURN     : None
1283  *==========================================================================*/
stopSnapshots()1284 void QCameraCbNotifier::stopSnapshots()
1285 {
1286     mProcTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC, FALSE, TRUE);
1287 }
1288 
1289 }; // namespace qcamera
1290