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