QCamera3Channel.cpp revision 65585b2d14faf1e7fa78560f8c9cd27d76c408ab
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    rc = QCamera3PicChannel::initialize();
974    if (rc < 0) {
975        ALOGE("%s: init failed", __func__);
976        return rc;
977    }
978
979    if (mCamera3Stream->format == HAL_PIXEL_FORMAT_BLOB) {
980        streamType = CAM_STREAM_TYPE_SNAPSHOT;
981        streamFormat = CAM_FORMAT_YUV_420_NV21;
982    } else {
983        //TODO: Fail for other types of streams for now
984        ALOGE("%s: format is not BLOB", __func__);
985        return -EINVAL;
986    }
987    /* Bookkeep buffer set because they go out of scope after register call */
988    mNumBufs = num_buffers;
989    mCamera3Buffers = new buffer_handle_t*[num_buffers];
990    if (mCamera3Buffers == NULL) {
991        ALOGE("%s: Failed to allocate buffer_handle_t*", __func__);
992        return -ENOMEM;
993    }
994    for (size_t i = 0; i < num_buffers; i++)
995        mCamera3Buffers[i] = buffers[i];
996
997    return rc;
998}
999
1000void QCamera3PicChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
1001                            QCamera3Stream *stream)
1002{
1003    //TODO
1004    //Used only for getting YUV. Jpeg callback will be sent back from channel directly to HWI.
1005    //Refer to func jpegEvtHandle
1006
1007    //Got the yuv callback. Calling yuv callback handler in PostProc
1008    uint8_t frameIndex;
1009    mm_camera_super_buf_t* frame = NULL;
1010
1011    if(!super_frame) {
1012         ALOGE("%s: Invalid Super buffer",__func__);
1013         return;
1014    }
1015
1016    if(super_frame->num_bufs != 1) {
1017         ALOGE("%s: Multiple streams are not supported",__func__);
1018         return;
1019    }
1020    if(super_frame->bufs[0] == NULL ) {
1021         ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
1022                  __func__);
1023         return;
1024    }
1025
1026    frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
1027    if(frameIndex >= mNumBufs) {
1028         ALOGE("%s: Error, Invalid index for buffer",__func__);
1029         if(stream) {
1030             stream->bufDone(frameIndex);
1031         }
1032         return;
1033    }
1034
1035    frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
1036    if (frame == NULL) {
1037       ALOGE("%s: Error allocating memory to save received_frame structure.", __func__);
1038       if(stream) {
1039           stream->bufDone(frameIndex);
1040       }
1041       return;
1042    }
1043    *frame = *super_frame;
1044
1045    m_postprocessor.processData(frame);
1046    return;
1047}
1048
1049QCamera3Memory* QCamera3PicChannel::getStreamBufs(uint32_t len)
1050{
1051    int rc = 0;
1052
1053    if (mNumBufs == 0 || mCamera3Buffers == NULL) {
1054        ALOGE("%s: buffers not registered yet", __func__);
1055        return NULL;
1056    }
1057
1058    mMemory = new QCamera3GrallocMemory();
1059    if (mMemory == NULL) {
1060        return NULL;
1061    }
1062
1063    //Registering Jpeg output buffer
1064    if (mMemory->registerBuffers(mNumBufs, mCamera3Buffers) < 0) {
1065        delete mMemory;
1066        mMemory = NULL;
1067        return NULL;
1068    }
1069
1070    mYuvMemory = new QCamera3HeapMemory();
1071    if (!mYuvMemory) {
1072        ALOGE("%s: unable to create metadata memory", __func__);
1073        return NULL;
1074    }
1075
1076    //Queue YUV buffers in the beginning mQueueAll = true
1077    rc = mYuvMemory->allocate(QCamera3PicChannel::kMaxBuffers + 1, len, true);
1078    if (rc < 0) {
1079        ALOGE("%s: unable to allocate metadata memory", __func__);
1080        delete mYuvMemory;
1081        mYuvMemory = NULL;
1082        return NULL;
1083    }
1084    return mYuvMemory;
1085}
1086
1087void QCamera3PicChannel::putStreamBufs()
1088{
1089    mMemory->unregisterBuffers();
1090    delete mMemory;
1091    mMemory = NULL;
1092
1093    mYuvMemory->deallocate();
1094    delete mYuvMemory;
1095    mYuvMemory = NULL;
1096}
1097
1098/*===========================================================================
1099 * FUNCTION   : needRotationReprocess
1100 *
1101 * DESCRIPTION: if online rotation needs to be done by cpp
1102 *
1103 * PARAMETERS : none
1104 *
1105 * RETURN     : true: needed
1106 *              false: no need
1107 *==========================================================================*/
1108bool QCamera3PicChannel::needOnlineRotation()
1109{
1110    //TBD_Later
1111    //if ((gCamCapability[mCameraId]->qcom_supported_feature_mask & CAM_QCOM_FEATURE_ROTATION) > 0 &&
1112       if (mJpegSettings->jpeg_orientation > 0) {
1113        // current rotation is not zero, and pp has the capability to process rotation
1114        ALOGD("%s: need do online rotation", __func__);
1115        return true;
1116    }
1117    return false;
1118}
1119
1120/*===========================================================================
1121 * FUNCTION   : getThumbnailSize
1122 *
1123 * DESCRIPTION: get user set thumbnail size
1124 *
1125 * PARAMETERS :
1126 *   @dim     : output of thumbnail dimension
1127 *
1128 * RETURN     : none
1129 *==========================================================================*/
1130void QCamera3PicChannel::getThumbnailSize(cam_dimension_t &dim)
1131{
1132    dim = mJpegSettings->thumbnail_size;
1133}
1134
1135/*===========================================================================
1136 * FUNCTION   : getJpegQuality
1137 *
1138 * DESCRIPTION: get user set jpeg quality
1139 *
1140 * PARAMETERS : none
1141 *
1142 * RETURN     : jpeg quality setting
1143 *==========================================================================*/
1144int QCamera3PicChannel::getJpegQuality()
1145{
1146    int quality = mJpegSettings->jpeg_quality;
1147    if (quality < 0) {
1148        quality = 85;  //set to default quality value
1149    }
1150    return quality;
1151}
1152
1153/*===========================================================================
1154 * FUNCTION   : getJpegRotation
1155 *
1156 * DESCRIPTION: get rotation information to be passed into jpeg encoding
1157 *
1158 * PARAMETERS : none
1159 *
1160 * RETURN     : rotation information
1161 *==========================================================================*/
1162int QCamera3PicChannel::getJpegRotation() {
1163    int rotation = mJpegSettings->jpeg_orientation;
1164    if (rotation < 0) {
1165        rotation = 0;
1166    }
1167    return rotation;
1168}
1169
1170/*===========================================================================
1171 * FUNCTION   : getRational
1172 *
1173 * DESCRIPTION: compose rational struct
1174 *
1175 * PARAMETERS :
1176 *   @rat     : ptr to struct to store rational info
1177 *   @num     :num of the rational
1178 *   @denom   : denom of the rational
1179 *
1180 * RETURN     : int32_t type of status
1181 *              NO_ERROR  -- success
1182 *              none-zero failure code
1183 *==========================================================================*/
1184int32_t getRational(rat_t *rat, int num, int denom)
1185{
1186    if (NULL == rat) {
1187        ALOGE("%s: NULL rat input", __func__);
1188        return BAD_VALUE;
1189    }
1190    rat->num = num;
1191    rat->denom = denom;
1192    return NO_ERROR;
1193}
1194
1195/*===========================================================================
1196 * FUNCTION   : parseGPSCoordinate
1197 *
1198 * DESCRIPTION: parse GPS coordinate string
1199 *
1200 * PARAMETERS :
1201 *   @coord_str : [input] coordinate string
1202 *   @coord     : [output]  ptr to struct to store coordinate
1203 *
1204 * RETURN     : int32_t type of status
1205 *              NO_ERROR  -- success
1206 *              none-zero failure code
1207 *==========================================================================*/
1208int parseGPSCoordinate(const char *coord_str, rat_t* coord)
1209{
1210    if(coord == NULL) {
1211        ALOGE("%s: error, invalid argument coord == NULL", __func__);
1212        return BAD_VALUE;
1213    }
1214    float degF = atof(coord_str);
1215    if (degF < 0) {
1216        degF = -degF;
1217    }
1218    float minF = (degF - (int) degF) * 60;
1219    float secF = (minF - (int) minF) * 60;
1220
1221    getRational(&coord[0], (int)degF, 1);
1222    getRational(&coord[1], (int)minF, 1);
1223    getRational(&coord[2], (int)(secF * 10000), 10000);
1224    return NO_ERROR;
1225}
1226
1227/*===========================================================================
1228 * FUNCTION   : getExifDateTime
1229 *
1230 * DESCRIPTION: query exif date time
1231 *
1232 * PARAMETERS :
1233 *   @dateTime : string to store exif date time
1234 *   @count    : lenght of the dateTime string
1235 *
1236 * RETURN     : int32_t type of status
1237 *              NO_ERROR  -- success
1238 *              none-zero failure code
1239 *==========================================================================*/
1240int32_t getExifDateTime(char *dateTime, uint32_t &count)
1241{
1242    //get time and date from system
1243    time_t rawtime;
1244    struct tm * timeinfo;
1245    time(&rawtime);
1246    timeinfo = localtime (&rawtime);
1247    //Write datetime according to EXIF Spec
1248    //"YYYY:MM:DD HH:MM:SS" (20 chars including \0)
1249    snprintf(dateTime, 20, "%04d:%02d:%02d %02d:%02d:%02d",
1250             timeinfo->tm_year + 1900, timeinfo->tm_mon + 1,
1251             timeinfo->tm_mday, timeinfo->tm_hour,
1252             timeinfo->tm_min, timeinfo->tm_sec);
1253    count = 20;
1254
1255    return NO_ERROR;
1256}
1257
1258/*===========================================================================
1259 * FUNCTION   : getExifFocalLength
1260 *
1261 * DESCRIPTION: get exif focal lenght
1262 *
1263 * PARAMETERS :
1264 *   @focalLength : ptr to rational strcut to store focal lenght
1265 *
1266 * RETURN     : int32_t type of status
1267 *              NO_ERROR  -- success
1268 *              none-zero failure code
1269 *==========================================================================*/
1270int32_t getExifFocalLength(rat_t *focalLength, float value)
1271{
1272    int focalLengthValue =
1273        (int)(value * FOCAL_LENGTH_DECIMAL_PRECISION);
1274    return getRational(focalLength, focalLengthValue, FOCAL_LENGTH_DECIMAL_PRECISION);
1275}
1276
1277/*===========================================================================
1278 * FUNCTION   : getExifGpsProcessingMethod
1279 *
1280 * DESCRIPTION: get GPS processing method
1281 *
1282 * PARAMETERS :
1283 *   @gpsProcessingMethod : string to store GPS process method
1284 *   @count               : lenght of the string
1285 *
1286 * RETURN     : int32_t type of status
1287 *              NO_ERROR  -- success
1288 *              none-zero failure code
1289 *==========================================================================*/
1290int32_t getExifGpsProcessingMethod(char *gpsProcessingMethod,
1291                                                      uint32_t &count, int value)
1292{
1293    char str[30];
1294    snprintf(str, sizeof(str), "%d", value);
1295    if(str != NULL) {
1296        memcpy(gpsProcessingMethod, ExifAsciiPrefix, EXIF_ASCII_PREFIX_SIZE);
1297        count = EXIF_ASCII_PREFIX_SIZE;
1298        strncpy(gpsProcessingMethod + EXIF_ASCII_PREFIX_SIZE, str, strlen(str));
1299        count += strlen(str);
1300        gpsProcessingMethod[count++] = '\0'; // increase 1 for the last NULL char
1301        return NO_ERROR;
1302    } else {
1303        return BAD_VALUE;
1304    }
1305}
1306
1307/*===========================================================================
1308 * FUNCTION   : getExifLatitude
1309 *
1310 * DESCRIPTION: get exif latitude
1311 *
1312 * PARAMETERS :
1313 *   @latitude : ptr to rational struct to store latitude info
1314 *   @ladRef   : charater to indicate latitude reference
1315 *
1316 * RETURN     : int32_t type of status
1317 *              NO_ERROR  -- success
1318 *              none-zero failure code
1319 *==========================================================================*/
1320int32_t getExifLatitude(rat_t *latitude,
1321                                           char *latRef, double value)
1322{
1323    char str[30];
1324    snprintf(str, sizeof(str), "%f", value);
1325    if(str != NULL) {
1326        parseGPSCoordinate(str, latitude);
1327
1328        //set Latitude Ref
1329        float latitudeValue = strtof(str, 0);
1330        if(latitudeValue < 0.0f) {
1331            latRef[0] = 'S';
1332        } else {
1333            latRef[0] = 'N';
1334        }
1335        latRef[1] = '\0';
1336        return NO_ERROR;
1337    }else{
1338        return BAD_VALUE;
1339    }
1340}
1341
1342/*===========================================================================
1343 * FUNCTION   : getExifLongitude
1344 *
1345 * DESCRIPTION: get exif longitude
1346 *
1347 * PARAMETERS :
1348 *   @longitude : ptr to rational struct to store longitude info
1349 *   @lonRef    : charater to indicate longitude reference
1350 *
1351 * RETURN     : int32_t type of status
1352 *              NO_ERROR  -- success
1353 *              none-zero failure code
1354 *==========================================================================*/
1355int32_t getExifLongitude(rat_t *longitude,
1356                                            char *lonRef, double value)
1357{
1358    char str[30];
1359    snprintf(str, sizeof(str), "%f", value);
1360    if(str != NULL) {
1361        parseGPSCoordinate(str, longitude);
1362
1363        //set Longitude Ref
1364        float longitudeValue = strtof(str, 0);
1365        if(longitudeValue < 0.0f) {
1366            lonRef[0] = 'W';
1367        } else {
1368            lonRef[0] = 'E';
1369        }
1370        lonRef[1] = '\0';
1371        return NO_ERROR;
1372    }else{
1373        return BAD_VALUE;
1374    }
1375}
1376
1377/*===========================================================================
1378 * FUNCTION   : getExifAltitude
1379 *
1380 * DESCRIPTION: get exif altitude
1381 *
1382 * PARAMETERS :
1383 *   @altitude : ptr to rational struct to store altitude info
1384 *   @altRef   : charater to indicate altitude reference
1385 *
1386 * RETURN     : int32_t type of status
1387 *              NO_ERROR  -- success
1388 *              none-zero failure code
1389 *==========================================================================*/
1390int32_t getExifAltitude(rat_t *altitude,
1391                                           char *altRef, double value)
1392{
1393    char str[30];
1394    snprintf(str, sizeof(str), "%f", value);
1395    if(str != NULL) {
1396        double value = atof(str);
1397        *altRef = 0;
1398        if(value < 0){
1399            *altRef = 1;
1400            value = -value;
1401        }
1402        return getRational(altitude, value*1000, 1000);
1403    }else{
1404        return BAD_VALUE;
1405    }
1406}
1407
1408/*===========================================================================
1409 * FUNCTION   : getExifGpsDateTimeStamp
1410 *
1411 * DESCRIPTION: get exif GPS date time stamp
1412 *
1413 * PARAMETERS :
1414 *   @gpsDateStamp : GPS date time stamp string
1415 *   @bufLen       : length of the string
1416 *   @gpsTimeStamp : ptr to rational struct to store time stamp info
1417 *
1418 * RETURN     : int32_t type of status
1419 *              NO_ERROR  -- success
1420 *              none-zero failure code
1421 *==========================================================================*/
1422int32_t getExifGpsDateTimeStamp(char *gpsDateStamp,
1423                                                   uint32_t bufLen,
1424                                                   rat_t *gpsTimeStamp, int64_t value)
1425{
1426    char str[30];
1427    snprintf(str, sizeof(str), "%d", value);
1428    if(str != NULL) {
1429        time_t unixTime = (time_t)atol(str);
1430        struct tm *UTCTimestamp = gmtime(&unixTime);
1431
1432        strftime(gpsDateStamp, bufLen, "%Y:%m:%d", UTCTimestamp);
1433
1434        getRational(&gpsTimeStamp[0], UTCTimestamp->tm_hour, 1);
1435        getRational(&gpsTimeStamp[1], UTCTimestamp->tm_min, 1);
1436        getRational(&gpsTimeStamp[2], UTCTimestamp->tm_sec, 1);
1437
1438        return NO_ERROR;
1439    } else {
1440        return BAD_VALUE;
1441    }
1442}
1443/*===========================================================================
1444 * FUNCTION   : getExifData
1445 *
1446 * DESCRIPTION: get exif data to be passed into jpeg encoding
1447 *
1448 * PARAMETERS : none
1449 *
1450 * RETURN     : exif data from user setting and GPS
1451 *==========================================================================*/
1452QCamera3Exif *QCamera3PicChannel::getExifData()
1453{
1454    QCamera3Exif *exif = new QCamera3Exif();
1455    if (exif == NULL) {
1456        ALOGE("%s: No memory for QCamera3Exif", __func__);
1457        return NULL;
1458    }
1459
1460    int32_t rc = NO_ERROR;
1461    uint32_t count = 0;
1462
1463    // add exif entries
1464    char dateTime[20];
1465    memset(dateTime, 0, sizeof(dateTime));
1466    count = 20;
1467    rc = getExifDateTime(dateTime, count);
1468    if(rc == NO_ERROR) {
1469        exif->addEntry(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL,
1470                       EXIF_ASCII,
1471                       count,
1472                       (void *)dateTime);
1473    } else {
1474        ALOGE("%s: getExifDateTime failed", __func__);
1475    }
1476
1477    rat_t focalLength;
1478    rc = getExifFocalLength(&focalLength, mJpegSettings->lens_focal_length);
1479    if (rc == NO_ERROR) {
1480        exif->addEntry(EXIFTAGID_FOCAL_LENGTH,
1481                       EXIF_RATIONAL,
1482                       1,
1483                       (void *)&(focalLength));
1484    } else {
1485        ALOGE("%s: getExifFocalLength failed", __func__);
1486    }
1487
1488    //TBD_Later
1489    /*uint16_t isoSpeed = mParameters.getExifIsoSpeed();
1490    exif->addEntry(EXIFTAGID_ISO_SPEED_RATING,
1491                   EXIF_SHORT,
1492                   1,
1493                   (void *)&(isoSpeed));
1494    */
1495    char gpsProcessingMethod[EXIF_ASCII_PREFIX_SIZE + GPS_PROCESSING_METHOD_SIZE];
1496    count = 0;
1497    rc = getExifGpsProcessingMethod(gpsProcessingMethod, count, mJpegSettings->gps_processing_method);
1498    if(rc == NO_ERROR) {
1499        exif->addEntry(EXIFTAGID_GPS_PROCESSINGMETHOD,
1500                       EXIF_ASCII,
1501                       count,
1502                       (void *)gpsProcessingMethod);
1503    } else {
1504        ALOGE("%s: getExifGpsProcessingMethod failed", __func__);
1505    }
1506
1507    rat_t latitude[3];
1508    char latRef[2];
1509    rc = getExifLatitude(latitude, latRef, mJpegSettings->gps_coordinates[0]);
1510    if(rc == NO_ERROR) {
1511        exif->addEntry(EXIFTAGID_GPS_LATITUDE,
1512                       EXIF_RATIONAL,
1513                       3,
1514                       (void *)latitude);
1515        exif->addEntry(EXIFTAGID_GPS_LATITUDE_REF,
1516                       EXIF_ASCII,
1517                       2,
1518                       (void *)latRef);
1519    } else {
1520        ALOGE("%s: getExifLatitude failed", __func__);
1521    }
1522
1523    rat_t longitude[3];
1524    char lonRef[2];
1525    rc = getExifLongitude(longitude, lonRef, mJpegSettings->gps_coordinates[1]);
1526    if(rc == NO_ERROR) {
1527        exif->addEntry(EXIFTAGID_GPS_LONGITUDE,
1528                       EXIF_RATIONAL,
1529                       3,
1530                       (void *)longitude);
1531
1532        exif->addEntry(EXIFTAGID_GPS_LONGITUDE_REF,
1533                       EXIF_ASCII,
1534                       2,
1535                       (void *)lonRef);
1536    } else {
1537        ALOGE("%s: getExifLongitude failed", __func__);
1538    }
1539
1540    rat_t altitude;
1541    char altRef;
1542    rc = getExifAltitude(&altitude, &altRef, mJpegSettings->gps_coordinates[2]);
1543    if(rc == NO_ERROR) {
1544        exif->addEntry(EXIFTAGID_GPS_ALTITUDE,
1545                       EXIF_RATIONAL,
1546                       1,
1547                       (void *)&(altitude));
1548
1549        exif->addEntry(EXIFTAGID_GPS_ALTITUDE_REF,
1550                       EXIF_BYTE,
1551                       1,
1552                       (void *)&altRef);
1553    } else {
1554        ALOGE("%s: getExifAltitude failed", __func__);
1555    }
1556
1557    char gpsDateStamp[20];
1558    rat_t gpsTimeStamp[3];
1559    rc = getExifGpsDateTimeStamp(gpsDateStamp, 20, gpsTimeStamp, mJpegSettings->gps_timestamp);
1560    if(rc == NO_ERROR) {
1561        exif->addEntry(EXIFTAGID_GPS_DATESTAMP,
1562                       EXIF_ASCII,
1563                       strlen(gpsDateStamp) + 1,
1564                       (void *)gpsDateStamp);
1565
1566        exif->addEntry(EXIFTAGID_GPS_TIMESTAMP,
1567                       EXIF_RATIONAL,
1568                       3,
1569                       (void *)gpsTimeStamp);
1570    } else {
1571        ALOGE("%s: getExifGpsDataTimeStamp failed", __func__);
1572    }
1573
1574    return exif;
1575}
1576
1577int QCamera3PicChannel::kMaxBuffers = 1;
1578}; // namespace qcamera
1579