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