QCamera3Channel.cpp revision b66f295ef24aea24873bcf80cee589835338e2a1
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*/,
668                                                uint32_t frameNumber)
669{
670    if (!m_bIsActive) {
671#ifdef FAKE_FRAME_NUMBERS
672        startingFrameNumber=frameNumber;
673#endif
674        return start();
675    }
676    else
677        return 0;
678}
679
680int32_t QCamera3MetadataChannel::registerBuffers(uint32_t /*num_buffers*/,
681                                        buffer_handle_t ** /*buffers*/)
682{
683    // no registerBuffers are supported for metadata channel
684    return -EINVAL;
685}
686
687void QCamera3MetadataChannel::streamCbRoutine(
688                        mm_camera_super_buf_t *super_frame,
689                        QCamera3Stream *stream)
690{
691    uint32_t requestNumber = 0;
692    if (super_frame == NULL || super_frame->num_bufs != 1) {
693        ALOGE("%s: super_frame is not valid", __func__);
694        return;
695    }
696#ifdef FAKE_FRAME_NUMBERS
697    requestNumber = startingFrameNumber++;
698#endif
699    mChannelCB(super_frame, NULL, requestNumber, mUserData);
700
701    //Return the buffer
702    stream->bufDone(super_frame->bufs[0]->buf_idx);
703}
704
705QCamera3Memory* QCamera3MetadataChannel::getStreamBufs(uint32_t len)
706{
707    int rc;
708    if (len != sizeof(metadata_buffer_t)) {
709        ALOGE("%s: size doesn't match %d vs %d", __func__,
710                len, sizeof(metadata_buffer_t));
711        return NULL;
712    }
713    mMemory = new QCamera3HeapMemory();
714    if (!mMemory) {
715        ALOGE("%s: unable to create metadata memory", __func__);
716        return NULL;
717    }
718    rc = mMemory->allocate(MIN_STREAMING_BUFFER_NUM, len, true);
719    if (rc < 0) {
720        ALOGE("%s: unable to allocate metadata memory", __func__);
721        delete mMemory;
722        mMemory = NULL;
723        return NULL;
724    }
725    memset(mMemory->getPtr(0), 0, sizeof(metadata_buffer_t));
726    return mMemory;
727}
728
729void QCamera3MetadataChannel::putStreamBufs()
730{
731    mMemory->deallocate();
732    delete mMemory;
733    mMemory = NULL;
734}
735
736/*===========================================================================
737 * FUNCTION   : jpegEvtHandle
738 *
739 * DESCRIPTION: Function registerd to mm-jpeg-interface to handle jpeg events.
740                Construct result payload and call mChannelCb to deliver buffer
741                to framework.
742 *
743 * PARAMETERS :
744 *   @status    : status of jpeg job
745 *   @client_hdl: jpeg client handle
746 *   @jobId     : jpeg job Id
747 *   @p_ouput   : ptr to jpeg output result struct
748 *   @userdata  : user data ptr
749 *
750 * RETURN     : none
751 *==========================================================================*/
752void QCamera3PicChannel::jpegEvtHandle(jpeg_job_status_t status,
753                                              uint32_t /*client_hdl*/,
754                                              uint32_t jobId,
755                                              mm_jpeg_output_t *p_output,
756                                              void *userdata)
757{
758    buffer_handle_t *resultBuffer;
759    int32_t resultFrameNumber;
760    int resultStatus = CAMERA3_BUFFER_STATUS_OK;
761    camera3_stream_buffer_t result;
762    camera3_jpeg_blob_t jpegHeader;
763    char* jpeg_eof = 0;
764    QCamera3PicChannel *obj = (QCamera3PicChannel *)userdata;
765    if (obj) {
766        //Construct payload for process_capture_result. Call mChannelCb
767
768        qcamera_jpeg_data_t *job = obj->m_postprocessor.findJpegJobByJobId(jobId);
769
770        if ((job == NULL) || (status == JPEG_JOB_STATUS_ERROR)) {
771            ALOGE("%s: Error in jobId: (%d) with status: %d", __func__, jobId, status);
772            resultStatus = CAMERA3_BUFFER_STATUS_ERROR;
773        }
774
775        //Construct jpeg transient header of type camera3_jpeg_blob_t
776        //Append at the end of jpeg image of buf_filled_len size
777
778        jpegHeader.jpeg_blob_id = CAMERA3_JPEG_BLOB_ID;
779        jpegHeader.jpeg_size = p_output->buf_filled_len;
780
781
782        char* jpeg_buf = (char *)p_output->buf_vaddr;
783
784        jpeg_eof = &jpeg_buf[p_output->buf_filled_len];
785        memcpy(jpeg_eof, &jpegHeader, sizeof(jpegHeader));
786
787        ////Use below data to issue framework callback
788        resultBuffer = obj->mCamera3Buffers[obj->mCurrentBufIndex];
789        resultFrameNumber = obj->mMemory->getFrameNumber(obj->mCurrentBufIndex);
790
791        result.stream = obj->mCamera3Stream;
792        result.buffer = resultBuffer;
793        result.status = resultStatus;
794        result.acquire_fence = -1;
795        result.release_fence = -1;
796
797        ALOGE("%s: Issue Callback", __func__);
798        obj->mChannelCB(NULL, &result, resultFrameNumber, obj->mUserData);
799
800        // release internal data for jpeg job
801        if (job != NULL) {
802            obj->m_postprocessor.releaseJpegJobData(job);
803            free(job);
804        }
805        return;
806        // }
807    } else {
808        ALOGE("%s: Null userdata in jpeg callback", __func__);
809    }
810}
811
812QCamera3PicChannel::QCamera3PicChannel(uint32_t cam_handle,
813                    mm_camera_ops_t *cam_ops,
814                    channel_cb_routine cb_routine,
815                    cam_padding_info_t *paddingInfo,
816                    void *userData,
817                    camera3_stream_t *stream) :
818                        QCamera3Channel(cam_handle, cam_ops, cb_routine,
819                        paddingInfo, userData),
820                        mCamera3Stream(stream),
821                        m_postprocessor(this),
822                        mCamera3Buffers(NULL),
823                        mMemory(NULL),
824                        mYuvMemory(NULL)
825{
826    int32_t rc = m_postprocessor.init(jpegEvtHandle, this);
827    if (rc != 0) {
828        ALOGE("Init Postprocessor failed");
829    }
830}
831
832QCamera3PicChannel::~QCamera3PicChannel()
833{
834    int32_t rc = m_postprocessor.deinit();
835    if (rc != 0) {
836        ALOGE("De-init Postprocessor failed");
837    }
838    if (mCamera3Buffers) {
839        delete[] mCamera3Buffers;
840    }
841}
842
843int32_t QCamera3PicChannel::initialize()
844{
845    int32_t rc = NO_ERROR;
846    cam_dimension_t streamDim;
847    cam_stream_type_t streamType;
848    cam_format_t streamFormat;
849    mm_camera_channel_attr_t attr;
850
851    memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
852    attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_BURST;
853    attr.look_back = 1;
854    attr.post_frame_skip = 1;
855    attr.water_mark = 1;
856    attr.max_unmatched_frames = 1;
857
858    rc = init(&attr, QCamera3PicChannel::dataNotifyCB);
859    if (rc < 0) {
860        ALOGE("%s: init failed", __func__);
861        return rc;
862    }
863
864    streamType = CAM_STREAM_TYPE_SNAPSHOT;
865    streamFormat = CAM_FORMAT_YUV_420_NV21;
866    streamDim.width = mCamera3Stream->width;
867    streamDim.height = mCamera3Stream->height;
868    int num_buffers = QCamera3PicChannel::kMaxBuffers + 1;
869
870    rc = QCamera3Channel::addStream(streamType, streamFormat, streamDim,
871            num_buffers);
872
873
874    return rc;
875}
876
877int32_t QCamera3PicChannel::request(buffer_handle_t *buffer, uint32_t frameNumber, jpeg_settings_t* jpegSettings)
878{
879    //FIX ME: Return buffer back in case of failures below.
880
881    int32_t rc = NO_ERROR;
882    int index;
883    mJpegSettings = jpegSettings;
884
885    if(!m_bIsActive) {
886        ALOGD("%s: First request on this channel starting stream",__func__);
887        //Stream on for main image. YUV buffer is queued to the kernel at the end of this call.
888        rc = start();
889    } else {
890        ALOGE("%s: Request on an existing stream",__func__);
891    }
892
893    if(rc != NO_ERROR) {
894        ALOGE("%s: Failed to start the stream on the request",__func__);
895        return rc;
896    }
897
898
899    if(!mMemory) {
900        ALOGE("%s: error, Gralloc Memory object not yet created for this stream",__func__);
901        return NO_MEMORY;
902    }
903
904    index = mMemory->getMatchBufIndex((void*)buffer);
905    if(index < 0) {
906        ALOGE("%s: Could not find object among registered buffers",__func__);
907        return DEAD_OBJECT;
908    }
909    rc = mMemory->markFrameNumber(index, frameNumber);
910
911    //Start the postprocessor for jpeg encoding. Pass mMemory as destination buffer
912    mCurrentBufIndex = index;
913    m_postprocessor.start(mMemory, index);
914    if(m_camOps->request_super_buf(m_camHandle,m_handle,1) < 0) {
915        ALOGE("%s: Request for super buffer failed",__func__);
916    }
917
918    return rc;
919}
920
921/*===========================================================================
922 * FUNCTION   : dataNotifyCB
923 *
924 * DESCRIPTION: Channel Level callback used for super buffer data notify.
925 *              This function is registered with mm-camera-interface to handle
926 *              data notify
927 *
928 * PARAMETERS :
929 *   @recvd_frame   : stream frame received
930 *   userdata       : user data ptr
931 *
932 * RETURN     : none
933 *==========================================================================*/
934void QCamera3PicChannel::dataNotifyCB(mm_camera_super_buf_t *recvd_frame,
935                                 void *userdata)
936{
937    ALOGE("%s: E\n", __func__);
938    QCamera3PicChannel *channel = (QCamera3PicChannel *)userdata;
939
940    if (channel == NULL) {
941        ALOGE("%s: invalid channel pointer", __func__);
942        return;
943    }
944
945    if(channel->m_numStreams != 1) {
946        ALOGE("%s: Error: Bug: This callback assumes one stream per channel",__func__);
947        return;
948    }
949
950
951    if(channel->mStreams[0] == NULL) {
952        ALOGE("%s: Error: Invalid Stream object",__func__);
953        return;
954    }
955
956    channel->QCamera3PicChannel::streamCbRoutine(recvd_frame, channel->mStreams[0]);
957    ALOGE("%s: X\n", __func__);
958
959    return;
960}
961
962
963int32_t QCamera3PicChannel::registerBuffers(uint32_t num_buffers,
964                        buffer_handle_t **buffers)
965{
966    int rc = 0;
967    struct private_handle_t *priv_handle = (struct private_handle_t *)(*buffers[0]);
968    cam_stream_type_t streamType;
969    cam_format_t streamFormat;
970    cam_dimension_t streamDim;
971
972    ALOGE("%s: E",__func__);
973    if (mCamera3Stream->format == HAL_PIXEL_FORMAT_BLOB) {
974        streamType = CAM_STREAM_TYPE_SNAPSHOT;
975        streamFormat = CAM_FORMAT_YUV_420_NV21;
976    } else {
977        //TODO: Fail for other types of streams for now
978        ALOGE("%s: format is not BLOB", __func__);
979        return -EINVAL;
980    }
981    /* Bookkeep buffer set because they go out of scope after register call */
982    mNumBufs = num_buffers;
983    mCamera3Buffers = new buffer_handle_t*[num_buffers];
984    if (mCamera3Buffers == NULL) {
985        ALOGE("%s: Failed to allocate buffer_handle_t*", __func__);
986        return -ENOMEM;
987    }
988    for (size_t i = 0; i < num_buffers; i++)
989        mCamera3Buffers[i] = buffers[i];
990
991    return rc;
992}
993
994void QCamera3PicChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
995                            QCamera3Stream *stream)
996{
997    //TODO
998    //Used only for getting YUV. Jpeg callback will be sent back from channel directly to HWI.
999    //Refer to func jpegEvtHandle
1000
1001    //Got the yuv callback. Calling yuv callback handler in PostProc
1002    uint8_t frameIndex;
1003    mm_camera_super_buf_t* frame = NULL;
1004
1005    if(!super_frame) {
1006         ALOGE("%s: Invalid Super buffer",__func__);
1007         return;
1008    }
1009
1010    if(super_frame->num_bufs != 1) {
1011         ALOGE("%s: Multiple streams are not supported",__func__);
1012         return;
1013    }
1014    if(super_frame->bufs[0] == NULL ) {
1015         ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
1016                  __func__);
1017         return;
1018    }
1019
1020    frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
1021    if(frameIndex >= mNumBufs) {
1022         ALOGE("%s: Error, Invalid index for buffer",__func__);
1023         if(stream) {
1024             stream->bufDone(frameIndex);
1025         }
1026         return;
1027    }
1028
1029    frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
1030    if (frame == NULL) {
1031       ALOGE("%s: Error allocating memory to save received_frame structure.", __func__);
1032       if(stream) {
1033           stream->bufDone(frameIndex);
1034       }
1035       return;
1036    }
1037    *frame = *super_frame;
1038
1039    m_postprocessor.processData(frame);
1040    return;
1041}
1042
1043QCamera3Memory* QCamera3PicChannel::getStreamBufs(uint32_t len)
1044{
1045    int rc = 0;
1046
1047    if (mNumBufs == 0 || mCamera3Buffers == NULL) {
1048        ALOGE("%s: buffers not registered yet", __func__);
1049        return NULL;
1050    }
1051
1052    mMemory = new QCamera3GrallocMemory();
1053    if (mMemory == NULL) {
1054        return NULL;
1055    }
1056
1057    //Registering Jpeg output buffer
1058    if (mMemory->registerBuffers(mNumBufs, mCamera3Buffers) < 0) {
1059        delete mMemory;
1060        mMemory = NULL;
1061        return NULL;
1062    }
1063
1064    mYuvMemory = new QCamera3HeapMemory();
1065    if (!mYuvMemory) {
1066        ALOGE("%s: unable to create metadata memory", __func__);
1067        return NULL;
1068    }
1069
1070    //Queue YUV buffers in the beginning mQueueAll = true
1071    rc = mYuvMemory->allocate(QCamera3PicChannel::kMaxBuffers + 1, len, true);
1072    if (rc < 0) {
1073        ALOGE("%s: unable to allocate metadata memory", __func__);
1074        delete mYuvMemory;
1075        mYuvMemory = NULL;
1076        return NULL;
1077    }
1078    return mYuvMemory;
1079}
1080
1081void QCamera3PicChannel::putStreamBufs()
1082{
1083    mMemory->unregisterBuffers();
1084    delete mMemory;
1085    mMemory = NULL;
1086
1087    mYuvMemory->deallocate();
1088    delete mYuvMemory;
1089    mYuvMemory = NULL;
1090}
1091
1092/*===========================================================================
1093 * FUNCTION   : needRotationReprocess
1094 *
1095 * DESCRIPTION: if online rotation needs to be done by cpp
1096 *
1097 * PARAMETERS : none
1098 *
1099 * RETURN     : true: needed
1100 *              false: no need
1101 *==========================================================================*/
1102bool QCamera3PicChannel::needOnlineRotation()
1103{
1104    //TBD_Later
1105    //if ((gCamCapability[mCameraId]->qcom_supported_feature_mask & CAM_QCOM_FEATURE_ROTATION) > 0 &&
1106       if (mJpegSettings->jpeg_orientation > 0) {
1107        // current rotation is not zero, and pp has the capability to process rotation
1108        ALOGD("%s: need do online rotation", __func__);
1109        return true;
1110    }
1111    return false;
1112}
1113
1114/*===========================================================================
1115 * FUNCTION   : getThumbnailSize
1116 *
1117 * DESCRIPTION: get user set thumbnail size
1118 *
1119 * PARAMETERS :
1120 *   @dim     : output of thumbnail dimension
1121 *
1122 * RETURN     : none
1123 *==========================================================================*/
1124void QCamera3PicChannel::getThumbnailSize(cam_dimension_t &dim)
1125{
1126    dim = mJpegSettings->thumbnail_size;
1127}
1128
1129/*===========================================================================
1130 * FUNCTION   : getJpegQuality
1131 *
1132 * DESCRIPTION: get user set jpeg quality
1133 *
1134 * PARAMETERS : none
1135 *
1136 * RETURN     : jpeg quality setting
1137 *==========================================================================*/
1138int QCamera3PicChannel::getJpegQuality()
1139{
1140    int quality = mJpegSettings->jpeg_quality;
1141    if (quality < 0) {
1142        quality = 85;  //set to default quality value
1143    }
1144    return quality;
1145}
1146
1147/*===========================================================================
1148 * FUNCTION   : getJpegRotation
1149 *
1150 * DESCRIPTION: get rotation information to be passed into jpeg encoding
1151 *
1152 * PARAMETERS : none
1153 *
1154 * RETURN     : rotation information
1155 *==========================================================================*/
1156int QCamera3PicChannel::getJpegRotation() {
1157    int rotation = mJpegSettings->jpeg_orientation;
1158    if (rotation < 0) {
1159        rotation = 0;
1160    }
1161    return rotation;
1162}
1163
1164/*===========================================================================
1165 * FUNCTION   : getRational
1166 *
1167 * DESCRIPTION: compose rational struct
1168 *
1169 * PARAMETERS :
1170 *   @rat     : ptr to struct to store rational info
1171 *   @num     :num of the rational
1172 *   @denom   : denom of the rational
1173 *
1174 * RETURN     : int32_t type of status
1175 *              NO_ERROR  -- success
1176 *              none-zero failure code
1177 *==========================================================================*/
1178int32_t getRational(rat_t *rat, int num, int denom)
1179{
1180    if (NULL == rat) {
1181        ALOGE("%s: NULL rat input", __func__);
1182        return BAD_VALUE;
1183    }
1184    rat->num = num;
1185    rat->denom = denom;
1186    return NO_ERROR;
1187}
1188
1189/*===========================================================================
1190 * FUNCTION   : parseGPSCoordinate
1191 *
1192 * DESCRIPTION: parse GPS coordinate string
1193 *
1194 * PARAMETERS :
1195 *   @coord_str : [input] coordinate string
1196 *   @coord     : [output]  ptr to struct to store coordinate
1197 *
1198 * RETURN     : int32_t type of status
1199 *              NO_ERROR  -- success
1200 *              none-zero failure code
1201 *==========================================================================*/
1202int parseGPSCoordinate(const char *coord_str, rat_t* coord)
1203{
1204    if(coord == NULL) {
1205        ALOGE("%s: error, invalid argument coord == NULL", __func__);
1206        return BAD_VALUE;
1207    }
1208    float degF = atof(coord_str);
1209    if (degF < 0) {
1210        degF = -degF;
1211    }
1212    float minF = (degF - (int) degF) * 60;
1213    float secF = (minF - (int) minF) * 60;
1214
1215    getRational(&coord[0], (int)degF, 1);
1216    getRational(&coord[1], (int)minF, 1);
1217    getRational(&coord[2], (int)(secF * 10000), 10000);
1218    return NO_ERROR;
1219}
1220
1221/*===========================================================================
1222 * FUNCTION   : getExifDateTime
1223 *
1224 * DESCRIPTION: query exif date time
1225 *
1226 * PARAMETERS :
1227 *   @dateTime : string to store exif date time
1228 *   @count    : lenght of the dateTime string
1229 *
1230 * RETURN     : int32_t type of status
1231 *              NO_ERROR  -- success
1232 *              none-zero failure code
1233 *==========================================================================*/
1234int32_t getExifDateTime(char *dateTime, uint32_t &count)
1235{
1236    //get time and date from system
1237    time_t rawtime;
1238    struct tm * timeinfo;
1239    time(&rawtime);
1240    timeinfo = localtime (&rawtime);
1241    //Write datetime according to EXIF Spec
1242    //"YYYY:MM:DD HH:MM:SS" (20 chars including \0)
1243    snprintf(dateTime, 20, "%04d:%02d:%02d %02d:%02d:%02d",
1244             timeinfo->tm_year + 1900, timeinfo->tm_mon + 1,
1245             timeinfo->tm_mday, timeinfo->tm_hour,
1246             timeinfo->tm_min, timeinfo->tm_sec);
1247    count = 20;
1248
1249    return NO_ERROR;
1250}
1251
1252/*===========================================================================
1253 * FUNCTION   : getExifFocalLength
1254 *
1255 * DESCRIPTION: get exif focal lenght
1256 *
1257 * PARAMETERS :
1258 *   @focalLength : ptr to rational strcut to store focal lenght
1259 *
1260 * RETURN     : int32_t type of status
1261 *              NO_ERROR  -- success
1262 *              none-zero failure code
1263 *==========================================================================*/
1264int32_t getExifFocalLength(rat_t *focalLength, float value)
1265{
1266    int focalLengthValue =
1267        (int)(value * FOCAL_LENGTH_DECIMAL_PRECISION);
1268    return getRational(focalLength, focalLengthValue, FOCAL_LENGTH_DECIMAL_PRECISION);
1269}
1270
1271/*===========================================================================
1272 * FUNCTION   : getExifGpsProcessingMethod
1273 *
1274 * DESCRIPTION: get GPS processing method
1275 *
1276 * PARAMETERS :
1277 *   @gpsProcessingMethod : string to store GPS process method
1278 *   @count               : lenght of the string
1279 *
1280 * RETURN     : int32_t type of status
1281 *              NO_ERROR  -- success
1282 *              none-zero failure code
1283 *==========================================================================*/
1284int32_t getExifGpsProcessingMethod(char *gpsProcessingMethod,
1285                                                      uint32_t &count, int value)
1286{
1287    char str[30];
1288    snprintf(str, sizeof(str), "%d", value);
1289    if(str != NULL) {
1290        memcpy(gpsProcessingMethod, ExifAsciiPrefix, EXIF_ASCII_PREFIX_SIZE);
1291        count = EXIF_ASCII_PREFIX_SIZE;
1292        strncpy(gpsProcessingMethod + EXIF_ASCII_PREFIX_SIZE, str, strlen(str));
1293        count += strlen(str);
1294        gpsProcessingMethod[count++] = '\0'; // increase 1 for the last NULL char
1295        return NO_ERROR;
1296    } else {
1297        return BAD_VALUE;
1298    }
1299}
1300
1301/*===========================================================================
1302 * FUNCTION   : getExifLatitude
1303 *
1304 * DESCRIPTION: get exif latitude
1305 *
1306 * PARAMETERS :
1307 *   @latitude : ptr to rational struct to store latitude info
1308 *   @ladRef   : charater to indicate latitude reference
1309 *
1310 * RETURN     : int32_t type of status
1311 *              NO_ERROR  -- success
1312 *              none-zero failure code
1313 *==========================================================================*/
1314int32_t getExifLatitude(rat_t *latitude,
1315                                           char *latRef, double value)
1316{
1317    char str[30];
1318    snprintf(str, sizeof(str), "%f", value);
1319    if(str != NULL) {
1320        parseGPSCoordinate(str, latitude);
1321
1322        //set Latitude Ref
1323        float latitudeValue = strtof(str, 0);
1324        if(latitudeValue < 0.0f) {
1325            latRef[0] = 'S';
1326        } else {
1327            latRef[0] = 'N';
1328        }
1329        latRef[1] = '\0';
1330        return NO_ERROR;
1331    }else{
1332        return BAD_VALUE;
1333    }
1334}
1335
1336/*===========================================================================
1337 * FUNCTION   : getExifLongitude
1338 *
1339 * DESCRIPTION: get exif longitude
1340 *
1341 * PARAMETERS :
1342 *   @longitude : ptr to rational struct to store longitude info
1343 *   @lonRef    : charater to indicate longitude reference
1344 *
1345 * RETURN     : int32_t type of status
1346 *              NO_ERROR  -- success
1347 *              none-zero failure code
1348 *==========================================================================*/
1349int32_t getExifLongitude(rat_t *longitude,
1350                                            char *lonRef, double value)
1351{
1352    char str[30];
1353    snprintf(str, sizeof(str), "%f", value);
1354    if(str != NULL) {
1355        parseGPSCoordinate(str, longitude);
1356
1357        //set Longitude Ref
1358        float longitudeValue = strtof(str, 0);
1359        if(longitudeValue < 0.0f) {
1360            lonRef[0] = 'W';
1361        } else {
1362            lonRef[0] = 'E';
1363        }
1364        lonRef[1] = '\0';
1365        return NO_ERROR;
1366    }else{
1367        return BAD_VALUE;
1368    }
1369}
1370
1371/*===========================================================================
1372 * FUNCTION   : getExifAltitude
1373 *
1374 * DESCRIPTION: get exif altitude
1375 *
1376 * PARAMETERS :
1377 *   @altitude : ptr to rational struct to store altitude info
1378 *   @altRef   : charater to indicate altitude reference
1379 *
1380 * RETURN     : int32_t type of status
1381 *              NO_ERROR  -- success
1382 *              none-zero failure code
1383 *==========================================================================*/
1384int32_t getExifAltitude(rat_t *altitude,
1385                                           char *altRef, double value)
1386{
1387    char str[30];
1388    snprintf(str, sizeof(str), "%f", value);
1389    if(str != NULL) {
1390        double value = atof(str);
1391        *altRef = 0;
1392        if(value < 0){
1393            *altRef = 1;
1394            value = -value;
1395        }
1396        return getRational(altitude, value*1000, 1000);
1397    }else{
1398        return BAD_VALUE;
1399    }
1400}
1401
1402/*===========================================================================
1403 * FUNCTION   : getExifGpsDateTimeStamp
1404 *
1405 * DESCRIPTION: get exif GPS date time stamp
1406 *
1407 * PARAMETERS :
1408 *   @gpsDateStamp : GPS date time stamp string
1409 *   @bufLen       : length of the string
1410 *   @gpsTimeStamp : ptr to rational struct to store time stamp info
1411 *
1412 * RETURN     : int32_t type of status
1413 *              NO_ERROR  -- success
1414 *              none-zero failure code
1415 *==========================================================================*/
1416int32_t getExifGpsDateTimeStamp(char *gpsDateStamp,
1417                                                   uint32_t bufLen,
1418                                                   rat_t *gpsTimeStamp, int64_t value)
1419{
1420    char str[30];
1421    snprintf(str, sizeof(str), "%d", value);
1422    if(str != NULL) {
1423        time_t unixTime = (time_t)atol(str);
1424        struct tm *UTCTimestamp = gmtime(&unixTime);
1425
1426        strftime(gpsDateStamp, bufLen, "%Y:%m:%d", UTCTimestamp);
1427
1428        getRational(&gpsTimeStamp[0], UTCTimestamp->tm_hour, 1);
1429        getRational(&gpsTimeStamp[1], UTCTimestamp->tm_min, 1);
1430        getRational(&gpsTimeStamp[2], UTCTimestamp->tm_sec, 1);
1431
1432        return NO_ERROR;
1433    } else {
1434        return BAD_VALUE;
1435    }
1436}
1437/*===========================================================================
1438 * FUNCTION   : getExifData
1439 *
1440 * DESCRIPTION: get exif data to be passed into jpeg encoding
1441 *
1442 * PARAMETERS : none
1443 *
1444 * RETURN     : exif data from user setting and GPS
1445 *==========================================================================*/
1446QCamera3Exif *QCamera3PicChannel::getExifData()
1447{
1448    QCamera3Exif *exif = new QCamera3Exif();
1449    if (exif == NULL) {
1450        ALOGE("%s: No memory for QCamera3Exif", __func__);
1451        return NULL;
1452    }
1453
1454    int32_t rc = NO_ERROR;
1455    uint32_t count = 0;
1456
1457    // add exif entries
1458    char dateTime[20];
1459    memset(dateTime, 0, sizeof(dateTime));
1460    count = 20;
1461    rc = getExifDateTime(dateTime, count);
1462    if(rc == NO_ERROR) {
1463        exif->addEntry(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL,
1464                       EXIF_ASCII,
1465                       count,
1466                       (void *)dateTime);
1467    } else {
1468        ALOGE("%s: getExifDateTime failed", __func__);
1469    }
1470
1471    rat_t focalLength;
1472    rc = getExifFocalLength(&focalLength, mJpegSettings->lens_focal_length);
1473    if (rc == NO_ERROR) {
1474        exif->addEntry(EXIFTAGID_FOCAL_LENGTH,
1475                       EXIF_RATIONAL,
1476                       1,
1477                       (void *)&(focalLength));
1478    } else {
1479        ALOGE("%s: getExifFocalLength failed", __func__);
1480    }
1481
1482    //TBD_Later
1483    /*uint16_t isoSpeed = mParameters.getExifIsoSpeed();
1484    exif->addEntry(EXIFTAGID_ISO_SPEED_RATING,
1485                   EXIF_SHORT,
1486                   1,
1487                   (void *)&(isoSpeed));
1488    */
1489    char gpsProcessingMethod[EXIF_ASCII_PREFIX_SIZE + GPS_PROCESSING_METHOD_SIZE];
1490    count = 0;
1491    rc = getExifGpsProcessingMethod(gpsProcessingMethod, count, mJpegSettings->gps_processing_method);
1492    if(rc == NO_ERROR) {
1493        exif->addEntry(EXIFTAGID_GPS_PROCESSINGMETHOD,
1494                       EXIF_ASCII,
1495                       count,
1496                       (void *)gpsProcessingMethod);
1497    } else {
1498        ALOGE("%s: getExifGpsProcessingMethod failed", __func__);
1499    }
1500
1501    rat_t latitude[3];
1502    char latRef[2];
1503    rc = getExifLatitude(latitude, latRef, mJpegSettings->gps_coordinates[0]);
1504    if(rc == NO_ERROR) {
1505        exif->addEntry(EXIFTAGID_GPS_LATITUDE,
1506                       EXIF_RATIONAL,
1507                       3,
1508                       (void *)latitude);
1509        exif->addEntry(EXIFTAGID_GPS_LATITUDE_REF,
1510                       EXIF_ASCII,
1511                       2,
1512                       (void *)latRef);
1513    } else {
1514        ALOGE("%s: getExifLatitude failed", __func__);
1515    }
1516
1517    rat_t longitude[3];
1518    char lonRef[2];
1519    rc = getExifLongitude(longitude, lonRef, mJpegSettings->gps_coordinates[1]);
1520    if(rc == NO_ERROR) {
1521        exif->addEntry(EXIFTAGID_GPS_LONGITUDE,
1522                       EXIF_RATIONAL,
1523                       3,
1524                       (void *)longitude);
1525
1526        exif->addEntry(EXIFTAGID_GPS_LONGITUDE_REF,
1527                       EXIF_ASCII,
1528                       2,
1529                       (void *)lonRef);
1530    } else {
1531        ALOGE("%s: getExifLongitude failed", __func__);
1532    }
1533
1534    rat_t altitude;
1535    char altRef;
1536    rc = getExifAltitude(&altitude, &altRef, mJpegSettings->gps_coordinates[2]);
1537    if(rc == NO_ERROR) {
1538        exif->addEntry(EXIFTAGID_GPS_ALTITUDE,
1539                       EXIF_RATIONAL,
1540                       1,
1541                       (void *)&(altitude));
1542
1543        exif->addEntry(EXIFTAGID_GPS_ALTITUDE_REF,
1544                       EXIF_BYTE,
1545                       1,
1546                       (void *)&altRef);
1547    } else {
1548        ALOGE("%s: getExifAltitude failed", __func__);
1549    }
1550
1551    char gpsDateStamp[20];
1552    rat_t gpsTimeStamp[3];
1553    rc = getExifGpsDateTimeStamp(gpsDateStamp, 20, gpsTimeStamp, mJpegSettings->gps_timestamp);
1554    if(rc == NO_ERROR) {
1555        exif->addEntry(EXIFTAGID_GPS_DATESTAMP,
1556                       EXIF_ASCII,
1557                       strlen(gpsDateStamp) + 1,
1558                       (void *)gpsDateStamp);
1559
1560        exif->addEntry(EXIFTAGID_GPS_TIMESTAMP,
1561                       EXIF_RATIONAL,
1562                       3,
1563                       (void *)gpsTimeStamp);
1564    } else {
1565        ALOGE("%s: getExifGpsDataTimeStamp failed", __func__);
1566    }
1567
1568    return exif;
1569}
1570
1571int QCamera3PicChannel::kMaxBuffers = 1;
1572}; // namespace qcamera
1573