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