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