QCamera3Channel.cpp revision c8d1059ae679132e7654708fdfca6ee221775187
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   : getInternalFormatBuffer
324 *
325 * DESCRIPTION: return buffer in the internal format structure
326 *
327 * PARAMETERS :
328 *   @streamHandle : buffer handle
329 *
330 * RETURN     : stream object. NULL if not found
331 *==========================================================================*/
332mm_camera_buf_def_t* QCamera3RegularChannel::getInternalFormatBuffer(
333                                            buffer_handle_t * buffer)
334{
335    int32_t index;
336    if(buffer == NULL)
337        return NULL;
338    index = mMemory->getMatchBufIndex((void*)buffer);
339    if(index < 0) {
340        ALOGE("%s: Could not find object among registered buffers",__func__);
341        return NULL;
342    }
343    return mStreams[0]->getInternalFormatBuffer(index);
344}
345
346/*===========================================================================
347 * FUNCTION   : getStreamByHandle
348 *
349 * DESCRIPTION: return stream object by stream handle
350 *
351 * PARAMETERS :
352 *   @streamHandle : stream handle
353 *
354 * RETURN     : stream object. NULL if not found
355 *==========================================================================*/
356QCamera3Stream *QCamera3Channel::getStreamByHandle(uint32_t streamHandle)
357{
358    for (int i = 0; i < m_numStreams; i++) {
359        if (mStreams[i] != NULL && mStreams[i]->getMyHandle() == streamHandle) {
360            return mStreams[i];
361        }
362    }
363    return NULL;
364}
365
366/*===========================================================================
367 * FUNCTION   : getStreamByHandle
368 *
369 * DESCRIPTION: return stream object by stream handle
370 *
371 * PARAMETERS :
372 *   @streamHandle : stream handle
373 *
374 * RETURN     : stream object. NULL if not found
375 *==========================================================================*/
376QCamera3Stream *QCamera3Channel::getStreamByIndex(uint8_t index)
377{
378    if (index < m_numStreams) {
379        return mStreams[index];
380    }
381    return NULL;
382}
383
384/*===========================================================================
385 * FUNCTION   : streamCbRoutine
386 *
387 * DESCRIPTION: callback routine for stream
388 *
389 * PARAMETERS :
390 *   @streamHandle : stream handle
391 *
392 * RETURN     : stream object. NULL if not found
393 *==========================================================================*/
394void QCamera3Channel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
395                QCamera3Stream *stream, void *userdata)
396{
397    QCamera3Channel *channel = (QCamera3Channel *)userdata;
398    if (channel == NULL) {
399        ALOGE("%s: invalid channel pointer", __func__);
400        return;
401    }
402    channel->streamCbRoutine(super_frame, stream);
403}
404
405/*===========================================================================
406 * FUNCTION   : QCamera3RegularChannel
407 *
408 * DESCRIPTION: constrcutor of QCamera3RegularChannel
409 *
410 * PARAMETERS :
411 *   @cam_handle : camera handle
412 *   @cam_ops    : ptr to camera ops table
413 *   @cb_routine : callback routine to frame aggregator
414 *   @stream     : camera3_stream_t structure
415 *
416 * RETURN     : none
417 *==========================================================================*/
418QCamera3RegularChannel::QCamera3RegularChannel(uint32_t cam_handle,
419                    mm_camera_ops_t *cam_ops,
420                    channel_cb_routine cb_routine,
421                    cam_padding_info_t *paddingInfo,
422                    void *userData,
423                    camera3_stream_t *stream) :
424                        QCamera3Channel(cam_handle, cam_ops, cb_routine,
425                                                paddingInfo, userData),
426                        mCamera3Stream(stream),
427                        mNumBufs(0),
428                        mCamera3Buffers(NULL),
429                        mMemory(NULL),
430                        mWidth(stream->width),
431                        mHeight(stream->height)
432{
433}
434
435/*===========================================================================
436 * FUNCTION   : QCamera3RegularChannel
437 *
438 * DESCRIPTION: constrcutor of QCamera3RegularChannel
439 *
440 * PARAMETERS :
441 *   @cam_handle : camera handle
442 *   @cam_ops    : ptr to camera ops table
443 *   @cb_routine : callback routine to frame aggregator
444 *   @stream     : camera3_stream_t structure
445 *
446 * RETURN     : none
447 *==========================================================================*/
448QCamera3RegularChannel::QCamera3RegularChannel(uint32_t cam_handle,
449                    mm_camera_ops_t *cam_ops,
450                    channel_cb_routine cb_routine,
451                    cam_padding_info_t *paddingInfo,
452                    void *userData,
453                    camera3_stream_t *stream,
454                    uint32_t width, uint32_t height) :
455                        QCamera3Channel(cam_handle, cam_ops, cb_routine,
456                                                paddingInfo, userData),
457                        mCamera3Stream(stream),
458                        mNumBufs(0),
459                        mCamera3Buffers(NULL),
460                        mMemory(NULL),
461                        mWidth(width),
462                        mHeight(height)
463{
464}
465
466/*===========================================================================
467 * FUNCTION   : ~QCamera3RegularChannel
468 *
469 * DESCRIPTION: destructor of QCamera3RegularChannel
470 *
471 * PARAMETERS : none
472 *
473 * RETURN     : none
474 *==========================================================================*/
475QCamera3RegularChannel::~QCamera3RegularChannel()
476{
477    if (mCamera3Buffers) {
478        delete[] mCamera3Buffers;
479    }
480}
481
482int32_t QCamera3RegularChannel::initialize()
483{
484  //TO DO
485  return 0;
486}
487
488/*===========================================================================
489 * FUNCTION   : request
490 *
491 * DESCRIPTION: process a request from camera service. Stream on if ncessary.
492 *
493 * PARAMETERS :
494 *   @buffer  : buffer to be filled for this request
495 *
496 * RETURN     : 0 on a success start of capture
497 *              -EINVAL on invalid input
498 *              -ENODEV on serious error
499 *==========================================================================*/
500int32_t QCamera3RegularChannel::request(buffer_handle_t *buffer, uint32_t frameNumber)
501{
502    //FIX ME: Return buffer back in case of failures below.
503
504    int32_t rc = NO_ERROR;
505    int index;
506    if(!m_bIsActive) {
507        ALOGD("%s: First request on this channel starting stream",__func__);
508        start();
509        if(rc != NO_ERROR) {
510            ALOGE("%s: Failed to start the stream on the request",__func__);
511            return rc;
512        }
513    } else {
514        ALOGV("%s: Request on an existing stream",__func__);
515    }
516
517    if(!mMemory) {
518        ALOGE("%s: error, Gralloc Memory object not yet created for this stream",__func__);
519        return NO_MEMORY;
520    }
521
522    index = mMemory->getMatchBufIndex((void*)buffer);
523    if(index < 0) {
524        ALOGE("%s: Could not find object among registered buffers",__func__);
525        return DEAD_OBJECT;
526    }
527
528    rc = mStreams[0]->bufDone(index);
529    if(rc != NO_ERROR) {
530        ALOGE("%s: Failed to Q new buffer to stream",__func__);
531        return rc;
532    }
533
534    rc = mMemory->markFrameNumber(index, frameNumber);
535    return rc;
536}
537
538/*===========================================================================
539 * FUNCTION   : registerBuffers
540 *
541 * DESCRIPTION: register streaming buffers to the channel object
542 *
543 * PARAMETERS :
544 *   @num_buffers : number of buffers to be registered
545 *   @buffers     : buffer to be registered
546 *
547 * RETURN     : 0 on a success start of capture
548 *              -EINVAL on invalid input
549 *              -ENOMEM on failure to register the buffer
550 *              -ENODEV on serious error
551 *==========================================================================*/
552int32_t QCamera3RegularChannel::registerBuffers(uint32_t num_buffers, buffer_handle_t **buffers)
553{
554    int rc = 0;
555    struct private_handle_t *priv_handle = (struct private_handle_t *)(*buffers[0]);
556    cam_stream_type_t streamType;
557    cam_format_t streamFormat;
558    cam_dimension_t streamDim;
559
560    rc = init(NULL, NULL);
561    if (rc < 0) {
562        ALOGE("%s: init failed", __func__);
563        return rc;
564    }
565
566    if (mCamera3Stream->format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
567        if (priv_handle->flags & private_handle_t::PRIV_FLAGS_VIDEO_ENCODER) {
568            streamType = CAM_STREAM_TYPE_VIDEO;
569            streamFormat = CAM_FORMAT_YUV_420_NV12;
570        } else if (priv_handle->flags & private_handle_t::PRIV_FLAGS_HW_TEXTURE) {
571            streamType = CAM_STREAM_TYPE_PREVIEW;
572            streamFormat = CAM_FORMAT_YUV_420_NV21;
573        } else {
574            //TODO: Add a new flag in libgralloc for ZSL buffers, and its size needs
575            // to be properly aligned and padded.
576            ALOGE("%s: priv_handle->flags 0x%x not supported",
577                    __func__, priv_handle->flags);
578            streamType = CAM_STREAM_TYPE_SNAPSHOT;
579            streamFormat = CAM_FORMAT_YUV_420_NV21;
580        }
581    } else if(mCamera3Stream->format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
582         streamType = CAM_STREAM_TYPE_PREVIEW;
583         streamFormat = CAM_FORMAT_YUV_420_NV21;
584    } else {
585        //TODO: Fail for other types of streams for now
586        ALOGE("%s: format is not IMPLEMENTATION_DEFINED or flexible", __func__);
587        return -EINVAL;
588    }
589
590    /* Bookkeep buffer set because they go out of scope after register call */
591    mNumBufs = num_buffers;
592    mCamera3Buffers = new buffer_handle_t*[num_buffers];
593    if (mCamera3Buffers == NULL) {
594        ALOGE("%s: Failed to allocate buffer_handle_t*", __func__);
595        return -ENOMEM;
596    }
597    for (size_t i = 0; i < num_buffers; i++)
598        mCamera3Buffers[i] = buffers[i];
599
600    streamDim.width = mWidth;
601    streamDim.height = mHeight;
602
603    rc = QCamera3Channel::addStream(streamType, streamFormat, streamDim,
604        num_buffers);
605    return rc;
606}
607
608void QCamera3RegularChannel::streamCbRoutine(
609                            mm_camera_super_buf_t *super_frame,
610                            QCamera3Stream *stream)
611{
612    //FIXME Q Buf back in case of error?
613    uint8_t frameIndex;
614    buffer_handle_t *resultBuffer;
615    int32_t resultFrameNumber;
616    camera3_stream_buffer_t result;
617
618    if(!super_frame) {
619         ALOGE("%s: Invalid Super buffer",__func__);
620         return;
621    }
622
623    if(super_frame->num_bufs != 1) {
624         ALOGE("%s: Multiple streams are not supported",__func__);
625         return;
626    }
627    if(super_frame->bufs[0] == NULL ) {
628         ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
629                  __func__);
630         return;
631    }
632
633    frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
634    if(frameIndex >= mNumBufs) {
635         ALOGE("%s: Error, Invalid index for buffer",__func__);
636         if(stream) {
637             stream->bufDone(frameIndex);
638         }
639         return;
640    }
641
642    ////Use below data to issue framework callback
643    resultBuffer = mCamera3Buffers[frameIndex];
644    resultFrameNumber = mMemory->getFrameNumber(frameIndex);
645
646    result.stream = mCamera3Stream;
647    result.buffer = resultBuffer;
648    result.status = CAMERA3_BUFFER_STATUS_OK;
649    result.acquire_fence = -1;
650    result.release_fence = -1;
651
652    mChannelCB(NULL, &result, resultFrameNumber, mUserData);
653    return;
654}
655
656QCamera3Memory* QCamera3RegularChannel::getStreamBufs(uint32_t /*len*/)
657{
658    if (mNumBufs == 0 || mCamera3Buffers == NULL) {
659        ALOGE("%s: buffers not registered yet", __func__);
660        return NULL;
661    }
662
663    mMemory = new QCamera3GrallocMemory();
664    if (mMemory == NULL) {
665        return NULL;
666    }
667
668    if (mMemory->registerBuffers(mNumBufs, mCamera3Buffers) < 0) {
669        delete mMemory;
670        mMemory = NULL;
671        return NULL;
672    }
673    return mMemory;
674}
675
676void QCamera3RegularChannel::putStreamBufs()
677{
678    mMemory->unregisterBuffers();
679    delete mMemory;
680    mMemory = NULL;
681}
682
683int QCamera3RegularChannel::kMaxBuffers = 7;
684
685QCamera3MetadataChannel::QCamera3MetadataChannel(uint32_t cam_handle,
686                    mm_camera_ops_t *cam_ops,
687                    channel_cb_routine cb_routine,
688                    cam_padding_info_t *paddingInfo,
689                    void *userData) :
690                        QCamera3Channel(cam_handle, cam_ops,
691                                cb_routine, paddingInfo, userData),
692                        mMemory(NULL)
693{
694}
695
696QCamera3MetadataChannel::~QCamera3MetadataChannel()
697{
698    if (m_bIsActive)
699        stop();
700
701    if (mMemory) {
702        mMemory->deallocate();
703        delete mMemory;
704        mMemory = NULL;
705    }
706}
707
708int32_t QCamera3MetadataChannel::initialize()
709{
710    int32_t rc;
711    cam_dimension_t streamDim;
712
713    if (mMemory || m_numStreams > 0) {
714        ALOGE("%s: metadata channel already initialized", __func__);
715        return -EINVAL;
716    }
717
718    rc = init(NULL, NULL);
719    if (rc < 0) {
720        ALOGE("%s: init failed", __func__);
721        return rc;
722    }
723
724    streamDim.width = sizeof(metadata_buffer_t),
725    streamDim.height = 1;
726    rc = QCamera3Channel::addStream(CAM_STREAM_TYPE_METADATA, CAM_FORMAT_MAX,
727        streamDim, MIN_STREAMING_BUFFER_NUM);
728    if (rc < 0) {
729        ALOGE("%s: addStream failed", __func__);
730    }
731    return rc;
732}
733
734int32_t QCamera3MetadataChannel::request(buffer_handle_t * /*buffer*/,
735                                                uint32_t /*frameNumber*/)
736{
737    if (!m_bIsActive) {
738        return start();
739    }
740    else
741        return 0;
742}
743
744int32_t QCamera3MetadataChannel::registerBuffers(uint32_t /*num_buffers*/,
745                                        buffer_handle_t ** /*buffers*/)
746{
747    // no registerBuffers are supported for metadata channel
748    return -EINVAL;
749}
750
751void QCamera3MetadataChannel::streamCbRoutine(
752                        mm_camera_super_buf_t *super_frame,
753                        QCamera3Stream *stream)
754{
755    uint32_t requestNumber = 0;
756    if (super_frame == NULL || super_frame->num_bufs != 1) {
757        ALOGE("%s: super_frame is not valid", __func__);
758        return;
759    }
760    mChannelCB(super_frame, NULL, requestNumber, mUserData);
761
762    //Return the buffer
763    stream->bufDone(super_frame->bufs[0]->buf_idx);
764}
765
766QCamera3Memory* QCamera3MetadataChannel::getStreamBufs(uint32_t len)
767{
768    int rc;
769    if (len < sizeof(metadata_buffer_t)) {
770        ALOGE("%s: size doesn't match %d vs %d", __func__,
771                len, sizeof(metadata_buffer_t));
772        return NULL;
773    }
774    mMemory = new QCamera3HeapMemory();
775    if (!mMemory) {
776        ALOGE("%s: unable to create metadata memory", __func__);
777        return NULL;
778    }
779    rc = mMemory->allocate(MIN_STREAMING_BUFFER_NUM, len, true);
780    if (rc < 0) {
781        ALOGE("%s: unable to allocate metadata memory", __func__);
782        delete mMemory;
783        mMemory = NULL;
784        return NULL;
785    }
786    memset(mMemory->getPtr(0), 0, sizeof(metadata_buffer_t));
787    return mMemory;
788}
789
790void QCamera3MetadataChannel::putStreamBufs()
791{
792    mMemory->deallocate();
793    delete mMemory;
794    mMemory = NULL;
795}
796
797/*===========================================================================
798 * FUNCTION   : jpegEvtHandle
799 *
800 * DESCRIPTION: Function registerd to mm-jpeg-interface to handle jpeg events.
801                Construct result payload and call mChannelCb to deliver buffer
802                to framework.
803 *
804 * PARAMETERS :
805 *   @status    : status of jpeg job
806 *   @client_hdl: jpeg client handle
807 *   @jobId     : jpeg job Id
808 *   @p_ouput   : ptr to jpeg output result struct
809 *   @userdata  : user data ptr
810 *
811 * RETURN     : none
812 *==========================================================================*/
813void QCamera3PicChannel::jpegEvtHandle(jpeg_job_status_t status,
814                                              uint32_t /*client_hdl*/,
815                                              uint32_t jobId,
816                                              mm_jpeg_output_t *p_output,
817                                              void *userdata)
818{
819    buffer_handle_t *resultBuffer;
820    int32_t resultFrameNumber;
821    int resultStatus = CAMERA3_BUFFER_STATUS_OK;
822    camera3_stream_buffer_t result;
823    camera3_jpeg_blob_t jpegHeader;
824    char* jpeg_eof = 0;
825    int maxJpegSize;
826    QCamera3PicChannel *obj = (QCamera3PicChannel *)userdata;
827    if (obj) {
828        //Construct payload for process_capture_result. Call mChannelCb
829
830        qcamera_jpeg_data_t *job = obj->m_postprocessor.findJpegJobByJobId(jobId);
831
832        if ((job == NULL) || (status == JPEG_JOB_STATUS_ERROR)) {
833            ALOGE("%s: Error in jobId: (%d) with status: %d", __func__, jobId, status);
834            resultStatus = CAMERA3_BUFFER_STATUS_ERROR;
835        }
836
837        //Construct jpeg transient header of type camera3_jpeg_blob_t
838        //Append at the end of jpeg image of buf_filled_len size
839
840        jpegHeader.jpeg_blob_id = CAMERA3_JPEG_BLOB_ID;
841        jpegHeader.jpeg_size = p_output->buf_filled_len;
842
843
844        char* jpeg_buf = (char *)p_output->buf_vaddr;
845
846        if(obj->mJpegSettings->max_jpeg_size <= 0 ||
847                obj->mJpegSettings->max_jpeg_size > obj->mMemory->getSize(obj->mCurrentBufIndex)){
848            ALOGE("%s:Max Jpeg size :%d is out of valid range setting to size of buffer",
849                    __func__, obj->mJpegSettings->max_jpeg_size);
850            maxJpegSize =  obj->mMemory->getSize(obj->mCurrentBufIndex);
851        } else {
852            maxJpegSize = obj->mJpegSettings->max_jpeg_size;
853            ALOGE("%s: Setting max jpeg size to %d",__func__, maxJpegSize);
854        }
855        jpeg_eof = &jpeg_buf[maxJpegSize-sizeof(jpegHeader)];
856        memcpy(jpeg_eof, &jpegHeader, sizeof(jpegHeader));
857        obj->mMemory->cleanInvalidateCache(obj->mCurrentBufIndex);
858
859        ////Use below data to issue framework callback
860        resultBuffer = obj->mCamera3Buffers[obj->mCurrentBufIndex];
861        resultFrameNumber = obj->mMemory->getFrameNumber(obj->mCurrentBufIndex);
862
863        result.stream = obj->mCamera3Stream;
864        result.buffer = resultBuffer;
865        result.status = resultStatus;
866        result.acquire_fence = -1;
867        result.release_fence = -1;
868
869        ALOGV("%s: Issue Callback", __func__);
870        obj->mChannelCB(NULL, &result, resultFrameNumber, obj->mUserData);
871
872        // release internal data for jpeg job
873        if (job != NULL) {
874            obj->m_postprocessor.releaseJpegJobData(job);
875            free(job);
876        }
877        return;
878        // }
879    } else {
880        ALOGE("%s: Null userdata in jpeg callback", __func__);
881    }
882}
883
884QCamera3PicChannel::QCamera3PicChannel(uint32_t cam_handle,
885                    mm_camera_ops_t *cam_ops,
886                    channel_cb_routine cb_routine,
887                    cam_padding_info_t *paddingInfo,
888                    void *userData,
889                    camera3_stream_t *stream) :
890                        QCamera3Channel(cam_handle, cam_ops, cb_routine,
891                        paddingInfo, userData),
892                        mCamera3Stream(stream),
893                        mNumBufs(0),
894                        mCamera3Buffers(NULL),
895                        mJpegSettings(NULL),
896                        mCurrentBufIndex(-1),
897                        mMemory(NULL),
898                        mYuvMemory(NULL),
899                        m_postprocessor(this)
900{
901    int32_t rc = m_postprocessor.init(jpegEvtHandle, this);
902    if (rc != 0) {
903        ALOGE("Init Postprocessor failed");
904    }
905}
906
907QCamera3PicChannel::~QCamera3PicChannel()
908{
909    int32_t rc = m_postprocessor.deinit();
910    if (rc != 0) {
911        ALOGE("De-init Postprocessor failed");
912    }
913    if (mCamera3Buffers) {
914        delete[] mCamera3Buffers;
915    }
916}
917
918int32_t QCamera3PicChannel::initialize()
919{
920    int32_t rc = NO_ERROR;
921    cam_dimension_t streamDim;
922    cam_stream_type_t streamType;
923    cam_format_t streamFormat;
924    mm_camera_channel_attr_t attr;
925
926    memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
927    attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_BURST;
928    attr.look_back = 1;
929    attr.post_frame_skip = 1;
930    attr.water_mark = 1;
931    attr.max_unmatched_frames = 1;
932
933    rc = init(&attr, NULL);
934    if (rc < 0) {
935        ALOGE("%s: init failed", __func__);
936        return rc;
937    }
938
939    streamType = CAM_STREAM_TYPE_SNAPSHOT;
940    streamFormat = CAM_FORMAT_YUV_420_NV21;
941    streamDim.width = mCamera3Stream->width;
942    streamDim.height = mCamera3Stream->height;
943
944    int num_buffers = 1;
945
946    rc = QCamera3Channel::addStream(streamType, streamFormat, streamDim,
947            num_buffers);
948
949
950    return rc;
951}
952
953int32_t QCamera3PicChannel::request(buffer_handle_t *buffer,
954        uint32_t frameNumber, jpeg_settings_t* jpegSettings,
955        mm_camera_buf_def_t *pInputBuffer,QCamera3Channel* pInputChannel)
956{
957    //FIX ME: Return buffer back in case of failures below.
958
959    int32_t rc = NO_ERROR;
960    int index;
961    mJpegSettings = jpegSettings;
962    if(!m_bIsActive) {
963        ALOGD("%s: First request on this channel starting stream",__func__);
964        //Stream on for main image. YUV buffer is queued to the kernel at the end of this call.
965        if(!pInputBuffer)
966            rc = start();
967        else
968            ALOGD("%s: Current request has input buffer no need to start h/w stream", __func__);
969    } else {
970        mStreams[0]->bufDone(0);
971        ALOGD("%s: Request on an existing stream",__func__);
972    }
973
974    if(rc != NO_ERROR) {
975        ALOGE("%s: Failed to start the stream on the request",__func__);
976        return rc;
977    }
978
979
980    if(!mMemory) {
981        if(pInputBuffer) {
982            mMemory = new QCamera3GrallocMemory();
983            if (mMemory == NULL) {
984                return NO_MEMORY;
985            }
986
987            //Registering Jpeg output buffer
988            if (mMemory->registerBuffers(mNumBufs, mCamera3Buffers) < 0) {
989                delete mMemory;
990                mMemory = NULL;
991                return NO_MEMORY;
992            }
993        } else {
994            ALOGE("%s: error, Gralloc Memory object not yet created for this stream",__func__);
995            return NO_MEMORY;
996        }
997    }
998
999    index = mMemory->getMatchBufIndex((void*)buffer);
1000    if(index < 0) {
1001        ALOGE("%s: Could not find object among registered buffers",__func__);
1002        return DEAD_OBJECT;
1003    }
1004    rc = mMemory->markFrameNumber(index, frameNumber);
1005
1006    //Start the postprocessor for jpeg encoding. Pass mMemory as destination buffer
1007    mCurrentBufIndex = index;
1008    m_postprocessor.start(mMemory, index);
1009
1010    ALOGD("%s: Post-process started", __func__);
1011    if(pInputBuffer) {
1012        ALOGD("%s: Issue call to reprocess", __func__);
1013        m_postprocessor.processAuxiliaryData(pInputBuffer,pInputChannel);
1014    }
1015
1016    return rc;
1017}
1018
1019/*===========================================================================
1020 * FUNCTION   : dataNotifyCB
1021 *
1022 * DESCRIPTION: Channel Level callback used for super buffer data notify.
1023 *              This function is registered with mm-camera-interface to handle
1024 *              data notify
1025 *
1026 * PARAMETERS :
1027 *   @recvd_frame   : stream frame received
1028 *   userdata       : user data ptr
1029 *
1030 * RETURN     : none
1031 *==========================================================================*/
1032void QCamera3PicChannel::dataNotifyCB(mm_camera_super_buf_t *recvd_frame,
1033                                 void *userdata)
1034{
1035    ALOGV("%s: E\n", __func__);
1036    QCamera3PicChannel *channel = (QCamera3PicChannel *)userdata;
1037
1038    if (channel == NULL) {
1039        ALOGE("%s: invalid channel pointer", __func__);
1040        return;
1041    }
1042
1043    if(channel->m_numStreams != 1) {
1044        ALOGE("%s: Error: Bug: This callback assumes one stream per channel",__func__);
1045        return;
1046    }
1047
1048
1049    if(channel->mStreams[0] == NULL) {
1050        ALOGE("%s: Error: Invalid Stream object",__func__);
1051        return;
1052    }
1053
1054    channel->QCamera3PicChannel::streamCbRoutine(recvd_frame, channel->mStreams[0]);
1055
1056    ALOGV("%s: X\n", __func__);
1057    return;
1058}
1059
1060
1061int32_t QCamera3PicChannel::registerBuffers(uint32_t num_buffers,
1062                        buffer_handle_t **buffers)
1063{
1064    int rc = 0;
1065    cam_stream_type_t streamType;
1066    cam_format_t streamFormat;
1067
1068    ALOGV("%s: E",__func__);
1069    rc = QCamera3PicChannel::initialize();
1070    if (rc < 0) {
1071        ALOGE("%s: init failed", __func__);
1072        return rc;
1073    }
1074
1075    if (mCamera3Stream->format == HAL_PIXEL_FORMAT_BLOB) {
1076        streamType = CAM_STREAM_TYPE_SNAPSHOT;
1077        streamFormat = CAM_FORMAT_YUV_420_NV21;
1078    } else {
1079        //TODO: Fail for other types of streams for now
1080        ALOGE("%s: format is not BLOB", __func__);
1081        return -EINVAL;
1082    }
1083    /* Bookkeep buffer set because they go out of scope after register call */
1084    mNumBufs = num_buffers;
1085    mCamera3Buffers = new buffer_handle_t*[num_buffers];
1086    if (mCamera3Buffers == NULL) {
1087        ALOGE("%s: Failed to allocate buffer_handle_t*", __func__);
1088        return -ENOMEM;
1089    }
1090    for (size_t i = 0; i < num_buffers; i++)
1091        mCamera3Buffers[i] = buffers[i];
1092
1093    ALOGV("%s: X",__func__);
1094    return rc;
1095}
1096
1097void QCamera3PicChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
1098                            QCamera3Stream *stream)
1099{
1100    //TODO
1101    //Used only for getting YUV. Jpeg callback will be sent back from channel
1102    //directly to HWI. Refer to func jpegEvtHandle
1103
1104    //Got the yuv callback. Calling yuv callback handler in PostProc
1105    uint8_t frameIndex;
1106    mm_camera_super_buf_t* frame = NULL;
1107    if(!super_frame) {
1108         ALOGE("%s: Invalid Super buffer",__func__);
1109         return;
1110    }
1111
1112    if(super_frame->num_bufs != 1) {
1113         ALOGE("%s: Multiple streams are not supported",__func__);
1114         return;
1115    }
1116    if(super_frame->bufs[0] == NULL ) {
1117         ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
1118                  __func__);
1119         return;
1120    }
1121
1122    frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
1123    if(frameIndex >= mNumBufs) {
1124         ALOGE("%s: Error, Invalid index for buffer",__func__);
1125         if(stream) {
1126             stream->bufDone(frameIndex);
1127         }
1128         return;
1129    }
1130
1131    frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
1132    if (frame == NULL) {
1133       ALOGE("%s: Error allocating memory to save received_frame structure.",
1134                                                                    __func__);
1135       if(stream) {
1136           stream->bufDone(frameIndex);
1137       }
1138       return;
1139    }
1140    *frame = *super_frame;
1141
1142    m_postprocessor.processData(frame);
1143    return;
1144}
1145
1146QCamera3Memory* QCamera3PicChannel::getStreamBufs(uint32_t len)
1147{
1148    int rc = 0;
1149
1150    if (mNumBufs == 0 || mCamera3Buffers == NULL) {
1151        ALOGE("%s: buffers not registered yet", __func__);
1152        return NULL;
1153    }
1154
1155    if(mMemory) {
1156        delete mMemory;
1157        mMemory = NULL;
1158    }
1159    mMemory = new QCamera3GrallocMemory();
1160    if (mMemory == NULL) {
1161        return NULL;
1162    }
1163
1164    //Registering Jpeg output buffer
1165    if (mMemory->registerBuffers(mNumBufs, mCamera3Buffers) < 0) {
1166        delete mMemory;
1167        mMemory = NULL;
1168        return NULL;
1169    }
1170
1171    mYuvMemory = new QCamera3HeapMemory();
1172    if (!mYuvMemory) {
1173        ALOGE("%s: unable to create metadata memory", __func__);
1174        return NULL;
1175    }
1176
1177    //Queue YUV buffers in the beginning mQueueAll = true
1178    rc = mYuvMemory->allocate(1, len, true);
1179    if (rc < 0) {
1180        ALOGE("%s: unable to allocate metadata memory", __func__);
1181        delete mYuvMemory;
1182        mYuvMemory = NULL;
1183        return NULL;
1184    }
1185    return mYuvMemory;
1186}
1187
1188void QCamera3PicChannel::putStreamBufs()
1189{
1190    mMemory->unregisterBuffers();
1191    delete mMemory;
1192    mMemory = NULL;
1193
1194    mYuvMemory->deallocate();
1195    delete mYuvMemory;
1196    mYuvMemory = NULL;
1197}
1198
1199/*===========================================================================
1200 * FUNCTION   : needRotationReprocess
1201 *
1202 * DESCRIPTION: if online rotation needs to be done by cpp
1203 *
1204 * PARAMETERS : none
1205 *
1206 * RETURN     : true: needed
1207 *              false: no need
1208 *==========================================================================*/
1209bool QCamera3PicChannel::needOnlineRotation()
1210{
1211    //TODO: For B Family chips, we need to do something different
1212    // because JPEG encoder cannot do rotation.
1213    return false;
1214}
1215
1216/*===========================================================================
1217 * FUNCTION   : getThumbnailSize
1218 *
1219 * DESCRIPTION: get user set thumbnail size
1220 *
1221 * PARAMETERS :
1222 *   @dim     : output of thumbnail dimension
1223 *
1224 * RETURN     : none
1225 *==========================================================================*/
1226void QCamera3PicChannel::getThumbnailSize(cam_dimension_t &dim)
1227{
1228    dim = mJpegSettings->thumbnail_size;
1229}
1230
1231/*===========================================================================
1232 * FUNCTION   : getJpegQuality
1233 *
1234 * DESCRIPTION: get user set jpeg quality
1235 *
1236 * PARAMETERS : none
1237 *
1238 * RETURN     : jpeg quality setting
1239 *==========================================================================*/
1240int QCamera3PicChannel::getJpegQuality()
1241{
1242    int quality = mJpegSettings->jpeg_quality;
1243    if (quality < 0) {
1244        quality = 85;  //set to default quality value
1245    }
1246    return quality;
1247}
1248
1249/*===========================================================================
1250 * FUNCTION   : getJpegRotation
1251 *
1252 * DESCRIPTION: get rotation information to be passed into jpeg encoding
1253 *
1254 * PARAMETERS : none
1255 *
1256 * RETURN     : rotation information
1257 *==========================================================================*/
1258int QCamera3PicChannel::getJpegRotation() {
1259    int rotation = mJpegSettings->jpeg_orientation;
1260    if (rotation < 0) {
1261        rotation = 0;
1262    }
1263    return rotation;
1264}
1265
1266/*===========================================================================
1267 * FUNCTION   : getRational
1268 *
1269 * DESCRIPTION: compose rational struct
1270 *
1271 * PARAMETERS :
1272 *   @rat     : ptr to struct to store rational info
1273 *   @num     :num of the rational
1274 *   @denom   : denom of the rational
1275 *
1276 * RETURN     : int32_t type of status
1277 *              NO_ERROR  -- success
1278 *              none-zero failure code
1279 *==========================================================================*/
1280int32_t getRational(rat_t *rat, int num, int denom)
1281{
1282    if (NULL == rat) {
1283        ALOGE("%s: NULL rat input", __func__);
1284        return BAD_VALUE;
1285    }
1286    rat->num = num;
1287    rat->denom = denom;
1288    return NO_ERROR;
1289}
1290
1291/*===========================================================================
1292 * FUNCTION   : parseGPSCoordinate
1293 *
1294 * DESCRIPTION: parse GPS coordinate string
1295 *
1296 * PARAMETERS :
1297 *   @coord_str : [input] coordinate string
1298 *   @coord     : [output]  ptr to struct to store coordinate
1299 *
1300 * RETURN     : int32_t type of status
1301 *              NO_ERROR  -- success
1302 *              none-zero failure code
1303 *==========================================================================*/
1304int parseGPSCoordinate(const char *coord_str, rat_t* coord)
1305{
1306    if(coord == NULL) {
1307        ALOGE("%s: error, invalid argument coord == NULL", __func__);
1308        return BAD_VALUE;
1309    }
1310    float degF = atof(coord_str);
1311    if (degF < 0) {
1312        degF = -degF;
1313    }
1314    float minF = (degF - (int) degF) * 60;
1315    float secF = (minF - (int) minF) * 60;
1316
1317    getRational(&coord[0], (int)degF, 1);
1318    getRational(&coord[1], (int)minF, 1);
1319    getRational(&coord[2], (int)(secF * 10000), 10000);
1320    return NO_ERROR;
1321}
1322
1323/*===========================================================================
1324 * FUNCTION   : getExifDateTime
1325 *
1326 * DESCRIPTION: query exif date time
1327 *
1328 * PARAMETERS :
1329 *   @dateTime : string to store exif date time
1330 *   @count    : lenght of the dateTime string
1331 *
1332 * RETURN     : int32_t type of status
1333 *              NO_ERROR  -- success
1334 *              none-zero failure code
1335 *==========================================================================*/
1336int32_t getExifDateTime(char *dateTime, uint32_t &count)
1337{
1338    //get time and date from system
1339    time_t rawtime;
1340    struct tm * timeinfo;
1341    time(&rawtime);
1342    timeinfo = localtime (&rawtime);
1343    //Write datetime according to EXIF Spec
1344    //"YYYY:MM:DD HH:MM:SS" (20 chars including \0)
1345    snprintf(dateTime, 20, "%04d:%02d:%02d %02d:%02d:%02d",
1346             timeinfo->tm_year + 1900, timeinfo->tm_mon + 1,
1347             timeinfo->tm_mday, timeinfo->tm_hour,
1348             timeinfo->tm_min, timeinfo->tm_sec);
1349    count = 20;
1350
1351    return NO_ERROR;
1352}
1353
1354/*===========================================================================
1355 * FUNCTION   : getExifFocalLength
1356 *
1357 * DESCRIPTION: get exif focal lenght
1358 *
1359 * PARAMETERS :
1360 *   @focalLength : ptr to rational strcut to store focal lenght
1361 *
1362 * RETURN     : int32_t type of status
1363 *              NO_ERROR  -- success
1364 *              none-zero failure code
1365 *==========================================================================*/
1366int32_t getExifFocalLength(rat_t *focalLength, float value)
1367{
1368    int focalLengthValue =
1369        (int)(value * FOCAL_LENGTH_DECIMAL_PRECISION);
1370    return getRational(focalLength, focalLengthValue, FOCAL_LENGTH_DECIMAL_PRECISION);
1371}
1372
1373/*===========================================================================
1374 * FUNCTION   : getExifGpsProcessingMethod
1375 *
1376 * DESCRIPTION: get GPS processing method
1377 *
1378 * PARAMETERS :
1379 *   @gpsProcessingMethod : string to store GPS process method
1380 *   @count               : lenght of the string
1381 *
1382 * RETURN     : int32_t type of status
1383 *              NO_ERROR  -- success
1384 *              none-zero failure code
1385 *==========================================================================*/
1386int32_t getExifGpsProcessingMethod(char *gpsProcessingMethod,
1387                                   uint32_t &count, char* value)
1388{
1389    if(value != NULL) {
1390        memcpy(gpsProcessingMethod, ExifAsciiPrefix, EXIF_ASCII_PREFIX_SIZE);
1391        count = EXIF_ASCII_PREFIX_SIZE;
1392        strncpy(gpsProcessingMethod + EXIF_ASCII_PREFIX_SIZE, value, strlen(value));
1393        count += strlen(value);
1394        gpsProcessingMethod[count++] = '\0'; // increase 1 for the last NULL char
1395        return NO_ERROR;
1396    } else {
1397        return BAD_VALUE;
1398    }
1399}
1400
1401/*===========================================================================
1402 * FUNCTION   : getExifLatitude
1403 *
1404 * DESCRIPTION: get exif latitude
1405 *
1406 * PARAMETERS :
1407 *   @latitude : ptr to rational struct to store latitude info
1408 *   @ladRef   : charater to indicate latitude reference
1409 *
1410 * RETURN     : int32_t type of status
1411 *              NO_ERROR  -- success
1412 *              none-zero failure code
1413 *==========================================================================*/
1414int32_t getExifLatitude(rat_t *latitude,
1415                                           char *latRef, double value)
1416{
1417    char str[30];
1418    snprintf(str, sizeof(str), "%f", value);
1419    if(str != NULL) {
1420        parseGPSCoordinate(str, latitude);
1421
1422        //set Latitude Ref
1423        float latitudeValue = strtof(str, 0);
1424        if(latitudeValue < 0.0f) {
1425            latRef[0] = 'S';
1426        } else {
1427            latRef[0] = 'N';
1428        }
1429        latRef[1] = '\0';
1430        return NO_ERROR;
1431    }else{
1432        return BAD_VALUE;
1433    }
1434}
1435
1436/*===========================================================================
1437 * FUNCTION   : getExifLongitude
1438 *
1439 * DESCRIPTION: get exif longitude
1440 *
1441 * PARAMETERS :
1442 *   @longitude : ptr to rational struct to store longitude info
1443 *   @lonRef    : charater to indicate longitude reference
1444 *
1445 * RETURN     : int32_t type of status
1446 *              NO_ERROR  -- success
1447 *              none-zero failure code
1448 *==========================================================================*/
1449int32_t getExifLongitude(rat_t *longitude,
1450                                            char *lonRef, double value)
1451{
1452    char str[30];
1453    snprintf(str, sizeof(str), "%f", value);
1454    if(str != NULL) {
1455        parseGPSCoordinate(str, longitude);
1456
1457        //set Longitude Ref
1458        float longitudeValue = strtof(str, 0);
1459        if(longitudeValue < 0.0f) {
1460            lonRef[0] = 'W';
1461        } else {
1462            lonRef[0] = 'E';
1463        }
1464        lonRef[1] = '\0';
1465        return NO_ERROR;
1466    }else{
1467        return BAD_VALUE;
1468    }
1469}
1470
1471/*===========================================================================
1472 * FUNCTION   : getExifAltitude
1473 *
1474 * DESCRIPTION: get exif altitude
1475 *
1476 * PARAMETERS :
1477 *   @altitude : ptr to rational struct to store altitude info
1478 *   @altRef   : charater to indicate altitude reference
1479 *
1480 * RETURN     : int32_t type of status
1481 *              NO_ERROR  -- success
1482 *              none-zero failure code
1483 *==========================================================================*/
1484int32_t getExifAltitude(rat_t *altitude,
1485                                           char *altRef, double value)
1486{
1487    char str[30];
1488    snprintf(str, sizeof(str), "%f", value);
1489    if(str != NULL) {
1490        double value = atof(str);
1491        *altRef = 0;
1492        if(value < 0){
1493            *altRef = 1;
1494            value = -value;
1495        }
1496        return getRational(altitude, value*1000, 1000);
1497    }else{
1498        return BAD_VALUE;
1499    }
1500}
1501
1502/*===========================================================================
1503 * FUNCTION   : getExifGpsDateTimeStamp
1504 *
1505 * DESCRIPTION: get exif GPS date time stamp
1506 *
1507 * PARAMETERS :
1508 *   @gpsDateStamp : GPS date time stamp string
1509 *   @bufLen       : length of the string
1510 *   @gpsTimeStamp : ptr to rational struct to store time stamp info
1511 *
1512 * RETURN     : int32_t type of status
1513 *              NO_ERROR  -- success
1514 *              none-zero failure code
1515 *==========================================================================*/
1516int32_t getExifGpsDateTimeStamp(char *gpsDateStamp,
1517                                           uint32_t bufLen,
1518                                           rat_t *gpsTimeStamp, int64_t value)
1519{
1520    char str[30];
1521    snprintf(str, sizeof(str), "%lld", value);
1522    if(str != NULL) {
1523        time_t unixTime = (time_t)atol(str);
1524        struct tm *UTCTimestamp = gmtime(&unixTime);
1525
1526        strftime(gpsDateStamp, bufLen, "%Y:%m:%d", UTCTimestamp);
1527
1528        getRational(&gpsTimeStamp[0], UTCTimestamp->tm_hour, 1);
1529        getRational(&gpsTimeStamp[1], UTCTimestamp->tm_min, 1);
1530        getRational(&gpsTimeStamp[2], UTCTimestamp->tm_sec, 1);
1531
1532        return NO_ERROR;
1533    } else {
1534        return BAD_VALUE;
1535    }
1536}
1537
1538int32_t getExifExposureValue(srat_t* exposure_val, int32_t exposure_comp,
1539                             cam_rational_type_t step)
1540{
1541    exposure_val->num = exposure_comp * step.numerator;
1542    exposure_val->denom = step.denominator;
1543    return 0;
1544}
1545/*===========================================================================
1546 * FUNCTION   : getExifData
1547 *
1548 * DESCRIPTION: get exif data to be passed into jpeg encoding
1549 *
1550 * PARAMETERS : none
1551 *
1552 * RETURN     : exif data from user setting and GPS
1553 *==========================================================================*/
1554QCamera3Exif *QCamera3PicChannel::getExifData()
1555{
1556    QCamera3Exif *exif = new QCamera3Exif();
1557    if (exif == NULL) {
1558        ALOGE("%s: No memory for QCamera3Exif", __func__);
1559        return NULL;
1560    }
1561
1562    int32_t rc = NO_ERROR;
1563    uint32_t count = 0;
1564
1565    // add exif entries
1566    char dateTime[20];
1567    memset(dateTime, 0, sizeof(dateTime));
1568    count = 20;
1569    rc = getExifDateTime(dateTime, count);
1570    if(rc == NO_ERROR) {
1571        exif->addEntry(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL,
1572                       EXIF_ASCII,
1573                       count,
1574                       (void *)dateTime);
1575    } else {
1576        ALOGE("%s: getExifDateTime failed", __func__);
1577    }
1578
1579    rat_t focalLength;
1580    rc = getExifFocalLength(&focalLength, mJpegSettings->lens_focal_length);
1581    if (rc == NO_ERROR) {
1582        exif->addEntry(EXIFTAGID_FOCAL_LENGTH,
1583                       EXIF_RATIONAL,
1584                       1,
1585                       (void *)&(focalLength));
1586    } else {
1587        ALOGE("%s: getExifFocalLength failed", __func__);
1588    }
1589
1590    uint16_t isoSpeed = (uint16_t)mJpegSettings->sensor_sensitivity;
1591    exif->addEntry(EXIFTAGID_ISO_SPEED_RATING,
1592                   EXIF_SHORT,
1593                   1,
1594                   (void *)&(isoSpeed));
1595
1596
1597    if (strlen(mJpegSettings->gps_processing_method) > 0) {
1598        char gpsProcessingMethod[EXIF_ASCII_PREFIX_SIZE + GPS_PROCESSING_METHOD_SIZE];
1599        count = 0;
1600        rc = getExifGpsProcessingMethod(gpsProcessingMethod, count, mJpegSettings->gps_processing_method);
1601        if(rc == NO_ERROR) {
1602            exif->addEntry(EXIFTAGID_GPS_PROCESSINGMETHOD,
1603                           EXIF_ASCII,
1604                           count,
1605                           (void *)gpsProcessingMethod);
1606        } else {
1607            ALOGE("%s: getExifGpsProcessingMethod failed", __func__);
1608        }
1609    }
1610
1611    if (mJpegSettings->gps_coordinates[0]) {
1612        rat_t latitude[3];
1613        char latRef[2];
1614        rc = getExifLatitude(latitude, latRef, *(mJpegSettings->gps_coordinates[0]));
1615        if(rc == NO_ERROR) {
1616            exif->addEntry(EXIFTAGID_GPS_LATITUDE,
1617                           EXIF_RATIONAL,
1618                           3,
1619                           (void *)latitude);
1620            exif->addEntry(EXIFTAGID_GPS_LATITUDE_REF,
1621                           EXIF_ASCII,
1622                           2,
1623                           (void *)latRef);
1624        } else {
1625            ALOGE("%s: getExifLatitude failed", __func__);
1626        }
1627    }
1628
1629    if (mJpegSettings->gps_coordinates[1]) {
1630        rat_t longitude[3];
1631        char lonRef[2];
1632        rc = getExifLongitude(longitude, lonRef, *(mJpegSettings->gps_coordinates[1]));
1633        if(rc == NO_ERROR) {
1634            exif->addEntry(EXIFTAGID_GPS_LONGITUDE,
1635                           EXIF_RATIONAL,
1636                           3,
1637                           (void *)longitude);
1638
1639            exif->addEntry(EXIFTAGID_GPS_LONGITUDE_REF,
1640                           EXIF_ASCII,
1641                           2,
1642                           (void *)lonRef);
1643        } else {
1644            ALOGE("%s: getExifLongitude failed", __func__);
1645        }
1646    }
1647
1648    if (mJpegSettings->gps_coordinates[2]) {
1649        rat_t altitude;
1650        char altRef;
1651        rc = getExifAltitude(&altitude, &altRef, *(mJpegSettings->gps_coordinates[2]));
1652        if(rc == NO_ERROR) {
1653            exif->addEntry(EXIFTAGID_GPS_ALTITUDE,
1654                           EXIF_RATIONAL,
1655                           1,
1656                           (void *)&(altitude));
1657
1658            exif->addEntry(EXIFTAGID_GPS_ALTITUDE_REF,
1659                           EXIF_BYTE,
1660                           1,
1661                           (void *)&altRef);
1662        } else {
1663            ALOGE("%s: getExifAltitude failed", __func__);
1664        }
1665    }
1666
1667    if (mJpegSettings->gps_timestamp) {
1668        char gpsDateStamp[20];
1669        rat_t gpsTimeStamp[3];
1670        rc = getExifGpsDateTimeStamp(gpsDateStamp, 20, gpsTimeStamp, *(mJpegSettings->gps_timestamp));
1671        if(rc == NO_ERROR) {
1672            exif->addEntry(EXIFTAGID_GPS_DATESTAMP,
1673                           EXIF_ASCII,
1674                           strlen(gpsDateStamp) + 1,
1675                           (void *)gpsDateStamp);
1676
1677            exif->addEntry(EXIFTAGID_GPS_TIMESTAMP,
1678                           EXIF_RATIONAL,
1679                           3,
1680                           (void *)gpsTimeStamp);
1681        } else {
1682            ALOGE("%s: getExifGpsDataTimeStamp failed", __func__);
1683        }
1684    }
1685
1686    srat_t exposure_val;
1687    rc = getExifExposureValue(&exposure_val, mJpegSettings->exposure_compensation,
1688                              mJpegSettings->exposure_comp_step);
1689    if(rc == NO_ERROR) {
1690        exif->addEntry(EXIFTAGID_EXPOSURE_BIAS_VALUE,
1691                       EXIF_SRATIONAL,
1692                       1,
1693                       (void *)(&exposure_val));
1694    } else {
1695        ALOGE("%s: getExifExposureValue failed ", __func__);
1696    }
1697
1698    char value[PROPERTY_VALUE_MAX];
1699    if (property_get("ro.product.manufacturer", value, "QCOM-AA") > 0) {
1700        exif->addEntry(EXIFTAGID_MAKE,
1701                       EXIF_ASCII,
1702                       strlen(value) + 1,
1703                       (void *)value);
1704    } else {
1705        ALOGE("%s: getExifMaker failed", __func__);
1706    }
1707
1708    if (property_get("ro.product.model", value, "QCAM-AA") > 0) {
1709        exif->addEntry(EXIFTAGID_MODEL,
1710                       EXIF_ASCII,
1711                       strlen(value) + 1,
1712                       (void *)value);
1713    } else {
1714        ALOGE("%s: getExifModel failed", __func__);
1715    }
1716
1717    return exif;
1718}
1719
1720int QCamera3PicChannel::kMaxBuffers = 2;
1721}; // namespace qcamera
1722