QCamera3Channel.cpp revision d897e24270f74b8266a37e01a1dd2f4797b13258
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    // Picture stream has already been started before any request comes in
980    if (!m_bIsActive) {
981        ALOGE("%s: Picture stream should have been started before any request",
982            __func__);
983        return -EINVAL;
984    }
985    if (pInputBuffer == NULL)
986        mStreams[0]->bufDone(0);
987
988    if(!mMemory) {
989        if(pInputBuffer) {
990            mMemory = new QCamera3GrallocMemory();
991            if (mMemory == NULL) {
992                return NO_MEMORY;
993            }
994
995            //Registering Jpeg output buffer
996            if (mMemory->registerBuffers(mNumBufs, mCamera3Buffers) < 0) {
997                delete mMemory;
998                mMemory = NULL;
999                return NO_MEMORY;
1000            }
1001        } else {
1002            ALOGE("%s: error, Gralloc Memory object not yet created for this stream",__func__);
1003            return NO_MEMORY;
1004        }
1005    }
1006
1007    index = mMemory->getMatchBufIndex((void*)buffer);
1008    if(index < 0) {
1009        ALOGE("%s: Could not find object among registered buffers",__func__);
1010        return DEAD_OBJECT;
1011    }
1012    rc = mMemory->markFrameNumber(index, frameNumber);
1013
1014    //Start the postprocessor for jpeg encoding. Pass mMemory as destination buffer
1015    mCurrentBufIndex = index;
1016
1017    m_postprocessor.start(mMemory, index, this);
1018
1019    ALOGD("%s: Post-process started", __func__);
1020    if(pInputBuffer) {
1021        ALOGD("%s: Issue call to reprocess", __func__);
1022        m_postprocessor.processAuxiliaryData(pInputBuffer,pInputChannel);
1023    }
1024    return rc;
1025}
1026
1027/*===========================================================================
1028 * FUNCTION   : dataNotifyCB
1029 *
1030 * DESCRIPTION: Channel Level callback used for super buffer data notify.
1031 *              This function is registered with mm-camera-interface to handle
1032 *              data notify
1033 *
1034 * PARAMETERS :
1035 *   @recvd_frame   : stream frame received
1036 *   userdata       : user data ptr
1037 *
1038 * RETURN     : none
1039 *==========================================================================*/
1040void QCamera3PicChannel::dataNotifyCB(mm_camera_super_buf_t *recvd_frame,
1041                                 void *userdata)
1042{
1043    ALOGV("%s: E\n", __func__);
1044    QCamera3PicChannel *channel = (QCamera3PicChannel *)userdata;
1045
1046    if (channel == NULL) {
1047        ALOGE("%s: invalid channel pointer", __func__);
1048        return;
1049    }
1050
1051    if(channel->m_numStreams != 1) {
1052        ALOGE("%s: Error: Bug: This callback assumes one stream per channel",__func__);
1053        return;
1054    }
1055
1056
1057    if(channel->mStreams[0] == NULL) {
1058        ALOGE("%s: Error: Invalid Stream object",__func__);
1059        return;
1060    }
1061
1062    channel->QCamera3PicChannel::streamCbRoutine(recvd_frame, channel->mStreams[0]);
1063
1064    ALOGV("%s: X\n", __func__);
1065    return;
1066}
1067
1068
1069int32_t QCamera3PicChannel::registerBuffers(uint32_t num_buffers,
1070                        buffer_handle_t **buffers)
1071{
1072    int rc = 0;
1073    cam_stream_type_t streamType;
1074    cam_format_t streamFormat;
1075
1076    ALOGV("%s: E",__func__);
1077    rc = QCamera3PicChannel::initialize();
1078    if (rc < 0) {
1079        ALOGE("%s: init failed", __func__);
1080        return rc;
1081    }
1082
1083    if (mCamera3Stream->format == HAL_PIXEL_FORMAT_BLOB) {
1084        streamType = CAM_STREAM_TYPE_NON_ZSL_SNAPSHOT;
1085        streamFormat = CAM_FORMAT_YUV_420_NV21;
1086    } else {
1087        //TODO: Fail for other types of streams for now
1088        ALOGE("%s: format is not BLOB", __func__);
1089        return -EINVAL;
1090    }
1091    /* Bookkeep buffer set because they go out of scope after register call */
1092    mNumBufs = num_buffers;
1093    mCamera3Buffers = new buffer_handle_t*[num_buffers];
1094    if (mCamera3Buffers == NULL) {
1095        ALOGE("%s: Failed to allocate buffer_handle_t*", __func__);
1096        return -ENOMEM;
1097    }
1098    for (size_t i = 0; i < num_buffers; i++)
1099        mCamera3Buffers[i] = buffers[i];
1100
1101    ALOGV("%s: X",__func__);
1102    return rc;
1103}
1104
1105void QCamera3PicChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
1106                            QCamera3Stream *stream)
1107{
1108    //TODO
1109    //Used only for getting YUV. Jpeg callback will be sent back from channel
1110    //directly to HWI. Refer to func jpegEvtHandle
1111
1112    //Got the yuv callback. Calling yuv callback handler in PostProc
1113    uint8_t frameIndex;
1114    mm_camera_super_buf_t* frame = NULL;
1115    if(!super_frame) {
1116         ALOGE("%s: Invalid Super buffer",__func__);
1117         return;
1118    }
1119
1120    if(super_frame->num_bufs != 1) {
1121         ALOGE("%s: Multiple streams are not supported",__func__);
1122         return;
1123    }
1124    if(super_frame->bufs[0] == NULL ) {
1125         ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
1126                  __func__);
1127         return;
1128    }
1129
1130    frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
1131    if(frameIndex >= mNumBufs) {
1132         ALOGE("%s: Error, Invalid index for buffer",__func__);
1133         if(stream) {
1134             stream->bufDone(frameIndex);
1135         }
1136         return;
1137    }
1138
1139    frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
1140    if (frame == NULL) {
1141       ALOGE("%s: Error allocating memory to save received_frame structure.",
1142                                                                    __func__);
1143       if(stream) {
1144           stream->bufDone(frameIndex);
1145       }
1146       return;
1147    }
1148    *frame = *super_frame;
1149
1150    m_postprocessor.processData(frame);
1151    free(super_frame);
1152    return;
1153}
1154
1155QCamera3Memory* QCamera3PicChannel::getStreamBufs(uint32_t len)
1156{
1157    int rc = 0;
1158
1159    if (mNumBufs == 0 || mCamera3Buffers == NULL) {
1160        ALOGE("%s: buffers not registered yet", __func__);
1161        return NULL;
1162    }
1163
1164    if(mMemory) {
1165        delete mMemory;
1166        mMemory = NULL;
1167    }
1168    mMemory = new QCamera3GrallocMemory();
1169    if (mMemory == NULL) {
1170        return NULL;
1171    }
1172
1173    //Registering Jpeg output buffer
1174    if (mMemory->registerBuffers(mNumBufs, mCamera3Buffers) < 0) {
1175        delete mMemory;
1176        mMemory = NULL;
1177        return NULL;
1178    }
1179
1180    mYuvMemory = new QCamera3HeapMemory();
1181    if (!mYuvMemory) {
1182        ALOGE("%s: unable to create metadata memory", __func__);
1183        return NULL;
1184    }
1185
1186    //Queue YUV buffers in the beginning mQueueAll = true
1187    rc = mYuvMemory->allocate(1, len, false);
1188    if (rc < 0) {
1189        ALOGE("%s: unable to allocate metadata memory", __func__);
1190        delete mYuvMemory;
1191        mYuvMemory = NULL;
1192        return NULL;
1193    }
1194    return mYuvMemory;
1195}
1196
1197void QCamera3PicChannel::putStreamBufs()
1198{
1199    mMemory->unregisterBuffers();
1200    delete mMemory;
1201    mMemory = NULL;
1202
1203    mYuvMemory->deallocate();
1204    delete mYuvMemory;
1205    mYuvMemory = NULL;
1206}
1207
1208bool QCamera3PicChannel::isRawSnapshot()
1209{
1210   return !(mJpegSettings->is_jpeg_format);
1211}
1212/*===========================================================================
1213 * FUNCTION   : getThumbnailSize
1214 *
1215 * DESCRIPTION: get user set thumbnail size
1216 *
1217 * PARAMETERS :
1218 *   @dim     : output of thumbnail dimension
1219 *
1220 * RETURN     : none
1221 *==========================================================================*/
1222void QCamera3PicChannel::getThumbnailSize(cam_dimension_t &dim)
1223{
1224    dim = mJpegSettings->thumbnail_size;
1225}
1226
1227/*===========================================================================
1228 * FUNCTION   : getJpegQuality
1229 *
1230 * DESCRIPTION: get user set jpeg quality
1231 *
1232 * PARAMETERS : none
1233 *
1234 * RETURN     : jpeg quality setting
1235 *==========================================================================*/
1236int QCamera3PicChannel::getJpegQuality()
1237{
1238    int quality = mJpegSettings->jpeg_quality;
1239    if (quality < 0) {
1240        quality = 85;  //set to default quality value
1241    }
1242    return quality;
1243}
1244
1245/*===========================================================================
1246 * FUNCTION   : getJpegRotation
1247 *
1248 * DESCRIPTION: get rotation information to be passed into jpeg encoding
1249 *
1250 * PARAMETERS : none
1251 *
1252 * RETURN     : rotation information
1253 *==========================================================================*/
1254int QCamera3PicChannel::getJpegRotation() {
1255    int rotation = mJpegSettings->jpeg_orientation;
1256    if (rotation < 0) {
1257        rotation = 0;
1258    }
1259    return rotation;
1260}
1261
1262void QCamera3PicChannel::queueMetadata(mm_camera_super_buf_t *metadata_buf)
1263{
1264    m_postprocessor.processPPMetadata(metadata_buf);
1265}
1266/*===========================================================================
1267 * FUNCTION   : getRational
1268 *
1269 * DESCRIPTION: compose rational struct
1270 *
1271 * PARAMETERS :
1272 *   @rat     : ptr to struct to store rational info
1273 *   @num     :num of the rational
1274 *   @denom   : denom of the rational
1275 *
1276 * RETURN     : int32_t type of status
1277 *              NO_ERROR  -- success
1278 *              none-zero failure code
1279 *==========================================================================*/
1280int32_t getRational(rat_t *rat, int num, int denom)
1281{
1282    if (NULL == rat) {
1283        ALOGE("%s: NULL rat input", __func__);
1284        return BAD_VALUE;
1285    }
1286    rat->num = num;
1287    rat->denom = denom;
1288    return NO_ERROR;
1289}
1290
1291/*===========================================================================
1292 * FUNCTION   : parseGPSCoordinate
1293 *
1294 * DESCRIPTION: parse GPS coordinate string
1295 *
1296 * PARAMETERS :
1297 *   @coord_str : [input] coordinate string
1298 *   @coord     : [output]  ptr to struct to store coordinate
1299 *
1300 * RETURN     : int32_t type of status
1301 *              NO_ERROR  -- success
1302 *              none-zero failure code
1303 *==========================================================================*/
1304int parseGPSCoordinate(const char *coord_str, rat_t* coord)
1305{
1306    if(coord == NULL) {
1307        ALOGE("%s: error, invalid argument coord == NULL", __func__);
1308        return BAD_VALUE;
1309    }
1310    float degF = atof(coord_str);
1311    if (degF < 0) {
1312        degF = -degF;
1313    }
1314    float minF = (degF - (int) degF) * 60;
1315    float secF = (minF - (int) minF) * 60;
1316
1317    getRational(&coord[0], (int)degF, 1);
1318    getRational(&coord[1], (int)minF, 1);
1319    getRational(&coord[2], (int)(secF * 10000), 10000);
1320    return NO_ERROR;
1321}
1322
1323/*===========================================================================
1324 * FUNCTION   : getExifDateTime
1325 *
1326 * DESCRIPTION: query exif date time
1327 *
1328 * PARAMETERS :
1329 *   @dateTime : string to store exif date time
1330 *   @count    : lenght of the dateTime string
1331 *
1332 * RETURN     : int32_t type of status
1333 *              NO_ERROR  -- success
1334 *              none-zero failure code
1335 *==========================================================================*/
1336int32_t getExifDateTime(char *dateTime, uint32_t &count)
1337{
1338    //get time and date from system
1339    time_t rawtime;
1340    struct tm * timeinfo;
1341    time(&rawtime);
1342    timeinfo = localtime (&rawtime);
1343    //Write datetime according to EXIF Spec
1344    //"YYYY:MM:DD HH:MM:SS" (20 chars including \0)
1345    snprintf(dateTime, 20, "%04d:%02d:%02d %02d:%02d:%02d",
1346             timeinfo->tm_year + 1900, timeinfo->tm_mon + 1,
1347             timeinfo->tm_mday, timeinfo->tm_hour,
1348             timeinfo->tm_min, timeinfo->tm_sec);
1349    count = 20;
1350
1351    return NO_ERROR;
1352}
1353
1354/*===========================================================================
1355 * FUNCTION   : getExifFocalLength
1356 *
1357 * DESCRIPTION: get exif focal lenght
1358 *
1359 * PARAMETERS :
1360 *   @focalLength : ptr to rational strcut to store focal lenght
1361 *
1362 * RETURN     : int32_t type of status
1363 *              NO_ERROR  -- success
1364 *              none-zero failure code
1365 *==========================================================================*/
1366int32_t getExifFocalLength(rat_t *focalLength, float value)
1367{
1368    int focalLengthValue =
1369        (int)(value * FOCAL_LENGTH_DECIMAL_PRECISION);
1370    return getRational(focalLength, focalLengthValue, FOCAL_LENGTH_DECIMAL_PRECISION);
1371}
1372
1373/*===========================================================================
1374  * FUNCTION   : getExifExpTimeInfo
1375  *
1376  * DESCRIPTION: get exif exposure time information
1377  *
1378  * PARAMETERS :
1379  *   @expoTimeInfo     : expousure time value
1380  * RETURN     : nt32_t type of status
1381  *              NO_ERROR  -- success
1382  *              none-zero failure code
1383  *==========================================================================*/
1384int32_t getExifExpTimeInfo(rat_t *expoTimeInfo, int64_t value)
1385{
1386
1387    int cal_exposureTime;
1388    if (value != 0)
1389        cal_exposureTime = value;
1390    else
1391        cal_exposureTime = 60;
1392
1393    return getRational(expoTimeInfo, 1, cal_exposureTime);
1394}
1395
1396/*===========================================================================
1397 * FUNCTION   : getExifGpsProcessingMethod
1398 *
1399 * DESCRIPTION: get GPS processing method
1400 *
1401 * PARAMETERS :
1402 *   @gpsProcessingMethod : string to store GPS process method
1403 *   @count               : lenght of the string
1404 *
1405 * RETURN     : int32_t type of status
1406 *              NO_ERROR  -- success
1407 *              none-zero failure code
1408 *==========================================================================*/
1409int32_t getExifGpsProcessingMethod(char *gpsProcessingMethod,
1410                                   uint32_t &count, char* value)
1411{
1412    if(value != NULL) {
1413        memcpy(gpsProcessingMethod, ExifAsciiPrefix, EXIF_ASCII_PREFIX_SIZE);
1414        count = EXIF_ASCII_PREFIX_SIZE;
1415        strncpy(gpsProcessingMethod + EXIF_ASCII_PREFIX_SIZE, value, strlen(value));
1416        count += strlen(value);
1417        gpsProcessingMethod[count++] = '\0'; // increase 1 for the last NULL char
1418        return NO_ERROR;
1419    } else {
1420        return BAD_VALUE;
1421    }
1422}
1423
1424/*===========================================================================
1425 * FUNCTION   : getExifLatitude
1426 *
1427 * DESCRIPTION: get exif latitude
1428 *
1429 * PARAMETERS :
1430 *   @latitude : ptr to rational struct to store latitude info
1431 *   @ladRef   : charater to indicate latitude reference
1432 *
1433 * RETURN     : int32_t type of status
1434 *              NO_ERROR  -- success
1435 *              none-zero failure code
1436 *==========================================================================*/
1437int32_t getExifLatitude(rat_t *latitude,
1438                                           char *latRef, double value)
1439{
1440    char str[30];
1441    snprintf(str, sizeof(str), "%f", value);
1442    if(str != NULL) {
1443        parseGPSCoordinate(str, latitude);
1444
1445        //set Latitude Ref
1446        float latitudeValue = strtof(str, 0);
1447        if(latitudeValue < 0.0f) {
1448            latRef[0] = 'S';
1449        } else {
1450            latRef[0] = 'N';
1451        }
1452        latRef[1] = '\0';
1453        return NO_ERROR;
1454    }else{
1455        return BAD_VALUE;
1456    }
1457}
1458
1459/*===========================================================================
1460 * FUNCTION   : getExifLongitude
1461 *
1462 * DESCRIPTION: get exif longitude
1463 *
1464 * PARAMETERS :
1465 *   @longitude : ptr to rational struct to store longitude info
1466 *   @lonRef    : charater to indicate longitude reference
1467 *
1468 * RETURN     : int32_t type of status
1469 *              NO_ERROR  -- success
1470 *              none-zero failure code
1471 *==========================================================================*/
1472int32_t getExifLongitude(rat_t *longitude,
1473                                            char *lonRef, double value)
1474{
1475    char str[30];
1476    snprintf(str, sizeof(str), "%f", value);
1477    if(str != NULL) {
1478        parseGPSCoordinate(str, longitude);
1479
1480        //set Longitude Ref
1481        float longitudeValue = strtof(str, 0);
1482        if(longitudeValue < 0.0f) {
1483            lonRef[0] = 'W';
1484        } else {
1485            lonRef[0] = 'E';
1486        }
1487        lonRef[1] = '\0';
1488        return NO_ERROR;
1489    }else{
1490        return BAD_VALUE;
1491    }
1492}
1493
1494/*===========================================================================
1495 * FUNCTION   : getExifAltitude
1496 *
1497 * DESCRIPTION: get exif altitude
1498 *
1499 * PARAMETERS :
1500 *   @altitude : ptr to rational struct to store altitude info
1501 *   @altRef   : charater to indicate altitude reference
1502 *
1503 * RETURN     : int32_t type of status
1504 *              NO_ERROR  -- success
1505 *              none-zero failure code
1506 *==========================================================================*/
1507int32_t getExifAltitude(rat_t *altitude,
1508                                           char *altRef, double value)
1509{
1510    char str[30];
1511    snprintf(str, sizeof(str), "%f", value);
1512    if(str != NULL) {
1513        double value = atof(str);
1514        *altRef = 0;
1515        if(value < 0){
1516            *altRef = 1;
1517            value = -value;
1518        }
1519        return getRational(altitude, value*1000, 1000);
1520    }else{
1521        return BAD_VALUE;
1522    }
1523}
1524
1525/*===========================================================================
1526 * FUNCTION   : getExifGpsDateTimeStamp
1527 *
1528 * DESCRIPTION: get exif GPS date time stamp
1529 *
1530 * PARAMETERS :
1531 *   @gpsDateStamp : GPS date time stamp string
1532 *   @bufLen       : length of the string
1533 *   @gpsTimeStamp : ptr to rational struct to store time stamp info
1534 *
1535 * RETURN     : int32_t type of status
1536 *              NO_ERROR  -- success
1537 *              none-zero failure code
1538 *==========================================================================*/
1539int32_t getExifGpsDateTimeStamp(char *gpsDateStamp,
1540                                           uint32_t bufLen,
1541                                           rat_t *gpsTimeStamp, int64_t value)
1542{
1543    char str[30];
1544    snprintf(str, sizeof(str), "%lld", value);
1545    if(str != NULL) {
1546        time_t unixTime = (time_t)atol(str);
1547        struct tm *UTCTimestamp = gmtime(&unixTime);
1548
1549        strftime(gpsDateStamp, bufLen, "%Y:%m:%d", UTCTimestamp);
1550
1551        getRational(&gpsTimeStamp[0], UTCTimestamp->tm_hour, 1);
1552        getRational(&gpsTimeStamp[1], UTCTimestamp->tm_min, 1);
1553        getRational(&gpsTimeStamp[2], UTCTimestamp->tm_sec, 1);
1554
1555        return NO_ERROR;
1556    } else {
1557        return BAD_VALUE;
1558    }
1559}
1560
1561int32_t getExifExposureValue(srat_t* exposure_val, int32_t exposure_comp,
1562                             cam_rational_type_t step)
1563{
1564    exposure_val->num = exposure_comp * step.numerator;
1565    exposure_val->denom = step.denominator;
1566    return 0;
1567}
1568/*===========================================================================
1569 * FUNCTION   : getExifData
1570 *
1571 * DESCRIPTION: get exif data to be passed into jpeg encoding
1572 *
1573 * PARAMETERS : none
1574 *
1575 * RETURN     : exif data from user setting and GPS
1576 *==========================================================================*/
1577QCamera3Exif *QCamera3PicChannel::getExifData()
1578{
1579    QCamera3Exif *exif = new QCamera3Exif();
1580    if (exif == NULL) {
1581        ALOGE("%s: No memory for QCamera3Exif", __func__);
1582        return NULL;
1583    }
1584
1585    int32_t rc = NO_ERROR;
1586    uint32_t count = 0;
1587
1588    // add exif entries
1589    char dateTime[20];
1590    memset(dateTime, 0, sizeof(dateTime));
1591    count = 20;
1592    rc = getExifDateTime(dateTime, count);
1593    if(rc == NO_ERROR) {
1594        exif->addEntry(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL,
1595                       EXIF_ASCII,
1596                       count,
1597                       (void *)dateTime);
1598    } else {
1599        ALOGE("%s: getExifDateTime failed", __func__);
1600    }
1601
1602    rat_t focalLength;
1603    rc = getExifFocalLength(&focalLength, mJpegSettings->lens_focal_length);
1604    if (rc == NO_ERROR) {
1605        exif->addEntry(EXIFTAGID_FOCAL_LENGTH,
1606                       EXIF_RATIONAL,
1607                       1,
1608                       (void *)&(focalLength));
1609    } else {
1610        ALOGE("%s: getExifFocalLength failed", __func__);
1611    }
1612
1613    uint16_t isoSpeed = (uint16_t)mJpegSettings->sensor_sensitivity;
1614    exif->addEntry(EXIFTAGID_ISO_SPEED_RATING,
1615                   EXIF_SHORT,
1616                   1,
1617                   (void *)&(isoSpeed));
1618
1619    rat_t sensorExpTime ;
1620    rc = getExifExpTimeInfo(&sensorExpTime, (int64_t)mJpegSettings->sensor_exposure_time);
1621    if (rc == NO_ERROR){
1622        exif->addEntry(EXIFTAGID_EXPOSURE_TIME,
1623                       EXIF_RATIONAL,
1624                       1,
1625                       (void *)&(sensorExpTime));
1626    } else {
1627        ALOGE("now addEntry for EXIFTAGID_EXPOSURE_TIME is %d", sensorExpTime);
1628    }
1629
1630    if (strlen(mJpegSettings->gps_processing_method) > 0) {
1631        char gpsProcessingMethod[EXIF_ASCII_PREFIX_SIZE + GPS_PROCESSING_METHOD_SIZE];
1632        count = 0;
1633        rc = getExifGpsProcessingMethod(gpsProcessingMethod, count, mJpegSettings->gps_processing_method);
1634        if(rc == NO_ERROR) {
1635            exif->addEntry(EXIFTAGID_GPS_PROCESSINGMETHOD,
1636                           EXIF_ASCII,
1637                           count,
1638                           (void *)gpsProcessingMethod);
1639        } else {
1640            ALOGE("%s: getExifGpsProcessingMethod failed", __func__);
1641        }
1642    }
1643
1644    if (mJpegSettings->gps_coordinates[0]) {
1645        rat_t latitude[3];
1646        char latRef[2];
1647        rc = getExifLatitude(latitude, latRef, *(mJpegSettings->gps_coordinates[0]));
1648        if(rc == NO_ERROR) {
1649            exif->addEntry(EXIFTAGID_GPS_LATITUDE,
1650                           EXIF_RATIONAL,
1651                           3,
1652                           (void *)latitude);
1653            exif->addEntry(EXIFTAGID_GPS_LATITUDE_REF,
1654                           EXIF_ASCII,
1655                           2,
1656                           (void *)latRef);
1657        } else {
1658            ALOGE("%s: getExifLatitude failed", __func__);
1659        }
1660    }
1661
1662    if (mJpegSettings->gps_coordinates[1]) {
1663        rat_t longitude[3];
1664        char lonRef[2];
1665        rc = getExifLongitude(longitude, lonRef, *(mJpegSettings->gps_coordinates[1]));
1666        if(rc == NO_ERROR) {
1667            exif->addEntry(EXIFTAGID_GPS_LONGITUDE,
1668                           EXIF_RATIONAL,
1669                           3,
1670                           (void *)longitude);
1671
1672            exif->addEntry(EXIFTAGID_GPS_LONGITUDE_REF,
1673                           EXIF_ASCII,
1674                           2,
1675                           (void *)lonRef);
1676        } else {
1677            ALOGE("%s: getExifLongitude failed", __func__);
1678        }
1679    }
1680
1681    if (mJpegSettings->gps_coordinates[2]) {
1682        rat_t altitude;
1683        char altRef;
1684        rc = getExifAltitude(&altitude, &altRef, *(mJpegSettings->gps_coordinates[2]));
1685        if(rc == NO_ERROR) {
1686            exif->addEntry(EXIFTAGID_GPS_ALTITUDE,
1687                           EXIF_RATIONAL,
1688                           1,
1689                           (void *)&(altitude));
1690
1691            exif->addEntry(EXIFTAGID_GPS_ALTITUDE_REF,
1692                           EXIF_BYTE,
1693                           1,
1694                           (void *)&altRef);
1695        } else {
1696            ALOGE("%s: getExifAltitude failed", __func__);
1697        }
1698    }
1699
1700    if (mJpegSettings->gps_timestamp) {
1701        char gpsDateStamp[20];
1702        rat_t gpsTimeStamp[3];
1703        rc = getExifGpsDateTimeStamp(gpsDateStamp, 20, gpsTimeStamp, *(mJpegSettings->gps_timestamp));
1704        if(rc == NO_ERROR) {
1705            exif->addEntry(EXIFTAGID_GPS_DATESTAMP,
1706                           EXIF_ASCII,
1707                           strlen(gpsDateStamp) + 1,
1708                           (void *)gpsDateStamp);
1709
1710            exif->addEntry(EXIFTAGID_GPS_TIMESTAMP,
1711                           EXIF_RATIONAL,
1712                           3,
1713                           (void *)gpsTimeStamp);
1714        } else {
1715            ALOGE("%s: getExifGpsDataTimeStamp failed", __func__);
1716        }
1717    }
1718
1719    srat_t exposure_val;
1720    rc = getExifExposureValue(&exposure_val, mJpegSettings->exposure_compensation,
1721                              mJpegSettings->exposure_comp_step);
1722    if(rc == NO_ERROR) {
1723        exif->addEntry(EXIFTAGID_EXPOSURE_BIAS_VALUE,
1724                       EXIF_SRATIONAL,
1725                       1,
1726                       (void *)(&exposure_val));
1727    } else {
1728        ALOGE("%s: getExifExposureValue failed ", __func__);
1729    }
1730
1731    return exif;
1732}
1733
1734int QCamera3PicChannel::kMaxBuffers = 1;
1735
1736/*===========================================================================
1737 * FUNCTION   : QCamera3ReprocessChannel
1738 *
1739 * DESCRIPTION: constructor of QCamera3ReprocessChannel
1740 *
1741 * PARAMETERS :
1742 *   @cam_handle : camera handle
1743 *   @cam_ops    : ptr to camera ops table
1744 *   @pp_mask    : post-proccess feature mask
1745 *
1746 * RETURN     : none
1747 *==========================================================================*/
1748QCamera3ReprocessChannel::QCamera3ReprocessChannel(uint32_t cam_handle,
1749                                                 mm_camera_ops_t *cam_ops,
1750                                                 channel_cb_routine cb_routine,
1751                                                 cam_padding_info_t *paddingInfo,
1752                                                 void *userData, void *ch_hdl) :
1753    QCamera3Channel(cam_handle, cam_ops, cb_routine, paddingInfo, userData),
1754    picChHandle(ch_hdl),
1755    m_pSrcChannel(NULL),
1756    m_pMetaChannel(NULL),
1757    m_metaFrame(NULL),
1758    mMemory(NULL)
1759{
1760    memset(mSrcStreamHandles, 0, sizeof(mSrcStreamHandles));
1761}
1762
1763
1764/*===========================================================================
1765 * FUNCTION   : QCamera3ReprocessChannel
1766 *
1767 * DESCRIPTION: constructor of QCamera3ReprocessChannel
1768 *
1769 * PARAMETERS :
1770 *   @cam_handle : camera handle
1771 *   @cam_ops    : ptr to camera ops table
1772 *   @pp_mask    : post-proccess feature mask
1773 *
1774 * RETURN     : none
1775 *==========================================================================*/
1776int32_t QCamera3ReprocessChannel::initialize()
1777{
1778    int32_t rc = NO_ERROR;
1779    mm_camera_channel_attr_t attr;
1780
1781    memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
1782    attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS;
1783    attr.max_unmatched_frames = 1;
1784
1785    rc = init(&attr, NULL);
1786    if (rc < 0) {
1787        ALOGE("%s: init failed", __func__);
1788    }
1789    return rc;
1790}
1791
1792
1793/*===========================================================================
1794 * FUNCTION   : QCamera3ReprocessChannel
1795 *
1796 * DESCRIPTION: constructor of QCamera3ReprocessChannel
1797 *
1798 * PARAMETERS :
1799 *   @cam_handle : camera handle
1800 *   @cam_ops    : ptr to camera ops table
1801 *   @pp_mask    : post-proccess feature mask
1802 *
1803 * RETURN     : none
1804 *==========================================================================*/
1805void QCamera3ReprocessChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
1806                                  QCamera3Stream *stream)
1807{
1808    //Got the pproc data callback. Now send to jpeg encoding
1809    uint8_t frameIndex;
1810    mm_camera_super_buf_t* frame = NULL;
1811    QCamera3PicChannel *obj = (QCamera3PicChannel *)picChHandle;
1812
1813    if(!super_frame) {
1814         ALOGE("%s: Invalid Super buffer",__func__);
1815         return;
1816    }
1817
1818    if(super_frame->num_bufs != 1) {
1819         ALOGE("%s: Multiple streams are not supported",__func__);
1820         return;
1821    }
1822    if(super_frame->bufs[0] == NULL ) {
1823         ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
1824                  __func__);
1825         return;
1826    }
1827
1828    frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
1829    frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
1830    if (frame == NULL) {
1831       ALOGE("%s: Error allocating memory to save received_frame structure.",
1832                                                                    __func__);
1833       if(stream) {
1834           stream->bufDone(frameIndex);
1835       }
1836       return;
1837    }
1838    *frame = *super_frame;
1839    //queue back the metadata buffer
1840    if (m_metaFrame != NULL) {
1841       ((QCamera3MetadataChannel*)m_pMetaChannel)->bufDone(m_metaFrame);
1842       free(m_metaFrame);
1843       m_metaFrame = NULL;
1844    } else {
1845       ALOGE("%s: Meta frame was NULL", __func__);
1846    }
1847    obj->m_postprocessor.processPPData(frame);
1848    return;
1849}
1850
1851/*===========================================================================
1852 * FUNCTION   : QCamera3ReprocessChannel
1853 *
1854 * DESCRIPTION: default constructor of QCamera3ReprocessChannel
1855 *
1856 * PARAMETERS : none
1857 *
1858 * RETURN     : none
1859 *==========================================================================*/
1860QCamera3ReprocessChannel::QCamera3ReprocessChannel() :
1861    m_pSrcChannel(NULL),
1862    m_pMetaChannel(NULL),
1863    m_metaFrame(NULL)
1864{
1865}
1866
1867/*===========================================================================
1868 * FUNCTION   : QCamera3ReprocessChannel
1869 *
1870 * DESCRIPTION: register the buffers of the reprocess channel
1871 *
1872 * PARAMETERS : none
1873 *
1874 * RETURN     : none
1875 *==========================================================================*/
1876int32_t QCamera3ReprocessChannel::registerBuffers(uint32_t num_buffers, buffer_handle_t **buffers)
1877{
1878   return 0;
1879}
1880
1881/*===========================================================================
1882 * FUNCTION   : getStreamBufs
1883 *
1884 * DESCRIPTION: register the buffers of the reprocess channel
1885 *
1886 * PARAMETERS : none
1887 *
1888 * RETURN     : QCamera3Memory *
1889 *==========================================================================*/
1890QCamera3Memory* QCamera3ReprocessChannel::getStreamBufs(uint32_t len)
1891{
1892   int rc = 0;
1893
1894    mMemory = new QCamera3HeapMemory();
1895    if (!mMemory) {
1896        ALOGE("%s: unable to create reproc memory", __func__);
1897        return NULL;
1898    }
1899
1900    //Queue YUV buffers in the beginning mQueueAll = true
1901    rc = mMemory->allocate(2, len, true);
1902    if (rc < 0) {
1903        ALOGE("%s: unable to allocate reproc memory", __func__);
1904        delete mMemory;
1905        mMemory = NULL;
1906        return NULL;
1907    }
1908    return mMemory;
1909}
1910
1911/*===========================================================================
1912 * FUNCTION   : getStreamBufs
1913 *
1914 * DESCRIPTION: register the buffers of the reprocess channel
1915 *
1916 * PARAMETERS : none
1917 *
1918 * RETURN     :
1919 *==========================================================================*/
1920void QCamera3ReprocessChannel::putStreamBufs()
1921{
1922    mMemory->deallocate();
1923    delete mMemory;
1924    mMemory = NULL;
1925}
1926
1927/*===========================================================================
1928 * FUNCTION   : ~QCamera3ReprocessChannel
1929 *
1930 * DESCRIPTION: destructor of QCamera3ReprocessChannel
1931 *
1932 * PARAMETERS : none
1933 *
1934 * RETURN     : none
1935 *==========================================================================*/
1936QCamera3ReprocessChannel::~QCamera3ReprocessChannel()
1937{
1938}
1939
1940/*===========================================================================
1941 * FUNCTION   : getStreamBySourceHandle
1942 *
1943 * DESCRIPTION: find reprocess stream by its source stream handle
1944 *
1945 * PARAMETERS :
1946 *   @srcHandle : source stream handle
1947 *
1948 * RETURN     : ptr to reprocess stream if found. NULL if not found
1949 *==========================================================================*/
1950QCamera3Stream * QCamera3ReprocessChannel::getStreamBySourceHandle(uint32_t srcHandle)
1951{
1952    QCamera3Stream *pStream = NULL;
1953
1954    for (int i = 0; i < m_numStreams; i++) {
1955        if (mSrcStreamHandles[i] == srcHandle) {
1956            pStream = mStreams[i];
1957            break;
1958        }
1959    }
1960    return pStream;
1961}
1962
1963/*===========================================================================
1964 * FUNCTION   : doReprocess
1965 *
1966 * DESCRIPTION: request to do a reprocess on the frame
1967 *
1968 * PARAMETERS :
1969 *   @frame   : frame to be performed a reprocess
1970 *
1971 * RETURN     : int32_t type of status
1972 *              NO_ERROR  -- success
1973 *              none-zero failure code
1974 *==========================================================================*/
1975int32_t QCamera3ReprocessChannel::doReprocess(mm_camera_super_buf_t *frame,
1976                                              mm_camera_super_buf_t *meta_frame)
1977{
1978    int32_t rc = 0;
1979    if (m_numStreams < 1) {
1980        ALOGE("%s: No reprocess stream is created", __func__);
1981        return -1;
1982    }
1983    if (m_pSrcChannel == NULL) {
1984        ALOGE("%s: No source channel for reprocess", __func__);
1985        return -1;
1986    }
1987    m_metaFrame = meta_frame;
1988    for (int i = 0; i < frame->num_bufs; i++) {
1989        QCamera3Stream *pStream = getStreamBySourceHandle(frame->bufs[i]->stream_id);
1990        if (pStream != NULL) {
1991            cam_stream_parm_buffer_t param;
1992            memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
1993            param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
1994            param.reprocess.buf_index = frame->bufs[i]->buf_idx;
1995            param.reprocess.frame_idx = frame->bufs[i]->frame_idx;
1996            if (meta_frame != NULL) {
1997               param.reprocess.meta_present = 1;
1998               param.reprocess.meta_stream_handle = m_pMetaChannel->mStreams[0]->getMyServerID();
1999               param.reprocess.meta_buf_index = meta_frame->bufs[0]->buf_idx;
2000            }
2001            rc = pStream->setParameter(param);
2002            if (rc != NO_ERROR) {
2003                ALOGE("%s: stream setParameter for reprocess failed", __func__);
2004                break;
2005            }
2006        }
2007    }
2008    return rc;
2009}
2010
2011/*===========================================================================
2012 * FUNCTION   : doReprocess
2013 *
2014 * DESCRIPTION: request to do a reprocess on the frame
2015 *
2016 * PARAMETERS :
2017 *   @buf_fd     : fd to the input buffer that needs reprocess
2018 *   @buf_lenght : length of the input buffer
2019 *   @ret_val    : result of reprocess.
2020 *                 Example: Could be faceID in case of register face image.
2021 *
2022 * RETURN     : int32_t type of status
2023 *              NO_ERROR  -- success
2024 *              none-zero failure code
2025 *==========================================================================*/
2026int32_t QCamera3ReprocessChannel::doReprocess(int buf_fd,
2027                                              uint32_t buf_length,
2028                                              int32_t &ret_val,
2029                                              mm_camera_super_buf_t *meta_frame)
2030{
2031    int32_t rc = 0;
2032    if (m_numStreams < 1) {
2033        ALOGE("%s: No reprocess stream is created", __func__);
2034        return -1;
2035    }
2036    if (meta_frame == NULL) {
2037        ALOGE("%s: Did not get corresponding metadata in time", __func__);
2038        return -1;
2039    }
2040
2041    uint32_t buf_idx = 0;
2042    for (int i = 0; i < m_numStreams; i++) {
2043        rc = mStreams[i]->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
2044                                 buf_idx, -1,
2045                                 buf_fd, buf_length);
2046
2047        if (rc == NO_ERROR) {
2048            cam_stream_parm_buffer_t param;
2049            memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
2050            param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
2051            param.reprocess.buf_index = buf_idx;
2052            param.reprocess.meta_present = 1;
2053            param.reprocess.meta_stream_handle = m_pMetaChannel->mStreams[0]->getMyServerID();
2054            param.reprocess.meta_buf_index = meta_frame->bufs[0]->buf_idx;
2055            rc = mStreams[i]->setParameter(param);
2056            if (rc == NO_ERROR) {
2057                ret_val = param.reprocess.ret_val;
2058            }
2059            mStreams[i]->unmapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
2060                                  buf_idx, -1);
2061        }
2062    }
2063    return rc;
2064}
2065
2066/*===========================================================================
2067 * FUNCTION   : addReprocStreamsFromSource
2068 *
2069 * DESCRIPTION: add reprocess streams from input source channel
2070 *
2071 * PARAMETERS :
2072 *   @config         : pp feature configuration
2073 *   @pSrcChannel    : ptr to input source channel that needs reprocess
2074 *   @pMetaChannel   : ptr to metadata channel to get corresp. metadata
2075 *
2076 * RETURN     : int32_t type of status
2077 *              NO_ERROR  -- success
2078 *              none-zero failure code
2079 *==========================================================================*/
2080int32_t QCamera3ReprocessChannel::addReprocStreamsFromSource(cam_pp_feature_config_t &config,
2081                                                             QCamera3Channel *pSrcChannel,
2082                                                             QCamera3Channel *pMetaChannel)
2083{
2084    int32_t rc = 0;
2085    QCamera3Stream *pSrcStream = pSrcChannel->getStreamByIndex(0);
2086    if (pSrcStream == NULL) {
2087       ALOGE("%s: source channel doesn't have a stream", __func__);
2088       return BAD_VALUE;
2089    }
2090    cam_stream_reproc_config_t reprocess_config;
2091    cam_dimension_t streamDim;
2092    cam_stream_type_t streamType;
2093    cam_format_t streamFormat;
2094    cam_frame_len_offset_t frameOffset;
2095    int num_buffers = 2;
2096
2097    streamType = CAM_STREAM_TYPE_OFFLINE_PROC;
2098    pSrcStream->getFormat(streamFormat);
2099    pSrcStream->getFrameDimension(streamDim);
2100    pSrcStream->getFrameOffset(frameOffset);
2101
2102    reprocess_config.pp_type = CAM_ONLINE_REPROCESS_TYPE;
2103    reprocess_config.online.input_stream_id = pSrcStream->getMyServerID();
2104    reprocess_config.online.input_stream_type = pSrcStream->getMyType();
2105    reprocess_config.pp_feature_config = config;
2106
2107    mSrcStreamHandles[m_numStreams] = pSrcStream->getMyHandle();
2108
2109    if (reprocess_config.pp_feature_config.feature_mask & CAM_QCOM_FEATURE_ROTATION) {
2110        if (reprocess_config.pp_feature_config.rotation == ROTATE_90 ||
2111            reprocess_config.pp_feature_config.rotation == ROTATE_270) {
2112            // rotated by 90 or 270, need to switch width and height
2113            int32_t temp = streamDim.height;
2114            streamDim.height = streamDim.width;
2115            streamDim.width = temp;
2116        }
2117    }
2118
2119    QCamera3Stream *pStream = new QCamera3Stream(m_camHandle,
2120                                               m_handle,
2121                                               m_camOps,
2122                                               mPaddingInfo,
2123                                               (QCamera3Channel*)this);
2124    if (pStream == NULL) {
2125        ALOGE("%s: No mem for Stream", __func__);
2126        return NO_MEMORY;
2127    }
2128
2129    rc = pStream->init(streamType, streamFormat, streamDim, &reprocess_config,
2130                       num_buffers,QCamera3Channel::streamCbRoutine, this);
2131
2132
2133    if (rc == 0) {
2134        mStreams[m_numStreams] = pStream;
2135        m_numStreams++;
2136    } else {
2137        ALOGE("%s: failed to create reprocess stream", __func__);
2138        delete pStream;
2139    }
2140
2141    if (rc == NO_ERROR) {
2142        m_pSrcChannel = pSrcChannel;
2143        m_pMetaChannel = pMetaChannel;
2144    }
2145    if(m_camOps->request_super_buf(m_camHandle,m_handle,1) < 0) {
2146        ALOGE("%s: Request for super buffer failed",__func__);
2147    }
2148    return rc;
2149}
2150
2151
2152}; // namespace qcamera
2153