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
37namespace 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 *==========================================================================*/
55void 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*==========================================================================*/
106void 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*==========================================================================*/
197void 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 *==========================================================================*/
245void 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 *==========================================================================*/
370void 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 *==========================================================================*/
448void 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 *==========================================================================*/
520void 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 *==========================================================================*/
589void 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 *==========================================================================*/
628void 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 *==========================================================================*/
664void 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 *==========================================================================*/
771void 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 *==========================================================================*/
806void 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 *==========================================================================*/
925void 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 *==========================================================================*/
951void 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 *==========================================================================*/
977QCameraCbNotifier::~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 *==========================================================================*/
993void 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 *==========================================================================*/
1017bool 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 *==========================================================================*/
1041void * 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 *==========================================================================*/
1203int32_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 *==========================================================================*/
1239void 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 *==========================================================================*/
1270int32_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 *==========================================================================*/
1284void QCameraCbNotifier::stopSnapshots()
1285{
1286    mProcTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC, FALSE, TRUE);
1287}
1288
1289}; // namespace qcamera
1290