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