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 
     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  *==========================================================================*/
     77 QCameraChannel::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  *==========================================================================*/
     95 QCameraChannel::~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  *==========================================================================*/
    121 void 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  *==========================================================================*/
    147 int32_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  *==========================================================================*/
    174 int32_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  *==========================================================================*/
    209 int32_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  *==========================================================================*/
    262 int32_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  *==========================================================================*/
    295 int32_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  *==========================================================================*/
    372 int32_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  *==========================================================================*/
    411 int32_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  *==========================================================================*/
    442 int32_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  *==========================================================================*/
    485 int32_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  *==========================================================================*/
    508 QCameraStream *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  *==========================================================================*/
    528 QCameraStream *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  *==========================================================================*/
    548 QCameraStream *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  *==========================================================================*/
    572 int32_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  *==========================================================================*/
    648 QCameraPicChannel::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  *==========================================================================*/
    664 QCameraPicChannel::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  *==========================================================================*/
    678 QCameraPicChannel::~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  *==========================================================================*/
    694 int32_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  *==========================================================================*/
    711 int32_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  *==========================================================================*/
    729 int32_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  *==========================================================================*/
    749 int32_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  *==========================================================================*/
    771 int32_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  *==========================================================================*/
    788 QCameraVideoChannel::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  *==========================================================================*/
    803 QCameraVideoChannel::QCameraVideoChannel()
    804 {
    805 }
    806 
    807 /*===========================================================================
    808  * FUNCTION   : ~QCameraVideoChannel
    809  *
    810  * DESCRIPTION: destructor of QCameraVideoChannel
    811  *
    812  * PARAMETERS : none
    813  *
    814  * RETURN     : none
    815  *==========================================================================*/
    816 QCameraVideoChannel::~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  *==========================================================================*/
    832 int32_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  *==========================================================================*/
    849 int32_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  *==========================================================================*/
    868 int32_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  *==========================================================================*/
    899 QCameraReprocessChannel::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  *==========================================================================*/
    917 QCameraReprocessChannel::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  *==========================================================================*/
    932 QCameraReprocessChannel::~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  *==========================================================================*/
    956 int32_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  *==========================================================================*/
   1210 QCameraStream * 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  *==========================================================================*/
   1235 int32_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  *==========================================================================*/
   1274 int32_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  *==========================================================================*/
   1376 int32_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  *==========================================================================*/
   1475 int32_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  *==========================================================================*/
   1552 int32_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