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