1/* Copyright (c) 2012-2014, 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//#define LOG_NDEBUG 0
32
33#include <stdlib.h>
34#include <cstdlib>
35#include <stdio.h>
36#include <string.h>
37#include <hardware/camera3.h>
38#include <system/camera_metadata.h>
39#include <gralloc_priv.h>
40#include <utils/Log.h>
41#include <utils/Errors.h>
42#include <cutils/properties.h>
43#include "QCamera3Channel.h"
44
45using namespace android;
46
47#define MIN_STREAMING_BUFFER_NUM 7+11
48
49namespace qcamera {
50static const char ExifAsciiPrefix[] =
51    { 0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0 };          // "ASCII\0\0\0"
52static const char ExifUndefinedPrefix[] =
53    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };   // "\0\0\0\0\0\0\0\0"
54
55#define GPS_PROCESSING_METHOD_SIZE       101
56#define EXIF_ASCII_PREFIX_SIZE           8   //(sizeof(ExifAsciiPrefix))
57#define FOCAL_LENGTH_DECIMAL_PRECISION   100
58
59/*===========================================================================
60 * FUNCTION   : QCamera3Channel
61 *
62 * DESCRIPTION: constrcutor of QCamera3Channel
63 *
64 * PARAMETERS :
65 *   @cam_handle : camera handle
66 *   @cam_ops    : ptr to camera ops table
67 *
68 * RETURN     : none
69 *==========================================================================*/
70QCamera3Channel::QCamera3Channel(uint32_t cam_handle,
71                               mm_camera_ops_t *cam_ops,
72                               channel_cb_routine cb_routine,
73                               cam_padding_info_t *paddingInfo,
74                               void *userData)
75{
76    m_camHandle = cam_handle;
77    m_camOps = cam_ops;
78    m_bIsActive = false;
79
80    m_handle = 0;
81    m_numStreams = 0;
82    memset(mStreams, 0, sizeof(mStreams));
83    mUserData = userData;
84
85    mStreamInfoBuf = NULL;
86    mChannelCB = cb_routine;
87    mPaddingInfo = paddingInfo;
88}
89
90/*===========================================================================
91 * FUNCTION   : QCamera3Channel
92 *
93 * DESCRIPTION: default constrcutor of QCamera3Channel
94 *
95 * PARAMETERS : none
96 *
97 * RETURN     : none
98 *==========================================================================*/
99QCamera3Channel::QCamera3Channel()
100{
101    m_camHandle = 0;
102    m_camOps = NULL;
103    m_bIsActive = false;
104
105    m_handle = 0;
106    m_numStreams = 0;
107    memset(mStreams, 0, sizeof(mStreams));
108    mUserData = NULL;
109
110    mStreamInfoBuf = NULL;
111    mChannelCB = NULL;
112    mPaddingInfo = NULL;
113}
114
115/*===========================================================================
116 * FUNCTION   : ~QCamera3Channel
117 *
118 * DESCRIPTION: destructor of QCamera3Channel
119 *
120 * PARAMETERS : none
121 *
122 * RETURN     : none
123 *==========================================================================*/
124QCamera3Channel::~QCamera3Channel()
125{
126    if (m_bIsActive)
127        stop();
128
129    for (int i = 0; i < m_numStreams; i++) {
130        if (mStreams[i] != NULL) {
131            delete mStreams[i];
132            mStreams[i] = 0;
133        }
134    }
135    if (m_handle) {
136        m_camOps->delete_channel(m_camHandle, m_handle);
137        ALOGE("%s: deleting channel %d", __func__, m_handle);
138        m_handle = 0;
139    }
140    m_numStreams = 0;
141}
142
143/*===========================================================================
144 * FUNCTION   : init
145 *
146 * DESCRIPTION: initialization of channel
147 *
148 * PARAMETERS :
149 *   @attr    : channel bundle attribute setting
150 *   @dataCB  : data notify callback
151 *   @userData: user data ptr
152 *
153 * RETURN     : int32_t type of status
154 *              NO_ERROR  -- success
155 *              none-zero failure code
156 *==========================================================================*/
157int32_t QCamera3Channel::init(mm_camera_channel_attr_t *attr,
158                             mm_camera_buf_notify_t dataCB)
159{
160    m_handle = m_camOps->add_channel(m_camHandle,
161                                      attr,
162                                      dataCB,
163                                      this);
164    if (m_handle == 0) {
165        ALOGE("%s: Add channel failed", __func__);
166        return UNKNOWN_ERROR;
167    }
168    return NO_ERROR;
169}
170
171/*===========================================================================
172 * FUNCTION   : addStream
173 *
174 * DESCRIPTION: add a stream into channel
175 *
176 * PARAMETERS :
177 *   @allocator      : stream related buffer allocator
178 *   @streamInfoBuf  : ptr to buf that constains stream info
179 *   @minStreamBufNum: number of stream buffers needed
180 *   @paddingInfo    : padding information
181 *   @stream_cb      : stream data notify callback
182 *   @userdata       : user data ptr
183 *
184 * RETURN     : int32_t type of status
185 *              NO_ERROR  -- success
186 *              none-zero failure code
187 *==========================================================================*/
188int32_t QCamera3Channel::addStream(cam_stream_type_t streamType,
189                                  cam_format_t streamFormat,
190                                  cam_dimension_t streamDim,
191                                  uint8_t minStreamBufNum)
192{
193    int32_t rc = NO_ERROR;
194
195    if (m_numStreams >= 1) {
196        ALOGE("%s: Only one stream per channel supported in v3 Hal", __func__);
197        return BAD_VALUE;
198    }
199
200    if (m_numStreams >= MAX_STREAM_NUM_IN_BUNDLE) {
201        ALOGE("%s: stream number (%d) exceeds max limit (%d)",
202              __func__, m_numStreams, MAX_STREAM_NUM_IN_BUNDLE);
203        return BAD_VALUE;
204    }
205    QCamera3Stream *pStream = new QCamera3Stream(m_camHandle,
206                                               m_handle,
207                                               m_camOps,
208                                               mPaddingInfo,
209                                               this);
210    if (pStream == NULL) {
211        ALOGE("%s: No mem for Stream", __func__);
212        return NO_MEMORY;
213    }
214
215    rc = pStream->init(streamType, streamFormat, streamDim, NULL, minStreamBufNum,
216                                                    streamCbRoutine, this);
217    if (rc == 0) {
218        mStreams[m_numStreams] = pStream;
219        m_numStreams++;
220    } else {
221        delete pStream;
222    }
223    return rc;
224}
225
226/*===========================================================================
227 * FUNCTION   : start
228 *
229 * DESCRIPTION: start channel, which will start all streams belong to this channel
230 *
231 * PARAMETERS :
232 *
233 * RETURN     : int32_t type of status
234 *              NO_ERROR  -- success
235 *              none-zero failure code
236 *==========================================================================*/
237int32_t QCamera3Channel::start()
238{
239    int32_t rc = NO_ERROR;
240
241    if (m_numStreams > 1) {
242        ALOGE("%s: bundle not supported", __func__);
243    }
244
245    for (int i = 0; i < m_numStreams; i++) {
246        if (mStreams[i] != NULL) {
247            mStreams[i]->start();
248        }
249    }
250    rc = m_camOps->start_channel(m_camHandle, m_handle);
251
252    if (rc != NO_ERROR) {
253        for (int i = 0; i < m_numStreams; i++) {
254            if (mStreams[i] != NULL) {
255                mStreams[i]->stop();
256            }
257        }
258    } else {
259        m_bIsActive = true;
260    }
261
262    return rc;
263}
264
265/*===========================================================================
266 * FUNCTION   : stop
267 *
268 * DESCRIPTION: stop a channel, which will stop all streams belong to this channel
269 *
270 * PARAMETERS : none
271 *
272 * RETURN     : int32_t type of status
273 *              NO_ERROR  -- success
274 *              none-zero failure code
275 *==========================================================================*/
276int32_t QCamera3Channel::stop()
277{
278    int32_t rc = NO_ERROR;
279    if(!m_bIsActive) {
280        ALOGE("%s: Attempt to stop inactive channel",__func__);
281        return rc;
282    }
283
284    rc = m_camOps->stop_channel(m_camHandle, m_handle);
285
286    for (int i = 0; i < m_numStreams; i++) {
287        if (mStreams[i] != NULL) {
288            mStreams[i]->stop();
289        }
290    }
291
292    m_bIsActive = false;
293    return rc;
294}
295
296/*===========================================================================
297 * FUNCTION   : bufDone
298 *
299 * DESCRIPTION: return a stream buf back to kernel
300 *
301 * PARAMETERS :
302 *   @recvd_frame  : stream buf frame to be returned
303 *
304 * RETURN     : int32_t type of status
305 *              NO_ERROR  -- success
306 *              none-zero failure code
307 *==========================================================================*/
308int32_t QCamera3Channel::bufDone(mm_camera_super_buf_t *recvd_frame)
309{
310    int32_t rc = NO_ERROR;
311    for (int i = 0; i < recvd_frame->num_bufs; i++) {
312         if (recvd_frame->bufs[i] != NULL) {
313             for (int j = 0; j < m_numStreams; j++) {
314                 if (mStreams[j] != NULL &&
315                     mStreams[j]->getMyHandle() == recvd_frame->bufs[i]->stream_id) {
316                     rc = mStreams[j]->bufDone(recvd_frame->bufs[i]->buf_idx);
317                     break; // break loop j
318                 }
319             }
320         }
321    }
322
323    return rc;
324}
325
326/*===========================================================================
327 * FUNCTION   : getStreamTypeMask
328 *
329 * DESCRIPTION: Get bit mask of all stream types in this channel
330 *
331 * PARAMETERS : None
332 *
333 * RETURN     : Bit mask of all stream types in this channel
334 *==========================================================================*/
335uint32_t QCamera3Channel::getStreamTypeMask()
336{
337    uint32_t mask = 0;
338    for (int i = 0; i < m_numStreams; i++) {
339       mask |= (0x1 << mStreams[i]->getMyType());
340    }
341    return mask;
342}
343
344/*===========================================================================
345 * FUNCTION   : getStreamID
346 *
347 * DESCRIPTION: Get StreamID of requested stream type
348 *
349 * PARAMETERS : streamMask
350 *
351 * RETURN     : Stream ID
352 *==========================================================================*/
353uint32_t QCamera3Channel::getStreamID(uint32_t streamMask)
354{
355    uint32_t streamID = 0;
356    for (int i = 0; i < m_numStreams; i++) {
357        if (streamMask == (uint32_t )(0x1 << mStreams[i]->getMyType())) {
358            streamID = mStreams[i]->getMyServerID();
359            break;
360        }
361    }
362    return streamID;
363}
364
365/*===========================================================================
366 * FUNCTION   : getInternalFormatBuffer
367 *
368 * DESCRIPTION: return buffer in the internal format structure
369 *
370 * PARAMETERS :
371 *   @streamHandle : buffer handle
372 *
373 * RETURN     : stream object. NULL if not found
374 *==========================================================================*/
375mm_camera_buf_def_t* QCamera3RegularChannel::getInternalFormatBuffer(
376                                            buffer_handle_t * buffer)
377{
378    int32_t index;
379    if(buffer == NULL)
380        return NULL;
381    index = mMemory->getMatchBufIndex((void*)buffer);
382    if(index < 0) {
383        ALOGE("%s: Could not find object among registered buffers",__func__);
384        return NULL;
385    }
386    return mStreams[0]->getInternalFormatBuffer(index);
387}
388
389/*===========================================================================
390 * FUNCTION   : getStreamByHandle
391 *
392 * DESCRIPTION: return stream object by stream handle
393 *
394 * PARAMETERS :
395 *   @streamHandle : stream handle
396 *
397 * RETURN     : stream object. NULL if not found
398 *==========================================================================*/
399QCamera3Stream *QCamera3Channel::getStreamByHandle(uint32_t streamHandle)
400{
401    for (int i = 0; i < m_numStreams; i++) {
402        if (mStreams[i] != NULL && mStreams[i]->getMyHandle() == streamHandle) {
403            return mStreams[i];
404        }
405    }
406    return NULL;
407}
408
409/*===========================================================================
410 * FUNCTION   : getStreamByIndex
411 *
412 * DESCRIPTION: return stream object by index
413 *
414 * PARAMETERS :
415 *   @streamHandle : stream handle
416 *
417 * RETURN     : stream object. NULL if not found
418 *==========================================================================*/
419QCamera3Stream *QCamera3Channel::getStreamByIndex(uint8_t index)
420{
421    if (index < m_numStreams) {
422        return mStreams[index];
423    }
424    return NULL;
425}
426
427/*===========================================================================
428 * FUNCTION   : streamCbRoutine
429 *
430 * DESCRIPTION: callback routine for stream
431 *
432 * PARAMETERS :
433 *   @streamHandle : stream handle
434 *
435 * RETURN     : stream object. NULL if not found
436 *==========================================================================*/
437void QCamera3Channel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
438                QCamera3Stream *stream, void *userdata)
439{
440    QCamera3Channel *channel = (QCamera3Channel *)userdata;
441    if (channel == NULL) {
442        ALOGE("%s: invalid channel pointer", __func__);
443        return;
444    }
445    channel->streamCbRoutine(super_frame, stream);
446}
447
448/*===========================================================================
449 * FUNCTION   : QCamera3RegularChannel
450 *
451 * DESCRIPTION: constrcutor of QCamera3RegularChannel
452 *
453 * PARAMETERS :
454 *   @cam_handle : camera handle
455 *   @cam_ops    : ptr to camera ops table
456 *   @cb_routine : callback routine to frame aggregator
457 *   @stream     : camera3_stream_t structure
458 *
459 * RETURN     : none
460 *==========================================================================*/
461QCamera3RegularChannel::QCamera3RegularChannel(uint32_t cam_handle,
462                    mm_camera_ops_t *cam_ops,
463                    channel_cb_routine cb_routine,
464                    cam_padding_info_t *paddingInfo,
465                    void *userData,
466                    camera3_stream_t *stream) :
467                        QCamera3Channel(cam_handle, cam_ops, cb_routine,
468                                                paddingInfo, userData),
469                        mCamera3Stream(stream),
470                        mNumBufs(0),
471                        mCamera3Buffers(NULL),
472                        mMemory(NULL),
473                        mWidth(stream->width),
474                        mHeight(stream->height)
475{
476}
477
478/*===========================================================================
479 * FUNCTION   : QCamera3RegularChannel
480 *
481 * DESCRIPTION: constrcutor of QCamera3RegularChannel
482 *
483 * PARAMETERS :
484 *   @cam_handle : camera handle
485 *   @cam_ops    : ptr to camera ops table
486 *   @cb_routine : callback routine to frame aggregator
487 *   @stream     : camera3_stream_t structure
488 *
489 * RETURN     : none
490 *==========================================================================*/
491QCamera3RegularChannel::QCamera3RegularChannel(uint32_t cam_handle,
492                    mm_camera_ops_t *cam_ops,
493                    channel_cb_routine cb_routine,
494                    cam_padding_info_t *paddingInfo,
495                    void *userData,
496                    camera3_stream_t *stream,
497                    uint32_t width, uint32_t height) :
498                        QCamera3Channel(cam_handle, cam_ops, cb_routine,
499                                                paddingInfo, userData),
500                        mCamera3Stream(stream),
501                        mNumBufs(0),
502                        mCamera3Buffers(NULL),
503                        mMemory(NULL),
504                        mWidth(width),
505                        mHeight(height)
506{
507}
508
509/*===========================================================================
510 * FUNCTION   : ~QCamera3RegularChannel
511 *
512 * DESCRIPTION: destructor of QCamera3RegularChannel
513 *
514 * PARAMETERS : none
515 *
516 * RETURN     : none
517 *==========================================================================*/
518QCamera3RegularChannel::~QCamera3RegularChannel()
519{
520    if (mCamera3Buffers) {
521        delete[] mCamera3Buffers;
522    }
523}
524
525int32_t QCamera3RegularChannel::initialize()
526{
527  //TO DO
528  return 0;
529}
530
531/*===========================================================================
532 * FUNCTION   : request
533 *
534 * DESCRIPTION: process a request from camera service. Stream on if ncessary.
535 *
536 * PARAMETERS :
537 *   @buffer  : buffer to be filled for this request
538 *
539 * RETURN     : 0 on a success start of capture
540 *              -EINVAL on invalid input
541 *              -ENODEV on serious error
542 *==========================================================================*/
543int32_t QCamera3RegularChannel::request(buffer_handle_t *buffer, uint32_t frameNumber)
544{
545    //FIX ME: Return buffer back in case of failures below.
546
547    int32_t rc = NO_ERROR;
548    int index;
549    if(!m_bIsActive) {
550        ALOGD("%s: First request on this channel starting stream",__func__);
551        start();
552        if(rc != NO_ERROR) {
553            ALOGE("%s: Failed to start the stream on the request",__func__);
554            return rc;
555        }
556    } else {
557        ALOGV("%s: Request on an existing stream",__func__);
558    }
559
560    if(!mMemory) {
561        ALOGE("%s: error, Gralloc Memory object not yet created for this stream",__func__);
562        return NO_MEMORY;
563    }
564
565    index = mMemory->getMatchBufIndex((void*)buffer);
566    if(index < 0) {
567        ALOGE("%s: Could not find object among registered buffers",__func__);
568        return DEAD_OBJECT;
569    }
570
571    rc = mStreams[0]->bufDone(index);
572    if(rc != NO_ERROR) {
573        ALOGE("%s: Failed to Q new buffer to stream",__func__);
574        return rc;
575    }
576
577    rc = mMemory->markFrameNumber(index, frameNumber);
578    return rc;
579}
580
581/*===========================================================================
582 * FUNCTION   : registerBuffers
583 *
584 * DESCRIPTION: register streaming buffers to the channel object
585 *
586 * PARAMETERS :
587 *   @num_buffers : number of buffers to be registered
588 *   @buffers     : buffer to be registered
589 *
590 * RETURN     : 0 on a success start of capture
591 *              -EINVAL on invalid input
592 *              -ENOMEM on failure to register the buffer
593 *              -ENODEV on serious error
594 *==========================================================================*/
595int32_t QCamera3RegularChannel::registerBuffers(uint32_t num_buffers, buffer_handle_t **buffers)
596{
597    int rc = 0;
598    struct private_handle_t *priv_handle = (struct private_handle_t *)(*buffers[0]);
599    cam_stream_type_t streamType;
600    cam_format_t streamFormat;
601    cam_dimension_t streamDim;
602
603    rc = init(NULL, NULL);
604    if (rc < 0) {
605        ALOGE("%s: init failed", __func__);
606        return rc;
607    }
608
609    if (mCamera3Stream->format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
610        if (priv_handle->flags & private_handle_t::PRIV_FLAGS_VIDEO_ENCODER) {
611            streamType = CAM_STREAM_TYPE_VIDEO;
612            streamFormat = CAM_FORMAT_YUV_420_NV12;
613        } else if (priv_handle->flags & private_handle_t::PRIV_FLAGS_HW_TEXTURE) {
614            streamType = CAM_STREAM_TYPE_PREVIEW;
615            streamFormat = CAM_FORMAT_YUV_420_NV21;
616        } else {
617            //TODO: Add a new flag in libgralloc for ZSL buffers, and its size needs
618            // to be properly aligned and padded.
619            ALOGE("%s: priv_handle->flags 0x%x not supported",
620                    __func__, priv_handle->flags);
621            streamType = CAM_STREAM_TYPE_SNAPSHOT;
622            streamFormat = CAM_FORMAT_YUV_420_NV21;
623        }
624    } else if(mCamera3Stream->format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
625         streamType = CAM_STREAM_TYPE_CALLBACK;
626         streamFormat = CAM_FORMAT_YUV_420_NV21;
627    } else {
628        //TODO: Fail for other types of streams for now
629        ALOGE("%s: format is not IMPLEMENTATION_DEFINED or flexible", __func__);
630        return -EINVAL;
631    }
632
633    /* Bookkeep buffer set because they go out of scope after register call */
634    mNumBufs = num_buffers;
635    mCamera3Buffers = new buffer_handle_t*[num_buffers];
636    if (mCamera3Buffers == NULL) {
637        ALOGE("%s: Failed to allocate buffer_handle_t*", __func__);
638        return -ENOMEM;
639    }
640    for (size_t i = 0; i < num_buffers; i++)
641        mCamera3Buffers[i] = buffers[i];
642
643    streamDim.width = mWidth;
644    streamDim.height = mHeight;
645
646    rc = QCamera3Channel::addStream(streamType, streamFormat, streamDim,
647        num_buffers);
648    return rc;
649}
650
651void QCamera3RegularChannel::streamCbRoutine(
652                            mm_camera_super_buf_t *super_frame,
653                            QCamera3Stream *stream)
654{
655    //FIXME Q Buf back in case of error?
656    uint8_t frameIndex;
657    buffer_handle_t *resultBuffer;
658    int32_t resultFrameNumber;
659    camera3_stream_buffer_t result;
660
661    if(!super_frame) {
662         ALOGE("%s: Invalid Super buffer",__func__);
663         return;
664    }
665
666    if(super_frame->num_bufs != 1) {
667         ALOGE("%s: Multiple streams are not supported",__func__);
668         return;
669    }
670    if(super_frame->bufs[0] == NULL ) {
671         ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
672                  __func__);
673         return;
674    }
675
676    frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
677    if(frameIndex >= mNumBufs) {
678         ALOGE("%s: Error, Invalid index for buffer",__func__);
679         if(stream) {
680             stream->bufDone(frameIndex);
681         }
682         return;
683    }
684
685    ////Use below data to issue framework callback
686    resultBuffer = mCamera3Buffers[frameIndex];
687    resultFrameNumber = mMemory->getFrameNumber(frameIndex);
688
689    result.stream = mCamera3Stream;
690    result.buffer = resultBuffer;
691    result.status = CAMERA3_BUFFER_STATUS_OK;
692    result.acquire_fence = -1;
693    result.release_fence = -1;
694
695    mChannelCB(NULL, &result, resultFrameNumber, mUserData);
696    free(super_frame);
697    return;
698}
699
700QCamera3Memory* QCamera3RegularChannel::getStreamBufs(uint32_t /*len*/)
701{
702    if (mNumBufs == 0 || mCamera3Buffers == NULL) {
703        ALOGE("%s: buffers not registered yet", __func__);
704        return NULL;
705    }
706
707    mMemory = new QCamera3GrallocMemory();
708    if (mMemory == NULL) {
709        return NULL;
710    }
711
712    if (mMemory->registerBuffers(mNumBufs, mCamera3Buffers) < 0) {
713        delete mMemory;
714        mMemory = NULL;
715        return NULL;
716    }
717    return mMemory;
718}
719
720void QCamera3RegularChannel::putStreamBufs()
721{
722    mMemory->unregisterBuffers();
723    delete mMemory;
724    mMemory = NULL;
725}
726
727int QCamera3RegularChannel::kMaxBuffers = 7;
728
729QCamera3MetadataChannel::QCamera3MetadataChannel(uint32_t cam_handle,
730                    mm_camera_ops_t *cam_ops,
731                    channel_cb_routine cb_routine,
732                    cam_padding_info_t *paddingInfo,
733                    void *userData) :
734                        QCamera3Channel(cam_handle, cam_ops,
735                                cb_routine, paddingInfo, userData),
736                        mMemory(NULL)
737{
738}
739
740QCamera3MetadataChannel::~QCamera3MetadataChannel()
741{
742    if (m_bIsActive)
743        stop();
744
745    if (mMemory) {
746        mMemory->deallocate();
747        delete mMemory;
748        mMemory = NULL;
749    }
750}
751
752int32_t QCamera3MetadataChannel::initialize()
753{
754    int32_t rc;
755    cam_dimension_t streamDim;
756
757    if (mMemory || m_numStreams > 0) {
758        ALOGE("%s: metadata channel already initialized", __func__);
759        return -EINVAL;
760    }
761
762    rc = init(NULL, NULL);
763    if (rc < 0) {
764        ALOGE("%s: init failed", __func__);
765        return rc;
766    }
767
768    streamDim.width = sizeof(metadata_buffer_t),
769    streamDim.height = 1;
770    rc = QCamera3Channel::addStream(CAM_STREAM_TYPE_METADATA, CAM_FORMAT_MAX,
771        streamDim, MIN_STREAMING_BUFFER_NUM);
772    if (rc < 0) {
773        ALOGE("%s: addStream failed", __func__);
774    }
775    return rc;
776}
777
778int32_t QCamera3MetadataChannel::request(buffer_handle_t * /*buffer*/,
779                                                uint32_t /*frameNumber*/)
780{
781    if (!m_bIsActive) {
782        return start();
783    }
784    else
785        return 0;
786}
787
788int32_t QCamera3MetadataChannel::registerBuffers(uint32_t /*num_buffers*/,
789                                        buffer_handle_t ** /*buffers*/)
790{
791    // no registerBuffers are supported for metadata channel
792    return -EINVAL;
793}
794
795void QCamera3MetadataChannel::streamCbRoutine(
796                        mm_camera_super_buf_t *super_frame,
797                        QCamera3Stream * /*stream*/)
798{
799    uint32_t requestNumber = 0;
800    if (super_frame == NULL || super_frame->num_bufs != 1) {
801        ALOGE("%s: super_frame is not valid", __func__);
802        return;
803    }
804    mChannelCB(super_frame, NULL, requestNumber, mUserData);
805}
806
807QCamera3Memory* QCamera3MetadataChannel::getStreamBufs(uint32_t len)
808{
809    int rc;
810    if (len < sizeof(metadata_buffer_t)) {
811        ALOGE("%s: size doesn't match %d vs %d", __func__,
812                len, sizeof(metadata_buffer_t));
813        return NULL;
814    }
815    mMemory = new QCamera3HeapMemory();
816    if (!mMemory) {
817        ALOGE("%s: unable to create metadata memory", __func__);
818        return NULL;
819    }
820    rc = mMemory->allocate(MIN_STREAMING_BUFFER_NUM, len, true);
821    if (rc < 0) {
822        ALOGE("%s: unable to allocate metadata memory", __func__);
823        delete mMemory;
824        mMemory = NULL;
825        return NULL;
826    }
827    memset(mMemory->getPtr(0), 0, sizeof(metadata_buffer_t));
828    return mMemory;
829}
830
831void QCamera3MetadataChannel::putStreamBufs()
832{
833    mMemory->deallocate();
834    delete mMemory;
835    mMemory = NULL;
836}
837
838/*===========================================================================
839 * FUNCTION   : jpegEvtHandle
840 *
841 * DESCRIPTION: Function registerd to mm-jpeg-interface to handle jpeg events.
842                Construct result payload and call mChannelCb to deliver buffer
843                to framework.
844 *
845 * PARAMETERS :
846 *   @status    : status of jpeg job
847 *   @client_hdl: jpeg client handle
848 *   @jobId     : jpeg job Id
849 *   @p_ouput   : ptr to jpeg output result struct
850 *   @userdata  : user data ptr
851 *
852 * RETURN     : none
853 *==========================================================================*/
854void QCamera3PicChannel::jpegEvtHandle(jpeg_job_status_t status,
855                                              uint32_t /*client_hdl*/,
856                                              uint32_t jobId,
857                                              mm_jpeg_output_t *p_output,
858                                              void *userdata)
859{
860    buffer_handle_t *resultBuffer;
861    int32_t resultFrameNumber;
862    int resultStatus = CAMERA3_BUFFER_STATUS_OK;
863    camera3_stream_buffer_t result;
864    camera3_jpeg_blob_t jpegHeader;
865    char* jpeg_eof = 0;
866    int maxJpegSize;
867    QCamera3PicChannel *obj = (QCamera3PicChannel *)userdata;
868    if (obj) {
869
870        //Release any cached metabuffer information
871        if (obj->mMetaFrame != NULL && obj->m_pMetaChannel != NULL) {
872            ((QCamera3MetadataChannel*)(obj->m_pMetaChannel))->bufDone(obj->mMetaFrame);
873            obj->mMetaFrame = NULL;
874            obj->m_pMetaChannel = NULL;
875        } else {
876            ALOGE("%s: Meta frame was NULL", __func__);
877        }
878        //Construct payload for process_capture_result. Call mChannelCb
879
880        qcamera_jpeg_data_t *job = obj->m_postprocessor.findJpegJobByJobId(jobId);
881
882        if ((job == NULL) || (status == JPEG_JOB_STATUS_ERROR)) {
883            ALOGE("%s: Error in jobId: (%d) with status: %d", __func__, jobId, status);
884            resultStatus = CAMERA3_BUFFER_STATUS_ERROR;
885        }
886
887        //Construct jpeg transient header of type camera3_jpeg_blob_t
888        //Append at the end of jpeg image of buf_filled_len size
889
890        jpegHeader.jpeg_blob_id = CAMERA3_JPEG_BLOB_ID;
891        jpegHeader.jpeg_size = p_output->buf_filled_len;
892
893
894        char* jpeg_buf = (char *)p_output->buf_vaddr;
895
896        if(obj->mJpegSettings->max_jpeg_size <= 0 ||
897                obj->mJpegSettings->max_jpeg_size > obj->mMemory->getSize(obj->mCurrentBufIndex)){
898            ALOGW("%s:Max Jpeg size :%d is out of valid range setting to size of buffer",
899                    __func__, obj->mJpegSettings->max_jpeg_size);
900            maxJpegSize =  obj->mMemory->getSize(obj->mCurrentBufIndex);
901        } else {
902            maxJpegSize = obj->mJpegSettings->max_jpeg_size;
903            ALOGI("%s: Setting max jpeg size to %d",__func__, maxJpegSize);
904        }
905        jpeg_eof = &jpeg_buf[maxJpegSize-sizeof(jpegHeader)];
906        memcpy(jpeg_eof, &jpegHeader, sizeof(jpegHeader));
907        obj->mMemory->cleanInvalidateCache(obj->mCurrentBufIndex);
908
909        ////Use below data to issue framework callback
910        resultBuffer = obj->mCamera3Buffers[obj->mCurrentBufIndex];
911        resultFrameNumber = obj->mMemory->getFrameNumber(obj->mCurrentBufIndex);
912
913        result.stream = obj->mCamera3Stream;
914        result.buffer = resultBuffer;
915        result.status = resultStatus;
916        result.acquire_fence = -1;
917        result.release_fence = -1;
918
919        ALOGV("%s: Issue Callback", __func__);
920        obj->mChannelCB(NULL, &result, resultFrameNumber, obj->mUserData);
921
922        // release internal data for jpeg job
923        if (job != NULL) {
924            obj->m_postprocessor.releaseJpegJobData(job);
925            free(job);
926        }
927        return;
928        // }
929    } else {
930        ALOGE("%s: Null userdata in jpeg callback", __func__);
931    }
932}
933
934QCamera3PicChannel::QCamera3PicChannel(uint32_t cam_handle,
935                    mm_camera_ops_t *cam_ops,
936                    channel_cb_routine cb_routine,
937                    cam_padding_info_t *paddingInfo,
938                    void *userData,
939                    camera3_stream_t *stream) :
940                        QCamera3Channel(cam_handle, cam_ops, cb_routine,
941                        paddingInfo, userData),
942                        m_postprocessor(this),
943                        mCamera3Stream(stream),
944                        mNumBufs(0),
945                        mCamera3Buffers(NULL),
946                        mJpegSettings(NULL),
947                        mCurrentBufIndex(-1),
948                        mMemory(NULL),
949                        mYuvMemory(NULL),
950                        mMetaFrame(NULL)
951{
952    int32_t rc = m_postprocessor.init(jpegEvtHandle, this);
953    if (rc != 0) {
954        ALOGE("Init Postprocessor failed");
955    }
956}
957
958QCamera3PicChannel::~QCamera3PicChannel()
959{
960    int32_t rc = m_postprocessor.deinit();
961    if (rc != 0) {
962        ALOGE("De-init Postprocessor failed");
963    }
964    if (mCamera3Buffers) {
965        delete[] mCamera3Buffers;
966    }
967}
968
969int32_t QCamera3PicChannel::initialize()
970{
971    int32_t rc = NO_ERROR;
972    cam_dimension_t streamDim;
973    cam_stream_type_t streamType;
974    cam_format_t streamFormat;
975    mm_camera_channel_attr_t attr;
976
977    memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
978    attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_BURST;
979    attr.look_back = 1;
980    attr.post_frame_skip = 1;
981    attr.water_mark = 1;
982    attr.max_unmatched_frames = 1;
983
984    rc = init(&attr, NULL);
985    if (rc < 0) {
986        ALOGE("%s: init failed", __func__);
987        return rc;
988    }
989
990    streamType = CAM_STREAM_TYPE_NON_ZSL_SNAPSHOT;
991    streamFormat = CAM_FORMAT_YUV_420_NV21;
992    streamDim.width = mCamera3Stream->width;
993    streamDim.height = mCamera3Stream->height;
994
995    int num_buffers = 1;
996
997    rc = QCamera3Channel::addStream(streamType, streamFormat, streamDim,
998            num_buffers);
999
1000    return rc;
1001}
1002
1003int32_t QCamera3PicChannel::request(buffer_handle_t *buffer,
1004        uint32_t frameNumber, jpeg_settings_t* jpegSettings,
1005        mm_camera_buf_def_t *pInputBuffer,QCamera3Channel* pInputChannel)
1006{
1007    //FIX ME: Return buffer back in case of failures below.
1008
1009    int32_t rc = NO_ERROR;
1010    int index;
1011    mJpegSettings = jpegSettings;
1012    // Picture stream has already been started before any request comes in
1013    if (!m_bIsActive) {
1014        ALOGE("%s: Picture stream should have been started before any request",
1015            __func__);
1016        return -EINVAL;
1017    }
1018    if (pInputBuffer == NULL)
1019        mStreams[0]->bufDone(0);
1020
1021    if(!mMemory) {
1022        if(pInputBuffer) {
1023            mMemory = new QCamera3GrallocMemory();
1024            if (mMemory == NULL) {
1025                return NO_MEMORY;
1026            }
1027
1028            //Registering Jpeg output buffer
1029            if (mMemory->registerBuffers(mNumBufs, mCamera3Buffers) < 0) {
1030                delete mMemory;
1031                mMemory = NULL;
1032                return NO_MEMORY;
1033            }
1034        } else {
1035            ALOGE("%s: error, Gralloc Memory object not yet created for this stream",__func__);
1036            return NO_MEMORY;
1037        }
1038    }
1039
1040    index = mMemory->getMatchBufIndex((void*)buffer);
1041    if(index < 0) {
1042        ALOGE("%s: Could not find object among registered buffers",__func__);
1043        return DEAD_OBJECT;
1044    }
1045    rc = mMemory->markFrameNumber(index, frameNumber);
1046
1047    //Start the postprocessor for jpeg encoding. Pass mMemory as destination buffer
1048    mCurrentBufIndex = index;
1049
1050    if(pInputBuffer) {
1051        m_postprocessor.start(mMemory, index, pInputChannel);
1052        ALOGD("%s: Post-process started", __func__);
1053        ALOGD("%s: Issue call to reprocess", __func__);
1054        m_postprocessor.processAuxiliaryData(pInputBuffer,pInputChannel);
1055    } else {
1056        m_postprocessor.start(mMemory, index, this);
1057    }
1058    return rc;
1059}
1060
1061/*===========================================================================
1062 * FUNCTION   : dataNotifyCB
1063 *
1064 * DESCRIPTION: Channel Level callback used for super buffer data notify.
1065 *              This function is registered with mm-camera-interface to handle
1066 *              data notify
1067 *
1068 * PARAMETERS :
1069 *   @recvd_frame   : stream frame received
1070 *   userdata       : user data ptr
1071 *
1072 * RETURN     : none
1073 *==========================================================================*/
1074void QCamera3PicChannel::dataNotifyCB(mm_camera_super_buf_t *recvd_frame,
1075                                 void *userdata)
1076{
1077    ALOGV("%s: E\n", __func__);
1078    QCamera3PicChannel *channel = (QCamera3PicChannel *)userdata;
1079
1080    if (channel == NULL) {
1081        ALOGE("%s: invalid channel pointer", __func__);
1082        return;
1083    }
1084
1085    if(channel->m_numStreams != 1) {
1086        ALOGE("%s: Error: Bug: This callback assumes one stream per channel",__func__);
1087        return;
1088    }
1089
1090
1091    if(channel->mStreams[0] == NULL) {
1092        ALOGE("%s: Error: Invalid Stream object",__func__);
1093        return;
1094    }
1095
1096    channel->QCamera3PicChannel::streamCbRoutine(recvd_frame, channel->mStreams[0]);
1097
1098    ALOGV("%s: X\n", __func__);
1099    return;
1100}
1101
1102
1103int32_t QCamera3PicChannel::registerBuffers(uint32_t num_buffers,
1104                        buffer_handle_t **buffers)
1105{
1106    int rc = 0;
1107    cam_stream_type_t streamType;
1108    cam_format_t streamFormat;
1109
1110    ALOGV("%s: E",__func__);
1111    rc = QCamera3PicChannel::initialize();
1112    if (rc < 0) {
1113        ALOGE("%s: init failed", __func__);
1114        return rc;
1115    }
1116
1117    if (mCamera3Stream->format == HAL_PIXEL_FORMAT_BLOB) {
1118        streamType = CAM_STREAM_TYPE_NON_ZSL_SNAPSHOT;
1119        streamFormat = CAM_FORMAT_YUV_420_NV21;
1120    } else {
1121        //TODO: Fail for other types of streams for now
1122        ALOGE("%s: format is not BLOB", __func__);
1123        return -EINVAL;
1124    }
1125    /* Bookkeep buffer set because they go out of scope after register call */
1126    mNumBufs = num_buffers;
1127    mCamera3Buffers = new buffer_handle_t*[num_buffers];
1128    if (mCamera3Buffers == NULL) {
1129        ALOGE("%s: Failed to allocate buffer_handle_t*", __func__);
1130        return -ENOMEM;
1131    }
1132    for (size_t i = 0; i < num_buffers; i++)
1133        mCamera3Buffers[i] = buffers[i];
1134
1135    ALOGV("%s: X",__func__);
1136    return rc;
1137}
1138
1139void QCamera3PicChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
1140                            QCamera3Stream *stream)
1141{
1142    //TODO
1143    //Used only for getting YUV. Jpeg callback will be sent back from channel
1144    //directly to HWI. Refer to func jpegEvtHandle
1145
1146    //Got the yuv callback. Calling yuv callback handler in PostProc
1147    uint8_t frameIndex;
1148    mm_camera_super_buf_t* frame = NULL;
1149    if(!super_frame) {
1150         ALOGE("%s: Invalid Super buffer",__func__);
1151         return;
1152    }
1153
1154    if(super_frame->num_bufs != 1) {
1155         ALOGE("%s: Multiple streams are not supported",__func__);
1156         return;
1157    }
1158    if(super_frame->bufs[0] == NULL ) {
1159         ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
1160                  __func__);
1161         return;
1162    }
1163
1164    frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
1165    if(frameIndex >= mNumBufs) {
1166         ALOGE("%s: Error, Invalid index for buffer",__func__);
1167         if(stream) {
1168             stream->bufDone(frameIndex);
1169         }
1170         return;
1171    }
1172
1173    frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
1174    if (frame == NULL) {
1175       ALOGE("%s: Error allocating memory to save received_frame structure.",
1176                                                                    __func__);
1177       if(stream) {
1178           stream->bufDone(frameIndex);
1179       }
1180       return;
1181    }
1182    *frame = *super_frame;
1183
1184    m_postprocessor.processData(frame);
1185    free(super_frame);
1186    return;
1187}
1188
1189QCamera3Memory* QCamera3PicChannel::getStreamBufs(uint32_t len)
1190{
1191    int rc = 0;
1192
1193    if (mNumBufs == 0 || mCamera3Buffers == NULL) {
1194        ALOGE("%s: buffers not registered yet", __func__);
1195        return NULL;
1196    }
1197
1198    if(mMemory) {
1199        delete mMemory;
1200        mMemory = NULL;
1201    }
1202    mMemory = new QCamera3GrallocMemory();
1203    if (mMemory == NULL) {
1204        return NULL;
1205    }
1206
1207    //Registering Jpeg output buffer
1208    if (mMemory->registerBuffers(mNumBufs, mCamera3Buffers) < 0) {
1209        delete mMemory;
1210        mMemory = NULL;
1211        return NULL;
1212    }
1213
1214    mYuvMemory = new QCamera3HeapMemory();
1215    if (!mYuvMemory) {
1216        ALOGE("%s: unable to create metadata memory", __func__);
1217        return NULL;
1218    }
1219
1220    //Queue YUV buffers in the beginning mQueueAll = true
1221    rc = mYuvMemory->allocate(1, len, false);
1222    if (rc < 0) {
1223        ALOGE("%s: unable to allocate metadata memory", __func__);
1224        delete mYuvMemory;
1225        mYuvMemory = NULL;
1226        return NULL;
1227    }
1228    return mYuvMemory;
1229}
1230
1231void QCamera3PicChannel::putStreamBufs()
1232{
1233    mMemory->unregisterBuffers();
1234    delete mMemory;
1235    mMemory = NULL;
1236
1237    mYuvMemory->deallocate();
1238    delete mYuvMemory;
1239    mYuvMemory = NULL;
1240}
1241
1242bool QCamera3PicChannel::isRawSnapshot()
1243{
1244   return !(mJpegSettings->is_jpeg_format);
1245}
1246/*===========================================================================
1247 * FUNCTION   : getThumbnailSize
1248 *
1249 * DESCRIPTION: get user set thumbnail size
1250 *
1251 * PARAMETERS :
1252 *   @dim     : output of thumbnail dimension
1253 *
1254 * RETURN     : none
1255 *==========================================================================*/
1256void QCamera3PicChannel::getThumbnailSize(cam_dimension_t &dim)
1257{
1258    dim = mJpegSettings->thumbnail_size;
1259}
1260
1261/*===========================================================================
1262 * FUNCTION   : getJpegQuality
1263 *
1264 * DESCRIPTION: get user set jpeg quality
1265 *
1266 * PARAMETERS : none
1267 *
1268 * RETURN     : jpeg quality setting
1269 *==========================================================================*/
1270int QCamera3PicChannel::getJpegQuality()
1271{
1272    int quality = mJpegSettings->jpeg_quality;
1273    if (quality < 0) {
1274        quality = 85;  //set to default quality value
1275    }
1276    return quality;
1277}
1278
1279/*===========================================================================
1280 * FUNCTION   : getJpegRotation
1281 *
1282 * DESCRIPTION: get rotation information to be passed into jpeg encoding
1283 *
1284 * PARAMETERS : none
1285 *
1286 * RETURN     : rotation information
1287 *==========================================================================*/
1288int QCamera3PicChannel::getJpegRotation() {
1289    int rotation = mJpegSettings->jpeg_orientation;
1290    if (rotation < 0) {
1291        rotation = 0;
1292    }
1293    return rotation;
1294}
1295
1296void QCamera3PicChannel::queueMetadata(mm_camera_super_buf_t *metadata_buf,
1297                                       QCamera3Channel *pMetaChannel,
1298                                       bool relinquish)
1299{
1300    if(relinquish)
1301        mMetaFrame = metadata_buf;
1302    m_pMetaChannel = pMetaChannel;
1303    m_postprocessor.processPPMetadata(metadata_buf);
1304}
1305/*===========================================================================
1306 * FUNCTION   : getRational
1307 *
1308 * DESCRIPTION: compose rational struct
1309 *
1310 * PARAMETERS :
1311 *   @rat     : ptr to struct to store rational info
1312 *   @num     :num of the rational
1313 *   @denom   : denom of the rational
1314 *
1315 * RETURN     : int32_t type of status
1316 *              NO_ERROR  -- success
1317 *              none-zero failure code
1318 *==========================================================================*/
1319int32_t getRational(rat_t *rat, int num, int denom)
1320{
1321    if (NULL == rat) {
1322        ALOGE("%s: NULL rat input", __func__);
1323        return BAD_VALUE;
1324    }
1325    rat->num = num;
1326    rat->denom = denom;
1327    return NO_ERROR;
1328}
1329
1330/*===========================================================================
1331 * FUNCTION   : parseGPSCoordinate
1332 *
1333 * DESCRIPTION: parse GPS coordinate string
1334 *
1335 * PARAMETERS :
1336 *   @coord_str : [input] coordinate string
1337 *   @coord     : [output]  ptr to struct to store coordinate
1338 *
1339 * RETURN     : int32_t type of status
1340 *              NO_ERROR  -- success
1341 *              none-zero failure code
1342 *==========================================================================*/
1343int parseGPSCoordinate(const char *coord_str, rat_t* coord)
1344{
1345    if(coord == NULL) {
1346        ALOGE("%s: error, invalid argument coord == NULL", __func__);
1347        return BAD_VALUE;
1348    }
1349    float degF = atof(coord_str);
1350    if (degF < 0) {
1351        degF = -degF;
1352    }
1353    float minF = (degF - (int) degF) * 60;
1354    float secF = (minF - (int) minF) * 60;
1355
1356    getRational(&coord[0], (int)degF, 1);
1357    getRational(&coord[1], (int)minF, 1);
1358    getRational(&coord[2], (int)(secF * 10000), 10000);
1359    return NO_ERROR;
1360}
1361
1362/*===========================================================================
1363 * FUNCTION   : getExifDateTime
1364 *
1365 * DESCRIPTION: query exif date time
1366 *
1367 * PARAMETERS :
1368 *   @dateTime : string to store exif date time
1369 *   @count    : lenght of the dateTime string
1370 *
1371 * RETURN     : int32_t type of status
1372 *              NO_ERROR  -- success
1373 *              none-zero failure code
1374 *==========================================================================*/
1375int32_t getExifDateTime(char *dateTime, uint32_t &count)
1376{
1377    //get time and date from system
1378    time_t rawtime;
1379    struct tm * timeinfo;
1380    time(&rawtime);
1381    timeinfo = localtime (&rawtime);
1382    //Write datetime according to EXIF Spec
1383    //"YYYY:MM:DD HH:MM:SS" (20 chars including \0)
1384    snprintf(dateTime, 20, "%04d:%02d:%02d %02d:%02d:%02d",
1385             timeinfo->tm_year + 1900, timeinfo->tm_mon + 1,
1386             timeinfo->tm_mday, timeinfo->tm_hour,
1387             timeinfo->tm_min, timeinfo->tm_sec);
1388    count = 20;
1389
1390    return NO_ERROR;
1391}
1392
1393/*===========================================================================
1394 * FUNCTION   : getExifFocalLength
1395 *
1396 * DESCRIPTION: get exif focal lenght
1397 *
1398 * PARAMETERS :
1399 *   @focalLength : ptr to rational strcut to store focal lenght
1400 *
1401 * RETURN     : int32_t type of status
1402 *              NO_ERROR  -- success
1403 *              none-zero failure code
1404 *==========================================================================*/
1405int32_t getExifFocalLength(rat_t *focalLength, float value)
1406{
1407    int focalLengthValue =
1408        (int)(value * FOCAL_LENGTH_DECIMAL_PRECISION);
1409    return getRational(focalLength, focalLengthValue, FOCAL_LENGTH_DECIMAL_PRECISION);
1410}
1411
1412/*===========================================================================
1413  * FUNCTION   : getExifExpTimeInfo
1414  *
1415  * DESCRIPTION: get exif exposure time information
1416  *
1417  * PARAMETERS :
1418  *   @expoTimeInfo     : expousure time value
1419  * RETURN     : nt32_t type of status
1420  *              NO_ERROR  -- success
1421  *              none-zero failure code
1422  *==========================================================================*/
1423int32_t getExifExpTimeInfo(rat_t *expoTimeInfo, int64_t value)
1424{
1425
1426    int cal_exposureTime;
1427    if (value != 0)
1428        cal_exposureTime = value;
1429    else
1430        cal_exposureTime = 60;
1431
1432    return getRational(expoTimeInfo, 1, cal_exposureTime);
1433}
1434
1435/*===========================================================================
1436 * FUNCTION   : getExifGpsProcessingMethod
1437 *
1438 * DESCRIPTION: get GPS processing method
1439 *
1440 * PARAMETERS :
1441 *   @gpsProcessingMethod : string to store GPS process method
1442 *   @count               : lenght of the string
1443 *
1444 * RETURN     : int32_t type of status
1445 *              NO_ERROR  -- success
1446 *              none-zero failure code
1447 *==========================================================================*/
1448int32_t getExifGpsProcessingMethod(char *gpsProcessingMethod,
1449                                   uint32_t &count, char* value)
1450{
1451    if(value != NULL) {
1452        memcpy(gpsProcessingMethod, ExifAsciiPrefix, EXIF_ASCII_PREFIX_SIZE);
1453        count = EXIF_ASCII_PREFIX_SIZE;
1454        strncpy(gpsProcessingMethod + EXIF_ASCII_PREFIX_SIZE, value, strlen(value));
1455        count += strlen(value);
1456        gpsProcessingMethod[count++] = '\0'; // increase 1 for the last NULL char
1457        return NO_ERROR;
1458    } else {
1459        return BAD_VALUE;
1460    }
1461}
1462
1463/*===========================================================================
1464 * FUNCTION   : getExifLatitude
1465 *
1466 * DESCRIPTION: get exif latitude
1467 *
1468 * PARAMETERS :
1469 *   @latitude : ptr to rational struct to store latitude info
1470 *   @ladRef   : charater to indicate latitude reference
1471 *
1472 * RETURN     : int32_t type of status
1473 *              NO_ERROR  -- success
1474 *              none-zero failure code
1475 *==========================================================================*/
1476int32_t getExifLatitude(rat_t *latitude,
1477                                           char *latRef, double value)
1478{
1479    char str[30];
1480    snprintf(str, sizeof(str), "%f", value);
1481    if(str != NULL) {
1482        parseGPSCoordinate(str, latitude);
1483
1484        //set Latitude Ref
1485        float latitudeValue = strtof(str, 0);
1486        if(latitudeValue < 0.0f) {
1487            latRef[0] = 'S';
1488        } else {
1489            latRef[0] = 'N';
1490        }
1491        latRef[1] = '\0';
1492        return NO_ERROR;
1493    }else{
1494        return BAD_VALUE;
1495    }
1496}
1497
1498/*===========================================================================
1499 * FUNCTION   : getExifLongitude
1500 *
1501 * DESCRIPTION: get exif longitude
1502 *
1503 * PARAMETERS :
1504 *   @longitude : ptr to rational struct to store longitude info
1505 *   @lonRef    : charater to indicate longitude reference
1506 *
1507 * RETURN     : int32_t type of status
1508 *              NO_ERROR  -- success
1509 *              none-zero failure code
1510 *==========================================================================*/
1511int32_t getExifLongitude(rat_t *longitude,
1512                                            char *lonRef, double value)
1513{
1514    char str[30];
1515    snprintf(str, sizeof(str), "%f", value);
1516    if(str != NULL) {
1517        parseGPSCoordinate(str, longitude);
1518
1519        //set Longitude Ref
1520        float longitudeValue = strtof(str, 0);
1521        if(longitudeValue < 0.0f) {
1522            lonRef[0] = 'W';
1523        } else {
1524            lonRef[0] = 'E';
1525        }
1526        lonRef[1] = '\0';
1527        return NO_ERROR;
1528    }else{
1529        return BAD_VALUE;
1530    }
1531}
1532
1533/*===========================================================================
1534 * FUNCTION   : getExifAltitude
1535 *
1536 * DESCRIPTION: get exif altitude
1537 *
1538 * PARAMETERS :
1539 *   @altitude : ptr to rational struct to store altitude info
1540 *   @altRef   : charater to indicate altitude reference
1541 *
1542 * RETURN     : int32_t type of status
1543 *              NO_ERROR  -- success
1544 *              none-zero failure code
1545 *==========================================================================*/
1546int32_t getExifAltitude(rat_t *altitude,
1547                                           char *altRef, double value)
1548{
1549    char str[30];
1550    snprintf(str, sizeof(str), "%f", value);
1551    if(str != NULL) {
1552        double value = atof(str);
1553        *altRef = 0;
1554        if(value < 0){
1555            *altRef = 1;
1556            value = -value;
1557        }
1558        return getRational(altitude, value*1000, 1000);
1559    }else{
1560        return BAD_VALUE;
1561    }
1562}
1563
1564/*===========================================================================
1565 * FUNCTION   : getExifGpsDateTimeStamp
1566 *
1567 * DESCRIPTION: get exif GPS date time stamp
1568 *
1569 * PARAMETERS :
1570 *   @gpsDateStamp : GPS date time stamp string
1571 *   @bufLen       : length of the string
1572 *   @gpsTimeStamp : ptr to rational struct to store time stamp info
1573 *
1574 * RETURN     : int32_t type of status
1575 *              NO_ERROR  -- success
1576 *              none-zero failure code
1577 *==========================================================================*/
1578int32_t getExifGpsDateTimeStamp(char *gpsDateStamp,
1579                                           uint32_t bufLen,
1580                                           rat_t *gpsTimeStamp, int64_t value)
1581{
1582    char str[30];
1583    snprintf(str, sizeof(str), "%lld", value);
1584    if(str != NULL) {
1585        time_t unixTime = (time_t)atol(str);
1586        struct tm *UTCTimestamp = gmtime(&unixTime);
1587
1588        strftime(gpsDateStamp, bufLen, "%Y:%m:%d", UTCTimestamp);
1589
1590        getRational(&gpsTimeStamp[0], UTCTimestamp->tm_hour, 1);
1591        getRational(&gpsTimeStamp[1], UTCTimestamp->tm_min, 1);
1592        getRational(&gpsTimeStamp[2], UTCTimestamp->tm_sec, 1);
1593
1594        return NO_ERROR;
1595    } else {
1596        return BAD_VALUE;
1597    }
1598}
1599
1600int32_t getExifExposureValue(srat_t* exposure_val, int32_t exposure_comp,
1601                             cam_rational_type_t step)
1602{
1603    exposure_val->num = exposure_comp * step.numerator;
1604    exposure_val->denom = step.denominator;
1605    return 0;
1606}
1607/*===========================================================================
1608 * FUNCTION   : getExifData
1609 *
1610 * DESCRIPTION: get exif data to be passed into jpeg encoding
1611 *
1612 * PARAMETERS : none
1613 *
1614 * RETURN     : exif data from user setting and GPS
1615 *==========================================================================*/
1616QCamera3Exif *QCamera3PicChannel::getExifData()
1617{
1618    QCamera3Exif *exif = new QCamera3Exif();
1619    if (exif == NULL) {
1620        ALOGE("%s: No memory for QCamera3Exif", __func__);
1621        return NULL;
1622    }
1623
1624    int32_t rc = NO_ERROR;
1625    uint32_t count = 0;
1626
1627    // add exif entries
1628    char dateTime[20];
1629    memset(dateTime, 0, sizeof(dateTime));
1630    count = 20;
1631    rc = getExifDateTime(dateTime, count);
1632    if(rc == NO_ERROR) {
1633        exif->addEntry(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL,
1634                       EXIF_ASCII,
1635                       count,
1636                       (void *)dateTime);
1637        exif->addEntry(EXIFTAGID_EXIF_DATE_TIME_DIGITIZED,
1638                       EXIF_ASCII,
1639                       count,
1640                       (void *)dateTime);
1641    } else {
1642        ALOGE("%s: getExifDateTime failed", __func__);
1643    }
1644
1645    rat_t focalLength;
1646    rc = getExifFocalLength(&focalLength, mJpegSettings->lens_focal_length);
1647    if (rc == NO_ERROR) {
1648        exif->addEntry(EXIFTAGID_FOCAL_LENGTH,
1649                       EXIF_RATIONAL,
1650                       1,
1651                       (void *)&(focalLength));
1652    } else {
1653        ALOGE("%s: getExifFocalLength failed", __func__);
1654    }
1655
1656    uint16_t isoSpeed = (uint16_t)mJpegSettings->sensor_sensitivity;
1657    exif->addEntry(EXIFTAGID_ISO_SPEED_RATING,
1658                   EXIF_SHORT,
1659                   1,
1660                   (void *)&(isoSpeed));
1661
1662    rat_t sensorExpTime ;
1663    rc = getExifExpTimeInfo(&sensorExpTime, (int64_t)mJpegSettings->sensor_exposure_time);
1664    if (rc == NO_ERROR){
1665        exif->addEntry(EXIFTAGID_EXPOSURE_TIME,
1666                       EXIF_RATIONAL,
1667                       1,
1668                       (void *)&(sensorExpTime));
1669    } else {
1670        ALOGE("%s: getExifExpTimeInfo failed", __func__);
1671    }
1672
1673    if (strlen(mJpegSettings->gps_processing_method) > 0) {
1674        char gpsProcessingMethod[EXIF_ASCII_PREFIX_SIZE + GPS_PROCESSING_METHOD_SIZE];
1675        count = 0;
1676        rc = getExifGpsProcessingMethod(gpsProcessingMethod, count, mJpegSettings->gps_processing_method);
1677        if(rc == NO_ERROR) {
1678            exif->addEntry(EXIFTAGID_GPS_PROCESSINGMETHOD,
1679                           EXIF_ASCII,
1680                           count,
1681                           (void *)gpsProcessingMethod);
1682        } else {
1683            ALOGE("%s: getExifGpsProcessingMethod failed", __func__);
1684        }
1685    }
1686
1687    if (mJpegSettings->gps_coordinates[0]) {
1688        rat_t latitude[3];
1689        char latRef[2];
1690        rc = getExifLatitude(latitude, latRef, *(mJpegSettings->gps_coordinates[0]));
1691        if(rc == NO_ERROR) {
1692            exif->addEntry(EXIFTAGID_GPS_LATITUDE,
1693                           EXIF_RATIONAL,
1694                           3,
1695                           (void *)latitude);
1696            exif->addEntry(EXIFTAGID_GPS_LATITUDE_REF,
1697                           EXIF_ASCII,
1698                           2,
1699                           (void *)latRef);
1700        } else {
1701            ALOGE("%s: getExifLatitude failed", __func__);
1702        }
1703    }
1704
1705    if (mJpegSettings->gps_coordinates[1]) {
1706        rat_t longitude[3];
1707        char lonRef[2];
1708        rc = getExifLongitude(longitude, lonRef, *(mJpegSettings->gps_coordinates[1]));
1709        if(rc == NO_ERROR) {
1710            exif->addEntry(EXIFTAGID_GPS_LONGITUDE,
1711                           EXIF_RATIONAL,
1712                           3,
1713                           (void *)longitude);
1714
1715            exif->addEntry(EXIFTAGID_GPS_LONGITUDE_REF,
1716                           EXIF_ASCII,
1717                           2,
1718                           (void *)lonRef);
1719        } else {
1720            ALOGE("%s: getExifLongitude failed", __func__);
1721        }
1722    }
1723
1724    if (mJpegSettings->gps_coordinates[2]) {
1725        rat_t altitude;
1726        char altRef;
1727        rc = getExifAltitude(&altitude, &altRef, *(mJpegSettings->gps_coordinates[2]));
1728        if(rc == NO_ERROR) {
1729            exif->addEntry(EXIFTAGID_GPS_ALTITUDE,
1730                           EXIF_RATIONAL,
1731                           1,
1732                           (void *)&(altitude));
1733
1734            exif->addEntry(EXIFTAGID_GPS_ALTITUDE_REF,
1735                           EXIF_BYTE,
1736                           1,
1737                           (void *)&altRef);
1738        } else {
1739            ALOGE("%s: getExifAltitude failed", __func__);
1740        }
1741    }
1742
1743    if (mJpegSettings->gps_timestamp) {
1744        char gpsDateStamp[20];
1745        rat_t gpsTimeStamp[3];
1746        rc = getExifGpsDateTimeStamp(gpsDateStamp, 20, gpsTimeStamp, *(mJpegSettings->gps_timestamp));
1747        if(rc == NO_ERROR) {
1748            exif->addEntry(EXIFTAGID_GPS_DATESTAMP,
1749                           EXIF_ASCII,
1750                           strlen(gpsDateStamp) + 1,
1751                           (void *)gpsDateStamp);
1752
1753            exif->addEntry(EXIFTAGID_GPS_TIMESTAMP,
1754                           EXIF_RATIONAL,
1755                           3,
1756                           (void *)gpsTimeStamp);
1757        } else {
1758            ALOGE("%s: getExifGpsDataTimeStamp failed", __func__);
1759        }
1760    }
1761
1762    srat_t exposure_val;
1763    rc = getExifExposureValue(&exposure_val, mJpegSettings->exposure_compensation,
1764                              mJpegSettings->exposure_comp_step);
1765    if(rc == NO_ERROR) {
1766        exif->addEntry(EXIFTAGID_EXPOSURE_BIAS_VALUE,
1767                       EXIF_SRATIONAL,
1768                       1,
1769                       (void *)(&exposure_val));
1770    } else {
1771        ALOGE("%s: getExifExposureValue failed ", __func__);
1772    }
1773
1774    char value[PROPERTY_VALUE_MAX];
1775    if (property_get("ro.product.manufacturer", value, "QCOM-AA") > 0) {
1776        exif->addEntry(EXIFTAGID_MAKE,
1777                       EXIF_ASCII,
1778                       strlen(value) + 1,
1779                       (void *)value);
1780    } else {
1781        ALOGE("%s: getExifMaker failed", __func__);
1782    }
1783
1784    if (property_get("ro.product.model", value, "QCAM-AA") > 0) {
1785        exif->addEntry(EXIFTAGID_MODEL,
1786                       EXIF_ASCII,
1787                       strlen(value) + 1,
1788                       (void *)value);
1789    } else {
1790        ALOGE("%s: getExifModel failed", __func__);
1791    }
1792
1793    return exif;
1794}
1795
1796int QCamera3PicChannel::kMaxBuffers = 2;
1797
1798/*===========================================================================
1799 * FUNCTION   : QCamera3ReprocessChannel
1800 *
1801 * DESCRIPTION: constructor of QCamera3ReprocessChannel
1802 *
1803 * PARAMETERS :
1804 *   @cam_handle : camera handle
1805 *   @cam_ops    : ptr to camera ops table
1806 *   @pp_mask    : post-proccess feature mask
1807 *
1808 * RETURN     : none
1809 *==========================================================================*/
1810QCamera3ReprocessChannel::QCamera3ReprocessChannel(uint32_t cam_handle,
1811                                                 mm_camera_ops_t *cam_ops,
1812                                                 channel_cb_routine cb_routine,
1813                                                 cam_padding_info_t *paddingInfo,
1814                                                 void *userData, void *ch_hdl) :
1815    QCamera3Channel(cam_handle, cam_ops, cb_routine, paddingInfo, userData),
1816    picChHandle(ch_hdl),
1817    m_pSrcChannel(NULL),
1818    m_pMetaChannel(NULL),
1819    mMemory(NULL)
1820{
1821    memset(mSrcStreamHandles, 0, sizeof(mSrcStreamHandles));
1822}
1823
1824
1825/*===========================================================================
1826 * FUNCTION   : QCamera3ReprocessChannel
1827 *
1828 * DESCRIPTION: constructor of QCamera3ReprocessChannel
1829 *
1830 * PARAMETERS :
1831 *   @cam_handle : camera handle
1832 *   @cam_ops    : ptr to camera ops table
1833 *   @pp_mask    : post-proccess feature mask
1834 *
1835 * RETURN     : none
1836 *==========================================================================*/
1837int32_t QCamera3ReprocessChannel::initialize()
1838{
1839    int32_t rc = NO_ERROR;
1840    mm_camera_channel_attr_t attr;
1841
1842    memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
1843    attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS;
1844    attr.max_unmatched_frames = 1;
1845
1846    rc = init(&attr, NULL);
1847    if (rc < 0) {
1848        ALOGE("%s: init failed", __func__);
1849    }
1850    return rc;
1851}
1852
1853
1854/*===========================================================================
1855 * FUNCTION   : QCamera3ReprocessChannel
1856 *
1857 * DESCRIPTION: constructor of QCamera3ReprocessChannel
1858 *
1859 * PARAMETERS :
1860 *   @cam_handle : camera handle
1861 *   @cam_ops    : ptr to camera ops table
1862 *   @pp_mask    : post-proccess feature mask
1863 *
1864 * RETURN     : none
1865 *==========================================================================*/
1866void QCamera3ReprocessChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
1867                                  QCamera3Stream *stream)
1868{
1869    //Got the pproc data callback. Now send to jpeg encoding
1870    uint8_t frameIndex;
1871    mm_camera_super_buf_t* frame = NULL;
1872    QCamera3PicChannel *obj = (QCamera3PicChannel *)picChHandle;
1873
1874    if(!super_frame) {
1875         ALOGE("%s: Invalid Super buffer",__func__);
1876         return;
1877    }
1878
1879    if(super_frame->num_bufs != 1) {
1880         ALOGE("%s: Multiple streams are not supported",__func__);
1881         return;
1882    }
1883    if(super_frame->bufs[0] == NULL ) {
1884         ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
1885                  __func__);
1886         return;
1887    }
1888
1889    frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
1890    frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
1891    if (frame == NULL) {
1892       ALOGE("%s: Error allocating memory to save received_frame structure.",
1893                                                                    __func__);
1894       if(stream) {
1895           stream->bufDone(frameIndex);
1896       }
1897       return;
1898    }
1899    *frame = *super_frame;
1900    obj->m_postprocessor.processPPData(frame);
1901    return;
1902}
1903
1904/*===========================================================================
1905 * FUNCTION   : QCamera3ReprocessChannel
1906 *
1907 * DESCRIPTION: default constructor of QCamera3ReprocessChannel
1908 *
1909 * PARAMETERS : none
1910 *
1911 * RETURN     : none
1912 *==========================================================================*/
1913QCamera3ReprocessChannel::QCamera3ReprocessChannel() :
1914    m_pSrcChannel(NULL),
1915    m_pMetaChannel(NULL)
1916{
1917}
1918
1919/*===========================================================================
1920 * FUNCTION   : QCamera3ReprocessChannel
1921 *
1922 * DESCRIPTION: register the buffers of the reprocess channel
1923 *
1924 * PARAMETERS : none
1925 *
1926 * RETURN     : none
1927 *==========================================================================*/
1928int32_t QCamera3ReprocessChannel::registerBuffers(
1929    uint32_t /*num_buffers*/, buffer_handle_t ** /*buffers*/)
1930{
1931   return 0;
1932}
1933
1934/*===========================================================================
1935 * FUNCTION   : getStreamBufs
1936 *
1937 * DESCRIPTION: register the buffers of the reprocess channel
1938 *
1939 * PARAMETERS : none
1940 *
1941 * RETURN     : QCamera3Memory *
1942 *==========================================================================*/
1943QCamera3Memory* QCamera3ReprocessChannel::getStreamBufs(uint32_t len)
1944{
1945   int rc = 0;
1946
1947    mMemory = new QCamera3HeapMemory();
1948    if (!mMemory) {
1949        ALOGE("%s: unable to create reproc memory", __func__);
1950        return NULL;
1951    }
1952
1953    //Queue YUV buffers in the beginning mQueueAll = true
1954    rc = mMemory->allocate(2, len, true);
1955    if (rc < 0) {
1956        ALOGE("%s: unable to allocate reproc memory", __func__);
1957        delete mMemory;
1958        mMemory = NULL;
1959        return NULL;
1960    }
1961    return mMemory;
1962}
1963
1964/*===========================================================================
1965 * FUNCTION   : getStreamBufs
1966 *
1967 * DESCRIPTION: register the buffers of the reprocess channel
1968 *
1969 * PARAMETERS : none
1970 *
1971 * RETURN     :
1972 *==========================================================================*/
1973void QCamera3ReprocessChannel::putStreamBufs()
1974{
1975    mMemory->deallocate();
1976    delete mMemory;
1977    mMemory = NULL;
1978}
1979
1980/*===========================================================================
1981 * FUNCTION   : ~QCamera3ReprocessChannel
1982 *
1983 * DESCRIPTION: destructor of QCamera3ReprocessChannel
1984 *
1985 * PARAMETERS : none
1986 *
1987 * RETURN     : none
1988 *==========================================================================*/
1989QCamera3ReprocessChannel::~QCamera3ReprocessChannel()
1990{
1991}
1992
1993/*===========================================================================
1994 * FUNCTION   : getStreamBySourceHandle
1995 *
1996 * DESCRIPTION: find reprocess stream by its source stream handle
1997 *
1998 * PARAMETERS :
1999 *   @srcHandle : source stream handle
2000 *
2001 * RETURN     : ptr to reprocess stream if found. NULL if not found
2002 *==========================================================================*/
2003QCamera3Stream * QCamera3ReprocessChannel::getStreamBySourceHandle(uint32_t srcHandle)
2004{
2005    QCamera3Stream *pStream = NULL;
2006
2007    for (int i = 0; i < m_numStreams; i++) {
2008        if (mSrcStreamHandles[i] == srcHandle) {
2009            pStream = mStreams[i];
2010            break;
2011        }
2012    }
2013    return pStream;
2014}
2015
2016/*===========================================================================
2017 * FUNCTION   : metadataBufDone
2018 *
2019 * DESCRIPTION: buf done method for a metadata buffer
2020 *
2021 * PARAMETERS :
2022 *   @recvd_frame : received metadata frame
2023 *
2024 * RETURN     :
2025 *==========================================================================*/
2026int32_t QCamera3ReprocessChannel::metadataBufDone(mm_camera_super_buf_t *recvd_frame)
2027{
2028   int32_t rc;
2029   rc = ((QCamera3MetadataChannel*)m_pMetaChannel)->bufDone(recvd_frame);
2030   free(recvd_frame);
2031   recvd_frame = NULL;
2032   return rc;
2033}
2034
2035/*===========================================================================
2036 * FUNCTION   : doReprocess
2037 *
2038 * DESCRIPTION: request to do a reprocess on the frame
2039 *
2040 * PARAMETERS :
2041 *   @frame   : frame to be performed a reprocess
2042 *
2043 * RETURN     : int32_t type of status
2044 *              NO_ERROR  -- success
2045 *              none-zero failure code
2046 *==========================================================================*/
2047int32_t QCamera3ReprocessChannel::doReprocess(mm_camera_super_buf_t *frame,
2048                                              mm_camera_super_buf_t *meta_frame)
2049{
2050    int32_t rc = 0;
2051    if (m_numStreams < 1) {
2052        ALOGE("%s: No reprocess stream is created", __func__);
2053        return -1;
2054    }
2055    if (m_pSrcChannel == NULL) {
2056        ALOGE("%s: No source channel for reprocess", __func__);
2057        return -1;
2058    }
2059    for (int i = 0; i < frame->num_bufs; i++) {
2060        QCamera3Stream *pStream = getStreamBySourceHandle(frame->bufs[i]->stream_id);
2061        if (pStream != NULL) {
2062            cam_stream_parm_buffer_t param;
2063            memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
2064            param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
2065            param.reprocess.buf_index = frame->bufs[i]->buf_idx;
2066            param.reprocess.frame_idx = frame->bufs[i]->frame_idx;
2067            if (meta_frame != NULL) {
2068               param.reprocess.meta_present = 1;
2069               param.reprocess.meta_stream_handle = m_pMetaChannel->mStreams[0]->getMyServerID();
2070               param.reprocess.meta_buf_index = meta_frame->bufs[0]->buf_idx;
2071            }
2072            rc = pStream->setParameter(param);
2073            if (rc != NO_ERROR) {
2074                ALOGE("%s: stream setParameter for reprocess failed", __func__);
2075                break;
2076            }
2077        }
2078    }
2079    return rc;
2080}
2081
2082/*===========================================================================
2083 * FUNCTION   : doReprocess
2084 *
2085 * DESCRIPTION: request to do a reprocess on the frame
2086 *
2087 * PARAMETERS :
2088 *   @buf_fd     : fd to the input buffer that needs reprocess
2089 *   @buf_lenght : length of the input buffer
2090 *   @ret_val    : result of reprocess.
2091 *                 Example: Could be faceID in case of register face image.
2092 *
2093 * RETURN     : int32_t type of status
2094 *              NO_ERROR  -- success
2095 *              none-zero failure code
2096 *==========================================================================*/
2097int32_t QCamera3ReprocessChannel::doReprocess(int buf_fd,
2098                                              uint32_t buf_length,
2099                                              int32_t &ret_val,
2100                                              mm_camera_super_buf_t *meta_frame)
2101{
2102    int32_t rc = 0;
2103    if (m_numStreams < 1) {
2104        ALOGE("%s: No reprocess stream is created", __func__);
2105        return -1;
2106    }
2107    if (meta_frame == NULL) {
2108        ALOGE("%s: Did not get corresponding metadata in time", __func__);
2109        return -1;
2110    }
2111
2112    uint32_t buf_idx = 0;
2113    for (int i = 0; i < m_numStreams; i++) {
2114        rc = mStreams[i]->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
2115                                 buf_idx, -1,
2116                                 buf_fd, buf_length);
2117
2118        if (rc == NO_ERROR) {
2119            cam_stream_parm_buffer_t param;
2120            memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
2121            param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
2122            param.reprocess.buf_index = buf_idx;
2123            param.reprocess.meta_present = 1;
2124            param.reprocess.meta_stream_handle = m_pMetaChannel->mStreams[0]->getMyServerID();
2125            param.reprocess.meta_buf_index = meta_frame->bufs[0]->buf_idx;
2126            rc = mStreams[i]->setParameter(param);
2127            if (rc == NO_ERROR) {
2128                ret_val = param.reprocess.ret_val;
2129            }
2130            mStreams[i]->unmapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
2131                                  buf_idx, -1);
2132        }
2133    }
2134    return rc;
2135}
2136
2137/*===========================================================================
2138 * FUNCTION   : addReprocStreamsFromSource
2139 *
2140 * DESCRIPTION: add reprocess streams from input source channel
2141 *
2142 * PARAMETERS :
2143 *   @config         : pp feature configuration
2144 *   @pSrcChannel    : ptr to input source channel that needs reprocess
2145 *   @pMetaChannel   : ptr to metadata channel to get corresp. metadata
2146 *
2147 * RETURN     : int32_t type of status
2148 *              NO_ERROR  -- success
2149 *              none-zero failure code
2150 *==========================================================================*/
2151int32_t QCamera3ReprocessChannel::addReprocStreamsFromSource(cam_pp_feature_config_t &config,
2152                                                             QCamera3Channel *pSrcChannel,
2153                                                             QCamera3Channel *pMetaChannel)
2154{
2155    int32_t rc = 0;
2156    QCamera3Stream *pSrcStream = pSrcChannel->getStreamByIndex(0);
2157    if (pSrcStream == NULL) {
2158       ALOGE("%s: source channel doesn't have a stream", __func__);
2159       return BAD_VALUE;
2160    }
2161    cam_stream_reproc_config_t reprocess_config;
2162    cam_dimension_t streamDim;
2163    cam_stream_type_t streamType;
2164    cam_format_t streamFormat;
2165    cam_frame_len_offset_t frameOffset;
2166    int num_buffers = 2;
2167
2168    streamType = CAM_STREAM_TYPE_OFFLINE_PROC;
2169    pSrcStream->getFormat(streamFormat);
2170    pSrcStream->getFrameDimension(streamDim);
2171    pSrcStream->getFrameOffset(frameOffset);
2172
2173    reprocess_config.pp_type = CAM_ONLINE_REPROCESS_TYPE;
2174    reprocess_config.online.input_stream_id = pSrcStream->getMyServerID();
2175    reprocess_config.online.input_stream_type = pSrcStream->getMyType();
2176    reprocess_config.pp_feature_config = config;
2177
2178    mSrcStreamHandles[m_numStreams] = pSrcStream->getMyHandle();
2179
2180    if (reprocess_config.pp_feature_config.feature_mask & CAM_QCOM_FEATURE_ROTATION) {
2181        if (reprocess_config.pp_feature_config.rotation == ROTATE_90 ||
2182            reprocess_config.pp_feature_config.rotation == ROTATE_270) {
2183            // rotated by 90 or 270, need to switch width and height
2184            int32_t temp = streamDim.height;
2185            streamDim.height = streamDim.width;
2186            streamDim.width = temp;
2187        }
2188    }
2189
2190    QCamera3Stream *pStream = new QCamera3Stream(m_camHandle,
2191                                               m_handle,
2192                                               m_camOps,
2193                                               mPaddingInfo,
2194                                               (QCamera3Channel*)this);
2195    if (pStream == NULL) {
2196        ALOGE("%s: No mem for Stream", __func__);
2197        return NO_MEMORY;
2198    }
2199
2200    rc = pStream->init(streamType, streamFormat, streamDim, &reprocess_config,
2201                       num_buffers,QCamera3Channel::streamCbRoutine, this);
2202
2203
2204    if (rc == 0) {
2205        mStreams[m_numStreams] = pStream;
2206        m_numStreams++;
2207    } else {
2208        ALOGE("%s: failed to create reprocess stream", __func__);
2209        delete pStream;
2210    }
2211
2212    if (rc == NO_ERROR) {
2213        m_pSrcChannel = pSrcChannel;
2214        m_pMetaChannel = pMetaChannel;
2215    }
2216    if(m_camOps->request_super_buf(m_camHandle,m_handle,1) < 0) {
2217        ALOGE("%s: Request for super buffer failed",__func__);
2218    }
2219    return rc;
2220}
2221
2222
2223}; // namespace qcamera
2224