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