QCamera3Channel.cpp revision 7f4ce92de7851ebde8b89bca7b7565ce8ca2467b
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
31#define LOG_TAG "QCamera3Channel"
32
33// To remove
34#include <cutils/properties.h>
35
36// System dependencies
37#include <fcntl.h>
38#include <stdio.h>
39#include <stdlib.h>
40#include "gralloc.h"
41
42// Camera dependencies
43#include "QCamera3Channel.h"
44#include "QCamera3HWI.h"
45#include "QCameraTrace.h"
46
47extern "C" {
48#include "mm_camera_dbg.h"
49}
50
51using namespace android;
52
53namespace qcamera {
54#define IS_BUFFER_ERROR(x) (((x) & V4L2_BUF_FLAG_ERROR) == V4L2_BUF_FLAG_ERROR)
55
56/*===========================================================================
57 * FUNCTION   : QCamera3Channel
58 *
59 * DESCRIPTION: constrcutor of QCamera3Channel
60 *
61 * PARAMETERS :
62 *   @cam_handle : camera handle
63 *   @cam_ops    : ptr to camera ops table
64 *
65 * RETURN     : none
66 *==========================================================================*/
67QCamera3Channel::QCamera3Channel(uint32_t cam_handle,
68                               uint32_t channel_handle,
69                               mm_camera_ops_t *cam_ops,
70                               channel_cb_routine cb_routine,
71                               channel_cb_buffer_err cb_buffer_err,
72                               cam_padding_info_t *paddingInfo,
73                               cam_feature_mask_t postprocess_mask,
74                               void *userData, uint32_t numBuffers)
75{
76    m_camHandle = cam_handle;
77    m_handle = channel_handle;
78    m_camOps = cam_ops;
79    m_bIsActive = false;
80
81    m_numStreams = 0;
82    memset(mStreams, 0, sizeof(mStreams));
83    mUserData = userData;
84
85    mStreamInfoBuf = NULL;
86    mChannelCB = cb_routine;
87    mChannelCbBufErr = cb_buffer_err;
88    mPaddingInfo = *paddingInfo;
89    mPaddingInfo.offset_info.offset_x = 0;
90    mPaddingInfo.offset_info.offset_y = 0;
91
92    mPostProcMask = postprocess_mask;
93
94    mIsType = IS_TYPE_NONE;
95    mNumBuffers = numBuffers;
96    mPerFrameMapUnmapEnable = true;
97    mDumpFrmCnt = 0;
98}
99
100/*===========================================================================
101 * FUNCTION   : ~QCamera3Channel
102 *
103 * DESCRIPTION: destructor of QCamera3Channel
104 *
105 * PARAMETERS : none
106 *
107 * RETURN     : none
108 *==========================================================================*/
109QCamera3Channel::~QCamera3Channel()
110{
111}
112
113/*===========================================================================
114 * FUNCTION   : destroy
115 *
116 * DESCRIPTION: internal destructor of QCamera3Channel called by the subclasses
117 *              this destructor will call pure virtual functions.  stop will eventuall call
118 *              QCamera3Stream::putBufs.  The putBufs function will
119 *              call QCamera3Channel::putStreamBufs which is pure virtual
120 *
121 * PARAMETERS : none
122 *
123 * RETURN     : none
124 *==========================================================================*/
125void QCamera3Channel::destroy()
126{
127    if (m_bIsActive)
128        stop();
129
130    for (uint32_t i = 0; i < m_numStreams; i++) {
131        if (mStreams[i] != NULL) {
132            delete mStreams[i];
133            mStreams[i] = 0;
134        }
135    }
136    m_numStreams = 0;
137}
138
139/*===========================================================================
140 * FUNCTION   : addStream
141 *
142 * DESCRIPTION: add a stream into channel
143 *
144 * PARAMETERS :
145 *   @streamType     : stream type
146 *   @streamFormat   : stream format
147 *   @streamDim      : stream dimension
148 *   @streamRotation : rotation of the stream
149 *   @minStreamBufNum : minimal buffer count for particular stream type
150 *   @postprocessMask : post-proccess feature mask
151 *   @isType         : type of image stabilization required on the stream
152 *
153 * RETURN     : int32_t type of status
154 *              NO_ERROR  -- success
155 *              none-zero failure code
156 *==========================================================================*/
157int32_t QCamera3Channel::addStream(cam_stream_type_t streamType,
158                                  cam_format_t streamFormat,
159                                  cam_dimension_t streamDim,
160                                  cam_rotation_t streamRotation,
161                                  uint8_t minStreamBufNum,
162                                  cam_feature_mask_t postprocessMask,
163                                  cam_is_type_t isType,
164                                  uint32_t batchSize)
165{
166    int32_t rc = NO_ERROR;
167
168    if (m_numStreams >= 1) {
169        LOGE("Only one stream per channel supported in v3 Hal");
170        return BAD_VALUE;
171    }
172
173    if (m_numStreams >= MAX_STREAM_NUM_IN_BUNDLE) {
174        LOGE("stream number (%d) exceeds max limit (%d)",
175               m_numStreams, MAX_STREAM_NUM_IN_BUNDLE);
176        return BAD_VALUE;
177    }
178    QCamera3Stream *pStream = new QCamera3Stream(m_camHandle,
179                                               m_handle,
180                                               m_camOps,
181                                               &mPaddingInfo,
182                                               this);
183    if (pStream == NULL) {
184        LOGE("No mem for Stream");
185        return NO_MEMORY;
186    }
187    LOGD("batch size is %d", batchSize);
188
189    rc = pStream->init(streamType, streamFormat, streamDim, streamRotation,
190            NULL, minStreamBufNum, postprocessMask, isType, batchSize,
191            streamCbRoutine, this);
192    if (rc == 0) {
193        mStreams[m_numStreams] = pStream;
194        m_numStreams++;
195    } else {
196        delete pStream;
197    }
198    return rc;
199}
200
201/*===========================================================================
202 * FUNCTION   : start
203 *
204 * DESCRIPTION: start channel, which will start all streams belong to this channel
205 *
206 * PARAMETERS :
207 *
208 * RETURN     : int32_t type of status
209 *              NO_ERROR  -- success
210 *              none-zero failure code
211 *==========================================================================*/
212int32_t QCamera3Channel::start()
213{
214    ATRACE_CALL();
215    int32_t rc = NO_ERROR;
216
217    if (m_numStreams > 1) {
218        LOGW("bundle not supported");
219    } else if (m_numStreams == 0) {
220        return NO_INIT;
221    }
222
223    if(m_bIsActive) {
224        LOGW("Attempt to start active channel");
225        return rc;
226    }
227
228    for (uint32_t i = 0; i < m_numStreams; i++) {
229        if (mStreams[i] != NULL) {
230            mStreams[i]->start();
231        }
232    }
233
234    m_bIsActive = true;
235
236    return rc;
237}
238
239/*===========================================================================
240 * FUNCTION   : stop
241 *
242 * DESCRIPTION: stop a channel, which will stop all streams belong to this channel
243 *
244 * PARAMETERS : none
245 *
246 * RETURN     : int32_t type of status
247 *              NO_ERROR  -- success
248 *              none-zero failure code
249 *==========================================================================*/
250int32_t QCamera3Channel::stop()
251{
252    ATRACE_CALL();
253    int32_t rc = NO_ERROR;
254    if(!m_bIsActive) {
255        LOGE("Attempt to stop inactive channel");
256        return rc;
257    }
258
259    for (uint32_t i = 0; i < m_numStreams; i++) {
260        if (mStreams[i] != NULL) {
261            mStreams[i]->stop();
262        }
263    }
264
265    m_bIsActive = false;
266    return rc;
267}
268
269/*===========================================================================
270 * FUNCTION   : setBatchSize
271 *
272 * DESCRIPTION: Set batch size for the channel. This is a dummy implementation
273 *              for the base class
274 *
275 * PARAMETERS :
276 *   @batchSize  : Number of image buffers in a batch
277 *
278 * RETURN     : int32_t type of status
279 *              NO_ERROR  -- success always
280 *              none-zero failure code
281 *==========================================================================*/
282int32_t QCamera3Channel::setBatchSize(uint32_t batchSize)
283{
284    LOGD("Dummy method. batchSize: %d unused ", batchSize);
285    return NO_ERROR;
286}
287
288/*===========================================================================
289 * FUNCTION   : queueBatchBuf
290 *
291 * DESCRIPTION: This is a dummy implementation for the base class
292 *
293 * PARAMETERS :
294 *
295 * RETURN     : int32_t type of status
296 *              NO_ERROR  -- success always
297 *              none-zero failure code
298 *==========================================================================*/
299int32_t QCamera3Channel::queueBatchBuf()
300{
301    LOGD("Dummy method. Unused ");
302    return NO_ERROR;
303}
304
305/*===========================================================================
306 * FUNCTION   : setPerFrameMapUnmap
307 *
308 * DESCRIPTION: Sets internal enable flag
309 *
310 * PARAMETERS :
311 *  @enable : Bool value for the enable flag
312 *
313 * RETURN     : int32_t type of status
314 *              NO_ERROR  -- success always
315 *              none-zero failure code
316 *==========================================================================*/
317int32_t QCamera3Channel::setPerFrameMapUnmap(bool enable)
318{
319    mPerFrameMapUnmapEnable = enable;
320    return NO_ERROR;
321}
322
323/*===========================================================================
324 * FUNCTION   : flush
325 *
326 * DESCRIPTION: flush a channel
327 *
328 * PARAMETERS : none
329 *
330 * RETURN     : int32_t type of status
331 *              NO_ERROR  -- success
332 *              none-zero failure code
333 *==========================================================================*/
334int32_t QCamera3Channel::flush()
335{
336    ATRACE_CALL();
337    return NO_ERROR;
338}
339
340/*===========================================================================
341 * FUNCTION   : bufDone
342 *
343 * DESCRIPTION: return a stream buf back to kernel
344 *
345 * PARAMETERS :
346 *   @recvd_frame  : stream buf frame to be returned
347 *
348 * RETURN     : int32_t type of status
349 *              NO_ERROR  -- success
350 *              none-zero failure code
351 *==========================================================================*/
352int32_t QCamera3Channel::bufDone(mm_camera_super_buf_t *recvd_frame)
353{
354    int32_t rc = NO_ERROR;
355    for (uint32_t i = 0; i < recvd_frame->num_bufs; i++) {
356         if (recvd_frame->bufs[i] != NULL) {
357             for (uint32_t j = 0; j < m_numStreams; j++) {
358                 if (mStreams[j] != NULL &&
359                     mStreams[j]->getMyHandle() == recvd_frame->bufs[i]->stream_id) {
360                     rc = mStreams[j]->bufDone(recvd_frame->bufs[i]->buf_idx);
361                     break; // break loop j
362                 }
363             }
364         }
365    }
366
367    return rc;
368}
369
370int32_t QCamera3Channel::setBundleInfo(const cam_bundle_config_t &bundleInfo)
371{
372    int32_t rc = NO_ERROR;
373    cam_stream_parm_buffer_t param;
374    memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
375    param.type = CAM_STREAM_PARAM_TYPE_SET_BUNDLE_INFO;
376    param.bundleInfo = bundleInfo;
377    rc = mStreams[0]->setParameter(param);
378    if (rc != NO_ERROR) {
379        LOGE("stream setParameter for set bundle failed");
380    }
381
382    return rc;
383}
384
385/*===========================================================================
386 * FUNCTION   : getStreamTypeMask
387 *
388 * DESCRIPTION: Get bit mask of all stream types in this channel
389 *
390 * PARAMETERS : None
391 *
392 * RETURN     : Bit mask of all stream types in this channel
393 *==========================================================================*/
394uint32_t QCamera3Channel::getStreamTypeMask()
395{
396    uint32_t mask = 0;
397    for (uint32_t i = 0; i < m_numStreams; i++) {
398       mask |= (1U << mStreams[i]->getMyType());
399    }
400    return mask;
401}
402
403/*===========================================================================
404 * FUNCTION   : getStreamID
405 *
406 * DESCRIPTION: Get StreamID of requested stream type
407 *
408 * PARAMETERS : streamMask
409 *
410 * RETURN     : Stream ID
411 *==========================================================================*/
412uint32_t QCamera3Channel::getStreamID(uint32_t streamMask)
413{
414    uint32_t streamID = 0;
415    for (uint32_t i = 0; i < m_numStreams; i++) {
416        if (streamMask == (uint32_t )(0x1 << mStreams[i]->getMyType())) {
417            streamID = mStreams[i]->getMyServerID();
418            break;
419        }
420    }
421    return streamID;
422}
423
424/*===========================================================================
425 * FUNCTION   : getStreamByHandle
426 *
427 * DESCRIPTION: return stream object by stream handle
428 *
429 * PARAMETERS :
430 *   @streamHandle : stream handle
431 *
432 * RETURN     : stream object. NULL if not found
433 *==========================================================================*/
434QCamera3Stream *QCamera3Channel::getStreamByHandle(uint32_t streamHandle)
435{
436    for (uint32_t i = 0; i < m_numStreams; i++) {
437        if (mStreams[i] != NULL && mStreams[i]->getMyHandle() == streamHandle) {
438            return mStreams[i];
439        }
440    }
441    return NULL;
442}
443
444/*===========================================================================
445 * FUNCTION   : getStreamByIndex
446 *
447 * DESCRIPTION: return stream object by index
448 *
449 * PARAMETERS :
450 *   @streamHandle : stream handle
451 *
452 * RETURN     : stream object. NULL if not found
453 *==========================================================================*/
454QCamera3Stream *QCamera3Channel::getStreamByIndex(uint32_t index)
455{
456    if (index < m_numStreams) {
457        return mStreams[index];
458    }
459    return NULL;
460}
461
462/*===========================================================================
463 * FUNCTION   : streamCbRoutine
464 *
465 * DESCRIPTION: callback routine for stream
466 *
467 * PARAMETERS :
468 *   @streamHandle : stream handle
469 *
470 * RETURN     : stream object. NULL if not found
471 *==========================================================================*/
472void QCamera3Channel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
473                QCamera3Stream *stream, void *userdata)
474{
475    QCamera3Channel *channel = (QCamera3Channel *)userdata;
476    if (channel == NULL) {
477        LOGE("invalid channel pointer");
478        return;
479    }
480    channel->streamCbRoutine(super_frame, stream);
481}
482
483/*===========================================================================
484 * FUNCTION   : dumpYUV
485 *
486 * DESCRIPTION: function to dump the YUV data from ISP/pproc
487 *
488 * PARAMETERS :
489 *   @frame   : frame to be dumped
490 *   @dim     : dimension of the stream
491 *   @offset  : offset of the data
492 *   @name    : 1 if it is ISP output/pproc input, 2 if it is pproc output
493 *
494 * RETURN  :
495 *==========================================================================*/
496void QCamera3Channel::dumpYUV(mm_camera_buf_def_t *frame, cam_dimension_t dim,
497        cam_frame_len_offset_t offset, uint8_t dump_type)
498{
499    char buf[FILENAME_MAX];
500    memset(buf, 0, sizeof(buf));
501    static int counter = 0;
502    char prop[PROPERTY_VALUE_MAX];
503    property_get("persist.camera.dumpimg", prop, "0");
504    mYUVDump = (uint32_t)atoi(prop);
505    if (mYUVDump & dump_type) {
506        mFrmNum = ((mYUVDump & 0xffff0000) >> 16);
507        if (mFrmNum == 0) {
508            mFrmNum = 10;
509        }
510        if (mFrmNum > 256) {
511            mFrmNum = 256;
512        }
513        mSkipMode = ((mYUVDump & 0x0000ff00) >> 8);
514        if (mSkipMode == 0) {
515            mSkipMode = 1;
516        }
517        if (mDumpSkipCnt == 0) {
518            mDumpSkipCnt = 1;
519        }
520        if (mDumpSkipCnt % mSkipMode == 0) {
521            if (mDumpFrmCnt <= mFrmNum) {
522                /* Note that the image dimension will be the unrotated stream dimension.
523                * If you feel that the image would have been rotated during reprocess
524                * then swap the dimensions while opening the file
525                * */
526                switch (dump_type) {
527                    case QCAMERA_DUMP_FRM_PREVIEW:
528                        snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"p_%d_%d_%dx%d.yuv",
529                            counter, frame->frame_idx, dim.width, dim.height);
530                    break;
531                    case QCAMERA_DUMP_FRM_VIDEO:
532                        snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"v_%d_%d_%dx%d.yuv",
533                            counter, frame->frame_idx, dim.width, dim.height);
534                    break;
535                    case QCAMERA_DUMP_FRM_SNAPSHOT:
536                        snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"s_%d_%d_%dx%d.yuv",
537                            counter, frame->frame_idx, dim.width, dim.height);
538                    break;
539                    case QCAMERA_DUMP_FRM_INPUT_REPROCESS:
540                        snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"ir_%d_%d_%dx%d.yuv",
541                            counter, frame->frame_idx, dim.width, dim.height);
542                    break;
543                    case QCAMERA_DUMP_FRM_CALLBACK:
544                        snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"c_%d_%d_%dx%d.yuv",
545                            counter, frame->frame_idx, dim.width, dim.height);
546                    break;
547                    default :
548                        LOGE("dumping not enabled for stream type %d",dump_type);
549                    break;
550                }
551                counter++;
552                int file_fd = open(buf, O_RDWR | O_CREAT, 0777);
553                ssize_t written_len = 0;
554                if (file_fd >= 0) {
555                    void *data = NULL;
556                    fchmod(file_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
557                    for (uint32_t i = 0; i < offset.num_planes; i++) {
558                        uint32_t index = offset.mp[i].offset;
559                        if (i > 0) {
560                            index += offset.mp[i-1].len;
561                        }
562                        for (int j = 0; j < offset.mp[i].height; j++) {
563                            data = (void *)((uint8_t *)frame->buffer + index);
564                            written_len += write(file_fd, data,
565                                    (size_t)offset.mp[i].width);
566                            index += (uint32_t)offset.mp[i].stride;
567                        }
568                    }
569                    LOGH("written number of bytes %ld\n", written_len);
570                    mDumpFrmCnt++;
571                    close(file_fd);
572                } else {
573                    LOGE("failed to open file to dump image");
574                }
575            }
576        } else {
577            mDumpSkipCnt++;
578        }
579    }
580}
581
582/*===========================================================================
583 * FUNCTION   : isUBWCEnabled
584 *
585 * DESCRIPTION: Function to get UBWC hardware support.
586 *
587 * PARAMETERS : None
588 *
589 * RETURN     : TRUE -- UBWC format supported
590 *              FALSE -- UBWC is not supported.
591 *==========================================================================*/
592bool QCamera3Channel::isUBWCEnabled()
593{
594#ifdef UBWC_PRESENT
595    char value[PROPERTY_VALUE_MAX];
596    int prop_value = 0;
597    memset(value, 0, sizeof(value));
598    property_get("debug.gralloc.gfx_ubwc_disable", value, "0");
599    prop_value = atoi(value);
600    if (prop_value) {
601        return FALSE;
602    }
603
604    //Disable UBWC if Eztune is enabled
605    //EzTune process CPP output frame and cannot understand UBWC.
606    memset(value, 0, sizeof(value));
607    property_get("persist.camera.eztune.enable", value, "0");
608    prop_value = atoi(value);
609    if (prop_value) {
610        return FALSE;
611    }
612    return TRUE;
613#else
614    return FALSE;
615#endif
616}
617
618/*===========================================================================
619 * FUNCTION   : getStreamDefaultFormat
620 *
621 * DESCRIPTION: return default buffer format for the stream
622 *
623 * PARAMETERS : type : Stream type
624 *
625 ** RETURN    : format for stream type
626 *
627 *==========================================================================*/
628cam_format_t QCamera3Channel::getStreamDefaultFormat(cam_stream_type_t type,
629        uint32_t width, uint32_t height)
630{
631    cam_format_t streamFormat;
632
633    switch (type) {
634    case CAM_STREAM_TYPE_PREVIEW:
635        if (isUBWCEnabled()) {
636            char prop[PROPERTY_VALUE_MAX];
637            int pFormat;
638            memset(prop, 0, sizeof(prop));
639            property_get("persist.camera.preview.ubwc", prop, "1");
640            pFormat = atoi(prop);
641            if (pFormat == 1) {
642                streamFormat = CAM_FORMAT_YUV_420_NV12_UBWC;
643            } else {
644                streamFormat = CAM_FORMAT_YUV_420_NV12_VENUS;
645            }
646        } else {
647            streamFormat = CAM_FORMAT_YUV_420_NV12_VENUS;
648        }
649        break;
650    case CAM_STREAM_TYPE_VIDEO:
651    {
652        /* Disable UBWC for smaller video resolutions due to CPP downscale
653            limits. Refer cpp_hw_params.h::CPP_DOWNSCALE_LIMIT_UBWC */
654        if (isUBWCEnabled() && (width >= 640) && (height >= 480)) {
655            char prop[PROPERTY_VALUE_MAX];
656            int pFormat;
657            memset(prop, 0, sizeof(prop));
658            property_get("persist.camera.video.ubwc", prop, "1");
659            pFormat = atoi(prop);
660            if (pFormat == 1) {
661                streamFormat = CAM_FORMAT_YUV_420_NV12_UBWC;
662            } else {
663                streamFormat = CAM_FORMAT_YUV_420_NV12_VENUS;
664            }
665        } else {
666#if VENUS_PRESENT
667        streamFormat = CAM_FORMAT_YUV_420_NV12_VENUS;
668#else
669        streamFormat = CAM_FORMAT_YUV_420_NV12;
670#endif
671        }
672        break;
673    }
674    case CAM_STREAM_TYPE_SNAPSHOT:
675        streamFormat = CAM_FORMAT_YUV_420_NV21;
676        break;
677    case CAM_STREAM_TYPE_CALLBACK:
678        streamFormat = CAM_FORMAT_YUV_420_NV21;
679        break;
680    case CAM_STREAM_TYPE_RAW:
681        streamFormat = CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG;
682        break;
683    default:
684        streamFormat = CAM_FORMAT_YUV_420_NV21;
685        break;
686    }
687    return streamFormat;
688}
689
690
691/* QCamera3ProcessingChannel methods */
692
693/*===========================================================================
694 * FUNCTION   : QCamera3ProcessingChannel
695 *
696 * DESCRIPTION: constructor of QCamera3ProcessingChannel
697 *
698 * PARAMETERS :
699 *   @cam_handle : camera handle
700 *   @cam_ops    : ptr to camera ops table
701 *   @cb_routine : callback routine to frame aggregator
702 *   @paddingInfo: stream padding info
703 *   @userData   : HWI handle
704 *   @stream     : camera3_stream_t structure
705 *   @stream_type: Channel stream type
706 *   @postprocess_mask: the postprocess mask for streams of this channel
707 *   @metadataChannel: handle to the metadataChannel
708 *   @numBuffers : number of max dequeued buffers
709 * RETURN     : none
710 *==========================================================================*/
711QCamera3ProcessingChannel::QCamera3ProcessingChannel(uint32_t cam_handle,
712        uint32_t channel_handle,
713        mm_camera_ops_t *cam_ops,
714        channel_cb_routine cb_routine,
715        channel_cb_buffer_err cb_buffer_err,
716        cam_padding_info_t *paddingInfo,
717        void *userData,
718        camera3_stream_t *stream,
719        cam_stream_type_t stream_type,
720        cam_feature_mask_t postprocess_mask,
721        QCamera3Channel *metadataChannel,
722        uint32_t numBuffers) :
723            QCamera3Channel(cam_handle, channel_handle, cam_ops, cb_routine,
724                    cb_buffer_err, paddingInfo, postprocess_mask, userData, numBuffers),
725            m_postprocessor(this),
726            mFrameCount(0),
727            mLastFrameCount(0),
728            mLastFpsTime(0),
729            mMemory(numBuffers),
730            mCamera3Stream(stream),
731            mNumBufs(CAM_MAX_NUM_BUFS_PER_STREAM),
732            mStreamType(stream_type),
733            mPostProcStarted(false),
734            mInputBufferConfig(false),
735            m_pMetaChannel(metadataChannel),
736            mMetaFrame(NULL),
737            mOfflineMemory(0),
738            mOfflineMetaMemory(numBuffers + (MAX_REPROCESS_PIPELINE_STAGES - 1),
739                    false)
740{
741    char prop[PROPERTY_VALUE_MAX];
742    property_get("persist.debug.sf.showfps", prop, "0");
743    mDebugFPS = (uint8_t) atoi(prop);
744
745    int32_t rc = m_postprocessor.init(&mMemory);
746    if (rc != 0) {
747        LOGE("Init Postprocessor failed");
748    }
749}
750
751/*===========================================================================
752 * FUNCTION   : ~QCamera3ProcessingChannel
753 *
754 * DESCRIPTION: destructor of QCamera3ProcessingChannel
755 *
756 * PARAMETERS : none
757 *
758 * RETURN     : none
759 *==========================================================================*/
760QCamera3ProcessingChannel::~QCamera3ProcessingChannel()
761{
762    destroy();
763
764    int32_t rc = m_postprocessor.deinit();
765    if (rc != 0) {
766        LOGE("De-init Postprocessor failed");
767    }
768
769    if (0 < mOfflineMetaMemory.getCnt()) {
770        mOfflineMetaMemory.deallocate();
771    }
772    if (0 < mOfflineMemory.getCnt()) {
773        mOfflineMemory.unregisterBuffers();
774    }
775
776}
777
778/*===========================================================================
779 * FUNCTION   : streamCbRoutine
780 *
781 * DESCRIPTION:
782 *
783 * PARAMETERS :
784 * @super_frame : the super frame with filled buffer
785 * @stream      : stream on which the buffer was requested and filled
786 *
787 * RETURN     : none
788 *==========================================================================*/
789void QCamera3ProcessingChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
790        QCamera3Stream *stream)
791{
792     ATRACE_CALL();
793    //FIXME Q Buf back in case of error?
794    uint8_t frameIndex;
795    buffer_handle_t *resultBuffer;
796    int32_t resultFrameNumber;
797    camera3_stream_buffer_t result;
798    cam_dimension_t dim;
799    cam_frame_len_offset_t offset;
800
801    memset(&dim, 0, sizeof(dim));
802    memset(&offset, 0, sizeof(cam_frame_len_offset_t));
803    if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) {
804        LOGE("Error with the stream callback");
805        return;
806    }
807
808    frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
809    if(frameIndex >= mNumBufs) {
810         LOGE("Error, Invalid index for buffer");
811         stream->bufDone(frameIndex);
812         return;
813    }
814
815    if (mDebugFPS) {
816        showDebugFPS(stream->getMyType());
817    }
818    stream->getFrameDimension(dim);
819    stream->getFrameOffset(offset);
820    if (stream->getMyType() == CAM_STREAM_TYPE_PREVIEW) {
821        dumpYUV(super_frame->bufs[0], dim, offset, QCAMERA_DUMP_FRM_PREVIEW);
822    } else if (stream->getMyType() == CAM_STREAM_TYPE_VIDEO) {
823        dumpYUV(super_frame->bufs[0], dim, offset, QCAMERA_DUMP_FRM_VIDEO);
824    } else if (stream->getMyType() == CAM_STREAM_TYPE_CALLBACK) {
825        dumpYUV(super_frame->bufs[0], dim, offset, QCAMERA_DUMP_FRM_CALLBACK);
826    }
827
828    do {
829
830       //Use below data to issue framework callback
831       resultBuffer = (buffer_handle_t *)mMemory.getBufferHandle(frameIndex);
832       resultFrameNumber = mMemory.getFrameNumber(frameIndex);
833       uint32_t oldestBufIndex;
834       int32_t lowestFrameNumber = mMemory.getOldestFrameNumber(oldestBufIndex);
835       QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
836       if ((lowestFrameNumber != -1 ) && (lowestFrameNumber < resultFrameNumber) &&
837            hal_obj->mOpMode != CAMERA3_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE) {
838           LOGE("Error buffer dropped for framenumber:%d with bufidx:%d",
839                   lowestFrameNumber, oldestBufIndex);
840           if (mOutOfSequenceBuffers.empty()) {
841              stream->cancelBuffer(oldestBufIndex);
842           }
843           mOutOfSequenceBuffers.push_back(super_frame);
844           return;
845       }
846
847       result.stream = mCamera3Stream;
848       result.buffer = resultBuffer;
849       if (IS_BUFFER_ERROR(super_frame->bufs[0]->flags)) {
850           result.status = CAMERA3_BUFFER_STATUS_ERROR;
851           LOGW("CAMERA3_BUFFER_STATUS_ERROR for stream_type: %d",
852                   mStreams[0]->getMyType());
853           mChannelCbBufErr(this, resultFrameNumber, CAMERA3_BUFFER_STATUS_ERROR, mUserData);
854       } else {
855           result.status = CAMERA3_BUFFER_STATUS_OK;
856       }
857       result.acquire_fence = -1;
858       result.release_fence = -1;
859       if(mPerFrameMapUnmapEnable) {
860           int32_t rc = stream->bufRelease(frameIndex);
861           if (NO_ERROR != rc) {
862               LOGE("Error %d releasing stream buffer %d",
863                        rc, frameIndex);
864           }
865
866           rc = mMemory.unregisterBuffer(frameIndex);
867           if (NO_ERROR != rc) {
868               LOGE("Error %d unregistering stream buffer %d",
869                        rc, frameIndex);
870           }
871       }
872
873       if (0 <= resultFrameNumber) {
874           if (mChannelCB) {
875               mChannelCB(NULL, &result, (uint32_t)resultFrameNumber, false, mUserData);
876           }
877       } else {
878           LOGE("Bad frame number");
879       }
880       free(super_frame);
881       super_frame = NULL;
882       if (mOutOfSequenceBuffers.empty()) {
883          break;
884       } else {
885            auto itr = mOutOfSequenceBuffers.begin();
886            super_frame = *itr;
887            frameIndex = super_frame->bufs[0]->buf_idx;
888            resultFrameNumber = mMemory.getFrameNumber(frameIndex);
889            lowestFrameNumber = mMemory.getOldestFrameNumber(oldestBufIndex);
890            LOGE("Attempting to recover next frame: result Frame#: %d, resultIdx: %d, "
891                    "Lowest Frame#: %d, oldestBufIndex: %d",
892                    resultFrameNumber, frameIndex, lowestFrameNumber, oldestBufIndex);
893            if ((lowestFrameNumber != -1) && (lowestFrameNumber < resultFrameNumber)) {
894                LOGE("Multiple frame dropped requesting cancel for frame %d, idx:%d",
895                        lowestFrameNumber, oldestBufIndex);
896                stream->cancelBuffer(oldestBufIndex);
897                return;
898             } else if (lowestFrameNumber == resultFrameNumber) {
899                LOGE("Time to flush out head of list continue loop with this new super frame");
900                itr = mOutOfSequenceBuffers.erase(itr);
901             } else {
902                LOGE("Unexpected condition head of list is not the lowest frame number");
903                itr = mOutOfSequenceBuffers.erase(itr);
904             }
905          }
906    } while (1);
907    return;
908}
909
910/*===========================================================================
911 * FUNCTION   : putStreamBufs
912 *
913 * DESCRIPTION: release the buffers allocated to the stream
914 *
915 * PARAMETERS : NONE
916 *
917 * RETURN     : NONE
918 *==========================================================================*/
919void QCamera3YUVChannel::putStreamBufs()
920{
921    QCamera3ProcessingChannel::putStreamBufs();
922
923    // Free allocated heap buffer.
924    mMemory.deallocate();
925    // Clear free heap buffer list.
926    mFreeHeapBufferList.clear();
927    // Clear offlinePpInfoList
928    mOfflinePpInfoList.clear();
929}
930
931/*===========================================================================
932 * FUNCTION   : timeoutFrame
933 *
934 * DESCRIPTION: Method to indicate to channel that a given frame has take too
935 *              long to be generated
936 *
937 * PARAMETERS : framenumber indicating the framenumber of the buffer timingout
938 *
939 * RETURN     : int32_t type of status
940 *              NO_ERROR  -- success
941 *              none-zero failure code
942 *==========================================================================*/
943int32_t QCamera3ProcessingChannel::timeoutFrame(uint32_t frameNumber)
944{
945    int32_t bufIdx;
946
947    bufIdx = mMemory.getBufferIndex(frameNumber);
948
949    if (bufIdx < 0) {
950        ALOGE("%s: Buffer not found for frame:%d", __func__, frameNumber);
951        return -1;
952    }
953
954    mStreams[0]->timeoutFrame(bufIdx);
955    return NO_ERROR;
956}
957
958/*===========================================================================
959 * FUNCTION   : request
960 *
961 * DESCRIPTION: handle the request - either with an input buffer or a direct
962 *              output request
963 *
964 * PARAMETERS :
965 * @buffer          : pointer to the output buffer
966 * @frameNumber     : frame number of the request
967 * @pInputBuffer    : pointer to input buffer if an input request
968 * @metadata        : parameters associated with the request
969 *
970 * RETURN     : 0 on a success start of capture
971 *              -EINVAL on invalid input
972 *              -ENODEV on serious error
973 *==========================================================================*/
974int32_t QCamera3ProcessingChannel::request(buffer_handle_t *buffer,
975        uint32_t frameNumber,
976        camera3_stream_buffer_t* pInputBuffer,
977        metadata_buffer_t* metadata,
978        int &indexUsed)
979{
980    int32_t rc = NO_ERROR;
981    int index;
982
983    if (NULL == buffer || NULL == metadata) {
984        LOGE("Invalid buffer/metadata in channel request");
985        return BAD_VALUE;
986    }
987
988    if (pInputBuffer) {
989        //need to send to reprocessing
990        LOGD("Got a request with input buffer, output streamType = %d", mStreamType);
991        reprocess_config_t reproc_cfg;
992        cam_dimension_t dim;
993        memset(&reproc_cfg, 0, sizeof(reprocess_config_t));
994        memset(&dim, 0, sizeof(dim));
995        setReprocConfig(reproc_cfg, pInputBuffer, metadata, mStreamFormat, dim);
996        startPostProc(reproc_cfg);
997
998        qcamera_fwk_input_pp_data_t *src_frame = NULL;
999        src_frame = (qcamera_fwk_input_pp_data_t *)calloc(1,
1000                sizeof(qcamera_fwk_input_pp_data_t));
1001        if (src_frame == NULL) {
1002            LOGE("No memory for src frame");
1003            return NO_MEMORY;
1004        }
1005        rc = setFwkInputPPData(src_frame, pInputBuffer, &reproc_cfg, metadata, buffer, frameNumber);
1006        if (NO_ERROR != rc) {
1007            LOGE("Error %d while setting framework input PP data", rc);
1008            free(src_frame);
1009            return rc;
1010        }
1011        LOGH("Post-process started");
1012        m_postprocessor.processData(src_frame);
1013    } else {
1014        //need to fill output buffer with new data and return
1015        if(!m_bIsActive) {
1016            rc = registerBuffer(buffer, mIsType);
1017            if (NO_ERROR != rc) {
1018                LOGE("On-the-fly buffer registration failed %d",
1019                         rc);
1020                return rc;
1021            }
1022
1023            rc = start();
1024            if (NO_ERROR != rc)
1025                return rc;
1026        } else {
1027            LOGD("Request on an existing stream");
1028        }
1029
1030        index = mMemory.getMatchBufIndex((void*)buffer);
1031        if(index < 0) {
1032            rc = registerBuffer(buffer, mIsType);
1033            if (NO_ERROR != rc) {
1034                LOGE("On-the-fly buffer registration failed %d",
1035                         rc);
1036                return rc;
1037            }
1038
1039            index = mMemory.getMatchBufIndex((void*)buffer);
1040            if (index < 0) {
1041                LOGE("Could not find object among registered buffers");
1042                return DEAD_OBJECT;
1043            }
1044        }
1045        rc = mMemory.markFrameNumber(index, frameNumber);
1046        if(rc != NO_ERROR) {
1047            LOGE("Error marking frame number:%d for index %d", frameNumber,
1048                index);
1049            return rc;
1050        }
1051        rc = mStreams[0]->bufDone(index);
1052        if(rc != NO_ERROR) {
1053            LOGE("Failed to Q new buffer to stream");
1054            mMemory.markFrameNumber(index, -1);
1055            return rc;
1056        }
1057        indexUsed = index;
1058    }
1059    return rc;
1060}
1061
1062/*===========================================================================
1063 * FUNCTION   : initialize
1064 *
1065 * DESCRIPTION:
1066 *
1067 * PARAMETERS : isType : type of image stabilization on the buffer
1068 *
1069 * RETURN     : int32_t type of status
1070 *              NO_ERROR  -- success
1071 *              none-zero failure code
1072 *==========================================================================*/
1073int32_t QCamera3ProcessingChannel::initialize(__unused cam_is_type_t isType)
1074{
1075    int32_t rc = NO_ERROR;
1076    rc = mOfflineMetaMemory.allocateAll(sizeof(metadata_buffer_t));
1077    if (rc == NO_ERROR) {
1078        Mutex::Autolock lock(mFreeOfflineMetaBuffersLock);
1079        mFreeOfflineMetaBuffersList.clear();
1080        for (uint32_t i = 0; i < mNumBuffers + (MAX_REPROCESS_PIPELINE_STAGES - 1);
1081                i++) {
1082            mFreeOfflineMetaBuffersList.push_back(i);
1083        }
1084    } else {
1085        LOGE("Could not allocate offline meta buffers for input reprocess");
1086    }
1087    mOutOfSequenceBuffers.clear();
1088    return rc;
1089}
1090
1091/*===========================================================================
1092 * FUNCTION   : registerBuffer
1093 *
1094 * DESCRIPTION: register streaming buffer to the channel object
1095 *
1096 * PARAMETERS :
1097 *   @buffer     : buffer to be registered
1098 *   @isType     : image stabilization type on the stream
1099 *
1100 * RETURN     : int32_t type of status
1101 *              NO_ERROR  -- success
1102 *              none-zero failure code
1103 *==========================================================================*/
1104int32_t QCamera3ProcessingChannel::registerBuffer(buffer_handle_t *buffer,
1105        cam_is_type_t isType)
1106{
1107    ATRACE_CALL();
1108    int rc = 0;
1109    mIsType = isType;
1110    cam_stream_type_t streamType;
1111
1112    if ((uint32_t)mMemory.getCnt() > (mNumBufs - 1)) {
1113        LOGE("Trying to register more buffers than initially requested");
1114        return BAD_VALUE;
1115    }
1116
1117    if (0 == m_numStreams) {
1118        rc = initialize(mIsType);
1119        if (rc != NO_ERROR) {
1120            LOGE("Couldn't initialize camera stream %d", rc);
1121            return rc;
1122        }
1123    }
1124
1125    streamType = mStreams[0]->getMyType();
1126    rc = mMemory.registerBuffer(buffer, streamType);
1127    if (ALREADY_EXISTS == rc) {
1128        return NO_ERROR;
1129    } else if (NO_ERROR != rc) {
1130        LOGE("Buffer %p couldn't be registered %d", buffer, rc);
1131        return rc;
1132    }
1133
1134    return rc;
1135}
1136
1137/*===========================================================================
1138 * FUNCTION   : setFwkInputPPData
1139 *
1140 * DESCRIPTION: fill out the framework src frame information for reprocessing
1141 *
1142 * PARAMETERS :
1143 *   @src_frame         : input pp data to be filled out
1144 *   @pInputBuffer      : input buffer for reprocessing
1145 *   @reproc_cfg        : pointer to the reprocess config
1146 *   @metadata          : pointer to the metadata buffer
1147 *   @output_buffer     : output buffer for reprocessing; could be NULL if not
1148 *                        framework allocated
1149 *   @frameNumber       : frame number of the request
1150 *
1151 * RETURN     : int32_t type of status
1152 *              NO_ERROR  -- success
1153 *              none-zero failure code
1154 *==========================================================================*/
1155int32_t QCamera3ProcessingChannel::setFwkInputPPData(qcamera_fwk_input_pp_data_t *src_frame,
1156        camera3_stream_buffer_t *pInputBuffer, reprocess_config_t *reproc_cfg,
1157        metadata_buffer_t *metadata, buffer_handle_t *output_buffer,
1158        uint32_t frameNumber)
1159{
1160    int32_t rc = NO_ERROR;
1161    int input_index = mOfflineMemory.getMatchBufIndex((void*)pInputBuffer->buffer);
1162    if(input_index < 0) {
1163        rc = mOfflineMemory.registerBuffer(pInputBuffer->buffer, mStreamType);
1164        if (NO_ERROR != rc) {
1165            LOGE("On-the-fly input buffer registration failed %d",
1166                     rc);
1167            return rc;
1168        }
1169        input_index = mOfflineMemory.getMatchBufIndex((void*)pInputBuffer->buffer);
1170        if (input_index < 0) {
1171            LOGE("Could not find object among registered buffers");
1172            return DEAD_OBJECT;
1173        }
1174    }
1175    mOfflineMemory.markFrameNumber(input_index, frameNumber);
1176
1177    src_frame->src_frame = *pInputBuffer;
1178    rc = mOfflineMemory.getBufDef(reproc_cfg->input_stream_plane_info.plane_info,
1179            src_frame->input_buffer, input_index);
1180    if (rc != 0) {
1181        return rc;
1182    }
1183    dumpYUV(&src_frame->input_buffer, reproc_cfg->input_stream_dim,
1184            reproc_cfg->input_stream_plane_info.plane_info, QCAMERA_DUMP_FRM_INPUT_REPROCESS);
1185    cam_dimension_t dim = {sizeof(metadata_buffer_t), 1};
1186    cam_stream_buf_plane_info_t meta_planes;
1187    rc = mm_stream_calc_offset_metadata(&dim, &mPaddingInfo, &meta_planes);
1188    if (rc != 0) {
1189        LOGE("Metadata stream plane info calculation failed!");
1190        return rc;
1191    }
1192    uint32_t metaBufIdx;
1193    {
1194        Mutex::Autolock lock(mFreeOfflineMetaBuffersLock);
1195        if (mFreeOfflineMetaBuffersList.empty()) {
1196            LOGE("mFreeOfflineMetaBuffersList is null. Fatal");
1197            return BAD_VALUE;
1198        }
1199
1200        metaBufIdx = *(mFreeOfflineMetaBuffersList.begin());
1201        mFreeOfflineMetaBuffersList.erase(mFreeOfflineMetaBuffersList.begin());
1202        LOGD("erasing %d, mFreeOfflineMetaBuffersList.size %d", metaBufIdx,
1203                mFreeOfflineMetaBuffersList.size());
1204    }
1205
1206    mOfflineMetaMemory.markFrameNumber(metaBufIdx, frameNumber);
1207
1208    mm_camera_buf_def_t meta_buf;
1209    cam_frame_len_offset_t offset = meta_planes.plane_info;
1210    rc = mOfflineMetaMemory.getBufDef(offset, meta_buf, metaBufIdx);
1211    if (NO_ERROR != rc) {
1212        return rc;
1213    }
1214    memcpy(meta_buf.buffer, metadata, sizeof(metadata_buffer_t));
1215    src_frame->metadata_buffer = meta_buf;
1216    src_frame->reproc_config = *reproc_cfg;
1217    src_frame->output_buffer = output_buffer;
1218    src_frame->frameNumber = frameNumber;
1219    return rc;
1220}
1221
1222/*===========================================================================
1223 * FUNCTION   : checkStreamCbErrors
1224 *
1225 * DESCRIPTION: check the stream callback for errors
1226 *
1227 * PARAMETERS :
1228 *   @super_frame : the super frame with filled buffer
1229 *   @stream      : stream on which the buffer was requested and filled
1230 *
1231 * RETURN     : int32_t type of status
1232 *              NO_ERROR  -- success
1233 *              none-zero failure code
1234 *==========================================================================*/
1235int32_t QCamera3ProcessingChannel::checkStreamCbErrors(mm_camera_super_buf_t *super_frame,
1236        QCamera3Stream *stream)
1237{
1238    if (NULL == stream) {
1239        LOGE("Invalid stream");
1240        return BAD_VALUE;
1241    }
1242
1243    if(NULL == super_frame) {
1244         LOGE("Invalid Super buffer");
1245         return BAD_VALUE;
1246    }
1247
1248    if(super_frame->num_bufs != 1) {
1249         LOGE("Multiple streams are not supported");
1250         return BAD_VALUE;
1251    }
1252    if(NULL == super_frame->bufs[0]) {
1253         LOGE("Error, Super buffer frame does not contain valid buffer");
1254         return BAD_VALUE;
1255    }
1256    return NO_ERROR;
1257}
1258
1259/*===========================================================================
1260 * FUNCTION   : getStreamSize
1261 *
1262 * DESCRIPTION: get the size from the camera3_stream_t for the channel
1263 *
1264 * PARAMETERS :
1265 *   @dim     : Return the size of the stream
1266 *
1267 * RETURN     : int32_t type of status
1268 *              NO_ERROR  -- success
1269 *              none-zero failure code
1270 *==========================================================================*/
1271int32_t QCamera3ProcessingChannel::getStreamSize(cam_dimension_t &dim)
1272{
1273    if (mCamera3Stream) {
1274        dim.width = mCamera3Stream->width;
1275        dim.height = mCamera3Stream->height;
1276        return NO_ERROR;
1277    } else {
1278        return BAD_VALUE;
1279    }
1280}
1281
1282/*===========================================================================
1283 * FUNCTION   : getStreamBufs
1284 *
1285 * DESCRIPTION: get the buffers allocated to the stream
1286 *
1287 * PARAMETERS :
1288 * @len       : buffer length
1289 *
1290 * RETURN     : int32_t type of status
1291 *              NO_ERROR  -- success
1292 *              none-zero failure code
1293 *==========================================================================*/
1294QCamera3StreamMem* QCamera3ProcessingChannel::getStreamBufs(uint32_t /*len*/)
1295{
1296    KPI_ATRACE_CALL();
1297    return &mMemory;
1298}
1299
1300/*===========================================================================
1301 * FUNCTION   : putStreamBufs
1302 *
1303 * DESCRIPTION: release the buffers allocated to the stream
1304 *
1305 * PARAMETERS : NONE
1306 *
1307 * RETURN     : NONE
1308 *==========================================================================*/
1309void QCamera3ProcessingChannel::putStreamBufs()
1310{
1311    mMemory.unregisterBuffers();
1312
1313    /* Reclaim all the offline metabuffers and push them to free list */
1314    {
1315        Mutex::Autolock lock(mFreeOfflineMetaBuffersLock);
1316        mFreeOfflineMetaBuffersList.clear();
1317        for (uint32_t i = 0; i < mOfflineMetaMemory.getCnt(); i++) {
1318            mFreeOfflineMetaBuffersList.push_back(i);
1319        }
1320    }
1321}
1322
1323
1324/*===========================================================================
1325 * FUNCTION   : stop
1326 *
1327 * DESCRIPTION: stop processing channel, which will stop all streams within,
1328 *              including the reprocessing channel in postprocessor.
1329 *
1330 * PARAMETERS : none
1331 *
1332 * RETURN     : int32_t type of status
1333 *              NO_ERROR  -- success
1334 *              none-zero failure code
1335 *==========================================================================*/
1336int32_t QCamera3ProcessingChannel::stop()
1337{
1338    int32_t rc = NO_ERROR;
1339    if(!m_bIsActive) {
1340        LOGE("Attempt to stop inactive channel");
1341        return rc;
1342    }
1343
1344    m_postprocessor.stop();
1345    mPostProcStarted = false;
1346    rc |= QCamera3Channel::stop();
1347    return rc;
1348}
1349
1350/*===========================================================================
1351 * FUNCTION   : startPostProc
1352 *
1353 * DESCRIPTION: figure out if the postprocessor needs to be restarted and if yes
1354 *              start it
1355 *
1356 * PARAMETERS :
1357 * @inputBufExists : whether there is an input buffer for post processing
1358 * @config         : reprocessing configuration
1359 * @metadata       : metadata associated with the reprocessing request
1360 *
1361 * RETURN     : NONE
1362 *==========================================================================*/
1363void QCamera3ProcessingChannel::startPostProc(const reprocess_config_t &config)
1364{
1365    if(!mPostProcStarted) {
1366        m_postprocessor.start(config);
1367        mPostProcStarted = true;
1368    }
1369}
1370
1371/*===========================================================================
1372 * FUNCTION   : queueReprocMetadata
1373 *
1374 * DESCRIPTION: queue the reprocess metadata to the postprocessor
1375 *
1376 * PARAMETERS : metadata : the metadata corresponding to the pp frame
1377 *
1378 * RETURN     : int32_t type of status
1379 *              NO_ERROR  -- success
1380 *              none-zero failure code
1381 *==========================================================================*/
1382int32_t QCamera3ProcessingChannel::queueReprocMetadata(mm_camera_super_buf_t *metadata)
1383{
1384    return m_postprocessor.processPPMetadata(metadata);
1385}
1386
1387/*===========================================================================
1388 * FUNCTION : metadataBufDone
1389 *
1390 * DESCRIPTION: Buffer done method for a metadata buffer
1391 *
1392 * PARAMETERS :
1393 * @recvd_frame : received metadata frame
1394 *
1395 * RETURN     : int32_t type of status
1396 *              NO_ERROR  -- success
1397 *              none-zero failure code
1398 *==========================================================================*/
1399int32_t QCamera3ProcessingChannel::metadataBufDone(mm_camera_super_buf_t *recvd_frame)
1400{
1401    int32_t rc = NO_ERROR;;
1402    if ((NULL == m_pMetaChannel) || (NULL == recvd_frame)) {
1403        LOGE("Metadata channel or metadata buffer invalid");
1404        return BAD_VALUE;
1405    }
1406
1407    rc = ((QCamera3MetadataChannel*)m_pMetaChannel)->bufDone(recvd_frame);
1408
1409    return rc;
1410}
1411
1412/*===========================================================================
1413 * FUNCTION : translateStreamTypeAndFormat
1414 *
1415 * DESCRIPTION: translates the framework stream format into HAL stream type
1416 *              and format
1417 *
1418 * PARAMETERS :
1419 * @streamType   : translated stream type
1420 * @streamFormat : translated stream format
1421 * @stream       : fwk stream
1422 *
1423 * RETURN     : int32_t type of status
1424 *              NO_ERROR  -- success
1425 *              none-zero failure code
1426 *==========================================================================*/
1427int32_t QCamera3ProcessingChannel::translateStreamTypeAndFormat(camera3_stream_t *stream,
1428        cam_stream_type_t &streamType, cam_format_t &streamFormat)
1429{
1430    switch (stream->format) {
1431        case HAL_PIXEL_FORMAT_YCbCr_420_888:
1432            if(stream->stream_type == CAMERA3_STREAM_INPUT){
1433                streamType = CAM_STREAM_TYPE_SNAPSHOT;
1434                streamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_SNAPSHOT,
1435                        stream->width, stream->height);
1436            } else {
1437                streamType = CAM_STREAM_TYPE_CALLBACK;
1438                streamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_CALLBACK,
1439                        stream->width, stream->height);
1440            }
1441            break;
1442        case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
1443            if (stream->usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) {
1444                streamType = CAM_STREAM_TYPE_VIDEO;
1445                streamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_VIDEO,
1446                        stream->width, stream->height);
1447            } else if(stream->stream_type == CAMERA3_STREAM_INPUT ||
1448                    stream->stream_type == CAMERA3_STREAM_BIDIRECTIONAL ||
1449                    IS_USAGE_ZSL(stream->usage)){
1450                streamType = CAM_STREAM_TYPE_SNAPSHOT;
1451                streamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_SNAPSHOT,
1452                        stream->width, stream->height);
1453            } else {
1454                streamType = CAM_STREAM_TYPE_PREVIEW;
1455                streamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_PREVIEW,
1456                        stream->width, stream->height);
1457            }
1458            break;
1459        case HAL_PIXEL_FORMAT_RAW_OPAQUE:
1460        case HAL_PIXEL_FORMAT_RAW16:
1461        case HAL_PIXEL_FORMAT_RAW10:
1462            streamType = CAM_STREAM_TYPE_RAW;
1463            streamFormat = CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG;
1464            break;
1465        default:
1466            return -EINVAL;
1467    }
1468    LOGD("fwk_format = %d, streamType = %d, streamFormat = %d",
1469            stream->format, streamType, streamFormat);
1470    return NO_ERROR;
1471}
1472
1473/*===========================================================================
1474 * FUNCTION : setReprocConfig
1475 *
1476 * DESCRIPTION: sets the reprocessing parameters for the input buffer
1477 *
1478 * PARAMETERS :
1479 * @reproc_cfg : the configuration to be set
1480 * @pInputBuffer : pointer to the input buffer
1481 * @metadata : pointer to the reprocessing metadata buffer
1482 * @streamFormat : format of the input stream
1483 *
1484 * RETURN     : int32_t type of status
1485 *              NO_ERROR  -- success
1486 *              none-zero failure code
1487 *==========================================================================*/
1488int32_t QCamera3ProcessingChannel::setReprocConfig(reprocess_config_t &reproc_cfg,
1489        camera3_stream_buffer_t *pInputBuffer,
1490        __unused metadata_buffer_t *metadata,
1491        cam_format_t streamFormat, cam_dimension_t dim)
1492{
1493    int32_t rc = 0;
1494    reproc_cfg.padding = &mPaddingInfo;
1495    //to ensure a big enough buffer size set the height and width
1496    //padding to max(height padding, width padding)
1497    if (reproc_cfg.padding->height_padding > reproc_cfg.padding->width_padding) {
1498       reproc_cfg.padding->width_padding = reproc_cfg.padding->height_padding;
1499    } else {
1500       reproc_cfg.padding->height_padding = reproc_cfg.padding->width_padding;
1501    }
1502    if (NULL != pInputBuffer) {
1503        reproc_cfg.input_stream_dim.width = (int32_t)pInputBuffer->stream->width;
1504        reproc_cfg.input_stream_dim.height = (int32_t)pInputBuffer->stream->height;
1505    } else {
1506        reproc_cfg.input_stream_dim.width = (int32_t)dim.width;
1507        reproc_cfg.input_stream_dim.height = (int32_t)dim.height;
1508    }
1509    reproc_cfg.src_channel = this;
1510    reproc_cfg.output_stream_dim.width = mCamera3Stream->width;
1511    reproc_cfg.output_stream_dim.height = mCamera3Stream->height;
1512    reproc_cfg.reprocess_type = getReprocessType();
1513
1514    //offset calculation
1515    if (NULL != pInputBuffer) {
1516        rc = translateStreamTypeAndFormat(pInputBuffer->stream,
1517                reproc_cfg.stream_type, reproc_cfg.stream_format);
1518        if (rc != NO_ERROR) {
1519            LOGE("Stream format %d is not supported",
1520                    pInputBuffer->stream->format);
1521            return rc;
1522        }
1523    } else {
1524        reproc_cfg.stream_type = mStreamType;
1525        reproc_cfg.stream_format = streamFormat;
1526    }
1527
1528    switch (reproc_cfg.stream_type) {
1529        case CAM_STREAM_TYPE_PREVIEW:
1530            if (getStreamByIndex(0) == NULL) {
1531                LOGE("Could not find stream");
1532                rc = -1;
1533                break;
1534            }
1535            rc = mm_stream_calc_offset_preview(
1536                    getStreamByIndex(0)->getStreamInfo(),
1537                    &reproc_cfg.input_stream_dim,
1538                    reproc_cfg.padding,
1539                    &reproc_cfg.input_stream_plane_info);
1540            break;
1541        case CAM_STREAM_TYPE_VIDEO:
1542            rc = mm_stream_calc_offset_video(reproc_cfg.stream_format,
1543                    &reproc_cfg.input_stream_dim,
1544                    &reproc_cfg.input_stream_plane_info);
1545            break;
1546        case CAM_STREAM_TYPE_RAW:
1547            rc = mm_stream_calc_offset_raw(reproc_cfg.stream_format,
1548                    &reproc_cfg.input_stream_dim,
1549                    reproc_cfg.padding, &reproc_cfg.input_stream_plane_info);
1550            break;
1551        case CAM_STREAM_TYPE_SNAPSHOT:
1552        case CAM_STREAM_TYPE_CALLBACK:
1553        default:
1554            rc = mm_stream_calc_offset_snapshot(streamFormat, &reproc_cfg.input_stream_dim,
1555                    reproc_cfg.padding, &reproc_cfg.input_stream_plane_info);
1556            break;
1557    }
1558    if (rc != 0) {
1559        LOGE("Stream %d plane info calculation failed!", mStreamType);
1560        return rc;
1561    }
1562    return rc;
1563}
1564
1565/*===========================================================================
1566 * FUNCTION   : reprocessCbRoutine
1567 *
1568 * DESCRIPTION: callback function for the reprocessed frame. This frame now
1569 *              should be returned to the framework
1570 *
1571 * PARAMETERS :
1572 * @resultBuffer      : buffer containing the reprocessed data
1573 * @resultFrameNumber : frame number on which the buffer was requested
1574 *
1575 * RETURN     : NONE
1576 *
1577 *==========================================================================*/
1578void QCamera3ProcessingChannel::reprocessCbRoutine(buffer_handle_t *resultBuffer,
1579        uint32_t resultFrameNumber)
1580{
1581    ATRACE_CALL();
1582    int rc = NO_ERROR;
1583
1584    rc = releaseOfflineMemory(resultFrameNumber);
1585    if (NO_ERROR != rc) {
1586        LOGE("Error releasing offline memory %d", rc);
1587    }
1588    /* Since reprocessing is done, send the callback to release the input buffer */
1589    if (mChannelCB) {
1590        mChannelCB(NULL, NULL, resultFrameNumber, true, mUserData);
1591    }
1592    issueChannelCb(resultBuffer, resultFrameNumber);
1593
1594    return;
1595}
1596
1597/*===========================================================================
1598 * FUNCTION   : issueChannelCb
1599 *
1600 * DESCRIPTION: function to set the result and issue channel callback
1601 *
1602 * PARAMETERS :
1603 * @resultBuffer      : buffer containing the data
1604 * @resultFrameNumber : frame number on which the buffer was requested
1605 *
1606 * RETURN     : NONE
1607 *
1608 *
1609 *==========================================================================*/
1610void QCamera3ProcessingChannel::issueChannelCb(buffer_handle_t *resultBuffer,
1611        uint32_t resultFrameNumber)
1612{
1613    camera3_stream_buffer_t result;
1614    //Use below data to issue framework callback
1615    result.stream = mCamera3Stream;
1616    result.buffer = resultBuffer;
1617    result.status = CAMERA3_BUFFER_STATUS_OK;
1618    result.acquire_fence = -1;
1619    result.release_fence = -1;
1620
1621    if (mChannelCB) {
1622        mChannelCB(NULL, &result, resultFrameNumber, false, mUserData);
1623    }
1624}
1625
1626/*===========================================================================
1627 * FUNCTION   : showDebugFPS
1628 *
1629 * DESCRIPTION: Function to log the fps for preview, video, callback and raw
1630 *              streams
1631 *
1632 * PARAMETERS : Stream type
1633 *
1634 * RETURN  : None
1635 *==========================================================================*/
1636void QCamera3ProcessingChannel::showDebugFPS(int32_t streamType)
1637{
1638    double fps = 0;
1639    mFrameCount++;
1640    nsecs_t now = systemTime();
1641    nsecs_t diff = now - mLastFpsTime;
1642    if (diff > ms2ns(250)) {
1643        fps = (((double)(mFrameCount - mLastFrameCount)) *
1644                (double)(s2ns(1))) / (double)diff;
1645        switch(streamType) {
1646            case CAM_STREAM_TYPE_PREVIEW:
1647                LOGH("PROFILE_PREVIEW_FRAMES_PER_SECOND : %.4f: mFrameCount=%d",
1648                         fps, mFrameCount);
1649                break;
1650            case CAM_STREAM_TYPE_VIDEO:
1651                LOGH("PROFILE_VIDEO_FRAMES_PER_SECOND : %.4f",
1652                         fps);
1653                break;
1654            case CAM_STREAM_TYPE_CALLBACK:
1655                LOGH("PROFILE_CALLBACK_FRAMES_PER_SECOND : %.4f",
1656                         fps);
1657                break;
1658            case CAM_STREAM_TYPE_RAW:
1659                LOGH("PROFILE_RAW_FRAMES_PER_SECOND : %.4f",
1660                         fps);
1661                break;
1662            default:
1663                LOGH("logging not supported for the stream");
1664                break;
1665        }
1666        mLastFpsTime = now;
1667        mLastFrameCount = mFrameCount;
1668    }
1669}
1670
1671/*===========================================================================
1672 * FUNCTION   : releaseOfflineMemory
1673 *
1674 * DESCRIPTION: function to clean up the offline memory used for input reprocess
1675 *
1676 * PARAMETERS :
1677 * @resultFrameNumber : frame number on which the buffer was requested
1678 *
1679 * RETURN     : int32_t type of status
1680 *              NO_ERROR  -- success
1681 *              non-zero failure code
1682 *
1683 *
1684 *==========================================================================*/
1685int32_t QCamera3ProcessingChannel::releaseOfflineMemory(uint32_t resultFrameNumber)
1686{
1687    int32_t rc = NO_ERROR;
1688    int32_t inputBufIndex =
1689            mOfflineMemory.getGrallocBufferIndex(resultFrameNumber);
1690    if (0 <= inputBufIndex) {
1691        rc = mOfflineMemory.unregisterBuffer(inputBufIndex);
1692    } else {
1693        LOGW("Could not find offline input buffer, resultFrameNumber %d",
1694                 resultFrameNumber);
1695    }
1696    if (rc != NO_ERROR) {
1697        LOGE("Failed to unregister offline input buffer");
1698    }
1699
1700    int32_t metaBufIndex =
1701            mOfflineMetaMemory.getHeapBufferIndex(resultFrameNumber);
1702    if (0 <= metaBufIndex) {
1703        Mutex::Autolock lock(mFreeOfflineMetaBuffersLock);
1704        mFreeOfflineMetaBuffersList.push_back((uint32_t)metaBufIndex);
1705    } else {
1706        LOGW("Could not find offline meta buffer, resultFrameNumber %d",
1707                resultFrameNumber);
1708    }
1709
1710    return rc;
1711}
1712
1713/* Regular Channel methods */
1714/*===========================================================================
1715 * FUNCTION   : QCamera3RegularChannel
1716 *
1717 * DESCRIPTION: constructor of QCamera3RegularChannel
1718 *
1719 * PARAMETERS :
1720 *   @cam_handle : camera handle
1721 *   @cam_ops    : ptr to camera ops table
1722 *   @cb_routine : callback routine to frame aggregator
1723 *   @stream     : camera3_stream_t structure
1724 *   @stream_type: Channel stream type
1725 *   @postprocess_mask: feature mask for postprocessing
1726 *   @metadataChannel : metadata channel for the session
1727 *   @numBuffers : number of max dequeued buffers
1728 *
1729 * RETURN     : none
1730 *==========================================================================*/
1731QCamera3RegularChannel::QCamera3RegularChannel(uint32_t cam_handle,
1732        uint32_t channel_handle,
1733        mm_camera_ops_t *cam_ops,
1734        channel_cb_routine cb_routine,
1735        channel_cb_buffer_err cb_buffer_err,
1736        cam_padding_info_t *paddingInfo,
1737        void *userData,
1738        camera3_stream_t *stream,
1739        cam_stream_type_t stream_type,
1740        cam_feature_mask_t postprocess_mask,
1741        QCamera3Channel *metadataChannel,
1742        uint32_t numBuffers) :
1743            QCamera3ProcessingChannel(cam_handle, channel_handle, cam_ops,
1744                    cb_routine, cb_buffer_err, paddingInfo, userData, stream, stream_type,
1745                    postprocess_mask, metadataChannel, numBuffers),
1746            mBatchSize(0),
1747            mRotation(ROTATE_0)
1748{
1749}
1750
1751/*===========================================================================
1752 * FUNCTION   : ~QCamera3RegularChannel
1753 *
1754 * DESCRIPTION: destructor of QCamera3RegularChannel
1755 *
1756 * PARAMETERS : none
1757 *
1758 * RETURN     : none
1759 *==========================================================================*/
1760QCamera3RegularChannel::~QCamera3RegularChannel()
1761{
1762    destroy();
1763}
1764
1765/*===========================================================================
1766 * FUNCTION   : initialize
1767 *
1768 * DESCRIPTION: Initialize and add camera channel & stream
1769 *
1770 * PARAMETERS :
1771 *    @isType : type of image stabilization required on this stream
1772 *
1773 * RETURN     : int32_t type of status
1774 *              NO_ERROR  -- success
1775 *              none-zero failure code
1776 *==========================================================================*/
1777
1778int32_t QCamera3RegularChannel::initialize(cam_is_type_t isType)
1779{
1780    ATRACE_CALL();
1781    int32_t rc = NO_ERROR;
1782
1783    cam_dimension_t streamDim;
1784
1785    if (NULL == mCamera3Stream) {
1786        LOGE("Camera stream uninitialized");
1787        return NO_INIT;
1788    }
1789
1790    if (1 <= m_numStreams) {
1791        // Only one stream per channel supported in v3 Hal
1792        return NO_ERROR;
1793    }
1794
1795    mIsType  = isType;
1796
1797    rc = translateStreamTypeAndFormat(mCamera3Stream, mStreamType,
1798            mStreamFormat);
1799    if (rc != NO_ERROR) {
1800        return -EINVAL;
1801    }
1802
1803
1804    if ((mStreamType == CAM_STREAM_TYPE_VIDEO) ||
1805            (mStreamType == CAM_STREAM_TYPE_PREVIEW)) {
1806        if ((mCamera3Stream->rotation != CAMERA3_STREAM_ROTATION_0) &&
1807                ((mPostProcMask & CAM_QCOM_FEATURE_ROTATION) == 0)) {
1808            LOGE("attempting rotation %d when rotation is disabled",
1809                    mCamera3Stream->rotation);
1810            return -EINVAL;
1811        }
1812
1813        switch (mCamera3Stream->rotation) {
1814            case CAMERA3_STREAM_ROTATION_0:
1815                mRotation = ROTATE_0;
1816                break;
1817            case CAMERA3_STREAM_ROTATION_90: {
1818                mRotation = ROTATE_90;
1819                break;
1820            }
1821            case CAMERA3_STREAM_ROTATION_180:
1822                mRotation = ROTATE_180;
1823                break;
1824            case CAMERA3_STREAM_ROTATION_270: {
1825                mRotation = ROTATE_270;
1826                break;
1827            }
1828            default:
1829                LOGE("Unknown rotation: %d",
1830                         mCamera3Stream->rotation);
1831            return -EINVAL;
1832        }
1833    } else if (mCamera3Stream->rotation != CAMERA3_STREAM_ROTATION_0) {
1834        LOGE("Rotation %d is not supported by stream type %d",
1835                mCamera3Stream->rotation,
1836                mStreamType);
1837        return -EINVAL;
1838    }
1839
1840    streamDim.width = mCamera3Stream->width;
1841    streamDim.height = mCamera3Stream->height;
1842
1843    LOGD("batch size is %d", mBatchSize);
1844    rc = QCamera3Channel::addStream(mStreamType,
1845            mStreamFormat,
1846            streamDim,
1847            mRotation,
1848            mNumBufs,
1849            mPostProcMask,
1850            mIsType,
1851            mBatchSize);
1852
1853    return rc;
1854}
1855
1856/*===========================================================================
1857 * FUNCTION   : setBatchSize
1858 *
1859 * DESCRIPTION: Set batch size for the channel.
1860 *
1861 * PARAMETERS :
1862 *   @batchSize  : Number of image buffers in a batch
1863 *
1864 * RETURN     : int32_t type of status
1865 *              NO_ERROR  -- success always
1866 *              none-zero failure code
1867 *==========================================================================*/
1868int32_t QCamera3RegularChannel::setBatchSize(uint32_t batchSize)
1869{
1870    int32_t rc = NO_ERROR;
1871
1872    mBatchSize = batchSize;
1873    LOGD("Batch size set: %d", mBatchSize);
1874    return rc;
1875}
1876
1877/*===========================================================================
1878 * FUNCTION   : getStreamTypeMask
1879 *
1880 * DESCRIPTION: Get bit mask of all stream types in this channel.
1881 *              If stream is not initialized, then generate mask based on
1882 *              local streamType
1883 *
1884 * PARAMETERS : None
1885 *
1886 * RETURN     : Bit mask of all stream types in this channel
1887 *==========================================================================*/
1888uint32_t QCamera3RegularChannel::getStreamTypeMask()
1889{
1890    if (mStreams[0]) {
1891        return QCamera3Channel::getStreamTypeMask();
1892    } else {
1893        return (1U << mStreamType);
1894    }
1895}
1896
1897/*===========================================================================
1898 * FUNCTION   : queueBatchBuf
1899 *
1900 * DESCRIPTION: queue batch container to downstream
1901 *
1902 * PARAMETERS :
1903 *
1904 * RETURN     : int32_t type of status
1905 *              NO_ERROR  -- success always
1906 *              none-zero failure code
1907 *==========================================================================*/
1908int32_t QCamera3RegularChannel::queueBatchBuf()
1909{
1910    int32_t rc = NO_ERROR;
1911
1912    if (mStreams[0]) {
1913        rc = mStreams[0]->queueBatchBuf();
1914    }
1915    if (rc != NO_ERROR) {
1916        LOGE("stream->queueBatchContainer failed");
1917    }
1918    return rc;
1919}
1920
1921/*===========================================================================
1922 * FUNCTION   : request
1923 *
1924 * DESCRIPTION: process a request from camera service. Stream on if ncessary.
1925 *
1926 * PARAMETERS :
1927 *   @buffer  : buffer to be filled for this request
1928 *
1929 * RETURN     : 0 on a success start of capture
1930 *              -EINVAL on invalid input
1931 *              -ENODEV on serious error
1932 *==========================================================================*/
1933int32_t QCamera3RegularChannel::request(buffer_handle_t *buffer, uint32_t frameNumber, int &indexUsed)
1934{
1935    ATRACE_CALL();
1936    //FIX ME: Return buffer back in case of failures below.
1937
1938    int32_t rc = NO_ERROR;
1939    int index;
1940
1941    if (NULL == buffer) {
1942        LOGE("Invalid buffer in channel request");
1943        return BAD_VALUE;
1944    }
1945
1946    if(!m_bIsActive) {
1947        rc = registerBuffer(buffer, mIsType);
1948        if (NO_ERROR != rc) {
1949            LOGE("On-the-fly buffer registration failed %d",
1950                     rc);
1951            return rc;
1952        }
1953
1954        rc = start();
1955        if (NO_ERROR != rc) {
1956            return rc;
1957        }
1958    } else {
1959        LOGD("Request on an existing stream");
1960    }
1961
1962    index = mMemory.getMatchBufIndex((void*)buffer);
1963    if(index < 0) {
1964        rc = registerBuffer(buffer, mIsType);
1965        if (NO_ERROR != rc) {
1966            LOGE("On-the-fly buffer registration failed %d",
1967                     rc);
1968            return rc;
1969        }
1970
1971        index = mMemory.getMatchBufIndex((void*)buffer);
1972        if (index < 0) {
1973            LOGE("Could not find object among registered buffers");
1974            return DEAD_OBJECT;
1975        }
1976    }
1977
1978    rc = mMemory.markFrameNumber((uint32_t)index, frameNumber);
1979    if(rc != NO_ERROR) {
1980        LOGE("Failed to mark FrameNumber:%d,idx:%d",frameNumber,index);
1981        return rc;
1982    }
1983    rc = mStreams[0]->bufDone((uint32_t)index);
1984    if(rc != NO_ERROR) {
1985        LOGE("Failed to Q new buffer to stream");
1986        mMemory.markFrameNumber(index, -1);
1987        return rc;
1988    }
1989
1990    indexUsed = index;
1991    return rc;
1992}
1993
1994/*===========================================================================
1995 * FUNCTION   : getReprocessType
1996 *
1997 * DESCRIPTION: get the type of reprocess output supported by this channel
1998 *
1999 * PARAMETERS : NONE
2000 *
2001 * RETURN     : reprocess_type_t : type of reprocess
2002 *==========================================================================*/
2003reprocess_type_t QCamera3RegularChannel::getReprocessType()
2004{
2005    return REPROCESS_TYPE_PRIVATE;
2006}
2007
2008
2009QCamera3MetadataChannel::QCamera3MetadataChannel(uint32_t cam_handle,
2010                    uint32_t channel_handle,
2011                    mm_camera_ops_t *cam_ops,
2012                    channel_cb_routine cb_routine,
2013                    channel_cb_buffer_err cb_buffer_err,
2014                    cam_padding_info_t *paddingInfo,
2015                    cam_feature_mask_t postprocess_mask,
2016                    void *userData, uint32_t numBuffers) :
2017                        QCamera3Channel(cam_handle, channel_handle, cam_ops,
2018                                cb_routine, cb_buffer_err, paddingInfo, postprocess_mask,
2019                                userData, numBuffers),
2020                        mMemory(NULL)
2021{
2022}
2023
2024QCamera3MetadataChannel::~QCamera3MetadataChannel()
2025{
2026    destroy();
2027
2028    if (mMemory) {
2029        mMemory->deallocate();
2030        delete mMemory;
2031        mMemory = NULL;
2032    }
2033}
2034
2035int32_t QCamera3MetadataChannel::initialize(cam_is_type_t isType)
2036{
2037    ATRACE_CALL();
2038    int32_t rc;
2039    cam_dimension_t streamDim;
2040
2041    if (mMemory || m_numStreams > 0) {
2042        LOGE("metadata channel already initialized");
2043        return -EINVAL;
2044    }
2045
2046    streamDim.width = (int32_t)sizeof(metadata_buffer_t),
2047    streamDim.height = 1;
2048
2049    mIsType = isType;
2050    rc = QCamera3Channel::addStream(CAM_STREAM_TYPE_METADATA, CAM_FORMAT_MAX,
2051            streamDim, ROTATE_0, (uint8_t)mNumBuffers, mPostProcMask, mIsType);
2052    if (rc < 0) {
2053        LOGE("addStream failed");
2054    }
2055    return rc;
2056}
2057
2058int32_t QCamera3MetadataChannel::request(buffer_handle_t * /*buffer*/,
2059                                                uint32_t /*frameNumber*/,
2060                                                int&  /*indexUsed*/)
2061{
2062    if (!m_bIsActive) {
2063        return start();
2064    }
2065    else
2066        return 0;
2067}
2068
2069void QCamera3MetadataChannel::streamCbRoutine(
2070                        mm_camera_super_buf_t *super_frame,
2071                        QCamera3Stream * /*stream*/)
2072{
2073    ATRACE_NAME("metadata_stream_cb_routine");
2074    uint32_t requestNumber = 0;
2075    if (super_frame == NULL || super_frame->num_bufs != 1) {
2076        LOGE("super_frame is not valid");
2077        return;
2078    }
2079    if (mChannelCB) {
2080        mChannelCB(super_frame, NULL, requestNumber, false, mUserData);
2081    }
2082}
2083
2084QCamera3StreamMem* QCamera3MetadataChannel::getStreamBufs(uint32_t len)
2085{
2086    int rc;
2087    if (len < sizeof(metadata_buffer_t)) {
2088        LOGE("Metadata buffer size less than structure %d vs %d",
2089                len,
2090                sizeof(metadata_buffer_t));
2091        return NULL;
2092    }
2093    mMemory = new QCamera3StreamMem(MIN_STREAMING_BUFFER_NUM);
2094    if (!mMemory) {
2095        LOGE("unable to create metadata memory");
2096        return NULL;
2097    }
2098    rc = mMemory->allocateAll(len);
2099    if (rc < 0) {
2100        LOGE("unable to allocate metadata memory");
2101        delete mMemory;
2102        mMemory = NULL;
2103        return NULL;
2104    }
2105    clear_metadata_buffer((metadata_buffer_t*)mMemory->getPtr(0));
2106    return mMemory;
2107}
2108
2109void QCamera3MetadataChannel::putStreamBufs()
2110{
2111    mMemory->deallocate();
2112    delete mMemory;
2113    mMemory = NULL;
2114}
2115/*************************************************************************************/
2116// RAW Channel related functions
2117QCamera3RawChannel::QCamera3RawChannel(uint32_t cam_handle,
2118                    uint32_t channel_handle,
2119                    mm_camera_ops_t *cam_ops,
2120                    channel_cb_routine cb_routine,
2121                    channel_cb_buffer_err cb_buffer_err,
2122                    cam_padding_info_t *paddingInfo,
2123                    void *userData,
2124                    camera3_stream_t *stream,
2125                    cam_feature_mask_t postprocess_mask,
2126                    QCamera3Channel *metadataChannel,
2127                    bool raw_16, uint32_t numBuffers) :
2128                        QCamera3RegularChannel(cam_handle, channel_handle, cam_ops,
2129                                cb_routine, cb_buffer_err, paddingInfo, userData, stream,
2130                                CAM_STREAM_TYPE_RAW, postprocess_mask,
2131                                metadataChannel, numBuffers),
2132                        mIsRaw16(raw_16)
2133{
2134    char prop[PROPERTY_VALUE_MAX];
2135    property_get("persist.camera.raw.debug.dump", prop, "0");
2136    mRawDump = atoi(prop);
2137}
2138
2139QCamera3RawChannel::~QCamera3RawChannel()
2140{
2141}
2142
2143/*===========================================================================
2144 * FUNCTION   : initialize
2145 *
2146 * DESCRIPTION: Initialize and add camera channel & stream
2147 *
2148 * PARAMETERS :
2149 * @isType    : image stabilization type on the stream
2150 *
2151 * RETURN     : int32_t type of status
2152 *              NO_ERROR  -- success
2153 *              none-zero failure code
2154 *==========================================================================*/
2155
2156int32_t QCamera3RawChannel::initialize(cam_is_type_t isType)
2157{
2158    return QCamera3RegularChannel::initialize(isType);
2159}
2160
2161void QCamera3RawChannel::streamCbRoutine(
2162                        mm_camera_super_buf_t *super_frame,
2163                        QCamera3Stream * stream)
2164{
2165    ATRACE_CALL();
2166    /* Move this back down once verified */
2167    if (mRawDump)
2168        dumpRawSnapshot(super_frame->bufs[0]);
2169
2170    if (mIsRaw16) {
2171        cam_format_t streamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_RAW,
2172                mCamera3Stream->width, mCamera3Stream->height);
2173        if (streamFormat == CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG)
2174            convertMipiToRaw16(super_frame->bufs[0]);
2175        else
2176            convertLegacyToRaw16(super_frame->bufs[0]);
2177    }
2178
2179    //Make sure cache coherence because extra processing is done
2180    mMemory.cleanInvalidateCache(super_frame->bufs[0]->buf_idx);
2181
2182    QCamera3RegularChannel::streamCbRoutine(super_frame, stream);
2183    return;
2184}
2185
2186void QCamera3RawChannel::dumpRawSnapshot(mm_camera_buf_def_t *frame)
2187{
2188   QCamera3Stream *stream = getStreamByIndex(0);
2189   if (stream != NULL) {
2190       char buf[FILENAME_MAX];
2191       memset(buf, 0, sizeof(buf));
2192       cam_dimension_t dim;
2193       memset(&dim, 0, sizeof(dim));
2194       stream->getFrameDimension(dim);
2195
2196       cam_frame_len_offset_t offset;
2197       memset(&offset, 0, sizeof(cam_frame_len_offset_t));
2198       stream->getFrameOffset(offset);
2199       snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"r_%d_%dx%d.raw",
2200                frame->frame_idx, offset.mp[0].stride, offset.mp[0].scanline);
2201
2202       int file_fd = open(buf, O_RDWR| O_CREAT, 0644);
2203       if (file_fd >= 0) {
2204          ssize_t written_len = write(file_fd, frame->buffer, frame->frame_len);
2205          LOGD("written number of bytes %zd", written_len);
2206          close(file_fd);
2207       } else {
2208          LOGE("failed to open file to dump image");
2209       }
2210   } else {
2211       LOGE("Could not find stream");
2212   }
2213
2214}
2215
2216void QCamera3RawChannel::convertLegacyToRaw16(mm_camera_buf_def_t *frame)
2217{
2218    // Convert image buffer from Opaque raw format to RAW16 format
2219    // 10bit Opaque raw is stored in the format of:
2220    // 0000 - p5 - p4 - p3 - p2 - p1 - p0
2221    // where p0 to p5 are 6 pixels (each is 10bit)_and most significant
2222    // 4 bits are 0s. Each 64bit word contains 6 pixels.
2223
2224  QCamera3Stream *stream = getStreamByIndex(0);
2225  if (stream != NULL) {
2226      cam_dimension_t dim;
2227      memset(&dim, 0, sizeof(dim));
2228      stream->getFrameDimension(dim);
2229
2230      cam_frame_len_offset_t offset;
2231      memset(&offset, 0, sizeof(cam_frame_len_offset_t));
2232      stream->getFrameOffset(offset);
2233
2234      uint32_t raw16_stride = ((uint32_t)dim.width + 15U) & ~15U;
2235      uint16_t* raw16_buffer = (uint16_t *)frame->buffer;
2236
2237      // In-place format conversion.
2238      // Raw16 format always occupy more memory than opaque raw10.
2239      // Convert to Raw16 by iterating through all pixels from bottom-right
2240      // to top-left of the image.
2241      // One special notes:
2242      // 1. Cross-platform raw16's stride is 16 pixels.
2243      // 2. Opaque raw10's stride is 6 pixels, and aligned to 16 bytes.
2244      for (int32_t ys = dim.height - 1; ys >= 0; ys--) {
2245          uint32_t y = (uint32_t)ys;
2246          uint64_t* row_start = (uint64_t *)frame->buffer +
2247                  y * (uint32_t)offset.mp[0].stride_in_bytes / 8;
2248          for (int32_t xs = dim.width - 1; xs >= 0; xs--) {
2249              uint32_t x = (uint32_t)xs;
2250              uint16_t raw16_pixel = 0x3FF & (row_start[x/6] >> (10*(x%6)));
2251              raw16_buffer[y*raw16_stride+x] = raw16_pixel;
2252          }
2253      }
2254  } else {
2255      LOGE("Could not find stream");
2256  }
2257
2258}
2259
2260void QCamera3RawChannel::convertMipiToRaw16(mm_camera_buf_def_t *frame)
2261{
2262    // Convert image buffer from mipi10 raw format to RAW16 format
2263    // mipi10 opaque raw is stored in the format of:
2264    // P3(1:0) P2(1:0) P1(1:0) P0(1:0) P3(9:2) P2(9:2) P1(9:2) P0(9:2)
2265    // 4 pixels occupy 5 bytes, no padding needed
2266
2267    QCamera3Stream *stream = getStreamByIndex(0);
2268    if (stream != NULL) {
2269        cam_dimension_t dim;
2270        memset(&dim, 0, sizeof(dim));
2271        stream->getFrameDimension(dim);
2272
2273        cam_frame_len_offset_t offset;
2274        memset(&offset, 0, sizeof(cam_frame_len_offset_t));
2275        stream->getFrameOffset(offset);
2276
2277        uint32_t raw16_stride = ((uint32_t)dim.width + 15U) & ~15U;
2278        uint16_t* raw16_buffer = (uint16_t *)frame->buffer;
2279
2280        // In-place format conversion.
2281        // Raw16 format always occupy more memory than opaque raw10.
2282        // Convert to Raw16 by iterating through all pixels from bottom-right
2283        // to top-left of the image.
2284        // One special notes:
2285        // 1. Cross-platform raw16's stride is 16 pixels.
2286        // 2. mipi raw10's stride is 4 pixels, and aligned to 16 bytes.
2287        for (int32_t ys = dim.height - 1; ys >= 0; ys--) {
2288            uint32_t y = (uint32_t)ys;
2289            uint8_t* row_start = (uint8_t *)frame->buffer +
2290                    y * (uint32_t)offset.mp[0].stride_in_bytes;
2291            for (int32_t xs = dim.width - 1; xs >= 0; xs--) {
2292                uint32_t x = (uint32_t)xs;
2293                uint8_t upper_8bit = row_start[5*(x/4)+x%4];
2294                uint8_t lower_2bit = ((row_start[5*(x/4)+4] >> (x%4)) & 0x3);
2295                uint16_t raw16_pixel =
2296                        (uint16_t)(((uint16_t)upper_8bit)<<2 |
2297                        (uint16_t)lower_2bit);
2298                raw16_buffer[y*raw16_stride+x] = raw16_pixel;
2299            }
2300        }
2301    } else {
2302        LOGE("Could not find stream");
2303    }
2304
2305}
2306
2307/*===========================================================================
2308 * FUNCTION   : getReprocessType
2309 *
2310 * DESCRIPTION: get the type of reprocess output supported by this channel
2311 *
2312 * PARAMETERS : NONE
2313 *
2314 * RETURN     : reprocess_type_t : type of reprocess
2315 *==========================================================================*/
2316reprocess_type_t QCamera3RawChannel::getReprocessType()
2317{
2318    return REPROCESS_TYPE_RAW;
2319}
2320
2321
2322/*************************************************************************************/
2323// RAW Dump Channel related functions
2324
2325/*===========================================================================
2326 * FUNCTION   : QCamera3RawDumpChannel
2327 *
2328 * DESCRIPTION: Constructor for RawDumpChannel
2329 *
2330 * PARAMETERS :
2331 *   @cam_handle    : Handle for Camera
2332 *   @cam_ops       : Function pointer table
2333 *   @rawDumpSize   : Dimensions for the Raw stream
2334 *   @paddinginfo   : Padding information for stream
2335 *   @userData      : Cookie for parent
2336 *   @pp mask       : PP feature mask for this stream
2337 *   @numBuffers    : number of max dequeued buffers
2338 *
2339 * RETURN           : NA
2340 *==========================================================================*/
2341QCamera3RawDumpChannel::QCamera3RawDumpChannel(uint32_t cam_handle,
2342                    uint32_t channel_handle,
2343                    mm_camera_ops_t *cam_ops,
2344                    cam_dimension_t rawDumpSize,
2345                    cam_padding_info_t *paddingInfo,
2346                    void *userData,
2347                    cam_feature_mask_t postprocess_mask, uint32_t numBuffers) :
2348                        QCamera3Channel(cam_handle, channel_handle, cam_ops, NULL,
2349                                NULL, paddingInfo, postprocess_mask,
2350                                userData, numBuffers),
2351                        mDim(rawDumpSize),
2352                        mMemory(NULL)
2353{
2354    char prop[PROPERTY_VALUE_MAX];
2355    property_get("persist.camera.raw.dump", prop, "0");
2356    mRawDump = atoi(prop);
2357}
2358
2359/*===========================================================================
2360 * FUNCTION   : QCamera3RawDumpChannel
2361 *
2362 * DESCRIPTION: Destructor for RawDumpChannel
2363 *
2364 * PARAMETERS :
2365 *
2366 * RETURN           : NA
2367 *==========================================================================*/
2368
2369QCamera3RawDumpChannel::~QCamera3RawDumpChannel()
2370{
2371    destroy();
2372}
2373
2374/*===========================================================================
2375 * FUNCTION   : dumpRawSnapshot
2376 *
2377 * DESCRIPTION: Helper function to dump Raw frames
2378 *
2379 * PARAMETERS :
2380 *  @frame      : stream buf frame to be dumped
2381 *
2382 *  RETURN      : NA
2383 *==========================================================================*/
2384void QCamera3RawDumpChannel::dumpRawSnapshot(mm_camera_buf_def_t *frame)
2385{
2386    QCamera3Stream *stream = getStreamByIndex(0);
2387    if (stream != NULL) {
2388        char buf[FILENAME_MAX];
2389        struct timeval tv;
2390        struct tm timeinfo_data;
2391        struct tm *timeinfo;
2392
2393        cam_dimension_t dim;
2394        memset(&dim, 0, sizeof(dim));
2395        stream->getFrameDimension(dim);
2396
2397        cam_frame_len_offset_t offset;
2398        memset(&offset, 0, sizeof(cam_frame_len_offset_t));
2399        stream->getFrameOffset(offset);
2400
2401        gettimeofday(&tv, NULL);
2402        timeinfo = localtime_r(&tv.tv_sec, &timeinfo_data);
2403
2404        if (NULL != timeinfo) {
2405            memset(buf, 0, sizeof(buf));
2406            /* Consistent naming for Jpeg+meta+raw: Raw name */
2407            snprintf(buf, sizeof(buf),
2408                    QCAMERA_DUMP_FRM_LOCATION
2409                    "IMG_%04d%02d%02d_%02d%02d%02d_%dx%d.raw",
2410                    timeinfo->tm_year + 1900, timeinfo->tm_mon + 1,
2411                    timeinfo->tm_mday, timeinfo->tm_hour,
2412                    timeinfo->tm_min, timeinfo->tm_sec,
2413                    dim.width, dim.height);
2414            /* Consistent naming for Jpeg+meta+raw: Raw name end*/
2415            int file_fd = open(buf, O_RDWR| O_CREAT, 0777);
2416            if (file_fd >= 0) {
2417                ssize_t written_len =
2418                        write(file_fd, frame->buffer, offset.frame_len);
2419                LOGD("written number of bytes %zd", written_len);
2420                close(file_fd);
2421            } else {
2422                LOGE("failed to open file to dump image");
2423            }
2424        } else {
2425            LOGE("localtime_r() error");
2426        }
2427    } else {
2428        LOGE("Could not find stream");
2429    }
2430
2431}
2432
2433/*===========================================================================
2434 * FUNCTION   : streamCbRoutine
2435 *
2436 * DESCRIPTION: Callback routine invoked for each frame generated for
2437 *              Rawdump channel
2438 *
2439 * PARAMETERS :
2440 *   @super_frame  : stream buf frame generated
2441 *   @stream       : Underlying Stream object cookie
2442 *
2443 * RETURN          : NA
2444 *==========================================================================*/
2445void QCamera3RawDumpChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
2446                                                __unused QCamera3Stream *stream)
2447{
2448    LOGD("E");
2449    if (super_frame == NULL || super_frame->num_bufs != 1) {
2450        LOGE("super_frame is not valid");
2451        return;
2452    }
2453
2454    if (mRawDump)
2455        dumpRawSnapshot(super_frame->bufs[0]);
2456
2457    bufDone(super_frame);
2458    free(super_frame);
2459}
2460
2461/*===========================================================================
2462 * FUNCTION   : getStreamBufs
2463 *
2464 * DESCRIPTION: Callback function provided to interface to get buffers.
2465 *
2466 * PARAMETERS :
2467 *   @len       : Length of each buffer to be allocated
2468 *
2469 * RETURN     : NULL on buffer allocation failure
2470 *              QCamera3StreamMem object on sucess
2471 *==========================================================================*/
2472QCamera3StreamMem* QCamera3RawDumpChannel::getStreamBufs(uint32_t len)
2473{
2474    int rc;
2475    mMemory = new QCamera3StreamMem(mNumBuffers);
2476
2477    if (!mMemory) {
2478        LOGE("unable to create heap memory");
2479        return NULL;
2480    }
2481    rc = mMemory->allocateAll((size_t)len);
2482    if (rc < 0) {
2483        LOGE("unable to allocate heap memory");
2484        delete mMemory;
2485        mMemory = NULL;
2486        return NULL;
2487    }
2488    return mMemory;
2489}
2490
2491/*===========================================================================
2492 * FUNCTION   : putStreamBufs
2493 *
2494 * DESCRIPTION: Callback function provided to interface to return buffers.
2495 *              Although no handles are actually returned, implicitl assumption
2496 *              that interface will no longer use buffers and channel can
2497 *              deallocated if necessary.
2498 *
2499 * PARAMETERS : NA
2500 *
2501 * RETURN     : NA
2502 *==========================================================================*/
2503void QCamera3RawDumpChannel::putStreamBufs()
2504{
2505    mMemory->deallocate();
2506    delete mMemory;
2507    mMemory = NULL;
2508}
2509
2510/*===========================================================================
2511 * FUNCTION : request
2512 *
2513 * DESCRIPTION: Request function used as trigger
2514 *
2515 * PARAMETERS :
2516 * @recvd_frame : buffer- this will be NULL since this is internal channel
2517 * @frameNumber : Undefined again since this is internal stream
2518 *
2519 * RETURN     : int32_t type of status
2520 *              NO_ERROR  -- success
2521 *              none-zero failure code
2522 *==========================================================================*/
2523int32_t QCamera3RawDumpChannel::request(buffer_handle_t * /*buffer*/,
2524                                                uint32_t /*frameNumber*/,
2525                                                int & /*indexUsed*/)
2526{
2527    if (!m_bIsActive) {
2528        return QCamera3Channel::start();
2529    }
2530    else
2531        return 0;
2532}
2533
2534/*===========================================================================
2535 * FUNCTION : intialize
2536 *
2537 * DESCRIPTION: Initializes channel params and creates underlying stream
2538 *
2539 * PARAMETERS :
2540 *    @isType : type of image stabilization required on this stream
2541 *
2542 * RETURN     : int32_t type of status
2543 *              NO_ERROR  -- success
2544 *              none-zero failure code
2545 *==========================================================================*/
2546int32_t QCamera3RawDumpChannel::initialize(cam_is_type_t isType)
2547{
2548    int32_t rc;
2549
2550    mIsType = isType;
2551    rc = QCamera3Channel::addStream(CAM_STREAM_TYPE_RAW,
2552        CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG, mDim, ROTATE_0, (uint8_t)mNumBuffers,
2553        mPostProcMask, mIsType);
2554    if (rc < 0) {
2555        LOGE("addStream failed");
2556    }
2557    return rc;
2558}
2559/*************************************************************************************/
2560
2561/* QCamera3YUVChannel methods */
2562
2563/*===========================================================================
2564 * FUNCTION   : QCamera3YUVChannel
2565 *
2566 * DESCRIPTION: constructor of QCamera3YUVChannel
2567 *
2568 * PARAMETERS :
2569 *   @cam_handle : camera handle
2570 *   @cam_ops    : ptr to camera ops table
2571 *   @cb_routine : callback routine to frame aggregator
2572 *   @paddingInfo : padding information for the stream
2573 *   @stream     : camera3_stream_t structure
2574 *   @stream_type: Channel stream type
2575 *   @postprocess_mask: the postprocess mask for streams of this channel
2576 *   @metadataChannel: handle to the metadataChannel
2577 * RETURN     : none
2578 *==========================================================================*/
2579QCamera3YUVChannel::QCamera3YUVChannel(uint32_t cam_handle,
2580        uint32_t channel_handle,
2581        mm_camera_ops_t *cam_ops,
2582        channel_cb_routine cb_routine,
2583        channel_cb_buffer_err cb_buf_err,
2584        cam_padding_info_t *paddingInfo,
2585        void *userData,
2586        camera3_stream_t *stream,
2587        cam_stream_type_t stream_type,
2588        cam_feature_mask_t postprocess_mask,
2589        QCamera3Channel *metadataChannel) :
2590            QCamera3ProcessingChannel(cam_handle, channel_handle, cam_ops,
2591                    cb_routine, cb_buf_err, paddingInfo, userData, stream, stream_type,
2592                    postprocess_mask, metadataChannel)
2593{
2594
2595    mBypass = (postprocess_mask == CAM_QCOM_FEATURE_NONE);
2596    mFrameLen = 0;
2597    mEdgeMode.edge_mode = CAM_EDGE_MODE_OFF;
2598    mEdgeMode.sharpness = 0;
2599    mNoiseRedMode = CAM_NOISE_REDUCTION_MODE_OFF;
2600    memset(&mCropRegion, 0, sizeof(mCropRegion));
2601}
2602
2603/*===========================================================================
2604 * FUNCTION   : ~QCamera3YUVChannel
2605 *
2606 * DESCRIPTION: destructor of QCamera3YUVChannel
2607 *
2608 * PARAMETERS : none
2609 *
2610 *
2611 * RETURN     : none
2612 *==========================================================================*/
2613QCamera3YUVChannel::~QCamera3YUVChannel()
2614{
2615   // Deallocation of heap buffers allocated in mMemory is freed
2616   // automatically by its destructor
2617}
2618
2619/*===========================================================================
2620 * FUNCTION   : initialize
2621 *
2622 * DESCRIPTION: Initialize and add camera channel & stream
2623 *
2624 * PARAMETERS :
2625 * @isType    : the image stabilization type
2626 *
2627 * RETURN     : int32_t type of status
2628 *              NO_ERROR  -- success
2629 *              none-zero failure code
2630 *==========================================================================*/
2631int32_t QCamera3YUVChannel::initialize(cam_is_type_t isType)
2632{
2633    ATRACE_CALL();
2634    int32_t rc = NO_ERROR;
2635    cam_dimension_t streamDim;
2636
2637    if (NULL == mCamera3Stream) {
2638        LOGE("Camera stream uninitialized");
2639        return NO_INIT;
2640    }
2641
2642    if (1 <= m_numStreams) {
2643        // Only one stream per channel supported in v3 Hal
2644        return NO_ERROR;
2645    }
2646
2647    mIsType  = isType;
2648    mStreamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_CALLBACK,
2649            mCamera3Stream->width, mCamera3Stream->height);
2650    streamDim.width = mCamera3Stream->width;
2651    streamDim.height = mCamera3Stream->height;
2652
2653    rc = QCamera3Channel::addStream(mStreamType,
2654            mStreamFormat,
2655            streamDim,
2656            ROTATE_0,
2657            mNumBufs,
2658            mPostProcMask,
2659            mIsType);
2660    if (rc < 0) {
2661        LOGE("addStream failed");
2662        return rc;
2663    }
2664
2665    cam_stream_buf_plane_info_t buf_planes;
2666    cam_padding_info_t paddingInfo = mPaddingInfo;
2667
2668    memset(&buf_planes, 0, sizeof(buf_planes));
2669    //to ensure a big enough buffer size set the height and width
2670    //padding to max(height padding, width padding)
2671    paddingInfo.width_padding = MAX(paddingInfo.width_padding, paddingInfo.height_padding);
2672    paddingInfo.height_padding = paddingInfo.width_padding;
2673
2674    rc = mm_stream_calc_offset_snapshot(mStreamFormat, &streamDim, &paddingInfo,
2675            &buf_planes);
2676    if (rc < 0) {
2677        LOGE("mm_stream_calc_offset_preview failed");
2678        return rc;
2679    }
2680
2681    mFrameLen = buf_planes.plane_info.frame_len;
2682
2683    if (NO_ERROR != rc) {
2684        LOGE("Initialize failed, rc = %d", rc);
2685        return rc;
2686    }
2687
2688    /* initialize offline meta memory for input reprocess */
2689    rc = QCamera3ProcessingChannel::initialize(isType);
2690    if (NO_ERROR != rc) {
2691        LOGE("Processing Channel initialize failed, rc = %d",
2692                 rc);
2693    }
2694
2695    return rc;
2696}
2697
2698/*===========================================================================
2699 * FUNCTION   : request
2700 *
2701 * DESCRIPTION: entry function for a request on a YUV stream. This function
2702 *              has the logic to service a request based on its type
2703 *
2704 * PARAMETERS :
2705 * @buffer          : pointer to the output buffer
2706 * @frameNumber     : frame number of the request
2707 * @pInputBuffer    : pointer to input buffer if an input request
2708 * @metadata        : parameters associated with the request
2709 *
2710 * RETURN     : 0 on a success start of capture
2711 *              -EINVAL on invalid input
2712 *              -ENODEV on serious error
2713 *==========================================================================*/
2714int32_t QCamera3YUVChannel::request(buffer_handle_t *buffer,
2715        uint32_t frameNumber,
2716        camera3_stream_buffer_t* pInputBuffer,
2717        metadata_buffer_t* metadata, bool &needMetadata,
2718        int &indexUsed)
2719{
2720    int32_t rc = NO_ERROR;
2721    Mutex::Autolock lock(mOfflinePpLock);
2722
2723    LOGD("pInputBuffer is %p frame number %d", pInputBuffer, frameNumber);
2724    if (NULL == buffer || NULL == metadata) {
2725        LOGE("Invalid buffer/metadata in channel request");
2726        return BAD_VALUE;
2727    }
2728
2729    PpInfo ppInfo;
2730    memset(&ppInfo, 0, sizeof(ppInfo));
2731    ppInfo.frameNumber = frameNumber;
2732    ppInfo.offlinePpFlag = false;
2733    if (mBypass && !pInputBuffer ) {
2734        ppInfo.offlinePpFlag = needsFramePostprocessing(metadata);
2735        ppInfo.output = buffer;
2736        mOfflinePpInfoList.push_back(ppInfo);
2737    }
2738
2739    LOGD("offlinePpFlag is %d", ppInfo.offlinePpFlag);
2740    needMetadata = ppInfo.offlinePpFlag;
2741    if (!ppInfo.offlinePpFlag) {
2742        // regular request
2743        return QCamera3ProcessingChannel::request(buffer, frameNumber,
2744                pInputBuffer, metadata, indexUsed);
2745    } else {
2746        if(!m_bIsActive) {
2747            rc = start();
2748            if (NO_ERROR != rc)
2749                return rc;
2750        } else {
2751            LOGD("Request on an existing stream");
2752        }
2753
2754        //we need to send this frame through the CPP
2755        //Allocate heap memory, then buf done on the buffer
2756        uint32_t bufIdx;
2757        if (mFreeHeapBufferList.empty()) {
2758            rc = mMemory.allocateOne(mFrameLen);
2759            if (rc < 0) {
2760                LOGE("Failed allocating heap buffer. Fatal");
2761                return BAD_VALUE;
2762            } else {
2763                bufIdx = (uint32_t)rc;
2764            }
2765        } else {
2766            bufIdx = *(mFreeHeapBufferList.begin());
2767            mFreeHeapBufferList.erase(mFreeHeapBufferList.begin());
2768        }
2769
2770        /* Configure and start postproc if necessary */
2771        reprocess_config_t reproc_cfg;
2772        cam_dimension_t dim;
2773        memset(&reproc_cfg, 0, sizeof(reprocess_config_t));
2774        memset(&dim, 0, sizeof(dim));
2775        mStreams[0]->getFrameDimension(dim);
2776        setReprocConfig(reproc_cfg, NULL, metadata, mStreamFormat, dim);
2777
2778        // Start postprocessor without input buffer
2779        startPostProc(reproc_cfg);
2780
2781        LOGD("erasing %d", bufIdx);
2782
2783        mMemory.markFrameNumber(bufIdx, frameNumber);
2784        indexUsed = bufIdx;
2785        mStreams[0]->bufDone(bufIdx);
2786
2787    }
2788    return rc;
2789}
2790
2791/*===========================================================================
2792 * FUNCTION   : streamCbRoutine
2793 *
2794 * DESCRIPTION:
2795 *
2796 * PARAMETERS :
2797 * @super_frame : the super frame with filled buffer
2798 * @stream      : stream on which the buffer was requested and filled
2799 *
2800 * RETURN     : none
2801 *==========================================================================*/
2802void QCamera3YUVChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
2803        QCamera3Stream *stream)
2804{
2805    ATRACE_CALL();
2806    uint8_t frameIndex;
2807    int32_t resultFrameNumber;
2808
2809    if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) {
2810        LOGE("Error with the stream callback");
2811        return;
2812    }
2813
2814    frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
2815    if(frameIndex >= mNumBufs) {
2816         LOGE("Error, Invalid index for buffer");
2817         stream->bufDone(frameIndex);
2818         return;
2819    }
2820
2821    if (mBypass) {
2822        List<PpInfo>::iterator ppInfo;
2823
2824        Mutex::Autolock lock(mOfflinePpLock);
2825        resultFrameNumber = mMemory.getFrameNumber(frameIndex);
2826        for (ppInfo = mOfflinePpInfoList.begin();
2827                ppInfo != mOfflinePpInfoList.end(); ppInfo++) {
2828            if (ppInfo->frameNumber == (uint32_t)resultFrameNumber) {
2829                break;
2830            }
2831        }
2832        LOGD("frame index %d, frame number %d", frameIndex, resultFrameNumber);
2833        //check the reprocessing required flag against the frame number
2834        if (ppInfo == mOfflinePpInfoList.end()) {
2835            LOGE("Error, request for frame number is a reprocess.");
2836            stream->bufDone(frameIndex);
2837            return;
2838        }
2839
2840        if (IS_BUFFER_ERROR(super_frame->bufs[0]->flags)) {
2841            mChannelCbBufErr(this, resultFrameNumber,
2842                            CAMERA3_BUFFER_STATUS_ERROR, mUserData);
2843        }
2844
2845        if (ppInfo->offlinePpFlag) {
2846            mm_camera_super_buf_t *frame =
2847                    (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
2848            if (frame == NULL) {
2849                LOGE("Error allocating memory to save received_frame structure.");
2850                if(stream) {
2851                    stream->bufDone(frameIndex);
2852                }
2853                return;
2854            }
2855
2856            *frame = *super_frame;
2857            m_postprocessor.processData(frame, ppInfo->output, resultFrameNumber);
2858            free(super_frame);
2859            return;
2860        } else {
2861            if (ppInfo != mOfflinePpInfoList.begin()) {
2862                // There is pending reprocess buffer, cache current buffer
2863                if (ppInfo->callback_buffer != NULL) {
2864                    LOGE("Fatal: cached callback_buffer is already present");
2865                }
2866                ppInfo->callback_buffer = super_frame;
2867                return;
2868            } else {
2869                mOfflinePpInfoList.erase(ppInfo);
2870            }
2871        }
2872    }
2873
2874    QCamera3ProcessingChannel::streamCbRoutine(super_frame, stream);
2875    return;
2876}
2877
2878/*===========================================================================
2879 * FUNCTION   : reprocessCbRoutine
2880 *
2881 * DESCRIPTION: callback function for the reprocessed frame. This frame now
2882 *              should be returned to the framework. This same callback is
2883 *              used during input reprocessing or offline postprocessing
2884 *
2885 * PARAMETERS :
2886 * @resultBuffer      : buffer containing the reprocessed data
2887 * @resultFrameNumber : frame number on which the buffer was requested
2888 *
2889 * RETURN     : NONE
2890 *
2891 *==========================================================================*/
2892void QCamera3YUVChannel::reprocessCbRoutine(buffer_handle_t *resultBuffer,
2893        uint32_t resultFrameNumber)
2894{
2895    LOGD("E: frame number %d", resultFrameNumber);
2896    Vector<mm_camera_super_buf_t *> pendingCbs;
2897
2898    /* release the input buffer and input metadata buffer if used */
2899    if (0 > mMemory.getHeapBufferIndex(resultFrameNumber)) {
2900        /* mOfflineMemory and mOfflineMetaMemory used only for input reprocessing */
2901        int32_t rc = releaseOfflineMemory(resultFrameNumber);
2902        if (NO_ERROR != rc) {
2903            LOGE("Error releasing offline memory rc = %d", rc);
2904        }
2905        /* Since reprocessing is done, send the callback to release the input buffer */
2906        if (mChannelCB) {
2907            mChannelCB(NULL, NULL, resultFrameNumber, true, mUserData);
2908        }
2909    }
2910
2911    if (mBypass) {
2912        int32_t rc = handleOfflinePpCallback(resultFrameNumber, pendingCbs);
2913        if (rc != NO_ERROR) {
2914            return;
2915        }
2916    }
2917
2918    issueChannelCb(resultBuffer, resultFrameNumber);
2919
2920    // Call all pending callbacks to return buffers
2921    for (size_t i = 0; i < pendingCbs.size(); i++) {
2922        QCamera3ProcessingChannel::streamCbRoutine(
2923                pendingCbs[i], mStreams[0]);
2924    }
2925
2926}
2927
2928/*===========================================================================
2929 * FUNCTION   : needsFramePostprocessing
2930 *
2931 * DESCRIPTION:
2932 *
2933 * PARAMETERS :
2934 *
2935 * RETURN     :
2936 *  TRUE if frame needs to be postprocessed
2937 *  FALSE is frame does not need to be postprocessed
2938 *
2939 *==========================================================================*/
2940bool QCamera3YUVChannel::needsFramePostprocessing(metadata_buffer_t *meta)
2941{
2942    bool ppNeeded = false;
2943
2944    //sharpness
2945    IF_META_AVAILABLE(cam_edge_application_t, edgeMode,
2946            CAM_INTF_META_EDGE_MODE, meta) {
2947        mEdgeMode = *edgeMode;
2948    }
2949
2950    //wnr
2951    IF_META_AVAILABLE(uint32_t, noiseRedMode,
2952            CAM_INTF_META_NOISE_REDUCTION_MODE, meta) {
2953        mNoiseRedMode = *noiseRedMode;
2954    }
2955
2956    //crop region
2957    IF_META_AVAILABLE(cam_crop_region_t, scalerCropRegion,
2958            CAM_INTF_META_SCALER_CROP_REGION, meta) {
2959        mCropRegion = *scalerCropRegion;
2960    }
2961
2962    if ((CAM_EDGE_MODE_OFF != mEdgeMode.edge_mode) &&
2963            (CAM_EDGE_MODE_ZERO_SHUTTER_LAG != mEdgeMode.edge_mode)) {
2964        ppNeeded = true;
2965    }
2966    if ((CAM_NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG != mNoiseRedMode) &&
2967            (CAM_NOISE_REDUCTION_MODE_OFF != mNoiseRedMode) &&
2968            (CAM_NOISE_REDUCTION_MODE_MINIMAL != mNoiseRedMode)) {
2969        ppNeeded = true;
2970    }
2971    if ((mCropRegion.width < (int32_t)mCamera3Stream->width) ||
2972            (mCropRegion.height < (int32_t)mCamera3Stream->height)) {
2973        ppNeeded = true;
2974    }
2975
2976    return ppNeeded;
2977}
2978
2979/*===========================================================================
2980 * FUNCTION   : handleOfflinePpCallback
2981 *
2982 * DESCRIPTION: callback function for the reprocessed frame from offline
2983 *              postprocessing.
2984 *
2985 * PARAMETERS :
2986 * @resultFrameNumber : frame number on which the buffer was requested
2987 * @pendingCbs        : pending buffers to be returned first
2988 *
2989 * RETURN     : int32_t type of status
2990 *              NO_ERROR  -- success
2991 *              none-zero failure code
2992 *==========================================================================*/
2993int32_t QCamera3YUVChannel::handleOfflinePpCallback(uint32_t resultFrameNumber,
2994            Vector<mm_camera_super_buf_t *>& pendingCbs)
2995{
2996    Mutex::Autolock lock(mOfflinePpLock);
2997    List<PpInfo>::iterator ppInfo;
2998
2999    for (ppInfo = mOfflinePpInfoList.begin();
3000            ppInfo != mOfflinePpInfoList.end(); ppInfo++) {
3001        if (ppInfo->frameNumber == resultFrameNumber) {
3002            break;
3003        }
3004    }
3005
3006    if (ppInfo == mOfflinePpInfoList.end()) {
3007        LOGI("Request of frame number %d is reprocessing",
3008                 resultFrameNumber);
3009        return NO_ERROR;
3010    } else if (ppInfo != mOfflinePpInfoList.begin()) {
3011        LOGE("callback for frame number %d should be head of list",
3012                 resultFrameNumber);
3013        return BAD_VALUE;
3014    }
3015
3016    if (ppInfo->offlinePpFlag) {
3017        // Need to get the input buffer frame index from the
3018        // mMemory object and add that to the free heap buffers list.
3019        int32_t bufferIndex =
3020                mMemory.getHeapBufferIndex(resultFrameNumber);
3021        if (bufferIndex < 0) {
3022            LOGE("Fatal %d: no buffer index for frame number %d",
3023                     bufferIndex, resultFrameNumber);
3024            return BAD_VALUE;
3025        }
3026        mMemory.markFrameNumber(bufferIndex, -1);
3027        mFreeHeapBufferList.push_back(bufferIndex);
3028        //Move heap buffer into free pool and invalidate the frame number
3029        ppInfo = mOfflinePpInfoList.erase(ppInfo);
3030
3031        // Return pending buffer callbacks
3032        while (ppInfo != mOfflinePpInfoList.end() &&
3033                !ppInfo->offlinePpFlag && ppInfo->callback_buffer) {
3034
3035            // Call stream callbacks for cached buffers
3036            pendingCbs.push_back(ppInfo->callback_buffer);
3037
3038            ppInfo = mOfflinePpInfoList.erase(ppInfo);
3039        }
3040
3041    } else {
3042        LOGE("Fatal: request of frame number %d doesn't need"
3043                " offline postprocessing. However there is"
3044                " reprocessing callback.",
3045                resultFrameNumber);
3046        return BAD_VALUE;
3047    }
3048
3049    return NO_ERROR;
3050}
3051
3052/*===========================================================================
3053 * FUNCTION   : getReprocessType
3054 *
3055 * DESCRIPTION: get the type of reprocess output supported by this channel
3056 *
3057 * PARAMETERS : NONE
3058 *
3059 * RETURN     : reprocess_type_t : type of reprocess
3060 *==========================================================================*/
3061reprocess_type_t QCamera3YUVChannel::getReprocessType()
3062{
3063    return REPROCESS_TYPE_YUV;
3064}
3065
3066/* QCamera3PicChannel methods */
3067
3068/*===========================================================================
3069 * FUNCTION   : jpegEvtHandle
3070 *
3071 * DESCRIPTION: Function registerd to mm-jpeg-interface to handle jpeg events.
3072                Construct result payload and call mChannelCb to deliver buffer
3073                to framework.
3074 *
3075 * PARAMETERS :
3076 *   @status    : status of jpeg job
3077 *   @client_hdl: jpeg client handle
3078 *   @jobId     : jpeg job Id
3079 *   @p_ouput   : ptr to jpeg output result struct
3080 *   @userdata  : user data ptr
3081 *
3082 * RETURN     : none
3083 *==========================================================================*/
3084void QCamera3PicChannel::jpegEvtHandle(jpeg_job_status_t status,
3085                                              uint32_t /*client_hdl*/,
3086                                              uint32_t jobId,
3087                                              mm_jpeg_output_t *p_output,
3088                                              void *userdata)
3089{
3090    ATRACE_CALL();
3091    buffer_handle_t *resultBuffer = NULL;
3092    buffer_handle_t *jpegBufferHandle = NULL;
3093    int resultStatus = CAMERA3_BUFFER_STATUS_OK;
3094    camera3_stream_buffer_t result;
3095    camera3_jpeg_blob_t jpegHeader;
3096
3097    KPI_ATRACE_INT("SNAPSHOT", 0);
3098    QCamera3PicChannel *obj = (QCamera3PicChannel *)userdata;
3099    if (obj) {
3100        //Construct payload for process_capture_result. Call mChannelCb
3101
3102        qcamera_hal3_jpeg_data_t *job = obj->m_postprocessor.findJpegJobByJobId(jobId);
3103
3104        if ((job == NULL) || (status == JPEG_JOB_STATUS_ERROR)) {
3105            LOGE("Error in jobId: (%d) with status: %d", jobId, status);
3106            resultStatus = CAMERA3_BUFFER_STATUS_ERROR;
3107        }
3108
3109        if (NULL != job) {
3110            uint32_t bufIdx = (uint32_t)job->jpeg_settings->out_buf_index;
3111            LOGD("jpeg out_buf_index: %d", bufIdx);
3112
3113            //Construct jpeg transient header of type camera3_jpeg_blob_t
3114            //Append at the end of jpeg image of buf_filled_len size
3115
3116            jpegHeader.jpeg_blob_id = CAMERA3_JPEG_BLOB_ID;
3117            if (JPEG_JOB_STATUS_DONE == status) {
3118                jpegHeader.jpeg_size = (uint32_t)p_output->buf_filled_len;
3119                char* jpeg_buf = (char *)p_output->buf_vaddr;
3120
3121                ssize_t maxJpegSize = -1;
3122
3123                // Gralloc buffer may have additional padding for 4K page size
3124                // Follow size guidelines based on spec since framework relies
3125                // on that to reach end of buffer and with it the header
3126
3127                //Handle same as resultBuffer, but for readablity
3128                jpegBufferHandle =
3129                        (buffer_handle_t *)obj->mMemory.getBufferHandle(bufIdx);
3130
3131                if (NULL != jpegBufferHandle) {
3132                    maxJpegSize = ((private_handle_t*)(*jpegBufferHandle))->width;
3133                    if (maxJpegSize > obj->mMemory.getSize(bufIdx)) {
3134                        maxJpegSize = obj->mMemory.getSize(bufIdx);
3135                    }
3136
3137                    size_t jpeg_eof_offset =
3138                            (size_t)(maxJpegSize - (ssize_t)sizeof(jpegHeader));
3139                    char *jpeg_eof = &jpeg_buf[jpeg_eof_offset];
3140                    memcpy(jpeg_eof, &jpegHeader, sizeof(jpegHeader));
3141                    obj->mMemory.cleanInvalidateCache(bufIdx);
3142                    bool jpegDump = false;
3143                    char prop[PROPERTY_VALUE_MAX];
3144                    property_get("persist.camera.jpeg.dump", prop, "0");
3145                    jpegDump = atoi(prop);
3146                    if (jpegDump) {
3147                        char buf[FILENAME_MAX];
3148                        char timeBuf[FILENAME_MAX];
3149                        memset(buf, 0, sizeof(buf));
3150                        memset(timeBuf, 0, sizeof(timeBuf));
3151                        time_t current_time;
3152                        struct tm * timeinfo;
3153                        time (&current_time);
3154                        timeinfo = localtime (&current_time);
3155                        if (timeinfo != NULL) {
3156                            /* Consistent naming for Jpeg+meta+raw: meta name */
3157                            strftime (timeBuf, sizeof(timeBuf),
3158                                    QCAMERA_DUMP_FRM_LOCATION"IMG_%Y%m%d_%H%M%S", timeinfo);
3159                            /* Consistent naming for Jpeg+meta+raw: meta name end*/
3160                        }
3161                        String8 filePath(timeBuf);
3162                        snprintf(buf, sizeof(buf), "_%d.jpg",
3163                                obj->mMemory.getFrameNumber(bufIdx));
3164                        filePath.append(buf);
3165                        int file_fd = open(filePath.string(), O_RDWR | O_CREAT, 0777);
3166                        ssize_t written_len = 0;
3167                        if (file_fd >= 0) {
3168                            fchmod(file_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
3169                            written_len += write(file_fd, jpeg_buf,
3170                                    (size_t)maxJpegSize);
3171                            LOGI("written number of bytes %ld attempted: %ld\n", written_len,
3172                                maxJpegSize);
3173                            close(file_fd);
3174                        } else {
3175                            LOGE("failed to open file to dump image");
3176                        }
3177
3178                    }
3179                } else {
3180                    LOGE("JPEG buffer not found and index: %d",
3181                            bufIdx);
3182                    resultStatus = CAMERA3_BUFFER_STATUS_ERROR;
3183                }
3184            }
3185
3186            ////Use below data to issue framework callback
3187            resultBuffer =
3188                    (buffer_handle_t *)obj->mMemory.getBufferHandle(bufIdx);
3189            int32_t resultFrameNumber = obj->mMemory.getFrameNumber(bufIdx);
3190            int32_t rc = obj->mMemory.unregisterBuffer(bufIdx);
3191            if (NO_ERROR != rc) {
3192                LOGE("Error %d unregistering stream buffer %d",
3193                     rc, bufIdx);
3194            }
3195
3196            result.stream = obj->mCamera3Stream;
3197            result.buffer = resultBuffer;
3198            result.status = resultStatus;
3199            result.acquire_fence = -1;
3200            result.release_fence = -1;
3201
3202            // Release any snapshot buffers before calling
3203            // the user callback. The callback can potentially
3204            // unblock pending requests to snapshot stream.
3205            int32_t snapshotIdx = -1;
3206            mm_camera_super_buf_t* src_frame = NULL;
3207
3208            if (job->src_reproc_frame)
3209                src_frame = job->src_reproc_frame;
3210            else
3211                src_frame = job->src_frame;
3212
3213            if (src_frame) {
3214                if (obj->mStreams[0]->getMyHandle() ==
3215                        src_frame->bufs[0]->stream_id) {
3216                    snapshotIdx = (int32_t)src_frame->bufs[0]->buf_idx;
3217                    if (0 <= snapshotIdx) {
3218                        Mutex::Autolock lock(obj->mFreeBuffersLock);
3219                        obj->mFreeBufferList.push_back((uint32_t)snapshotIdx);
3220                    }
3221                }
3222            }
3223
3224            LOGI("Issue Jpeg Callback frameNumber = %d status = %d",
3225                    resultFrameNumber, resultStatus);
3226            if (obj->mChannelCB) {
3227                obj->mChannelCB(NULL,
3228                        &result,
3229                        (uint32_t)resultFrameNumber,
3230                        false,
3231                        obj->mUserData);
3232            }
3233
3234            // release internal data for jpeg job
3235            if ((NULL != job->fwk_frame) || (NULL != job->fwk_src_buffer)) {
3236                /* unregister offline input buffer */
3237                int32_t inputBufIndex =
3238                        obj->mOfflineMemory.getGrallocBufferIndex((uint32_t)resultFrameNumber);
3239                if (0 <= inputBufIndex) {
3240                    rc = obj->mOfflineMemory.unregisterBuffer(inputBufIndex);
3241                } else {
3242                    LOGE("could not find the input buf index, frame number %d",
3243                             resultFrameNumber);
3244                }
3245                if (NO_ERROR != rc) {
3246                    LOGE("Error %d unregistering input buffer %d",
3247                             rc, bufIdx);
3248                }
3249
3250                /* unregister offline meta buffer */
3251                int32_t metaBufIndex =
3252                        obj->mOfflineMetaMemory.getHeapBufferIndex((uint32_t)resultFrameNumber);
3253                if (0 <= metaBufIndex) {
3254                    Mutex::Autolock lock(obj->mFreeOfflineMetaBuffersLock);
3255                    obj->mFreeOfflineMetaBuffersList.push_back((uint32_t)metaBufIndex);
3256                } else {
3257                    LOGE("could not find the input meta buf index, frame number %d",
3258                             resultFrameNumber);
3259                }
3260            }
3261            obj->m_postprocessor.releaseOfflineBuffers(false);
3262            obj->m_postprocessor.releaseJpegJobData(job);
3263            free(job);
3264        }
3265
3266        obj->resetCppPerfParam();
3267        return;
3268        // }
3269    } else {
3270        LOGE("Null userdata in jpeg callback");
3271    }
3272}
3273
3274QCamera3PicChannel::QCamera3PicChannel(uint32_t cam_handle,
3275                    uint32_t channel_handle,
3276                    mm_camera_ops_t *cam_ops,
3277                    channel_cb_routine cb_routine,
3278                    channel_cb_buffer_err cb_buf_err,
3279                    cam_padding_info_t *paddingInfo,
3280                    void *userData,
3281                    camera3_stream_t *stream,
3282                    cam_feature_mask_t postprocess_mask,
3283                    __unused bool is4KVideo,
3284                    bool isInputStreamConfigured,
3285                    QCamera3Channel *metadataChannel,
3286                    uint32_t numBuffers) :
3287                        QCamera3ProcessingChannel(cam_handle, channel_handle,
3288                                cam_ops, cb_routine, cb_buf_err, paddingInfo, userData,
3289                                stream, CAM_STREAM_TYPE_SNAPSHOT,
3290                                postprocess_mask, metadataChannel, numBuffers),
3291                        mNumSnapshotBufs(0),
3292                        mInputBufferHint(isInputStreamConfigured),
3293                        mYuvMemory(NULL),
3294                        mFrameLen(0)
3295{
3296    QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
3297    m_max_pic_dim = hal_obj->calcMaxJpegDim();
3298    mYuvWidth = stream->width;
3299    mYuvHeight = stream->height;
3300    mStreamType = CAM_STREAM_TYPE_SNAPSHOT;
3301    mPendingLiveSnapshotFrames = 0;
3302    // Use same pixelformat for 4K video case
3303    mStreamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_SNAPSHOT,
3304            stream->width, stream->height);
3305    int32_t rc = m_postprocessor.initJpeg(jpegEvtHandle, &m_max_pic_dim, this);
3306    if (rc != 0) {
3307        LOGE("Init Postprocessor failed");
3308    }
3309}
3310
3311/*===========================================================================
3312 * FUNCTION   : flush
3313 *
3314 * DESCRIPTION: flush pic channel, which will stop all processing within, including
3315 *              the reprocessing channel in postprocessor and YUV stream.
3316 *
3317 * PARAMETERS : none
3318 *
3319 * RETURN     : int32_t type of status
3320 *              NO_ERROR  -- success
3321 *              none-zero failure code
3322 *==========================================================================*/
3323int32_t QCamera3PicChannel::flush()
3324{
3325    int32_t rc = NO_ERROR;
3326    if(!m_bIsActive) {
3327        LOGE("Attempt to flush inactive channel");
3328        return NO_INIT;
3329    }
3330
3331    rc = m_postprocessor.flush();
3332    if (rc == 0) {
3333        LOGE("Postprocessor flush failed, rc = %d", rc);
3334        return rc;
3335    }
3336
3337    if (0 < mOfflineMetaMemory.getCnt()) {
3338        mOfflineMetaMemory.deallocate();
3339    }
3340    if (0 < mOfflineMemory.getCnt()) {
3341        mOfflineMemory.unregisterBuffers();
3342    }
3343    Mutex::Autolock lock(mFreeBuffersLock);
3344    mFreeBufferList.clear();
3345    for (uint32_t i = 0; i < mCamera3Stream->max_buffers; i++) {
3346        mFreeBufferList.push_back(i);
3347    }
3348    return rc;
3349}
3350
3351
3352QCamera3PicChannel::~QCamera3PicChannel()
3353{
3354}
3355
3356int32_t QCamera3PicChannel::initialize(cam_is_type_t isType)
3357{
3358    int32_t rc = NO_ERROR;
3359    cam_dimension_t streamDim;
3360    cam_stream_type_t streamType;
3361    cam_format_t streamFormat;
3362
3363    if (NULL == mCamera3Stream) {
3364        LOGE("Camera stream uninitialized");
3365        return NO_INIT;
3366    }
3367
3368    if (1 <= m_numStreams) {
3369        // Only one stream per channel supported in v3 Hal
3370        return NO_ERROR;
3371    }
3372
3373    mIsType = isType;
3374    streamType = mStreamType;
3375    streamFormat = mStreamFormat;
3376    streamDim.width = (int32_t)mYuvWidth;
3377    streamDim.height = (int32_t)mYuvHeight;
3378
3379    mNumSnapshotBufs = mCamera3Stream->max_buffers;
3380    rc = QCamera3Channel::addStream(streamType, streamFormat, streamDim,
3381            ROTATE_0, (uint8_t)mCamera3Stream->max_buffers, mPostProcMask,
3382            mIsType);
3383
3384    if (NO_ERROR != rc) {
3385        LOGE("Initialize failed, rc = %d", rc);
3386        return rc;
3387    }
3388
3389    /* initialize offline meta memory for input reprocess */
3390    rc = QCamera3ProcessingChannel::initialize(isType);
3391    if (NO_ERROR != rc) {
3392        LOGE("Processing Channel initialize failed, rc = %d",
3393                 rc);
3394    }
3395
3396    return rc;
3397}
3398
3399/*===========================================================================
3400 * FUNCTION   : request
3401 *
3402 * DESCRIPTION: handle the request - either with an input buffer or a direct
3403 *              output request
3404 *
3405 * PARAMETERS :
3406 * @buffer       : pointer to the output buffer
3407 * @frameNumber  : frame number of the request
3408 * @pInputBuffer : pointer to input buffer if an input request
3409 * @metadata     : parameters associated with the request
3410 *
3411 * RETURN     : 0 on a success start of capture
3412 *              -EINVAL on invalid input
3413 *              -ENODEV on serious error
3414 *==========================================================================*/
3415int32_t QCamera3PicChannel::request(buffer_handle_t *buffer,
3416        uint32_t frameNumber,
3417        camera3_stream_buffer_t *pInputBuffer,
3418        metadata_buffer_t *metadata, int &indexUsed)
3419{
3420    ATRACE_CALL();
3421    //FIX ME: Return buffer back in case of failures below.
3422
3423    int32_t rc = NO_ERROR;
3424
3425    reprocess_config_t reproc_cfg;
3426    cam_dimension_t dim;
3427    memset(&reproc_cfg, 0, sizeof(reprocess_config_t));
3428    //make sure to set the correct input stream dim in case of YUV size override
3429    //and recalculate the plane info
3430    dim.width = (int32_t)mYuvWidth;
3431    dim.height = (int32_t)mYuvHeight;
3432    setReprocConfig(reproc_cfg, pInputBuffer, metadata, mStreamFormat, dim);
3433
3434    // Picture stream has already been started before any request comes in
3435    if (!m_bIsActive) {
3436        LOGE("Channel not started!!");
3437        return NO_INIT;
3438    }
3439
3440    int index = mMemory.getMatchBufIndex((void*)buffer);
3441
3442    if(index < 0) {
3443        rc = registerBuffer(buffer, mIsType);
3444        if (NO_ERROR != rc) {
3445            LOGE("On-the-fly buffer registration failed %d",
3446                     rc);
3447            return rc;
3448        }
3449
3450        index = mMemory.getMatchBufIndex((void*)buffer);
3451        if (index < 0) {
3452            LOGE("Could not find object among registered buffers");
3453            return DEAD_OBJECT;
3454        }
3455    }
3456    LOGD("buffer index %d, frameNumber: %u", index, frameNumber);
3457
3458    rc = mMemory.markFrameNumber((uint32_t)index, frameNumber);
3459
3460    // Start postprocessor
3461    startPostProc(reproc_cfg);
3462
3463    // Only set the perf mode for online cpp processing
3464    if (reproc_cfg.reprocess_type == REPROCESS_TYPE_NONE) {
3465        setCppPerfParam();
3466    }
3467
3468    // Queue jpeg settings
3469    rc = queueJpegSetting((uint32_t)index, metadata);
3470
3471    if (pInputBuffer == NULL) {
3472        Mutex::Autolock lock(mFreeBuffersLock);
3473        uint32_t bufIdx;
3474        if (mFreeBufferList.empty()) {
3475            rc = mYuvMemory->allocateOne(mFrameLen);
3476            if (rc < 0) {
3477                LOGE("Failed to allocate heap buffer. Fatal");
3478                return rc;
3479            } else {
3480                bufIdx = (uint32_t)rc;
3481            }
3482        } else {
3483            List<uint32_t>::iterator it = mFreeBufferList.begin();
3484            bufIdx = *it;
3485            mFreeBufferList.erase(it);
3486        }
3487        mYuvMemory->markFrameNumber(bufIdx, frameNumber);
3488        mStreams[0]->bufDone(bufIdx);
3489        indexUsed = bufIdx;
3490    } else {
3491        qcamera_fwk_input_pp_data_t *src_frame = NULL;
3492        src_frame = (qcamera_fwk_input_pp_data_t *)calloc(1,
3493                sizeof(qcamera_fwk_input_pp_data_t));
3494        if (src_frame == NULL) {
3495            LOGE("No memory for src frame");
3496            return NO_MEMORY;
3497        }
3498        rc = setFwkInputPPData(src_frame, pInputBuffer, &reproc_cfg, metadata,
3499                NULL /*fwk output buffer*/, frameNumber);
3500        if (NO_ERROR != rc) {
3501            LOGE("Error %d while setting framework input PP data", rc);
3502            free(src_frame);
3503            return rc;
3504        }
3505        LOGH("Post-process started");
3506        m_postprocessor.processData(src_frame);
3507    }
3508    return rc;
3509}
3510
3511
3512
3513/*===========================================================================
3514 * FUNCTION   : dataNotifyCB
3515 *
3516 * DESCRIPTION: Channel Level callback used for super buffer data notify.
3517 *              This function is registered with mm-camera-interface to handle
3518 *              data notify
3519 *
3520 * PARAMETERS :
3521 *   @recvd_frame   : stream frame received
3522 *   userdata       : user data ptr
3523 *
3524 * RETURN     : none
3525 *==========================================================================*/
3526void QCamera3PicChannel::dataNotifyCB(mm_camera_super_buf_t *recvd_frame,
3527                                 void *userdata)
3528{
3529    ATRACE_CALL();
3530    LOGD("E\n");
3531    QCamera3PicChannel *channel = (QCamera3PicChannel *)userdata;
3532
3533    if (channel == NULL) {
3534        LOGE("invalid channel pointer");
3535        return;
3536    }
3537
3538    if(channel->m_numStreams != 1) {
3539        LOGE("Error: Bug: This callback assumes one stream per channel");
3540        return;
3541    }
3542
3543
3544    if(channel->mStreams[0] == NULL) {
3545        LOGE("Error: Invalid Stream object");
3546        return;
3547    }
3548
3549    channel->QCamera3PicChannel::streamCbRoutine(recvd_frame, channel->mStreams[0]);
3550
3551    LOGD("X\n");
3552    return;
3553}
3554
3555/*===========================================================================
3556 * FUNCTION   : streamCbRoutine
3557 *
3558 * DESCRIPTION:
3559 *
3560 * PARAMETERS :
3561 * @super_frame : the super frame with filled buffer
3562 * @stream      : stream on which the buffer was requested and filled
3563 *
3564 * RETURN     : none
3565 *==========================================================================*/
3566void QCamera3PicChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
3567                            QCamera3Stream *stream)
3568{
3569    ATRACE_CALL();
3570    //TODO
3571    //Used only for getting YUV. Jpeg callback will be sent back from channel
3572    //directly to HWI. Refer to func jpegEvtHandle
3573
3574    //Got the yuv callback. Calling yuv callback handler in PostProc
3575    uint8_t frameIndex;
3576    mm_camera_super_buf_t* frame = NULL;
3577    cam_dimension_t dim;
3578    cam_frame_len_offset_t offset;
3579
3580    memset(&dim, 0, sizeof(dim));
3581    memset(&offset, 0, sizeof(cam_frame_len_offset_t));
3582
3583    if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) {
3584        LOGE("Error with the stream callback");
3585        return;
3586    }
3587
3588    frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
3589    LOGD("recvd buf_idx: %u for further processing",
3590         (uint32_t)frameIndex);
3591    if(frameIndex >= mNumSnapshotBufs) {
3592         LOGE("Error, Invalid index for buffer");
3593         if(stream) {
3594             Mutex::Autolock lock(mFreeBuffersLock);
3595             mFreeBufferList.push_back(frameIndex);
3596             stream->bufDone(frameIndex);
3597         }
3598         return;
3599    }
3600
3601    frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
3602    if (frame == NULL) {
3603       LOGE("Error allocating memory to save received_frame structure.");
3604       if(stream) {
3605           Mutex::Autolock lock(mFreeBuffersLock);
3606           mFreeBufferList.push_back(frameIndex);
3607           stream->bufDone(frameIndex);
3608       }
3609       return;
3610    }
3611    *frame = *super_frame;
3612    stream->getFrameDimension(dim);
3613    stream->getFrameOffset(offset);
3614    dumpYUV(frame->bufs[0], dim, offset, QCAMERA_DUMP_FRM_INPUT_REPROCESS);
3615
3616    if (IS_BUFFER_ERROR(super_frame->bufs[0]->flags)) {
3617        mChannelCbBufErr(this, mYuvMemory->getFrameNumber(frameIndex),
3618                            CAMERA3_BUFFER_STATUS_ERROR, mUserData);
3619    }
3620
3621    m_postprocessor.processData(frame);
3622    free(super_frame);
3623    return;
3624}
3625
3626QCamera3StreamMem* QCamera3PicChannel::getStreamBufs(uint32_t len)
3627{
3628    mYuvMemory = new QCamera3StreamMem(mCamera3Stream->max_buffers, false);
3629    if (!mYuvMemory) {
3630        LOGE("unable to create metadata memory");
3631        return NULL;
3632    }
3633    mFrameLen = len;
3634
3635    return mYuvMemory;
3636}
3637
3638void QCamera3PicChannel::putStreamBufs()
3639{
3640    QCamera3ProcessingChannel::putStreamBufs();
3641
3642    mYuvMemory->deallocate();
3643    delete mYuvMemory;
3644    mYuvMemory = NULL;
3645    mFreeBufferList.clear();
3646}
3647
3648int32_t QCamera3PicChannel::queueJpegSetting(uint32_t index, metadata_buffer_t *metadata)
3649{
3650    QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
3651    jpeg_settings_t *settings =
3652            (jpeg_settings_t *)malloc(sizeof(jpeg_settings_t));
3653
3654    if (!settings) {
3655        LOGE("out of memory allocating jpeg_settings");
3656        return -ENOMEM;
3657    }
3658
3659    memset(settings, 0, sizeof(jpeg_settings_t));
3660
3661    settings->out_buf_index = index;
3662
3663    settings->jpeg_orientation = 0;
3664    IF_META_AVAILABLE(int32_t, orientation, CAM_INTF_META_JPEG_ORIENTATION, metadata) {
3665        settings->jpeg_orientation = *orientation;
3666    }
3667
3668    settings->jpeg_quality = 85;
3669    IF_META_AVAILABLE(uint32_t, quality1, CAM_INTF_META_JPEG_QUALITY, metadata) {
3670        settings->jpeg_quality = (uint8_t) *quality1;
3671    }
3672
3673    IF_META_AVAILABLE(uint32_t, quality2, CAM_INTF_META_JPEG_THUMB_QUALITY, metadata) {
3674        settings->jpeg_thumb_quality = (uint8_t) *quality2;
3675    }
3676
3677    IF_META_AVAILABLE(cam_dimension_t, dimension, CAM_INTF_META_JPEG_THUMB_SIZE, metadata) {
3678        settings->thumbnail_size = *dimension;
3679    }
3680
3681    settings->gps_timestamp_valid = 0;
3682    IF_META_AVAILABLE(int64_t, timestamp, CAM_INTF_META_JPEG_GPS_TIMESTAMP, metadata) {
3683        settings->gps_timestamp = *timestamp;
3684        settings->gps_timestamp_valid = 1;
3685    }
3686
3687    settings->gps_coordinates_valid = 0;
3688    IF_META_AVAILABLE(double, coordinates, CAM_INTF_META_JPEG_GPS_COORDINATES, metadata) {
3689        memcpy(settings->gps_coordinates, coordinates, 3*sizeof(double));
3690        settings->gps_coordinates_valid = 1;
3691    }
3692
3693    IF_META_AVAILABLE(uint8_t, proc_methods, CAM_INTF_META_JPEG_GPS_PROC_METHODS, metadata) {
3694        memset(settings->gps_processing_method, 0,
3695                sizeof(settings->gps_processing_method));
3696        strlcpy(settings->gps_processing_method, (const char *)proc_methods,
3697                sizeof(settings->gps_processing_method));
3698    }
3699
3700    // Image description
3701    const char *eepromVersion = hal_obj->getEepromVersionInfo();
3702    const uint32_t *ldafCalib = hal_obj->getLdafCalib();
3703    if ((eepromVersion && strlen(eepromVersion)) ||
3704            ldafCalib) {
3705        int len = 0;
3706        settings->image_desc_valid = true;
3707        if (eepromVersion && strlen(eepromVersion)) {
3708            len = snprintf(settings->image_desc, sizeof(settings->image_desc),
3709                    "M:%s ", eepromVersion);
3710        }
3711        if (ldafCalib) {
3712            snprintf(settings->image_desc + len,
3713                    sizeof(settings->image_desc) - len, "L:%u-%u",
3714                    ldafCalib[0], ldafCalib[1]);
3715        }
3716    }
3717
3718    return m_postprocessor.processJpegSettingData(settings);
3719}
3720
3721
3722void QCamera3PicChannel::overrideYuvSize(uint32_t width, uint32_t height)
3723{
3724   mYuvWidth = width;
3725   mYuvHeight = height;
3726}
3727
3728/*===========================================================================
3729 * FUNCTION   : getReprocessType
3730 *
3731 * DESCRIPTION: get the type of reprocess output supported by this channel
3732 *
3733 * PARAMETERS : NONE
3734 *
3735 * RETURN     : reprocess_type_t : type of reprocess
3736 *==========================================================================*/
3737reprocess_type_t QCamera3PicChannel::getReprocessType()
3738{
3739    /* a picture channel could either use the postprocessor for reprocess+jpeg
3740       or only for reprocess */
3741    reprocess_type_t expectedReprocess;
3742    if (mPostProcMask == CAM_QCOM_FEATURE_NONE || mInputBufferHint) {
3743        expectedReprocess = REPROCESS_TYPE_JPEG;
3744    } else {
3745        expectedReprocess = REPROCESS_TYPE_NONE;
3746    }
3747    LOGH("expectedReprocess from Pic Channel is %d", expectedReprocess);
3748    return expectedReprocess;
3749}
3750
3751/*===========================================================================
3752 * FUNCTION   : setCppPerfParam
3753 *
3754 * DESCRIPTION: set the performance related stream params
3755 *
3756 * PARAMETERS : NONE
3757 *
3758 * RETURN     : NONE
3759 *==========================================================================*/
3760
3761void QCamera3PicChannel::setCppPerfParam()
3762{
3763    if (mPendingLiveSnapshotFrames == 0) {
3764        int32_t rc = 0;
3765        QCamera3Stream *pStream = mStreams[0];
3766        cam_stream_parm_buffer_t param;
3767        memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
3768        param.type = CAM_STREAM_PARAM_TYPE_REQUEST_OPS_MODE;
3769        param.perf_mode = CAM_PERF_SET;
3770        rc = pStream->setParameter(param);
3771        if (rc != NO_ERROR) {
3772            LOGE("%s: setParameter for CAM_PERF_SET failed",
3773                __func__);
3774        }
3775    }
3776    mPendingLiveSnapshotFrames++;
3777}
3778
3779/*===========================================================================
3780 * FUNCTION   : resetCppPerfParam
3781 *
3782 * DESCRIPTION: reset the performance related stream params
3783 *
3784 * PARAMETERS : NONE
3785 *
3786 * RETURN     : NONE
3787 *==========================================================================*/
3788
3789void QCamera3PicChannel::resetCppPerfParam()
3790{
3791    if (mPendingLiveSnapshotFrames > 0) {
3792        int32_t rc = NO_ERROR;
3793        QCamera3Stream *pStream = mStreams[0];
3794        cam_stream_parm_buffer_t param;
3795        memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
3796        param.type = CAM_STREAM_PARAM_TYPE_REQUEST_OPS_MODE;
3797        param.perf_mode = CAM_PERF_RESET;
3798        rc = pStream->setParameter(param);
3799        if (rc != NO_ERROR) {
3800            LOGE("%s: setParameter for CAM_PERF_RESET failed",
3801                __func__);
3802        }
3803        mPendingLiveSnapshotFrames--;
3804    }
3805}
3806
3807/*===========================================================================
3808 * FUNCTION   : timeoutFrame
3809 *
3810 * DESCRIPTION: Method to indicate to channel that a given frame has take too
3811 *              long to be generated
3812 *
3813 * PARAMETERS : framenumber indicating the framenumber of the buffer timingout
3814 *
3815 * RETURN     : int32_t type of status
3816 *              NO_ERROR  -- success
3817 *              none-zero failure code
3818 *==========================================================================*/
3819int32_t QCamera3PicChannel::timeoutFrame(uint32_t frameNumber)
3820{
3821    int32_t bufIdx;
3822
3823    bufIdx = mYuvMemory->getBufferIndex(frameNumber);
3824
3825    if (bufIdx < 0) {
3826        ALOGE("%s: Buffer not found for frame:%d", __func__, frameNumber);
3827        return -1;
3828    }
3829
3830    mStreams[0]->timeoutFrame(bufIdx);
3831
3832    return NO_ERROR;
3833}
3834
3835/*===========================================================================
3836 * FUNCTION   : QCamera3ReprocessChannel
3837 *
3838 * DESCRIPTION: constructor of QCamera3ReprocessChannel
3839 *
3840 * PARAMETERS :
3841 *   @cam_handle : camera handle
3842 *   @cam_ops    : ptr to camera ops table
3843 *   @pp_mask    : post-proccess feature mask
3844 *
3845 * RETURN     : none
3846 *==========================================================================*/
3847QCamera3ReprocessChannel::QCamera3ReprocessChannel(uint32_t cam_handle,
3848                                                 uint32_t channel_handle,
3849                                                 mm_camera_ops_t *cam_ops,
3850                                                 channel_cb_routine cb_routine,
3851                                                 channel_cb_buffer_err cb_buf_err,
3852                                                 cam_padding_info_t *paddingInfo,
3853                                                 cam_feature_mask_t postprocess_mask,
3854                                                 void *userData, void *ch_hdl) :
3855    /* In case of framework reprocessing, pproc and jpeg operations could be
3856     * parallelized by allowing 1 extra buffer for reprocessing output:
3857     * ch_hdl->getNumBuffers() + 1 */
3858    QCamera3Channel(cam_handle, channel_handle, cam_ops, cb_routine, cb_buf_err, paddingInfo,
3859                    postprocess_mask, userData,
3860                    ((QCamera3ProcessingChannel *)ch_hdl)->getNumBuffers()
3861                              + (MAX_REPROCESS_PIPELINE_STAGES - 1)),
3862    inputChHandle(ch_hdl),
3863    mOfflineBuffersIndex(-1),
3864    mFrameLen(0),
3865    mReprocessType(REPROCESS_TYPE_NONE),
3866    m_pSrcChannel(NULL),
3867    m_pMetaChannel(NULL),
3868    mMemory(NULL),
3869    mGrallocMemory(0),
3870    mReprocessPerfMode(false)
3871{
3872    memset(mSrcStreamHandles, 0, sizeof(mSrcStreamHandles));
3873    mOfflineBuffersIndex = mNumBuffers -1;
3874    mOfflineMetaIndex = (int32_t) (2*mNumBuffers -1);
3875}
3876
3877
3878/*===========================================================================
3879 * FUNCTION   : QCamera3ReprocessChannel
3880 *
3881 * DESCRIPTION: constructor of QCamera3ReprocessChannel
3882 *
3883 * PARAMETERS :
3884 *   @cam_handle : camera handle
3885 *   @cam_ops    : ptr to camera ops table
3886 *   @pp_mask    : post-proccess feature mask
3887 *
3888 * RETURN     : none
3889 *==========================================================================*/
3890int32_t QCamera3ReprocessChannel::initialize(cam_is_type_t isType)
3891{
3892    int32_t rc = NO_ERROR;
3893    mm_camera_channel_attr_t attr;
3894
3895    memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
3896    attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS;
3897    attr.max_unmatched_frames = 1;
3898
3899    m_handle = m_camOps->add_channel(m_camHandle,
3900                                      &attr,
3901                                      NULL,
3902                                      this);
3903    if (m_handle == 0) {
3904        LOGE("Add channel failed");
3905        return UNKNOWN_ERROR;
3906    }
3907
3908    mIsType = isType;
3909    return rc;
3910}
3911
3912/*===========================================================================
3913 * FUNCTION   : registerBuffer
3914 *
3915 * DESCRIPTION: register streaming buffer to the channel object
3916 *
3917 * PARAMETERS :
3918 *   @buffer     : buffer to be registered
3919 *   @isType     : the image stabilization type for the buffer
3920 *
3921 * RETURN     : int32_t type of status
3922 *              NO_ERROR  -- success
3923 *              none-zero failure code
3924 *==========================================================================*/
3925int32_t QCamera3ReprocessChannel::registerBuffer(buffer_handle_t *buffer,
3926        cam_is_type_t isType)
3927{
3928    ATRACE_CALL();
3929    int rc = 0;
3930    mIsType = isType;
3931    cam_stream_type_t streamType;
3932
3933    if (buffer == NULL) {
3934        LOGE("Error: Cannot register a NULL buffer");
3935        return BAD_VALUE;
3936    }
3937
3938    if ((uint32_t)mGrallocMemory.getCnt() > (mNumBuffers - 1)) {
3939        LOGE("Trying to register more buffers than initially requested");
3940        return BAD_VALUE;
3941    }
3942
3943    if (0 == m_numStreams) {
3944        rc = initialize(mIsType);
3945        if (rc != NO_ERROR) {
3946            LOGE("Couldn't initialize camera stream %d",
3947                     rc);
3948            return rc;
3949        }
3950    }
3951
3952    streamType = mStreams[0]->getMyType();
3953    rc = mGrallocMemory.registerBuffer(buffer, streamType);
3954    if (ALREADY_EXISTS == rc) {
3955        return NO_ERROR;
3956    } else if (NO_ERROR != rc) {
3957        LOGE("Buffer %p couldn't be registered %d", buffer, rc);
3958        return rc;
3959    }
3960
3961    return rc;
3962}
3963
3964/*===========================================================================
3965 * FUNCTION   : QCamera3ReprocessChannel
3966 *
3967 * DESCRIPTION: constructor of QCamera3ReprocessChannel
3968 *
3969 * PARAMETERS :
3970 *   @cam_handle : camera handle
3971 *   @cam_ops    : ptr to camera ops table
3972 *   @pp_mask    : post-proccess feature mask
3973 *
3974 * RETURN     : none
3975 *==========================================================================*/
3976void QCamera3ReprocessChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
3977                                  QCamera3Stream *stream)
3978{
3979    //Got the pproc data callback. Now send to jpeg encoding
3980    uint8_t frameIndex;
3981    uint32_t resultFrameNumber;
3982    mm_camera_super_buf_t* frame = NULL;
3983    QCamera3ProcessingChannel *obj = (QCamera3ProcessingChannel *)inputChHandle;
3984    cam_dimension_t dim;
3985    cam_frame_len_offset_t offset;
3986
3987    memset(&dim, 0, sizeof(dim));
3988    memset(&offset, 0, sizeof(cam_frame_len_offset_t));
3989    if(!super_frame) {
3990         LOGE("Invalid Super buffer");
3991         return;
3992    }
3993
3994    if(super_frame->num_bufs != 1) {
3995         LOGE("Multiple streams are not supported");
3996         return;
3997    }
3998    if(super_frame->bufs[0] == NULL ) {
3999         LOGE("Error, Super buffer frame does not contain valid buffer");
4000         return;
4001    }
4002    frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
4003
4004
4005    if (mReprocessType == REPROCESS_TYPE_JPEG) {
4006        resultFrameNumber =  mMemory->getFrameNumber(frameIndex);
4007        frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
4008        if (frame == NULL) {
4009           LOGE("Error allocating memory to save received_frame structure.");
4010           if(stream) {
4011               stream->bufDone(frameIndex);
4012           }
4013           return;
4014        }
4015        LOGI("bufIndex: %u recvd from post proc",
4016                 (uint32_t)frameIndex);
4017        *frame = *super_frame;
4018
4019        stream->getFrameDimension(dim);
4020        stream->getFrameOffset(offset);
4021        dumpYUV(frame->bufs[0], dim, offset, QCAMERA_DUMP_FRM_SNAPSHOT);
4022        /* Since reprocessing is done, send the callback to release the input buffer */
4023        if (mChannelCB) {
4024            mChannelCB(NULL, NULL, resultFrameNumber, true, mUserData);
4025        }
4026        obj->m_postprocessor.processPPData(frame);
4027    } else {
4028        buffer_handle_t *resultBuffer;
4029        frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
4030        resultBuffer = (buffer_handle_t *)mGrallocMemory.getBufferHandle(frameIndex);
4031        resultFrameNumber = mGrallocMemory.getFrameNumber(frameIndex);
4032        int32_t rc = stream->bufRelease(frameIndex);
4033        if (NO_ERROR != rc) {
4034            LOGE("Error %d releasing stream buffer %d",
4035                     rc, frameIndex);
4036        }
4037        rc = mGrallocMemory.unregisterBuffer(frameIndex);
4038        if (NO_ERROR != rc) {
4039            LOGE("Error %d unregistering stream buffer %d",
4040                     rc, frameIndex);
4041        }
4042        obj->reprocessCbRoutine(resultBuffer, resultFrameNumber);
4043
4044        obj->m_postprocessor.releaseOfflineBuffers(false);
4045        qcamera_hal3_pp_data_t *pp_job = obj->m_postprocessor.dequeuePPJob(resultFrameNumber);
4046        if (pp_job != NULL) {
4047            obj->m_postprocessor.releasePPJobData(pp_job);
4048        }
4049        free(pp_job);
4050    }
4051    resetToCamPerfNormal(resultFrameNumber);
4052    free(super_frame);
4053    return;
4054}
4055
4056/*===========================================================================
4057 * FUNCTION   : resetToCamPerfNormal
4058 *
4059 * DESCRIPTION: Set the perf mode to normal if all the priority frames
4060 *              have been reprocessed
4061 *
4062 * PARAMETERS :
4063 *      @frameNumber: Frame number of the reprocess completed frame
4064 *
4065 * RETURN     : QCamera3StreamMem *
4066 *==========================================================================*/
4067int32_t QCamera3ReprocessChannel::resetToCamPerfNormal(uint32_t frameNumber)
4068{
4069    int32_t rc = NO_ERROR;
4070    bool resetToPerfNormal = false;
4071    {
4072        Mutex::Autolock lock(mPriorityFramesLock);
4073        /* remove the priority frame number from the list */
4074        for (size_t i = 0; i < mPriorityFrames.size(); i++) {
4075            if (mPriorityFrames[i] == frameNumber) {
4076                mPriorityFrames.removeAt(i);
4077            }
4078        }
4079        /* reset the perf mode if pending priority frame list is empty */
4080        if (mReprocessPerfMode && mPriorityFrames.empty()) {
4081            resetToPerfNormal = true;
4082        }
4083    }
4084    if (resetToPerfNormal) {
4085        QCamera3Stream *pStream = mStreams[0];
4086        cam_stream_parm_buffer_t param;
4087        memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
4088
4089        param.type = CAM_STREAM_PARAM_TYPE_REQUEST_OPS_MODE;
4090        param.perf_mode = CAM_PERF_NORMAL;
4091        rc = pStream->setParameter(param);
4092        {
4093            Mutex::Autolock lock(mPriorityFramesLock);
4094            mReprocessPerfMode = false;
4095        }
4096    }
4097    return rc;
4098}
4099
4100/*===========================================================================
4101 * FUNCTION   : getStreamBufs
4102 *
4103 * DESCRIPTION: register the buffers of the reprocess channel
4104 *
4105 * PARAMETERS : none
4106 *
4107 * RETURN     : QCamera3StreamMem *
4108 *==========================================================================*/
4109QCamera3StreamMem* QCamera3ReprocessChannel::getStreamBufs(uint32_t len)
4110{
4111    if (mReprocessType == REPROCESS_TYPE_JPEG) {
4112        mMemory = new QCamera3StreamMem(mNumBuffers, false);
4113        if (!mMemory) {
4114            LOGE("unable to create reproc memory");
4115            return NULL;
4116        }
4117        mFrameLen = len;
4118        return mMemory;
4119    }
4120    return &mGrallocMemory;
4121}
4122
4123/*===========================================================================
4124 * FUNCTION   : putStreamBufs
4125 *
4126 * DESCRIPTION: release the reprocess channel buffers
4127 *
4128 * PARAMETERS : none
4129 *
4130 * RETURN     :
4131 *==========================================================================*/
4132void QCamera3ReprocessChannel::putStreamBufs()
4133{
4134   if (mReprocessType == REPROCESS_TYPE_JPEG) {
4135       mMemory->deallocate();
4136       delete mMemory;
4137       mMemory = NULL;
4138       mFreeBufferList.clear();
4139   } else {
4140       mGrallocMemory.unregisterBuffers();
4141   }
4142}
4143
4144/*===========================================================================
4145 * FUNCTION   : ~QCamera3ReprocessChannel
4146 *
4147 * DESCRIPTION: destructor of QCamera3ReprocessChannel
4148 *
4149 * PARAMETERS : none
4150 *
4151 * RETURN     : none
4152 *==========================================================================*/
4153QCamera3ReprocessChannel::~QCamera3ReprocessChannel()
4154{
4155    destroy();
4156
4157    if (m_handle) {
4158        m_camOps->delete_channel(m_camHandle, m_handle);
4159        LOGD("deleting channel %d", m_handle);
4160        m_handle = 0;
4161    }
4162}
4163
4164/*===========================================================================
4165 * FUNCTION   : start
4166 *
4167 * DESCRIPTION: start reprocess channel.
4168 *
4169 * PARAMETERS :
4170 *
4171 * RETURN     : int32_t type of status
4172 *              NO_ERROR  -- success
4173 *              none-zero failure code
4174 *==========================================================================*/
4175int32_t QCamera3ReprocessChannel::start()
4176{
4177    ATRACE_CALL();
4178    int32_t rc = NO_ERROR;
4179
4180    rc = QCamera3Channel::start();
4181
4182    if (rc == NO_ERROR) {
4183       rc = m_camOps->start_channel(m_camHandle, m_handle);
4184
4185       // Check failure
4186       if (rc != NO_ERROR) {
4187           LOGE("start_channel failed %d", rc);
4188           QCamera3Channel::stop();
4189       }
4190    }
4191    return rc;
4192}
4193
4194/*===========================================================================
4195 * FUNCTION   : stop
4196 *
4197 * DESCRIPTION: stop reprocess channel.
4198 *
4199 * PARAMETERS : none
4200 *
4201 * RETURN     : int32_t type of status
4202 *              NO_ERROR  -- success
4203 *              none-zero failure code
4204 *==========================================================================*/
4205int32_t QCamera3ReprocessChannel::stop()
4206{
4207    ATRACE_CALL();
4208    int32_t rc = NO_ERROR;
4209
4210    rc = QCamera3Channel::stop();
4211    unmapOfflineBuffers(true);
4212
4213    rc |= m_camOps->stop_channel(m_camHandle, m_handle);
4214
4215    return rc;
4216}
4217
4218/*===========================================================================
4219 * FUNCTION   : getStreamBySrcHandle
4220 *
4221 * DESCRIPTION: find reprocess stream by its source stream handle
4222 *
4223 * PARAMETERS :
4224 *   @srcHandle : source stream handle
4225 *
4226 * RETURN     : ptr to reprocess stream if found. NULL if not found
4227 *==========================================================================*/
4228QCamera3Stream * QCamera3ReprocessChannel::getStreamBySrcHandle(uint32_t srcHandle)
4229{
4230    QCamera3Stream *pStream = NULL;
4231
4232    for (uint32_t i = 0; i < m_numStreams; i++) {
4233        if (mSrcStreamHandles[i] == srcHandle) {
4234            pStream = mStreams[i];
4235            break;
4236        }
4237    }
4238    return pStream;
4239}
4240
4241/*===========================================================================
4242 * FUNCTION   : getSrcStreamBySrcHandle
4243 *
4244 * DESCRIPTION: find source stream by source stream handle
4245 *
4246 * PARAMETERS :
4247 *   @srcHandle : source stream handle
4248 *
4249 * RETURN     : ptr to reprocess stream if found. NULL if not found
4250 *==========================================================================*/
4251QCamera3Stream * QCamera3ReprocessChannel::getSrcStreamBySrcHandle(uint32_t srcHandle)
4252{
4253    QCamera3Stream *pStream = NULL;
4254
4255    if (NULL == m_pSrcChannel) {
4256        return NULL;
4257    }
4258
4259    for (uint32_t i = 0; i < m_numStreams; i++) {
4260        if (mSrcStreamHandles[i] == srcHandle) {
4261            pStream = m_pSrcChannel->getStreamByIndex(i);
4262            break;
4263        }
4264    }
4265    return pStream;
4266}
4267
4268/*===========================================================================
4269 * FUNCTION   : unmapOfflineBuffers
4270 *
4271 * DESCRIPTION: Unmaps offline buffers
4272 *
4273 * PARAMETERS : none
4274 *
4275 * RETURN     : int32_t type of status
4276 *              NO_ERROR  -- success
4277 *              none-zero failure code
4278 *==========================================================================*/
4279int32_t QCamera3ReprocessChannel::unmapOfflineBuffers(bool all)
4280{
4281    int rc = NO_ERROR;
4282    if (!mOfflineBuffers.empty()) {
4283        QCamera3Stream *stream = NULL;
4284        List<OfflineBuffer>::iterator it = mOfflineBuffers.begin();
4285        for (; it != mOfflineBuffers.end(); it++) {
4286           stream = (*it).stream;
4287           if (NULL != stream) {
4288               rc = stream->unmapBuf((*it).type,
4289                                     (*it).index,
4290                                        -1);
4291               if (NO_ERROR != rc) {
4292                   LOGE("Error during offline buffer unmap %d",
4293                          rc);
4294               }
4295               LOGD("Unmapped buffer with index %d", (*it).index);
4296           }
4297           if (!all) {
4298               mOfflineBuffers.erase(it);
4299               break;
4300           }
4301        }
4302        if (all) {
4303           mOfflineBuffers.clear();
4304        }
4305    }
4306
4307    if (!mOfflineMetaBuffers.empty()) {
4308        QCamera3Stream *stream = NULL;
4309        List<OfflineBuffer>::iterator it = mOfflineMetaBuffers.begin();
4310        for (; it != mOfflineMetaBuffers.end(); it++) {
4311           stream = (*it).stream;
4312           if (NULL != stream) {
4313               rc = stream->unmapBuf((*it).type,
4314                                     (*it).index,
4315                                        -1);
4316               if (NO_ERROR != rc) {
4317                   LOGE("Error during offline buffer unmap %d",
4318                          rc);
4319               }
4320               LOGD("Unmapped meta buffer with index %d", (*it).index);
4321           }
4322           if (!all) {
4323               mOfflineMetaBuffers.erase(it);
4324               break;
4325           }
4326        }
4327        if (all) {
4328           mOfflineMetaBuffers.clear();
4329        }
4330    }
4331    return rc;
4332}
4333
4334/*===========================================================================
4335 * FUNCTION   : bufDone
4336 *
4337 * DESCRIPTION: Return reprocess stream buffer to free buffer list.
4338 *              Note that this function doesn't queue buffer back to kernel.
4339 *              It's up to doReprocessOffline to do that instead.
4340 * PARAMETERS :
4341 *   @recvd_frame  : stream buf frame to be returned
4342 *
4343 * RETURN     : int32_t type of status
4344 *              NO_ERROR  -- success
4345 *              none-zero failure code
4346 *==========================================================================*/
4347int32_t QCamera3ReprocessChannel::bufDone(mm_camera_super_buf_t *recvd_frame)
4348{
4349    int rc = NO_ERROR;
4350    if (recvd_frame && recvd_frame->num_bufs == 1) {
4351        Mutex::Autolock lock(mFreeBuffersLock);
4352        uint32_t buf_idx = recvd_frame->bufs[0]->buf_idx;
4353        mFreeBufferList.push_back(buf_idx);
4354
4355    } else {
4356        LOGE("Fatal. Not supposed to be here");
4357        rc = BAD_VALUE;
4358    }
4359
4360    return rc;
4361}
4362
4363/*===========================================================================
4364 * FUNCTION   : overrideMetadata
4365 *
4366 * DESCRIPTION: Override metadata entry such as rotation, crop, and CDS info.
4367 *
4368 * PARAMETERS :
4369 *   @frame     : input frame from source stream
4370 *   meta_buffer: metadata buffer
4371 *   @metadata  : corresponding metadata
4372 *   @fwk_frame :
4373 *
4374 * RETURN     : int32_t type of status
4375 *              NO_ERROR  -- success
4376 *              none-zero failure code
4377 *==========================================================================*/
4378int32_t QCamera3ReprocessChannel::overrideMetadata(qcamera_hal3_pp_buffer_t *pp_buffer,
4379        mm_camera_buf_def_t *meta_buffer, jpeg_settings_t *jpeg_settings,
4380        qcamera_fwk_input_pp_data_t &fwk_frame)
4381{
4382    int32_t rc = NO_ERROR;
4383    QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
4384    if ((NULL == meta_buffer) || (NULL == pp_buffer) || (NULL == pp_buffer->input) ||
4385            (NULL == hal_obj)) {
4386        return BAD_VALUE;
4387    }
4388
4389    metadata_buffer_t *meta = (metadata_buffer_t *)meta_buffer->buffer;
4390    mm_camera_super_buf_t *frame = pp_buffer->input;
4391    if (NULL == meta) {
4392        return BAD_VALUE;
4393    }
4394
4395    for (uint32_t i = 0; i < frame->num_bufs; i++) {
4396        QCamera3Stream *pStream = getStreamBySrcHandle(frame->bufs[i]->stream_id);
4397        QCamera3Stream *pSrcStream = getSrcStreamBySrcHandle(frame->bufs[i]->stream_id);
4398
4399        if (pStream != NULL && pSrcStream != NULL) {
4400            if (jpeg_settings) {
4401                // Find rotation info for reprocess stream
4402                cam_rotation_info_t rotation_info;
4403                memset(&rotation_info, 0, sizeof(rotation_info));
4404                if (jpeg_settings->jpeg_orientation == 0) {
4405                   rotation_info.rotation = ROTATE_0;
4406                } else if (jpeg_settings->jpeg_orientation == 90) {
4407                   rotation_info.rotation = ROTATE_90;
4408                } else if (jpeg_settings->jpeg_orientation == 180) {
4409                   rotation_info.rotation = ROTATE_180;
4410                } else if (jpeg_settings->jpeg_orientation == 270) {
4411                   rotation_info.rotation = ROTATE_270;
4412                }
4413                rotation_info.device_rotation = ROTATE_0;
4414                rotation_info.streamId = mStreams[0]->getMyServerID();
4415                ADD_SET_PARAM_ENTRY_TO_BATCH(meta, CAM_INTF_PARM_ROTATION, rotation_info);
4416            }
4417
4418            // Find and insert crop info for reprocess stream
4419            IF_META_AVAILABLE(cam_crop_data_t, crop_data, CAM_INTF_META_CROP_DATA, meta) {
4420                if (MAX_NUM_STREAMS > crop_data->num_of_streams) {
4421                    for (int j = 0; j < crop_data->num_of_streams; j++) {
4422                        if (crop_data->crop_info[j].stream_id ==
4423                                pSrcStream->getMyServerID()) {
4424
4425                            // Store crop/roi information for offline reprocess
4426                            // in the reprocess stream slot
4427                            crop_data->crop_info[crop_data->num_of_streams].crop =
4428                                    crop_data->crop_info[j].crop;
4429                            crop_data->crop_info[crop_data->num_of_streams].roi_map =
4430                                    crop_data->crop_info[j].roi_map;
4431                            crop_data->crop_info[crop_data->num_of_streams].stream_id =
4432                                    mStreams[0]->getMyServerID();
4433                            crop_data->num_of_streams++;
4434
4435                            LOGD("Reprocess stream server id: %d",
4436                                     mStreams[0]->getMyServerID());
4437                            LOGD("Found offline reprocess crop %dx%d %dx%d",
4438                                    crop_data->crop_info[j].crop.left,
4439                                    crop_data->crop_info[j].crop.top,
4440                                    crop_data->crop_info[j].crop.width,
4441                                    crop_data->crop_info[j].crop.height);
4442                            LOGD("Found offline reprocess roimap %dx%d %dx%d",
4443                                    crop_data->crop_info[j].roi_map.left,
4444                                    crop_data->crop_info[j].roi_map.top,
4445                                    crop_data->crop_info[j].roi_map.width,
4446                                    crop_data->crop_info[j].roi_map.height);
4447
4448                            break;
4449                        }
4450                    }
4451                } else {
4452                    LOGE("No space to add reprocess stream crop/roi information");
4453                }
4454            }
4455
4456            IF_META_AVAILABLE(cam_cds_data_t, cdsInfo, CAM_INTF_META_CDS_DATA, meta) {
4457                uint8_t cnt = cdsInfo->num_of_streams;
4458                if (cnt <= MAX_NUM_STREAMS) {
4459                    cam_stream_cds_info_t repro_cds_info;
4460                    memset(&repro_cds_info, 0, sizeof(repro_cds_info));
4461                    repro_cds_info.stream_id = mStreams[0]->getMyServerID();
4462                    for (size_t i = 0; i < cnt; i++) {
4463                        if (cdsInfo->cds_info[i].stream_id ==
4464                                pSrcStream->getMyServerID()) {
4465                            repro_cds_info.cds_enable =
4466                                    cdsInfo->cds_info[i].cds_enable;
4467                            break;
4468                        }
4469                    }
4470                    cdsInfo->num_of_streams = 1;
4471                    cdsInfo->cds_info[0] = repro_cds_info;
4472                } else {
4473                    LOGE("No space to add reprocess stream cds information");
4474                }
4475            }
4476
4477            fwk_frame.input_buffer = *frame->bufs[i];
4478            fwk_frame.metadata_buffer = *meta_buffer;
4479            fwk_frame.output_buffer = pp_buffer->output;
4480            break;
4481        } else {
4482            LOGE("Source/Re-process streams are invalid");
4483            rc |= BAD_VALUE;
4484        }
4485    }
4486
4487    return rc;
4488}
4489
4490/*===========================================================================
4491* FUNCTION : overrideFwkMetadata
4492*
4493* DESCRIPTION: Override frameworks metadata such as crop, and CDS data.
4494*
4495* PARAMETERS :
4496* @frame : input frame for reprocessing
4497*
4498* RETURN : int32_t type of status
4499* NO_ERROR -- success
4500* none-zero failure code
4501*==========================================================================*/
4502int32_t QCamera3ReprocessChannel::overrideFwkMetadata(
4503        qcamera_fwk_input_pp_data_t *frame)
4504{
4505    if (NULL == frame) {
4506        LOGE("Incorrect input frame");
4507        return BAD_VALUE;
4508    }
4509
4510    if (NULL == frame->metadata_buffer.buffer) {
4511        LOGE("No metadata available");
4512        return BAD_VALUE;
4513    }
4514
4515    // Find and insert crop info for reprocess stream
4516    metadata_buffer_t *meta = (metadata_buffer_t *) frame->metadata_buffer.buffer;
4517    IF_META_AVAILABLE(cam_crop_data_t, crop_data, CAM_INTF_META_CROP_DATA, meta) {
4518        if (1 == crop_data->num_of_streams) {
4519            // Store crop/roi information for offline reprocess
4520            // in the reprocess stream slot
4521            crop_data->crop_info[crop_data->num_of_streams].crop =
4522                    crop_data->crop_info[0].crop;
4523            crop_data->crop_info[crop_data->num_of_streams].roi_map =
4524                    crop_data->crop_info[0].roi_map;
4525            crop_data->crop_info[crop_data->num_of_streams].stream_id =
4526                    mStreams[0]->getMyServerID();
4527            crop_data->num_of_streams++;
4528
4529            LOGD("Reprocess stream server id: %d",
4530                     mStreams[0]->getMyServerID());
4531            LOGD("Found offline reprocess crop %dx%d %dx%d",
4532                    crop_data->crop_info[0].crop.left,
4533                    crop_data->crop_info[0].crop.top,
4534                    crop_data->crop_info[0].crop.width,
4535                    crop_data->crop_info[0].crop.height);
4536            LOGD("Found offline reprocess roi map %dx%d %dx%d",
4537                    crop_data->crop_info[0].roi_map.left,
4538                    crop_data->crop_info[0].roi_map.top,
4539                    crop_data->crop_info[0].roi_map.width,
4540                    crop_data->crop_info[0].roi_map.height);
4541        } else {
4542            LOGE("Incorrect number of offline crop data entries %d",
4543                    crop_data->num_of_streams);
4544            return BAD_VALUE;
4545        }
4546    } else {
4547        LOGW("Crop data not present");
4548    }
4549
4550    IF_META_AVAILABLE(cam_cds_data_t, cdsInfo, CAM_INTF_META_CDS_DATA, meta) {
4551        if (1 == cdsInfo->num_of_streams) {
4552            cdsInfo->cds_info[0].stream_id = mStreams[0]->getMyServerID();
4553        } else {
4554            LOGE("Incorrect number of offline cds info entries %d",
4555                     cdsInfo->num_of_streams);
4556            return BAD_VALUE;
4557        }
4558    }
4559
4560    return NO_ERROR;
4561}
4562
4563/*===========================================================================
4564 * FUNCTION   : doReprocessOffline
4565 *
4566 * DESCRIPTION: request to do a reprocess on the frame
4567 *
4568 * PARAMETERS :
4569 *   @frame     : input frame for reprocessing
4570 *   @isPriorityFrame: Hint that this frame is of priority, equivalent to
4571 *              real time, even though it is processed in offline mechanism
4572 *
4573 * RETURN     : int32_t type of status
4574 *              NO_ERROR  -- success
4575 *              none-zero failure code
4576 *==========================================================================*/
4577 int32_t  QCamera3ReprocessChannel::doReprocessOffline(
4578        qcamera_fwk_input_pp_data_t *frame, bool isPriorityFrame)
4579{
4580    int32_t rc = 0;
4581    int index;
4582    OfflineBuffer mappedBuffer;
4583
4584    if (m_numStreams < 1) {
4585        LOGE("No reprocess stream is created");
4586        return -1;
4587    }
4588
4589    if (NULL == frame) {
4590        LOGE("Incorrect input frame");
4591        return BAD_VALUE;
4592    }
4593
4594    if (NULL == frame->metadata_buffer.buffer) {
4595        LOGE("No metadata available");
4596        return BAD_VALUE;
4597    }
4598
4599    if (NULL == frame->input_buffer.buffer) {
4600        LOGE("No input buffer available");
4601        return BAD_VALUE;
4602    }
4603
4604    if ((0 == m_numStreams) || (NULL == mStreams[0])) {
4605        LOGE("Reprocess stream not initialized!");
4606        return NO_INIT;
4607    }
4608
4609    QCamera3Stream *pStream = mStreams[0];
4610
4611    //qbuf the output buffer if it was allocated by the framework
4612    if (mReprocessType != REPROCESS_TYPE_JPEG && frame->output_buffer != NULL) {
4613        if(!m_bIsActive) {
4614            rc = registerBuffer(frame->output_buffer, mIsType);
4615            if (NO_ERROR != rc) {
4616                LOGE("On-the-fly buffer registration failed %d",
4617                         rc);
4618                return rc;
4619            }
4620
4621            rc = start();
4622            if (NO_ERROR != rc) {
4623                return rc;
4624            }
4625        }
4626        index = mGrallocMemory.getMatchBufIndex((void*)frame->output_buffer);
4627        if(index < 0) {
4628            rc = registerBuffer(frame->output_buffer, mIsType);
4629            if (NO_ERROR != rc) {
4630                LOGE("On-the-fly buffer registration failed %d",
4631                         rc);
4632                return rc;
4633            }
4634
4635            index = mGrallocMemory.getMatchBufIndex((void*)frame->output_buffer);
4636            if (index < 0) {
4637                LOGE("Could not find object among registered buffers");
4638                return DEAD_OBJECT;
4639            }
4640        }
4641        rc = mGrallocMemory.markFrameNumber(index, frame->frameNumber);
4642        if(rc != NO_ERROR) {
4643            LOGE("Failed to mark frame#:%d, index:%d",frame->frameNumber,index);
4644            return rc;
4645        }
4646        rc = pStream->bufDone(index);
4647        if(rc != NO_ERROR) {
4648            LOGE("Failed to Q new buffer to stream");
4649            mGrallocMemory.markFrameNumber(index, -1);
4650            return rc;
4651        }
4652
4653    } else if (mReprocessType == REPROCESS_TYPE_JPEG) {
4654        Mutex::Autolock lock(mFreeBuffersLock);
4655        uint32_t bufIdx;
4656        if (mFreeBufferList.empty()) {
4657            rc = mMemory->allocateOne(mFrameLen);
4658            if (rc < 0) {
4659                LOGE("Failed allocating heap buffer. Fatal");
4660                return BAD_VALUE;
4661            } else {
4662                bufIdx = (uint32_t)rc;
4663            }
4664        } else {
4665            bufIdx = *(mFreeBufferList.begin());
4666            mFreeBufferList.erase(mFreeBufferList.begin());
4667        }
4668
4669        mMemory->markFrameNumber(bufIdx, frame->frameNumber);
4670        rc = pStream->bufDone(bufIdx);
4671        if (rc != NO_ERROR) {
4672            LOGE("Failed to queue new buffer to stream");
4673            return rc;
4674        }
4675    }
4676
4677    int32_t max_idx = (int32_t) (mNumBuffers - 1);
4678    //loop back the indices if max burst count reached
4679    if (mOfflineBuffersIndex == max_idx) {
4680       mOfflineBuffersIndex = -1;
4681    }
4682    uint32_t buf_idx = (uint32_t)(mOfflineBuffersIndex + 1);
4683    rc = pStream->mapBuf(
4684            CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
4685            buf_idx, -1,
4686            frame->input_buffer.fd, frame->input_buffer.buffer,
4687            frame->input_buffer.frame_len);
4688    if (NO_ERROR == rc) {
4689        mappedBuffer.index = buf_idx;
4690        mappedBuffer.stream = pStream;
4691        mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF;
4692        mOfflineBuffers.push_back(mappedBuffer);
4693        mOfflineBuffersIndex = (int32_t)buf_idx;
4694        LOGD("Mapped buffer with index %d", mOfflineBuffersIndex);
4695    }
4696
4697    max_idx = (int32_t) ((mNumBuffers * 2) - 1);
4698    //loop back the indices if max burst count reached
4699    if (mOfflineMetaIndex == max_idx) {
4700       mOfflineMetaIndex = (int32_t) (mNumBuffers - 1);
4701    }
4702    uint32_t meta_buf_idx = (uint32_t)(mOfflineMetaIndex + 1);
4703    rc |= pStream->mapBuf(
4704            CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF,
4705            meta_buf_idx, -1,
4706            frame->metadata_buffer.fd, frame->metadata_buffer.buffer,
4707            frame->metadata_buffer.frame_len);
4708    if (NO_ERROR == rc) {
4709        mappedBuffer.index = meta_buf_idx;
4710        mappedBuffer.stream = pStream;
4711        mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF;
4712        mOfflineMetaBuffers.push_back(mappedBuffer);
4713        mOfflineMetaIndex = (int32_t)meta_buf_idx;
4714        LOGD("Mapped meta buffer with index %d", mOfflineMetaIndex);
4715    }
4716
4717    if (rc == NO_ERROR) {
4718        cam_stream_parm_buffer_t param;
4719        uint32_t numPendingPriorityFrames = 0;
4720
4721        if(isPriorityFrame) {
4722            Mutex::Autolock lock(mPriorityFramesLock);
4723            /* read the length before pushing the frame number to check if
4724             * vector is empty */
4725            numPendingPriorityFrames = mPriorityFrames.size();
4726            mPriorityFrames.push(frame->frameNumber);
4727        }
4728
4729        if(isPriorityFrame && !numPendingPriorityFrames) {
4730            memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
4731            param.type = CAM_STREAM_PARAM_TYPE_REQUEST_OPS_MODE;
4732            param.perf_mode = CAM_PERF_HIGH_PERFORMANCE;
4733            rc = pStream->setParameter(param);
4734
4735            if (rc != NO_ERROR) {
4736                ALOGE("%s: setParameter for CAM_PERF_HIGH_PERFORMANCE failed",
4737                    __func__);
4738            }
4739            {
4740                Mutex::Autolock lock(mPriorityFramesLock);
4741                mReprocessPerfMode = true;
4742            }
4743        }
4744
4745        memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
4746        param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
4747        param.reprocess.buf_index = buf_idx;
4748        param.reprocess.frame_idx = frame->input_buffer.frame_idx;
4749        param.reprocess.meta_present = 1;
4750        param.reprocess.meta_buf_index = meta_buf_idx;
4751
4752        LOGI("Offline reprocessing id = %d buf Id = %d meta index = %d",
4753                    param.reprocess.frame_idx, param.reprocess.buf_index,
4754                    param.reprocess.meta_buf_index);
4755        rc = pStream->setParameter(param);
4756        if (rc != NO_ERROR) {
4757            LOGE("stream setParameter for reprocess failed");
4758            resetToCamPerfNormal(frame->frameNumber);
4759        }
4760    } else {
4761        LOGE("Input buffer memory map failed: %d", rc);
4762    }
4763
4764    return rc;
4765}
4766
4767/*===========================================================================
4768 * FUNCTION   : doReprocess
4769 *
4770 * DESCRIPTION: request to do a reprocess on the frame
4771 *
4772 * PARAMETERS :
4773 *   @buf_fd     : fd to the input buffer that needs reprocess
4774 *   @buffer     : Buffer ptr
4775 *   @buf_lenght : length of the input buffer
4776 *   @ret_val    : result of reprocess.
4777 *                 Example: Could be faceID in case of register face image.
4778 *   @meta_frame : metadata frame.
4779 *
4780 * RETURN     : int32_t type of status
4781 *              NO_ERROR  -- success
4782 *              none-zero failure code
4783 *==========================================================================*/
4784int32_t QCamera3ReprocessChannel::doReprocess(int buf_fd, void *buffer, size_t buf_length,
4785        int32_t &ret_val, mm_camera_super_buf_t *meta_frame)
4786{
4787    int32_t rc = 0;
4788    if (m_numStreams < 1) {
4789        LOGE("No reprocess stream is created");
4790        return -1;
4791    }
4792    if (meta_frame == NULL) {
4793        LOGE("Did not get corresponding metadata in time");
4794        return -1;
4795    }
4796
4797    uint8_t buf_idx = 0;
4798    for (uint32_t i = 0; i < m_numStreams; i++) {
4799        rc = mStreams[i]->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
4800                                 buf_idx, -1,
4801                                 buf_fd, buffer, buf_length);
4802
4803        if (rc == NO_ERROR) {
4804            cam_stream_parm_buffer_t param;
4805            memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
4806            param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
4807            param.reprocess.buf_index = buf_idx;
4808            param.reprocess.meta_present = 1;
4809            param.reprocess.meta_stream_handle = m_pMetaChannel->mStreams[0]->getMyServerID();
4810            param.reprocess.meta_buf_index = meta_frame->bufs[0]->buf_idx;
4811
4812            LOGI("Online reprocessing id = %d buf Id = %d meta index = %d",
4813                    param.reprocess.frame_idx, param.reprocess.buf_index,
4814                    param.reprocess.meta_buf_index);
4815            rc = mStreams[i]->setParameter(param);
4816            if (rc == NO_ERROR) {
4817                ret_val = param.reprocess.ret_val;
4818            }
4819            mStreams[i]->unmapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
4820                                  buf_idx, -1);
4821        }
4822    }
4823    return rc;
4824}
4825
4826/*===========================================================================
4827 * FUNCTION   : addReprocStreamsFromSource
4828 *
4829 * DESCRIPTION: add reprocess streams from input source channel
4830 *
4831 * PARAMETERS :
4832 *   @config         : pp feature configuration
4833 *   @src_config     : source reprocess configuration
4834 *   @isType         : type of image stabilization required on this stream
4835 *   @pMetaChannel   : ptr to metadata channel to get corresp. metadata
4836 *
4837 *
4838 * RETURN     : int32_t type of status
4839 *              NO_ERROR  -- success
4840 *              none-zero failure code
4841 *==========================================================================*/
4842int32_t QCamera3ReprocessChannel::addReprocStreamsFromSource(cam_pp_feature_config_t &pp_config,
4843        const reprocess_config_t &src_config , cam_is_type_t is_type,
4844        QCamera3Channel *pMetaChannel)
4845{
4846    int32_t rc = 0;
4847    cam_stream_reproc_config_t reprocess_config;
4848    cam_stream_type_t streamType;
4849
4850    cam_dimension_t streamDim = src_config.output_stream_dim;
4851
4852    if (NULL != src_config.src_channel) {
4853        QCamera3Stream *pSrcStream = src_config.src_channel->getStreamByIndex(0);
4854        if (pSrcStream == NULL) {
4855           LOGE("source channel doesn't have a stream");
4856           return BAD_VALUE;
4857        }
4858        mSrcStreamHandles[m_numStreams] = pSrcStream->getMyHandle();
4859    }
4860
4861    streamType = CAM_STREAM_TYPE_OFFLINE_PROC;
4862    reprocess_config.pp_type = CAM_OFFLINE_REPROCESS_TYPE;
4863
4864    reprocess_config.offline.input_fmt = src_config.stream_format;
4865    reprocess_config.offline.input_dim = src_config.input_stream_dim;
4866    reprocess_config.offline.input_buf_planes.plane_info =
4867            src_config.input_stream_plane_info.plane_info;
4868    reprocess_config.offline.num_of_bufs = (uint8_t)mNumBuffers;
4869    reprocess_config.offline.input_type = src_config.stream_type;
4870
4871    reprocess_config.pp_feature_config = pp_config;
4872    QCamera3Stream *pStream = new QCamera3Stream(m_camHandle,
4873            m_handle,
4874            m_camOps,
4875            &mPaddingInfo,
4876            (QCamera3Channel*)this);
4877    if (pStream == NULL) {
4878        LOGE("No mem for Stream");
4879        return NO_MEMORY;
4880    }
4881
4882    rc = pStream->init(streamType, src_config.stream_format,
4883            streamDim, ROTATE_0, &reprocess_config,
4884            (uint8_t)mNumBuffers,
4885            reprocess_config.pp_feature_config.feature_mask,
4886            is_type,
4887            0,/* batchSize */
4888            QCamera3Channel::streamCbRoutine, this);
4889
4890    if (rc == 0) {
4891        mStreams[m_numStreams] = pStream;
4892        m_numStreams++;
4893    } else {
4894        LOGE("failed to create reprocess stream");
4895        delete pStream;
4896    }
4897
4898    if (rc == NO_ERROR) {
4899        m_pSrcChannel = src_config.src_channel;
4900        m_pMetaChannel = pMetaChannel;
4901        mReprocessType = src_config.reprocess_type;
4902        LOGD("mReprocessType is %d", mReprocessType);
4903    }
4904    mm_camera_req_buf_t buf;
4905    memset(&buf, 0x0, sizeof(buf));
4906    buf.type = MM_CAMERA_REQ_SUPER_BUF;
4907    buf.num_buf_requested = 1;
4908    if(m_camOps->request_super_buf(m_camHandle,m_handle, &buf) < 0) {
4909        LOGE("Request for super buffer failed");
4910    }
4911    return rc;
4912}
4913
4914/* QCamera3SupportChannel methods */
4915
4916cam_dimension_t QCamera3SupportChannel::kDim = {640, 480};
4917
4918QCamera3SupportChannel::QCamera3SupportChannel(uint32_t cam_handle,
4919                    uint32_t channel_handle,
4920                    mm_camera_ops_t *cam_ops,
4921                    cam_padding_info_t *paddingInfo,
4922                    cam_feature_mask_t postprocess_mask,
4923                    cam_stream_type_t streamType,
4924                    cam_dimension_t *dim,
4925                    cam_format_t streamFormat,
4926                    uint8_t hw_analysis_supported,
4927                    void *userData, uint32_t numBuffers) :
4928                        QCamera3Channel(cam_handle, channel_handle, cam_ops,
4929                                NULL, NULL, paddingInfo, postprocess_mask,
4930                                userData, numBuffers),
4931                        mMemory(NULL)
4932{
4933    memcpy(&mDim, dim, sizeof(cam_dimension_t));
4934    mStreamType = streamType;
4935    mStreamFormat = streamFormat;
4936   // Make Analysis same as Preview format
4937   if (!hw_analysis_supported && mStreamType == CAM_STREAM_TYPE_ANALYSIS) {
4938        mStreamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_PREVIEW,
4939                dim->width, dim->height);
4940   }
4941}
4942
4943QCamera3SupportChannel::~QCamera3SupportChannel()
4944{
4945    destroy();
4946
4947    if (mMemory) {
4948        mMemory->deallocate();
4949        delete mMemory;
4950        mMemory = NULL;
4951    }
4952}
4953
4954int32_t QCamera3SupportChannel::initialize(cam_is_type_t isType)
4955{
4956    int32_t rc;
4957
4958    if (mMemory || m_numStreams > 0) {
4959        LOGE("metadata channel already initialized");
4960        return -EINVAL;
4961    }
4962
4963    mIsType = isType;
4964    rc = QCamera3Channel::addStream(mStreamType,
4965            mStreamFormat, mDim, ROTATE_0, MIN_STREAMING_BUFFER_NUM,
4966            mPostProcMask, mIsType);
4967    if (rc < 0) {
4968        LOGE("addStream failed");
4969    }
4970    return rc;
4971}
4972
4973int32_t QCamera3SupportChannel::request(buffer_handle_t * /*buffer*/,
4974                                                uint32_t /*frameNumber*/,
4975                                                int & /*indexUsed*/)
4976{
4977    return NO_ERROR;
4978}
4979
4980void QCamera3SupportChannel::streamCbRoutine(
4981                        mm_camera_super_buf_t *super_frame,
4982                        QCamera3Stream * /*stream*/)
4983{
4984    if (super_frame == NULL || super_frame->num_bufs != 1) {
4985        LOGE("super_frame is not valid");
4986        return;
4987    }
4988    bufDone(super_frame);
4989    free(super_frame);
4990}
4991
4992QCamera3StreamMem* QCamera3SupportChannel::getStreamBufs(uint32_t len)
4993{
4994    int rc;
4995    mMemory = new QCamera3StreamMem(mNumBuffers);
4996    if (!mMemory) {
4997        LOGE("unable to create heap memory");
4998        return NULL;
4999    }
5000    rc = mMemory->allocateAll(len);
5001    if (rc < 0) {
5002        LOGE("unable to allocate heap memory");
5003        delete mMemory;
5004        mMemory = NULL;
5005        return NULL;
5006    }
5007    return mMemory;
5008}
5009
5010void QCamera3SupportChannel::putStreamBufs()
5011{
5012    mMemory->deallocate();
5013    delete mMemory;
5014    mMemory = NULL;
5015}
5016
5017}; // namespace qcamera
5018