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