QCamera2HWICallbacks.cpp revision 6f83d735d8e3b918da42e6b559fcd0efb78133e5
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    ALOGV("%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    ALOGV("%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("%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("%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("%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("%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("%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    memory->cleanCache(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    ALOGV("%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    ALOGV("%s",__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        previewMemObj->cleanCache(frame->buf_idx);
410
411        pme->dumpFrameToFile(frame->buffer, frame->frame_len,
412                             frame->frame_idx, QCAMERA_DUMP_FRM_PREVIEW);
413
414        if (pme->needProcessPreviewFrame() &&
415            pme->mDataCb != NULL &&
416            pme->msgTypeEnabledWithLock(CAMERA_MSG_PREVIEW_FRAME) > 0 ) {
417            qcamera_callback_argm_t cbArg;
418            memset(&cbArg, 0, sizeof(qcamera_callback_argm_t));
419            cbArg.cb_type = QCAMERA_DATA_CALLBACK;
420            cbArg.msg_type = CAMERA_MSG_PREVIEW_FRAME;
421            cbArg.data = preview_mem;
422            int user_data = frame->buf_idx;
423            cbArg.user_data = ( void * ) user_data;
424            cbArg.cookie = stream;
425            cbArg.release_cb = returnStreamBuffer;
426            pme->m_cbNotifier.notifyCallback(cbArg);
427        } else {
428            stream->bufDone(frame->buf_idx);
429        }
430    }
431    free(super_frame);
432}
433
434/*===========================================================================
435 * FUNCTION   : postview_stream_cb_routine
436 *
437 * DESCRIPTION: helper function to handle post frame from postview stream
438 *
439 * PARAMETERS :
440 *   @super_frame : received super buffer
441 *   @stream      : stream object
442 *   @userdata    : user data ptr
443 *
444 * RETURN    : None
445 *
446 * NOTE      : caller passes the ownership of super_frame, it's our
447 *             responsibility to free super_frame once it's done.
448 *==========================================================================*/
449void QCamera2HardwareInterface::postview_stream_cb_routine(mm_camera_super_buf_t *super_frame,
450                                                           QCameraStream *stream,
451                                                           void *userdata)
452{
453    int err = NO_ERROR;
454    QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata;
455    QCameraGrallocMemory *memory = (QCameraGrallocMemory *)super_frame->bufs[0]->mem_info;
456
457    if (pme == NULL) {
458        ALOGE("%s: Invalid hardware object", __func__);
459        free(super_frame);
460        return;
461    }
462    if (memory == NULL) {
463        ALOGE("%s: Invalid memory object", __func__);
464        free(super_frame);
465        return;
466    }
467
468    ALOGD("%s : BEGIN", __func__);
469
470    mm_camera_buf_def_t *frame = super_frame->bufs[0];
471    if (NULL == frame) {
472        ALOGE("%s: preview frame is NLUL", __func__);
473        free(super_frame);
474        return;
475    }
476
477    QCameraMemory *memObj = (QCameraMemory *)frame->mem_info;
478    if (NULL != memObj) {
479        memObj->cleanCache(frame->buf_idx);
480
481        pme->dumpFrameToFile(frame->buffer, frame->frame_len,
482                             frame->frame_idx, QCAMERA_DUMP_FRM_THUMBNAIL);
483    }
484
485    // Display the buffer.
486    int dequeuedIdx = memory->displayBuffer(frame->buf_idx);
487    if (dequeuedIdx < 0 || dequeuedIdx >= memory->getCnt()) {
488        ALOGD("%s: Invalid dequeued buffer index %d",
489              __func__, dequeuedIdx);
490        free(super_frame);
491        return;
492    }
493
494    // Return dequeued buffer back to driver
495    err = stream->bufDone(dequeuedIdx);
496    if ( err < 0) {
497        ALOGE("stream bufDone failed %d", err);
498    }
499
500    free(super_frame);
501    ALOGD("%s : END", __func__);
502    return;
503}
504
505/*===========================================================================
506 * FUNCTION   : video_stream_cb_routine
507 *
508 * DESCRIPTION: helper function to handle video frame from video stream
509 *
510 * PARAMETERS :
511 *   @super_frame : received super buffer
512 *   @stream      : stream object
513 *   @userdata    : user data ptr
514 *
515 * RETURN    : None
516 *
517 * NOTE      : caller passes the ownership of super_frame, it's our
518 *             responsibility to free super_frame once it's done. video
519 *             frame will be sent to video encoder. Once video encoder is
520 *             done with the video frame, it will call another API
521 *             (release_recording_frame) to return the frame back
522 *==========================================================================*/
523void QCamera2HardwareInterface::video_stream_cb_routine(mm_camera_super_buf_t *super_frame,
524                                                        QCameraStream */*stream*/,
525                                                        void *userdata)
526{
527    ALOGV("%s : BEGIN", __func__);
528    QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata;
529    if (pme == NULL ||
530        pme->mCameraHandle == NULL ||
531        pme->mCameraHandle->camera_handle != super_frame->camera_handle){
532        ALOGE("%s: camera obj not valid", __func__);
533        // simply free super frame
534        free(super_frame);
535        return;
536    }
537    mm_camera_buf_def_t *frame = super_frame->bufs[0];
538
539    if (pme->needDebugFps()) {
540        pme->debugShowVideoFPS();
541    }
542
543    ALOGE("%s: Stream(%d), Timestamp: %ld %ld",
544          __func__,
545          frame->stream_id,
546          frame->ts.tv_sec,
547          frame->ts.tv_nsec);
548
549    nsecs_t timeStamp = nsecs_t(frame->ts.tv_sec) * 1000000000LL + frame->ts.tv_nsec;
550    ALOGE("Send Video frame to services/encoder TimeStamp : %lld", timeStamp);
551    QCameraMemory *videoMemObj = (QCameraMemory *)frame->mem_info;
552    camera_memory_t *video_mem = NULL;
553    if (NULL != videoMemObj) {
554        video_mem = videoMemObj->getMemory(frame->buf_idx, (pme->mStoreMetaDataInFrame > 0)? true : false);
555    }
556    if (NULL != videoMemObj && NULL != video_mem) {
557        videoMemObj->cleanCache(frame->buf_idx);
558        pme->dumpFrameToFile(frame->buffer, frame->frame_len,
559                             frame->frame_idx, QCAMERA_DUMP_FRM_VIDEO);
560        if ((pme->mDataCbTimestamp != NULL) &&
561            pme->msgTypeEnabledWithLock(CAMERA_MSG_VIDEO_FRAME) > 0) {
562            qcamera_callback_argm_t cbArg;
563            memset(&cbArg, 0, sizeof(qcamera_callback_argm_t));
564            cbArg.cb_type = QCAMERA_DATA_TIMESTAMP_CALLBACK;
565            cbArg.msg_type = CAMERA_MSG_VIDEO_FRAME;
566            cbArg.data = video_mem;
567            cbArg.timestamp = timeStamp;
568            pme->m_cbNotifier.notifyCallback(cbArg);
569        }
570    }
571    free(super_frame);
572    ALOGV("%s : END", __func__);
573}
574
575/*===========================================================================
576 * FUNCTION   : snapshot_stream_cb_routine
577 *
578 * DESCRIPTION: helper function to handle snapshot frame from snapshot stream
579 *
580 * PARAMETERS :
581 *   @super_frame : received super buffer
582 *   @stream      : stream object
583 *   @userdata    : user data ptr
584 *
585 * RETURN    : None
586 *
587 * NOTE      : caller passes the ownership of super_frame, it's our
588 *             responsibility to free super_frame once it's done. For
589 *             snapshot, it need to send to postprocessor for jpeg
590 *             encoding, therefore the ownership of super_frame will be
591 *             hand to postprocessor.
592 *==========================================================================*/
593void QCamera2HardwareInterface::snapshot_stream_cb_routine(mm_camera_super_buf_t *super_frame,
594                                                           QCameraStream * /*stream*/,
595                                                           void *userdata)
596{
597    ALOGD("%s: E", __func__);
598    QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata;
599    if (pme == NULL ||
600        pme->mCameraHandle == NULL ||
601        pme->mCameraHandle->camera_handle != super_frame->camera_handle){
602        ALOGE("%s: camera obj not valid", __func__);
603        // simply free super frame
604        free(super_frame);
605        return;
606    }
607
608    pme->m_postprocessor.processData(super_frame);
609
610    ALOGD("%s: X", __func__);
611}
612
613/*===========================================================================
614 * FUNCTION   : raw_stream_cb_routine
615 *
616 * DESCRIPTION: helper function to handle raw dump frame from raw stream
617 *
618 * PARAMETERS :
619 *   @super_frame : received super buffer
620 *   @stream      : stream object
621 *   @userdata    : user data ptr
622 *
623 * RETURN    : None
624 *
625 * NOTE      : caller passes the ownership of super_frame, it's our
626 *             responsibility to free super_frame once it's done. For raw
627 *             frame, there is no need to send to postprocessor for jpeg
628 *             encoding. this function will play shutter and send the data
629 *             callback to upper layer. Raw frame buffer will be returned
630 *             back to kernel, and frame will be free after use.
631 *==========================================================================*/
632void QCamera2HardwareInterface::raw_stream_cb_routine(mm_camera_super_buf_t * super_frame,
633                                                      QCameraStream * /*stream*/,
634                                                      void * userdata)
635{
636    ALOGV("%s : BEGIN", __func__);
637    QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata;
638    if (pme == NULL ||
639        pme->mCameraHandle == NULL ||
640        pme->mCameraHandle->camera_handle != super_frame->camera_handle){
641        ALOGE("%s: camera obj not valid", __func__);
642        // simply free super frame
643        free(super_frame);
644        return;
645    }
646
647    pme->m_postprocessor.processRawData(super_frame);
648    ALOGV("%s : END", __func__);
649}
650
651/*===========================================================================
652 * FUNCTION   : metadata_stream_cb_routine
653 *
654 * DESCRIPTION: helper function to handle metadata frame from metadata stream
655 *
656 * PARAMETERS :
657 *   @super_frame : received super buffer
658 *   @stream      : stream object
659 *   @userdata    : user data ptr
660 *
661 * RETURN    : None
662 *
663 * NOTE      : caller passes the ownership of super_frame, it's our
664 *             responsibility to free super_frame once it's done. Metadata
665 *             could have valid entries for face detection result or
666 *             histogram statistics information.
667 *==========================================================================*/
668void QCamera2HardwareInterface::metadata_stream_cb_routine(mm_camera_super_buf_t * super_frame,
669                                                           QCameraStream * stream,
670                                                           void * userdata)
671{
672    ALOGD("%s : BEGIN", __func__);
673    QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata;
674    if (pme == NULL ||
675        pme->mCameraHandle == NULL ||
676        pme->mCameraHandle->camera_handle != super_frame->camera_handle){
677        ALOGE("%s: camera obj not valid", __func__);
678        // simply free super frame
679        free(super_frame);
680        return;
681    }
682
683    mm_camera_buf_def_t *frame = super_frame->bufs[0];
684    cam_metadata_info_t *pMetaData = (cam_metadata_info_t *)frame->buffer;
685
686    if (pMetaData->is_faces_valid) {
687        if (pMetaData->faces_data.num_faces_detected > MAX_ROI) {
688            ALOGE("%s: Invalid number of faces %d",
689                __func__, pMetaData->faces_data.num_faces_detected);
690        } else {
691            // process face detection result
692            pme->processFaceDetectionResult(&pMetaData->faces_data);
693        }
694    }
695
696    if (pMetaData->is_stats_valid) {
697        // process histogram statistics info
698        pme->processHistogramStats(pMetaData->stats_data);
699    }
700
701    if (pMetaData->is_focus_valid) {
702        // process focus info
703        qcamera_sm_internal_evt_payload_t *payload =
704            (qcamera_sm_internal_evt_payload_t *)malloc(sizeof(qcamera_sm_internal_evt_payload_t));
705        if (NULL != payload) {
706            memset(payload, 0, sizeof(qcamera_sm_internal_evt_payload_t));
707            payload->evt_type = QCAMERA_INTERNAL_EVT_FOCUS_UPDATE;
708            payload->focus_data = pMetaData->focus_data;
709            int32_t rc = pme->processEvt(QCAMERA_SM_EVT_EVT_INTERNAL, payload);
710            if (rc != NO_ERROR) {
711                ALOGE("%s: processEVt failed", __func__);
712                free(payload);
713                payload = NULL;
714
715            }
716        } else {
717            ALOGE("%s: No memory for qcamera_sm_internal_evt_payload_t", __func__);
718        }
719    }
720
721    if (pMetaData->is_crop_valid) {
722        if (pMetaData->crop_data.num_of_streams > MAX_NUM_STREAMS) {
723            ALOGE("%s: Invalid num_of_streams %d in crop_data", __func__,
724                pMetaData->crop_data.num_of_streams);
725        } else {
726            pme->processZoomEvent(pMetaData->crop_data);
727        }
728    }
729
730    if (pMetaData->is_prep_snapshot_done_valid) {
731        qcamera_sm_internal_evt_payload_t *payload =
732            (qcamera_sm_internal_evt_payload_t *)malloc(sizeof(qcamera_sm_internal_evt_payload_t));
733        if (NULL != payload) {
734            memset(payload, 0, sizeof(qcamera_sm_internal_evt_payload_t));
735            payload->evt_type = QCAMERA_INTERNAL_EVT_PREP_SNAPSHOT_DONE;
736            payload->prep_snapshot_state = pMetaData->prep_snapshot_done_state;
737            int32_t rc = pme->processEvt(QCAMERA_SM_EVT_EVT_INTERNAL, payload);
738            if (rc != NO_ERROR) {
739                ALOGE("%s: processEVt failed", __func__);
740                free(payload);
741                payload = NULL;
742
743            }
744        } else {
745            ALOGE("%s: No memory for qcamera_sm_internal_evt_payload_t", __func__);
746        }
747    }
748
749    stream->bufDone(frame->buf_idx);
750    free(super_frame);
751
752    ALOGD("%s : END", __func__);
753}
754
755/*===========================================================================
756 * FUNCTION   : reprocess_stream_cb_routine
757 *
758 * DESCRIPTION: helper function to handle reprocess frame from reprocess stream
759                (after reprocess, e.g., ZSL snapshot frame after WNR if
760 *              WNR is enabled)
761 *
762 * PARAMETERS :
763 *   @super_frame : received super buffer
764 *   @stream      : stream object
765 *   @userdata    : user data ptr
766 *
767 * RETURN    : None
768 *
769 * NOTE      : caller passes the ownership of super_frame, it's our
770 *             responsibility to free super_frame once it's done. In this
771 *             case, reprocessed frame need to be passed to postprocessor
772 *             for jpeg encoding.
773 *==========================================================================*/
774void QCamera2HardwareInterface::reprocess_stream_cb_routine(mm_camera_super_buf_t * super_frame,
775                                                            QCameraStream * /*stream*/,
776                                                            void * userdata)
777{
778    ALOGV("%s: E", __func__);
779    QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata;
780    if (pme == NULL ||
781        pme->mCameraHandle == NULL ||
782        pme->mCameraHandle->camera_handle != super_frame->camera_handle){
783        ALOGE("%s: camera obj not valid", __func__);
784        // simply free super frame
785        free(super_frame);
786        return;
787    }
788
789    pme->m_postprocessor.processPPData(super_frame);
790
791    ALOGV("%s: X", __func__);
792}
793
794/*===========================================================================
795 * FUNCTION   : dumpFrameToFile
796 *
797 * DESCRIPTION: helper function to dump frame into file for debug purpose.
798 *
799 * PARAMETERS :
800 *    @data : data ptr
801 *    @size : length of data buffer
802 *    @index : identifier for data
803 *    @dump_type : type of the frame to be dumped. Only such
804 *                 dump type is enabled, the frame will be
805 *                 dumped into a file.
806 *
807 * RETURN     : None
808 *==========================================================================*/
809void QCamera2HardwareInterface::dumpFrameToFile(const void *data,
810                                                uint32_t size,
811                                                int index,
812                                                int dump_type)
813{
814    char value[PROPERTY_VALUE_MAX];
815    property_get("persist.camera.dumpimg", value, "0");
816    int32_t enabled = atoi(value);
817    int frm_num = 0;
818    uint32_t skip_mode = 0;
819
820    char buf[32];
821    cam_dimension_t dim;
822    memset(buf, 0, sizeof(buf));
823    memset(&dim, 0, sizeof(dim));
824
825    if(enabled & QCAMERA_DUMP_FRM_MASK_ALL) {
826        if((enabled & dump_type) && data) {
827            frm_num = ((enabled & 0xffff0000) >> 16);
828            if(frm_num == 0) {
829                frm_num = 10; //default 10 frames
830            }
831            if(frm_num > 256) {
832                frm_num = 256; //256 buffers cycle around
833            }
834            skip_mode = ((enabled & 0x0000ff00) >> 8);
835            if(skip_mode == 0) {
836                skip_mode = 1; //no-skip
837            }
838
839            if( mDumpSkipCnt % skip_mode == 0) {
840                if((frm_num == 256) && (mDumpFrmCnt >= frm_num)) {
841                    // reset frame count if cycling
842                    mDumpFrmCnt = 0;
843                }
844                if (mDumpFrmCnt >= 0 && mDumpFrmCnt <= frm_num) {
845                    switch (dump_type) {
846                    case QCAMERA_DUMP_FRM_PREVIEW:
847                        {
848                            mParameters.getStreamDimension(CAM_STREAM_TYPE_PREVIEW, dim);
849                            snprintf(buf, sizeof(buf), "/data/%dp_%dx%d_%d.yuv",
850                                     mDumpFrmCnt, dim.width, dim.height, index);
851                        }
852                        break;
853                    case QCAMERA_DUMP_FRM_THUMBNAIL:
854                        {
855                        mParameters.getStreamDimension(CAM_STREAM_TYPE_POSTVIEW, dim);
856                        snprintf(buf, sizeof(buf), "/data/%dt_%dx%d_%d.yuv",
857                                 mDumpFrmCnt, dim.width, dim.height, index);
858                        }
859                        break;
860                    case QCAMERA_DUMP_FRM_SNAPSHOT:
861                        {
862                            mParameters.getStreamDimension(CAM_STREAM_TYPE_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                            mParameters.getStreamDimension(CAM_STREAM_TYPE_SNAPSHOT, dim);
884                            snprintf(buf, sizeof(buf), "/data/%dj_%dx%d_%d.yuv",
885                                     mDumpFrmCnt, dim.width, dim.height, index);
886                        }
887                        break;
888                    default:
889                        ALOGE("%s: Not supported for dumping stream type %d",
890                              __func__, dump_type);
891                        return;
892                    }
893
894                    ALOGD("dump %s size =%d, data = %p", buf, size, data);
895                    int file_fd = open(buf, O_RDWR | O_CREAT, 0777);
896                    if (file_fd > 0) {
897                        int written_len = write(file_fd, data, size);
898                        ALOGD("%s: written number of bytes %d\n", __func__, written_len);
899                        close(file_fd);
900                    } else {
901                        ALOGE("%s: fail t open file for image dumping", __func__);
902                    }
903                    mDumpFrmCnt++;
904                }
905            }
906            mDumpSkipCnt++;
907        }
908    } else {
909        mDumpFrmCnt = 0;
910    }
911}
912
913/*===========================================================================
914 * FUNCTION   : debugShowVideoFPS
915 *
916 * DESCRIPTION: helper function to log video frame FPS for debug purpose.
917 *
918 * PARAMETERS : None
919 *
920 * RETURN     : None
921 *==========================================================================*/
922void QCamera2HardwareInterface::debugShowVideoFPS()
923{
924    static int n_vFrameCount = 0;
925    static int n_vLastFrameCount = 0;
926    static nsecs_t n_vLastFpsTime = 0;
927    static float n_vFps = 0;
928    n_vFrameCount++;
929    nsecs_t now = systemTime();
930    nsecs_t diff = now - n_vLastFpsTime;
931    if (diff > ms2ns(250)) {
932        n_vFps =  ((n_vFrameCount - n_vLastFrameCount) * float(s2ns(1))) / diff;
933        ALOGE("Video Frames Per Second: %.4f", n_vFps);
934        n_vLastFpsTime = now;
935        n_vLastFrameCount = n_vFrameCount;
936    }
937}
938
939/*===========================================================================
940 * FUNCTION   : debugShowPreviewFPS
941 *
942 * DESCRIPTION: helper function to log preview frame FPS for debug purpose.
943 *
944 * PARAMETERS : None
945 *
946 * RETURN     : None
947 *==========================================================================*/
948void QCamera2HardwareInterface::debugShowPreviewFPS()
949{
950    static int n_pFrameCount = 0;
951    static int n_pLastFrameCount = 0;
952    static nsecs_t n_pLastFpsTime = 0;
953    static float n_pFps = 0;
954    n_pFrameCount++;
955    nsecs_t now = systemTime();
956    nsecs_t diff = now - n_pLastFpsTime;
957    if (diff > ms2ns(250)) {
958        n_pFps =  ((n_pFrameCount - n_pLastFrameCount) * float(s2ns(1))) / diff;
959        ALOGE("Preview Frames Per Second: %.4f", n_pFps);
960        n_pLastFpsTime = now;
961        n_pLastFrameCount = n_pFrameCount;
962    }
963}
964
965/*===========================================================================
966 * FUNCTION   : ~QCameraCbNotifier
967 *
968 * DESCRIPTION: Destructor for exiting the callback context.
969 *
970 * PARAMETERS : None
971 *
972 * RETURN     : None
973 *==========================================================================*/
974QCameraCbNotifier::~QCameraCbNotifier()
975{
976    mProcTh.exit();
977}
978
979/*===========================================================================
980 * FUNCTION   : releaseNotifications
981 *
982 * DESCRIPTION: callback for releasing data stored in the callback queue.
983 *
984 * PARAMETERS :
985 *   @data      : data to be released
986 *   @user_data : context data
987 *
988 * RETURN     : None
989 *==========================================================================*/
990void QCameraCbNotifier::releaseNotifications(void *data, void *user_data)
991{
992    qcamera_callback_argm_t *arg = ( qcamera_callback_argm_t * ) data;
993
994    if ( ( NULL != arg ) && ( NULL != user_data ) ) {
995
996        if ( arg->release_cb ) {
997            arg->release_cb(arg->user_data, arg->cookie);
998        }
999
1000        delete arg;
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 (pme->mNotifyCb) {
1095                                    pme->mNotifyCb(cb->msg_type,
1096                                                  cb->ext1,
1097                                                  cb->ext2,
1098                                                  pme->mCallbackCookie);
1099                                } else {
1100                                    ALOGE("%s : notify callback not set!",
1101                                          __func__);
1102                                }
1103                            }
1104                            break;
1105                        case QCAMERA_DATA_CALLBACK:
1106                            {
1107                                if (pme->mDataCb) {
1108                                    pme->mDataCb(cb->msg_type,
1109                                                 cb->data,
1110                                                 cb->index,
1111                                                 cb->metadata,
1112                                                 pme->mCallbackCookie);
1113                                } else {
1114                                    ALOGE("%s : data callback not set!",
1115                                          __func__);
1116                                }
1117                            }
1118                            break;
1119                        case QCAMERA_DATA_TIMESTAMP_CALLBACK:
1120                            {
1121                                if(pme->mDataCbTimestamp) {
1122                                    pme->mDataCbTimestamp(cb->timestamp,
1123                                                          cb->msg_type,
1124                                                          cb->data,
1125                                                          cb->index,
1126                                                          pme->mCallbackCookie);
1127                                } else {
1128                                    ALOGE("%s:data cb with tmp not set!",
1129                                          __func__);
1130                                }
1131                            }
1132                            break;
1133                        case QCAMERA_DATA_SNAPSHOT_CALLBACK:
1134                            {
1135                                if (TRUE == isSnapshotActive && pme->mDataCb ) {
1136                                    pme->mDataCb(cb->msg_type,
1137                                                 cb->data,
1138                                                 cb->index,
1139                                                 cb->metadata,
1140                                                 pme->mCallbackCookie);
1141                                    numOfSnapshotRcvd++;
1142                                    if (numOfSnapshotExpected > 0 &&
1143                                        numOfSnapshotExpected == numOfSnapshotRcvd) {
1144                                        // notify HWI that snapshot is done
1145                                        pme->mParent->processEvt(QCAMERA_SM_EVT_SNAPSHOT_DONE,
1146                                                                 NULL);
1147                                    }
1148                                }
1149                            }
1150                            break;
1151                        default:
1152                            {
1153                                ALOGE("%s : invalid cb type %d",
1154                                      __func__,
1155                                      cb->cb_type);
1156                            }
1157                            break;
1158                        };
1159                    } else {
1160                        ALOGE("%s : cb message type %d not enabled!",
1161                              __func__,
1162                              cb->msg_type);
1163                    }
1164                    if ( cb->release_cb ) {
1165                        cb->release_cb(cb->user_data, cb->cookie);
1166                    }
1167                    delete cb;
1168                } else {
1169                    ALOGE("%s: invalid cb type passed", __func__);
1170                }
1171            }
1172            break;
1173        case CAMERA_CMD_TYPE_EXIT:
1174            {
1175                pme->mDataQ.flush();
1176                running = 0;
1177            }
1178            break;
1179        default:
1180            break;
1181        }
1182    } while (running);
1183    ALOGV("%s: X", __func__);
1184
1185    return NULL;
1186}
1187
1188/*===========================================================================
1189 * FUNCTION   : notifyCallback
1190 *
1191 * DESCRIPTION: Enqueus pending callback notifications for the upper layers.
1192 *
1193 * PARAMETERS :
1194 *   @cbArgs  : callback arguments
1195 *
1196 * RETURN     : int32_t type of status
1197 *              NO_ERROR  -- success
1198 *              none-zero failure code
1199 *==========================================================================*/
1200int32_t QCameraCbNotifier::notifyCallback(qcamera_callback_argm_t &cbArgs)
1201{
1202    qcamera_callback_argm_t *cbArg = new qcamera_callback_argm_t();
1203    if (NULL == cbArg) {
1204        ALOGE("%s: no mem for qcamera_callback_argm_t", __func__);
1205        return NO_MEMORY;
1206    }
1207    memset(cbArg, 0, sizeof(qcamera_callback_argm_t));
1208    *cbArg = cbArgs;
1209
1210    if (mDataQ.enqueue((void *)cbArg)) {
1211        mProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
1212    } else {
1213        ALOGE("%s: Error adding cb data into queue", __func__);
1214        delete cbArg;
1215        return UNKNOWN_ERROR;
1216    }
1217
1218    return NO_ERROR;
1219}
1220
1221/*===========================================================================
1222 * FUNCTION   : setCallbacks
1223 *
1224 * DESCRIPTION: Initializes the callback functions, which would be used for
1225 *              communication with the upper layers and launches the callback
1226 *              context in which the callbacks will occur.
1227 *
1228 * PARAMETERS :
1229 *   @notifyCb          : notification callback
1230 *   @dataCb            : data callback
1231 *   @dataCbTimestamp   : data with timestamp callback
1232 *   @callbackCookie    : callback context data
1233 *
1234 * RETURN     : None
1235 *==========================================================================*/
1236void QCameraCbNotifier::setCallbacks(camera_notify_callback notifyCb,
1237                                     camera_data_callback dataCb,
1238                                     camera_data_timestamp_callback dataCbTimestamp,
1239                                     void *callbackCookie)
1240{
1241    if ( ( NULL == mNotifyCb ) &&
1242         ( NULL == mDataCb ) &&
1243         ( NULL == mDataCbTimestamp ) &&
1244         ( NULL == mCallbackCookie ) ) {
1245        mNotifyCb = notifyCb;
1246        mDataCb = dataCb;
1247        mDataCbTimestamp = dataCbTimestamp;
1248        mCallbackCookie = callbackCookie;
1249        mProcTh.launch(cbNotifyRoutine, this);
1250    } else {
1251        ALOGE("%s : Camera callback notifier already initialized!",
1252              __func__);
1253    }
1254}
1255
1256/*===========================================================================
1257 * FUNCTION   : startSnapshots
1258 *
1259 * DESCRIPTION: Enables snapshot mode
1260 *
1261 * PARAMETERS : None
1262 *
1263 * RETURN     : int32_t type of status
1264 *              NO_ERROR  -- success
1265 *              none-zero failure code
1266 *==========================================================================*/
1267int32_t QCameraCbNotifier::startSnapshots()
1268{
1269    return mProcTh.sendCmd(CAMERA_CMD_TYPE_START_DATA_PROC, FALSE, TRUE);
1270}
1271
1272/*===========================================================================
1273 * FUNCTION   : stopSnapshots
1274 *
1275 * DESCRIPTION: Disables snapshot processing mode
1276 *
1277 * PARAMETERS : None
1278 *
1279 * RETURN     : None
1280 *==========================================================================*/
1281void QCameraCbNotifier::stopSnapshots()
1282{
1283    mProcTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC, FALSE, TRUE);
1284}
1285
1286}; // namespace qcamera
1287