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 "QCameraChannel"
31
32#include <utils/Errors.h>
33#include "QCameraParameters.h"
34#include "QCamera2HWI.h"
35#include "QCameraChannel.h"
36
37using namespace android;
38
39namespace qcamera {
40
41/*===========================================================================
42 * FUNCTION   : QCameraChannel
43 *
44 * DESCRIPTION: constrcutor of QCameraChannel
45 *
46 * PARAMETERS :
47 *   @cam_handle : camera handle
48 *   @cam_ops    : ptr to camera ops table
49 *
50 * RETURN     : none
51 *==========================================================================*/
52QCameraChannel::QCameraChannel(uint32_t cam_handle,
53                               mm_camera_ops_t *cam_ops)
54{
55    m_camHandle = cam_handle;
56    m_camOps = cam_ops;
57    m_bIsActive = false;
58    m_bAllowDynBufAlloc = false;
59
60    m_handle = 0;
61    m_numStreams = 0;
62    memset(mStreams, 0, sizeof(mStreams));
63}
64
65/*===========================================================================
66 * FUNCTION   : QCameraChannel
67 *
68 * DESCRIPTION: default constrcutor of QCameraChannel
69 *
70 * PARAMETERS : none
71 *
72 * RETURN     : none
73 *==========================================================================*/
74QCameraChannel::QCameraChannel()
75{
76    m_camHandle = 0;
77    m_camOps = NULL;
78    m_bIsActive = false;
79
80    m_handle = 0;
81    m_numStreams = 0;
82    memset(mStreams, 0, sizeof(mStreams));
83}
84
85/*===========================================================================
86 * FUNCTION   : ~QCameraChannel
87 *
88 * DESCRIPTION: destructor of QCameraChannel
89 *
90 * PARAMETERS : none
91 *
92 * RETURN     : none
93 *==========================================================================*/
94QCameraChannel::~QCameraChannel()
95{
96    if (m_bIsActive) {
97        stop();
98    }
99
100    for (int i = 0; i < m_numStreams; i++) {
101        if (mStreams[i] != NULL) {
102            delete mStreams[i];
103            mStreams[i] = 0;
104        }
105    }
106    m_numStreams = 0;
107    m_camOps->delete_channel(m_camHandle, m_handle);
108    m_handle = 0;
109}
110
111/*===========================================================================
112 * FUNCTION   : deleteChannel
113 *
114 * DESCRIPTION: deletes a camera channel
115 *
116 * PARAMETERS : none
117 *
118 * RETURN     : none
119 *==========================================================================*/
120void QCameraChannel::deleteChannel()
121{
122    if (m_bIsActive) {
123        stop();
124    }
125
126    for (int i = 0; i < m_numStreams; i++) {
127        if (mStreams[i] != NULL) {
128            mStreams[i]->deleteStream();
129        }
130    }
131    m_camOps->delete_channel(m_camHandle, m_handle);
132}
133
134/*===========================================================================
135 * FUNCTION   : init
136 *
137 * DESCRIPTION: initialization of channel
138 *
139 * PARAMETERS :
140 *   @attr    : channel bundle attribute setting
141 *   @dataCB  : data notify callback
142 *   @userData: user data ptr
143 *
144 * RETURN     : int32_t type of status
145 *              NO_ERROR  -- success
146 *              none-zero failure code
147 *==========================================================================*/
148int32_t QCameraChannel::init(mm_camera_channel_attr_t *attr,
149                             mm_camera_buf_notify_t dataCB,
150                             void *userData)
151{
152    m_handle = m_camOps->add_channel(m_camHandle,
153                                      attr,
154                                      dataCB,
155                                      userData);
156    if (m_handle == 0) {
157        ALOGE("%s: Add channel failed", __func__);
158        return UNKNOWN_ERROR;
159    }
160    return NO_ERROR;
161}
162
163/*===========================================================================
164 * FUNCTION   : addStream
165 *
166 * DESCRIPTION: add a stream into channel
167 *
168 * PARAMETERS :
169 *   @allocator      : stream related buffer allocator
170 *   @streamInfoBuf  : ptr to buf that constains stream info
171 *   @minStreamBufNum: number of stream buffers needed
172 *   @paddingInfo    : padding information
173 *   @stream_cb      : stream data notify callback
174 *   @userdata       : user data ptr
175 *   @bDynAllocBuf   : flag indicating if allow allocate buffers in 2 steps
176 *
177 * RETURN     : int32_t type of status
178 *              NO_ERROR  -- success
179 *              none-zero failure code
180 *==========================================================================*/
181int32_t QCameraChannel::addStream(QCameraAllocator &allocator,
182                                  QCameraHeapMemory *streamInfoBuf,
183                                  uint8_t minStreamBufNum,
184                                  cam_padding_info_t *paddingInfo,
185                                  stream_cb_routine stream_cb,
186                                  void *userdata,
187                                  bool bDynAllocBuf,
188                                  bool bDeffAlloc)
189{
190    int32_t rc = NO_ERROR;
191    if (m_numStreams >= MAX_STREAM_NUM_IN_BUNDLE) {
192        ALOGE("%s: stream number (%d) exceeds max limit (%d)",
193              __func__, m_numStreams, MAX_STREAM_NUM_IN_BUNDLE);
194        return BAD_VALUE;
195    }
196    QCameraStream *pStream = new QCameraStream(allocator,
197                                               m_camHandle,
198                                               m_handle,
199                                               m_camOps,
200                                               paddingInfo,
201                                               bDeffAlloc);
202    if (pStream == NULL) {
203        ALOGE("%s: No mem for Stream", __func__);
204        return NO_MEMORY;
205    }
206
207    rc = pStream->init(streamInfoBuf, minStreamBufNum,
208                       stream_cb, userdata, bDynAllocBuf);
209    if (rc == 0) {
210        mStreams[m_numStreams] = pStream;
211        m_numStreams++;
212    } else {
213        delete pStream;
214    }
215    return rc;
216}
217/*===========================================================================
218 * FUNCTION   : config
219 *
220 * DESCRIPTION: Configure any deffered channel streams
221 *
222 * PARAMETERS : None
223 *
224 * RETURN     : int32_t type of status
225 *              NO_ERROR  -- success
226 *              none-zero failure code
227 *==========================================================================*/
228int32_t QCameraChannel::config()
229{
230    int32_t rc = NO_ERROR;
231
232    for (int i = 0; i < m_numStreams; ++i) {
233        if ( mStreams[i]->isDeffered() ) {
234            rc = mStreams[i]->configStream();
235            if (rc != NO_ERROR) {
236                break;
237            }
238        }
239    }
240
241    return rc;
242}
243
244/*===========================================================================
245 * FUNCTION   : start
246 *
247 * DESCRIPTION: start channel, which will start all streams belong to this channel
248 *
249 * PARAMETERS : None
250 *
251 * RETURN     : int32_t type of status
252 *              NO_ERROR  -- success
253 *              none-zero failure code
254 *==========================================================================*/
255int32_t QCameraChannel::start()
256{
257    int32_t rc = NO_ERROR;
258
259    if (m_numStreams > 1) {
260        // there is more than one stream in the channel
261        // we need to notify mctl that all streams in this channel need to be bundled
262        cam_bundle_config_t bundleInfo;
263        memset(&bundleInfo, 0, sizeof(bundleInfo));
264        rc = m_camOps->get_bundle_info(m_camHandle, m_handle, &bundleInfo);
265        if (rc != NO_ERROR) {
266            ALOGE("%s: get_bundle_info failed", __func__);
267            return rc;
268        }
269        if (bundleInfo.num_of_streams > 1) {
270            for (int i = 0; i < bundleInfo.num_of_streams; i++) {
271                QCameraStream *pStream = getStreamByServerID(bundleInfo.stream_ids[i]);
272                if (pStream != NULL) {
273                    if (pStream->isTypeOf(CAM_STREAM_TYPE_METADATA)) {
274                        // Skip metadata for reprocess now because PP module cannot handle meta data
275                        // May need furthur discussion if Imaginglib need meta data
276                        continue;
277                    }
278
279                    cam_stream_parm_buffer_t param;
280                    memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
281                    param.type = CAM_STREAM_PARAM_TYPE_SET_BUNDLE_INFO;
282                    param.bundleInfo = bundleInfo;
283                    rc = pStream->setParameter(param);
284                    if (rc != NO_ERROR) {
285                        ALOGE("%s: stream setParameter for set bundle failed", __func__);
286                        return rc;
287                    }
288                }
289            }
290        }
291    }
292
293    for (int i = 0; i < m_numStreams; i++) {
294        if (mStreams[i] != NULL) {
295            mStreams[i]->start();
296        }
297    }
298    rc = m_camOps->start_channel(m_camHandle, m_handle);
299
300    if (rc != NO_ERROR) {
301        for (int i = 0; i < m_numStreams; i++) {
302            if (mStreams[i] != NULL) {
303                mStreams[i]->stop();
304            }
305        }
306    } else {
307        m_bIsActive = true;
308        for (int i = 0; i < m_numStreams; i++) {
309            if (mStreams[i] != NULL) {
310                mStreams[i]->cond_signal();
311            }
312        }
313    }
314
315    return rc;
316}
317
318/*===========================================================================
319 * FUNCTION   : stop
320 *
321 * DESCRIPTION: stop a channel, which will stop all streams belong to this channel
322 *
323 * PARAMETERS : none
324 *
325 * RETURN     : int32_t type of status
326 *              NO_ERROR  -- success
327 *              none-zero failure code
328 *==========================================================================*/
329int32_t QCameraChannel::stop()
330{
331    int32_t rc = NO_ERROR;
332    for (int i = 0; i < m_numStreams; i++) {
333        if (mStreams[i] != NULL) {
334            mStreams[i]->stop();
335        }
336    }
337
338    rc = m_camOps->stop_channel(m_camHandle, m_handle);
339
340    m_bIsActive = false;
341    return rc;
342}
343
344/*===========================================================================
345 * FUNCTION   : bufDone
346 *
347 * DESCRIPTION: return a stream buf back to kernel
348 *
349 * PARAMETERS :
350 *   @recvd_frame  : stream buf frame to be returned
351 *
352 * RETURN     : int32_t type of status
353 *              NO_ERROR  -- success
354 *              none-zero failure code
355 *==========================================================================*/
356int32_t QCameraChannel::bufDone(mm_camera_super_buf_t *recvd_frame)
357{
358    int32_t rc = NO_ERROR;
359    for (int i = 0; i < recvd_frame->num_bufs; i++) {
360         if (recvd_frame->bufs[i] != NULL) {
361             for (int j = 0; j < m_numStreams; j++) {
362                 if (mStreams[j] != NULL &&
363                     mStreams[j]->getMyHandle() == recvd_frame->bufs[i]->stream_id) {
364                     rc = mStreams[j]->bufDone(recvd_frame->bufs[i]->buf_idx);
365                     break; // break loop j
366                 }
367             }
368         }
369    }
370
371    return rc;
372}
373
374/*===========================================================================
375 * FUNCTION   : processZoomDone
376 *
377 * DESCRIPTION: process zoom done event
378 *
379 * PARAMETERS :
380 *   @previewWindoe : ptr to preview window ops table, needed to set preview
381 *                    crop information
382 *   @crop_info     : crop info as a result of zoom operation
383 *
384 * RETURN     : int32_t type of status
385 *              NO_ERROR  -- success
386 *              none-zero failure code
387 *==========================================================================*/
388int32_t QCameraChannel::processZoomDone(preview_stream_ops_t *previewWindow,
389                                        cam_crop_data_t &crop_info)
390{
391    int32_t rc = NO_ERROR;
392    for (int i = 0; i < m_numStreams; i++) {
393        if (mStreams[i] != NULL) {
394            rc = mStreams[i]->processZoomDone(previewWindow, crop_info);
395        }
396    }
397    return rc;
398}
399
400/*===========================================================================
401 * FUNCTION   : getStreamByHandle
402 *
403 * DESCRIPTION: return stream object by stream handle
404 *
405 * PARAMETERS :
406 *   @streamHandle : stream handle
407 *
408 * RETURN     : stream object. NULL if not found
409 *==========================================================================*/
410QCameraStream *QCameraChannel::getStreamByHandle(uint32_t streamHandle)
411{
412    for (int i = 0; i < m_numStreams; i++) {
413        if (mStreams[i] != NULL && mStreams[i]->getMyHandle() == streamHandle) {
414            return mStreams[i];
415        }
416    }
417    return NULL;
418}
419
420/*===========================================================================
421 * FUNCTION   : getStreamByServerID
422 *
423 * DESCRIPTION: return stream object by stream server ID from daemon
424 *
425 * PARAMETERS :
426 *   @serverID : stream server ID
427 *
428 * RETURN     : stream object. NULL if not found
429 *==========================================================================*/
430QCameraStream *QCameraChannel::getStreamByServerID(uint32_t serverID)
431{
432    for (int i = 0; i < m_numStreams; i++) {
433        if (mStreams[i] != NULL && mStreams[i]->getMyServerID() == serverID) {
434            return mStreams[i];
435        }
436    }
437    return NULL;
438}
439
440/*===========================================================================
441 * FUNCTION   : getStreamByIndex
442 *
443 * DESCRIPTION: return stream object by index of streams in the channel
444 *
445 * PARAMETERS :
446 *   @index : index of stream in the channel
447 *
448 * RETURN     : stream object. NULL if not found
449 *==========================================================================*/
450QCameraStream *QCameraChannel::getStreamByIndex(uint8_t index)
451{
452    if (index >= MAX_STREAM_NUM_IN_BUNDLE) {
453        return NULL;
454    }
455
456    if (index < m_numStreams) {
457        return mStreams[index];
458    }
459    return NULL;
460}
461
462/*===========================================================================
463 * FUNCTION   : UpdateStreamBasedParameters
464 *
465 * DESCRIPTION: update any stream based settings from parameters
466 *
467 * PARAMETERS :
468 *   @param   : reference to parameters object
469 *
470 * RETURN     : int32_t type of status
471 *              NO_ERROR  -- success
472 *              none-zero failure code
473 *==========================================================================*/
474int32_t QCameraChannel::UpdateStreamBasedParameters(QCameraParameters &param)
475{
476    int32_t rc = NO_ERROR;
477    if (param.isPreviewFlipChanged()) {
478        // try to find preview stream
479        for (int i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) {
480            if (mStreams[i] != NULL &&
481                (mStreams[i]->isTypeOf(CAM_STREAM_TYPE_PREVIEW) ||
482                (mStreams[i]->isOrignalTypeOf(CAM_STREAM_TYPE_PREVIEW))) ) {
483                cam_stream_parm_buffer_t param_buf;
484                memset(&param_buf, 0, sizeof(cam_stream_parm_buffer_t));
485                param_buf.type = CAM_STREAM_PARAM_TYPE_SET_FLIP;
486                param_buf.flipInfo.flip_mask = param.getFlipMode(CAM_STREAM_TYPE_PREVIEW);
487                rc = mStreams[i]->setParameter(param_buf);
488                if (rc != NO_ERROR) {
489                    ALOGE("%s: set preview stream flip failed", __func__);
490                }
491            }
492        }
493    }
494    if (param.isVideoFlipChanged()) {
495        // try to find video stream
496        for (int i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) {
497            if (mStreams[i] != NULL &&
498                (mStreams[i]->isTypeOf(CAM_STREAM_TYPE_VIDEO) ||
499                (mStreams[i]->isOrignalTypeOf(CAM_STREAM_TYPE_VIDEO))) ) {
500                cam_stream_parm_buffer_t param_buf;
501                memset(&param_buf, 0, sizeof(cam_stream_parm_buffer_t));
502                param_buf.type = CAM_STREAM_PARAM_TYPE_SET_FLIP;
503                param_buf.flipInfo.flip_mask = param.getFlipMode(CAM_STREAM_TYPE_VIDEO);
504                rc = mStreams[i]->setParameter(param_buf);
505                if (rc != NO_ERROR) {
506                    ALOGE("%s: set video stream flip failed", __func__);
507                }
508            }
509        }
510    }
511    if (param.isSnapshotFlipChanged()) {
512        // try to find snapshot/postview stream
513        for (int i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) {
514            if (mStreams[i] != NULL &&
515                (mStreams[i]->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
516                 mStreams[i]->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
517                 mStreams[i]->isTypeOf(CAM_STREAM_TYPE_POSTVIEW) ||
518                 mStreams[i]->isOrignalTypeOf(CAM_STREAM_TYPE_POSTVIEW) ) ) {
519                cam_stream_parm_buffer_t param_buf;
520                memset(&param_buf, 0, sizeof(cam_stream_parm_buffer_t));
521                param_buf.type = CAM_STREAM_PARAM_TYPE_SET_FLIP;
522                param_buf.flipInfo.flip_mask = param.getFlipMode(CAM_STREAM_TYPE_SNAPSHOT);
523                rc = mStreams[i]->setParameter(param_buf);
524                if (rc != NO_ERROR) {
525                    ALOGE("%s: set snapshot stream flip failed", __func__);
526                }
527            }
528        }
529    }
530    return rc;
531}
532
533/*===========================================================================
534 * FUNCTION   : QCameraPicChannel
535 *
536 * DESCRIPTION: constructor of QCameraPicChannel
537 *
538 * PARAMETERS :
539 *   @cam_handle : camera handle
540 *   @cam_ops    : ptr to camera ops table
541 *
542 * RETURN     : none
543 *==========================================================================*/
544QCameraPicChannel::QCameraPicChannel(uint32_t cam_handle,
545                                     mm_camera_ops_t *cam_ops) :
546    QCameraChannel(cam_handle, cam_ops)
547{
548    m_bAllowDynBufAlloc = true;
549}
550
551/*===========================================================================
552 * FUNCTION   : QCameraPicChannel
553 *
554 * DESCRIPTION: default constructor of QCameraPicChannel
555 *
556 * PARAMETERS : none
557 *
558 * RETURN     : none
559 *==========================================================================*/
560QCameraPicChannel::QCameraPicChannel()
561{
562    m_bAllowDynBufAlloc = true;
563}
564
565/*===========================================================================
566 * FUNCTION   : ~QCameraPicChannel
567 *
568 * DESCRIPTION: destructor of QCameraPicChannel
569 *
570 * PARAMETERS : none
571 *
572 * RETURN     : none
573 *==========================================================================*/
574QCameraPicChannel::~QCameraPicChannel()
575{
576}
577
578/*===========================================================================
579 * FUNCTION   : takePicture
580 *
581 * DESCRIPTION: send request for queued snapshot frames
582 *
583 * PARAMETERS :
584 *   @num_of_snapshot : number of snapshot frames requested
585 *   @num_of_retro_snapshot : number of retro snapshot frames requested
586 *
587 * RETURN     : int32_t type of status
588 *              NO_ERROR  -- success
589 *              none-zero failure code
590 *==========================================================================*/
591int32_t QCameraPicChannel::takePicture (
592    uint8_t num_of_snapshot,
593    uint8_t num_of_retro_snapshot)
594{
595    int32_t rc = m_camOps->request_super_buf(m_camHandle,
596                                             m_handle,
597                                             num_of_snapshot,
598                                             num_of_retro_snapshot);
599    return rc;
600}
601
602/*===========================================================================
603 * FUNCTION   : cancelPicture
604 *
605 * DESCRIPTION: cancel request for queued snapshot frames
606 *
607 * PARAMETERS : none
608 *
609 * RETURN     : int32_t type of status
610 *              NO_ERROR  -- success
611 *              none-zero failure code
612 *==========================================================================*/
613int32_t QCameraPicChannel::cancelPicture()
614{
615    int32_t rc = m_camOps->cancel_super_buf_request(m_camHandle, m_handle);
616    return rc;
617}
618
619/*===========================================================================
620 * FUNCTION   : startAdvancedCapture
621 *
622 * DESCRIPTION: start advanced capture based on advanced capture type.
623 *
624 * PARAMETERS :
625 *   @type : advanced capture type.
626 *
627 * RETURN     : int32_t type of status
628 *              NO_ERROR  -- success
629 *              none-zero failure code
630 *==========================================================================*/
631int32_t QCameraPicChannel::startAdvancedCapture(mm_camera_advanced_capture_t type)
632{
633    int32_t rc = m_camOps->process_advanced_capture(m_camHandle, type,
634                                              m_handle, 1);
635    return rc;
636}
637
638/*===========================================================================
639 * FUNCTION   : QCameraVideoChannel
640 *
641 * DESCRIPTION: constructor of QCameraVideoChannel
642 *
643 * PARAMETERS :
644 *   @cam_handle : camera handle
645 *   @cam_ops    : ptr to camera ops table
646 *
647 * RETURN     : none
648 *==========================================================================*/
649QCameraVideoChannel::QCameraVideoChannel(uint32_t cam_handle,
650                                         mm_camera_ops_t *cam_ops) :
651    QCameraChannel(cam_handle, cam_ops)
652{
653}
654
655/*===========================================================================
656 * FUNCTION   : QCameraVideoChannel
657 *
658 * DESCRIPTION: default constructor of QCameraVideoChannel
659 *
660 * PARAMETERS : none
661 *
662 * RETURN     : none
663 *==========================================================================*/
664QCameraVideoChannel::QCameraVideoChannel()
665{
666}
667
668/*===========================================================================
669 * FUNCTION   : ~QCameraVideoChannel
670 *
671 * DESCRIPTION: destructor of QCameraVideoChannel
672 *
673 * PARAMETERS : none
674 *
675 * RETURN     : none
676 *==========================================================================*/
677QCameraVideoChannel::~QCameraVideoChannel()
678{
679}
680
681/*===========================================================================
682 * FUNCTION   : releaseFrame
683 *
684 * DESCRIPTION: return video frame from app
685 *
686 * PARAMETERS :
687 *   @opaque     : ptr to video frame to be returned
688 *   @isMetaData : if frame is a metadata or real frame
689 *
690 * RETURN     : int32_t type of status
691 *              NO_ERROR  -- success
692 *              none-zero failure code
693 *==========================================================================*/
694int32_t QCameraVideoChannel::releaseFrame(const void * opaque, bool isMetaData)
695{
696    QCameraStream *pVideoStream = NULL;
697    for (int i = 0; i < m_numStreams; i++) {
698        if (mStreams[i] != NULL && mStreams[i]->isTypeOf(CAM_STREAM_TYPE_VIDEO)) {
699            pVideoStream = mStreams[i];
700            break;
701        }
702    }
703
704    if (NULL == pVideoStream) {
705        ALOGE("%s: No video stream in the channel", __func__);
706        return BAD_VALUE;
707    }
708
709    int32_t rc = pVideoStream->bufDone(opaque, isMetaData);
710    return rc;
711}
712
713/*===========================================================================
714 * FUNCTION   : QCameraReprocessChannel
715 *
716 * DESCRIPTION: constructor of QCameraReprocessChannel
717 *
718 * PARAMETERS :
719 *   @cam_handle : camera handle
720 *   @cam_ops    : ptr to camera ops table
721 *   @pp_mask    : post-proccess feature mask
722 *
723 * RETURN     : none
724 *==========================================================================*/
725QCameraReprocessChannel::QCameraReprocessChannel(uint32_t cam_handle,
726                                                 mm_camera_ops_t *cam_ops) :
727    QCameraChannel(cam_handle, cam_ops),
728    m_pSrcChannel(NULL)
729{
730    memset(mSrcStreamHandles, 0, sizeof(mSrcStreamHandles));
731}
732
733/*===========================================================================
734 * FUNCTION   : QCameraReprocessChannel
735 *
736 * DESCRIPTION: default constructor of QCameraReprocessChannel
737 *
738 * PARAMETERS : none
739 *
740 * RETURN     : none
741 *==========================================================================*/
742QCameraReprocessChannel::QCameraReprocessChannel() :
743    m_pSrcChannel(NULL)
744{
745}
746
747/*===========================================================================
748 * FUNCTION   : ~QCameraReprocessChannel
749 *
750 * DESCRIPTION: destructor of QCameraReprocessChannel
751 *
752 * PARAMETERS : none
753 *
754 * RETURN     : none
755 *==========================================================================*/
756QCameraReprocessChannel::~QCameraReprocessChannel()
757{
758}
759
760/*===========================================================================
761 * FUNCTION   : addReprocStreamsFromSource
762 *
763 * DESCRIPTION: add reprocess streams from input source channel
764 *
765 * PARAMETERS :
766 *   @allocator      : stream related buffer allocator
767 *   @config         : pp feature configuration
768 *   @pSrcChannel    : ptr to input source channel that needs reprocess
769 *   @minStreamBufNum: number of stream buffers needed
770 *   @burstNum       : number of burst captures needed
771 *   @paddingInfo    : padding information
772 *   @param          : reference to parameters
773 *   @contStream     : continous streaming mode or burst
774 *   @offline        : configure for offline reprocessing
775 *
776 * RETURN     : int32_t type of status
777 *              NO_ERROR  -- success
778 *              none-zero failure code
779 *==========================================================================*/
780int32_t QCameraReprocessChannel::addReprocStreamsFromSource(QCameraAllocator& allocator,
781                                                            cam_pp_feature_config_t &config,
782                                                            QCameraChannel *pSrcChannel,
783                                                            uint8_t minStreamBufNum,
784                                                            uint32_t burstNum,
785                                                            cam_padding_info_t *paddingInfo,
786                                                            QCameraParameters &param,
787                                                            bool contStream,
788                                                            bool offline)
789{
790    int32_t rc = 0;
791    QCameraStream *pStream = NULL;
792    QCameraHeapMemory *pStreamInfoBuf = NULL;
793    cam_stream_info_t *streamInfo = NULL;
794
795    memset(mSrcStreamHandles, 0, sizeof(mSrcStreamHandles));
796
797    for (int i = 0; i < pSrcChannel->getNumOfStreams(); i++) {
798        pStream = pSrcChannel->getStreamByIndex(i);
799        if (pStream != NULL) {
800            if (pStream->isTypeOf(CAM_STREAM_TYPE_METADATA) ||
801                pStream->isTypeOf(CAM_STREAM_TYPE_RAW)) {
802                // Skip metadata&raw for reprocess now because PP module cannot handle
803                // meta data&raw. May need furthur discussion if Imaginglib need meta data
804                continue;
805            }
806
807            if (pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW) ||
808                pStream->isTypeOf(CAM_STREAM_TYPE_PREVIEW)) {
809                // Skip postview: in non zsl case, dont want to send
810                // thumbnail through reprocess.
811                // Skip preview: for same reason for zsl case
812                continue;
813            }
814
815            if(pStream->isTypeOf(CAM_STREAM_TYPE_PREVIEW) ||
816               pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW) ||
817               pStream->isOrignalTypeOf(CAM_STREAM_TYPE_PREVIEW) ||
818               pStream->isOrignalTypeOf(CAM_STREAM_TYPE_POSTVIEW)) {
819                  uint32_t feature_mask = config.feature_mask;
820
821                  if ((feature_mask & ~CAM_QCOM_FEATURE_HDR) == 0
822                      && param.isHDREnabled()
823                      && !param.isHDRThumbnailProcessNeeded()) {
824
825                      // Skip thumbnail stream reprocessing in HDR
826                      // if only hdr is enabled
827                      continue;
828                  }
829
830                  // skip thumbnail reprocessing if not needed
831                  if (!param.needThumbnailReprocess(&feature_mask)) {
832                      continue;
833                  }
834
835                  //Don't do WNR for thumbnail
836                  feature_mask &= ~CAM_QCOM_FEATURE_DENOISE2D;
837                  if(!feature_mask) {
838                    // Skip thumbnail stream reprocessing since no other
839                    //reprocessing is enabled.
840                      continue;
841                  }
842            }
843
844            pStreamInfoBuf = allocator.allocateStreamInfoBuf(CAM_STREAM_TYPE_OFFLINE_PROC);
845            if (pStreamInfoBuf == NULL) {
846                ALOGE("%s: no mem for stream info buf", __func__);
847                rc = NO_MEMORY;
848                break;
849            }
850
851            streamInfo = (cam_stream_info_t *)pStreamInfoBuf->getPtr(0);
852            memset(streamInfo, 0, sizeof(cam_stream_info_t));
853            streamInfo->stream_type = CAM_STREAM_TYPE_OFFLINE_PROC;
854            rc = pStream->getFormat(streamInfo->fmt);
855            rc = pStream->getFrameDimension(streamInfo->dim);
856            if ( contStream ) {
857                streamInfo->streaming_mode = CAM_STREAMING_MODE_CONTINUOUS;
858                streamInfo->num_of_burst = 0;
859            } else {
860                streamInfo->streaming_mode = CAM_STREAMING_MODE_BURST;
861                streamInfo->num_of_burst = burstNum;
862            }
863
864            cam_stream_reproc_config_t rp_cfg;
865            memset(&rp_cfg, 0, sizeof(cam_stream_reproc_config_t));
866            if (offline) {
867                cam_frame_len_offset_t offset;
868                memset(&offset, 0, sizeof(cam_frame_len_offset_t));
869
870                rp_cfg.pp_type = CAM_OFFLINE_REPROCESS_TYPE;
871                pStream->getFormat(rp_cfg.offline.input_fmt);
872                pStream->getFrameDimension(rp_cfg.offline.input_dim);
873                pStream->getFrameOffset(offset);
874                rp_cfg.offline.input_buf_planes.plane_info = offset;
875                rp_cfg.offline.input_type = pStream->getMyType();
876                //For input metadata + input buffer
877                rp_cfg.offline.num_of_bufs = 2;
878            } else {
879                rp_cfg.pp_type = CAM_ONLINE_REPROCESS_TYPE;
880                rp_cfg.online.input_stream_id = pStream->getMyServerID();
881                rp_cfg.online.input_stream_type = pStream->getMyType();
882            }
883            streamInfo->reprocess_config = rp_cfg;
884            streamInfo->reprocess_config.pp_feature_config = config;
885
886            if (!(pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
887                pStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT))) {
888                streamInfo->reprocess_config.pp_feature_config.feature_mask &= ~CAM_QCOM_FEATURE_CAC;
889                //Don't do WNR for thumbnail
890                streamInfo->reprocess_config.pp_feature_config.feature_mask &= ~CAM_QCOM_FEATURE_DENOISE2D;
891
892                if (param.isHDREnabled()
893                  && !param.isHDRThumbnailProcessNeeded()){
894                    streamInfo->reprocess_config.pp_feature_config.feature_mask
895                      &= ~CAM_QCOM_FEATURE_HDR;
896                }
897            }
898
899            if (streamInfo->reprocess_config.pp_feature_config.feature_mask & CAM_QCOM_FEATURE_ROTATION) {
900                if (streamInfo->reprocess_config.pp_feature_config.rotation == ROTATE_90 ||
901                    streamInfo->reprocess_config.pp_feature_config.rotation == ROTATE_270) {
902                    // rotated by 90 or 270, need to switch width and height
903                    int32_t temp = streamInfo->dim.height;
904                    streamInfo->dim.height = streamInfo->dim.width;
905                    streamInfo->dim.width = temp;
906                }
907            }
908
909            if (param.isZSLMode() &&
910                (streamInfo->reprocess_config.online.input_stream_type == CAM_STREAM_TYPE_SNAPSHOT)) {
911                // ZSL mode snapshot need reprocess to do the flip
912                int flipMode =
913                    param.getFlipMode(streamInfo->reprocess_config.online.input_stream_type);
914                if (flipMode > 0) {
915                    streamInfo->reprocess_config.pp_feature_config.feature_mask |= CAM_QCOM_FEATURE_FLIP;
916                    streamInfo->reprocess_config.pp_feature_config.flip = flipMode;
917                }
918            }
919
920            if(streamInfo->reprocess_config.pp_feature_config.feature_mask & CAM_QCOM_FEATURE_SCALE){
921                //we only Scale Snapshot frame
922                if(pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT)){
923                    //also check whether rotation is needed
924                    if((streamInfo->reprocess_config.pp_feature_config.feature_mask & CAM_QCOM_FEATURE_ROTATION) &&
925                       (streamInfo->reprocess_config.pp_feature_config.rotation == ROTATE_90 ||
926                        streamInfo->reprocess_config.pp_feature_config.rotation == ROTATE_270)){
927                        //need swap
928                        streamInfo->dim.width = streamInfo->reprocess_config.pp_feature_config.scale_param.output_height;
929                        streamInfo->dim.height = streamInfo->reprocess_config.pp_feature_config.scale_param.output_width;
930                    }else{
931                        streamInfo->dim.width = streamInfo->reprocess_config.pp_feature_config.scale_param.output_width;
932                        streamInfo->dim.height = streamInfo->reprocess_config.pp_feature_config.scale_param.output_height;
933                    }
934                }
935                CDBG_HIGH("%s: stream width=%d, height=%d.", __func__, streamInfo->dim.width, streamInfo->dim.height);
936            }
937
938            // save source stream handler
939            mSrcStreamHandles[m_numStreams] = pStream->getMyHandle();
940
941            // add reprocess stream
942            rc = addStream(allocator,
943                           pStreamInfoBuf, minStreamBufNum,
944                           paddingInfo,
945                           NULL, NULL, false);
946            if (rc != NO_ERROR) {
947                ALOGE("%s: add reprocess stream failed, ret = %d", __func__, rc);
948                break;
949            }
950        }
951    }
952
953    if (rc == NO_ERROR) {
954        m_pSrcChannel = pSrcChannel;
955    }
956    return rc;
957}
958
959/*===========================================================================
960 * FUNCTION   : getStreamBySrouceHandle
961 *
962 * DESCRIPTION: find reprocess stream by its source stream handle
963 *
964 * PARAMETERS :
965 *   @srcHandle : source stream handle
966 *
967 * RETURN     : ptr to reprocess stream if found. NULL if not found
968 *==========================================================================*/
969QCameraStream * QCameraReprocessChannel::getStreamBySrouceHandle(uint32_t srcHandle)
970{
971    QCameraStream *pStream = NULL;
972
973    for (int i = 0; i < m_numStreams; i++) {
974        if (mSrcStreamHandles[i] == srcHandle) {
975            pStream = mStreams[i];
976            break;
977        }
978    }
979
980    return pStream;
981}
982
983/*===========================================================================
984 * FUNCTION   : stop
985 *
986 * DESCRIPTION: Unmap offline buffers and stop channel
987 *
988 * PARAMETERS : none
989 *
990 * RETURN     : int32_t type of status
991 *              NO_ERROR  -- success
992 *              none-zero failure code
993 *==========================================================================*/
994int32_t QCameraReprocessChannel::stop()
995{
996    if (!mOfflineBuffers.empty()) {
997        QCameraStream *stream = NULL;
998        List<OfflineBuffer>::iterator it = mOfflineBuffers.begin();
999        int error = NO_ERROR;
1000        for( ; it != mOfflineBuffers.end(); it++) {
1001            stream = (*it).stream;
1002            if (NULL != stream) {
1003                error = stream->unmapBuf((*it).type,
1004                                         (*it).index,
1005                                         -1);
1006                if (NO_ERROR != error) {
1007                    ALOGE("%s: Error during offline buffer unmap %d",
1008                          __func__, error);
1009                }
1010            }
1011        }
1012        mOfflineBuffers.clear();
1013    }
1014
1015    return QCameraChannel::stop();
1016}
1017
1018/*===========================================================================
1019 * FUNCTION   : doReprocessOffline
1020 *
1021 * DESCRIPTION: request to do offline reprocess on the frame
1022 *
1023 * PARAMETERS :
1024 *   @frame   : frame to be performed a reprocess
1025 *
1026 * RETURN     : int32_t type of status
1027 *              NO_ERROR  -- success
1028 *              none-zero failure code
1029 *==========================================================================*/
1030int32_t QCameraReprocessChannel::doReprocessOffline(
1031                mm_camera_super_buf_t *frame)
1032{
1033    int32_t rc = 0;
1034    OfflineBuffer mappedBuffer;
1035
1036    if (m_numStreams < 1) {
1037        ALOGE("%s: No reprocess stream is created", __func__);
1038        return -1;
1039    }
1040    if (m_pSrcChannel == NULL) {
1041        ALOGE("%s: No source channel for reprocess", __func__);
1042        return -1;
1043    }
1044
1045    if (frame == NULL) {
1046        ALOGE("%s: Invalid source frame", __func__);
1047        return BAD_VALUE;
1048    }
1049
1050    // find meta data stream and index of meta data frame in the superbuf
1051    uint8_t meta_buf_index = -1;
1052    mm_camera_buf_def_t *meta_buf = NULL;
1053    QCameraStream *pStream = NULL;
1054    for (int i = 0; i < frame->num_bufs; i++) {
1055        pStream = m_pSrcChannel->getStreamByHandle(frame->bufs[i]->stream_id);
1056        if (pStream != NULL) {
1057            if (pStream->isTypeOf(CAM_STREAM_TYPE_METADATA)) {
1058                meta_buf = frame->bufs[i];
1059                break;
1060            }
1061        }
1062    }
1063
1064    for (int i = 0; i < frame->num_bufs; i++) {
1065        pStream = getStreamBySrouceHandle(frame->bufs[i]->stream_id);
1066        if (pStream != NULL) {
1067            if (pStream->isTypeOf(CAM_STREAM_TYPE_METADATA)) {
1068                continue;
1069            }
1070
1071            meta_buf_index = 0;
1072            if (NULL != meta_buf) {
1073                rc = pStream->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF,
1074                                     meta_buf_index,
1075                                     -1,
1076                                     meta_buf->fd,
1077                                     meta_buf->frame_len);
1078                if (NO_ERROR != rc ) {
1079                    ALOGE("%s : Error during metadata buffer mapping",
1080                          __func__);
1081                    break;
1082                }
1083            }
1084            mappedBuffer.index = meta_buf_index;
1085            mappedBuffer.stream = pStream;
1086            mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF;
1087            mOfflineBuffers.push_back(mappedBuffer);
1088
1089            int buf_index = 1;
1090            rc = pStream->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
1091                                 buf_index,
1092                                 -1,
1093                                 frame->bufs[i]->fd,
1094                                 frame->bufs[i]->frame_len);
1095            if (NO_ERROR != rc ) {
1096                ALOGE("%s : Error during reprocess input buffer mapping",
1097                      __func__);
1098                break;
1099            }
1100            mappedBuffer.index = buf_index;
1101            mappedBuffer.stream = pStream;
1102            mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF;
1103            mOfflineBuffers.push_back(mappedBuffer);
1104
1105            cam_stream_parm_buffer_t param;
1106            memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
1107            param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
1108            param.reprocess.buf_index = buf_index;
1109            param.reprocess.frame_pp_config.uv_upsample =
1110                            frame->bufs[i]->is_uv_subsampled;
1111            if (NULL != meta_buf) {
1112                // we have meta data sent together with reprocess frame
1113                param.reprocess.meta_present = 1;
1114                param.reprocess.meta_buf_index = meta_buf_index;
1115                uint32_t stream_id = frame->bufs[i]->stream_id;
1116                QCameraStream *srcStream =
1117                        m_pSrcChannel->getStreamByHandle(stream_id);
1118                metadata_buffer_t *pMetaData =
1119                        (metadata_buffer_t *)meta_buf->buffer;
1120                if (NULL != pMetaData) {
1121                    cam_crop_data_t *crop = NULL;
1122                    if (IS_META_AVAILABLE(CAM_INTF_META_CROP_DATA, pMetaData)) {
1123                        crop = (cam_crop_data_t *)
1124                            POINTER_OF_META(CAM_INTF_META_CROP_DATA, pMetaData);
1125                    }
1126
1127                    if ((NULL != crop) && (NULL != srcStream)) {
1128                        for (int j = 0; j < MAX_NUM_STREAMS; j++) {
1129                            if (crop->crop_info[j].stream_id ==
1130                                            srcStream->getMyServerID()) {
1131                                param.reprocess.frame_pp_config.crop.crop_enabled = 1;
1132                                param.reprocess.frame_pp_config.crop.input_crop =
1133                                        crop->crop_info[j].crop;
1134                                break;
1135                            }
1136                        }
1137                    }
1138                }
1139            }
1140            rc = pStream->setParameter(param);
1141            if (rc != NO_ERROR) {
1142                ALOGE("%s: stream setParameter for reprocess failed",
1143                      __func__);
1144                break;
1145            }
1146        }
1147    }
1148    return rc;
1149}
1150
1151/*===========================================================================
1152 * FUNCTION   : doReprocess
1153 *
1154 * DESCRIPTION: request to do a reprocess on the frame
1155 *
1156 * PARAMETERS :
1157 *   @frame   : frame to be performed a reprocess
1158 *
1159 * RETURN     : int32_t type of status
1160 *              NO_ERROR  -- success
1161 *              none-zero failure code
1162 *==========================================================================*/
1163int32_t QCameraReprocessChannel::doReprocess(mm_camera_super_buf_t *frame)
1164{
1165    int32_t rc = 0;
1166    if (m_numStreams < 1) {
1167        ALOGE("%s: No reprocess stream is created", __func__);
1168        return -1;
1169    }
1170    if (m_pSrcChannel == NULL) {
1171        ALOGE("%s: No source channel for reprocess", __func__);
1172        return -1;
1173    }
1174
1175    // find meta data stream and index of meta data frame in the superbuf
1176    QCameraStream *pMetaStream = NULL;
1177    uint8_t meta_buf_index = 0;
1178    for (int i = 0; i < frame->num_bufs; i++) {
1179        QCameraStream *pStream = m_pSrcChannel->getStreamByHandle(frame->bufs[i]->stream_id);
1180        if (pStream != NULL) {
1181            if (pStream->isTypeOf(CAM_STREAM_TYPE_METADATA)) {
1182                meta_buf_index = frame->bufs[i]->buf_idx;
1183                pMetaStream = pStream;
1184                break;
1185            }
1186        }
1187    }
1188
1189    for (int i = 0; i < frame->num_bufs; i++) {
1190        QCameraStream *pStream = getStreamBySrouceHandle(frame->bufs[i]->stream_id);
1191        if (pStream != NULL) {
1192            if (pStream->isTypeOf(CAM_STREAM_TYPE_METADATA)) {
1193                // Skip metadata for reprocess now because PP module cannot handle meta data
1194                // May need furthur discussion if Imaginglib need meta data
1195                continue;
1196            }
1197
1198            if (pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW) ||
1199                pStream->isTypeOf(CAM_STREAM_TYPE_PREVIEW)) {
1200                // Skip postview: In non zsl case, dont want to send
1201                // thumbnail through reprocess.
1202                // Skip preview: for same reason in ZSL case
1203                continue;
1204            }
1205
1206            cam_stream_parm_buffer_t param;
1207            memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
1208            param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
1209            param.reprocess.buf_index = frame->bufs[i]->buf_idx;
1210            param.reprocess.frame_idx = frame->bufs[i]->frame_idx;
1211            param.reprocess.frame_pp_config.uv_upsample = frame->bufs[i]->is_uv_subsampled;
1212            if (pMetaStream != NULL) {
1213                // we have meta data frame bundled, sent together with reprocess frame
1214                param.reprocess.meta_present = 1;
1215                param.reprocess.meta_stream_handle = pMetaStream->getMyServerID();
1216                param.reprocess.meta_buf_index = meta_buf_index;
1217            }
1218            rc = pStream->setParameter(param);
1219            if (rc != NO_ERROR) {
1220                ALOGE("%s: stream setParameter for reprocess failed", __func__);
1221                break;
1222            }
1223        }
1224    }
1225    return rc;
1226}
1227
1228/*===========================================================================
1229 * FUNCTION   : doReprocess
1230 *
1231 * DESCRIPTION: request to do a reprocess on the frame
1232 *
1233 * PARAMETERS :
1234 *   @buf_fd     : fd to the input buffer that needs reprocess
1235 *   @buf_lenght : length of the input buffer
1236 *   @ret_val    : result of reprocess.
1237 *                 Example: Could be faceID in case of register face image.
1238 *
1239 * RETURN     : int32_t type of status
1240 *              NO_ERROR  -- success
1241 *              none-zero failure code
1242 *==========================================================================*/
1243int32_t QCameraReprocessChannel::doReprocess(int buf_fd,
1244                                             uint32_t buf_length,
1245                                             int32_t &ret_val)
1246{
1247    int32_t rc = 0;
1248    if (m_numStreams < 1) {
1249        ALOGE("%s: No reprocess stream is created", __func__);
1250        return -1;
1251    }
1252
1253    uint32_t buf_idx = 0;
1254    for (int i = 0; i < m_numStreams; i++) {
1255        rc = mStreams[i]->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
1256                                 buf_idx, -1,
1257                                 buf_fd, buf_length);
1258
1259        if (rc == NO_ERROR) {
1260            cam_stream_parm_buffer_t param;
1261            memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
1262            param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
1263            param.reprocess.buf_index = buf_idx;
1264            rc = mStreams[i]->setParameter(param);
1265            if (rc == NO_ERROR) {
1266                ret_val = param.reprocess.ret_val;
1267            }
1268            mStreams[i]->unmapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
1269                                  buf_idx, -1);
1270        }
1271    }
1272    return rc;
1273}
1274
1275}; // namespace qcamera
1276