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