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