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