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