1/* Copyright (c) 2012-2016, The Linux Foundation. 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 "QCameraChannel"
31
32// System dependencies
33#include <utils/Errors.h>
34
35// Camera dependencies
36#include "QCamera2HWI.h"
37
38extern "C" {
39#include "mm_camera_dbg.h"
40}
41
42using namespace android;
43
44namespace qcamera {
45
46/*===========================================================================
47 * FUNCTION   : QCameraChannel
48 *
49 * DESCRIPTION: constrcutor of QCameraChannel
50 *
51 * PARAMETERS :
52 *   @cam_handle : camera handle
53 *   @cam_ops    : ptr to camera ops table
54 *
55 * RETURN     : none
56 *==========================================================================*/
57QCameraChannel::QCameraChannel(uint32_t cam_handle,
58                               mm_camera_ops_t *cam_ops)
59{
60    m_camHandle = cam_handle;
61    m_camOps = cam_ops;
62    m_bIsActive = false;
63    m_bAllowDynBufAlloc = false;
64
65    m_handle = 0;
66}
67
68/*===========================================================================
69 * FUNCTION   : QCameraChannel
70 *
71 * DESCRIPTION: default constrcutor of QCameraChannel
72 *
73 * PARAMETERS : none
74 *
75 * RETURN     : none
76 *==========================================================================*/
77QCameraChannel::QCameraChannel()
78{
79    m_camHandle = 0;
80    m_camOps = NULL;
81    m_bIsActive = false;
82
83    m_handle = 0;
84}
85
86/*===========================================================================
87 * FUNCTION   : ~QCameraChannel
88 *
89 * DESCRIPTION: destructor of QCameraChannel
90 *
91 * PARAMETERS : none
92 *
93 * RETURN     : none
94 *==========================================================================*/
95QCameraChannel::~QCameraChannel()
96{
97    if (m_bIsActive) {
98        stop();
99    }
100    for (size_t i = 0; i < mStreams.size(); i++) {
101        if (mStreams[i] != NULL) {
102                if (m_handle == mStreams[i]->getChannelHandle()) {
103                    delete mStreams[i];
104                }
105        }
106    }
107    mStreams.clear();
108    m_camOps->delete_channel(m_camHandle, m_handle);
109    m_handle = 0;
110}
111
112/*===========================================================================
113 * FUNCTION   : deleteChannel
114 *
115 * DESCRIPTION: deletes a camera channel
116 *
117 * PARAMETERS : none
118 *
119 * RETURN     : none
120 *==========================================================================*/
121void QCameraChannel::deleteChannel()
122{
123    if (m_bIsActive) {
124        stop();
125    }
126    for (size_t i = 0; i < mStreams.size(); i++) {
127        if ((mStreams[i] != NULL) && (m_handle == mStreams[i]->getChannelHandle())) {
128            mStreams[i]->deleteStream();
129        }
130    }
131    m_camOps->delete_channel(m_camHandle, m_handle);
132}
133
134/*===========================================================================
135 * FUNCTION   : setStreamSyncCB
136 *
137 * DESCRIPTION: reg callback function to stream of stream type
138 *
139 * PARAMETERS :
140 *    @stream_type : Stream type for which callback needs to be registered.
141 *    @stream_cb   : Callback function
142
143 * RETURN     : int32_t type of status
144 *              NO_ERROR  -- success
145 *              non-zero failure code
146 *==========================================================================*/
147int32_t QCameraChannel::setStreamSyncCB (cam_stream_type_t stream_type,
148        stream_cb_routine stream_cb)
149{
150    int32_t rc = UNKNOWN_ERROR;
151    for (size_t i = 0; i < mStreams.size(); i++) {
152        if ((mStreams[i] != NULL) && (stream_type == mStreams[i]->getMyType())) {
153            rc = mStreams[i]->setSyncDataCB(stream_cb);
154            break;
155        }
156    }
157    return rc;
158}
159
160/*===========================================================================
161 * FUNCTION   : init
162 *
163 * DESCRIPTION: initialization of channel
164 *
165 * PARAMETERS :
166 *   @attr    : channel bundle attribute setting
167 *   @dataCB  : data notify callback
168 *   @userData: user data ptr
169 *
170 * RETURN     : int32_t type of status
171 *              NO_ERROR  -- success
172 *              none-zero failure code
173 *==========================================================================*/
174int32_t QCameraChannel::init(mm_camera_channel_attr_t *attr,
175                             mm_camera_buf_notify_t dataCB,
176                             void *userData)
177{
178    m_handle = m_camOps->add_channel(m_camHandle,
179                                      attr,
180                                      dataCB,
181                                      userData);
182    if (m_handle == 0) {
183        LOGE("Add channel failed");
184        return UNKNOWN_ERROR;
185    }
186    return NO_ERROR;
187}
188
189/*===========================================================================
190 * FUNCTION   : addStream
191 *
192 * DESCRIPTION: add a stream into channel
193 *
194 * PARAMETERS :
195 *   @allocator      : stream related buffer allocator
196 *   @streamInfoBuf  : ptr to buf that contains stream info
197 *   @miscBuf        : ptr to buf that contains misc buffers
198 *   @minStreamBufNum: number of stream buffers needed
199 *   @paddingInfo    : padding information
200 *   @stream_cb      : stream data notify callback
201 *   @userdata       : user data ptr
202 *   @bDynAllocBuf   : flag indicating if allow allocate buffers in 2 steps
203 *   @online_rotation: rotation applied online
204 *
205 * RETURN     : int32_t type of status
206 *              NO_ERROR  -- success
207 *              none-zero failure code
208 *==========================================================================*/
209int32_t QCameraChannel::addStream(QCameraAllocator &allocator,
210        QCameraHeapMemory *streamInfoBuf, QCameraHeapMemory *miscBuf,
211        uint8_t minStreamBufNum, cam_padding_info_t *paddingInfo,
212        stream_cb_routine stream_cb, void *userdata, bool bDynAllocBuf,
213        bool bDeffAlloc, cam_rotation_t online_rotation)
214{
215    int32_t rc = NO_ERROR;
216    if (mStreams.size() >= MAX_STREAM_NUM_IN_BUNDLE) {
217        LOGE("stream number (%zu) exceeds max limit (%d)",
218               mStreams.size(), MAX_STREAM_NUM_IN_BUNDLE);
219        if (streamInfoBuf != NULL) {
220            streamInfoBuf->deallocate();
221            delete streamInfoBuf;
222            streamInfoBuf = NULL;
223        }
224        return BAD_VALUE;
225    }
226    QCameraStream *pStream = new QCameraStream(allocator,
227            m_camHandle, m_handle, m_camOps, paddingInfo, bDeffAlloc,
228            online_rotation);
229    if (pStream == NULL) {
230        LOGE("No mem for Stream");
231        if (streamInfoBuf != NULL) {
232            streamInfoBuf->deallocate();
233            delete streamInfoBuf;
234            streamInfoBuf = NULL;
235        }
236        return NO_MEMORY;
237    }
238
239    rc = pStream->init(streamInfoBuf, miscBuf, minStreamBufNum,
240                       stream_cb, userdata, bDynAllocBuf);
241    if (rc == 0) {
242        mStreams.add(pStream);
243    } else {
244        delete pStream;
245    }
246    return rc;
247}
248
249/*===========================================================================
250 * FUNCTION   : linkStream
251 *
252 * DESCRIPTION: link a stream into channel
253 *
254 * PARAMETERS :
255 *   @ch      : Channel which the stream belongs to
256 *   @stream  : Stream which needs to be linked
257 *
258 * RETURN     : int32_t type of status
259 *              NO_ERROR  -- success
260 *              none-zero failure code
261 *==========================================================================*/
262int32_t QCameraChannel::linkStream(QCameraChannel *ch, QCameraStream *stream)
263{
264    int32_t rc = NO_ERROR;
265
266    if ((0 == m_handle) || (NULL == ch) || (NULL == stream)) {
267        return NO_INIT;
268    }
269
270    int32_t handle = m_camOps->link_stream(m_camHandle,
271            ch->getMyHandle(),
272            stream->getMyHandle(),
273            m_handle);
274    if (0 == handle) {
275        LOGE("Linking of stream failed");
276        rc = INVALID_OPERATION;
277    } else {
278        mStreams.add(stream);
279    }
280
281    return rc;
282}
283
284/*===========================================================================
285 * FUNCTION   : start
286 *
287 * DESCRIPTION: start channel, which will start all streams belong to this channel
288 *
289 * PARAMETERS : None
290 *
291 * RETURN     : int32_t type of status
292 *              NO_ERROR  -- success
293 *              none-zero failure code
294 *==========================================================================*/
295int32_t QCameraChannel::start()
296{
297    int32_t rc = NO_ERROR;
298
299    if (mStreams.size() > 1) {
300        // there is more than one stream in the channel
301        // we need to notify mctl that all streams in this channel need to be bundled
302        cam_bundle_config_t bundleInfo;
303        memset(&bundleInfo, 0, sizeof(bundleInfo));
304        rc = m_camOps->get_bundle_info(m_camHandle, m_handle, &bundleInfo);
305        if (rc != NO_ERROR) {
306            LOGE("get_bundle_info failed");
307            return rc;
308        }
309        if (bundleInfo.num_of_streams > 1) {
310            for (int i = 0; i < bundleInfo.num_of_streams; i++) {
311                QCameraStream *pStream = getStreamByServerID(bundleInfo.stream_ids[i]);
312                if (pStream != NULL) {
313                    if ((pStream->isTypeOf(CAM_STREAM_TYPE_METADATA))
314                            || (pStream->isTypeOf(CAM_STREAM_TYPE_OFFLINE_PROC))) {
315                        // Skip metadata for reprocess now because PP module cannot handle meta data
316                        // May need furthur discussion if Imaginglib need meta data
317                        continue;
318                    }
319
320                    cam_stream_parm_buffer_t param;
321                    memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
322                    param.type = CAM_STREAM_PARAM_TYPE_SET_BUNDLE_INFO;
323                    param.bundleInfo = bundleInfo;
324                    rc = pStream->setParameter(param);
325                    if (rc != NO_ERROR) {
326                        LOGE("stream setParameter for set bundle failed");
327                        return rc;
328                    }
329                }
330            }
331        }
332    }
333
334    for (size_t i = 0; i < mStreams.size(); i++) {
335        if ((mStreams[i] != NULL) &&
336                (m_handle == mStreams[i]->getChannelHandle())) {
337            mStreams[i]->start();
338        }
339    }
340    rc = m_camOps->start_channel(m_camHandle, m_handle);
341
342    if (rc != NO_ERROR) {
343        for (size_t i = 0; i < mStreams.size(); i++) {
344            if ((mStreams[i] != NULL) &&
345                    (m_handle == mStreams[i]->getChannelHandle())) {
346                mStreams[i]->stop();
347            }
348        }
349    } else {
350        m_bIsActive = true;
351        for (size_t i = 0; i < mStreams.size(); i++) {
352            if (mStreams[i] != NULL) {
353                mStreams[i]->cond_signal();
354            }
355        }
356    }
357
358    return rc;
359}
360
361/*===========================================================================
362 * FUNCTION   : stop
363 *
364 * DESCRIPTION: stop a channel, which will stop all streams belong to this channel
365 *
366 * PARAMETERS : none
367 *
368 * RETURN     : int32_t type of status
369 *              NO_ERROR  -- success
370 *              none-zero failure code
371 *==========================================================================*/
372int32_t QCameraChannel::stop()
373{
374    int32_t rc = NO_ERROR;
375    size_t i = 0;
376
377    if (!m_bIsActive) {
378        return NO_INIT;
379    }
380
381    while(i < mStreams.size()) {
382        if (mStreams[i] != NULL) {
383            if (m_handle == mStreams[i]->getChannelHandle()) {
384                mStreams[i]->stop();
385                i++;
386            } else {
387                // Remove linked stream from stream list
388                mStreams.removeAt(i);
389            }
390        }
391    }
392
393    rc = m_camOps->stop_channel(m_camHandle, m_handle);
394
395    m_bIsActive = false;
396    return rc;
397}
398
399/*===========================================================================
400 * FUNCTION   : bufDone
401 *
402 * DESCRIPTION: return a stream buf back to kernel
403 *
404 * PARAMETERS :
405 *   @recvd_frame  : stream buf frame to be returned
406 *
407 * RETURN     : int32_t type of status
408 *              NO_ERROR  -- success
409 *              none-zero failure code
410 *==========================================================================*/
411int32_t QCameraChannel::bufDone(mm_camera_super_buf_t *recvd_frame)
412{
413    int32_t rc = NO_ERROR;
414    for (uint32_t i = 0; i < recvd_frame->num_bufs; i++) {
415        if (recvd_frame->bufs[i] != NULL) {
416            for (size_t j = 0; j < mStreams.size(); j++) {
417                if (mStreams[j] != NULL &&
418                        mStreams[j]->getMyHandle() == recvd_frame->bufs[i]->stream_id) {
419                    rc = mStreams[j]->bufDone(recvd_frame->bufs[i]->buf_idx);
420                    break; // break loop j
421                }
422            }
423        }
424    }
425
426    return rc;
427}
428
429/*===========================================================================
430 * FUNCTION   : bufDone
431 *
432 * DESCRIPTION: return specified buffer from super buffer to kernel
433 *
434 * PARAMETERS :
435 *   @recvd_frame  : stream buf frame to be returned
436 *   @stream_id      : stream ID of the buffer to be released
437 *
438 * RETURN     : int32_t type of status
439 *              NO_ERROR  -- success
440 *              none-zero failure code
441 *==========================================================================*/
442int32_t QCameraChannel::bufDone(mm_camera_super_buf_t *recvd_frame, uint32_t stream_id)
443{
444    int32_t rc = NO_ERROR;
445    int32_t index;
446    for (int32_t i = 0; i < (int32_t)recvd_frame->num_bufs; i++) {
447        index = -1;
448        if ((recvd_frame->bufs[i] != NULL) &&
449                (recvd_frame->bufs[i]->stream_id == stream_id)) {
450            for (size_t j = 0; j < mStreams.size(); j++) {
451                if ((mStreams[j] != NULL) &&
452                        (mStreams[j]->getMyHandle() == stream_id)) {
453                    rc = mStreams[j]->bufDone(recvd_frame->bufs[i]->buf_idx);
454                    index = i;
455                    break; // break loop j
456                }
457            }
458            if ((index >= 0) && (index < (int32_t)recvd_frame->num_bufs)) {
459                for (int32_t j = index; j < (int32_t)(recvd_frame->num_bufs - 1); j++) {
460                    recvd_frame->bufs[j] = recvd_frame->bufs[j + 1];
461                }
462                recvd_frame->num_bufs--;
463                i--;
464            }
465        }
466    }
467
468    return rc;
469}
470
471/*===========================================================================
472 * FUNCTION   : processZoomDone
473 *
474 * DESCRIPTION: process zoom done event
475 *
476 * PARAMETERS :
477 *   @previewWindoe : ptr to preview window ops table, needed to set preview
478 *                    crop information
479 *   @crop_info     : crop info as a result of zoom operation
480 *
481 * RETURN     : int32_t type of status
482 *              NO_ERROR  -- success
483 *              none-zero failure code
484 *==========================================================================*/
485int32_t QCameraChannel::processZoomDone(preview_stream_ops_t *previewWindow,
486                                        cam_crop_data_t &crop_info)
487{
488    int32_t rc = NO_ERROR;
489    for (size_t i = 0; i < mStreams.size(); i++) {
490        if ((mStreams[i] != NULL) &&
491                (m_handle == mStreams[i]->getChannelHandle())) {
492            rc = mStreams[i]->processZoomDone(previewWindow, crop_info);
493        }
494    }
495    return rc;
496}
497
498/*===========================================================================
499 * FUNCTION   : getStreamByHandle
500 *
501 * DESCRIPTION: return stream object by stream handle
502 *
503 * PARAMETERS :
504 *   @streamHandle : stream handle
505 *
506 * RETURN     : stream object. NULL if not found
507 *==========================================================================*/
508QCameraStream *QCameraChannel::getStreamByHandle(uint32_t streamHandle)
509{
510    for (size_t i = 0; i < mStreams.size(); i++) {
511        if (mStreams[i] != NULL && mStreams[i]->getMyHandle() == streamHandle) {
512            return mStreams[i];
513        }
514    }
515    return NULL;
516}
517
518/*===========================================================================
519 * FUNCTION   : getStreamByServerID
520 *
521 * DESCRIPTION: return stream object by stream server ID from daemon
522 *
523 * PARAMETERS :
524 *   @serverID : stream server ID
525 *
526 * RETURN     : stream object. NULL if not found
527 *==========================================================================*/
528QCameraStream *QCameraChannel::getStreamByServerID(uint32_t serverID)
529{
530    for (size_t i = 0; i < mStreams.size(); i++) {
531        if (mStreams[i] != NULL && mStreams[i]->getMyServerID() == serverID) {
532            return mStreams[i];
533        }
534    }
535    return NULL;
536}
537
538/*===========================================================================
539 * FUNCTION   : getStreamByIndex
540 *
541 * DESCRIPTION: return stream object by index of streams in the channel
542 *
543 * PARAMETERS :
544 *   @index : index of stream in the channel
545 *
546 * RETURN     : stream object. NULL if not found
547 *==========================================================================*/
548QCameraStream *QCameraChannel::getStreamByIndex(uint32_t index)
549{
550    if (index >= MAX_STREAM_NUM_IN_BUNDLE) {
551        return NULL;
552    }
553
554    if (index < mStreams.size()) {
555        return mStreams[index];
556    }
557    return NULL;
558}
559
560/*===========================================================================
561 * FUNCTION   : UpdateStreamBasedParameters
562 *
563 * DESCRIPTION: update any stream based settings from parameters
564 *
565 * PARAMETERS :
566 *   @param   : reference to parameters object
567 *
568 * RETURN     : int32_t type of status
569 *              NO_ERROR  -- success
570 *              none-zero failure code
571 *==========================================================================*/
572int32_t QCameraChannel::UpdateStreamBasedParameters(QCameraParametersIntf &param)
573{
574    int32_t rc = NO_ERROR;
575    if (param.isPreviewFlipChanged()) {
576        // try to find preview stream
577        for (size_t i = 0; i < mStreams.size(); i++) {
578            if ((mStreams[i] != NULL) &&
579                    (m_handle == mStreams[i]->getChannelHandle()) &&
580                    (mStreams[i]->isTypeOf(CAM_STREAM_TYPE_PREVIEW) ||
581                    (mStreams[i]->isOrignalTypeOf(CAM_STREAM_TYPE_PREVIEW))) ) {
582                cam_stream_parm_buffer_t param_buf;
583                memset(&param_buf, 0, sizeof(cam_stream_parm_buffer_t));
584                param_buf.type = CAM_STREAM_PARAM_TYPE_SET_FLIP;
585                param_buf.flipInfo.flip_mask =
586                        (uint32_t)param.getFlipMode(CAM_STREAM_TYPE_PREVIEW);
587                rc = mStreams[i]->setParameter(param_buf);
588                if (rc != NO_ERROR) {
589                    LOGW("set preview stream flip failed");
590                }
591            }
592        }
593    }
594    if (param.isVideoFlipChanged()) {
595        // try to find video stream
596        for (size_t i = 0; i < mStreams.size(); i++) {
597            if ((mStreams[i] != NULL) &&
598                    (m_handle == mStreams[i]->getChannelHandle()) &&
599                    (mStreams[i]->isTypeOf(CAM_STREAM_TYPE_VIDEO) ||
600                    (mStreams[i]->isOrignalTypeOf(CAM_STREAM_TYPE_VIDEO))) ) {
601                cam_stream_parm_buffer_t param_buf;
602                memset(&param_buf, 0, sizeof(cam_stream_parm_buffer_t));
603                param_buf.type = CAM_STREAM_PARAM_TYPE_SET_FLIP;
604                param_buf.flipInfo.flip_mask =
605                        (uint32_t)param.getFlipMode(CAM_STREAM_TYPE_VIDEO);
606                rc = mStreams[i]->setParameter(param_buf);
607                if (rc != NO_ERROR) {
608                    LOGW("set video stream flip failed");
609                }
610            }
611        }
612    }
613    if (param.isSnapshotFlipChanged()) {
614        // try to find snapshot/postview stream
615        for (size_t i = 0; i < mStreams.size(); i++) {
616            if (mStreams[i] != NULL &&
617                    (m_handle == mStreams[i]->getChannelHandle()) &&
618                    (mStreams[i]->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
619                     mStreams[i]->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
620                     mStreams[i]->isTypeOf(CAM_STREAM_TYPE_POSTVIEW) ||
621                 mStreams[i]->isOrignalTypeOf(CAM_STREAM_TYPE_POSTVIEW) ) ) {
622                cam_stream_parm_buffer_t param_buf;
623                memset(&param_buf, 0, sizeof(cam_stream_parm_buffer_t));
624                param_buf.type = CAM_STREAM_PARAM_TYPE_SET_FLIP;
625                param_buf.flipInfo.flip_mask =
626                        (uint32_t)param.getFlipMode(CAM_STREAM_TYPE_SNAPSHOT);
627                rc = mStreams[i]->setParameter(param_buf);
628                if (rc != NO_ERROR) {
629                    LOGW("set snapshot stream flip failed");
630                }
631            }
632        }
633    }
634    return rc;
635}
636
637/*===========================================================================
638 * FUNCTION   : QCameraPicChannel
639 *
640 * DESCRIPTION: constructor of QCameraPicChannel
641 *
642 * PARAMETERS :
643 *   @cam_handle : camera handle
644 *   @cam_ops    : ptr to camera ops table
645 *
646 * RETURN     : none
647 *==========================================================================*/
648QCameraPicChannel::QCameraPicChannel(uint32_t cam_handle,
649                                     mm_camera_ops_t *cam_ops) :
650    QCameraChannel(cam_handle, cam_ops)
651{
652    m_bAllowDynBufAlloc = true;
653}
654
655/*===========================================================================
656 * FUNCTION   : QCameraPicChannel
657 *
658 * DESCRIPTION: default constructor of QCameraPicChannel
659 *
660 * PARAMETERS : none
661 *
662 * RETURN     : none
663 *==========================================================================*/
664QCameraPicChannel::QCameraPicChannel()
665{
666    m_bAllowDynBufAlloc = true;
667}
668
669/*===========================================================================
670 * FUNCTION   : ~QCameraPicChannel
671 *
672 * DESCRIPTION: destructor of QCameraPicChannel
673 *
674 * PARAMETERS : none
675 *
676 * RETURN     : none
677 *==========================================================================*/
678QCameraPicChannel::~QCameraPicChannel()
679{
680}
681
682/*===========================================================================
683 * FUNCTION   : takePicture
684 *
685 * DESCRIPTION: send request for queued snapshot frames
686 *
687 * PARAMETERS :
688 *   @buf : request buf info
689 *
690 * RETURN     : int32_t type of status
691 *              NO_ERROR  -- success
692 *              none-zero failure code
693 *==========================================================================*/
694int32_t QCameraPicChannel::takePicture (mm_camera_req_buf_t *buf)
695{
696    int32_t rc = m_camOps->request_super_buf(m_camHandle, m_handle, buf);
697    return rc;
698}
699
700/*===========================================================================
701 * FUNCTION   : cancelPicture
702 *
703 * DESCRIPTION: cancel request for queued snapshot frames
704 *
705 * PARAMETERS : none
706 *
707 * RETURN     : int32_t type of status
708 *              NO_ERROR  -- success
709 *              none-zero failure code
710 *==========================================================================*/
711int32_t QCameraPicChannel::cancelPicture()
712{
713    int32_t rc = m_camOps->cancel_super_buf_request(m_camHandle, m_handle);
714    return rc;
715}
716
717/*===========================================================================
718 * FUNCTION   : stopAdvancedCapture
719 *
720 * DESCRIPTION: stop advanced capture based on advanced capture type.
721 *
722 * PARAMETERS :
723 *   @type : advanced capture type.
724 *
725 * RETURN     : int32_t type of status
726 *              NO_ERROR  -- success
727 *              none-zero failure code
728 *==========================================================================*/
729int32_t QCameraPicChannel::stopAdvancedCapture(mm_camera_advanced_capture_t type)
730{
731    int32_t rc = m_camOps->process_advanced_capture(m_camHandle,
732            m_handle, type, 0, NULL);
733    return rc;
734}
735
736/*===========================================================================
737 * FUNCTION   : startAdvancedCapture
738 *
739 * DESCRIPTION: start advanced capture based on advanced capture type.
740 *
741 * PARAMETERS :
742 *   @type : advanced capture type.
743 *   @config: advance capture config
744 *
745 * RETURN     : int32_t type of status
746 *              NO_ERROR  -- success
747 *              none-zero failure code
748 *==========================================================================*/
749int32_t QCameraPicChannel::startAdvancedCapture(mm_camera_advanced_capture_t type,
750        cam_capture_frame_config_t *config)
751{
752    int32_t rc = NO_ERROR;
753
754    rc = m_camOps->process_advanced_capture(m_camHandle, m_handle, type,
755            1, config);
756    return rc;
757}
758
759/*===========================================================================
760* FUNCTION   : flushSuperbuffer
761 *
762 * DESCRIPTION: flush the all superbuffer frames.
763 *
764 * PARAMETERS :
765 *   @frame_idx : frame index of focused frame
766 *
767 * RETURN     : int32_t type of status
768 *              NO_ERROR  -- success
769 *              none-zero failure code
770 *==========================================================================*/
771int32_t QCameraPicChannel::flushSuperbuffer(uint32_t frame_idx)
772{
773    int32_t rc = m_camOps->flush_super_buf_queue(m_camHandle, m_handle, frame_idx);
774    return rc;
775}
776
777/*===========================================================================
778 * FUNCTION   : QCameraVideoChannel
779 *
780 * DESCRIPTION: constructor of QCameraVideoChannel
781 *
782 * PARAMETERS :
783 *   @cam_handle : camera handle
784 *   @cam_ops    : ptr to camera ops table
785 *
786 * RETURN     : none
787 *==========================================================================*/
788QCameraVideoChannel::QCameraVideoChannel(uint32_t cam_handle,
789                                         mm_camera_ops_t *cam_ops) :
790    QCameraChannel(cam_handle, cam_ops)
791{
792}
793
794/*===========================================================================
795 * FUNCTION   : QCameraVideoChannel
796 *
797 * DESCRIPTION: default constructor of QCameraVideoChannel
798 *
799 * PARAMETERS : none
800 *
801 * RETURN     : none
802 *==========================================================================*/
803QCameraVideoChannel::QCameraVideoChannel()
804{
805}
806
807/*===========================================================================
808 * FUNCTION   : ~QCameraVideoChannel
809 *
810 * DESCRIPTION: destructor of QCameraVideoChannel
811 *
812 * PARAMETERS : none
813 *
814 * RETURN     : none
815 *==========================================================================*/
816QCameraVideoChannel::~QCameraVideoChannel()
817{
818}
819
820/*===========================================================================
821 * FUNCTION   : takePicture
822 *
823 * DESCRIPTION: send request for queued snapshot frames
824 *
825 * PARAMETERS :
826 *   @mm_camera_req_buf_t : request buf info
827 *
828 * RETURN     : int32_t type of status
829 *              NO_ERROR  -- success
830 *              none-zero failure code
831 *==========================================================================*/
832int32_t QCameraVideoChannel::takePicture(mm_camera_req_buf_t *buf)
833{
834    int32_t rc = m_camOps->request_super_buf(m_camHandle, m_handle, buf);
835    return rc;
836}
837
838/*===========================================================================
839 * FUNCTION   : cancelPicture
840 *
841 * DESCRIPTION: cancel request for queued snapshot frames
842 *
843 * PARAMETERS : none
844 *
845 * RETURN     : int32_t type of status
846 *              NO_ERROR  -- success
847 *              none-zero failure code
848 *==========================================================================*/
849int32_t QCameraVideoChannel::cancelPicture()
850{
851    int32_t rc = m_camOps->cancel_super_buf_request(m_camHandle, m_handle);
852    return rc;
853}
854
855/*===========================================================================
856 * FUNCTION   : releaseFrame
857 *
858 * DESCRIPTION: return video frame from app
859 *
860 * PARAMETERS :
861 *   @opaque     : ptr to video frame to be returned
862 *   @isMetaData : if frame is a metadata or real frame
863 *
864 * RETURN     : int32_t type of status
865 *              NO_ERROR  -- success
866 *              none-zero failure code
867 *==========================================================================*/
868int32_t QCameraVideoChannel::releaseFrame(const void * opaque, bool isMetaData)
869{
870    QCameraStream *pVideoStream = NULL;
871    for (size_t i = 0; i < mStreams.size(); i++) {
872        if (mStreams[i] != NULL && mStreams[i]->isTypeOf(CAM_STREAM_TYPE_VIDEO)) {
873            pVideoStream = mStreams[i];
874            break;
875        }
876    }
877
878    if (NULL == pVideoStream) {
879        LOGE("No video stream in the channel");
880        return BAD_VALUE;
881    }
882
883    int32_t rc = pVideoStream->bufDone(opaque, isMetaData);
884    return rc;
885}
886
887/*===========================================================================
888 * FUNCTION   : QCameraReprocessChannel
889 *
890 * DESCRIPTION: constructor of QCameraReprocessChannel
891 *
892 * PARAMETERS :
893 *   @cam_handle : camera handle
894 *   @cam_ops    : ptr to camera ops table
895 *   @pp_mask    : post-proccess feature mask
896 *
897 * RETURN     : none
898 *==========================================================================*/
899QCameraReprocessChannel::QCameraReprocessChannel(uint32_t cam_handle,
900                                                 mm_camera_ops_t *cam_ops) :
901    QCameraChannel(cam_handle, cam_ops),
902    m_pSrcChannel(NULL),
903    mPassCount(0)
904{
905    memset(mSrcStreamHandles, 0, sizeof(mSrcStreamHandles));
906}
907
908/*===========================================================================
909 * FUNCTION   : QCameraReprocessChannel
910 *
911 * DESCRIPTION: default constructor of QCameraReprocessChannel
912 *
913 * PARAMETERS : none
914 *
915 * RETURN     : none
916 *==========================================================================*/
917QCameraReprocessChannel::QCameraReprocessChannel() :
918    m_pSrcChannel(NULL),
919    mPassCount(0)
920{
921}
922
923/*===========================================================================
924 * FUNCTION   : ~QCameraReprocessChannel
925 *
926 * DESCRIPTION: destructor of QCameraReprocessChannel
927 *
928 * PARAMETERS : none
929 *
930 * RETURN     : none
931 *==========================================================================*/
932QCameraReprocessChannel::~QCameraReprocessChannel()
933{
934}
935
936/*===========================================================================
937 * FUNCTION   : addReprocStreamsFromSource
938 *
939 * DESCRIPTION: add reprocess streams from input source channel
940 *
941 * PARAMETERS :
942 *   @allocator      : stream related buffer allocator
943 *   @featureConfig  : pp feature configuration
944 *   @pSrcChannel    : ptr to input source channel that needs reprocess
945 *   @minStreamBufNum: number of stream buffers needed
946 *   @burstNum       : number of burst captures needed
947 *   @paddingInfo    : padding information
948 *   @param          : reference to parameters
949 *   @contStream     : continous streaming mode or burst
950 *   @offline        : configure for offline reprocessing
951 *
952 * RETURN     : int32_t type of status
953 *              NO_ERROR  -- success
954 *              none-zero failure code
955 *==========================================================================*/
956int32_t QCameraReprocessChannel::addReprocStreamsFromSource(
957        QCameraAllocator& allocator, cam_pp_feature_config_t &featureConfig,
958        QCameraChannel *pSrcChannel, uint8_t minStreamBufNum, uint8_t burstNum,
959        cam_padding_info_t *paddingInfo, QCameraParametersIntf &param, bool contStream,
960        bool offline)
961{
962    int32_t rc = 0;
963    QCameraStream *pStream = NULL;
964    QCameraHeapMemory *pStreamInfoBuf = NULL;
965    QCameraHeapMemory *pMiscBuf = NULL;
966    cam_stream_info_t *streamInfo = NULL;
967    cam_padding_info_t padding;
968
969    memset(mSrcStreamHandles, 0, sizeof(mSrcStreamHandles));
970    if (NULL == paddingInfo) {
971        return BAD_VALUE;
972    }
973    padding = *paddingInfo;
974    //Use maximum padding so that the buffer
975    //can be rotated
976    padding.width_padding = MAX(padding.width_padding, padding.height_padding);
977    padding.height_padding = padding.width_padding;
978    padding.offset_info.offset_x = 0;
979    padding.offset_info.offset_y = 0;
980
981    LOGD("num of src stream = %d", pSrcChannel->getNumOfStreams());
982
983    for (uint32_t i = 0; i < pSrcChannel->getNumOfStreams(); i++) {
984        cam_pp_feature_config_t pp_featuremask = featureConfig;
985        pStream = pSrcChannel->getStreamByIndex(i);
986        if (pStream != NULL) {
987            if (param.getofflineRAW() && !((pStream->isTypeOf(CAM_STREAM_TYPE_RAW))
988                    || (pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW))
989                    || (pStream->isTypeOf(CAM_STREAM_TYPE_METADATA))
990                    || (pStream->isOrignalTypeOf(CAM_STREAM_TYPE_RAW)))) {
991                //Skip all the stream other than RAW and POSTVIEW incase of offline of RAW
992                continue;
993            }
994
995            if (pStream->isTypeOf(CAM_STREAM_TYPE_RAW)
996                    && (!param.getofflineRAW())) {
997                // Skip raw for reprocess now because PP module cannot handle
998                // meta data&raw. May need furthur discussion if Imaginglib need meta data
999                continue;
1000            }
1001
1002            if (((pStream->isTypeOf(CAM_STREAM_TYPE_METADATA))
1003                    && !(param.getManualCaptureMode() >=
1004                    CAM_MANUAL_CAPTURE_TYPE_3))
1005                    || (pStream->isTypeOf(CAM_STREAM_TYPE_ANALYSIS))) {
1006                // Skip metadata
1007                continue;
1008            }
1009
1010            if (pStream->isTypeOf(CAM_STREAM_TYPE_PREVIEW) ||
1011                    pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW) ||
1012                    pStream->isOrignalTypeOf(CAM_STREAM_TYPE_PREVIEW) ||
1013                    pStream->isOrignalTypeOf(CAM_STREAM_TYPE_POSTVIEW)) {
1014                uint32_t feature_mask = featureConfig.feature_mask;
1015
1016                // skip thumbnail reprocessing if not needed
1017                if (!param.needThumbnailReprocess(&feature_mask)) {
1018                    continue;
1019                }
1020                // CAC, SHARPNESS, FLIP and WNR would have been already applied -
1021                // on preview/postview stream in realtime.
1022                // So, need not apply again.
1023                feature_mask &= ~(CAM_QCOM_FEATURE_DENOISE2D |
1024                        CAM_QCOM_FEATURE_CAC |
1025                        CAM_QCOM_FEATURE_SHARPNESS |
1026                        CAM_QCOM_FEATURE_FLIP |
1027                        CAM_QCOM_FEATURE_RAW_PROCESSING);
1028                if (!feature_mask) {
1029                    // Skip thumbnail stream reprocessing since no other
1030                    //reprocessing is enabled.
1031                    continue;
1032                }
1033            }
1034
1035            if (pStream->isTypeOf(CAM_STREAM_TYPE_METADATA)) {
1036                pp_featuremask.feature_mask = 0;
1037                pp_featuremask.feature_mask |= CAM_QCOM_FEATURE_METADATA_PROCESSING;
1038            }
1039
1040            pStreamInfoBuf = allocator.allocateStreamInfoBuf(CAM_STREAM_TYPE_OFFLINE_PROC);
1041            if (pStreamInfoBuf == NULL) {
1042                LOGE("no mem for stream info buf");
1043                rc = NO_MEMORY;
1044                break;
1045            }
1046
1047            streamInfo = (cam_stream_info_t *)pStreamInfoBuf->getPtr(0);
1048            memset(streamInfo, 0, sizeof(cam_stream_info_t));
1049            streamInfo->stream_type = CAM_STREAM_TYPE_OFFLINE_PROC;
1050            // Enable CPP high performance mode to put it in turbo frequency mode for
1051            // burst/longshot/HDR snapshot cases
1052            streamInfo->perf_mode = CAM_PERF_HIGH_PERFORMANCE;
1053            if (param.getofflineRAW() && pStream->isTypeOf(CAM_STREAM_TYPE_RAW)) {
1054                streamInfo->fmt = CAM_FORMAT_YUV_420_NV21;
1055            } else {
1056                rc = pStream->getFormat(streamInfo->fmt);
1057            }
1058
1059            if (pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW) ||
1060                    pStream->isTypeOf(CAM_STREAM_TYPE_PREVIEW)) {
1061                param.getThumbnailSize(&(streamInfo->dim.width), &(streamInfo->dim.height));
1062            } else {
1063                if ((param.isPostProcScaling()) &&
1064                        (pp_featuremask.feature_mask & CAM_QCOM_FEATURE_SCALE)) {
1065                    rc = param.getStreamDimension(CAM_STREAM_TYPE_OFFLINE_PROC,
1066                            streamInfo->dim);
1067                } else if ((param.getofflineRAW()) &&
1068                        (pStream->isTypeOf(CAM_STREAM_TYPE_RAW))) {
1069                    param.getStreamDimension(CAM_STREAM_TYPE_SNAPSHOT,streamInfo->dim);
1070                } else {
1071                    rc = pStream->getFrameDimension(streamInfo->dim);
1072                }
1073            }
1074
1075            if ( contStream ) {
1076                streamInfo->streaming_mode = CAM_STREAMING_MODE_CONTINUOUS;
1077                streamInfo->num_of_burst = 0;
1078            } else {
1079                streamInfo->streaming_mode = CAM_STREAMING_MODE_BURST;
1080                streamInfo->num_of_burst = burstNum;
1081            }
1082            streamInfo->num_bufs = minStreamBufNum;
1083
1084            cam_stream_reproc_config_t rp_cfg;
1085            memset(&rp_cfg, 0, sizeof(cam_stream_reproc_config_t));
1086            if (offline) {
1087                cam_frame_len_offset_t offset;
1088                memset(&offset, 0, sizeof(cam_frame_len_offset_t));
1089
1090                rp_cfg.pp_type = CAM_OFFLINE_REPROCESS_TYPE;
1091                pStream->getFormat(rp_cfg.offline.input_fmt);
1092                pStream->getFrameDimension(rp_cfg.offline.input_dim);
1093                pStream->getFrameOffset(offset);
1094                rp_cfg.offline.input_buf_planes.plane_info = offset;
1095                rp_cfg.offline.input_type = pStream->getMyOriginalType();
1096                //For input metadata + input buffer
1097                rp_cfg.offline.num_of_bufs = 2;
1098            } else {
1099                rp_cfg.pp_type = CAM_ONLINE_REPROCESS_TYPE;
1100                rp_cfg.online.input_stream_id = pStream->getMyServerID();
1101                rp_cfg.online.input_stream_type = pStream->getMyOriginalType();
1102            }
1103            param.getStreamRotation(streamInfo->stream_type,
1104                    streamInfo->pp_config, streamInfo->dim);
1105            streamInfo->reprocess_config = rp_cfg;
1106            streamInfo->reprocess_config.pp_feature_config = pp_featuremask;
1107
1108            if (!(pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT)
1109                || pStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT)
1110                || pStream->isTypeOf(CAM_STREAM_TYPE_RAW)
1111                || pStream->isOrignalTypeOf(CAM_STREAM_TYPE_RAW))) {
1112                // CAC, SHARPNESS, FLIP and WNR would have been already applied -
1113                // on preview/postview stream in realtime. Need not apply again.
1114                streamInfo->reprocess_config.pp_feature_config.feature_mask &=
1115                        ~CAM_QCOM_FEATURE_CAC;
1116                streamInfo->reprocess_config.pp_feature_config.feature_mask &=
1117                        ~CAM_QCOM_FEATURE_SHARPNESS;
1118                streamInfo->reprocess_config.pp_feature_config.feature_mask &=
1119                        ~CAM_QCOM_FEATURE_FLIP;
1120                //Don't do WNR for thumbnail
1121                streamInfo->reprocess_config.pp_feature_config.feature_mask &=
1122                        ~CAM_QCOM_FEATURE_DENOISE2D;
1123                streamInfo->reprocess_config.pp_feature_config.feature_mask &=
1124                        ~CAM_QCOM_FEATURE_CDS;
1125                streamInfo->reprocess_config.pp_feature_config.feature_mask &=
1126                        ~CAM_QCOM_FEATURE_DSDN;
1127                //No need of RAW processing for other than RAW streams
1128                streamInfo->reprocess_config.pp_feature_config.feature_mask &=
1129                        ~CAM_QCOM_FEATURE_RAW_PROCESSING;
1130
1131                if (param.isHDREnabled()
1132                  && !param.isHDRThumbnailProcessNeeded()){
1133                    streamInfo->reprocess_config.pp_feature_config.feature_mask
1134                      &= ~CAM_QCOM_FEATURE_HDR;
1135                }
1136            }
1137
1138            cam_stream_type_t type = CAM_STREAM_TYPE_DEFAULT;
1139            if (offline) {
1140                type = streamInfo->reprocess_config.offline.input_type;
1141            } else {
1142                type = streamInfo->reprocess_config.online.input_stream_type;
1143            }
1144            if (type == CAM_STREAM_TYPE_SNAPSHOT) {
1145                int flipMode = param.getFlipMode(type);
1146                if (flipMode > 0) {
1147                    streamInfo->reprocess_config.pp_feature_config.feature_mask |=
1148                            CAM_QCOM_FEATURE_FLIP;
1149                    streamInfo->reprocess_config.pp_feature_config.flip = (uint32_t)flipMode;
1150                }
1151            }
1152
1153            if ((streamInfo->reprocess_config.pp_feature_config.feature_mask
1154                    & CAM_QCOM_FEATURE_SCALE)
1155                    && param.isReprocScaleEnabled()
1156                    && param.isUnderReprocScaling()) {
1157                //we only Scale Snapshot frame
1158                if (pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT)) {
1159                    streamInfo->dim.width =
1160                            streamInfo->reprocess_config.pp_feature_config.scale_param.output_width;
1161                    streamInfo->dim.height =
1162                            streamInfo->reprocess_config.pp_feature_config.scale_param.output_height;
1163                }
1164                LOGH("stream width=%d, height=%d.",
1165                         streamInfo->dim.width, streamInfo->dim.height);
1166            }
1167
1168            // save source stream handler
1169            mSrcStreamHandles[mStreams.size()] = pStream->getMyHandle();
1170
1171            pMiscBuf = allocator.allocateMiscBuf(streamInfo);
1172
1173            LOGH("Configure Reprocessing: stream = %d, res = %dX%d, fmt = %d, type = %d",
1174                    pStream->getMyOriginalType(), streamInfo->dim.width,
1175                    streamInfo->dim.height, streamInfo->fmt, type);
1176
1177            // add reprocess stream
1178            if (streamInfo->reprocess_config.pp_feature_config.feature_mask
1179                    & CAM_QCOM_FEATURE_ROTATION) {
1180                rc = addStream(allocator, pStreamInfoBuf, pMiscBuf,
1181                        minStreamBufNum, &padding, NULL, NULL, false, false,
1182                        streamInfo->reprocess_config.pp_feature_config.rotation);
1183            } else {
1184                rc = addStream(allocator, pStreamInfoBuf, pMiscBuf,
1185                        minStreamBufNum, &padding, NULL, NULL, false, false);
1186            }
1187            if (rc != NO_ERROR) {
1188                LOGE("add reprocess stream failed, ret = %d", rc);
1189                break;
1190            }
1191        }
1192    }
1193
1194    if (rc == NO_ERROR) {
1195        m_pSrcChannel = pSrcChannel;
1196    }
1197    return rc;
1198}
1199
1200/*===========================================================================
1201 * FUNCTION   : getStreamBySrouceHandle
1202 *
1203 * DESCRIPTION: find reprocess stream by its source stream handle
1204 *
1205 * PARAMETERS :
1206 *   @srcHandle : source stream handle
1207 *
1208 * RETURN     : ptr to reprocess stream if found. NULL if not found
1209 *==========================================================================*/
1210QCameraStream * QCameraReprocessChannel::getStreamBySrouceHandle(uint32_t srcHandle)
1211{
1212    QCameraStream *pStream = NULL;
1213
1214    for (size_t i = 0; i < mStreams.size(); i++) {
1215        if (mSrcStreamHandles[i] == srcHandle) {
1216            pStream = mStreams[i];
1217            break;
1218        }
1219    }
1220
1221    return pStream;
1222}
1223
1224/*===========================================================================
1225 * FUNCTION   : stop
1226 *
1227 * DESCRIPTION: stop channel and unmap offline buffers
1228 *
1229 * PARAMETERS : none
1230 *
1231 * RETURN     : int32_t type of status
1232 *              NO_ERROR  -- success
1233 *              none-zero failure code
1234 *==========================================================================*/
1235int32_t QCameraReprocessChannel::stop()
1236{
1237    int32_t rc = QCameraChannel::stop();
1238
1239    if (!mOfflineBuffers.empty()) {
1240        QCameraStream *stream = NULL;
1241        List<OfflineBuffer>::iterator it = mOfflineBuffers.begin();
1242        int error = NO_ERROR;
1243        for( ; it != mOfflineBuffers.end(); it++) {
1244            stream = (*it).stream;
1245            if (NULL != stream) {
1246                error = stream->unmapBuf((*it).type,
1247                                         (*it).index,
1248                                         -1);
1249                if (NO_ERROR != error) {
1250                    LOGE("Error during offline buffer unmap %d",
1251                           error);
1252                }
1253            }
1254        }
1255        mOfflineBuffers.clear();
1256    }
1257    return rc;
1258}
1259
1260/*===========================================================================
1261 * FUNCTION   : doReprocessOffline
1262 *
1263 * DESCRIPTION: request to do offline reprocess on the frame
1264 *
1265 * PARAMETERS :
1266 *   @frame   : frame to be performed a reprocess
1267 *   @meta_buf : Metadata buffer for reprocessing
1268 *   @pStream  : Actual reprocess stream
1269 *
1270 * RETURN     : int32_t type of status
1271 *              NO_ERROR  -- success
1272 *              none-zero failure code
1273 *==========================================================================*/
1274int32_t QCameraReprocessChannel::doReprocessOffline(mm_camera_buf_def_t *frame,
1275        mm_camera_buf_def_t *meta_buf, QCameraStream *pStream)
1276{
1277    int32_t rc = 0;
1278    OfflineBuffer mappedBuffer;
1279    uint32_t buf_index = 0;
1280    uint32_t meta_buf_index = 0;
1281
1282    if ((frame == NULL) || (meta_buf == NULL)) {
1283        LOGE("Invalid Input Paramters");
1284        return INVALID_OPERATION;
1285    }
1286
1287    if (pStream == NULL) {
1288        pStream = getStreamBySrouceHandle(frame->stream_id);
1289        if (pStream == NULL) {
1290            LOGE("Input validation failed.");
1291            return INVALID_OPERATION;
1292        }
1293    }
1294
1295    if (!mOfflineBuffers.empty()) {
1296        List<OfflineBuffer>::iterator it = mOfflineBuffers.begin();
1297        for( ; it != mOfflineBuffers.end(); it++) {
1298            buf_index = (buf_index < ((*it).index)) ? ((*it).index) : buf_index;
1299        }
1300        buf_index += 1;
1301    }
1302
1303    meta_buf_index = buf_index;
1304    if (meta_buf != NULL) {
1305        rc = pStream->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF,
1306                meta_buf_index,
1307                -1,
1308                meta_buf->fd,
1309                meta_buf->frame_len);
1310        if (NO_ERROR != rc ) {
1311            LOGE("Error during metadata buffer mapping");
1312            rc = -1;
1313            return rc;
1314        }
1315
1316        mappedBuffer.index = meta_buf_index;
1317        mappedBuffer.stream = pStream;
1318        mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF;
1319        mOfflineBuffers.push_back(mappedBuffer);
1320        buf_index += 1;
1321    }
1322
1323    rc = pStream->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
1324             buf_index,
1325             -1,
1326             frame->fd,
1327             frame->frame_len);
1328    if (NO_ERROR != rc ) {
1329        LOGE("Error during reprocess input buffer mapping");
1330        rc = -1;
1331        return rc;
1332    }
1333    mappedBuffer.index = buf_index;
1334    mappedBuffer.stream = pStream;
1335    mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF;
1336    mOfflineBuffers.push_back(mappedBuffer);
1337
1338    cam_stream_parm_buffer_t param;
1339    memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
1340
1341    param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
1342    param.reprocess.buf_index = buf_index;
1343    param.reprocess.frame_idx = frame->frame_idx;
1344
1345    if (meta_buf != NULL) {
1346        param.reprocess.meta_present = 1;
1347        param.reprocess.meta_buf_index = meta_buf_index;
1348    }
1349
1350    LOGI("Offline reprocessing id = %d buf Id = %d meta index = %d type = %d",
1351             param.reprocess.frame_idx, param.reprocess.buf_index,
1352            param.reprocess.meta_buf_index, pStream->getMyOriginalType());
1353
1354    rc = pStream->setParameter(param);
1355    if (rc != NO_ERROR) {
1356        LOGE("stream setParameter for reprocess failed");
1357        return rc;
1358    }
1359    return rc;
1360}
1361
1362/*===========================================================================
1363 * FUNCTION   : doReprocessOffline
1364 *
1365 * DESCRIPTION: request to do offline reprocess on the frame
1366 *
1367 * PARAMETERS :
1368 *   @frame   : frame to be performed a reprocess
1369 *   @meta_buf : Metadata buffer for reprocessing
1370 *   @mParameter : camera parameters
1371 *
1372 * RETURN     : int32_t type of status
1373 *              NO_ERROR  -- success
1374 *              none-zero failure code
1375 *==========================================================================*/
1376int32_t QCameraReprocessChannel::doReprocessOffline(mm_camera_super_buf_t *frame,
1377        mm_camera_buf_def_t *meta_buf, QCameraParametersIntf &mParameter)
1378{
1379    int32_t rc = 0;
1380    QCameraStream *pStream = NULL;
1381
1382    if (mStreams.size() < 1) {
1383        LOGE("No reprocess streams");
1384        return -1;
1385    }
1386    if (m_pSrcChannel == NULL) {
1387        LOGE("No source channel for reprocess");
1388        return -1;
1389    }
1390
1391    if (frame == NULL) {
1392        LOGE("Invalid source frame");
1393        return BAD_VALUE;
1394    }
1395
1396    for (uint32_t i = 0; i < frame->num_bufs; i++) {
1397        pStream = getStreamBySrouceHandle(frame->bufs[i]->stream_id);
1398        if ((pStream != NULL) &&
1399                (m_handle == pStream->getChannelHandle())) {
1400            if (mParameter.getofflineRAW() &&
1401                    !((pStream->isOrignalTypeOf(CAM_STREAM_TYPE_RAW))
1402                    || (pStream->isOrignalTypeOf(CAM_STREAM_TYPE_METADATA)))) {
1403                continue;
1404            }
1405
1406            if ((pStream->isOrignalTypeOf(CAM_STREAM_TYPE_METADATA)
1407                     && (mParameter.getManualCaptureMode()
1408                     < CAM_MANUAL_CAPTURE_TYPE_3))
1409                     || (pStream->isTypeOf(CAM_STREAM_TYPE_ANALYSIS))) {
1410                // Skip metadata for reprocess now because PP module cannot handle meta data
1411                // May need furthur discussion if Imaginglib need meta data
1412                continue;
1413            }
1414
1415            // Update Metadata
1416            if (meta_buf != NULL) {
1417                uint32_t stream_id = frame->bufs[i]->stream_id;
1418                QCameraStream *srcStream =
1419                        m_pSrcChannel->getStreamByHandle(stream_id);
1420                metadata_buffer_t *pMetaData =
1421                        (metadata_buffer_t *)meta_buf->buffer;
1422                if ((NULL != pMetaData) && (NULL != srcStream)) {
1423                    IF_META_AVAILABLE(cam_crop_data_t, crop,
1424                            CAM_INTF_META_CROP_DATA, pMetaData) {
1425                        if (MAX_NUM_STREAMS > crop->num_of_streams) {
1426                            for (int j = 0; j < MAX_NUM_STREAMS; j++) {
1427                                if (crop->crop_info[j].stream_id ==
1428                                            srcStream->getMyServerID()) {
1429                                    // Store crop/roi information for offline reprocess
1430                                    // in the reprocess stream slot
1431                                    crop->crop_info[crop->num_of_streams].crop =
1432                                            crop->crop_info[j].crop;
1433                                    crop->crop_info[crop->num_of_streams].roi_map =
1434                                            crop->crop_info[j].roi_map;
1435                                    for (uint8_t k = 0; k < mStreams.size(); k++) {
1436                                        if (srcStream->getMyType() ==
1437                                                mStreams[k]->getMyOriginalType()) {
1438                                            crop->crop_info[crop->num_of_streams].stream_id =
1439                                                    mStreams[k]->getMyServerID();
1440                                            break;
1441                                        }
1442                                    }
1443                                    crop->num_of_streams++;
1444                                    break;
1445                                }
1446                            }
1447                        } else {
1448                            LOGE("No space to add reprocess stream crop/roi information");
1449                        }
1450                    }
1451                }
1452            }
1453
1454            rc = doReprocessOffline (frame->bufs[i], meta_buf, pStream);
1455        }
1456    }
1457    return rc;
1458}
1459
1460/*===========================================================================
1461 * FUNCTION   : doReprocess
1462 *
1463 * DESCRIPTION: request to do a reprocess on the frame
1464 *
1465 * PARAMETERS :
1466 *   @frame   : frame to be performed a reprocess
1467 *   @mParameter : camera parameters
1468 *   @pMetaStream: Metadata stream handle
1469 *   @meta_buf_index : Metadata buffer index
1470 *
1471 * RETURN     : int32_t type of status
1472 *              NO_ERROR  -- success
1473 *              none-zero failure code
1474 *==========================================================================*/
1475int32_t QCameraReprocessChannel::doReprocess(mm_camera_super_buf_t *frame,
1476        QCameraParametersIntf &mParameter, QCameraStream *pMetaStream,
1477        uint8_t meta_buf_index)
1478{
1479    int32_t rc = 0;
1480    if (mStreams.size() < 1) {
1481        LOGE("No reprocess streams");
1482        return -1;
1483    }
1484    if (m_pSrcChannel == NULL) {
1485        LOGE("No source channel for reprocess");
1486        return -1;
1487    }
1488
1489    if (pMetaStream == NULL) {
1490        LOGW("Null Metadata buffer for processing");
1491    }
1492
1493    for (uint32_t i = 0; i < frame->num_bufs; i++) {
1494        QCameraStream *pStream = getStreamBySrouceHandle(frame->bufs[i]->stream_id);
1495        if ((pStream != NULL) && (m_handle == pStream->getChannelHandle())) {
1496            if (mParameter.getofflineRAW() && !((pStream->isOrignalTypeOf(CAM_STREAM_TYPE_RAW))
1497                    || (pStream->isOrignalTypeOf(CAM_STREAM_TYPE_POSTVIEW))
1498                    || (pStream->isOrignalTypeOf(CAM_STREAM_TYPE_METADATA)))) {
1499                //Skip all the stream other than RAW and POSTVIEW incase of offline of RAW
1500                continue;
1501            }
1502            if ((pStream->isOrignalTypeOf(CAM_STREAM_TYPE_METADATA)
1503                     && (mParameter.getManualCaptureMode()
1504                     < CAM_MANUAL_CAPTURE_TYPE_3))
1505                     || (pStream->isTypeOf(CAM_STREAM_TYPE_ANALYSIS))) {
1506                // Skip metadata for reprocess now because PP module cannot handle meta data
1507                // May need furthur discussion if Imaginglib need meta data
1508                continue;
1509            }
1510
1511            cam_stream_parm_buffer_t param;
1512            memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
1513            param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
1514            param.reprocess.buf_index = frame->bufs[i]->buf_idx;
1515            param.reprocess.frame_idx = frame->bufs[i]->frame_idx;
1516            if (pMetaStream != NULL) {
1517                // we have meta data frame bundled, sent together with reprocess frame
1518                param.reprocess.meta_present = 1;
1519                param.reprocess.meta_stream_handle = pMetaStream->getMyServerID();
1520                param.reprocess.meta_buf_index = meta_buf_index;
1521            }
1522
1523            LOGI("Online reprocessing id = %d buf Id = %d meta index = %d type = %d",
1524                     param.reprocess.frame_idx, param.reprocess.buf_index,
1525                    param.reprocess.meta_buf_index, pStream->getMyOriginalType());
1526
1527            rc = pStream->setParameter(param);
1528            if (rc != NO_ERROR) {
1529                LOGE("stream setParameter for reprocess failed");
1530                break;
1531            }
1532        }
1533    }
1534    return rc;
1535}
1536
1537/*===========================================================================
1538 * FUNCTION   : doReprocess
1539 *
1540 * DESCRIPTION: request to do a reprocess on the frame
1541 *
1542 * PARAMETERS :
1543 *   @buf_fd     : fd to the input buffer that needs reprocess
1544 *   @buf_lenght : length of the input buffer
1545 *   @ret_val    : result of reprocess.
1546 *                 Example: Could be faceID in case of register face image.
1547 *
1548 * RETURN     : int32_t type of status
1549 *              NO_ERROR  -- success
1550 *              none-zero failure code
1551 *==========================================================================*/
1552int32_t QCameraReprocessChannel::doReprocess(int buf_fd,
1553        size_t buf_length, int32_t &ret_val)
1554{
1555    int32_t rc = 0;
1556    if (mStreams.size() < 1) {
1557        LOGE("No reprocess streams");
1558        return -1;
1559    }
1560
1561    uint32_t buf_idx = 0;
1562    for (size_t i = 0; i < mStreams.size(); i++) {
1563        if ((mStreams[i] != NULL) &&
1564                (m_handle != mStreams[i]->getChannelHandle())) {
1565            continue;
1566        }
1567        rc = mStreams[i]->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
1568                                 buf_idx, -1,
1569                                 buf_fd, buf_length);
1570
1571        if (rc == NO_ERROR) {
1572            cam_stream_parm_buffer_t param;
1573            memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
1574            param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
1575            param.reprocess.buf_index = buf_idx;
1576            rc = mStreams[i]->setParameter(param);
1577            if (rc == NO_ERROR) {
1578                ret_val = param.reprocess.ret_val;
1579            }
1580            mStreams[i]->unmapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
1581                                  buf_idx, -1);
1582        }
1583    }
1584    return rc;
1585}
1586
1587}; // namespace qcamera
1588