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