QCamera3Channel.cpp revision 66cadfdce2ea19f4707bf2a595b58bd36fbfdf3b
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 3
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    mChannelCB = cb_routine;
77    mPaddingInfo = paddingInfo;
78    mUserData = userData;
79    m_bIsActive = false;
80
81    m_handle = 0;
82    m_numStreams = 0;
83    memset(mStreams, 0, sizeof(mStreams));
84}
85
86/*===========================================================================
87 * FUNCTION   : QCamera3Channel
88 *
89 * DESCRIPTION: default constrcutor of QCamera3Channel
90 *
91 * PARAMETERS : none
92 *
93 * RETURN     : none
94 *==========================================================================*/
95QCamera3Channel::QCamera3Channel()
96{
97    m_camHandle = 0;
98    m_camOps = NULL;
99    mPaddingInfo = NULL;
100    mUserData = NULL;
101    m_bIsActive = false;
102
103    m_handle = 0;
104    m_numStreams = 0;
105    memset(mStreams, 0, sizeof(mStreams));
106}
107
108/*===========================================================================
109 * FUNCTION   : ~QCamera3Channel
110 *
111 * DESCRIPTION: destructor of QCamera3Channel
112 *
113 * PARAMETERS : none
114 *
115 * RETURN     : none
116 *==========================================================================*/
117QCamera3Channel::~QCamera3Channel()
118{
119    if (m_bIsActive)
120        stop();
121
122    for (int i = 0; i < m_numStreams; i++) {
123        if (mStreams[i] != NULL) {
124            delete mStreams[i];
125            mStreams[i] = 0;
126        }
127    }
128    m_numStreams = 0;
129    m_camOps->delete_channel(m_camHandle, m_handle);
130    m_handle = 0;
131}
132
133/*===========================================================================
134 * FUNCTION   : init
135 *
136 * DESCRIPTION: initialization of channel
137 *
138 * PARAMETERS :
139 *   @attr    : channel bundle attribute setting
140 *   @dataCB  : data notify callback
141 *   @userData: user data ptr
142 *
143 * RETURN     : int32_t type of status
144 *              NO_ERROR  -- success
145 *              none-zero failure code
146 *==========================================================================*/
147int32_t QCamera3Channel::init(mm_camera_channel_attr_t *attr,
148                             mm_camera_buf_notify_t dataCB)
149{
150    m_handle = m_camOps->add_channel(m_camHandle,
151                                      attr,
152                                      dataCB,
153                                      mUserData);
154    if (m_handle == 0) {
155        ALOGE("%s: Add channel failed", __func__);
156        return UNKNOWN_ERROR;
157    }
158    return NO_ERROR;
159}
160
161/*===========================================================================
162 * FUNCTION   : addStream
163 *
164 * DESCRIPTION: add a stream into channel
165 *
166 * PARAMETERS :
167 *   @allocator      : stream related buffer allocator
168 *   @streamInfoBuf  : ptr to buf that constains stream info
169 *   @minStreamBufNum: number of stream buffers needed
170 *   @paddingInfo    : padding information
171 *   @stream_cb      : stream data notify callback
172 *   @userdata       : user data ptr
173 *
174 * RETURN     : int32_t type of status
175 *              NO_ERROR  -- success
176 *              none-zero failure code
177 *==========================================================================*/
178int32_t QCamera3Channel::addStream(cam_stream_type_t streamType,
179                                  cam_format_t streamFormat,
180                                  cam_dimension_t streamDim,
181                                  uint8_t minStreamBufNum)
182{
183    int32_t rc = NO_ERROR;
184    if (m_numStreams >= MAX_STREAM_NUM_IN_BUNDLE) {
185        ALOGE("%s: stream number (%d) exceeds max limit (%d)",
186              __func__, m_numStreams, MAX_STREAM_NUM_IN_BUNDLE);
187        return BAD_VALUE;
188    }
189    QCamera3Stream *pStream = new QCamera3Stream(m_camHandle,
190                                               m_handle,
191                                               m_camOps,
192                                               mPaddingInfo,
193                                               this);
194    if (pStream == NULL) {
195        ALOGE("%s: No mem for Stream", __func__);
196        return NO_MEMORY;
197    }
198
199    rc = pStream->init(streamType, streamFormat, streamDim, minStreamBufNum,
200                                                    streamCbRoutine, this);
201    if (rc == 0) {
202        mStreams[m_numStreams] = pStream;
203        m_numStreams++;
204    } else {
205        delete pStream;
206    }
207    return rc;
208}
209
210/*===========================================================================
211 * FUNCTION   : start
212 *
213 * DESCRIPTION: start channel, which will start all streams belong to this channel
214 *
215 * PARAMETERS :
216 *
217 * RETURN     : int32_t type of status
218 *              NO_ERROR  -- success
219 *              none-zero failure code
220 *==========================================================================*/
221int32_t QCamera3Channel::start()
222{
223    int32_t rc = NO_ERROR;
224
225    if (m_numStreams > 1) {
226        ALOGE("%s: bundle not supported", __func__);
227    }
228
229    for (int i = 0; i < m_numStreams; i++) {
230        if (mStreams[i] != NULL) {
231            mStreams[i]->start();
232        }
233    }
234    rc = m_camOps->start_channel(m_camHandle, m_handle);
235
236    if (rc != NO_ERROR) {
237        for (int i = 0; i < m_numStreams; i++) {
238            if (mStreams[i] != NULL) {
239                mStreams[i]->stop();
240            }
241        }
242    } else {
243        m_bIsActive = true;
244    }
245
246    return rc;
247}
248
249/*===========================================================================
250 * FUNCTION   : stop
251 *
252 * DESCRIPTION: stop a channel, which will stop all streams belong to this channel
253 *
254 * PARAMETERS : none
255 *
256 * RETURN     : int32_t type of status
257 *              NO_ERROR  -- success
258 *              none-zero failure code
259 *==========================================================================*/
260int32_t QCamera3Channel::stop()
261{
262    int32_t rc = NO_ERROR;
263    rc = m_camOps->stop_channel(m_camHandle, m_handle);
264
265    for (int i = 0; i < m_numStreams; i++) {
266        if (mStreams[i] != NULL) {
267            mStreams[i]->stop();
268        }
269    }
270
271    m_bIsActive = false;
272    return rc;
273}
274
275/*===========================================================================
276 * FUNCTION   : bufDone
277 *
278 * DESCRIPTION: return a stream buf back to kernel
279 *
280 * PARAMETERS :
281 *   @recvd_frame  : stream buf frame to be returned
282 *
283 * RETURN     : int32_t type of status
284 *              NO_ERROR  -- success
285 *              none-zero failure code
286 *==========================================================================*/
287int32_t QCamera3Channel::bufDone(mm_camera_super_buf_t *recvd_frame)
288{
289    int32_t rc = NO_ERROR;
290    for (int i = 0; i < recvd_frame->num_bufs; i++) {
291         if (recvd_frame->bufs[i] != NULL) {
292             for (int j = 0; j < m_numStreams; j++) {
293                 if (mStreams[j] != NULL &&
294                     mStreams[j]->getMyHandle() == recvd_frame->bufs[i]->stream_id) {
295                     rc = mStreams[j]->bufDone(recvd_frame->bufs[i]->buf_idx);
296                     break; // break loop j
297                 }
298             }
299         }
300    }
301
302    return rc;
303}
304
305/*===========================================================================
306 * FUNCTION   : getStreamByHandle
307 *
308 * DESCRIPTION: return stream object by stream handle
309 *
310 * PARAMETERS :
311 *   @streamHandle : stream handle
312 *
313 * RETURN     : stream object. NULL if not found
314 *==========================================================================*/
315QCamera3Stream *QCamera3Channel::getStreamByHandle(uint32_t streamHandle)
316{
317    for (int i = 0; i < m_numStreams; i++) {
318        if (mStreams[i] != NULL && mStreams[i]->getMyHandle() == streamHandle) {
319            return mStreams[i];
320        }
321    }
322    return NULL;
323}
324
325/*===========================================================================
326 * FUNCTION   : getStreamByHandle
327 *
328 * DESCRIPTION: return stream object by stream handle
329 *
330 * PARAMETERS :
331 *   @streamHandle : stream handle
332 *
333 * RETURN     : stream object. NULL if not found
334 *==========================================================================*/
335QCamera3Stream *QCamera3Channel::getStreamByIndex(uint8_t index)
336{
337    if (index < m_numStreams) {
338        return mStreams[index];
339    }
340    return NULL;
341}
342
343/*===========================================================================
344 * FUNCTION   : streamCbRoutine
345 *
346 * DESCRIPTION: callback routine for stream
347 *
348 * PARAMETERS :
349 *   @streamHandle : stream handle
350 *
351 * RETURN     : stream object. NULL if not found
352 *==========================================================================*/
353void QCamera3Channel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
354                QCamera3Stream *stream, void *userdata)
355{
356    QCamera3Channel *channel = (QCamera3Channel *)userdata;
357    if (channel == NULL) {
358        ALOGE("%s: invalid channel pointer", __func__);
359        return;
360    }
361    channel->streamCbRoutine(super_frame, stream);
362}
363
364/*===========================================================================
365 * FUNCTION   : QCamera3RegularChannel
366 *
367 * DESCRIPTION: constrcutor of QCamera3RegularChannel
368 *
369 * PARAMETERS :
370 *   @cam_handle : camera handle
371 *   @cam_ops    : ptr to camera ops table
372 *   @cb_routine : callback routine to frame aggregator
373 *   @stream     : camera3_stream_t structure
374 *
375 * RETURN     : none
376 *==========================================================================*/
377QCamera3RegularChannel::QCamera3RegularChannel(uint32_t cam_handle,
378                    mm_camera_ops_t *cam_ops,
379                    channel_cb_routine cb_routine,
380                    cam_padding_info_t *paddingInfo,
381                    void *userData,
382                    camera3_stream_t *stream) :
383                        QCamera3Channel(cam_handle, cam_ops, cb_routine,
384                                                paddingInfo, userData),
385                        mCamera3Stream(stream),
386                        mNumBufs(0),
387                        mCamera3Buffers(NULL),
388                        mMemory(NULL)
389{
390}
391
392/*===========================================================================
393 * FUNCTION   : ~QCamera3RegularChannel
394 *
395 * DESCRIPTION: destructor of QCamera3RegularChannel
396 *
397 * PARAMETERS : none
398 *
399 * RETURN     : none
400 *==========================================================================*/
401QCamera3RegularChannel::~QCamera3RegularChannel()
402{
403    if (mCamera3Buffers) {
404        delete[] mCamera3Buffers;
405    }
406}
407
408int32_t QCamera3RegularChannel::initialize()
409{
410  //TO DO
411  return 0;
412}
413
414/*===========================================================================
415 * FUNCTION   : request
416 *
417 * DESCRIPTION: process a request from camera service. Stream on if ncessary.
418 *
419 * PARAMETERS :
420 *   @buffer  : buffer to be filled for this request
421 *
422 * RETURN     : 0 on a success start of capture
423 *              -EINVAL on invalid input
424 *              -ENODEV on serious error
425 *==========================================================================*/
426int32_t QCamera3RegularChannel::request(buffer_handle_t *buffer, uint32_t frameNumber)
427{
428    //FIX ME: Return buffer back in case of failures below.
429
430    int32_t rc = NO_ERROR;
431    int index;
432    if(!m_bIsActive) {
433        ALOGD("%s: First request on this channel starting stream",__func__);
434        start();
435        if(rc != NO_ERROR) {
436            ALOGE("%s: Failed to start the stream on the request",__func__);
437            return rc;
438        }
439    } else {
440        ALOGV("%s: Request on an existing stream",__func__);
441    }
442
443    if(!mMemory) {
444        ALOGE("%s: error, Gralloc Memory object not yet created for this stream",__func__);
445        return NO_MEMORY;
446    }
447
448    index = mMemory->getMatchBufIndex((void*)buffer);
449    if(index < 0) {
450        ALOGE("%s: Could not find object among registered buffers",__func__);
451        return DEAD_OBJECT;
452    }
453
454    rc = mStreams[0]->bufDone(index);
455    if(rc != NO_ERROR) {
456        ALOGE("%s: Failed to Q new buffer to stream",__func__);
457        return rc;
458    }
459
460    rc = mMemory->markFrameNumber(index, frameNumber);
461    return rc;
462}
463
464/*===========================================================================
465 * FUNCTION   : registerBuffers
466 *
467 * DESCRIPTION: register streaming buffers to the channel object
468 *
469 * PARAMETERS :
470 *   @num_buffers : number of buffers to be registered
471 *   @buffers     : buffer to be registered
472 *
473 * RETURN     : 0 on a success start of capture
474 *              -EINVAL on invalid input
475 *              -ENOMEM on failure to register the buffer
476 *              -ENODEV on serious error
477 *==========================================================================*/
478int32_t QCamera3RegularChannel::registerBuffers(uint32_t num_buffers, buffer_handle_t **buffers)
479{
480    int rc = 0;
481    struct private_handle_t *priv_handle = (struct private_handle_t *)(*buffers[0]);
482    cam_stream_type_t streamType;
483    cam_format_t streamFormat;
484    cam_dimension_t streamDim;
485
486    rc = init(NULL, NULL);
487    if (rc < 0) {
488        ALOGE("%s: init failed", __func__);
489        return rc;
490    }
491
492    if (mCamera3Stream->format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
493        if (priv_handle->flags & private_handle_t::PRIV_FLAGS_VIDEO_ENCODER) {
494            streamType = CAM_STREAM_TYPE_VIDEO;
495            streamFormat = CAM_FORMAT_YUV_420_NV12;
496        } else if (priv_handle->flags & private_handle_t::PRIV_FLAGS_EXTERNAL_ONLY) {
497            streamType = CAM_STREAM_TYPE_PREVIEW;
498            streamFormat = CAM_FORMAT_YUV_420_NV21;
499        } else {
500            ALOGE("%s: priv_handle->flags 0x%x not supported",
501                    __func__, priv_handle->flags);
502            return -EINVAL;
503        }
504    } else {
505        //TODO: Fail for other types of streams for now
506        ALOGE("%s: format is not IMPLEMENTATION_DEFINED", __func__);
507        return -EINVAL;
508    }
509
510    /* Bookkeep buffer set because they go out of scope after register call */
511    mNumBufs = num_buffers;
512    mCamera3Buffers = new buffer_handle_t*[num_buffers];
513    if (mCamera3Buffers == NULL) {
514        ALOGE("%s: Failed to allocate buffer_handle_t*", __func__);
515        return -ENOMEM;
516    }
517    for (size_t i = 0; i < num_buffers; i++)
518        mCamera3Buffers[i] = buffers[i];
519
520    streamDim.width = mCamera3Stream->width;
521    streamDim.height = mCamera3Stream->height;
522    rc = QCamera3Channel::addStream(streamType, streamFormat, streamDim,
523        num_buffers);
524
525    return rc;
526}
527
528void QCamera3RegularChannel::streamCbRoutine(
529                            mm_camera_super_buf_t *super_frame,
530                            QCamera3Stream *stream)
531{
532    //FIXME Q Buf back in case of error?
533    uint8_t frameIndex;
534    buffer_handle_t *resultBuffer;
535    int32_t resultFrameNumber;
536    camera3_stream_buffer_t result;
537
538    if(!super_frame) {
539         ALOGE("%s: Invalid Super buffer",__func__);
540         return;
541    }
542
543    if(super_frame->num_bufs != 1) {
544         ALOGE("%s: Multiple streams are not supported",__func__);
545         return;
546    }
547    if(super_frame->bufs[0] == NULL ) {
548         ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
549                  __func__);
550         return;
551    }
552
553    frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
554    if(frameIndex >= mNumBufs) {
555         ALOGE("%s: Error, Invalid index for buffer",__func__);
556         if(stream) {
557             stream->bufDone(frameIndex);
558         }
559         return;
560    }
561
562    ////Use below data to issue framework callback
563    resultBuffer = mCamera3Buffers[frameIndex];
564    resultFrameNumber = mMemory->getFrameNumber(frameIndex);
565
566    result.stream = mCamera3Stream;
567    result.buffer = resultBuffer;
568    result.status = CAMERA3_BUFFER_STATUS_OK;
569    result.acquire_fence = -1;
570    result.release_fence = -1;
571
572    mChannelCB(NULL, &result, resultFrameNumber, mUserData);
573    return;
574}
575
576QCamera3Memory* QCamera3RegularChannel::getStreamBufs(uint32_t len)
577{
578    if (mNumBufs == 0 || mCamera3Buffers == NULL) {
579        ALOGE("%s: buffers not registered yet", __func__);
580        return NULL;
581    }
582
583    mMemory = new QCamera3GrallocMemory();
584    if (mMemory == NULL) {
585        return NULL;
586    }
587
588    if (mMemory->registerBuffers(mNumBufs, mCamera3Buffers) < 0) {
589        delete mMemory;
590        mMemory = NULL;
591        return NULL;
592    }
593    return mMemory;
594}
595
596void QCamera3RegularChannel::putStreamBufs()
597{
598    mMemory->unregisterBuffers();
599    delete mMemory;
600    mMemory = NULL;
601}
602
603int QCamera3RegularChannel::kMaxBuffers = 3;
604
605QCamera3MetadataChannel::QCamera3MetadataChannel(uint32_t cam_handle,
606                    mm_camera_ops_t *cam_ops,
607                    channel_cb_routine cb_routine,
608                    cam_padding_info_t *paddingInfo,
609                    void *userData) :
610                        QCamera3Channel(cam_handle, cam_ops,
611                                cb_routine, paddingInfo, userData),
612                        mMemory(NULL)
613{
614#ifdef FAKE_FRAME_NUMBERS
615    startingFrameNumber=0;
616#endif
617}
618
619QCamera3MetadataChannel::~QCamera3MetadataChannel()
620{
621    if (m_bIsActive)
622        stop();
623
624    if (mMemory) {
625        mMemory->deallocate();
626        delete mMemory;
627        mMemory = NULL;
628    }
629}
630
631int32_t QCamera3MetadataChannel::initialize()
632{
633    int32_t rc;
634    cam_dimension_t streamDim;
635
636    if (mMemory || m_numStreams > 0) {
637        ALOGE("%s: metadata channel already initialized", __func__);
638        return -EINVAL;
639    }
640
641    rc = init(NULL, NULL);
642    if (rc < 0) {
643        ALOGE("%s: init failed", __func__);
644        return rc;
645    }
646
647    streamDim.width = sizeof(parm_buffer_t),
648    streamDim.height = 1;
649    rc = QCamera3Channel::addStream(CAM_STREAM_TYPE_METADATA, CAM_FORMAT_MAX,
650        streamDim, MIN_STREAMING_BUFFER_NUM);
651    if (rc < 0) {
652        ALOGE("%s: addStream failed", __func__);
653    }
654    return rc;
655}
656
657int32_t QCamera3MetadataChannel::request(buffer_handle_t *buffer, uint32_t frameNumber)
658{
659    if (!m_bIsActive) {
660#ifdef FAKE_FRAME_NUMBERS
661        startingFrameNumber=frameNumber;
662#endif
663        return start();
664    }
665    else
666        return 0;
667}
668
669int32_t QCamera3MetadataChannel::registerBuffers(uint32_t /*num_buffers*/,
670                                        buffer_handle_t ** /*buffers*/)
671{
672    // no registerBuffers are supported for metadata channel
673    return -EINVAL;
674}
675
676void QCamera3MetadataChannel::streamCbRoutine(
677                        mm_camera_super_buf_t *super_frame,
678                        QCamera3Stream *stream)
679{
680    uint32_t requestNumber = 0;
681    if (super_frame == NULL || super_frame->num_bufs != 1) {
682        ALOGE("%s: super_frame is not valid", __func__);
683        return;
684    }
685#ifdef FAKE_FRAME_NUMBERS
686    requestNumber = startingFrameNumber++;
687#endif
688    mChannelCB((metadata_buffer_t *)(super_frame->bufs[0]->buffer),
689                                            NULL, requestNumber, mUserData);
690
691    //Return the buffer
692    stream->bufDone(super_frame->bufs[0]->buf_idx);
693}
694
695QCamera3Memory* QCamera3MetadataChannel::getStreamBufs(uint32_t len)
696{
697    int rc;
698    if (len != sizeof(parm_buffer_t)) {
699        ALOGE("%s: size doesn't match %d vs %d", __func__,
700                len, sizeof(parm_buffer_t));
701        return NULL;
702    }
703    mMemory = new QCamera3HeapMemory();
704    if (!mMemory) {
705        ALOGE("%s: unable to create metadata memory", __func__);
706        return NULL;
707    }
708    rc = mMemory->allocate(MIN_STREAMING_BUFFER_NUM, len, true);
709    if (rc < 0) {
710        ALOGE("%s: unable to allocate metadata memory", __func__);
711        delete mMemory;
712        mMemory = NULL;
713        return NULL;
714    }
715    memset(mMemory->getPtr(0), 0, sizeof(parm_buffer_t));
716    return mMemory;
717}
718
719void QCamera3MetadataChannel::putStreamBufs()
720{
721    mMemory->deallocate();
722    delete mMemory;
723    mMemory = NULL;
724}
725
726/*===========================================================================
727 * FUNCTION   : jpegEvtHandle
728 *
729 * DESCRIPTION: Function registerd to mm-jpeg-interface to handle jpeg events.
730                Construct result payload and call mChannelCb to deliver buffer
731                to framework.
732 *
733 * PARAMETERS :
734 *   @status    : status of jpeg job
735 *   @client_hdl: jpeg client handle
736 *   @jobId     : jpeg job Id
737 *   @p_ouput   : ptr to jpeg output result struct
738 *   @userdata  : user data ptr
739 *
740 * RETURN     : none
741 *==========================================================================*/
742void QCamera3PicChannel::jpegEvtHandle(jpeg_job_status_t status,
743                                              uint32_t /*client_hdl*/,
744                                              uint32_t jobId,
745                                              mm_jpeg_output_t *p_output,
746                                              void *userdata)
747{
748    buffer_handle_t *resultBuffer;
749    int32_t resultFrameNumber;
750    int resultStatus = CAMERA3_BUFFER_STATUS_OK;
751    camera3_stream_buffer_t result;
752    camera3_jpeg_blob_t jpegHeader;
753    char* jpeg_eof = 0;
754    QCamera3PicChannel *obj = (QCamera3PicChannel *)userdata;
755    if (obj) {
756        //Construct payload for process_capture_result. Call mChannelCb
757
758        qcamera_jpeg_data_t *job = obj->m_postprocessor.findJpegJobByJobId(jobId);
759
760        if ((job == NULL) || (status == JPEG_JOB_STATUS_ERROR)) {
761            ALOGE("%s: Error in jobId: (%d) with status: %d", __func__, jobId, status);
762            resultStatus = CAMERA3_BUFFER_STATUS_ERROR;
763        }
764
765        //Construct jpeg transient header of type camera3_jpeg_blob_t
766        //Append at the end of jpeg image of buf_filled_len size
767
768        jpegHeader.jpeg_blob_id = CAMERA3_JPEG_BLOB_ID;
769        jpegHeader.jpeg_size = p_output->buf_filled_len;
770
771
772        char* jpeg_buf = (char *)p_output->buf_vaddr;
773
774        jpeg_eof = &jpeg_buf[p_output->buf_filled_len];
775        memcpy(jpeg_eof, &jpegHeader, sizeof(jpegHeader));
776
777        ////Use below data to issue framework callback
778
779        resultBuffer = obj->mCamera3Buffers[0];
780        resultFrameNumber = obj->mMemory->getFrameNumber(0);
781
782        result.stream = obj->mCamera3Stream;
783        result.buffer = resultBuffer;
784        result.status = resultStatus;
785        result.acquire_fence = -1;
786        result.release_fence = -1;
787
788        obj->mChannelCB(NULL, &result, resultFrameNumber, obj->mUserData);
789
790        // release internal data for jpeg job
791        if (job != NULL) {
792            obj->m_postprocessor.releaseJpegJobData(job);
793            free(job);
794        }
795        return;
796        // }
797    } else {
798        ALOGE("%s: Null userdata in jpeg callback", __func__);
799    }
800}
801
802QCamera3PicChannel::QCamera3PicChannel(uint32_t cam_handle,
803                    mm_camera_ops_t *cam_ops,
804                    channel_cb_routine cb_routine,
805                    cam_padding_info_t *paddingInfo,
806                    void *userData,
807                    camera3_stream_t *stream) :
808                        QCamera3Channel(cam_handle, cam_ops, cb_routine, paddingInfo, userData),
809                        mCamera3Stream(stream),
810                        m_postprocessor(this),
811                        mCamera3Buffers(NULL),
812                        mMemory(NULL),
813                        mYuvMemory(NULL)
814{
815    //TODO
816}
817
818QCamera3PicChannel::~QCamera3PicChannel()
819{
820    if (mCamera3Buffers) {
821        delete[] mCamera3Buffers;
822    }
823}
824
825int32_t QCamera3PicChannel::initialize()
826{
827    int32_t rc = m_postprocessor.init(jpegEvtHandle, this);
828    if (rc != 0) {
829        ALOGE("Init Postprocessor failed");
830        return UNKNOWN_ERROR;
831    }
832    return rc;
833}
834
835int32_t QCamera3PicChannel::request(buffer_handle_t *buffer, uint32_t frameNumber, jpeg_settings_t* jpegSettings)
836{
837    //FIX ME: Return buffer back in case of failures below.
838
839    int32_t rc = NO_ERROR;
840    int index;
841    mJpegSettings = jpegSettings;
842    if(!m_bIsActive) {
843        ALOGD("%s: First request on this channel starting stream",__func__);
844        //Stream on for main image. YUV buffer is queued to the kernel at the end of this call.
845        rc = start();
846    } else {
847        ALOGV("%s: Request on an existing stream",__func__);
848    }
849
850    if(rc != NO_ERROR) {
851        ALOGE("%s: Failed to start the stream on the request",__func__);
852        return rc;
853    }
854
855
856    if(!mMemory) {
857        ALOGE("%s: error, Gralloc Memory object not yet created for this stream",__func__);
858        return NO_MEMORY;
859    }
860
861    index = mMemory->getMatchBufIndex((void*)buffer);
862    if(index < 0) {
863        ALOGE("%s: Could not find object among registered buffers",__func__);
864        return DEAD_OBJECT;
865    }
866
867    rc = mMemory->markFrameNumber(index, frameNumber);
868
869    //Start the postprocessor for jpeg encoding. Pass mMemory as destination buffer
870    m_postprocessor.start(mMemory);
871    return rc;
872}
873
874int32_t QCamera3PicChannel::registerBuffers(uint32_t num_buffers,
875                        buffer_handle_t **buffers)
876{
877    int rc = 0;
878    struct private_handle_t *priv_handle = (struct private_handle_t *)(*buffers[0]);
879    cam_stream_type_t streamType;
880    cam_format_t streamFormat;
881    cam_dimension_t streamDim;
882
883    rc = init(NULL, NULL);
884    if (rc < 0) {
885        ALOGE("%s: init failed", __func__);
886        return rc;
887    }
888
889    if (mCamera3Stream->format == HAL_PIXEL_FORMAT_BLOB) {
890        streamType = CAM_STREAM_TYPE_SNAPSHOT;
891        streamFormat = CAM_FORMAT_YUV_420_NV21;
892    } else {
893        //TODO: Fail for other types of streams for now
894        ALOGE("%s: format is not BLOB", __func__);
895        return -EINVAL;
896    }
897    /* Bookkeep buffer set because they go out of scope after register call */
898    mNumBufs = num_buffers;
899    if(mNumBufs > 1) {
900        ALOGE("%s: currently no support for multiple snapshot buffers");
901        return -EINVAL;
902    }
903
904    mCamera3Buffers = new buffer_handle_t*[num_buffers];
905    if (mCamera3Buffers == NULL) {
906        ALOGE("%s: Failed to allocate buffer_handle_t*", __func__);
907        return -ENOMEM;
908    }
909    for (size_t i = 0; i < num_buffers; i++)
910        mCamera3Buffers[i] = buffers[i];
911
912    streamDim.width = mCamera3Stream->width;
913    streamDim.height = mCamera3Stream->height;
914    rc = QCamera3Channel::addStream(streamType, streamFormat, streamDim,
915        num_buffers);
916
917    return rc;
918}
919
920void QCamera3PicChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
921                            QCamera3Stream *stream)
922{
923    //TODO
924    //Used only for getting YUV. Jpeg callback will be sent back from channel directly to HWI.
925    //Refer to func jpegEvtHandle
926
927    //Got the yuv callback. Calling yuv callback handler in PostProc
928    uint8_t frameIndex;
929    if(!super_frame) {
930         ALOGE("%s: Invalid Super buffer",__func__);
931         return;
932    }
933
934    if(super_frame->num_bufs != 1) {
935         ALOGE("%s: Multiple streams are not supported",__func__);
936         return;
937    }
938    if(super_frame->bufs[0] == NULL ) {
939         ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
940                  __func__);
941         return;
942    }
943
944    frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
945    if(frameIndex >= mNumBufs) {
946         ALOGE("%s: Error, Invalid index for buffer",__func__);
947         if(stream) {
948             stream->bufDone(frameIndex);
949         }
950         return;
951    }
952
953    m_postprocessor.processData(super_frame);
954    return;
955}
956
957QCamera3Memory* QCamera3PicChannel::getStreamBufs(uint32_t len)
958{
959    int rc = 0;
960
961    if (mNumBufs == 0 || mCamera3Buffers == NULL) {
962        ALOGE("%s: buffers not registered yet", __func__);
963        return NULL;
964    }
965
966    mMemory = new QCamera3GrallocMemory();
967    if (mMemory == NULL) {
968        return NULL;
969    }
970
971    //Registering Jpeg output buffer
972    if (mMemory->registerBuffers(mNumBufs, mCamera3Buffers) < 0) {
973        delete mMemory;
974        mMemory = NULL;
975        return NULL;
976    }
977
978    mYuvMemory = new QCamera3HeapMemory();
979    if (!mYuvMemory) {
980        ALOGE("%s: unable to create metadata memory", __func__);
981        return NULL;
982    }
983
984    //Queue YUV buffers in the beginning mQueueAll = true
985    rc = mYuvMemory->allocate(1, len, true);
986    if (rc < 0) {
987        ALOGE("%s: unable to allocate metadata memory", __func__);
988        delete mYuvMemory;
989        mYuvMemory = NULL;
990        return NULL;
991    }
992    return mYuvMemory;
993}
994
995void QCamera3PicChannel::putStreamBufs()
996{
997    mMemory->unregisterBuffers();
998    delete mMemory;
999    mMemory = NULL;
1000
1001    mYuvMemory->deallocate();
1002    delete mYuvMemory;
1003    mYuvMemory = NULL;
1004}
1005
1006/*===========================================================================
1007 * FUNCTION   : needRotationReprocess
1008 *
1009 * DESCRIPTION: if online rotation needs to be done by cpp
1010 *
1011 * PARAMETERS : none
1012 *
1013 * RETURN     : true: needed
1014 *              false: no need
1015 *==========================================================================*/
1016bool QCamera3PicChannel::needOnlineRotation()
1017{
1018    //TBD_Later
1019    //if ((gCamCapability[mCameraId]->qcom_supported_feature_mask & CAM_QCOM_FEATURE_ROTATION) > 0 &&
1020       if (mJpegSettings->jpeg_orientation > 0) {
1021        // current rotation is not zero, and pp has the capability to process rotation
1022        ALOGD("%s: need do online rotation", __func__);
1023        return true;
1024    }
1025    return false;
1026}
1027
1028/*===========================================================================
1029 * FUNCTION   : getThumbnailSize
1030 *
1031 * DESCRIPTION: get user set thumbnail size
1032 *
1033 * PARAMETERS :
1034 *   @dim     : output of thumbnail dimension
1035 *
1036 * RETURN     : none
1037 *==========================================================================*/
1038void QCamera3PicChannel::getThumbnailSize(cam_dimension_t &dim)
1039{
1040    dim = mJpegSettings->thumbnail_size;
1041}
1042
1043/*===========================================================================
1044 * FUNCTION   : getJpegQuality
1045 *
1046 * DESCRIPTION: get user set jpeg quality
1047 *
1048 * PARAMETERS : none
1049 *
1050 * RETURN     : jpeg quality setting
1051 *==========================================================================*/
1052int QCamera3PicChannel::getJpegQuality()
1053{
1054    int quality = mJpegSettings->jpeg_quality;
1055    if (quality < 0) {
1056        quality = 85;  //set to default quality value
1057    }
1058    return quality;
1059}
1060
1061/*===========================================================================
1062 * FUNCTION   : getJpegRotation
1063 *
1064 * DESCRIPTION: get rotation information to be passed into jpeg encoding
1065 *
1066 * PARAMETERS : none
1067 *
1068 * RETURN     : rotation information
1069 *==========================================================================*/
1070int QCamera3PicChannel::getJpegRotation() {
1071    int rotation = mJpegSettings->jpeg_orientation;
1072    if (rotation < 0) {
1073        rotation = 0;
1074    }
1075    return rotation;
1076}
1077
1078/*===========================================================================
1079 * FUNCTION   : getRational
1080 *
1081 * DESCRIPTION: compose rational struct
1082 *
1083 * PARAMETERS :
1084 *   @rat     : ptr to struct to store rational info
1085 *   @num     :num of the rational
1086 *   @denom   : denom of the rational
1087 *
1088 * RETURN     : int32_t type of status
1089 *              NO_ERROR  -- success
1090 *              none-zero failure code
1091 *==========================================================================*/
1092int32_t getRational(rat_t *rat, int num, int denom)
1093{
1094    if (NULL == rat) {
1095        ALOGE("%s: NULL rat input", __func__);
1096        return BAD_VALUE;
1097    }
1098    rat->num = num;
1099    rat->denom = denom;
1100    return NO_ERROR;
1101}
1102
1103/*===========================================================================
1104 * FUNCTION   : parseGPSCoordinate
1105 *
1106 * DESCRIPTION: parse GPS coordinate string
1107 *
1108 * PARAMETERS :
1109 *   @coord_str : [input] coordinate string
1110 *   @coord     : [output]  ptr to struct to store coordinate
1111 *
1112 * RETURN     : int32_t type of status
1113 *              NO_ERROR  -- success
1114 *              none-zero failure code
1115 *==========================================================================*/
1116int parseGPSCoordinate(const char *coord_str, rat_t* coord)
1117{
1118    if(coord == NULL) {
1119        ALOGE("%s: error, invalid argument coord == NULL", __func__);
1120        return BAD_VALUE;
1121    }
1122    float degF = atof(coord_str);
1123    if (degF < 0) {
1124        degF = -degF;
1125    }
1126    float minF = (degF - (int) degF) * 60;
1127    float secF = (minF - (int) minF) * 60;
1128
1129    getRational(&coord[0], (int)degF, 1);
1130    getRational(&coord[1], (int)minF, 1);
1131    getRational(&coord[2], (int)(secF * 10000), 10000);
1132    return NO_ERROR;
1133}
1134
1135/*===========================================================================
1136 * FUNCTION   : getExifDateTime
1137 *
1138 * DESCRIPTION: query exif date time
1139 *
1140 * PARAMETERS :
1141 *   @dateTime : string to store exif date time
1142 *   @count    : lenght of the dateTime string
1143 *
1144 * RETURN     : int32_t type of status
1145 *              NO_ERROR  -- success
1146 *              none-zero failure code
1147 *==========================================================================*/
1148int32_t getExifDateTime(char *dateTime, uint32_t &count)
1149{
1150    //get time and date from system
1151    time_t rawtime;
1152    struct tm * timeinfo;
1153    time(&rawtime);
1154    timeinfo = localtime (&rawtime);
1155    //Write datetime according to EXIF Spec
1156    //"YYYY:MM:DD HH:MM:SS" (20 chars including \0)
1157    snprintf(dateTime, 20, "%04d:%02d:%02d %02d:%02d:%02d",
1158             timeinfo->tm_year + 1900, timeinfo->tm_mon + 1,
1159             timeinfo->tm_mday, timeinfo->tm_hour,
1160             timeinfo->tm_min, timeinfo->tm_sec);
1161    count = 20;
1162
1163    return NO_ERROR;
1164}
1165
1166/*===========================================================================
1167 * FUNCTION   : getExifFocalLength
1168 *
1169 * DESCRIPTION: get exif focal lenght
1170 *
1171 * PARAMETERS :
1172 *   @focalLength : ptr to rational strcut to store focal lenght
1173 *
1174 * RETURN     : int32_t type of status
1175 *              NO_ERROR  -- success
1176 *              none-zero failure code
1177 *==========================================================================*/
1178int32_t getExifFocalLength(rat_t *focalLength, float value)
1179{
1180    int focalLengthValue =
1181        (int)(value * FOCAL_LENGTH_DECIMAL_PRECISION);
1182    return getRational(focalLength, focalLengthValue, FOCAL_LENGTH_DECIMAL_PRECISION);
1183}
1184
1185/*===========================================================================
1186 * FUNCTION   : getExifGpsProcessingMethod
1187 *
1188 * DESCRIPTION: get GPS processing method
1189 *
1190 * PARAMETERS :
1191 *   @gpsProcessingMethod : string to store GPS process method
1192 *   @count               : lenght of the string
1193 *
1194 * RETURN     : int32_t type of status
1195 *              NO_ERROR  -- success
1196 *              none-zero failure code
1197 *==========================================================================*/
1198int32_t getExifGpsProcessingMethod(char *gpsProcessingMethod,
1199                                                      uint32_t &count, int value)
1200{
1201    char str[30];
1202    snprintf(str, sizeof(str), "%d", value);
1203    if(str != NULL) {
1204        memcpy(gpsProcessingMethod, ExifAsciiPrefix, EXIF_ASCII_PREFIX_SIZE);
1205        count = EXIF_ASCII_PREFIX_SIZE;
1206        strncpy(gpsProcessingMethod + EXIF_ASCII_PREFIX_SIZE, str, strlen(str));
1207        count += strlen(str);
1208        gpsProcessingMethod[count++] = '\0'; // increase 1 for the last NULL char
1209        return NO_ERROR;
1210    } else {
1211        return BAD_VALUE;
1212    }
1213}
1214
1215/*===========================================================================
1216 * FUNCTION   : getExifLatitude
1217 *
1218 * DESCRIPTION: get exif latitude
1219 *
1220 * PARAMETERS :
1221 *   @latitude : ptr to rational struct to store latitude info
1222 *   @ladRef   : charater to indicate latitude reference
1223 *
1224 * RETURN     : int32_t type of status
1225 *              NO_ERROR  -- success
1226 *              none-zero failure code
1227 *==========================================================================*/
1228int32_t getExifLatitude(rat_t *latitude,
1229                                           char *latRef, double value)
1230{
1231    char str[30];
1232    snprintf(str, sizeof(str), "%f", value);
1233    if(str != NULL) {
1234        parseGPSCoordinate(str, latitude);
1235
1236        //set Latitude Ref
1237        float latitudeValue = strtof(str, 0);
1238        if(latitudeValue < 0.0f) {
1239            latRef[0] = 'S';
1240        } else {
1241            latRef[0] = 'N';
1242        }
1243        latRef[1] = '\0';
1244        return NO_ERROR;
1245    }else{
1246        return BAD_VALUE;
1247    }
1248}
1249
1250/*===========================================================================
1251 * FUNCTION   : getExifLongitude
1252 *
1253 * DESCRIPTION: get exif longitude
1254 *
1255 * PARAMETERS :
1256 *   @longitude : ptr to rational struct to store longitude info
1257 *   @lonRef    : charater to indicate longitude reference
1258 *
1259 * RETURN     : int32_t type of status
1260 *              NO_ERROR  -- success
1261 *              none-zero failure code
1262 *==========================================================================*/
1263int32_t getExifLongitude(rat_t *longitude,
1264                                            char *lonRef, double value)
1265{
1266    char str[30];
1267    snprintf(str, sizeof(str), "%f", value);
1268    if(str != NULL) {
1269        parseGPSCoordinate(str, longitude);
1270
1271        //set Longitude Ref
1272        float longitudeValue = strtof(str, 0);
1273        if(longitudeValue < 0.0f) {
1274            lonRef[0] = 'W';
1275        } else {
1276            lonRef[0] = 'E';
1277        }
1278        lonRef[1] = '\0';
1279        return NO_ERROR;
1280    }else{
1281        return BAD_VALUE;
1282    }
1283}
1284
1285/*===========================================================================
1286 * FUNCTION   : getExifAltitude
1287 *
1288 * DESCRIPTION: get exif altitude
1289 *
1290 * PARAMETERS :
1291 *   @altitude : ptr to rational struct to store altitude info
1292 *   @altRef   : charater to indicate altitude reference
1293 *
1294 * RETURN     : int32_t type of status
1295 *              NO_ERROR  -- success
1296 *              none-zero failure code
1297 *==========================================================================*/
1298int32_t getExifAltitude(rat_t *altitude,
1299                                           char *altRef, double value)
1300{
1301    char str[30];
1302    snprintf(str, sizeof(str), "%f", value);
1303    if(str != NULL) {
1304        double value = atof(str);
1305        *altRef = 0;
1306        if(value < 0){
1307            *altRef = 1;
1308            value = -value;
1309        }
1310        return getRational(altitude, value*1000, 1000);
1311    }else{
1312        return BAD_VALUE;
1313    }
1314}
1315
1316/*===========================================================================
1317 * FUNCTION   : getExifGpsDateTimeStamp
1318 *
1319 * DESCRIPTION: get exif GPS date time stamp
1320 *
1321 * PARAMETERS :
1322 *   @gpsDateStamp : GPS date time stamp string
1323 *   @bufLen       : length of the string
1324 *   @gpsTimeStamp : ptr to rational struct to store time stamp info
1325 *
1326 * RETURN     : int32_t type of status
1327 *              NO_ERROR  -- success
1328 *              none-zero failure code
1329 *==========================================================================*/
1330int32_t getExifGpsDateTimeStamp(char *gpsDateStamp,
1331                                                   uint32_t bufLen,
1332                                                   rat_t *gpsTimeStamp, int64_t value)
1333{
1334    char str[30];
1335    snprintf(str, sizeof(str), "%d", value);
1336    if(str != NULL) {
1337        time_t unixTime = (time_t)atol(str);
1338        struct tm *UTCTimestamp = gmtime(&unixTime);
1339
1340        strftime(gpsDateStamp, bufLen, "%Y:%m:%d", UTCTimestamp);
1341
1342        getRational(&gpsTimeStamp[0], UTCTimestamp->tm_hour, 1);
1343        getRational(&gpsTimeStamp[1], UTCTimestamp->tm_min, 1);
1344        getRational(&gpsTimeStamp[2], UTCTimestamp->tm_sec, 1);
1345
1346        return NO_ERROR;
1347    } else {
1348        return BAD_VALUE;
1349    }
1350}
1351/*===========================================================================
1352 * FUNCTION   : getExifData
1353 *
1354 * DESCRIPTION: get exif data to be passed into jpeg encoding
1355 *
1356 * PARAMETERS : none
1357 *
1358 * RETURN     : exif data from user setting and GPS
1359 *==========================================================================*/
1360QCamera3Exif *QCamera3PicChannel::getExifData()
1361{
1362    QCamera3Exif *exif = new QCamera3Exif();
1363    if (exif == NULL) {
1364        ALOGE("%s: No memory for QCamera3Exif", __func__);
1365        return NULL;
1366    }
1367
1368    int32_t rc = NO_ERROR;
1369    uint32_t count = 0;
1370
1371    // add exif entries
1372    char dateTime[20];
1373    memset(dateTime, 0, sizeof(dateTime));
1374    count = 20;
1375    rc = getExifDateTime(dateTime, count);
1376    if(rc == NO_ERROR) {
1377        exif->addEntry(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL,
1378                       EXIF_ASCII,
1379                       count,
1380                       (void *)dateTime);
1381    } else {
1382        ALOGE("%s: getExifDateTime failed", __func__);
1383    }
1384
1385    rat_t focalLength;
1386    rc = getExifFocalLength(&focalLength, mJpegSettings->lens_focal_length);
1387    if (rc == NO_ERROR) {
1388        exif->addEntry(EXIFTAGID_FOCAL_LENGTH,
1389                       EXIF_RATIONAL,
1390                       1,
1391                       (void *)&(focalLength));
1392    } else {
1393        ALOGE("%s: getExifFocalLength failed", __func__);
1394    }
1395
1396    //TBD_Later
1397    /*uint16_t isoSpeed = mParameters.getExifIsoSpeed();
1398    exif->addEntry(EXIFTAGID_ISO_SPEED_RATING,
1399                   EXIF_SHORT,
1400                   1,
1401                   (void *)&(isoSpeed));
1402    */
1403    char gpsProcessingMethod[EXIF_ASCII_PREFIX_SIZE + GPS_PROCESSING_METHOD_SIZE];
1404    count = 0;
1405    rc = getExifGpsProcessingMethod(gpsProcessingMethod, count, mJpegSettings->gps_processing_method);
1406    if(rc == NO_ERROR) {
1407        exif->addEntry(EXIFTAGID_GPS_PROCESSINGMETHOD,
1408                       EXIF_ASCII,
1409                       count,
1410                       (void *)gpsProcessingMethod);
1411    } else {
1412        ALOGE("%s: getExifGpsProcessingMethod failed", __func__);
1413    }
1414
1415    rat_t latitude[3];
1416    char latRef[2];
1417    rc = getExifLatitude(latitude, latRef, mJpegSettings->gps_coordinates[0]);
1418    if(rc == NO_ERROR) {
1419        exif->addEntry(EXIFTAGID_GPS_LATITUDE,
1420                       EXIF_RATIONAL,
1421                       3,
1422                       (void *)latitude);
1423        exif->addEntry(EXIFTAGID_GPS_LATITUDE_REF,
1424                       EXIF_ASCII,
1425                       2,
1426                       (void *)latRef);
1427    } else {
1428        ALOGE("%s: getExifLatitude failed", __func__);
1429    }
1430
1431    rat_t longitude[3];
1432    char lonRef[2];
1433    rc = getExifLongitude(longitude, lonRef, mJpegSettings->gps_coordinates[1]);
1434    if(rc == NO_ERROR) {
1435        exif->addEntry(EXIFTAGID_GPS_LONGITUDE,
1436                       EXIF_RATIONAL,
1437                       3,
1438                       (void *)longitude);
1439
1440        exif->addEntry(EXIFTAGID_GPS_LONGITUDE_REF,
1441                       EXIF_ASCII,
1442                       2,
1443                       (void *)lonRef);
1444    } else {
1445        ALOGE("%s: getExifLongitude failed", __func__);
1446    }
1447
1448    rat_t altitude;
1449    char altRef;
1450    rc = getExifAltitude(&altitude, &altRef, mJpegSettings->gps_coordinates[2]);
1451    if(rc == NO_ERROR) {
1452        exif->addEntry(EXIFTAGID_GPS_ALTITUDE,
1453                       EXIF_RATIONAL,
1454                       1,
1455                       (void *)&(altitude));
1456
1457        exif->addEntry(EXIFTAGID_GPS_ALTITUDE_REF,
1458                       EXIF_BYTE,
1459                       1,
1460                       (void *)&altRef);
1461    } else {
1462        ALOGE("%s: getExifAltitude failed", __func__);
1463    }
1464
1465    char gpsDateStamp[20];
1466    rat_t gpsTimeStamp[3];
1467    rc = getExifGpsDateTimeStamp(gpsDateStamp, 20, gpsTimeStamp, mJpegSettings->gps_timestamp);
1468    if(rc == NO_ERROR) {
1469        exif->addEntry(EXIFTAGID_GPS_DATESTAMP,
1470                       EXIF_ASCII,
1471                       strlen(gpsDateStamp) + 1,
1472                       (void *)gpsDateStamp);
1473
1474        exif->addEntry(EXIFTAGID_GPS_TIMESTAMP,
1475                       EXIF_RATIONAL,
1476                       3,
1477                       (void *)gpsTimeStamp);
1478    } else {
1479        ALOGE("%s: getExifGpsDataTimeStamp failed", __func__);
1480    }
1481
1482    return exif;
1483}
1484
1485int QCamera3PicChannel::kMaxBuffers = 1;
1486}; // namespace qcamera
1487