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