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