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