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