QCamera3Channel.cpp revision 34a6e88cee59495adcf1437d027c105171738a07
1/* Copyright (c) 2012-2013, The Linux Foundataion. All rights reserved.
2*
3* Redistribution and use in source and binary forms, with or without
4* modification, are permitted provided that the following conditions are
5* met:
6*     * Redistributions of source code must retain the above copyright
7*       notice, this list of conditions and the following disclaimer.
8*     * Redistributions in binary form must reproduce the above
9*       copyright notice, this list of conditions and the following
10*       disclaimer in the documentation and/or other materials provided
11*       with the distribution.
12*     * Neither the name of The Linux Foundation nor the names of its
13*       contributors may be used to endorse or promote products derived
14*       from this software without specific prior written permission.
15*
16* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27*
28*/
29
30#define LOG_TAG "QCamera3Channel"
31
32#include <stdlib.h>
33#include <cstdlib>
34#include <stdio.h>
35#include <string.h>
36#include <hardware/camera3.h>
37#include <system/camera_metadata.h>
38#include <gralloc_priv.h>
39#include <utils/Log.h>
40#include <utils/Errors.h>
41#include "QCamera3Channel.h"
42
43using namespace android;
44
45#define MIN_STREAMING_BUFFER_NUM 7
46
47namespace qcamera {
48static const char ExifAsciiPrefix[] =
49    { 0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0 };          // "ASCII\0\0\0"
50static const char ExifUndefinedPrefix[] =
51    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };   // "\0\0\0\0\0\0\0\0"
52
53#define GPS_PROCESSING_METHOD_SIZE       101
54#define EXIF_ASCII_PREFIX_SIZE           8   //(sizeof(ExifAsciiPrefix))
55#define FOCAL_LENGTH_DECIMAL_PRECISION   100
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                               mm_camera_ops_t *cam_ops,
70                               channel_cb_routine cb_routine,
71                               cam_padding_info_t *paddingInfo,
72                               void *userData)
73{
74    m_camHandle = cam_handle;
75    m_camOps = cam_ops;
76    m_bIsActive = false;
77
78    m_handle = 0;
79    m_numStreams = 0;
80    memset(mStreams, 0, sizeof(mStreams));
81    mUserData = userData;
82
83    mStreamInfoBuf = NULL;
84    mChannelCB = cb_routine;
85    mPaddingInfo = paddingInfo;
86}
87
88/*===========================================================================
89 * FUNCTION   : QCamera3Channel
90 *
91 * DESCRIPTION: default constrcutor of QCamera3Channel
92 *
93 * PARAMETERS : none
94 *
95 * RETURN     : none
96 *==========================================================================*/
97QCamera3Channel::QCamera3Channel()
98{
99    m_camHandle = 0;
100    m_camOps = NULL;
101    m_bIsActive = false;
102
103    m_handle = 0;
104    m_numStreams = 0;
105    memset(mStreams, 0, sizeof(mStreams));
106    mUserData = NULL;
107
108    mStreamInfoBuf = NULL;
109    mChannelCB = NULL;
110    mPaddingInfo = NULL;
111}
112
113/*===========================================================================
114 * FUNCTION   : ~QCamera3Channel
115 *
116 * DESCRIPTION: destructor of QCamera3Channel
117 *
118 * PARAMETERS : none
119 *
120 * RETURN     : none
121 *==========================================================================*/
122QCamera3Channel::~QCamera3Channel()
123{
124    if (m_bIsActive)
125        stop();
126
127    for (int i = 0; i < m_numStreams; i++) {
128        if (mStreams[i] != NULL) {
129            delete mStreams[i];
130            mStreams[i] = 0;
131        }
132    }
133    if (m_handle) {
134        m_camOps->delete_channel(m_camHandle, m_handle);
135        ALOGE("%s: deleting channel %d", __func__, m_handle);
136        m_handle = 0;
137    }
138    m_numStreams = 0;
139}
140
141/*===========================================================================
142 * FUNCTION   : init
143 *
144 * DESCRIPTION: initialization of channel
145 *
146 * PARAMETERS :
147 *   @attr    : channel bundle attribute setting
148 *   @dataCB  : data notify callback
149 *   @userData: user data ptr
150 *
151 * RETURN     : int32_t type of status
152 *              NO_ERROR  -- success
153 *              none-zero failure code
154 *==========================================================================*/
155int32_t QCamera3Channel::init(mm_camera_channel_attr_t *attr,
156                             mm_camera_buf_notify_t dataCB)
157{
158    m_handle = m_camOps->add_channel(m_camHandle,
159                                      attr,
160                                      dataCB,
161                                      this);
162    if (m_handle == 0) {
163        ALOGE("%s: Add channel failed", __func__);
164        return UNKNOWN_ERROR;
165    }
166    return NO_ERROR;
167}
168
169/*===========================================================================
170 * FUNCTION   : addStream
171 *
172 * DESCRIPTION: add a stream into channel
173 *
174 * PARAMETERS :
175 *   @allocator      : stream related buffer allocator
176 *   @streamInfoBuf  : ptr to buf that constains stream info
177 *   @minStreamBufNum: number of stream buffers needed
178 *   @paddingInfo    : padding information
179 *   @stream_cb      : stream data notify callback
180 *   @userdata       : user data ptr
181 *
182 * RETURN     : int32_t type of status
183 *              NO_ERROR  -- success
184 *              none-zero failure code
185 *==========================================================================*/
186int32_t QCamera3Channel::addStream(cam_stream_type_t streamType,
187                                  cam_format_t streamFormat,
188                                  cam_dimension_t streamDim,
189                                  uint8_t minStreamBufNum)
190{
191    int32_t rc = NO_ERROR;
192
193    if (m_numStreams >= 1) {
194        ALOGE("%s: Only one stream per channel supported in v3 Hal", __func__);
195        return BAD_VALUE;
196    }
197
198    if (m_numStreams >= MAX_STREAM_NUM_IN_BUNDLE) {
199        ALOGE("%s: stream number (%d) exceeds max limit (%d)",
200              __func__, m_numStreams, MAX_STREAM_NUM_IN_BUNDLE);
201        return BAD_VALUE;
202    }
203    QCamera3Stream *pStream = new QCamera3Stream(m_camHandle,
204                                               m_handle,
205                                               m_camOps,
206                                               mPaddingInfo,
207                                               this);
208    if (pStream == NULL) {
209        ALOGE("%s: No mem for Stream", __func__);
210        return NO_MEMORY;
211    }
212
213    rc = pStream->init(streamType, streamFormat, streamDim, NULL, minStreamBufNum,
214                                                    streamCbRoutine, this);
215    if (rc == 0) {
216        mStreams[m_numStreams] = pStream;
217        m_numStreams++;
218    } else {
219        delete pStream;
220    }
221    return rc;
222}
223
224/*===========================================================================
225 * FUNCTION   : start
226 *
227 * DESCRIPTION: start channel, which will start all streams belong to this channel
228 *
229 * PARAMETERS :
230 *
231 * RETURN     : int32_t type of status
232 *              NO_ERROR  -- success
233 *              none-zero failure code
234 *==========================================================================*/
235int32_t QCamera3Channel::start()
236{
237    int32_t rc = NO_ERROR;
238
239    if (m_numStreams > 1) {
240        ALOGE("%s: bundle not supported", __func__);
241    }
242
243    for (int i = 0; i < m_numStreams; i++) {
244        if (mStreams[i] != NULL) {
245            mStreams[i]->start();
246        }
247    }
248    rc = m_camOps->start_channel(m_camHandle, m_handle);
249
250    if (rc != NO_ERROR) {
251        for (int i = 0; i < m_numStreams; i++) {
252            if (mStreams[i] != NULL) {
253                mStreams[i]->stop();
254            }
255        }
256    } else {
257        m_bIsActive = true;
258    }
259
260    return rc;
261}
262
263/*===========================================================================
264 * FUNCTION   : stop
265 *
266 * DESCRIPTION: stop a channel, which will stop all streams belong to this channel
267 *
268 * PARAMETERS : none
269 *
270 * RETURN     : int32_t type of status
271 *              NO_ERROR  -- success
272 *              none-zero failure code
273 *==========================================================================*/
274int32_t QCamera3Channel::stop()
275{
276    int32_t rc = NO_ERROR;
277    if(!m_bIsActive) {
278        ALOGE("%s: Attempt to stop inactive channel",__func__);
279        return rc;
280    }
281
282    rc = m_camOps->stop_channel(m_camHandle, m_handle);
283
284    for (int i = 0; i < m_numStreams; i++) {
285        if (mStreams[i] != NULL) {
286            mStreams[i]->stop();
287        }
288    }
289
290    m_bIsActive = false;
291    return rc;
292}
293
294/*===========================================================================
295 * FUNCTION   : bufDone
296 *
297 * DESCRIPTION: return a stream buf back to kernel
298 *
299 * PARAMETERS :
300 *   @recvd_frame  : stream buf frame to be returned
301 *
302 * RETURN     : int32_t type of status
303 *              NO_ERROR  -- success
304 *              none-zero failure code
305 *==========================================================================*/
306int32_t QCamera3Channel::bufDone(mm_camera_super_buf_t *recvd_frame)
307{
308    int32_t rc = NO_ERROR;
309    for (int i = 0; i < recvd_frame->num_bufs; i++) {
310         if (recvd_frame->bufs[i] != NULL) {
311             for (int j = 0; j < m_numStreams; j++) {
312                 if (mStreams[j] != NULL &&
313                     mStreams[j]->getMyHandle() == recvd_frame->bufs[i]->stream_id) {
314                     rc = mStreams[j]->bufDone(recvd_frame->bufs[i]->buf_idx);
315                     break; // break loop j
316                 }
317             }
318         }
319    }
320
321    return rc;
322}
323
324/*===========================================================================
325 * FUNCTION   : getStreamTypeMask
326 *
327 * DESCRIPTION: Get bit mask of all stream types in this channel
328 *
329 * PARAMETERS : None
330 *
331 * RETURN     : Bit mask of all stream types in this channel
332 *==========================================================================*/
333uint32_t QCamera3Channel::getStreamTypeMask()
334{
335    uint32_t mask = 0;
336    for (int i = 0; i < m_numStreams; i++) {
337       mask |= (0x1 << mStreams[i]->getMyType());
338    }
339    return mask;
340}
341
342/*===========================================================================
343 * FUNCTION   : getInternalFormatBuffer
344 *
345 * DESCRIPTION: return buffer in the internal format structure
346 *
347 * PARAMETERS :
348 *   @streamHandle : buffer handle
349 *
350 * RETURN     : stream object. NULL if not found
351 *==========================================================================*/
352mm_camera_buf_def_t* QCamera3RegularChannel::getInternalFormatBuffer(
353                                            buffer_handle_t * buffer)
354{
355    int32_t index;
356    if(buffer == NULL)
357        return NULL;
358    index = mMemory->getMatchBufIndex((void*)buffer);
359    if(index < 0) {
360        ALOGE("%s: Could not find object among registered buffers",__func__);
361        return NULL;
362    }
363    return mStreams[0]->getInternalFormatBuffer(index);
364}
365
366/*===========================================================================
367 * FUNCTION   : getStreamByHandle
368 *
369 * DESCRIPTION: return stream object by stream handle
370 *
371 * PARAMETERS :
372 *   @streamHandle : stream handle
373 *
374 * RETURN     : stream object. NULL if not found
375 *==========================================================================*/
376QCamera3Stream *QCamera3Channel::getStreamByHandle(uint32_t streamHandle)
377{
378    for (int i = 0; i < m_numStreams; i++) {
379        if (mStreams[i] != NULL && mStreams[i]->getMyHandle() == streamHandle) {
380            return mStreams[i];
381        }
382    }
383    return NULL;
384}
385
386/*===========================================================================
387 * FUNCTION   : getStreamByIndex
388 *
389 * DESCRIPTION: return stream object by index
390 *
391 * PARAMETERS :
392 *   @streamHandle : stream handle
393 *
394 * RETURN     : stream object. NULL if not found
395 *==========================================================================*/
396QCamera3Stream *QCamera3Channel::getStreamByIndex(uint8_t index)
397{
398    if (index < m_numStreams) {
399        return mStreams[index];
400    }
401    return NULL;
402}
403
404/*===========================================================================
405 * FUNCTION   : streamCbRoutine
406 *
407 * DESCRIPTION: callback routine for stream
408 *
409 * PARAMETERS :
410 *   @streamHandle : stream handle
411 *
412 * RETURN     : stream object. NULL if not found
413 *==========================================================================*/
414void QCamera3Channel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
415                QCamera3Stream *stream, void *userdata)
416{
417    QCamera3Channel *channel = (QCamera3Channel *)userdata;
418    if (channel == NULL) {
419        ALOGE("%s: invalid channel pointer", __func__);
420        return;
421    }
422    channel->streamCbRoutine(super_frame, stream);
423}
424
425/*===========================================================================
426 * FUNCTION   : QCamera3RegularChannel
427 *
428 * DESCRIPTION: constrcutor of QCamera3RegularChannel
429 *
430 * PARAMETERS :
431 *   @cam_handle : camera handle
432 *   @cam_ops    : ptr to camera ops table
433 *   @cb_routine : callback routine to frame aggregator
434 *   @stream     : camera3_stream_t structure
435 *
436 * RETURN     : none
437 *==========================================================================*/
438QCamera3RegularChannel::QCamera3RegularChannel(uint32_t cam_handle,
439                    mm_camera_ops_t *cam_ops,
440                    channel_cb_routine cb_routine,
441                    cam_padding_info_t *paddingInfo,
442                    void *userData,
443                    camera3_stream_t *stream) :
444                        QCamera3Channel(cam_handle, cam_ops, cb_routine,
445                                                paddingInfo, userData),
446                        mCamera3Stream(stream),
447                        mNumBufs(0),
448                        mCamera3Buffers(NULL),
449                        mMemory(NULL),
450                        mWidth(stream->width),
451                        mHeight(stream->height)
452{
453}
454
455/*===========================================================================
456 * FUNCTION   : QCamera3RegularChannel
457 *
458 * DESCRIPTION: constrcutor of QCamera3RegularChannel
459 *
460 * PARAMETERS :
461 *   @cam_handle : camera handle
462 *   @cam_ops    : ptr to camera ops table
463 *   @cb_routine : callback routine to frame aggregator
464 *   @stream     : camera3_stream_t structure
465 *
466 * RETURN     : none
467 *==========================================================================*/
468QCamera3RegularChannel::QCamera3RegularChannel(uint32_t cam_handle,
469                    mm_camera_ops_t *cam_ops,
470                    channel_cb_routine cb_routine,
471                    cam_padding_info_t *paddingInfo,
472                    void *userData,
473                    camera3_stream_t *stream,
474                    uint32_t width, uint32_t height) :
475                        QCamera3Channel(cam_handle, cam_ops, cb_routine,
476                                                paddingInfo, userData),
477                        mCamera3Stream(stream),
478                        mNumBufs(0),
479                        mCamera3Buffers(NULL),
480                        mMemory(NULL),
481                        mWidth(width),
482                        mHeight(height)
483{
484}
485
486/*===========================================================================
487 * FUNCTION   : ~QCamera3RegularChannel
488 *
489 * DESCRIPTION: destructor of QCamera3RegularChannel
490 *
491 * PARAMETERS : none
492 *
493 * RETURN     : none
494 *==========================================================================*/
495QCamera3RegularChannel::~QCamera3RegularChannel()
496{
497    if (mCamera3Buffers) {
498        delete[] mCamera3Buffers;
499    }
500}
501
502int32_t QCamera3RegularChannel::initialize()
503{
504  //TO DO
505  return 0;
506}
507
508/*===========================================================================
509 * FUNCTION   : request
510 *
511 * DESCRIPTION: process a request from camera service. Stream on if ncessary.
512 *
513 * PARAMETERS :
514 *   @buffer  : buffer to be filled for this request
515 *
516 * RETURN     : 0 on a success start of capture
517 *              -EINVAL on invalid input
518 *              -ENODEV on serious error
519 *==========================================================================*/
520int32_t QCamera3RegularChannel::request(buffer_handle_t *buffer, uint32_t frameNumber)
521{
522    //FIX ME: Return buffer back in case of failures below.
523
524    int32_t rc = NO_ERROR;
525    int index;
526    if(!m_bIsActive) {
527        ALOGD("%s: First request on this channel starting stream",__func__);
528        start();
529        if(rc != NO_ERROR) {
530            ALOGE("%s: Failed to start the stream on the request",__func__);
531            return rc;
532        }
533    } else {
534        ALOGV("%s: Request on an existing stream",__func__);
535    }
536
537    if(!mMemory) {
538        ALOGE("%s: error, Gralloc Memory object not yet created for this stream",__func__);
539        return NO_MEMORY;
540    }
541
542    index = mMemory->getMatchBufIndex((void*)buffer);
543    if(index < 0) {
544        ALOGE("%s: Could not find object among registered buffers",__func__);
545        return DEAD_OBJECT;
546    }
547
548    rc = mStreams[0]->bufDone(index);
549    if(rc != NO_ERROR) {
550        ALOGE("%s: Failed to Q new buffer to stream",__func__);
551        return rc;
552    }
553
554    rc = mMemory->markFrameNumber(index, frameNumber);
555    return rc;
556}
557
558/*===========================================================================
559 * FUNCTION   : registerBuffers
560 *
561 * DESCRIPTION: register streaming buffers to the channel object
562 *
563 * PARAMETERS :
564 *   @num_buffers : number of buffers to be registered
565 *   @buffers     : buffer to be registered
566 *
567 * RETURN     : 0 on a success start of capture
568 *              -EINVAL on invalid input
569 *              -ENOMEM on failure to register the buffer
570 *              -ENODEV on serious error
571 *==========================================================================*/
572int32_t QCamera3RegularChannel::registerBuffers(uint32_t num_buffers, buffer_handle_t **buffers)
573{
574    int rc = 0;
575    struct private_handle_t *priv_handle = (struct private_handle_t *)(*buffers[0]);
576    cam_stream_type_t streamType;
577    cam_format_t streamFormat;
578    cam_dimension_t streamDim;
579
580    rc = init(NULL, NULL);
581    if (rc < 0) {
582        ALOGE("%s: init failed", __func__);
583        return rc;
584    }
585
586    if (mCamera3Stream->format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
587        if (priv_handle->flags & private_handle_t::PRIV_FLAGS_VIDEO_ENCODER) {
588            streamType = CAM_STREAM_TYPE_VIDEO;
589            streamFormat = CAM_FORMAT_YUV_420_NV12;
590        } else if (priv_handle->flags & private_handle_t::PRIV_FLAGS_HW_TEXTURE) {
591            streamType = CAM_STREAM_TYPE_PREVIEW;
592            streamFormat = CAM_FORMAT_YUV_420_NV21;
593        } else {
594            //TODO: Add a new flag in libgralloc for ZSL buffers, and its size needs
595            // to be properly aligned and padded.
596            ALOGE("%s: priv_handle->flags 0x%x not supported",
597                    __func__, priv_handle->flags);
598            streamType = CAM_STREAM_TYPE_SNAPSHOT;
599            streamFormat = CAM_FORMAT_YUV_420_NV21;
600        }
601    } else if(mCamera3Stream->format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
602         streamType = CAM_STREAM_TYPE_CALLBACK;
603         streamFormat = CAM_FORMAT_YUV_420_NV21;
604    } else {
605        //TODO: Fail for other types of streams for now
606        ALOGE("%s: format is not IMPLEMENTATION_DEFINED or flexible", __func__);
607        return -EINVAL;
608    }
609
610    /* Bookkeep buffer set because they go out of scope after register call */
611    mNumBufs = num_buffers;
612    mCamera3Buffers = new buffer_handle_t*[num_buffers];
613    if (mCamera3Buffers == NULL) {
614        ALOGE("%s: Failed to allocate buffer_handle_t*", __func__);
615        return -ENOMEM;
616    }
617    for (size_t i = 0; i < num_buffers; i++)
618        mCamera3Buffers[i] = buffers[i];
619
620    streamDim.width = mWidth;
621    streamDim.height = mHeight;
622
623    rc = QCamera3Channel::addStream(streamType, streamFormat, streamDim,
624        num_buffers);
625    return rc;
626}
627
628void QCamera3RegularChannel::streamCbRoutine(
629                            mm_camera_super_buf_t *super_frame,
630                            QCamera3Stream *stream)
631{
632    //FIXME Q Buf back in case of error?
633    uint8_t frameIndex;
634    buffer_handle_t *resultBuffer;
635    int32_t resultFrameNumber;
636    camera3_stream_buffer_t result;
637
638    if(!super_frame) {
639         ALOGE("%s: Invalid Super buffer",__func__);
640         return;
641    }
642
643    if(super_frame->num_bufs != 1) {
644         ALOGE("%s: Multiple streams are not supported",__func__);
645         return;
646    }
647    if(super_frame->bufs[0] == NULL ) {
648         ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
649                  __func__);
650         return;
651    }
652
653    frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
654    if(frameIndex >= mNumBufs) {
655         ALOGE("%s: Error, Invalid index for buffer",__func__);
656         if(stream) {
657             stream->bufDone(frameIndex);
658         }
659         return;
660    }
661
662    ////Use below data to issue framework callback
663    resultBuffer = mCamera3Buffers[frameIndex];
664    resultFrameNumber = mMemory->getFrameNumber(frameIndex);
665
666    result.stream = mCamera3Stream;
667    result.buffer = resultBuffer;
668    result.status = CAMERA3_BUFFER_STATUS_OK;
669    result.acquire_fence = -1;
670    result.release_fence = -1;
671
672    mChannelCB(NULL, &result, resultFrameNumber, mUserData);
673    free(super_frame);
674    return;
675}
676
677QCamera3Memory* QCamera3RegularChannel::getStreamBufs(uint32_t /*len*/)
678{
679    if (mNumBufs == 0 || mCamera3Buffers == NULL) {
680        ALOGE("%s: buffers not registered yet", __func__);
681        return NULL;
682    }
683
684    mMemory = new QCamera3GrallocMemory();
685    if (mMemory == NULL) {
686        return NULL;
687    }
688
689    if (mMemory->registerBuffers(mNumBufs, mCamera3Buffers) < 0) {
690        delete mMemory;
691        mMemory = NULL;
692        return NULL;
693    }
694    return mMemory;
695}
696
697void QCamera3RegularChannel::putStreamBufs()
698{
699    mMemory->unregisterBuffers();
700    delete mMemory;
701    mMemory = NULL;
702}
703
704int QCamera3RegularChannel::kMaxBuffers = 7;
705
706QCamera3MetadataChannel::QCamera3MetadataChannel(uint32_t cam_handle,
707                    mm_camera_ops_t *cam_ops,
708                    channel_cb_routine cb_routine,
709                    cam_padding_info_t *paddingInfo,
710                    void *userData) :
711                        QCamera3Channel(cam_handle, cam_ops,
712                                cb_routine, paddingInfo, userData),
713                        mMemory(NULL)
714{
715}
716
717QCamera3MetadataChannel::~QCamera3MetadataChannel()
718{
719    if (m_bIsActive)
720        stop();
721
722    if (mMemory) {
723        mMemory->deallocate();
724        delete mMemory;
725        mMemory = NULL;
726    }
727}
728
729int32_t QCamera3MetadataChannel::initialize()
730{
731    int32_t rc;
732    cam_dimension_t streamDim;
733
734    if (mMemory || m_numStreams > 0) {
735        ALOGE("%s: metadata channel already initialized", __func__);
736        return -EINVAL;
737    }
738
739    rc = init(NULL, NULL);
740    if (rc < 0) {
741        ALOGE("%s: init failed", __func__);
742        return rc;
743    }
744
745    streamDim.width = sizeof(metadata_buffer_t),
746    streamDim.height = 1;
747    rc = QCamera3Channel::addStream(CAM_STREAM_TYPE_METADATA, CAM_FORMAT_MAX,
748        streamDim, MIN_STREAMING_BUFFER_NUM);
749    if (rc < 0) {
750        ALOGE("%s: addStream failed", __func__);
751    }
752    return rc;
753}
754
755int32_t QCamera3MetadataChannel::request(buffer_handle_t * /*buffer*/,
756                                                uint32_t /*frameNumber*/)
757{
758    if (!m_bIsActive) {
759        return start();
760    }
761    else
762        return 0;
763}
764
765int32_t QCamera3MetadataChannel::registerBuffers(uint32_t /*num_buffers*/,
766                                        buffer_handle_t ** /*buffers*/)
767{
768    // no registerBuffers are supported for metadata channel
769    return -EINVAL;
770}
771
772void QCamera3MetadataChannel::streamCbRoutine(
773                        mm_camera_super_buf_t *super_frame,
774                        QCamera3Stream *stream)
775{
776    uint32_t requestNumber = 0;
777    if (super_frame == NULL || super_frame->num_bufs != 1) {
778        ALOGE("%s: super_frame is not valid", __func__);
779        return;
780    }
781    mChannelCB(super_frame, NULL, requestNumber, mUserData);
782}
783
784QCamera3Memory* QCamera3MetadataChannel::getStreamBufs(uint32_t len)
785{
786    int rc;
787    if (len < sizeof(metadata_buffer_t)) {
788        ALOGE("%s: size doesn't match %d vs %d", __func__,
789                len, sizeof(metadata_buffer_t));
790        return NULL;
791    }
792    mMemory = new QCamera3HeapMemory();
793    if (!mMemory) {
794        ALOGE("%s: unable to create metadata memory", __func__);
795        return NULL;
796    }
797    rc = mMemory->allocate(MIN_STREAMING_BUFFER_NUM, len, true);
798    if (rc < 0) {
799        ALOGE("%s: unable to allocate metadata memory", __func__);
800        delete mMemory;
801        mMemory = NULL;
802        return NULL;
803    }
804    memset(mMemory->getPtr(0), 0, sizeof(metadata_buffer_t));
805    return mMemory;
806}
807
808void QCamera3MetadataChannel::putStreamBufs()
809{
810    mMemory->deallocate();
811    delete mMemory;
812    mMemory = NULL;
813}
814
815/*===========================================================================
816 * FUNCTION   : jpegEvtHandle
817 *
818 * DESCRIPTION: Function registerd to mm-jpeg-interface to handle jpeg events.
819                Construct result payload and call mChannelCb to deliver buffer
820                to framework.
821 *
822 * PARAMETERS :
823 *   @status    : status of jpeg job
824 *   @client_hdl: jpeg client handle
825 *   @jobId     : jpeg job Id
826 *   @p_ouput   : ptr to jpeg output result struct
827 *   @userdata  : user data ptr
828 *
829 * RETURN     : none
830 *==========================================================================*/
831void QCamera3PicChannel::jpegEvtHandle(jpeg_job_status_t status,
832                                              uint32_t /*client_hdl*/,
833                                              uint32_t jobId,
834                                              mm_jpeg_output_t *p_output,
835                                              void *userdata)
836{
837    buffer_handle_t *resultBuffer;
838    int32_t resultFrameNumber;
839    int resultStatus = CAMERA3_BUFFER_STATUS_OK;
840    camera3_stream_buffer_t result;
841    camera3_jpeg_blob_t jpegHeader;
842    char* jpeg_eof = 0;
843    int maxJpegSize;
844    QCamera3PicChannel *obj = (QCamera3PicChannel *)userdata;
845    if (obj) {
846        //Construct payload for process_capture_result. Call mChannelCb
847
848        qcamera_jpeg_data_t *job = obj->m_postprocessor.findJpegJobByJobId(jobId);
849
850        if ((job == NULL) || (status == JPEG_JOB_STATUS_ERROR)) {
851            ALOGE("%s: Error in jobId: (%d) with status: %d", __func__, jobId, status);
852            resultStatus = CAMERA3_BUFFER_STATUS_ERROR;
853        }
854
855        //Construct jpeg transient header of type camera3_jpeg_blob_t
856        //Append at the end of jpeg image of buf_filled_len size
857
858        jpegHeader.jpeg_blob_id = CAMERA3_JPEG_BLOB_ID;
859        jpegHeader.jpeg_size = p_output->buf_filled_len;
860
861
862        char* jpeg_buf = (char *)p_output->buf_vaddr;
863
864        if(obj->mJpegSettings->max_jpeg_size <= 0 ||
865                obj->mJpegSettings->max_jpeg_size > obj->mMemory->getSize(obj->mCurrentBufIndex)){
866            ALOGE("%s:Max Jpeg size :%d is out of valid range setting to size of buffer",
867                    __func__, obj->mJpegSettings->max_jpeg_size);
868            maxJpegSize =  obj->mMemory->getSize(obj->mCurrentBufIndex);
869        } else {
870            maxJpegSize = obj->mJpegSettings->max_jpeg_size;
871            ALOGE("%s: Setting max jpeg size to %d",__func__, maxJpegSize);
872        }
873        jpeg_eof = &jpeg_buf[maxJpegSize-sizeof(jpegHeader)];
874        memcpy(jpeg_eof, &jpegHeader, sizeof(jpegHeader));
875        obj->mMemory->cleanInvalidateCache(obj->mCurrentBufIndex);
876
877        ////Use below data to issue framework callback
878        resultBuffer = obj->mCamera3Buffers[obj->mCurrentBufIndex];
879        resultFrameNumber = obj->mMemory->getFrameNumber(obj->mCurrentBufIndex);
880
881        result.stream = obj->mCamera3Stream;
882        result.buffer = resultBuffer;
883        result.status = resultStatus;
884        result.acquire_fence = -1;
885        result.release_fence = -1;
886
887        ALOGV("%s: Issue Callback", __func__);
888        obj->mChannelCB(NULL, &result, resultFrameNumber, obj->mUserData);
889
890        // release internal data for jpeg job
891        if (job != NULL) {
892            obj->m_postprocessor.releaseJpegJobData(job);
893            free(job);
894        }
895        return;
896        // }
897    } else {
898        ALOGE("%s: Null userdata in jpeg callback", __func__);
899    }
900}
901
902QCamera3PicChannel::QCamera3PicChannel(uint32_t cam_handle,
903                    mm_camera_ops_t *cam_ops,
904                    channel_cb_routine cb_routine,
905                    cam_padding_info_t *paddingInfo,
906                    void *userData,
907                    camera3_stream_t *stream) :
908                        QCamera3Channel(cam_handle, cam_ops, cb_routine,
909                        paddingInfo, userData),
910                        m_postprocessor(this),
911                        mCamera3Stream(stream),
912                        mNumBufs(0),
913                        mCamera3Buffers(NULL),
914                        mJpegSettings(NULL),
915                        mCurrentBufIndex(-1),
916                        mMemory(NULL),
917                        mYuvMemory(NULL)
918{
919    int32_t rc = m_postprocessor.init(jpegEvtHandle, this);
920    if (rc != 0) {
921        ALOGE("Init Postprocessor failed");
922    }
923}
924
925QCamera3PicChannel::~QCamera3PicChannel()
926{
927    int32_t rc = m_postprocessor.deinit();
928    if (rc != 0) {
929        ALOGE("De-init Postprocessor failed");
930    }
931    if (mCamera3Buffers) {
932        delete[] mCamera3Buffers;
933    }
934}
935
936int32_t QCamera3PicChannel::initialize()
937{
938    int32_t rc = NO_ERROR;
939    cam_dimension_t streamDim;
940    cam_stream_type_t streamType;
941    cam_format_t streamFormat;
942    mm_camera_channel_attr_t attr;
943
944    memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
945    attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_BURST;
946    attr.look_back = 1;
947    attr.post_frame_skip = 1;
948    attr.water_mark = 1;
949    attr.max_unmatched_frames = 1;
950
951    rc = init(&attr, NULL);
952    if (rc < 0) {
953        ALOGE("%s: init failed", __func__);
954        return rc;
955    }
956
957    streamType = CAM_STREAM_TYPE_NON_ZSL_SNAPSHOT;
958    streamFormat = CAM_FORMAT_YUV_420_NV21;
959    streamDim.width = mCamera3Stream->width;
960    streamDim.height = mCamera3Stream->height;
961
962    int num_buffers = 1;
963
964    rc = QCamera3Channel::addStream(streamType, streamFormat, streamDim,
965            num_buffers);
966
967    return rc;
968}
969
970int32_t QCamera3PicChannel::request(buffer_handle_t *buffer,
971        uint32_t frameNumber, jpeg_settings_t* jpegSettings,
972        mm_camera_buf_def_t *pInputBuffer,QCamera3Channel* pInputChannel)
973{
974    //FIX ME: Return buffer back in case of failures below.
975
976    int32_t rc = NO_ERROR;
977    int index;
978    mJpegSettings = jpegSettings;
979    if(!m_bIsActive) {
980        ALOGD("%s: First request on this channel starting stream",__func__);
981        //Stream on for main image. YUV buffer is queued to the kernel at the end of this call.
982        if(!pInputBuffer)
983            rc = start();
984        else
985            ALOGD("%s: Current request has input buffer no need to start h/w stream", __func__);
986    } else {
987        mStreams[0]->bufDone(0);
988        ALOGD("%s: Request on an existing stream",__func__);
989    }
990
991    if(rc != NO_ERROR) {
992        ALOGE("%s: Failed to start the stream on the request",__func__);
993        return rc;
994    }
995
996
997    if(!mMemory) {
998        if(pInputBuffer) {
999            mMemory = new QCamera3GrallocMemory();
1000            if (mMemory == NULL) {
1001                return NO_MEMORY;
1002            }
1003
1004            //Registering Jpeg output buffer
1005            if (mMemory->registerBuffers(mNumBufs, mCamera3Buffers) < 0) {
1006                delete mMemory;
1007                mMemory = NULL;
1008                return NO_MEMORY;
1009            }
1010        } else {
1011            ALOGE("%s: error, Gralloc Memory object not yet created for this stream",__func__);
1012            return NO_MEMORY;
1013        }
1014    }
1015
1016    index = mMemory->getMatchBufIndex((void*)buffer);
1017    if(index < 0) {
1018        ALOGE("%s: Could not find object among registered buffers",__func__);
1019        return DEAD_OBJECT;
1020    }
1021    rc = mMemory->markFrameNumber(index, frameNumber);
1022
1023    //Start the postprocessor for jpeg encoding. Pass mMemory as destination buffer
1024    mCurrentBufIndex = index;
1025
1026    m_postprocessor.start(mMemory, index, this);
1027
1028    ALOGD("%s: Post-process started", __func__);
1029    if(pInputBuffer) {
1030        ALOGD("%s: Issue call to reprocess", __func__);
1031        m_postprocessor.processAuxiliaryData(pInputBuffer,pInputChannel);
1032    }
1033    return rc;
1034}
1035
1036/*===========================================================================
1037 * FUNCTION   : dataNotifyCB
1038 *
1039 * DESCRIPTION: Channel Level callback used for super buffer data notify.
1040 *              This function is registered with mm-camera-interface to handle
1041 *              data notify
1042 *
1043 * PARAMETERS :
1044 *   @recvd_frame   : stream frame received
1045 *   userdata       : user data ptr
1046 *
1047 * RETURN     : none
1048 *==========================================================================*/
1049void QCamera3PicChannel::dataNotifyCB(mm_camera_super_buf_t *recvd_frame,
1050                                 void *userdata)
1051{
1052    ALOGV("%s: E\n", __func__);
1053    QCamera3PicChannel *channel = (QCamera3PicChannel *)userdata;
1054
1055    if (channel == NULL) {
1056        ALOGE("%s: invalid channel pointer", __func__);
1057        return;
1058    }
1059
1060    if(channel->m_numStreams != 1) {
1061        ALOGE("%s: Error: Bug: This callback assumes one stream per channel",__func__);
1062        return;
1063    }
1064
1065
1066    if(channel->mStreams[0] == NULL) {
1067        ALOGE("%s: Error: Invalid Stream object",__func__);
1068        return;
1069    }
1070
1071    channel->QCamera3PicChannel::streamCbRoutine(recvd_frame, channel->mStreams[0]);
1072
1073    ALOGV("%s: X\n", __func__);
1074    return;
1075}
1076
1077
1078int32_t QCamera3PicChannel::registerBuffers(uint32_t num_buffers,
1079                        buffer_handle_t **buffers)
1080{
1081    int rc = 0;
1082    cam_stream_type_t streamType;
1083    cam_format_t streamFormat;
1084
1085    ALOGV("%s: E",__func__);
1086    rc = QCamera3PicChannel::initialize();
1087    if (rc < 0) {
1088        ALOGE("%s: init failed", __func__);
1089        return rc;
1090    }
1091
1092    if (mCamera3Stream->format == HAL_PIXEL_FORMAT_BLOB) {
1093        streamType = CAM_STREAM_TYPE_NON_ZSL_SNAPSHOT;
1094        streamFormat = CAM_FORMAT_YUV_420_NV21;
1095    } else {
1096        //TODO: Fail for other types of streams for now
1097        ALOGE("%s: format is not BLOB", __func__);
1098        return -EINVAL;
1099    }
1100    /* Bookkeep buffer set because they go out of scope after register call */
1101    mNumBufs = num_buffers;
1102    mCamera3Buffers = new buffer_handle_t*[num_buffers];
1103    if (mCamera3Buffers == NULL) {
1104        ALOGE("%s: Failed to allocate buffer_handle_t*", __func__);
1105        return -ENOMEM;
1106    }
1107    for (size_t i = 0; i < num_buffers; i++)
1108        mCamera3Buffers[i] = buffers[i];
1109
1110    ALOGV("%s: X",__func__);
1111    return rc;
1112}
1113
1114void QCamera3PicChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
1115                            QCamera3Stream *stream)
1116{
1117    //TODO
1118    //Used only for getting YUV. Jpeg callback will be sent back from channel
1119    //directly to HWI. Refer to func jpegEvtHandle
1120
1121    //Got the yuv callback. Calling yuv callback handler in PostProc
1122    uint8_t frameIndex;
1123    mm_camera_super_buf_t* frame = NULL;
1124    if(!super_frame) {
1125         ALOGE("%s: Invalid Super buffer",__func__);
1126         return;
1127    }
1128
1129    if(super_frame->num_bufs != 1) {
1130         ALOGE("%s: Multiple streams are not supported",__func__);
1131         return;
1132    }
1133    if(super_frame->bufs[0] == NULL ) {
1134         ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
1135                  __func__);
1136         return;
1137    }
1138
1139    frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
1140    if(frameIndex >= mNumBufs) {
1141         ALOGE("%s: Error, Invalid index for buffer",__func__);
1142         if(stream) {
1143             stream->bufDone(frameIndex);
1144         }
1145         return;
1146    }
1147
1148    frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
1149    if (frame == NULL) {
1150       ALOGE("%s: Error allocating memory to save received_frame structure.",
1151                                                                    __func__);
1152       if(stream) {
1153           stream->bufDone(frameIndex);
1154       }
1155       return;
1156    }
1157    *frame = *super_frame;
1158
1159    m_postprocessor.processData(frame);
1160    free(super_frame);
1161    return;
1162}
1163
1164QCamera3Memory* QCamera3PicChannel::getStreamBufs(uint32_t len)
1165{
1166    int rc = 0;
1167
1168    if (mNumBufs == 0 || mCamera3Buffers == NULL) {
1169        ALOGE("%s: buffers not registered yet", __func__);
1170        return NULL;
1171    }
1172
1173    if(mMemory) {
1174        delete mMemory;
1175        mMemory = NULL;
1176    }
1177    mMemory = new QCamera3GrallocMemory();
1178    if (mMemory == NULL) {
1179        return NULL;
1180    }
1181
1182    //Registering Jpeg output buffer
1183    if (mMemory->registerBuffers(mNumBufs, mCamera3Buffers) < 0) {
1184        delete mMemory;
1185        mMemory = NULL;
1186        return NULL;
1187    }
1188
1189    mYuvMemory = new QCamera3HeapMemory();
1190    if (!mYuvMemory) {
1191        ALOGE("%s: unable to create metadata memory", __func__);
1192        return NULL;
1193    }
1194
1195    //Queue YUV buffers in the beginning mQueueAll = true
1196    rc = mYuvMemory->allocate(1, len, true);
1197    if (rc < 0) {
1198        ALOGE("%s: unable to allocate metadata memory", __func__);
1199        delete mYuvMemory;
1200        mYuvMemory = NULL;
1201        return NULL;
1202    }
1203    return mYuvMemory;
1204}
1205
1206void QCamera3PicChannel::putStreamBufs()
1207{
1208    mMemory->unregisterBuffers();
1209    delete mMemory;
1210    mMemory = NULL;
1211
1212    mYuvMemory->deallocate();
1213    delete mYuvMemory;
1214    mYuvMemory = NULL;
1215}
1216
1217bool QCamera3PicChannel::isRawSnapshot()
1218{
1219   return !(mJpegSettings->is_jpeg_format);
1220}
1221/*===========================================================================
1222 * FUNCTION   : getThumbnailSize
1223 *
1224 * DESCRIPTION: get user set thumbnail size
1225 *
1226 * PARAMETERS :
1227 *   @dim     : output of thumbnail dimension
1228 *
1229 * RETURN     : none
1230 *==========================================================================*/
1231void QCamera3PicChannel::getThumbnailSize(cam_dimension_t &dim)
1232{
1233    dim = mJpegSettings->thumbnail_size;
1234}
1235
1236/*===========================================================================
1237 * FUNCTION   : getJpegQuality
1238 *
1239 * DESCRIPTION: get user set jpeg quality
1240 *
1241 * PARAMETERS : none
1242 *
1243 * RETURN     : jpeg quality setting
1244 *==========================================================================*/
1245int QCamera3PicChannel::getJpegQuality()
1246{
1247    int quality = mJpegSettings->jpeg_quality;
1248    if (quality < 0) {
1249        quality = 85;  //set to default quality value
1250    }
1251    return quality;
1252}
1253
1254/*===========================================================================
1255 * FUNCTION   : getJpegRotation
1256 *
1257 * DESCRIPTION: get rotation information to be passed into jpeg encoding
1258 *
1259 * PARAMETERS : none
1260 *
1261 * RETURN     : rotation information
1262 *==========================================================================*/
1263int QCamera3PicChannel::getJpegRotation() {
1264    int rotation = mJpegSettings->jpeg_orientation;
1265    if (rotation < 0) {
1266        rotation = 0;
1267    }
1268    return rotation;
1269}
1270
1271void QCamera3PicChannel::queueMetadata(mm_camera_super_buf_t *metadata_buf)
1272{
1273    m_postprocessor.processPPMetadata(metadata_buf);
1274}
1275/*===========================================================================
1276 * FUNCTION   : getRational
1277 *
1278 * DESCRIPTION: compose rational struct
1279 *
1280 * PARAMETERS :
1281 *   @rat     : ptr to struct to store rational info
1282 *   @num     :num of the rational
1283 *   @denom   : denom of the rational
1284 *
1285 * RETURN     : int32_t type of status
1286 *              NO_ERROR  -- success
1287 *              none-zero failure code
1288 *==========================================================================*/
1289int32_t getRational(rat_t *rat, int num, int denom)
1290{
1291    if (NULL == rat) {
1292        ALOGE("%s: NULL rat input", __func__);
1293        return BAD_VALUE;
1294    }
1295    rat->num = num;
1296    rat->denom = denom;
1297    return NO_ERROR;
1298}
1299
1300/*===========================================================================
1301 * FUNCTION   : parseGPSCoordinate
1302 *
1303 * DESCRIPTION: parse GPS coordinate string
1304 *
1305 * PARAMETERS :
1306 *   @coord_str : [input] coordinate string
1307 *   @coord     : [output]  ptr to struct to store coordinate
1308 *
1309 * RETURN     : int32_t type of status
1310 *              NO_ERROR  -- success
1311 *              none-zero failure code
1312 *==========================================================================*/
1313int parseGPSCoordinate(const char *coord_str, rat_t* coord)
1314{
1315    if(coord == NULL) {
1316        ALOGE("%s: error, invalid argument coord == NULL", __func__);
1317        return BAD_VALUE;
1318    }
1319    float degF = atof(coord_str);
1320    if (degF < 0) {
1321        degF = -degF;
1322    }
1323    float minF = (degF - (int) degF) * 60;
1324    float secF = (minF - (int) minF) * 60;
1325
1326    getRational(&coord[0], (int)degF, 1);
1327    getRational(&coord[1], (int)minF, 1);
1328    getRational(&coord[2], (int)(secF * 10000), 10000);
1329    return NO_ERROR;
1330}
1331
1332/*===========================================================================
1333 * FUNCTION   : getExifDateTime
1334 *
1335 * DESCRIPTION: query exif date time
1336 *
1337 * PARAMETERS :
1338 *   @dateTime : string to store exif date time
1339 *   @count    : lenght of the dateTime string
1340 *
1341 * RETURN     : int32_t type of status
1342 *              NO_ERROR  -- success
1343 *              none-zero failure code
1344 *==========================================================================*/
1345int32_t getExifDateTime(char *dateTime, uint32_t &count)
1346{
1347    //get time and date from system
1348    time_t rawtime;
1349    struct tm * timeinfo;
1350    time(&rawtime);
1351    timeinfo = localtime (&rawtime);
1352    //Write datetime according to EXIF Spec
1353    //"YYYY:MM:DD HH:MM:SS" (20 chars including \0)
1354    snprintf(dateTime, 20, "%04d:%02d:%02d %02d:%02d:%02d",
1355             timeinfo->tm_year + 1900, timeinfo->tm_mon + 1,
1356             timeinfo->tm_mday, timeinfo->tm_hour,
1357             timeinfo->tm_min, timeinfo->tm_sec);
1358    count = 20;
1359
1360    return NO_ERROR;
1361}
1362
1363/*===========================================================================
1364 * FUNCTION   : getExifFocalLength
1365 *
1366 * DESCRIPTION: get exif focal lenght
1367 *
1368 * PARAMETERS :
1369 *   @focalLength : ptr to rational strcut to store focal lenght
1370 *
1371 * RETURN     : int32_t type of status
1372 *              NO_ERROR  -- success
1373 *              none-zero failure code
1374 *==========================================================================*/
1375int32_t getExifFocalLength(rat_t *focalLength, float value)
1376{
1377    int focalLengthValue =
1378        (int)(value * FOCAL_LENGTH_DECIMAL_PRECISION);
1379    return getRational(focalLength, focalLengthValue, FOCAL_LENGTH_DECIMAL_PRECISION);
1380}
1381
1382/*===========================================================================
1383 * FUNCTION   : getExifGpsProcessingMethod
1384 *
1385 * DESCRIPTION: get GPS processing method
1386 *
1387 * PARAMETERS :
1388 *   @gpsProcessingMethod : string to store GPS process method
1389 *   @count               : lenght of the string
1390 *
1391 * RETURN     : int32_t type of status
1392 *              NO_ERROR  -- success
1393 *              none-zero failure code
1394 *==========================================================================*/
1395int32_t getExifGpsProcessingMethod(char *gpsProcessingMethod,
1396                                   uint32_t &count, char* value)
1397{
1398    if(value != NULL) {
1399        memcpy(gpsProcessingMethod, ExifAsciiPrefix, EXIF_ASCII_PREFIX_SIZE);
1400        count = EXIF_ASCII_PREFIX_SIZE;
1401        strncpy(gpsProcessingMethod + EXIF_ASCII_PREFIX_SIZE, value, strlen(value));
1402        count += strlen(value);
1403        gpsProcessingMethod[count++] = '\0'; // increase 1 for the last NULL char
1404        return NO_ERROR;
1405    } else {
1406        return BAD_VALUE;
1407    }
1408}
1409
1410/*===========================================================================
1411 * FUNCTION   : getExifLatitude
1412 *
1413 * DESCRIPTION: get exif latitude
1414 *
1415 * PARAMETERS :
1416 *   @latitude : ptr to rational struct to store latitude info
1417 *   @ladRef   : charater to indicate latitude reference
1418 *
1419 * RETURN     : int32_t type of status
1420 *              NO_ERROR  -- success
1421 *              none-zero failure code
1422 *==========================================================================*/
1423int32_t getExifLatitude(rat_t *latitude,
1424                                           char *latRef, double value)
1425{
1426    char str[30];
1427    snprintf(str, sizeof(str), "%f", value);
1428    if(str != NULL) {
1429        parseGPSCoordinate(str, latitude);
1430
1431        //set Latitude Ref
1432        float latitudeValue = strtof(str, 0);
1433        if(latitudeValue < 0.0f) {
1434            latRef[0] = 'S';
1435        } else {
1436            latRef[0] = 'N';
1437        }
1438        latRef[1] = '\0';
1439        return NO_ERROR;
1440    }else{
1441        return BAD_VALUE;
1442    }
1443}
1444
1445/*===========================================================================
1446 * FUNCTION   : getExifLongitude
1447 *
1448 * DESCRIPTION: get exif longitude
1449 *
1450 * PARAMETERS :
1451 *   @longitude : ptr to rational struct to store longitude info
1452 *   @lonRef    : charater to indicate longitude reference
1453 *
1454 * RETURN     : int32_t type of status
1455 *              NO_ERROR  -- success
1456 *              none-zero failure code
1457 *==========================================================================*/
1458int32_t getExifLongitude(rat_t *longitude,
1459                                            char *lonRef, double value)
1460{
1461    char str[30];
1462    snprintf(str, sizeof(str), "%f", value);
1463    if(str != NULL) {
1464        parseGPSCoordinate(str, longitude);
1465
1466        //set Longitude Ref
1467        float longitudeValue = strtof(str, 0);
1468        if(longitudeValue < 0.0f) {
1469            lonRef[0] = 'W';
1470        } else {
1471            lonRef[0] = 'E';
1472        }
1473        lonRef[1] = '\0';
1474        return NO_ERROR;
1475    }else{
1476        return BAD_VALUE;
1477    }
1478}
1479
1480/*===========================================================================
1481 * FUNCTION   : getExifAltitude
1482 *
1483 * DESCRIPTION: get exif altitude
1484 *
1485 * PARAMETERS :
1486 *   @altitude : ptr to rational struct to store altitude info
1487 *   @altRef   : charater to indicate altitude reference
1488 *
1489 * RETURN     : int32_t type of status
1490 *              NO_ERROR  -- success
1491 *              none-zero failure code
1492 *==========================================================================*/
1493int32_t getExifAltitude(rat_t *altitude,
1494                                           char *altRef, double value)
1495{
1496    char str[30];
1497    snprintf(str, sizeof(str), "%f", value);
1498    if(str != NULL) {
1499        double value = atof(str);
1500        *altRef = 0;
1501        if(value < 0){
1502            *altRef = 1;
1503            value = -value;
1504        }
1505        return getRational(altitude, value*1000, 1000);
1506    }else{
1507        return BAD_VALUE;
1508    }
1509}
1510
1511/*===========================================================================
1512 * FUNCTION   : getExifGpsDateTimeStamp
1513 *
1514 * DESCRIPTION: get exif GPS date time stamp
1515 *
1516 * PARAMETERS :
1517 *   @gpsDateStamp : GPS date time stamp string
1518 *   @bufLen       : length of the string
1519 *   @gpsTimeStamp : ptr to rational struct to store time stamp info
1520 *
1521 * RETURN     : int32_t type of status
1522 *              NO_ERROR  -- success
1523 *              none-zero failure code
1524 *==========================================================================*/
1525int32_t getExifGpsDateTimeStamp(char *gpsDateStamp,
1526                                           uint32_t bufLen,
1527                                           rat_t *gpsTimeStamp, int64_t value)
1528{
1529    char str[30];
1530    snprintf(str, sizeof(str), "%lld", value);
1531    if(str != NULL) {
1532        time_t unixTime = (time_t)atol(str);
1533        struct tm *UTCTimestamp = gmtime(&unixTime);
1534
1535        strftime(gpsDateStamp, bufLen, "%Y:%m:%d", UTCTimestamp);
1536
1537        getRational(&gpsTimeStamp[0], UTCTimestamp->tm_hour, 1);
1538        getRational(&gpsTimeStamp[1], UTCTimestamp->tm_min, 1);
1539        getRational(&gpsTimeStamp[2], UTCTimestamp->tm_sec, 1);
1540
1541        return NO_ERROR;
1542    } else {
1543        return BAD_VALUE;
1544    }
1545}
1546
1547int32_t getExifExposureValue(srat_t* exposure_val, int32_t exposure_comp,
1548                             cam_rational_type_t step)
1549{
1550    exposure_val->num = exposure_comp * step.numerator;
1551    exposure_val->denom = step.denominator;
1552    return 0;
1553}
1554/*===========================================================================
1555 * FUNCTION   : getExifData
1556 *
1557 * DESCRIPTION: get exif data to be passed into jpeg encoding
1558 *
1559 * PARAMETERS : none
1560 *
1561 * RETURN     : exif data from user setting and GPS
1562 *==========================================================================*/
1563QCamera3Exif *QCamera3PicChannel::getExifData()
1564{
1565    QCamera3Exif *exif = new QCamera3Exif();
1566    if (exif == NULL) {
1567        ALOGE("%s: No memory for QCamera3Exif", __func__);
1568        return NULL;
1569    }
1570
1571    int32_t rc = NO_ERROR;
1572    uint32_t count = 0;
1573
1574    // add exif entries
1575    char dateTime[20];
1576    memset(dateTime, 0, sizeof(dateTime));
1577    count = 20;
1578    rc = getExifDateTime(dateTime, count);
1579    if(rc == NO_ERROR) {
1580        exif->addEntry(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL,
1581                       EXIF_ASCII,
1582                       count,
1583                       (void *)dateTime);
1584    } else {
1585        ALOGE("%s: getExifDateTime failed", __func__);
1586    }
1587
1588    rat_t focalLength;
1589    rc = getExifFocalLength(&focalLength, mJpegSettings->lens_focal_length);
1590    if (rc == NO_ERROR) {
1591        exif->addEntry(EXIFTAGID_FOCAL_LENGTH,
1592                       EXIF_RATIONAL,
1593                       1,
1594                       (void *)&(focalLength));
1595    } else {
1596        ALOGE("%s: getExifFocalLength failed", __func__);
1597    }
1598
1599    uint16_t isoSpeed = (uint16_t)mJpegSettings->sensor_sensitivity;
1600    exif->addEntry(EXIFTAGID_ISO_SPEED_RATING,
1601                   EXIF_SHORT,
1602                   1,
1603                   (void *)&(isoSpeed));
1604
1605
1606    if (strlen(mJpegSettings->gps_processing_method) > 0) {
1607        char gpsProcessingMethod[EXIF_ASCII_PREFIX_SIZE + GPS_PROCESSING_METHOD_SIZE];
1608        count = 0;
1609        rc = getExifGpsProcessingMethod(gpsProcessingMethod, count, mJpegSettings->gps_processing_method);
1610        if(rc == NO_ERROR) {
1611            exif->addEntry(EXIFTAGID_GPS_PROCESSINGMETHOD,
1612                           EXIF_ASCII,
1613                           count,
1614                           (void *)gpsProcessingMethod);
1615        } else {
1616            ALOGE("%s: getExifGpsProcessingMethod failed", __func__);
1617        }
1618    }
1619
1620    if (mJpegSettings->gps_coordinates[0]) {
1621        rat_t latitude[3];
1622        char latRef[2];
1623        rc = getExifLatitude(latitude, latRef, *(mJpegSettings->gps_coordinates[0]));
1624        if(rc == NO_ERROR) {
1625            exif->addEntry(EXIFTAGID_GPS_LATITUDE,
1626                           EXIF_RATIONAL,
1627                           3,
1628                           (void *)latitude);
1629            exif->addEntry(EXIFTAGID_GPS_LATITUDE_REF,
1630                           EXIF_ASCII,
1631                           2,
1632                           (void *)latRef);
1633        } else {
1634            ALOGE("%s: getExifLatitude failed", __func__);
1635        }
1636    }
1637
1638    if (mJpegSettings->gps_coordinates[1]) {
1639        rat_t longitude[3];
1640        char lonRef[2];
1641        rc = getExifLongitude(longitude, lonRef, *(mJpegSettings->gps_coordinates[1]));
1642        if(rc == NO_ERROR) {
1643            exif->addEntry(EXIFTAGID_GPS_LONGITUDE,
1644                           EXIF_RATIONAL,
1645                           3,
1646                           (void *)longitude);
1647
1648            exif->addEntry(EXIFTAGID_GPS_LONGITUDE_REF,
1649                           EXIF_ASCII,
1650                           2,
1651                           (void *)lonRef);
1652        } else {
1653            ALOGE("%s: getExifLongitude failed", __func__);
1654        }
1655    }
1656
1657    if (mJpegSettings->gps_coordinates[2]) {
1658        rat_t altitude;
1659        char altRef;
1660        rc = getExifAltitude(&altitude, &altRef, *(mJpegSettings->gps_coordinates[2]));
1661        if(rc == NO_ERROR) {
1662            exif->addEntry(EXIFTAGID_GPS_ALTITUDE,
1663                           EXIF_RATIONAL,
1664                           1,
1665                           (void *)&(altitude));
1666
1667            exif->addEntry(EXIFTAGID_GPS_ALTITUDE_REF,
1668                           EXIF_BYTE,
1669                           1,
1670                           (void *)&altRef);
1671        } else {
1672            ALOGE("%s: getExifAltitude failed", __func__);
1673        }
1674    }
1675
1676    if (mJpegSettings->gps_timestamp) {
1677        char gpsDateStamp[20];
1678        rat_t gpsTimeStamp[3];
1679        rc = getExifGpsDateTimeStamp(gpsDateStamp, 20, gpsTimeStamp, *(mJpegSettings->gps_timestamp));
1680        if(rc == NO_ERROR) {
1681            exif->addEntry(EXIFTAGID_GPS_DATESTAMP,
1682                           EXIF_ASCII,
1683                           strlen(gpsDateStamp) + 1,
1684                           (void *)gpsDateStamp);
1685
1686            exif->addEntry(EXIFTAGID_GPS_TIMESTAMP,
1687                           EXIF_RATIONAL,
1688                           3,
1689                           (void *)gpsTimeStamp);
1690        } else {
1691            ALOGE("%s: getExifGpsDataTimeStamp failed", __func__);
1692        }
1693    }
1694
1695    srat_t exposure_val;
1696    rc = getExifExposureValue(&exposure_val, mJpegSettings->exposure_compensation,
1697                              mJpegSettings->exposure_comp_step);
1698    if(rc == NO_ERROR) {
1699        exif->addEntry(EXIFTAGID_EXPOSURE_BIAS_VALUE,
1700                       EXIF_SRATIONAL,
1701                       1,
1702                       (void *)(&exposure_val));
1703    } else {
1704        ALOGE("%s: getExifExposureValue failed ", __func__);
1705    }
1706
1707    return exif;
1708}
1709
1710int QCamera3PicChannel::kMaxBuffers = 2;
1711
1712/*===========================================================================
1713 * FUNCTION   : QCamera3ReprocessChannel
1714 *
1715 * DESCRIPTION: constructor of QCamera3ReprocessChannel
1716 *
1717 * PARAMETERS :
1718 *   @cam_handle : camera handle
1719 *   @cam_ops    : ptr to camera ops table
1720 *   @pp_mask    : post-proccess feature mask
1721 *
1722 * RETURN     : none
1723 *==========================================================================*/
1724QCamera3ReprocessChannel::QCamera3ReprocessChannel(uint32_t cam_handle,
1725                                                 mm_camera_ops_t *cam_ops,
1726                                                 channel_cb_routine cb_routine,
1727                                                 cam_padding_info_t *paddingInfo,
1728                                                 void *userData, void *ch_hdl) :
1729    QCamera3Channel(cam_handle, cam_ops, cb_routine, paddingInfo, userData),
1730    picChHandle(ch_hdl),
1731    m_pSrcChannel(NULL),
1732    m_pMetaChannel(NULL),
1733    m_metaFrame(NULL),
1734    mMemory(NULL)
1735{
1736    memset(mSrcStreamHandles, 0, sizeof(mSrcStreamHandles));
1737}
1738
1739
1740/*===========================================================================
1741 * FUNCTION   : QCamera3ReprocessChannel
1742 *
1743 * DESCRIPTION: constructor of QCamera3ReprocessChannel
1744 *
1745 * PARAMETERS :
1746 *   @cam_handle : camera handle
1747 *   @cam_ops    : ptr to camera ops table
1748 *   @pp_mask    : post-proccess feature mask
1749 *
1750 * RETURN     : none
1751 *==========================================================================*/
1752int32_t QCamera3ReprocessChannel::initialize()
1753{
1754    int32_t rc = NO_ERROR;
1755    mm_camera_channel_attr_t attr;
1756
1757    memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
1758    attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS;
1759    attr.max_unmatched_frames = 1;
1760
1761    rc = init(&attr, NULL);
1762    if (rc < 0) {
1763        ALOGE("%s: init failed", __func__);
1764    }
1765    return rc;
1766}
1767
1768
1769/*===========================================================================
1770 * FUNCTION   : QCamera3ReprocessChannel
1771 *
1772 * DESCRIPTION: constructor of QCamera3ReprocessChannel
1773 *
1774 * PARAMETERS :
1775 *   @cam_handle : camera handle
1776 *   @cam_ops    : ptr to camera ops table
1777 *   @pp_mask    : post-proccess feature mask
1778 *
1779 * RETURN     : none
1780 *==========================================================================*/
1781void QCamera3ReprocessChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
1782                                  QCamera3Stream *stream)
1783{
1784    //Got the pproc data callback. Now send to jpeg encoding
1785    uint8_t frameIndex;
1786    mm_camera_super_buf_t* frame = NULL;
1787    QCamera3PicChannel *obj = (QCamera3PicChannel *)picChHandle;
1788
1789    if(!super_frame) {
1790         ALOGE("%s: Invalid Super buffer",__func__);
1791         return;
1792    }
1793
1794    if(super_frame->num_bufs != 1) {
1795         ALOGE("%s: Multiple streams are not supported",__func__);
1796         return;
1797    }
1798    if(super_frame->bufs[0] == NULL ) {
1799         ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
1800                  __func__);
1801         return;
1802    }
1803
1804    frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
1805    frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
1806    if (frame == NULL) {
1807       ALOGE("%s: Error allocating memory to save received_frame structure.",
1808                                                                    __func__);
1809       if(stream) {
1810           stream->bufDone(frameIndex);
1811       }
1812       return;
1813    }
1814    *frame = *super_frame;
1815    //queue back the metadata buffer
1816    if (m_metaFrame != NULL) {
1817       ((QCamera3MetadataChannel*)m_pMetaChannel)->bufDone(m_metaFrame);
1818       free(m_metaFrame);
1819       m_metaFrame = NULL;
1820    } else {
1821       ALOGE("%s: Meta frame was NULL", __func__);
1822    }
1823    obj->m_postprocessor.processPPData(frame);
1824    return;
1825}
1826
1827/*===========================================================================
1828 * FUNCTION   : QCamera3ReprocessChannel
1829 *
1830 * DESCRIPTION: default constructor of QCamera3ReprocessChannel
1831 *
1832 * PARAMETERS : none
1833 *
1834 * RETURN     : none
1835 *==========================================================================*/
1836QCamera3ReprocessChannel::QCamera3ReprocessChannel() :
1837    m_pSrcChannel(NULL),
1838    m_pMetaChannel(NULL),
1839    m_metaFrame(NULL)
1840{
1841}
1842
1843/*===========================================================================
1844 * FUNCTION   : QCamera3ReprocessChannel
1845 *
1846 * DESCRIPTION: register the buffers of the reprocess channel
1847 *
1848 * PARAMETERS : none
1849 *
1850 * RETURN     : none
1851 *==========================================================================*/
1852int32_t QCamera3ReprocessChannel::registerBuffers(uint32_t num_buffers, buffer_handle_t **buffers)
1853{
1854   return 0;
1855}
1856
1857/*===========================================================================
1858 * FUNCTION   : getStreamBufs
1859 *
1860 * DESCRIPTION: register the buffers of the reprocess channel
1861 *
1862 * PARAMETERS : none
1863 *
1864 * RETURN     : QCamera3Memory *
1865 *==========================================================================*/
1866QCamera3Memory* QCamera3ReprocessChannel::getStreamBufs(uint32_t len)
1867{
1868   int rc = 0;
1869
1870    mMemory = new QCamera3HeapMemory();
1871    if (!mMemory) {
1872        ALOGE("%s: unable to create reproc memory", __func__);
1873        return NULL;
1874    }
1875
1876    //Queue YUV buffers in the beginning mQueueAll = true
1877    rc = mMemory->allocate(2, len, true);
1878    if (rc < 0) {
1879        ALOGE("%s: unable to allocate reproc memory", __func__);
1880        delete mMemory;
1881        mMemory = NULL;
1882        return NULL;
1883    }
1884    return mMemory;
1885}
1886
1887/*===========================================================================
1888 * FUNCTION   : getStreamBufs
1889 *
1890 * DESCRIPTION: register the buffers of the reprocess channel
1891 *
1892 * PARAMETERS : none
1893 *
1894 * RETURN     :
1895 *==========================================================================*/
1896void QCamera3ReprocessChannel::putStreamBufs()
1897{
1898    mMemory->deallocate();
1899    delete mMemory;
1900    mMemory = NULL;
1901}
1902
1903/*===========================================================================
1904 * FUNCTION   : ~QCamera3ReprocessChannel
1905 *
1906 * DESCRIPTION: destructor of QCamera3ReprocessChannel
1907 *
1908 * PARAMETERS : none
1909 *
1910 * RETURN     : none
1911 *==========================================================================*/
1912QCamera3ReprocessChannel::~QCamera3ReprocessChannel()
1913{
1914}
1915
1916/*===========================================================================
1917 * FUNCTION   : getStreamBySourceHandle
1918 *
1919 * DESCRIPTION: find reprocess stream by its source stream handle
1920 *
1921 * PARAMETERS :
1922 *   @srcHandle : source stream handle
1923 *
1924 * RETURN     : ptr to reprocess stream if found. NULL if not found
1925 *==========================================================================*/
1926QCamera3Stream * QCamera3ReprocessChannel::getStreamBySourceHandle(uint32_t srcHandle)
1927{
1928    QCamera3Stream *pStream = NULL;
1929
1930    for (int i = 0; i < m_numStreams; i++) {
1931        if (mSrcStreamHandles[i] == srcHandle) {
1932            pStream = mStreams[i];
1933            break;
1934        }
1935    }
1936    return pStream;
1937}
1938
1939/*===========================================================================
1940 * FUNCTION   : doReprocess
1941 *
1942 * DESCRIPTION: request to do a reprocess on the frame
1943 *
1944 * PARAMETERS :
1945 *   @frame   : frame to be performed a reprocess
1946 *
1947 * RETURN     : int32_t type of status
1948 *              NO_ERROR  -- success
1949 *              none-zero failure code
1950 *==========================================================================*/
1951int32_t QCamera3ReprocessChannel::doReprocess(mm_camera_super_buf_t *frame,
1952                                              mm_camera_super_buf_t *meta_frame)
1953{
1954    int32_t rc = 0;
1955    if (m_numStreams < 1) {
1956        ALOGE("%s: No reprocess stream is created", __func__);
1957        return -1;
1958    }
1959    if (m_pSrcChannel == NULL) {
1960        ALOGE("%s: No source channel for reprocess", __func__);
1961        return -1;
1962    }
1963    m_metaFrame = meta_frame;
1964    for (int i = 0; i < frame->num_bufs; i++) {
1965        QCamera3Stream *pStream = getStreamBySourceHandle(frame->bufs[i]->stream_id);
1966        if (pStream != NULL) {
1967            cam_stream_parm_buffer_t param;
1968            memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
1969            param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
1970            param.reprocess.buf_index = frame->bufs[i]->buf_idx;
1971            param.reprocess.frame_idx = frame->bufs[i]->frame_idx;
1972            if (meta_frame != NULL) {
1973               param.reprocess.meta_present = 1;
1974               param.reprocess.meta_stream_handle = m_pMetaChannel->mStreams[0]->getMyServerID();
1975               param.reprocess.meta_buf_index = meta_frame->bufs[0]->buf_idx;
1976            }
1977            rc = pStream->setParameter(param);
1978            if (rc != NO_ERROR) {
1979                ALOGE("%s: stream setParameter for reprocess failed", __func__);
1980                break;
1981            }
1982        }
1983    }
1984    return rc;
1985}
1986
1987/*===========================================================================
1988 * FUNCTION   : doReprocess
1989 *
1990 * DESCRIPTION: request to do a reprocess on the frame
1991 *
1992 * PARAMETERS :
1993 *   @buf_fd     : fd to the input buffer that needs reprocess
1994 *   @buf_lenght : length of the input buffer
1995 *   @ret_val    : result of reprocess.
1996 *                 Example: Could be faceID in case of register face image.
1997 *
1998 * RETURN     : int32_t type of status
1999 *              NO_ERROR  -- success
2000 *              none-zero failure code
2001 *==========================================================================*/
2002int32_t QCamera3ReprocessChannel::doReprocess(int buf_fd,
2003                                              uint32_t buf_length,
2004                                              int32_t &ret_val,
2005                                              mm_camera_super_buf_t *meta_frame)
2006{
2007    int32_t rc = 0;
2008    if (m_numStreams < 1) {
2009        ALOGE("%s: No reprocess stream is created", __func__);
2010        return -1;
2011    }
2012    if (meta_frame == NULL) {
2013        ALOGE("%s: Did not get corresponding metadata in time", __func__);
2014        return -1;
2015    }
2016
2017    uint32_t buf_idx = 0;
2018    for (int i = 0; i < m_numStreams; i++) {
2019        rc = mStreams[i]->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
2020                                 buf_idx, -1,
2021                                 buf_fd, buf_length);
2022
2023        if (rc == NO_ERROR) {
2024            cam_stream_parm_buffer_t param;
2025            memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
2026            param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
2027            param.reprocess.buf_index = buf_idx;
2028            param.reprocess.meta_present = 1;
2029            param.reprocess.meta_stream_handle = m_pMetaChannel->mStreams[0]->getMyServerID();
2030            param.reprocess.meta_buf_index = meta_frame->bufs[0]->buf_idx;
2031            rc = mStreams[i]->setParameter(param);
2032            if (rc == NO_ERROR) {
2033                ret_val = param.reprocess.ret_val;
2034            }
2035            mStreams[i]->unmapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
2036                                  buf_idx, -1);
2037        }
2038    }
2039    return rc;
2040}
2041
2042/*===========================================================================
2043 * FUNCTION   : addReprocStreamsFromSource
2044 *
2045 * DESCRIPTION: add reprocess streams from input source channel
2046 *
2047 * PARAMETERS :
2048 *   @config         : pp feature configuration
2049 *   @pSrcChannel    : ptr to input source channel that needs reprocess
2050 *   @pMetaChannel   : ptr to metadata channel to get corresp. metadata
2051 *
2052 * RETURN     : int32_t type of status
2053 *              NO_ERROR  -- success
2054 *              none-zero failure code
2055 *==========================================================================*/
2056int32_t QCamera3ReprocessChannel::addReprocStreamsFromSource(cam_pp_feature_config_t &config,
2057                                                             QCamera3Channel *pSrcChannel,
2058                                                             QCamera3Channel *pMetaChannel)
2059{
2060    int32_t rc = 0;
2061    QCamera3Stream *pSrcStream = pSrcChannel->getStreamByIndex(0);
2062    if (pSrcStream == NULL) {
2063       ALOGE("%s: source channel doesn't have a stream", __func__);
2064       return BAD_VALUE;
2065    }
2066    cam_stream_reproc_config_t reprocess_config;
2067    cam_dimension_t streamDim;
2068    cam_stream_type_t streamType;
2069    cam_format_t streamFormat;
2070    cam_frame_len_offset_t frameOffset;
2071    int num_buffers = 2;
2072
2073    streamType = CAM_STREAM_TYPE_OFFLINE_PROC;
2074    pSrcStream->getFormat(streamFormat);
2075    pSrcStream->getFrameDimension(streamDim);
2076    pSrcStream->getFrameOffset(frameOffset);
2077
2078    reprocess_config.pp_type = CAM_ONLINE_REPROCESS_TYPE;
2079    reprocess_config.online.input_stream_id = pSrcStream->getMyServerID();
2080    reprocess_config.online.input_stream_type = pSrcStream->getMyType();
2081    reprocess_config.pp_feature_config = config;
2082
2083    mSrcStreamHandles[m_numStreams] = pSrcStream->getMyHandle();
2084
2085    if (reprocess_config.pp_feature_config.feature_mask & CAM_QCOM_FEATURE_ROTATION) {
2086        if (reprocess_config.pp_feature_config.rotation == ROTATE_90 ||
2087            reprocess_config.pp_feature_config.rotation == ROTATE_270) {
2088            // rotated by 90 or 270, need to switch width and height
2089            int32_t temp = streamDim.height;
2090            streamDim.height = streamDim.width;
2091            streamDim.width = temp;
2092        }
2093    }
2094
2095    QCamera3Stream *pStream = new QCamera3Stream(m_camHandle,
2096                                               m_handle,
2097                                               m_camOps,
2098                                               mPaddingInfo,
2099                                               (QCamera3Channel*)this);
2100    if (pStream == NULL) {
2101        ALOGE("%s: No mem for Stream", __func__);
2102        return NO_MEMORY;
2103    }
2104
2105    rc = pStream->init(streamType, streamFormat, streamDim, &reprocess_config,
2106                       num_buffers,QCamera3Channel::streamCbRoutine, this);
2107
2108
2109    if (rc == 0) {
2110        mStreams[m_numStreams] = pStream;
2111        m_numStreams++;
2112    } else {
2113        ALOGE("%s: failed to create reprocess stream", __func__);
2114        delete pStream;
2115    }
2116
2117    if (rc == NO_ERROR) {
2118        m_pSrcChannel = pSrcChannel;
2119        m_pMetaChannel = pMetaChannel;
2120    }
2121    if(m_camOps->request_super_buf(m_camHandle,m_handle,1) < 0) {
2122        ALOGE("%s: Request for super buffer failed",__func__);
2123    }
2124    return rc;
2125}
2126
2127
2128}; // namespace qcamera
2129