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