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