QCamera3Channel.cpp revision 2f0dc524b1cce88a85757118419d1dc08916e650
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 <cutils/properties.h>
42#include "QCamera3Channel.h"
43
44using namespace android;
45
46#define MIN_STREAMING_BUFFER_NUM 7
47
48namespace qcamera {
49static const char ExifAsciiPrefix[] =
50    { 0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0 };          // "ASCII\0\0\0"
51static const char ExifUndefinedPrefix[] =
52    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };   // "\0\0\0\0\0\0\0\0"
53
54#define GPS_PROCESSING_METHOD_SIZE       101
55#define EXIF_ASCII_PREFIX_SIZE           8   //(sizeof(ExifAsciiPrefix))
56#define FOCAL_LENGTH_DECIMAL_PRECISION   100
57
58/*===========================================================================
59 * FUNCTION   : QCamera3Channel
60 *
61 * DESCRIPTION: constrcutor of QCamera3Channel
62 *
63 * PARAMETERS :
64 *   @cam_handle : camera handle
65 *   @cam_ops    : ptr to camera ops table
66 *
67 * RETURN     : none
68 *==========================================================================*/
69QCamera3Channel::QCamera3Channel(uint32_t cam_handle,
70                               mm_camera_ops_t *cam_ops,
71                               channel_cb_routine cb_routine,
72                               cam_padding_info_t *paddingInfo,
73                               void *userData)
74{
75    m_camHandle = cam_handle;
76    m_camOps = cam_ops;
77    m_bIsActive = false;
78
79    m_handle = 0;
80    m_numStreams = 0;
81    memset(mStreams, 0, sizeof(mStreams));
82    mUserData = userData;
83
84    mStreamInfoBuf = NULL;
85    mChannelCB = cb_routine;
86    mPaddingInfo = paddingInfo;
87}
88
89/*===========================================================================
90 * FUNCTION   : QCamera3Channel
91 *
92 * DESCRIPTION: default constrcutor of QCamera3Channel
93 *
94 * PARAMETERS : none
95 *
96 * RETURN     : none
97 *==========================================================================*/
98QCamera3Channel::QCamera3Channel()
99{
100    m_camHandle = 0;
101    m_camOps = NULL;
102    m_bIsActive = false;
103
104    m_handle = 0;
105    m_numStreams = 0;
106    memset(mStreams, 0, sizeof(mStreams));
107    mUserData = NULL;
108
109    mStreamInfoBuf = NULL;
110    mChannelCB = NULL;
111    mPaddingInfo = NULL;
112}
113
114/*===========================================================================
115 * FUNCTION   : ~QCamera3Channel
116 *
117 * DESCRIPTION: destructor of QCamera3Channel
118 *
119 * PARAMETERS : none
120 *
121 * RETURN     : none
122 *==========================================================================*/
123QCamera3Channel::~QCamera3Channel()
124{
125    if (m_bIsActive)
126        stop();
127
128    for (int i = 0; i < m_numStreams; i++) {
129        if (mStreams[i] != NULL) {
130            delete mStreams[i];
131            mStreams[i] = 0;
132        }
133    }
134    m_numStreams = 0;
135    m_camOps->delete_channel(m_camHandle, m_handle);
136    m_handle = 0;
137}
138
139/*===========================================================================
140 * FUNCTION   : init
141 *
142 * DESCRIPTION: initialization of channel
143 *
144 * PARAMETERS :
145 *   @attr    : channel bundle attribute setting
146 *   @dataCB  : data notify callback
147 *   @userData: user data ptr
148 *
149 * RETURN     : int32_t type of status
150 *              NO_ERROR  -- success
151 *              none-zero failure code
152 *==========================================================================*/
153int32_t QCamera3Channel::init(mm_camera_channel_attr_t *attr,
154                             mm_camera_buf_notify_t dataCB)
155{
156    m_handle = m_camOps->add_channel(m_camHandle,
157                                      attr,
158                                      dataCB,
159                                      this);
160    if (m_handle == 0) {
161        ALOGE("%s: Add channel failed", __func__);
162        return UNKNOWN_ERROR;
163    }
164    return NO_ERROR;
165}
166
167/*===========================================================================
168 * FUNCTION   : addStream
169 *
170 * DESCRIPTION: add a stream into channel
171 *
172 * PARAMETERS :
173 *   @allocator      : stream related buffer allocator
174 *   @streamInfoBuf  : ptr to buf that constains stream info
175 *   @minStreamBufNum: number of stream buffers needed
176 *   @paddingInfo    : padding information
177 *   @stream_cb      : stream data notify callback
178 *   @userdata       : user data ptr
179 *
180 * RETURN     : int32_t type of status
181 *              NO_ERROR  -- success
182 *              none-zero failure code
183 *==========================================================================*/
184int32_t QCamera3Channel::addStream(cam_stream_type_t streamType,
185                                  cam_format_t streamFormat,
186                                  cam_dimension_t streamDim,
187                                  uint8_t minStreamBufNum)
188{
189    int32_t rc = NO_ERROR;
190
191    if (m_numStreams >= 1) {
192        ALOGE("%s: Only one stream per channel supported in v3 Hal", __func__);
193        return BAD_VALUE;
194    }
195
196    if (m_numStreams >= MAX_STREAM_NUM_IN_BUNDLE) {
197        ALOGE("%s: stream number (%d) exceeds max limit (%d)",
198              __func__, m_numStreams, MAX_STREAM_NUM_IN_BUNDLE);
199        return BAD_VALUE;
200    }
201    QCamera3Stream *pStream = new QCamera3Stream(m_camHandle,
202                                               m_handle,
203                                               m_camOps,
204                                               mPaddingInfo,
205                                               this);
206    if (pStream == NULL) {
207        ALOGE("%s: No mem for Stream", __func__);
208        return NO_MEMORY;
209    }
210
211    rc = pStream->init(streamType, streamFormat, streamDim, minStreamBufNum,
212                                                    streamCbRoutine, this);
213    if (rc == 0) {
214        mStreams[m_numStreams] = pStream;
215        m_numStreams++;
216    } else {
217        delete pStream;
218    }
219    return rc;
220}
221
222/*===========================================================================
223 * FUNCTION   : start
224 *
225 * DESCRIPTION: start channel, which will start all streams belong to this channel
226 *
227 * PARAMETERS :
228 *
229 * RETURN     : int32_t type of status
230 *              NO_ERROR  -- success
231 *              none-zero failure code
232 *==========================================================================*/
233int32_t QCamera3Channel::start()
234{
235    int32_t rc = NO_ERROR;
236
237    if (m_numStreams > 1) {
238        ALOGE("%s: bundle not supported", __func__);
239    }
240
241    for (int i = 0; i < m_numStreams; i++) {
242        if (mStreams[i] != NULL) {
243            mStreams[i]->start();
244        }
245    }
246    rc = m_camOps->start_channel(m_camHandle, m_handle);
247
248    if (rc != NO_ERROR) {
249        for (int i = 0; i < m_numStreams; i++) {
250            if (mStreams[i] != NULL) {
251                mStreams[i]->stop();
252            }
253        }
254    } else {
255        m_bIsActive = true;
256    }
257
258    return rc;
259}
260
261/*===========================================================================
262 * FUNCTION   : stop
263 *
264 * DESCRIPTION: stop a channel, which will stop all streams belong to this channel
265 *
266 * PARAMETERS : none
267 *
268 * RETURN     : int32_t type of status
269 *              NO_ERROR  -- success
270 *              none-zero failure code
271 *==========================================================================*/
272int32_t QCamera3Channel::stop()
273{
274    int32_t rc = NO_ERROR;
275    if(!m_bIsActive) {
276        ALOGE("%s: Attempt to stop inactive channel",__func__);
277        return rc;
278    }
279
280    rc = m_camOps->stop_channel(m_camHandle, m_handle);
281
282    for (int i = 0; i < m_numStreams; i++) {
283        if (mStreams[i] != NULL) {
284            mStreams[i]->stop();
285        }
286    }
287
288    m_bIsActive = false;
289    return rc;
290}
291
292/*===========================================================================
293 * FUNCTION   : bufDone
294 *
295 * DESCRIPTION: return a stream buf back to kernel
296 *
297 * PARAMETERS :
298 *   @recvd_frame  : stream buf frame to be returned
299 *
300 * RETURN     : int32_t type of status
301 *              NO_ERROR  -- success
302 *              none-zero failure code
303 *==========================================================================*/
304int32_t QCamera3Channel::bufDone(mm_camera_super_buf_t *recvd_frame)
305{
306    int32_t rc = NO_ERROR;
307    for (int i = 0; i < recvd_frame->num_bufs; i++) {
308         if (recvd_frame->bufs[i] != NULL) {
309             for (int j = 0; j < m_numStreams; j++) {
310                 if (mStreams[j] != NULL &&
311                     mStreams[j]->getMyHandle() == recvd_frame->bufs[i]->stream_id) {
312                     rc = mStreams[j]->bufDone(recvd_frame->bufs[i]->buf_idx);
313                     break; // break loop j
314                 }
315             }
316         }
317    }
318
319    return rc;
320}
321
322/*===========================================================================
323 * FUNCTION   : getStreamByHandle
324 *
325 * DESCRIPTION: return stream object by stream handle
326 *
327 * PARAMETERS :
328 *   @streamHandle : stream handle
329 *
330 * RETURN     : stream object. NULL if not found
331 *==========================================================================*/
332QCamera3Stream *QCamera3Channel::getStreamByHandle(uint32_t streamHandle)
333{
334    for (int i = 0; i < m_numStreams; i++) {
335        if (mStreams[i] != NULL && mStreams[i]->getMyHandle() == streamHandle) {
336            return mStreams[i];
337        }
338    }
339    return NULL;
340}
341
342/*===========================================================================
343 * FUNCTION   : getStreamByHandle
344 *
345 * DESCRIPTION: return stream object by stream handle
346 *
347 * PARAMETERS :
348 *   @streamHandle : stream handle
349 *
350 * RETURN     : stream object. NULL if not found
351 *==========================================================================*/
352QCamera3Stream *QCamera3Channel::getStreamByIndex(uint8_t index)
353{
354    if (index < m_numStreams) {
355        return mStreams[index];
356    }
357    return NULL;
358}
359
360/*===========================================================================
361 * FUNCTION   : streamCbRoutine
362 *
363 * DESCRIPTION: callback routine for stream
364 *
365 * PARAMETERS :
366 *   @streamHandle : stream handle
367 *
368 * RETURN     : stream object. NULL if not found
369 *==========================================================================*/
370void QCamera3Channel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
371                QCamera3Stream *stream, void *userdata)
372{
373    QCamera3Channel *channel = (QCamera3Channel *)userdata;
374    if (channel == NULL) {
375        ALOGE("%s: invalid channel pointer", __func__);
376        return;
377    }
378    channel->streamCbRoutine(super_frame, stream);
379}
380
381/*===========================================================================
382 * FUNCTION   : QCamera3RegularChannel
383 *
384 * DESCRIPTION: constrcutor of QCamera3RegularChannel
385 *
386 * PARAMETERS :
387 *   @cam_handle : camera handle
388 *   @cam_ops    : ptr to camera ops table
389 *   @cb_routine : callback routine to frame aggregator
390 *   @stream     : camera3_stream_t structure
391 *
392 * RETURN     : none
393 *==========================================================================*/
394QCamera3RegularChannel::QCamera3RegularChannel(uint32_t cam_handle,
395                    mm_camera_ops_t *cam_ops,
396                    channel_cb_routine cb_routine,
397                    cam_padding_info_t *paddingInfo,
398                    void *userData,
399                    camera3_stream_t *stream) :
400                        QCamera3Channel(cam_handle, cam_ops, cb_routine,
401                                                paddingInfo, userData),
402                        mCamera3Stream(stream),
403                        mNumBufs(0),
404                        mCamera3Buffers(NULL),
405                        mMemory(NULL)
406{
407}
408
409/*===========================================================================
410 * FUNCTION   : ~QCamera3RegularChannel
411 *
412 * DESCRIPTION: destructor of QCamera3RegularChannel
413 *
414 * PARAMETERS : none
415 *
416 * RETURN     : none
417 *==========================================================================*/
418QCamera3RegularChannel::~QCamera3RegularChannel()
419{
420    if (mCamera3Buffers) {
421        delete[] mCamera3Buffers;
422    }
423}
424
425int32_t QCamera3RegularChannel::initialize()
426{
427  //TO DO
428  return 0;
429}
430
431/*===========================================================================
432 * FUNCTION   : request
433 *
434 * DESCRIPTION: process a request from camera service. Stream on if ncessary.
435 *
436 * PARAMETERS :
437 *   @buffer  : buffer to be filled for this request
438 *
439 * RETURN     : 0 on a success start of capture
440 *              -EINVAL on invalid input
441 *              -ENODEV on serious error
442 *==========================================================================*/
443int32_t QCamera3RegularChannel::request(buffer_handle_t *buffer, uint32_t frameNumber)
444{
445    //FIX ME: Return buffer back in case of failures below.
446
447    int32_t rc = NO_ERROR;
448    int index;
449    if(!m_bIsActive) {
450        ALOGD("%s: First request on this channel starting stream",__func__);
451        start();
452        if(rc != NO_ERROR) {
453            ALOGE("%s: Failed to start the stream on the request",__func__);
454            return rc;
455        }
456    } else {
457        ALOGV("%s: Request on an existing stream",__func__);
458    }
459
460    if(!mMemory) {
461        ALOGE("%s: error, Gralloc Memory object not yet created for this stream",__func__);
462        return NO_MEMORY;
463    }
464
465    index = mMemory->getMatchBufIndex((void*)buffer);
466    if(index < 0) {
467        ALOGE("%s: Could not find object among registered buffers",__func__);
468        return DEAD_OBJECT;
469    }
470
471    rc = mStreams[0]->bufDone(index);
472    if(rc != NO_ERROR) {
473        ALOGE("%s: Failed to Q new buffer to stream",__func__);
474        return rc;
475    }
476
477    rc = mMemory->markFrameNumber(index, frameNumber);
478    return rc;
479}
480
481/*===========================================================================
482 * FUNCTION   : registerBuffers
483 *
484 * DESCRIPTION: register streaming buffers to the channel object
485 *
486 * PARAMETERS :
487 *   @num_buffers : number of buffers to be registered
488 *   @buffers     : buffer to be registered
489 *
490 * RETURN     : 0 on a success start of capture
491 *              -EINVAL on invalid input
492 *              -ENOMEM on failure to register the buffer
493 *              -ENODEV on serious error
494 *==========================================================================*/
495int32_t QCamera3RegularChannel::registerBuffers(uint32_t num_buffers, buffer_handle_t **buffers)
496{
497    int rc = 0;
498    struct private_handle_t *priv_handle = (struct private_handle_t *)(*buffers[0]);
499    cam_stream_type_t streamType;
500    cam_format_t streamFormat;
501    cam_dimension_t streamDim;
502
503    rc = init(NULL, NULL);
504    if (rc < 0) {
505        ALOGE("%s: init failed", __func__);
506        return rc;
507    }
508
509    if (mCamera3Stream->format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
510        if (priv_handle->flags & private_handle_t::PRIV_FLAGS_VIDEO_ENCODER) {
511            streamType = CAM_STREAM_TYPE_VIDEO;
512            streamFormat = CAM_FORMAT_YUV_420_NV12;
513        } else if (priv_handle->flags & private_handle_t::PRIV_FLAGS_HW_TEXTURE) {
514            streamType = CAM_STREAM_TYPE_PREVIEW;
515            streamFormat = CAM_FORMAT_YUV_420_NV21;
516        } else {
517            ALOGE("%s: priv_handle->flags 0x%x not supported",
518                    __func__, priv_handle->flags);
519            return -EINVAL;
520        }
521    } else if(mCamera3Stream->format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
522         streamType = CAM_STREAM_TYPE_PREVIEW;
523         streamFormat = CAM_FORMAT_YUV_420_NV21;
524    } else {
525        //TODO: Fail for other types of streams for now
526        ALOGE("%s: format is not IMPLEMENTATION_DEFINED or flexible", __func__);
527        return -EINVAL;
528    }
529
530    /* Bookkeep buffer set because they go out of scope after register call */
531    mNumBufs = num_buffers;
532    mCamera3Buffers = new buffer_handle_t*[num_buffers];
533    if (mCamera3Buffers == NULL) {
534        ALOGE("%s: Failed to allocate buffer_handle_t*", __func__);
535        return -ENOMEM;
536    }
537    for (size_t i = 0; i < num_buffers; i++)
538        mCamera3Buffers[i] = buffers[i];
539
540    streamDim.width = mCamera3Stream->width;
541    streamDim.height = mCamera3Stream->height;
542    rc = QCamera3Channel::addStream(streamType, streamFormat, streamDim,
543        num_buffers);
544    return rc;
545}
546
547void QCamera3RegularChannel::streamCbRoutine(
548                            mm_camera_super_buf_t *super_frame,
549                            QCamera3Stream *stream)
550{
551    //FIXME Q Buf back in case of error?
552    uint8_t frameIndex;
553    buffer_handle_t *resultBuffer;
554    int32_t resultFrameNumber;
555    camera3_stream_buffer_t result;
556
557    if(!super_frame) {
558         ALOGE("%s: Invalid Super buffer",__func__);
559         return;
560    }
561
562    if(super_frame->num_bufs != 1) {
563         ALOGE("%s: Multiple streams are not supported",__func__);
564         return;
565    }
566    if(super_frame->bufs[0] == NULL ) {
567         ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
568                  __func__);
569         return;
570    }
571
572    frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
573    if(frameIndex >= mNumBufs) {
574         ALOGE("%s: Error, Invalid index for buffer",__func__);
575         if(stream) {
576             stream->bufDone(frameIndex);
577         }
578         return;
579    }
580
581    ////Use below data to issue framework callback
582    resultBuffer = mCamera3Buffers[frameIndex];
583    resultFrameNumber = mMemory->getFrameNumber(frameIndex);
584
585    result.stream = mCamera3Stream;
586    result.buffer = resultBuffer;
587    result.status = CAMERA3_BUFFER_STATUS_OK;
588    result.acquire_fence = -1;
589    result.release_fence = -1;
590
591    mChannelCB(NULL, &result, resultFrameNumber, mUserData);
592    return;
593}
594
595QCamera3Memory* QCamera3RegularChannel::getStreamBufs(uint32_t /*len*/)
596{
597    if (mNumBufs == 0 || mCamera3Buffers == NULL) {
598        ALOGE("%s: buffers not registered yet", __func__);
599        return NULL;
600    }
601
602    mMemory = new QCamera3GrallocMemory();
603    if (mMemory == NULL) {
604        return NULL;
605    }
606
607    if (mMemory->registerBuffers(mNumBufs, mCamera3Buffers) < 0) {
608        delete mMemory;
609        mMemory = NULL;
610        return NULL;
611    }
612    return mMemory;
613}
614
615void QCamera3RegularChannel::putStreamBufs()
616{
617    mMemory->unregisterBuffers();
618    delete mMemory;
619    mMemory = NULL;
620}
621
622int QCamera3RegularChannel::kMaxBuffers = 7;
623
624QCamera3MetadataChannel::QCamera3MetadataChannel(uint32_t cam_handle,
625                    mm_camera_ops_t *cam_ops,
626                    channel_cb_routine cb_routine,
627                    cam_padding_info_t *paddingInfo,
628                    void *userData) :
629                        QCamera3Channel(cam_handle, cam_ops,
630                                cb_routine, paddingInfo, userData),
631                        mMemory(NULL)
632{
633}
634
635QCamera3MetadataChannel::~QCamera3MetadataChannel()
636{
637    if (m_bIsActive)
638        stop();
639
640    if (mMemory) {
641        mMemory->deallocate();
642        delete mMemory;
643        mMemory = NULL;
644    }
645}
646
647int32_t QCamera3MetadataChannel::initialize()
648{
649    int32_t rc;
650    cam_dimension_t streamDim;
651
652    if (mMemory || m_numStreams > 0) {
653        ALOGE("%s: metadata channel already initialized", __func__);
654        return -EINVAL;
655    }
656
657    rc = init(NULL, NULL);
658    if (rc < 0) {
659        ALOGE("%s: init failed", __func__);
660        return rc;
661    }
662
663    streamDim.width = sizeof(metadata_buffer_t),
664    streamDim.height = 1;
665    rc = QCamera3Channel::addStream(CAM_STREAM_TYPE_METADATA, CAM_FORMAT_MAX,
666        streamDim, MIN_STREAMING_BUFFER_NUM);
667    if (rc < 0) {
668        ALOGE("%s: addStream failed", __func__);
669    }
670    return rc;
671}
672
673int32_t QCamera3MetadataChannel::request(buffer_handle_t * /*buffer*/,
674                                                uint32_t frameNumber)
675{
676    if (!m_bIsActive) {
677        return start();
678    }
679    else
680        return 0;
681}
682
683int32_t QCamera3MetadataChannel::registerBuffers(uint32_t /*num_buffers*/,
684                                        buffer_handle_t ** /*buffers*/)
685{
686    // no registerBuffers are supported for metadata channel
687    return -EINVAL;
688}
689
690void QCamera3MetadataChannel::streamCbRoutine(
691                        mm_camera_super_buf_t *super_frame,
692                        QCamera3Stream *stream)
693{
694    uint32_t requestNumber = 0;
695    if (super_frame == NULL || super_frame->num_bufs != 1) {
696        ALOGE("%s: super_frame is not valid", __func__);
697        return;
698    }
699    mChannelCB(super_frame, NULL, requestNumber, mUserData);
700
701    //Return the buffer
702    stream->bufDone(super_frame->bufs[0]->buf_idx);
703}
704
705QCamera3Memory* QCamera3MetadataChannel::getStreamBufs(uint32_t len)
706{
707    int rc;
708    if (len < sizeof(metadata_buffer_t)) {
709        ALOGE("%s: size doesn't match %d vs %d", __func__,
710                len, sizeof(metadata_buffer_t));
711        return NULL;
712    }
713    mMemory = new QCamera3HeapMemory();
714    if (!mMemory) {
715        ALOGE("%s: unable to create metadata memory", __func__);
716        return NULL;
717    }
718    rc = mMemory->allocate(MIN_STREAMING_BUFFER_NUM, len, true);
719    if (rc < 0) {
720        ALOGE("%s: unable to allocate metadata memory", __func__);
721        delete mMemory;
722        mMemory = NULL;
723        return NULL;
724    }
725    memset(mMemory->getPtr(0), 0, sizeof(metadata_buffer_t));
726    return mMemory;
727}
728
729void QCamera3MetadataChannel::putStreamBufs()
730{
731    mMemory->deallocate();
732    delete mMemory;
733    mMemory = NULL;
734}
735
736/*===========================================================================
737 * FUNCTION   : jpegEvtHandle
738 *
739 * DESCRIPTION: Function registerd to mm-jpeg-interface to handle jpeg events.
740                Construct result payload and call mChannelCb to deliver buffer
741                to framework.
742 *
743 * PARAMETERS :
744 *   @status    : status of jpeg job
745 *   @client_hdl: jpeg client handle
746 *   @jobId     : jpeg job Id
747 *   @p_ouput   : ptr to jpeg output result struct
748 *   @userdata  : user data ptr
749 *
750 * RETURN     : none
751 *==========================================================================*/
752void QCamera3PicChannel::jpegEvtHandle(jpeg_job_status_t status,
753                                              uint32_t /*client_hdl*/,
754                                              uint32_t jobId,
755                                              mm_jpeg_output_t *p_output,
756                                              void *userdata)
757{
758    buffer_handle_t *resultBuffer;
759    int32_t resultFrameNumber;
760    int resultStatus = CAMERA3_BUFFER_STATUS_OK;
761    camera3_stream_buffer_t result;
762    camera3_jpeg_blob_t jpegHeader;
763    char* jpeg_eof = 0;
764    int maxJpegSize;
765    QCamera3PicChannel *obj = (QCamera3PicChannel *)userdata;
766    if (obj) {
767        //Construct payload for process_capture_result. Call mChannelCb
768
769        qcamera_jpeg_data_t *job = obj->m_postprocessor.findJpegJobByJobId(jobId);
770
771        if ((job == NULL) || (status == JPEG_JOB_STATUS_ERROR)) {
772            ALOGE("%s: Error in jobId: (%d) with status: %d", __func__, jobId, status);
773            resultStatus = CAMERA3_BUFFER_STATUS_ERROR;
774        }
775
776        //Construct jpeg transient header of type camera3_jpeg_blob_t
777        //Append at the end of jpeg image of buf_filled_len size
778
779        jpegHeader.jpeg_blob_id = CAMERA3_JPEG_BLOB_ID;
780        jpegHeader.jpeg_size = p_output->buf_filled_len;
781
782
783        char* jpeg_buf = (char *)p_output->buf_vaddr;
784
785        if(obj->mJpegSettings->max_jpeg_size <= 0 ||
786                obj->mJpegSettings->max_jpeg_size > obj->mMemory->getSize(obj->mCurrentBufIndex)){
787            ALOGE("%s:Max Jpeg size :%d is out of valid range setting to size of buffer",
788                    __func__, obj->mJpegSettings->max_jpeg_size);
789            maxJpegSize =  obj->mMemory->getSize(obj->mCurrentBufIndex);
790        } else {
791            maxJpegSize = obj->mJpegSettings->max_jpeg_size;
792            ALOGE("%s: Setting max jpeg size to %d",__func__, maxJpegSize);
793        }
794        jpeg_eof = &jpeg_buf[maxJpegSize-sizeof(jpegHeader)];
795        memcpy(jpeg_eof, &jpegHeader, sizeof(jpegHeader));
796        obj->mMemory->cleanInvalidateCache(obj->mCurrentBufIndex);
797
798        ////Use below data to issue framework callback
799        resultBuffer = obj->mCamera3Buffers[obj->mCurrentBufIndex];
800        resultFrameNumber = obj->mMemory->getFrameNumber(obj->mCurrentBufIndex);
801
802        result.stream = obj->mCamera3Stream;
803        result.buffer = resultBuffer;
804        result.status = resultStatus;
805        result.acquire_fence = -1;
806        result.release_fence = -1;
807
808        ALOGD("%s: Issue Callback", __func__);
809        obj->mChannelCB(NULL, &result, resultFrameNumber, obj->mUserData);
810
811        // release internal data for jpeg job
812        if (job != NULL) {
813            obj->m_postprocessor.releaseJpegJobData(job);
814            free(job);
815        }
816        return;
817        // }
818    } else {
819        ALOGE("%s: Null userdata in jpeg callback", __func__);
820    }
821}
822
823QCamera3PicChannel::QCamera3PicChannel(uint32_t cam_handle,
824                    mm_camera_ops_t *cam_ops,
825                    channel_cb_routine cb_routine,
826                    cam_padding_info_t *paddingInfo,
827                    void *userData,
828                    camera3_stream_t *stream) :
829                        QCamera3Channel(cam_handle, cam_ops, cb_routine,
830                        paddingInfo, userData),
831                        mCamera3Stream(stream),
832                        mNumBufs(0),
833                        mCamera3Buffers(NULL),
834                        mJpegSettings(NULL),
835                        mCurrentBufIndex(-1),
836                        mMemory(NULL),
837                        mYuvMemory(NULL),
838                        m_postprocessor(this)
839{
840    int32_t rc = m_postprocessor.init(jpegEvtHandle, this);
841    if (rc != 0) {
842        ALOGE("Init Postprocessor failed");
843    }
844}
845
846QCamera3PicChannel::~QCamera3PicChannel()
847{
848    int32_t rc = m_postprocessor.deinit();
849    if (rc != 0) {
850        ALOGE("De-init Postprocessor failed");
851    }
852    if (mCamera3Buffers) {
853        delete[] mCamera3Buffers;
854    }
855}
856
857int32_t QCamera3PicChannel::initialize()
858{
859    int32_t rc = NO_ERROR;
860    cam_dimension_t streamDim;
861    cam_stream_type_t streamType;
862    cam_format_t streamFormat;
863    mm_camera_channel_attr_t attr;
864
865    memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
866    attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_BURST;
867    attr.look_back = 1;
868    attr.post_frame_skip = 1;
869    attr.water_mark = 1;
870    attr.max_unmatched_frames = 1;
871
872    rc = init(&attr, QCamera3PicChannel::dataNotifyCB);
873    if (rc < 0) {
874        ALOGE("%s: init failed", __func__);
875        return rc;
876    }
877
878    streamType = CAM_STREAM_TYPE_SNAPSHOT;
879    streamFormat = CAM_FORMAT_YUV_420_NV21;
880    streamDim.width = mCamera3Stream->width;
881    streamDim.height = mCamera3Stream->height;
882
883    int num_buffers = 1;
884
885    rc = QCamera3Channel::addStream(streamType, streamFormat, streamDim,
886            num_buffers);
887
888
889    return rc;
890}
891
892int32_t QCamera3PicChannel::request(buffer_handle_t *buffer, uint32_t frameNumber, jpeg_settings_t* jpegSettings)
893{
894    //FIX ME: Return buffer back in case of failures below.
895
896    int32_t rc = NO_ERROR;
897    int index;
898    mJpegSettings = jpegSettings;
899
900    if(!m_bIsActive) {
901        ALOGD("%s: First request on this channel starting stream",__func__);
902        //Stream on for main image. YUV buffer is queued to the kernel at the end of this call.
903        rc = start();
904    } else {
905        mStreams[0]->bufDone(0);
906        ALOGD("%s: Request on an existing stream",__func__);
907    }
908
909    if(rc != NO_ERROR) {
910        ALOGE("%s: Failed to start the stream on the request",__func__);
911        return rc;
912    }
913
914
915    if(!mMemory) {
916        ALOGE("%s: error, Gralloc Memory object not yet created for this stream",__func__);
917        return NO_MEMORY;
918    }
919
920    index = mMemory->getMatchBufIndex((void*)buffer);
921    if(index < 0) {
922        ALOGE("%s: Could not find object among registered buffers",__func__);
923        return DEAD_OBJECT;
924    }
925    rc = mMemory->markFrameNumber(index, frameNumber);
926
927    //Start the postprocessor for jpeg encoding. Pass mMemory as destination buffer
928    mCurrentBufIndex = index;
929    m_postprocessor.start(mMemory, index);
930    if(m_camOps->request_super_buf(m_camHandle,m_handle,1) < 0) {
931        ALOGE("%s: Request for super buffer failed",__func__);
932    }
933
934    return rc;
935}
936
937/*===========================================================================
938 * FUNCTION   : dataNotifyCB
939 *
940 * DESCRIPTION: Channel Level callback used for super buffer data notify.
941 *              This function is registered with mm-camera-interface to handle
942 *              data notify
943 *
944 * PARAMETERS :
945 *   @recvd_frame   : stream frame received
946 *   userdata       : user data ptr
947 *
948 * RETURN     : none
949 *==========================================================================*/
950void QCamera3PicChannel::dataNotifyCB(mm_camera_super_buf_t *recvd_frame,
951                                 void *userdata)
952{
953    ALOGV("%s: E\n", __func__);
954    QCamera3PicChannel *channel = (QCamera3PicChannel *)userdata;
955
956    if (channel == NULL) {
957        ALOGE("%s: invalid channel pointer", __func__);
958        return;
959    }
960
961    if(channel->m_numStreams != 1) {
962        ALOGE("%s: Error: Bug: This callback assumes one stream per channel",__func__);
963        return;
964    }
965
966
967    if(channel->mStreams[0] == NULL) {
968        ALOGE("%s: Error: Invalid Stream object",__func__);
969        return;
970    }
971
972    channel->QCamera3PicChannel::streamCbRoutine(recvd_frame, channel->mStreams[0]);
973
974    ALOGV("%s: X\n", __func__);
975    return;
976}
977
978
979int32_t QCamera3PicChannel::registerBuffers(uint32_t num_buffers,
980                        buffer_handle_t **buffers)
981{
982    int rc = 0;
983    cam_stream_type_t streamType;
984    cam_format_t streamFormat;
985
986    ALOGV("%s: E",__func__);
987    rc = QCamera3PicChannel::initialize();
988    if (rc < 0) {
989        ALOGE("%s: init failed", __func__);
990        return rc;
991    }
992
993    if (mCamera3Stream->format == HAL_PIXEL_FORMAT_BLOB) {
994        streamType = CAM_STREAM_TYPE_SNAPSHOT;
995        streamFormat = CAM_FORMAT_YUV_420_NV21;
996    } else {
997        //TODO: Fail for other types of streams for now
998        ALOGE("%s: format is not BLOB", __func__);
999        return -EINVAL;
1000    }
1001    /* Bookkeep buffer set because they go out of scope after register call */
1002    mNumBufs = num_buffers;
1003    mCamera3Buffers = new buffer_handle_t*[num_buffers];
1004    if (mCamera3Buffers == NULL) {
1005        ALOGE("%s: Failed to allocate buffer_handle_t*", __func__);
1006        return -ENOMEM;
1007    }
1008    for (size_t i = 0; i < num_buffers; i++)
1009        mCamera3Buffers[i] = buffers[i];
1010
1011    ALOGV("%s: X",__func__);
1012    return rc;
1013}
1014
1015void QCamera3PicChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
1016                            QCamera3Stream *stream)
1017{
1018    //TODO
1019    //Used only for getting YUV. Jpeg callback will be sent back from channel
1020    //directly to HWI. Refer to func jpegEvtHandle
1021
1022    //Got the yuv callback. Calling yuv callback handler in PostProc
1023    uint8_t frameIndex;
1024    mm_camera_super_buf_t* frame = NULL;
1025
1026    if(!super_frame) {
1027         ALOGE("%s: Invalid Super buffer",__func__);
1028         return;
1029    }
1030
1031    if(super_frame->num_bufs != 1) {
1032         ALOGE("%s: Multiple streams are not supported",__func__);
1033         return;
1034    }
1035    if(super_frame->bufs[0] == NULL ) {
1036         ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
1037                  __func__);
1038         return;
1039    }
1040
1041    frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
1042    if(frameIndex >= mNumBufs) {
1043         ALOGE("%s: Error, Invalid index for buffer",__func__);
1044         if(stream) {
1045             stream->bufDone(frameIndex);
1046         }
1047         return;
1048    }
1049
1050    frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
1051    if (frame == NULL) {
1052       ALOGE("%s: Error allocating memory to save received_frame structure.",
1053                                                                    __func__);
1054       if(stream) {
1055           stream->bufDone(frameIndex);
1056       }
1057       return;
1058    }
1059    *frame = *super_frame;
1060
1061    m_postprocessor.processData(frame);
1062    return;
1063}
1064
1065QCamera3Memory* QCamera3PicChannel::getStreamBufs(uint32_t len)
1066{
1067    int rc = 0;
1068
1069    if (mNumBufs == 0 || mCamera3Buffers == NULL) {
1070        ALOGE("%s: buffers not registered yet", __func__);
1071        return NULL;
1072    }
1073
1074    mMemory = new QCamera3GrallocMemory();
1075    if (mMemory == NULL) {
1076        return NULL;
1077    }
1078
1079    //Registering Jpeg output buffer
1080    if (mMemory->registerBuffers(mNumBufs, mCamera3Buffers) < 0) {
1081        delete mMemory;
1082        mMemory = NULL;
1083        return NULL;
1084    }
1085
1086    mYuvMemory = new QCamera3HeapMemory();
1087    if (!mYuvMemory) {
1088        ALOGE("%s: unable to create metadata memory", __func__);
1089        return NULL;
1090    }
1091
1092    //Queue YUV buffers in the beginning mQueueAll = true
1093    rc = mYuvMemory->allocate(1, len, true);
1094    if (rc < 0) {
1095        ALOGE("%s: unable to allocate metadata memory", __func__);
1096        delete mYuvMemory;
1097        mYuvMemory = NULL;
1098        return NULL;
1099    }
1100    return mYuvMemory;
1101}
1102
1103void QCamera3PicChannel::putStreamBufs()
1104{
1105    mMemory->unregisterBuffers();
1106    delete mMemory;
1107    mMemory = NULL;
1108
1109    mYuvMemory->deallocate();
1110    delete mYuvMemory;
1111    mYuvMemory = NULL;
1112}
1113
1114/*===========================================================================
1115 * FUNCTION   : needRotationReprocess
1116 *
1117 * DESCRIPTION: if online rotation needs to be done by cpp
1118 *
1119 * PARAMETERS : none
1120 *
1121 * RETURN     : true: needed
1122 *              false: no need
1123 *==========================================================================*/
1124bool QCamera3PicChannel::needOnlineRotation()
1125{
1126    //TODO: For B Family chips, we need to do something different
1127    // because JPEG encoder cannot do rotation.
1128    return false;
1129}
1130
1131/*===========================================================================
1132 * FUNCTION   : getThumbnailSize
1133 *
1134 * DESCRIPTION: get user set thumbnail size
1135 *
1136 * PARAMETERS :
1137 *   @dim     : output of thumbnail dimension
1138 *
1139 * RETURN     : none
1140 *==========================================================================*/
1141void QCamera3PicChannel::getThumbnailSize(cam_dimension_t &dim)
1142{
1143    dim = mJpegSettings->thumbnail_size;
1144}
1145
1146/*===========================================================================
1147 * FUNCTION   : getJpegQuality
1148 *
1149 * DESCRIPTION: get user set jpeg quality
1150 *
1151 * PARAMETERS : none
1152 *
1153 * RETURN     : jpeg quality setting
1154 *==========================================================================*/
1155int QCamera3PicChannel::getJpegQuality()
1156{
1157    int quality = mJpegSettings->jpeg_quality;
1158    if (quality < 0) {
1159        quality = 85;  //set to default quality value
1160    }
1161    return quality;
1162}
1163
1164/*===========================================================================
1165 * FUNCTION   : getJpegRotation
1166 *
1167 * DESCRIPTION: get rotation information to be passed into jpeg encoding
1168 *
1169 * PARAMETERS : none
1170 *
1171 * RETURN     : rotation information
1172 *==========================================================================*/
1173int QCamera3PicChannel::getJpegRotation() {
1174    int rotation = mJpegSettings->jpeg_orientation;
1175    if (rotation < 0) {
1176        rotation = 0;
1177    }
1178    return rotation;
1179}
1180
1181/*===========================================================================
1182 * FUNCTION   : getRational
1183 *
1184 * DESCRIPTION: compose rational struct
1185 *
1186 * PARAMETERS :
1187 *   @rat     : ptr to struct to store rational info
1188 *   @num     :num of the rational
1189 *   @denom   : denom of the rational
1190 *
1191 * RETURN     : int32_t type of status
1192 *              NO_ERROR  -- success
1193 *              none-zero failure code
1194 *==========================================================================*/
1195int32_t getRational(rat_t *rat, int num, int denom)
1196{
1197    if (NULL == rat) {
1198        ALOGE("%s: NULL rat input", __func__);
1199        return BAD_VALUE;
1200    }
1201    rat->num = num;
1202    rat->denom = denom;
1203    return NO_ERROR;
1204}
1205
1206/*===========================================================================
1207 * FUNCTION   : parseGPSCoordinate
1208 *
1209 * DESCRIPTION: parse GPS coordinate string
1210 *
1211 * PARAMETERS :
1212 *   @coord_str : [input] coordinate string
1213 *   @coord     : [output]  ptr to struct to store coordinate
1214 *
1215 * RETURN     : int32_t type of status
1216 *              NO_ERROR  -- success
1217 *              none-zero failure code
1218 *==========================================================================*/
1219int parseGPSCoordinate(const char *coord_str, rat_t* coord)
1220{
1221    if(coord == NULL) {
1222        ALOGE("%s: error, invalid argument coord == NULL", __func__);
1223        return BAD_VALUE;
1224    }
1225    float degF = atof(coord_str);
1226    if (degF < 0) {
1227        degF = -degF;
1228    }
1229    float minF = (degF - (int) degF) * 60;
1230    float secF = (minF - (int) minF) * 60;
1231
1232    getRational(&coord[0], (int)degF, 1);
1233    getRational(&coord[1], (int)minF, 1);
1234    getRational(&coord[2], (int)(secF * 10000), 10000);
1235    return NO_ERROR;
1236}
1237
1238/*===========================================================================
1239 * FUNCTION   : getExifDateTime
1240 *
1241 * DESCRIPTION: query exif date time
1242 *
1243 * PARAMETERS :
1244 *   @dateTime : string to store exif date time
1245 *   @count    : lenght of the dateTime string
1246 *
1247 * RETURN     : int32_t type of status
1248 *              NO_ERROR  -- success
1249 *              none-zero failure code
1250 *==========================================================================*/
1251int32_t getExifDateTime(char *dateTime, uint32_t &count)
1252{
1253    //get time and date from system
1254    time_t rawtime;
1255    struct tm * timeinfo;
1256    time(&rawtime);
1257    timeinfo = localtime (&rawtime);
1258    //Write datetime according to EXIF Spec
1259    //"YYYY:MM:DD HH:MM:SS" (20 chars including \0)
1260    snprintf(dateTime, 20, "%04d:%02d:%02d %02d:%02d:%02d",
1261             timeinfo->tm_year + 1900, timeinfo->tm_mon + 1,
1262             timeinfo->tm_mday, timeinfo->tm_hour,
1263             timeinfo->tm_min, timeinfo->tm_sec);
1264    count = 20;
1265
1266    return NO_ERROR;
1267}
1268
1269/*===========================================================================
1270 * FUNCTION   : getExifFocalLength
1271 *
1272 * DESCRIPTION: get exif focal lenght
1273 *
1274 * PARAMETERS :
1275 *   @focalLength : ptr to rational strcut to store focal lenght
1276 *
1277 * RETURN     : int32_t type of status
1278 *              NO_ERROR  -- success
1279 *              none-zero failure code
1280 *==========================================================================*/
1281int32_t getExifFocalLength(rat_t *focalLength, float value)
1282{
1283    int focalLengthValue =
1284        (int)(value * FOCAL_LENGTH_DECIMAL_PRECISION);
1285    return getRational(focalLength, focalLengthValue, FOCAL_LENGTH_DECIMAL_PRECISION);
1286}
1287
1288/*===========================================================================
1289 * FUNCTION   : getExifGpsProcessingMethod
1290 *
1291 * DESCRIPTION: get GPS processing method
1292 *
1293 * PARAMETERS :
1294 *   @gpsProcessingMethod : string to store GPS process method
1295 *   @count               : lenght of the string
1296 *
1297 * RETURN     : int32_t type of status
1298 *              NO_ERROR  -- success
1299 *              none-zero failure code
1300 *==========================================================================*/
1301int32_t getExifGpsProcessingMethod(char *gpsProcessingMethod,
1302                                   uint32_t &count, char* value)
1303{
1304    if(value != NULL) {
1305        memcpy(gpsProcessingMethod, ExifAsciiPrefix, EXIF_ASCII_PREFIX_SIZE);
1306        count = EXIF_ASCII_PREFIX_SIZE;
1307        strncpy(gpsProcessingMethod + EXIF_ASCII_PREFIX_SIZE, value, strlen(value));
1308        count += strlen(value);
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
1453int32_t getExifExposureValue(srat_t* exposure_val, int32_t exposure_comp,
1454                             cam_rational_type_t step)
1455{
1456    exposure_val->num = exposure_comp * step.numerator;
1457    exposure_val->denom = step.denominator;
1458    return 0;
1459}
1460/*===========================================================================
1461 * FUNCTION   : getExifData
1462 *
1463 * DESCRIPTION: get exif data to be passed into jpeg encoding
1464 *
1465 * PARAMETERS : none
1466 *
1467 * RETURN     : exif data from user setting and GPS
1468 *==========================================================================*/
1469QCamera3Exif *QCamera3PicChannel::getExifData()
1470{
1471    QCamera3Exif *exif = new QCamera3Exif();
1472    if (exif == NULL) {
1473        ALOGE("%s: No memory for QCamera3Exif", __func__);
1474        return NULL;
1475    }
1476
1477    int32_t rc = NO_ERROR;
1478    uint32_t count = 0;
1479
1480    // add exif entries
1481    char dateTime[20];
1482    memset(dateTime, 0, sizeof(dateTime));
1483    count = 20;
1484    rc = getExifDateTime(dateTime, count);
1485    if(rc == NO_ERROR) {
1486        exif->addEntry(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL,
1487                       EXIF_ASCII,
1488                       count,
1489                       (void *)dateTime);
1490    } else {
1491        ALOGE("%s: getExifDateTime failed", __func__);
1492    }
1493
1494    rat_t focalLength;
1495    rc = getExifFocalLength(&focalLength, mJpegSettings->lens_focal_length);
1496    if (rc == NO_ERROR) {
1497        exif->addEntry(EXIFTAGID_FOCAL_LENGTH,
1498                       EXIF_RATIONAL,
1499                       1,
1500                       (void *)&(focalLength));
1501    } else {
1502        ALOGE("%s: getExifFocalLength failed", __func__);
1503    }
1504
1505    uint16_t isoSpeed = (uint16_t)mJpegSettings->sensor_sensitivity;
1506    exif->addEntry(EXIFTAGID_ISO_SPEED_RATING,
1507                   EXIF_SHORT,
1508                   1,
1509                   (void *)&(isoSpeed));
1510
1511
1512    if (strlen(mJpegSettings->gps_processing_method) > 0) {
1513        char gpsProcessingMethod[EXIF_ASCII_PREFIX_SIZE + GPS_PROCESSING_METHOD_SIZE];
1514        count = 0;
1515        rc = getExifGpsProcessingMethod(gpsProcessingMethod, count, mJpegSettings->gps_processing_method);
1516        if(rc == NO_ERROR) {
1517            exif->addEntry(EXIFTAGID_GPS_PROCESSINGMETHOD,
1518                           EXIF_ASCII,
1519                           count,
1520                           (void *)gpsProcessingMethod);
1521        } else {
1522            ALOGE("%s: getExifGpsProcessingMethod failed", __func__);
1523        }
1524    }
1525
1526    if (mJpegSettings->gps_coordinates[0]) {
1527        rat_t latitude[3];
1528        char latRef[2];
1529        rc = getExifLatitude(latitude, latRef, *(mJpegSettings->gps_coordinates[0]));
1530        if(rc == NO_ERROR) {
1531            exif->addEntry(EXIFTAGID_GPS_LATITUDE,
1532                           EXIF_RATIONAL,
1533                           3,
1534                           (void *)latitude);
1535            exif->addEntry(EXIFTAGID_GPS_LATITUDE_REF,
1536                           EXIF_ASCII,
1537                           2,
1538                           (void *)latRef);
1539        } else {
1540            ALOGE("%s: getExifLatitude failed", __func__);
1541        }
1542    }
1543
1544    if (mJpegSettings->gps_coordinates[1]) {
1545        rat_t longitude[3];
1546        char lonRef[2];
1547        rc = getExifLongitude(longitude, lonRef, *(mJpegSettings->gps_coordinates[1]));
1548        if(rc == NO_ERROR) {
1549            exif->addEntry(EXIFTAGID_GPS_LONGITUDE,
1550                           EXIF_RATIONAL,
1551                           3,
1552                           (void *)longitude);
1553
1554            exif->addEntry(EXIFTAGID_GPS_LONGITUDE_REF,
1555                           EXIF_ASCII,
1556                           2,
1557                           (void *)lonRef);
1558        } else {
1559            ALOGE("%s: getExifLongitude failed", __func__);
1560        }
1561    }
1562
1563    if (mJpegSettings->gps_coordinates[2]) {
1564        rat_t altitude;
1565        char altRef;
1566        rc = getExifAltitude(&altitude, &altRef, *(mJpegSettings->gps_coordinates[2]));
1567        if(rc == NO_ERROR) {
1568            exif->addEntry(EXIFTAGID_GPS_ALTITUDE,
1569                           EXIF_RATIONAL,
1570                           1,
1571                           (void *)&(altitude));
1572
1573            exif->addEntry(EXIFTAGID_GPS_ALTITUDE_REF,
1574                           EXIF_BYTE,
1575                           1,
1576                           (void *)&altRef);
1577        } else {
1578            ALOGE("%s: getExifAltitude failed", __func__);
1579        }
1580    }
1581
1582    if (mJpegSettings->gps_timestamp) {
1583        char gpsDateStamp[20];
1584        rat_t gpsTimeStamp[3];
1585        rc = getExifGpsDateTimeStamp(gpsDateStamp, 20, gpsTimeStamp, *(mJpegSettings->gps_timestamp));
1586        if(rc == NO_ERROR) {
1587            exif->addEntry(EXIFTAGID_GPS_DATESTAMP,
1588                           EXIF_ASCII,
1589                           strlen(gpsDateStamp) + 1,
1590                           (void *)gpsDateStamp);
1591
1592            exif->addEntry(EXIFTAGID_GPS_TIMESTAMP,
1593                           EXIF_RATIONAL,
1594                           3,
1595                           (void *)gpsTimeStamp);
1596        } else {
1597            ALOGE("%s: getExifGpsDataTimeStamp failed", __func__);
1598        }
1599    }
1600
1601    srat_t exposure_val;
1602    rc = getExifExposureValue(&exposure_val, mJpegSettings->exposure_compensation,
1603                              mJpegSettings->exposure_comp_step);
1604    if(rc == NO_ERROR) {
1605        exif->addEntry(EXIFTAGID_EXPOSURE_BIAS_VALUE,
1606                       EXIF_SRATIONAL,
1607                       1,
1608                       (void *)(&exposure_val));
1609    } else {
1610        ALOGE("%s: getExifExposureValue failed ", __func__);
1611    }
1612
1613    char value[PROPERTY_VALUE_MAX];
1614    if (property_get("ro.product.manufacturer", value, "QCOM-AA") > 0) {
1615        exif->addEntry(EXIFTAGID_MAKE,
1616                       EXIF_ASCII,
1617                       strlen(value) + 1,
1618                       (void *)value);
1619    } else {
1620        ALOGE("%s: getExifMaker failed", __func__);
1621    }
1622
1623    if (property_get("ro.product.model", value, "QCAM-AA") > 0) {
1624        exif->addEntry(EXIFTAGID_MODEL,
1625                       EXIF_ASCII,
1626                       strlen(value) + 1,
1627                       (void *)value);
1628    } else {
1629        ALOGE("%s: getExifModel failed", __func__);
1630    }
1631
1632    return exif;
1633}
1634
1635int QCamera3PicChannel::kMaxBuffers = 2;
1636}; // namespace qcamera
1637