1 /* Copyright (c) 2012-2016, The Linux Foundation. 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
31 #define LOG_TAG "QCamera3Channel"
32
33 // To remove
34 #include <cutils/properties.h>
35
36 // System dependencies
37 #include <fcntl.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include "gralloc.h"
41
42 // Camera dependencies
43 #include "QCamera3Channel.h"
44 #include "QCamera3HWI.h"
45 #include "QCameraTrace.h"
46
47 extern "C" {
48 #include "mm_camera_dbg.h"
49 }
50
51 using namespace android;
52
53 namespace qcamera {
54 #define IS_BUFFER_ERROR(x) (((x) & V4L2_BUF_FLAG_ERROR) == V4L2_BUF_FLAG_ERROR)
55
56 /*===========================================================================
57 * FUNCTION : QCamera3Channel
58 *
59 * DESCRIPTION: constrcutor of QCamera3Channel
60 *
61 * PARAMETERS :
62 * @cam_handle : camera handle
63 * @cam_ops : ptr to camera ops table
64 *
65 * RETURN : none
66 *==========================================================================*/
QCamera3Channel(uint32_t cam_handle,uint32_t channel_handle,mm_camera_ops_t * cam_ops,channel_cb_routine cb_routine,channel_cb_buffer_err cb_buffer_err,cam_padding_info_t * paddingInfo,cam_feature_mask_t postprocess_mask,void * userData,uint32_t numBuffers)67 QCamera3Channel::QCamera3Channel(uint32_t cam_handle,
68 uint32_t channel_handle,
69 mm_camera_ops_t *cam_ops,
70 channel_cb_routine cb_routine,
71 channel_cb_buffer_err cb_buffer_err,
72 cam_padding_info_t *paddingInfo,
73 cam_feature_mask_t postprocess_mask,
74 void *userData, uint32_t numBuffers)
75 {
76 m_camHandle = cam_handle;
77 m_handle = channel_handle;
78 m_camOps = cam_ops;
79 m_bIsActive = false;
80
81 m_numStreams = 0;
82 memset(mStreams, 0, sizeof(mStreams));
83 mUserData = userData;
84
85 mStreamInfoBuf = NULL;
86 mChannelCB = cb_routine;
87 mChannelCbBufErr = cb_buffer_err;
88 mPaddingInfo = *paddingInfo;
89 mPaddingInfo.offset_info.offset_x = 0;
90 mPaddingInfo.offset_info.offset_y = 0;
91
92 mPostProcMask = postprocess_mask;
93
94 mIsType = IS_TYPE_NONE;
95 mNumBuffers = numBuffers;
96 mPerFrameMapUnmapEnable = true;
97 mDumpFrmCnt = 0;
98 }
99
100 /*===========================================================================
101 * FUNCTION : ~QCamera3Channel
102 *
103 * DESCRIPTION: destructor of QCamera3Channel
104 *
105 * PARAMETERS : none
106 *
107 * RETURN : none
108 *==========================================================================*/
~QCamera3Channel()109 QCamera3Channel::~QCamera3Channel()
110 {
111 }
112
113 /*===========================================================================
114 * FUNCTION : destroy
115 *
116 * DESCRIPTION: internal destructor of QCamera3Channel called by the subclasses
117 * this destructor will call pure virtual functions. stop will eventuall call
118 * QCamera3Stream::putBufs. The putBufs function will
119 * call QCamera3Channel::putStreamBufs which is pure virtual
120 *
121 * PARAMETERS : none
122 *
123 * RETURN : none
124 *==========================================================================*/
destroy()125 void QCamera3Channel::destroy()
126 {
127 if (m_bIsActive)
128 stop();
129
130 for (uint32_t i = 0; i < m_numStreams; i++) {
131 if (mStreams[i] != NULL) {
132 delete mStreams[i];
133 mStreams[i] = 0;
134 }
135 }
136 m_numStreams = 0;
137 }
138
139 /*===========================================================================
140 * FUNCTION : addStream
141 *
142 * DESCRIPTION: add a stream into channel
143 *
144 * PARAMETERS :
145 * @streamType : stream type
146 * @streamFormat : stream format
147 * @streamDim : stream dimension
148 * @streamRotation : rotation of the stream
149 * @minStreamBufNum : minimal buffer count for particular stream type
150 * @postprocessMask : post-proccess feature mask
151 * @isType : type of image stabilization required on the stream
152 *
153 * RETURN : int32_t type of status
154 * NO_ERROR -- success
155 * none-zero failure code
156 *==========================================================================*/
addStream(cam_stream_type_t streamType,cam_format_t streamFormat,cam_dimension_t streamDim,cam_rotation_t streamRotation,uint8_t minStreamBufNum,cam_feature_mask_t postprocessMask,cam_is_type_t isType,uint32_t batchSize)157 int32_t QCamera3Channel::addStream(cam_stream_type_t streamType,
158 cam_format_t streamFormat,
159 cam_dimension_t streamDim,
160 cam_rotation_t streamRotation,
161 uint8_t minStreamBufNum,
162 cam_feature_mask_t postprocessMask,
163 cam_is_type_t isType,
164 uint32_t batchSize)
165 {
166 int32_t rc = NO_ERROR;
167
168 if (m_numStreams >= 1) {
169 LOGE("Only one stream per channel supported in v3 Hal");
170 return BAD_VALUE;
171 }
172
173 if (m_numStreams >= MAX_STREAM_NUM_IN_BUNDLE) {
174 LOGE("stream number (%d) exceeds max limit (%d)",
175 m_numStreams, MAX_STREAM_NUM_IN_BUNDLE);
176 return BAD_VALUE;
177 }
178 QCamera3Stream *pStream = new QCamera3Stream(m_camHandle,
179 m_handle,
180 m_camOps,
181 &mPaddingInfo,
182 this);
183 if (pStream == NULL) {
184 LOGE("No mem for Stream");
185 return NO_MEMORY;
186 }
187 LOGD("batch size is %d", batchSize);
188
189 rc = pStream->init(streamType, streamFormat, streamDim, streamRotation,
190 NULL, minStreamBufNum, postprocessMask, isType, batchSize,
191 streamCbRoutine, this);
192 if (rc == 0) {
193 mStreams[m_numStreams] = pStream;
194 m_numStreams++;
195 } else {
196 delete pStream;
197 }
198 return rc;
199 }
200
201 /*===========================================================================
202 * FUNCTION : start
203 *
204 * DESCRIPTION: start channel, which will start all streams belong to this channel
205 *
206 * PARAMETERS :
207 *
208 * RETURN : int32_t type of status
209 * NO_ERROR -- success
210 * none-zero failure code
211 *==========================================================================*/
start()212 int32_t QCamera3Channel::start()
213 {
214 ATRACE_CALL();
215 int32_t rc = NO_ERROR;
216
217 if (m_numStreams > 1) {
218 LOGW("bundle not supported");
219 } else if (m_numStreams == 0) {
220 return NO_INIT;
221 }
222
223 if(m_bIsActive) {
224 LOGW("Attempt to start active channel");
225 return rc;
226 }
227
228 for (uint32_t i = 0; i < m_numStreams; i++) {
229 if (mStreams[i] != NULL) {
230 mStreams[i]->start();
231 }
232 }
233
234 m_bIsActive = true;
235
236 return rc;
237 }
238
239 /*===========================================================================
240 * FUNCTION : stop
241 *
242 * DESCRIPTION: stop a channel, which will stop all streams belong to this channel
243 *
244 * PARAMETERS : none
245 *
246 * RETURN : int32_t type of status
247 * NO_ERROR -- success
248 * none-zero failure code
249 *==========================================================================*/
stop()250 int32_t QCamera3Channel::stop()
251 {
252 ATRACE_CALL();
253 int32_t rc = NO_ERROR;
254 if(!m_bIsActive) {
255 LOGE("Attempt to stop inactive channel");
256 return rc;
257 }
258
259 for (uint32_t i = 0; i < m_numStreams; i++) {
260 if (mStreams[i] != NULL) {
261 mStreams[i]->stop();
262 }
263 }
264
265 m_bIsActive = false;
266 return rc;
267 }
268
269 /*===========================================================================
270 * FUNCTION : setBatchSize
271 *
272 * DESCRIPTION: Set batch size for the channel. This is a dummy implementation
273 * for the base class
274 *
275 * PARAMETERS :
276 * @batchSize : Number of image buffers in a batch
277 *
278 * RETURN : int32_t type of status
279 * NO_ERROR -- success always
280 * none-zero failure code
281 *==========================================================================*/
setBatchSize(uint32_t batchSize)282 int32_t QCamera3Channel::setBatchSize(uint32_t batchSize)
283 {
284 LOGD("Dummy method. batchSize: %d unused ", batchSize);
285 return NO_ERROR;
286 }
287
288 /*===========================================================================
289 * FUNCTION : queueBatchBuf
290 *
291 * DESCRIPTION: This is a dummy implementation for the base class
292 *
293 * PARAMETERS :
294 *
295 * RETURN : int32_t type of status
296 * NO_ERROR -- success always
297 * none-zero failure code
298 *==========================================================================*/
queueBatchBuf()299 int32_t QCamera3Channel::queueBatchBuf()
300 {
301 LOGD("Dummy method. Unused ");
302 return NO_ERROR;
303 }
304
305 /*===========================================================================
306 * FUNCTION : setPerFrameMapUnmap
307 *
308 * DESCRIPTION: Sets internal enable flag
309 *
310 * PARAMETERS :
311 * @enable : Bool value for the enable flag
312 *
313 * RETURN : int32_t type of status
314 * NO_ERROR -- success always
315 * none-zero failure code
316 *==========================================================================*/
setPerFrameMapUnmap(bool enable)317 int32_t QCamera3Channel::setPerFrameMapUnmap(bool enable)
318 {
319 mPerFrameMapUnmapEnable = enable;
320 return NO_ERROR;
321 }
322
323 /*===========================================================================
324 * FUNCTION : flush
325 *
326 * DESCRIPTION: flush a channel
327 *
328 * PARAMETERS : none
329 *
330 * RETURN : int32_t type of status
331 * NO_ERROR -- success
332 * none-zero failure code
333 *==========================================================================*/
flush()334 int32_t QCamera3Channel::flush()
335 {
336 ATRACE_CALL();
337 return NO_ERROR;
338 }
339
340 /*===========================================================================
341 * FUNCTION : bufDone
342 *
343 * DESCRIPTION: return a stream buf back to kernel
344 *
345 * PARAMETERS :
346 * @recvd_frame : stream buf frame to be returned
347 *
348 * RETURN : int32_t type of status
349 * NO_ERROR -- success
350 * none-zero failure code
351 *==========================================================================*/
bufDone(mm_camera_super_buf_t * recvd_frame)352 int32_t QCamera3Channel::bufDone(mm_camera_super_buf_t *recvd_frame)
353 {
354 int32_t rc = NO_ERROR;
355 for (uint32_t i = 0; i < recvd_frame->num_bufs; i++) {
356 if (recvd_frame->bufs[i] != NULL) {
357 for (uint32_t j = 0; j < m_numStreams; j++) {
358 if (mStreams[j] != NULL &&
359 mStreams[j]->getMyHandle() == recvd_frame->bufs[i]->stream_id) {
360 rc = mStreams[j]->bufDone(recvd_frame->bufs[i]->buf_idx);
361 break; // break loop j
362 }
363 }
364 }
365 }
366
367 return rc;
368 }
369
setBundleInfo(const cam_bundle_config_t & bundleInfo)370 int32_t QCamera3Channel::setBundleInfo(const cam_bundle_config_t &bundleInfo)
371 {
372 int32_t rc = NO_ERROR;
373 cam_stream_parm_buffer_t param;
374 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t));
375 param.type = CAM_STREAM_PARAM_TYPE_SET_BUNDLE_INFO;
376 param.bundleInfo = bundleInfo;
377 rc = mStreams[0]->setParameter(param);
378 if (rc != NO_ERROR) {
379 LOGE("stream setParameter for set bundle failed");
380 }
381
382 return rc;
383 }
384
385 /*===========================================================================
386 * FUNCTION : getStreamTypeMask
387 *
388 * DESCRIPTION: Get bit mask of all stream types in this channel
389 *
390 * PARAMETERS : None
391 *
392 * RETURN : Bit mask of all stream types in this channel
393 *==========================================================================*/
getStreamTypeMask()394 uint32_t QCamera3Channel::getStreamTypeMask()
395 {
396 uint32_t mask = 0;
397 for (uint32_t i = 0; i < m_numStreams; i++) {
398 mask |= (1U << mStreams[i]->getMyType());
399 }
400 return mask;
401 }
402
403 /*===========================================================================
404 * FUNCTION : getStreamID
405 *
406 * DESCRIPTION: Get StreamID of requested stream type
407 *
408 * PARAMETERS : streamMask
409 *
410 * RETURN : Stream ID
411 *==========================================================================*/
getStreamID(uint32_t streamMask)412 uint32_t QCamera3Channel::getStreamID(uint32_t streamMask)
413 {
414 uint32_t streamID = 0;
415 for (uint32_t i = 0; i < m_numStreams; i++) {
416 if (streamMask == (uint32_t )(0x1 << mStreams[i]->getMyType())) {
417 streamID = mStreams[i]->getMyServerID();
418 break;
419 }
420 }
421 return streamID;
422 }
423
424 /*===========================================================================
425 * FUNCTION : getStreamByHandle
426 *
427 * DESCRIPTION: return stream object by stream handle
428 *
429 * PARAMETERS :
430 * @streamHandle : stream handle
431 *
432 * RETURN : stream object. NULL if not found
433 *==========================================================================*/
getStreamByHandle(uint32_t streamHandle)434 QCamera3Stream *QCamera3Channel::getStreamByHandle(uint32_t streamHandle)
435 {
436 for (uint32_t i = 0; i < m_numStreams; i++) {
437 if (mStreams[i] != NULL && mStreams[i]->getMyHandle() == streamHandle) {
438 return mStreams[i];
439 }
440 }
441 return NULL;
442 }
443
444 /*===========================================================================
445 * FUNCTION : getStreamByIndex
446 *
447 * DESCRIPTION: return stream object by index
448 *
449 * PARAMETERS :
450 * @streamHandle : stream handle
451 *
452 * RETURN : stream object. NULL if not found
453 *==========================================================================*/
getStreamByIndex(uint32_t index)454 QCamera3Stream *QCamera3Channel::getStreamByIndex(uint32_t index)
455 {
456 if (index < m_numStreams) {
457 return mStreams[index];
458 }
459 return NULL;
460 }
461
462 /*===========================================================================
463 * FUNCTION : streamCbRoutine
464 *
465 * DESCRIPTION: callback routine for stream
466 *
467 * PARAMETERS :
468 * @streamHandle : stream handle
469 *
470 * RETURN : stream object. NULL if not found
471 *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream,void * userdata)472 void QCamera3Channel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
473 QCamera3Stream *stream, void *userdata)
474 {
475 QCamera3Channel *channel = (QCamera3Channel *)userdata;
476 if (channel == NULL) {
477 LOGE("invalid channel pointer");
478 return;
479 }
480 channel->streamCbRoutine(super_frame, stream);
481 }
482
483 /*===========================================================================
484 * FUNCTION : dumpYUV
485 *
486 * DESCRIPTION: function to dump the YUV data from ISP/pproc
487 *
488 * PARAMETERS :
489 * @frame : frame to be dumped
490 * @dim : dimension of the stream
491 * @offset : offset of the data
492 * @name : 1 if it is ISP output/pproc input, 2 if it is pproc output
493 *
494 * RETURN :
495 *==========================================================================*/
dumpYUV(mm_camera_buf_def_t * frame,cam_dimension_t dim,cam_frame_len_offset_t offset,uint8_t dump_type)496 void QCamera3Channel::dumpYUV(mm_camera_buf_def_t *frame, cam_dimension_t dim,
497 cam_frame_len_offset_t offset, uint8_t dump_type)
498 {
499 char buf[FILENAME_MAX];
500 memset(buf, 0, sizeof(buf));
501 static int counter = 0;
502 char prop[PROPERTY_VALUE_MAX];
503 property_get("persist.camera.dumpimg", prop, "0");
504 mYUVDump = (uint32_t)atoi(prop);
505 if (mYUVDump & dump_type) {
506 mFrmNum = ((mYUVDump & 0xffff0000) >> 16);
507 if (mFrmNum == 0) {
508 mFrmNum = 10;
509 }
510 if (mFrmNum > 256) {
511 mFrmNum = 256;
512 }
513 mSkipMode = ((mYUVDump & 0x0000ff00) >> 8);
514 if (mSkipMode == 0) {
515 mSkipMode = 1;
516 }
517 if (mDumpSkipCnt == 0) {
518 mDumpSkipCnt = 1;
519 }
520 if (mDumpSkipCnt % mSkipMode == 0) {
521 if (mDumpFrmCnt <= mFrmNum) {
522 /* Note that the image dimension will be the unrotated stream dimension.
523 * If you feel that the image would have been rotated during reprocess
524 * then swap the dimensions while opening the file
525 * */
526 switch (dump_type) {
527 case QCAMERA_DUMP_FRM_PREVIEW:
528 snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"p_%d_%d_%dx%d.yuv",
529 counter, frame->frame_idx, dim.width, dim.height);
530 break;
531 case QCAMERA_DUMP_FRM_VIDEO:
532 snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"v_%d_%d_%dx%d.yuv",
533 counter, frame->frame_idx, dim.width, dim.height);
534 break;
535 case QCAMERA_DUMP_FRM_SNAPSHOT:
536 snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"s_%d_%d_%dx%d.yuv",
537 counter, frame->frame_idx, dim.width, dim.height);
538 break;
539 case QCAMERA_DUMP_FRM_INPUT_REPROCESS:
540 snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"ir_%d_%d_%dx%d.yuv",
541 counter, frame->frame_idx, dim.width, dim.height);
542 break;
543 case QCAMERA_DUMP_FRM_CALLBACK:
544 snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"c_%d_%d_%dx%d.yuv",
545 counter, frame->frame_idx, dim.width, dim.height);
546 break;
547 default :
548 LOGE("dumping not enabled for stream type %d",dump_type);
549 break;
550 }
551 counter++;
552 int file_fd = open(buf, O_RDWR | O_CREAT, 0777);
553 ssize_t written_len = 0;
554 if (file_fd >= 0) {
555 void *data = NULL;
556 fchmod(file_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
557 for (uint32_t i = 0; i < offset.num_planes; i++) {
558 uint32_t index = offset.mp[i].offset;
559 if (i > 0) {
560 index += offset.mp[i-1].len;
561 }
562 for (int j = 0; j < offset.mp[i].height; j++) {
563 data = (void *)((uint8_t *)frame->buffer + index);
564 written_len += write(file_fd, data,
565 (size_t)offset.mp[i].width);
566 index += (uint32_t)offset.mp[i].stride;
567 }
568 }
569 LOGH("written number of bytes %ld\n", written_len);
570 mDumpFrmCnt++;
571 close(file_fd);
572 } else {
573 LOGE("failed to open file to dump image");
574 }
575 }
576 } else {
577 mDumpSkipCnt++;
578 }
579 }
580 }
581
582 /*===========================================================================
583 * FUNCTION : isUBWCEnabled
584 *
585 * DESCRIPTION: Function to get UBWC hardware support.
586 *
587 * PARAMETERS : None
588 *
589 * RETURN : TRUE -- UBWC format supported
590 * FALSE -- UBWC is not supported.
591 *==========================================================================*/
isUBWCEnabled()592 bool QCamera3Channel::isUBWCEnabled()
593 {
594 #ifdef UBWC_PRESENT
595 char value[PROPERTY_VALUE_MAX];
596 int prop_value = 0;
597 memset(value, 0, sizeof(value));
598 property_get("debug.gralloc.gfx_ubwc_disable", value, "0");
599 prop_value = atoi(value);
600 if (prop_value) {
601 return FALSE;
602 }
603
604 //Disable UBWC if Eztune is enabled
605 //EzTune process CPP output frame and cannot understand UBWC.
606 memset(value, 0, sizeof(value));
607 property_get("persist.camera.eztune.enable", value, "0");
608 prop_value = atoi(value);
609 if (prop_value) {
610 return FALSE;
611 }
612 return TRUE;
613 #else
614 return FALSE;
615 #endif
616 }
617
618 /*===========================================================================
619 * FUNCTION : getStreamDefaultFormat
620 *
621 * DESCRIPTION: return default buffer format for the stream
622 *
623 * PARAMETERS : type : Stream type
624 *
625 ** RETURN : format for stream type
626 *
627 *==========================================================================*/
getStreamDefaultFormat(cam_stream_type_t type,uint32_t width,uint32_t height)628 cam_format_t QCamera3Channel::getStreamDefaultFormat(cam_stream_type_t type,
629 uint32_t width, uint32_t height)
630 {
631 cam_format_t streamFormat;
632
633 switch (type) {
634 case CAM_STREAM_TYPE_PREVIEW:
635 if (isUBWCEnabled()) {
636 char prop[PROPERTY_VALUE_MAX];
637 int pFormat;
638 memset(prop, 0, sizeof(prop));
639 property_get("persist.camera.preview.ubwc", prop, "1");
640 pFormat = atoi(prop);
641 if (pFormat == 1) {
642 streamFormat = CAM_FORMAT_YUV_420_NV12_UBWC;
643 } else {
644 streamFormat = CAM_FORMAT_YUV_420_NV12_VENUS;
645 }
646 } else {
647 streamFormat = CAM_FORMAT_YUV_420_NV12_VENUS;
648 }
649 break;
650 case CAM_STREAM_TYPE_VIDEO:
651 {
652 /* Disable UBWC for smaller video resolutions due to CPP downscale
653 limits. Refer cpp_hw_params.h::CPP_DOWNSCALE_LIMIT_UBWC */
654 if (isUBWCEnabled() && (width >= 640) && (height >= 480)) {
655 char prop[PROPERTY_VALUE_MAX];
656 int pFormat;
657 memset(prop, 0, sizeof(prop));
658 property_get("persist.camera.video.ubwc", prop, "1");
659 pFormat = atoi(prop);
660 if (pFormat == 1) {
661 streamFormat = CAM_FORMAT_YUV_420_NV12_UBWC;
662 } else {
663 streamFormat = CAM_FORMAT_YUV_420_NV12_VENUS;
664 }
665 } else {
666 #if VENUS_PRESENT
667 streamFormat = CAM_FORMAT_YUV_420_NV12_VENUS;
668 #else
669 streamFormat = CAM_FORMAT_YUV_420_NV12;
670 #endif
671 }
672 break;
673 }
674 case CAM_STREAM_TYPE_SNAPSHOT:
675 streamFormat = CAM_FORMAT_YUV_420_NV21;
676 break;
677 case CAM_STREAM_TYPE_CALLBACK:
678 streamFormat = CAM_FORMAT_YUV_420_NV21;
679 break;
680 case CAM_STREAM_TYPE_RAW:
681 streamFormat = CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG;
682 break;
683 default:
684 streamFormat = CAM_FORMAT_YUV_420_NV21;
685 break;
686 }
687 return streamFormat;
688 }
689
690
691 /* QCamera3ProcessingChannel methods */
692
693 /*===========================================================================
694 * FUNCTION : QCamera3ProcessingChannel
695 *
696 * DESCRIPTION: constructor of QCamera3ProcessingChannel
697 *
698 * PARAMETERS :
699 * @cam_handle : camera handle
700 * @cam_ops : ptr to camera ops table
701 * @cb_routine : callback routine to frame aggregator
702 * @paddingInfo: stream padding info
703 * @userData : HWI handle
704 * @stream : camera3_stream_t structure
705 * @stream_type: Channel stream type
706 * @postprocess_mask: the postprocess mask for streams of this channel
707 * @metadataChannel: handle to the metadataChannel
708 * @numBuffers : number of max dequeued buffers
709 * RETURN : none
710 *==========================================================================*/
QCamera3ProcessingChannel(uint32_t cam_handle,uint32_t channel_handle,mm_camera_ops_t * cam_ops,channel_cb_routine cb_routine,channel_cb_buffer_err cb_buffer_err,cam_padding_info_t * paddingInfo,void * userData,camera3_stream_t * stream,cam_stream_type_t stream_type,cam_feature_mask_t postprocess_mask,QCamera3Channel * metadataChannel,uint32_t numBuffers)711 QCamera3ProcessingChannel::QCamera3ProcessingChannel(uint32_t cam_handle,
712 uint32_t channel_handle,
713 mm_camera_ops_t *cam_ops,
714 channel_cb_routine cb_routine,
715 channel_cb_buffer_err cb_buffer_err,
716 cam_padding_info_t *paddingInfo,
717 void *userData,
718 camera3_stream_t *stream,
719 cam_stream_type_t stream_type,
720 cam_feature_mask_t postprocess_mask,
721 QCamera3Channel *metadataChannel,
722 uint32_t numBuffers) :
723 QCamera3Channel(cam_handle, channel_handle, cam_ops, cb_routine,
724 cb_buffer_err, paddingInfo, postprocess_mask, userData, numBuffers),
725 m_postprocessor(this),
726 mFrameCount(0),
727 mLastFrameCount(0),
728 mLastFpsTime(0),
729 mMemory(numBuffers),
730 mCamera3Stream(stream),
731 mNumBufs(CAM_MAX_NUM_BUFS_PER_STREAM),
732 mStreamType(stream_type),
733 mPostProcStarted(false),
734 mInputBufferConfig(false),
735 m_pMetaChannel(metadataChannel),
736 mMetaFrame(NULL),
737 mOfflineMemory(0),
738 mOfflineMetaMemory(numBuffers + (MAX_REPROCESS_PIPELINE_STAGES - 1),
739 false)
740 {
741 char prop[PROPERTY_VALUE_MAX];
742 property_get("persist.debug.sf.showfps", prop, "0");
743 mDebugFPS = (uint8_t) atoi(prop);
744
745 int32_t rc = m_postprocessor.init(&mMemory);
746 if (rc != 0) {
747 LOGE("Init Postprocessor failed");
748 }
749 }
750
751 /*===========================================================================
752 * FUNCTION : ~QCamera3ProcessingChannel
753 *
754 * DESCRIPTION: destructor of QCamera3ProcessingChannel
755 *
756 * PARAMETERS : none
757 *
758 * RETURN : none
759 *==========================================================================*/
~QCamera3ProcessingChannel()760 QCamera3ProcessingChannel::~QCamera3ProcessingChannel()
761 {
762 destroy();
763
764 int32_t rc = m_postprocessor.deinit();
765 if (rc != 0) {
766 LOGE("De-init Postprocessor failed");
767 }
768
769 if (0 < mOfflineMetaMemory.getCnt()) {
770 mOfflineMetaMemory.deallocate();
771 }
772 if (0 < mOfflineMemory.getCnt()) {
773 mOfflineMemory.unregisterBuffers();
774 }
775
776 }
777
778 /*===========================================================================
779 * FUNCTION : streamCbRoutine
780 *
781 * DESCRIPTION:
782 *
783 * PARAMETERS :
784 * @super_frame : the super frame with filled buffer
785 * @stream : stream on which the buffer was requested and filled
786 *
787 * RETURN : none
788 *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream)789 void QCamera3ProcessingChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
790 QCamera3Stream *stream)
791 {
792 ATRACE_CALL();
793 //FIXME Q Buf back in case of error?
794 uint8_t frameIndex;
795 buffer_handle_t *resultBuffer;
796 int32_t resultFrameNumber;
797 camera3_stream_buffer_t result;
798 cam_dimension_t dim;
799 cam_frame_len_offset_t offset;
800
801 memset(&dim, 0, sizeof(dim));
802 memset(&offset, 0, sizeof(cam_frame_len_offset_t));
803 if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) {
804 LOGE("Error with the stream callback");
805 return;
806 }
807
808 frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
809 if(frameIndex >= mNumBufs) {
810 LOGE("Error, Invalid index for buffer");
811 stream->bufDone(frameIndex);
812 return;
813 }
814
815 if (mDebugFPS) {
816 showDebugFPS(stream->getMyType());
817 }
818 stream->getFrameDimension(dim);
819 stream->getFrameOffset(offset);
820 if (stream->getMyType() == CAM_STREAM_TYPE_PREVIEW) {
821 dumpYUV(super_frame->bufs[0], dim, offset, QCAMERA_DUMP_FRM_PREVIEW);
822 } else if (stream->getMyType() == CAM_STREAM_TYPE_VIDEO) {
823 dumpYUV(super_frame->bufs[0], dim, offset, QCAMERA_DUMP_FRM_VIDEO);
824 } else if (stream->getMyType() == CAM_STREAM_TYPE_CALLBACK) {
825 dumpYUV(super_frame->bufs[0], dim, offset, QCAMERA_DUMP_FRM_CALLBACK);
826 }
827
828 do {
829
830 //Use below data to issue framework callback
831 resultBuffer = (buffer_handle_t *)mMemory.getBufferHandle(frameIndex);
832 resultFrameNumber = mMemory.getFrameNumber(frameIndex);
833 uint32_t oldestBufIndex;
834 int32_t lowestFrameNumber = mMemory.getOldestFrameNumber(oldestBufIndex);
835 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
836 if ((lowestFrameNumber != -1 ) && (lowestFrameNumber < resultFrameNumber) &&
837 hal_obj->mOpMode != CAMERA3_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE) {
838 LOGE("Error buffer dropped for framenumber:%d with bufidx:%d",
839 lowestFrameNumber, oldestBufIndex);
840 if (mOutOfSequenceBuffers.empty()) {
841 stream->cancelBuffer(oldestBufIndex);
842 }
843 mOutOfSequenceBuffers.push_back(super_frame);
844 return;
845 }
846
847 result.stream = mCamera3Stream;
848 result.buffer = resultBuffer;
849 if (IS_BUFFER_ERROR(super_frame->bufs[0]->flags)) {
850 result.status = CAMERA3_BUFFER_STATUS_ERROR;
851 LOGW("CAMERA3_BUFFER_STATUS_ERROR for stream_type: %d",
852 mStreams[0]->getMyType());
853 mChannelCbBufErr(this, resultFrameNumber, CAMERA3_BUFFER_STATUS_ERROR, mUserData);
854 } else {
855 result.status = CAMERA3_BUFFER_STATUS_OK;
856 }
857 result.acquire_fence = -1;
858 result.release_fence = -1;
859 if(mPerFrameMapUnmapEnable) {
860 int32_t rc = stream->bufRelease(frameIndex);
861 if (NO_ERROR != rc) {
862 LOGE("Error %d releasing stream buffer %d",
863 rc, frameIndex);
864 }
865
866 rc = mMemory.unregisterBuffer(frameIndex);
867 if (NO_ERROR != rc) {
868 LOGE("Error %d unregistering stream buffer %d",
869 rc, frameIndex);
870 }
871 }
872
873 if (0 <= resultFrameNumber) {
874 if (mChannelCB) {
875 mChannelCB(NULL, &result, (uint32_t)resultFrameNumber, false, mUserData);
876 }
877 } else {
878 LOGE("Bad frame number");
879 }
880 free(super_frame);
881 super_frame = NULL;
882 if (mOutOfSequenceBuffers.empty()) {
883 break;
884 } else {
885 auto itr = mOutOfSequenceBuffers.begin();
886 super_frame = *itr;
887 frameIndex = super_frame->bufs[0]->buf_idx;
888 resultFrameNumber = mMemory.getFrameNumber(frameIndex);
889 lowestFrameNumber = mMemory.getOldestFrameNumber(oldestBufIndex);
890 LOGE("Attempting to recover next frame: result Frame#: %d, resultIdx: %d, "
891 "Lowest Frame#: %d, oldestBufIndex: %d",
892 resultFrameNumber, frameIndex, lowestFrameNumber, oldestBufIndex);
893 if ((lowestFrameNumber != -1) && (lowestFrameNumber < resultFrameNumber)) {
894 LOGE("Multiple frame dropped requesting cancel for frame %d, idx:%d",
895 lowestFrameNumber, oldestBufIndex);
896 stream->cancelBuffer(oldestBufIndex);
897 return;
898 } else if (lowestFrameNumber == resultFrameNumber) {
899 LOGE("Time to flush out head of list continue loop with this new super frame");
900 itr = mOutOfSequenceBuffers.erase(itr);
901 } else {
902 LOGE("Unexpected condition head of list is not the lowest frame number");
903 itr = mOutOfSequenceBuffers.erase(itr);
904 }
905 }
906 } while (1);
907 return;
908 }
909
910 /*===========================================================================
911 * FUNCTION : putStreamBufs
912 *
913 * DESCRIPTION: release the buffers allocated to the stream
914 *
915 * PARAMETERS : NONE
916 *
917 * RETURN : NONE
918 *==========================================================================*/
putStreamBufs()919 void QCamera3YUVChannel::putStreamBufs()
920 {
921 QCamera3ProcessingChannel::putStreamBufs();
922
923 // Free allocated heap buffer.
924 mMemory.deallocate();
925 // Clear free heap buffer list.
926 mFreeHeapBufferList.clear();
927 // Clear offlinePpInfoList
928 mOfflinePpInfoList.clear();
929 }
930
931 /*===========================================================================
932 * FUNCTION : timeoutFrame
933 *
934 * DESCRIPTION: Method to indicate to channel that a given frame has take too
935 * long to be generated
936 *
937 * PARAMETERS : framenumber indicating the framenumber of the buffer timingout
938 *
939 * RETURN : int32_t type of status
940 * NO_ERROR -- success
941 * none-zero failure code
942 *==========================================================================*/
timeoutFrame(uint32_t frameNumber)943 int32_t QCamera3ProcessingChannel::timeoutFrame(uint32_t frameNumber)
944 {
945 int32_t bufIdx;
946
947 bufIdx = mMemory.getBufferIndex(frameNumber);
948
949 if (bufIdx < 0) {
950 ALOGE("%s: Buffer not found for frame:%d", __func__, frameNumber);
951 return -1;
952 }
953
954 mStreams[0]->timeoutFrame(bufIdx);
955 return NO_ERROR;
956 }
957
958 /*===========================================================================
959 * FUNCTION : request
960 *
961 * DESCRIPTION: handle the request - either with an input buffer or a direct
962 * output request
963 *
964 * PARAMETERS :
965 * @buffer : pointer to the output buffer
966 * @frameNumber : frame number of the request
967 * @pInputBuffer : pointer to input buffer if an input request
968 * @metadata : parameters associated with the request
969 *
970 * RETURN : 0 on a success start of capture
971 * -EINVAL on invalid input
972 * -ENODEV on serious error
973 *==========================================================================*/
request(buffer_handle_t * buffer,uint32_t frameNumber,camera3_stream_buffer_t * pInputBuffer,metadata_buffer_t * metadata,int & indexUsed)974 int32_t QCamera3ProcessingChannel::request(buffer_handle_t *buffer,
975 uint32_t frameNumber,
976 camera3_stream_buffer_t* pInputBuffer,
977 metadata_buffer_t* metadata,
978 int &indexUsed)
979 {
980 int32_t rc = NO_ERROR;
981 int index;
982
983 if (NULL == buffer || NULL == metadata) {
984 LOGE("Invalid buffer/metadata in channel request");
985 return BAD_VALUE;
986 }
987
988 if (pInputBuffer) {
989 //need to send to reprocessing
990 LOGD("Got a request with input buffer, output streamType = %d", mStreamType);
991 reprocess_config_t reproc_cfg;
992 cam_dimension_t dim;
993 memset(&reproc_cfg, 0, sizeof(reprocess_config_t));
994 memset(&dim, 0, sizeof(dim));
995 setReprocConfig(reproc_cfg, pInputBuffer, metadata, mStreamFormat, dim);
996 startPostProc(reproc_cfg);
997
998 qcamera_fwk_input_pp_data_t *src_frame = NULL;
999 src_frame = (qcamera_fwk_input_pp_data_t *)calloc(1,
1000 sizeof(qcamera_fwk_input_pp_data_t));
1001 if (src_frame == NULL) {
1002 LOGE("No memory for src frame");
1003 return NO_MEMORY;
1004 }
1005 rc = setFwkInputPPData(src_frame, pInputBuffer, &reproc_cfg, metadata, buffer, frameNumber);
1006 if (NO_ERROR != rc) {
1007 LOGE("Error %d while setting framework input PP data", rc);
1008 free(src_frame);
1009 return rc;
1010 }
1011 LOGH("Post-process started");
1012 m_postprocessor.processData(src_frame);
1013 } else {
1014 //need to fill output buffer with new data and return
1015 if(!m_bIsActive) {
1016 rc = registerBuffer(buffer, mIsType);
1017 if (NO_ERROR != rc) {
1018 LOGE("On-the-fly buffer registration failed %d",
1019 rc);
1020 return rc;
1021 }
1022
1023 rc = start();
1024 if (NO_ERROR != rc)
1025 return rc;
1026 } else {
1027 LOGD("Request on an existing stream");
1028 }
1029
1030 index = mMemory.getMatchBufIndex((void*)buffer);
1031 if(index < 0) {
1032 rc = registerBuffer(buffer, mIsType);
1033 if (NO_ERROR != rc) {
1034 LOGE("On-the-fly buffer registration failed %d",
1035 rc);
1036 return rc;
1037 }
1038
1039 index = mMemory.getMatchBufIndex((void*)buffer);
1040 if (index < 0) {
1041 LOGE("Could not find object among registered buffers");
1042 return DEAD_OBJECT;
1043 }
1044 }
1045 rc = mMemory.markFrameNumber(index, frameNumber);
1046 if(rc != NO_ERROR) {
1047 LOGE("Error marking frame number:%d for index %d", frameNumber,
1048 index);
1049 return rc;
1050 }
1051 rc = mStreams[0]->bufDone(index);
1052 if(rc != NO_ERROR) {
1053 LOGE("Failed to Q new buffer to stream");
1054 mMemory.markFrameNumber(index, -1);
1055 return rc;
1056 }
1057 indexUsed = index;
1058 }
1059 return rc;
1060 }
1061
1062 /*===========================================================================
1063 * FUNCTION : initialize
1064 *
1065 * DESCRIPTION:
1066 *
1067 * PARAMETERS : isType : type of image stabilization on the buffer
1068 *
1069 * RETURN : int32_t type of status
1070 * NO_ERROR -- success
1071 * none-zero failure code
1072 *==========================================================================*/
initialize(__unused cam_is_type_t isType)1073 int32_t QCamera3ProcessingChannel::initialize(__unused cam_is_type_t isType)
1074 {
1075 int32_t rc = NO_ERROR;
1076 rc = mOfflineMetaMemory.allocateAll(sizeof(metadata_buffer_t));
1077 if (rc == NO_ERROR) {
1078 Mutex::Autolock lock(mFreeOfflineMetaBuffersLock);
1079 mFreeOfflineMetaBuffersList.clear();
1080 for (uint32_t i = 0; i < mNumBuffers + (MAX_REPROCESS_PIPELINE_STAGES - 1);
1081 i++) {
1082 mFreeOfflineMetaBuffersList.push_back(i);
1083 }
1084 } else {
1085 LOGE("Could not allocate offline meta buffers for input reprocess");
1086 }
1087 mOutOfSequenceBuffers.clear();
1088 return rc;
1089 }
1090
1091 /*===========================================================================
1092 * FUNCTION : registerBuffer
1093 *
1094 * DESCRIPTION: register streaming buffer to the channel object
1095 *
1096 * PARAMETERS :
1097 * @buffer : buffer to be registered
1098 * @isType : image stabilization type on the stream
1099 *
1100 * RETURN : int32_t type of status
1101 * NO_ERROR -- success
1102 * none-zero failure code
1103 *==========================================================================*/
registerBuffer(buffer_handle_t * buffer,cam_is_type_t isType)1104 int32_t QCamera3ProcessingChannel::registerBuffer(buffer_handle_t *buffer,
1105 cam_is_type_t isType)
1106 {
1107 ATRACE_CALL();
1108 int rc = 0;
1109 mIsType = isType;
1110 cam_stream_type_t streamType;
1111
1112 if ((uint32_t)mMemory.getCnt() > (mNumBufs - 1)) {
1113 LOGE("Trying to register more buffers than initially requested");
1114 return BAD_VALUE;
1115 }
1116
1117 if (0 == m_numStreams) {
1118 rc = initialize(mIsType);
1119 if (rc != NO_ERROR) {
1120 LOGE("Couldn't initialize camera stream %d", rc);
1121 return rc;
1122 }
1123 }
1124
1125 streamType = mStreams[0]->getMyType();
1126 rc = mMemory.registerBuffer(buffer, streamType);
1127 if (ALREADY_EXISTS == rc) {
1128 return NO_ERROR;
1129 } else if (NO_ERROR != rc) {
1130 LOGE("Buffer %p couldn't be registered %d", buffer, rc);
1131 return rc;
1132 }
1133
1134 return rc;
1135 }
1136
1137 /*===========================================================================
1138 * FUNCTION : setFwkInputPPData
1139 *
1140 * DESCRIPTION: fill out the framework src frame information for reprocessing
1141 *
1142 * PARAMETERS :
1143 * @src_frame : input pp data to be filled out
1144 * @pInputBuffer : input buffer for reprocessing
1145 * @reproc_cfg : pointer to the reprocess config
1146 * @metadata : pointer to the metadata buffer
1147 * @output_buffer : output buffer for reprocessing; could be NULL if not
1148 * framework allocated
1149 * @frameNumber : frame number of the request
1150 *
1151 * RETURN : int32_t type of status
1152 * NO_ERROR -- success
1153 * none-zero failure code
1154 *==========================================================================*/
setFwkInputPPData(qcamera_fwk_input_pp_data_t * src_frame,camera3_stream_buffer_t * pInputBuffer,reprocess_config_t * reproc_cfg,metadata_buffer_t * metadata,buffer_handle_t * output_buffer,uint32_t frameNumber)1155 int32_t QCamera3ProcessingChannel::setFwkInputPPData(qcamera_fwk_input_pp_data_t *src_frame,
1156 camera3_stream_buffer_t *pInputBuffer, reprocess_config_t *reproc_cfg,
1157 metadata_buffer_t *metadata, buffer_handle_t *output_buffer,
1158 uint32_t frameNumber)
1159 {
1160 int32_t rc = NO_ERROR;
1161 int input_index = mOfflineMemory.getMatchBufIndex((void*)pInputBuffer->buffer);
1162 if(input_index < 0) {
1163 rc = mOfflineMemory.registerBuffer(pInputBuffer->buffer, mStreamType);
1164 if (NO_ERROR != rc) {
1165 LOGE("On-the-fly input buffer registration failed %d",
1166 rc);
1167 return rc;
1168 }
1169 input_index = mOfflineMemory.getMatchBufIndex((void*)pInputBuffer->buffer);
1170 if (input_index < 0) {
1171 LOGE("Could not find object among registered buffers");
1172 return DEAD_OBJECT;
1173 }
1174 }
1175 mOfflineMemory.markFrameNumber(input_index, frameNumber);
1176
1177 src_frame->src_frame = *pInputBuffer;
1178 rc = mOfflineMemory.getBufDef(reproc_cfg->input_stream_plane_info.plane_info,
1179 src_frame->input_buffer, input_index);
1180 if (rc != 0) {
1181 return rc;
1182 }
1183 dumpYUV(&src_frame->input_buffer, reproc_cfg->input_stream_dim,
1184 reproc_cfg->input_stream_plane_info.plane_info, QCAMERA_DUMP_FRM_INPUT_REPROCESS);
1185 cam_dimension_t dim = {sizeof(metadata_buffer_t), 1};
1186 cam_stream_buf_plane_info_t meta_planes;
1187 rc = mm_stream_calc_offset_metadata(&dim, &mPaddingInfo, &meta_planes);
1188 if (rc != 0) {
1189 LOGE("Metadata stream plane info calculation failed!");
1190 return rc;
1191 }
1192 uint32_t metaBufIdx;
1193 {
1194 Mutex::Autolock lock(mFreeOfflineMetaBuffersLock);
1195 if (mFreeOfflineMetaBuffersList.empty()) {
1196 LOGE("mFreeOfflineMetaBuffersList is null. Fatal");
1197 return BAD_VALUE;
1198 }
1199
1200 metaBufIdx = *(mFreeOfflineMetaBuffersList.begin());
1201 mFreeOfflineMetaBuffersList.erase(mFreeOfflineMetaBuffersList.begin());
1202 LOGD("erasing %d, mFreeOfflineMetaBuffersList.size %d", metaBufIdx,
1203 mFreeOfflineMetaBuffersList.size());
1204 }
1205
1206 mOfflineMetaMemory.markFrameNumber(metaBufIdx, frameNumber);
1207
1208 mm_camera_buf_def_t meta_buf;
1209 cam_frame_len_offset_t offset = meta_planes.plane_info;
1210 rc = mOfflineMetaMemory.getBufDef(offset, meta_buf, metaBufIdx);
1211 if (NO_ERROR != rc) {
1212 return rc;
1213 }
1214 memcpy(meta_buf.buffer, metadata, sizeof(metadata_buffer_t));
1215 src_frame->metadata_buffer = meta_buf;
1216 src_frame->reproc_config = *reproc_cfg;
1217 src_frame->output_buffer = output_buffer;
1218 src_frame->frameNumber = frameNumber;
1219 return rc;
1220 }
1221
1222 /*===========================================================================
1223 * FUNCTION : checkStreamCbErrors
1224 *
1225 * DESCRIPTION: check the stream callback for errors
1226 *
1227 * PARAMETERS :
1228 * @super_frame : the super frame with filled buffer
1229 * @stream : stream on which the buffer was requested and filled
1230 *
1231 * RETURN : int32_t type of status
1232 * NO_ERROR -- success
1233 * none-zero failure code
1234 *==========================================================================*/
checkStreamCbErrors(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream)1235 int32_t QCamera3ProcessingChannel::checkStreamCbErrors(mm_camera_super_buf_t *super_frame,
1236 QCamera3Stream *stream)
1237 {
1238 if (NULL == stream) {
1239 LOGE("Invalid stream");
1240 return BAD_VALUE;
1241 }
1242
1243 if(NULL == super_frame) {
1244 LOGE("Invalid Super buffer");
1245 return BAD_VALUE;
1246 }
1247
1248 if(super_frame->num_bufs != 1) {
1249 LOGE("Multiple streams are not supported");
1250 return BAD_VALUE;
1251 }
1252 if(NULL == super_frame->bufs[0]) {
1253 LOGE("Error, Super buffer frame does not contain valid buffer");
1254 return BAD_VALUE;
1255 }
1256 return NO_ERROR;
1257 }
1258
1259 /*===========================================================================
1260 * FUNCTION : getStreamSize
1261 *
1262 * DESCRIPTION: get the size from the camera3_stream_t for the channel
1263 *
1264 * PARAMETERS :
1265 * @dim : Return the size of the stream
1266 *
1267 * RETURN : int32_t type of status
1268 * NO_ERROR -- success
1269 * none-zero failure code
1270 *==========================================================================*/
getStreamSize(cam_dimension_t & dim)1271 int32_t QCamera3ProcessingChannel::getStreamSize(cam_dimension_t &dim)
1272 {
1273 if (mCamera3Stream) {
1274 dim.width = mCamera3Stream->width;
1275 dim.height = mCamera3Stream->height;
1276 return NO_ERROR;
1277 } else {
1278 return BAD_VALUE;
1279 }
1280 }
1281
1282 /*===========================================================================
1283 * FUNCTION : getStreamBufs
1284 *
1285 * DESCRIPTION: get the buffers allocated to the stream
1286 *
1287 * PARAMETERS :
1288 * @len : buffer length
1289 *
1290 * RETURN : int32_t type of status
1291 * NO_ERROR -- success
1292 * none-zero failure code
1293 *==========================================================================*/
getStreamBufs(uint32_t)1294 QCamera3StreamMem* QCamera3ProcessingChannel::getStreamBufs(uint32_t /*len*/)
1295 {
1296 KPI_ATRACE_CALL();
1297 return &mMemory;
1298 }
1299
1300 /*===========================================================================
1301 * FUNCTION : putStreamBufs
1302 *
1303 * DESCRIPTION: release the buffers allocated to the stream
1304 *
1305 * PARAMETERS : NONE
1306 *
1307 * RETURN : NONE
1308 *==========================================================================*/
putStreamBufs()1309 void QCamera3ProcessingChannel::putStreamBufs()
1310 {
1311 mMemory.unregisterBuffers();
1312
1313 /* Reclaim all the offline metabuffers and push them to free list */
1314 {
1315 Mutex::Autolock lock(mFreeOfflineMetaBuffersLock);
1316 mFreeOfflineMetaBuffersList.clear();
1317 for (uint32_t i = 0; i < mOfflineMetaMemory.getCnt(); i++) {
1318 mFreeOfflineMetaBuffersList.push_back(i);
1319 }
1320 }
1321 }
1322
1323
1324 /*===========================================================================
1325 * FUNCTION : stop
1326 *
1327 * DESCRIPTION: stop processing channel, which will stop all streams within,
1328 * including the reprocessing channel in postprocessor.
1329 *
1330 * PARAMETERS : none
1331 *
1332 * RETURN : int32_t type of status
1333 * NO_ERROR -- success
1334 * none-zero failure code
1335 *==========================================================================*/
stop()1336 int32_t QCamera3ProcessingChannel::stop()
1337 {
1338 int32_t rc = NO_ERROR;
1339 if(!m_bIsActive) {
1340 LOGE("Attempt to stop inactive channel");
1341 return rc;
1342 }
1343
1344 m_postprocessor.stop();
1345 mPostProcStarted = false;
1346 rc |= QCamera3Channel::stop();
1347 return rc;
1348 }
1349
1350 /*===========================================================================
1351 * FUNCTION : startPostProc
1352 *
1353 * DESCRIPTION: figure out if the postprocessor needs to be restarted and if yes
1354 * start it
1355 *
1356 * PARAMETERS :
1357 * @inputBufExists : whether there is an input buffer for post processing
1358 * @config : reprocessing configuration
1359 * @metadata : metadata associated with the reprocessing request
1360 *
1361 * RETURN : NONE
1362 *==========================================================================*/
startPostProc(const reprocess_config_t & config)1363 void QCamera3ProcessingChannel::startPostProc(const reprocess_config_t &config)
1364 {
1365 if(!mPostProcStarted) {
1366 m_postprocessor.start(config);
1367 mPostProcStarted = true;
1368 }
1369 }
1370
1371 /*===========================================================================
1372 * FUNCTION : queueReprocMetadata
1373 *
1374 * DESCRIPTION: queue the reprocess metadata to the postprocessor
1375 *
1376 * PARAMETERS : metadata : the metadata corresponding to the pp frame
1377 *
1378 * RETURN : int32_t type of status
1379 * NO_ERROR -- success
1380 * none-zero failure code
1381 *==========================================================================*/
queueReprocMetadata(mm_camera_super_buf_t * metadata)1382 int32_t QCamera3ProcessingChannel::queueReprocMetadata(mm_camera_super_buf_t *metadata)
1383 {
1384 return m_postprocessor.processPPMetadata(metadata);
1385 }
1386
1387 /*===========================================================================
1388 * FUNCTION : metadataBufDone
1389 *
1390 * DESCRIPTION: Buffer done method for a metadata buffer
1391 *
1392 * PARAMETERS :
1393 * @recvd_frame : received metadata frame
1394 *
1395 * RETURN : int32_t type of status
1396 * NO_ERROR -- success
1397 * none-zero failure code
1398 *==========================================================================*/
metadataBufDone(mm_camera_super_buf_t * recvd_frame)1399 int32_t QCamera3ProcessingChannel::metadataBufDone(mm_camera_super_buf_t *recvd_frame)
1400 {
1401 int32_t rc = NO_ERROR;;
1402 if ((NULL == m_pMetaChannel) || (NULL == recvd_frame)) {
1403 LOGE("Metadata channel or metadata buffer invalid");
1404 return BAD_VALUE;
1405 }
1406
1407 rc = ((QCamera3MetadataChannel*)m_pMetaChannel)->bufDone(recvd_frame);
1408
1409 return rc;
1410 }
1411
1412 /*===========================================================================
1413 * FUNCTION : translateStreamTypeAndFormat
1414 *
1415 * DESCRIPTION: translates the framework stream format into HAL stream type
1416 * and format
1417 *
1418 * PARAMETERS :
1419 * @streamType : translated stream type
1420 * @streamFormat : translated stream format
1421 * @stream : fwk stream
1422 *
1423 * RETURN : int32_t type of status
1424 * NO_ERROR -- success
1425 * none-zero failure code
1426 *==========================================================================*/
translateStreamTypeAndFormat(camera3_stream_t * stream,cam_stream_type_t & streamType,cam_format_t & streamFormat)1427 int32_t QCamera3ProcessingChannel::translateStreamTypeAndFormat(camera3_stream_t *stream,
1428 cam_stream_type_t &streamType, cam_format_t &streamFormat)
1429 {
1430 switch (stream->format) {
1431 case HAL_PIXEL_FORMAT_YCbCr_420_888:
1432 if(stream->stream_type == CAMERA3_STREAM_INPUT){
1433 streamType = CAM_STREAM_TYPE_SNAPSHOT;
1434 streamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_SNAPSHOT,
1435 stream->width, stream->height);
1436 } else {
1437 streamType = CAM_STREAM_TYPE_CALLBACK;
1438 streamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_CALLBACK,
1439 stream->width, stream->height);
1440 }
1441 break;
1442 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
1443 if (stream->usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) {
1444 streamType = CAM_STREAM_TYPE_VIDEO;
1445 streamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_VIDEO,
1446 stream->width, stream->height);
1447 } else if(stream->stream_type == CAMERA3_STREAM_INPUT ||
1448 stream->stream_type == CAMERA3_STREAM_BIDIRECTIONAL ||
1449 IS_USAGE_ZSL(stream->usage)){
1450 streamType = CAM_STREAM_TYPE_SNAPSHOT;
1451 streamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_SNAPSHOT,
1452 stream->width, stream->height);
1453 } else {
1454 streamType = CAM_STREAM_TYPE_PREVIEW;
1455 streamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_PREVIEW,
1456 stream->width, stream->height);
1457 }
1458 break;
1459 case HAL_PIXEL_FORMAT_RAW_OPAQUE:
1460 case HAL_PIXEL_FORMAT_RAW16:
1461 case HAL_PIXEL_FORMAT_RAW10:
1462 streamType = CAM_STREAM_TYPE_RAW;
1463 streamFormat = CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG;
1464 break;
1465 default:
1466 return -EINVAL;
1467 }
1468 LOGD("fwk_format = %d, streamType = %d, streamFormat = %d",
1469 stream->format, streamType, streamFormat);
1470 return NO_ERROR;
1471 }
1472
1473 /*===========================================================================
1474 * FUNCTION : setReprocConfig
1475 *
1476 * DESCRIPTION: sets the reprocessing parameters for the input buffer
1477 *
1478 * PARAMETERS :
1479 * @reproc_cfg : the configuration to be set
1480 * @pInputBuffer : pointer to the input buffer
1481 * @metadata : pointer to the reprocessing metadata buffer
1482 * @streamFormat : format of the input stream
1483 *
1484 * RETURN : int32_t type of status
1485 * NO_ERROR -- success
1486 * none-zero failure code
1487 *==========================================================================*/
setReprocConfig(reprocess_config_t & reproc_cfg,camera3_stream_buffer_t * pInputBuffer,__unused metadata_buffer_t * metadata,cam_format_t streamFormat,cam_dimension_t dim)1488 int32_t QCamera3ProcessingChannel::setReprocConfig(reprocess_config_t &reproc_cfg,
1489 camera3_stream_buffer_t *pInputBuffer,
1490 __unused metadata_buffer_t *metadata,
1491 cam_format_t streamFormat, cam_dimension_t dim)
1492 {
1493 int32_t rc = 0;
1494 reproc_cfg.padding = &mPaddingInfo;
1495 //to ensure a big enough buffer size set the height and width
1496 //padding to max(height padding, width padding)
1497 if (reproc_cfg.padding->height_padding > reproc_cfg.padding->width_padding) {
1498 reproc_cfg.padding->width_padding = reproc_cfg.padding->height_padding;
1499 } else {
1500 reproc_cfg.padding->height_padding = reproc_cfg.padding->width_padding;
1501 }
1502 if (NULL != pInputBuffer) {
1503 reproc_cfg.input_stream_dim.width = (int32_t)pInputBuffer->stream->width;
1504 reproc_cfg.input_stream_dim.height = (int32_t)pInputBuffer->stream->height;
1505 } else {
1506 reproc_cfg.input_stream_dim.width = (int32_t)dim.width;
1507 reproc_cfg.input_stream_dim.height = (int32_t)dim.height;
1508 }
1509 reproc_cfg.src_channel = this;
1510 reproc_cfg.output_stream_dim.width = mCamera3Stream->width;
1511 reproc_cfg.output_stream_dim.height = mCamera3Stream->height;
1512 reproc_cfg.reprocess_type = getReprocessType();
1513
1514 //offset calculation
1515 if (NULL != pInputBuffer) {
1516 rc = translateStreamTypeAndFormat(pInputBuffer->stream,
1517 reproc_cfg.stream_type, reproc_cfg.stream_format);
1518 if (rc != NO_ERROR) {
1519 LOGE("Stream format %d is not supported",
1520 pInputBuffer->stream->format);
1521 return rc;
1522 }
1523 } else {
1524 reproc_cfg.stream_type = mStreamType;
1525 reproc_cfg.stream_format = streamFormat;
1526 }
1527
1528 switch (reproc_cfg.stream_type) {
1529 case CAM_STREAM_TYPE_PREVIEW:
1530 if (getStreamByIndex(0) == NULL) {
1531 LOGE("Could not find stream");
1532 rc = -1;
1533 break;
1534 }
1535 rc = mm_stream_calc_offset_preview(
1536 getStreamByIndex(0)->getStreamInfo(),
1537 &reproc_cfg.input_stream_dim,
1538 reproc_cfg.padding,
1539 &reproc_cfg.input_stream_plane_info);
1540 break;
1541 case CAM_STREAM_TYPE_VIDEO:
1542 rc = mm_stream_calc_offset_video(reproc_cfg.stream_format,
1543 &reproc_cfg.input_stream_dim,
1544 &reproc_cfg.input_stream_plane_info);
1545 break;
1546 case CAM_STREAM_TYPE_RAW:
1547 rc = mm_stream_calc_offset_raw(reproc_cfg.stream_format,
1548 &reproc_cfg.input_stream_dim,
1549 reproc_cfg.padding, &reproc_cfg.input_stream_plane_info);
1550 break;
1551 case CAM_STREAM_TYPE_SNAPSHOT:
1552 case CAM_STREAM_TYPE_CALLBACK:
1553 default:
1554 rc = mm_stream_calc_offset_snapshot(streamFormat, &reproc_cfg.input_stream_dim,
1555 reproc_cfg.padding, &reproc_cfg.input_stream_plane_info);
1556 break;
1557 }
1558 if (rc != 0) {
1559 LOGE("Stream %d plane info calculation failed!", mStreamType);
1560 return rc;
1561 }
1562 return rc;
1563 }
1564
1565 /*===========================================================================
1566 * FUNCTION : reprocessCbRoutine
1567 *
1568 * DESCRIPTION: callback function for the reprocessed frame. This frame now
1569 * should be returned to the framework
1570 *
1571 * PARAMETERS :
1572 * @resultBuffer : buffer containing the reprocessed data
1573 * @resultFrameNumber : frame number on which the buffer was requested
1574 *
1575 * RETURN : NONE
1576 *
1577 *==========================================================================*/
reprocessCbRoutine(buffer_handle_t * resultBuffer,uint32_t resultFrameNumber)1578 void QCamera3ProcessingChannel::reprocessCbRoutine(buffer_handle_t *resultBuffer,
1579 uint32_t resultFrameNumber)
1580 {
1581 ATRACE_CALL();
1582 int rc = NO_ERROR;
1583
1584 rc = releaseOfflineMemory(resultFrameNumber);
1585 if (NO_ERROR != rc) {
1586 LOGE("Error releasing offline memory %d", rc);
1587 }
1588 /* Since reprocessing is done, send the callback to release the input buffer */
1589 if (mChannelCB) {
1590 mChannelCB(NULL, NULL, resultFrameNumber, true, mUserData);
1591 }
1592 issueChannelCb(resultBuffer, resultFrameNumber);
1593
1594 return;
1595 }
1596
1597 /*===========================================================================
1598 * FUNCTION : issueChannelCb
1599 *
1600 * DESCRIPTION: function to set the result and issue channel callback
1601 *
1602 * PARAMETERS :
1603 * @resultBuffer : buffer containing the data
1604 * @resultFrameNumber : frame number on which the buffer was requested
1605 *
1606 * RETURN : NONE
1607 *
1608 *
1609 *==========================================================================*/
issueChannelCb(buffer_handle_t * resultBuffer,uint32_t resultFrameNumber)1610 void QCamera3ProcessingChannel::issueChannelCb(buffer_handle_t *resultBuffer,
1611 uint32_t resultFrameNumber)
1612 {
1613 camera3_stream_buffer_t result;
1614 //Use below data to issue framework callback
1615 result.stream = mCamera3Stream;
1616 result.buffer = resultBuffer;
1617 result.status = CAMERA3_BUFFER_STATUS_OK;
1618 result.acquire_fence = -1;
1619 result.release_fence = -1;
1620
1621 if (mChannelCB) {
1622 mChannelCB(NULL, &result, resultFrameNumber, false, mUserData);
1623 }
1624 }
1625
1626 /*===========================================================================
1627 * FUNCTION : showDebugFPS
1628 *
1629 * DESCRIPTION: Function to log the fps for preview, video, callback and raw
1630 * streams
1631 *
1632 * PARAMETERS : Stream type
1633 *
1634 * RETURN : None
1635 *==========================================================================*/
showDebugFPS(int32_t streamType)1636 void QCamera3ProcessingChannel::showDebugFPS(int32_t streamType)
1637 {
1638 double fps = 0;
1639 mFrameCount++;
1640 nsecs_t now = systemTime();
1641 nsecs_t diff = now - mLastFpsTime;
1642 if (diff > ms2ns(250)) {
1643 fps = (((double)(mFrameCount - mLastFrameCount)) *
1644 (double)(s2ns(1))) / (double)diff;
1645 switch(streamType) {
1646 case CAM_STREAM_TYPE_PREVIEW:
1647 LOGH("PROFILE_PREVIEW_FRAMES_PER_SECOND : %.4f: mFrameCount=%d",
1648 fps, mFrameCount);
1649 break;
1650 case CAM_STREAM_TYPE_VIDEO:
1651 LOGH("PROFILE_VIDEO_FRAMES_PER_SECOND : %.4f",
1652 fps);
1653 break;
1654 case CAM_STREAM_TYPE_CALLBACK:
1655 LOGH("PROFILE_CALLBACK_FRAMES_PER_SECOND : %.4f",
1656 fps);
1657 break;
1658 case CAM_STREAM_TYPE_RAW:
1659 LOGH("PROFILE_RAW_FRAMES_PER_SECOND : %.4f",
1660 fps);
1661 break;
1662 default:
1663 LOGH("logging not supported for the stream");
1664 break;
1665 }
1666 mLastFpsTime = now;
1667 mLastFrameCount = mFrameCount;
1668 }
1669 }
1670
1671 /*===========================================================================
1672 * FUNCTION : releaseOfflineMemory
1673 *
1674 * DESCRIPTION: function to clean up the offline memory used for input reprocess
1675 *
1676 * PARAMETERS :
1677 * @resultFrameNumber : frame number on which the buffer was requested
1678 *
1679 * RETURN : int32_t type of status
1680 * NO_ERROR -- success
1681 * non-zero failure code
1682 *
1683 *
1684 *==========================================================================*/
releaseOfflineMemory(uint32_t resultFrameNumber)1685 int32_t QCamera3ProcessingChannel::releaseOfflineMemory(uint32_t resultFrameNumber)
1686 {
1687 int32_t rc = NO_ERROR;
1688 int32_t inputBufIndex =
1689 mOfflineMemory.getGrallocBufferIndex(resultFrameNumber);
1690 if (0 <= inputBufIndex) {
1691 rc = mOfflineMemory.unregisterBuffer(inputBufIndex);
1692 } else {
1693 LOGW("Could not find offline input buffer, resultFrameNumber %d",
1694 resultFrameNumber);
1695 }
1696 if (rc != NO_ERROR) {
1697 LOGE("Failed to unregister offline input buffer");
1698 }
1699
1700 int32_t metaBufIndex =
1701 mOfflineMetaMemory.getHeapBufferIndex(resultFrameNumber);
1702 if (0 <= metaBufIndex) {
1703 Mutex::Autolock lock(mFreeOfflineMetaBuffersLock);
1704 mFreeOfflineMetaBuffersList.push_back((uint32_t)metaBufIndex);
1705 } else {
1706 LOGW("Could not find offline meta buffer, resultFrameNumber %d",
1707 resultFrameNumber);
1708 }
1709
1710 return rc;
1711 }
1712
1713 /* Regular Channel methods */
1714 /*===========================================================================
1715 * FUNCTION : QCamera3RegularChannel
1716 *
1717 * DESCRIPTION: constructor of QCamera3RegularChannel
1718 *
1719 * PARAMETERS :
1720 * @cam_handle : camera handle
1721 * @cam_ops : ptr to camera ops table
1722 * @cb_routine : callback routine to frame aggregator
1723 * @stream : camera3_stream_t structure
1724 * @stream_type: Channel stream type
1725 * @postprocess_mask: feature mask for postprocessing
1726 * @metadataChannel : metadata channel for the session
1727 * @numBuffers : number of max dequeued buffers
1728 *
1729 * RETURN : none
1730 *==========================================================================*/
QCamera3RegularChannel(uint32_t cam_handle,uint32_t channel_handle,mm_camera_ops_t * cam_ops,channel_cb_routine cb_routine,channel_cb_buffer_err cb_buffer_err,cam_padding_info_t * paddingInfo,void * userData,camera3_stream_t * stream,cam_stream_type_t stream_type,cam_feature_mask_t postprocess_mask,QCamera3Channel * metadataChannel,uint32_t numBuffers)1731 QCamera3RegularChannel::QCamera3RegularChannel(uint32_t cam_handle,
1732 uint32_t channel_handle,
1733 mm_camera_ops_t *cam_ops,
1734 channel_cb_routine cb_routine,
1735 channel_cb_buffer_err cb_buffer_err,
1736 cam_padding_info_t *paddingInfo,
1737 void *userData,
1738 camera3_stream_t *stream,
1739 cam_stream_type_t stream_type,
1740 cam_feature_mask_t postprocess_mask,
1741 QCamera3Channel *metadataChannel,
1742 uint32_t numBuffers) :
1743 QCamera3ProcessingChannel(cam_handle, channel_handle, cam_ops,
1744 cb_routine, cb_buffer_err, paddingInfo, userData, stream, stream_type,
1745 postprocess_mask, metadataChannel, numBuffers),
1746 mBatchSize(0),
1747 mRotation(ROTATE_0)
1748 {
1749 }
1750
1751 /*===========================================================================
1752 * FUNCTION : ~QCamera3RegularChannel
1753 *
1754 * DESCRIPTION: destructor of QCamera3RegularChannel
1755 *
1756 * PARAMETERS : none
1757 *
1758 * RETURN : none
1759 *==========================================================================*/
~QCamera3RegularChannel()1760 QCamera3RegularChannel::~QCamera3RegularChannel()
1761 {
1762 destroy();
1763 }
1764
1765 /*===========================================================================
1766 * FUNCTION : initialize
1767 *
1768 * DESCRIPTION: Initialize and add camera channel & stream
1769 *
1770 * PARAMETERS :
1771 * @isType : type of image stabilization required on this stream
1772 *
1773 * RETURN : int32_t type of status
1774 * NO_ERROR -- success
1775 * none-zero failure code
1776 *==========================================================================*/
1777
initialize(cam_is_type_t isType)1778 int32_t QCamera3RegularChannel::initialize(cam_is_type_t isType)
1779 {
1780 ATRACE_CALL();
1781 int32_t rc = NO_ERROR;
1782
1783 cam_dimension_t streamDim;
1784
1785 if (NULL == mCamera3Stream) {
1786 LOGE("Camera stream uninitialized");
1787 return NO_INIT;
1788 }
1789
1790 if (1 <= m_numStreams) {
1791 // Only one stream per channel supported in v3 Hal
1792 return NO_ERROR;
1793 }
1794
1795 mIsType = isType;
1796
1797 rc = translateStreamTypeAndFormat(mCamera3Stream, mStreamType,
1798 mStreamFormat);
1799 if (rc != NO_ERROR) {
1800 return -EINVAL;
1801 }
1802
1803
1804 if ((mStreamType == CAM_STREAM_TYPE_VIDEO) ||
1805 (mStreamType == CAM_STREAM_TYPE_PREVIEW)) {
1806 if ((mCamera3Stream->rotation != CAMERA3_STREAM_ROTATION_0) &&
1807 ((mPostProcMask & CAM_QCOM_FEATURE_ROTATION) == 0)) {
1808 LOGE("attempting rotation %d when rotation is disabled",
1809 mCamera3Stream->rotation);
1810 return -EINVAL;
1811 }
1812
1813 switch (mCamera3Stream->rotation) {
1814 case CAMERA3_STREAM_ROTATION_0:
1815 mRotation = ROTATE_0;
1816 break;
1817 case CAMERA3_STREAM_ROTATION_90: {
1818 mRotation = ROTATE_90;
1819 break;
1820 }
1821 case CAMERA3_STREAM_ROTATION_180:
1822 mRotation = ROTATE_180;
1823 break;
1824 case CAMERA3_STREAM_ROTATION_270: {
1825 mRotation = ROTATE_270;
1826 break;
1827 }
1828 default:
1829 LOGE("Unknown rotation: %d",
1830 mCamera3Stream->rotation);
1831 return -EINVAL;
1832 }
1833 } else if (mCamera3Stream->rotation != CAMERA3_STREAM_ROTATION_0) {
1834 LOGE("Rotation %d is not supported by stream type %d",
1835 mCamera3Stream->rotation,
1836 mStreamType);
1837 return -EINVAL;
1838 }
1839
1840 streamDim.width = mCamera3Stream->width;
1841 streamDim.height = mCamera3Stream->height;
1842
1843 LOGD("batch size is %d", mBatchSize);
1844 rc = QCamera3Channel::addStream(mStreamType,
1845 mStreamFormat,
1846 streamDim,
1847 mRotation,
1848 mNumBufs,
1849 mPostProcMask,
1850 mIsType,
1851 mBatchSize);
1852
1853 return rc;
1854 }
1855
1856 /*===========================================================================
1857 * FUNCTION : setBatchSize
1858 *
1859 * DESCRIPTION: Set batch size for the channel.
1860 *
1861 * PARAMETERS :
1862 * @batchSize : Number of image buffers in a batch
1863 *
1864 * RETURN : int32_t type of status
1865 * NO_ERROR -- success always
1866 * none-zero failure code
1867 *==========================================================================*/
setBatchSize(uint32_t batchSize)1868 int32_t QCamera3RegularChannel::setBatchSize(uint32_t batchSize)
1869 {
1870 int32_t rc = NO_ERROR;
1871
1872 mBatchSize = batchSize;
1873 LOGD("Batch size set: %d", mBatchSize);
1874 return rc;
1875 }
1876
1877 /*===========================================================================
1878 * FUNCTION : getStreamTypeMask
1879 *
1880 * DESCRIPTION: Get bit mask of all stream types in this channel.
1881 * If stream is not initialized, then generate mask based on
1882 * local streamType
1883 *
1884 * PARAMETERS : None
1885 *
1886 * RETURN : Bit mask of all stream types in this channel
1887 *==========================================================================*/
getStreamTypeMask()1888 uint32_t QCamera3RegularChannel::getStreamTypeMask()
1889 {
1890 if (mStreams[0]) {
1891 return QCamera3Channel::getStreamTypeMask();
1892 } else {
1893 return (1U << mStreamType);
1894 }
1895 }
1896
1897 /*===========================================================================
1898 * FUNCTION : queueBatchBuf
1899 *
1900 * DESCRIPTION: queue batch container to downstream
1901 *
1902 * PARAMETERS :
1903 *
1904 * RETURN : int32_t type of status
1905 * NO_ERROR -- success always
1906 * none-zero failure code
1907 *==========================================================================*/
queueBatchBuf()1908 int32_t QCamera3RegularChannel::queueBatchBuf()
1909 {
1910 int32_t rc = NO_ERROR;
1911
1912 if (mStreams[0]) {
1913 rc = mStreams[0]->queueBatchBuf();
1914 }
1915 if (rc != NO_ERROR) {
1916 LOGE("stream->queueBatchContainer failed");
1917 }
1918 return rc;
1919 }
1920
1921 /*===========================================================================
1922 * FUNCTION : request
1923 *
1924 * DESCRIPTION: process a request from camera service. Stream on if ncessary.
1925 *
1926 * PARAMETERS :
1927 * @buffer : buffer to be filled for this request
1928 *
1929 * RETURN : 0 on a success start of capture
1930 * -EINVAL on invalid input
1931 * -ENODEV on serious error
1932 *==========================================================================*/
request(buffer_handle_t * buffer,uint32_t frameNumber,int & indexUsed)1933 int32_t QCamera3RegularChannel::request(buffer_handle_t *buffer, uint32_t frameNumber, int &indexUsed)
1934 {
1935 ATRACE_CALL();
1936 //FIX ME: Return buffer back in case of failures below.
1937
1938 int32_t rc = NO_ERROR;
1939 int index;
1940
1941 if (NULL == buffer) {
1942 LOGE("Invalid buffer in channel request");
1943 return BAD_VALUE;
1944 }
1945
1946 if(!m_bIsActive) {
1947 rc = registerBuffer(buffer, mIsType);
1948 if (NO_ERROR != rc) {
1949 LOGE("On-the-fly buffer registration failed %d",
1950 rc);
1951 return rc;
1952 }
1953
1954 rc = start();
1955 if (NO_ERROR != rc) {
1956 return rc;
1957 }
1958 } else {
1959 LOGD("Request on an existing stream");
1960 }
1961
1962 index = mMemory.getMatchBufIndex((void*)buffer);
1963 if(index < 0) {
1964 rc = registerBuffer(buffer, mIsType);
1965 if (NO_ERROR != rc) {
1966 LOGE("On-the-fly buffer registration failed %d",
1967 rc);
1968 return rc;
1969 }
1970
1971 index = mMemory.getMatchBufIndex((void*)buffer);
1972 if (index < 0) {
1973 LOGE("Could not find object among registered buffers");
1974 return DEAD_OBJECT;
1975 }
1976 }
1977
1978 rc = mMemory.markFrameNumber((uint32_t)index, frameNumber);
1979 if(rc != NO_ERROR) {
1980 LOGE("Failed to mark FrameNumber:%d,idx:%d",frameNumber,index);
1981 return rc;
1982 }
1983 rc = mStreams[0]->bufDone((uint32_t)index);
1984 if(rc != NO_ERROR) {
1985 LOGE("Failed to Q new buffer to stream");
1986 mMemory.markFrameNumber(index, -1);
1987 return rc;
1988 }
1989
1990 indexUsed = index;
1991 return rc;
1992 }
1993
1994 /*===========================================================================
1995 * FUNCTION : getReprocessType
1996 *
1997 * DESCRIPTION: get the type of reprocess output supported by this channel
1998 *
1999 * PARAMETERS : NONE
2000 *
2001 * RETURN : reprocess_type_t : type of reprocess
2002 *==========================================================================*/
getReprocessType()2003 reprocess_type_t QCamera3RegularChannel::getReprocessType()
2004 {
2005 return REPROCESS_TYPE_PRIVATE;
2006 }
2007
2008
QCamera3MetadataChannel(uint32_t cam_handle,uint32_t channel_handle,mm_camera_ops_t * cam_ops,channel_cb_routine cb_routine,channel_cb_buffer_err cb_buffer_err,cam_padding_info_t * paddingInfo,cam_feature_mask_t postprocess_mask,void * userData,uint32_t numBuffers)2009 QCamera3MetadataChannel::QCamera3MetadataChannel(uint32_t cam_handle,
2010 uint32_t channel_handle,
2011 mm_camera_ops_t *cam_ops,
2012 channel_cb_routine cb_routine,
2013 channel_cb_buffer_err cb_buffer_err,
2014 cam_padding_info_t *paddingInfo,
2015 cam_feature_mask_t postprocess_mask,
2016 void *userData, uint32_t numBuffers) :
2017 QCamera3Channel(cam_handle, channel_handle, cam_ops,
2018 cb_routine, cb_buffer_err, paddingInfo, postprocess_mask,
2019 userData, numBuffers),
2020 mMemory(NULL)
2021 {
2022 }
2023
~QCamera3MetadataChannel()2024 QCamera3MetadataChannel::~QCamera3MetadataChannel()
2025 {
2026 destroy();
2027
2028 if (mMemory) {
2029 mMemory->deallocate();
2030 delete mMemory;
2031 mMemory = NULL;
2032 }
2033 }
2034
initialize(cam_is_type_t isType)2035 int32_t QCamera3MetadataChannel::initialize(cam_is_type_t isType)
2036 {
2037 ATRACE_CALL();
2038 int32_t rc;
2039 cam_dimension_t streamDim;
2040
2041 if (mMemory || m_numStreams > 0) {
2042 LOGE("metadata channel already initialized");
2043 return -EINVAL;
2044 }
2045
2046 streamDim.width = (int32_t)sizeof(metadata_buffer_t),
2047 streamDim.height = 1;
2048
2049 mIsType = isType;
2050 rc = QCamera3Channel::addStream(CAM_STREAM_TYPE_METADATA, CAM_FORMAT_MAX,
2051 streamDim, ROTATE_0, (uint8_t)mNumBuffers, mPostProcMask, mIsType);
2052 if (rc < 0) {
2053 LOGE("addStream failed");
2054 }
2055 return rc;
2056 }
2057
request(buffer_handle_t *,uint32_t,int &)2058 int32_t QCamera3MetadataChannel::request(buffer_handle_t * /*buffer*/,
2059 uint32_t /*frameNumber*/,
2060 int& /*indexUsed*/)
2061 {
2062 if (!m_bIsActive) {
2063 return start();
2064 }
2065 else
2066 return 0;
2067 }
2068
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream *)2069 void QCamera3MetadataChannel::streamCbRoutine(
2070 mm_camera_super_buf_t *super_frame,
2071 QCamera3Stream * /*stream*/)
2072 {
2073 ATRACE_NAME("metadata_stream_cb_routine");
2074 uint32_t requestNumber = 0;
2075 if (super_frame == NULL || super_frame->num_bufs != 1) {
2076 LOGE("super_frame is not valid");
2077 return;
2078 }
2079 if (mChannelCB) {
2080 mChannelCB(super_frame, NULL, requestNumber, false, mUserData);
2081 }
2082 }
2083
getStreamBufs(uint32_t len)2084 QCamera3StreamMem* QCamera3MetadataChannel::getStreamBufs(uint32_t len)
2085 {
2086 int rc;
2087 if (len < sizeof(metadata_buffer_t)) {
2088 LOGE("Metadata buffer size less than structure %d vs %d",
2089 len,
2090 sizeof(metadata_buffer_t));
2091 return NULL;
2092 }
2093 mMemory = new QCamera3StreamMem(MIN_STREAMING_BUFFER_NUM);
2094 if (!mMemory) {
2095 LOGE("unable to create metadata memory");
2096 return NULL;
2097 }
2098 rc = mMemory->allocateAll(len);
2099 if (rc < 0) {
2100 LOGE("unable to allocate metadata memory");
2101 delete mMemory;
2102 mMemory = NULL;
2103 return NULL;
2104 }
2105 clear_metadata_buffer((metadata_buffer_t*)mMemory->getPtr(0));
2106 return mMemory;
2107 }
2108
putStreamBufs()2109 void QCamera3MetadataChannel::putStreamBufs()
2110 {
2111 mMemory->deallocate();
2112 delete mMemory;
2113 mMemory = NULL;
2114 }
2115 /*************************************************************************************/
2116 // RAW Channel related functions
QCamera3RawChannel(uint32_t cam_handle,uint32_t channel_handle,mm_camera_ops_t * cam_ops,channel_cb_routine cb_routine,channel_cb_buffer_err cb_buffer_err,cam_padding_info_t * paddingInfo,void * userData,camera3_stream_t * stream,cam_feature_mask_t postprocess_mask,QCamera3Channel * metadataChannel,bool raw_16,uint32_t numBuffers)2117 QCamera3RawChannel::QCamera3RawChannel(uint32_t cam_handle,
2118 uint32_t channel_handle,
2119 mm_camera_ops_t *cam_ops,
2120 channel_cb_routine cb_routine,
2121 channel_cb_buffer_err cb_buffer_err,
2122 cam_padding_info_t *paddingInfo,
2123 void *userData,
2124 camera3_stream_t *stream,
2125 cam_feature_mask_t postprocess_mask,
2126 QCamera3Channel *metadataChannel,
2127 bool raw_16, uint32_t numBuffers) :
2128 QCamera3RegularChannel(cam_handle, channel_handle, cam_ops,
2129 cb_routine, cb_buffer_err, paddingInfo, userData, stream,
2130 CAM_STREAM_TYPE_RAW, postprocess_mask,
2131 metadataChannel, numBuffers),
2132 mIsRaw16(raw_16)
2133 {
2134 char prop[PROPERTY_VALUE_MAX];
2135 property_get("persist.camera.raw.debug.dump", prop, "0");
2136 mRawDump = atoi(prop);
2137 }
2138
~QCamera3RawChannel()2139 QCamera3RawChannel::~QCamera3RawChannel()
2140 {
2141 }
2142
2143 /*===========================================================================
2144 * FUNCTION : initialize
2145 *
2146 * DESCRIPTION: Initialize and add camera channel & stream
2147 *
2148 * PARAMETERS :
2149 * @isType : image stabilization type on the stream
2150 *
2151 * RETURN : int32_t type of status
2152 * NO_ERROR -- success
2153 * none-zero failure code
2154 *==========================================================================*/
2155
initialize(cam_is_type_t isType)2156 int32_t QCamera3RawChannel::initialize(cam_is_type_t isType)
2157 {
2158 return QCamera3RegularChannel::initialize(isType);
2159 }
2160
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream)2161 void QCamera3RawChannel::streamCbRoutine(
2162 mm_camera_super_buf_t *super_frame,
2163 QCamera3Stream * stream)
2164 {
2165 ATRACE_CALL();
2166 /* Move this back down once verified */
2167 if (mRawDump)
2168 dumpRawSnapshot(super_frame->bufs[0]);
2169
2170 if (mIsRaw16) {
2171 cam_format_t streamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_RAW,
2172 mCamera3Stream->width, mCamera3Stream->height);
2173 if (streamFormat == CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG)
2174 convertMipiToRaw16(super_frame->bufs[0]);
2175 else
2176 convertLegacyToRaw16(super_frame->bufs[0]);
2177 }
2178
2179 //Make sure cache coherence because extra processing is done
2180 mMemory.cleanInvalidateCache(super_frame->bufs[0]->buf_idx);
2181
2182 QCamera3RegularChannel::streamCbRoutine(super_frame, stream);
2183 return;
2184 }
2185
dumpRawSnapshot(mm_camera_buf_def_t * frame)2186 void QCamera3RawChannel::dumpRawSnapshot(mm_camera_buf_def_t *frame)
2187 {
2188 QCamera3Stream *stream = getStreamByIndex(0);
2189 if (stream != NULL) {
2190 char buf[FILENAME_MAX];
2191 memset(buf, 0, sizeof(buf));
2192 cam_dimension_t dim;
2193 memset(&dim, 0, sizeof(dim));
2194 stream->getFrameDimension(dim);
2195
2196 cam_frame_len_offset_t offset;
2197 memset(&offset, 0, sizeof(cam_frame_len_offset_t));
2198 stream->getFrameOffset(offset);
2199 snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"r_%d_%dx%d.raw",
2200 frame->frame_idx, offset.mp[0].stride, offset.mp[0].scanline);
2201
2202 int file_fd = open(buf, O_RDWR| O_CREAT, 0644);
2203 if (file_fd >= 0) {
2204 ssize_t written_len = write(file_fd, frame->buffer, frame->frame_len);
2205 LOGD("written number of bytes %zd", written_len);
2206 close(file_fd);
2207 } else {
2208 LOGE("failed to open file to dump image");
2209 }
2210 } else {
2211 LOGE("Could not find stream");
2212 }
2213
2214 }
2215
convertLegacyToRaw16(mm_camera_buf_def_t * frame)2216 void QCamera3RawChannel::convertLegacyToRaw16(mm_camera_buf_def_t *frame)
2217 {
2218 // Convert image buffer from Opaque raw format to RAW16 format
2219 // 10bit Opaque raw is stored in the format of:
2220 // 0000 - p5 - p4 - p3 - p2 - p1 - p0
2221 // where p0 to p5 are 6 pixels (each is 10bit)_and most significant
2222 // 4 bits are 0s. Each 64bit word contains 6 pixels.
2223
2224 QCamera3Stream *stream = getStreamByIndex(0);
2225 if (stream != NULL) {
2226 cam_dimension_t dim;
2227 memset(&dim, 0, sizeof(dim));
2228 stream->getFrameDimension(dim);
2229
2230 cam_frame_len_offset_t offset;
2231 memset(&offset, 0, sizeof(cam_frame_len_offset_t));
2232 stream->getFrameOffset(offset);
2233
2234 uint32_t raw16_stride = ((uint32_t)dim.width + 15U) & ~15U;
2235 uint16_t* raw16_buffer = (uint16_t *)frame->buffer;
2236
2237 // In-place format conversion.
2238 // Raw16 format always occupy more memory than opaque raw10.
2239 // Convert to Raw16 by iterating through all pixels from bottom-right
2240 // to top-left of the image.
2241 // One special notes:
2242 // 1. Cross-platform raw16's stride is 16 pixels.
2243 // 2. Opaque raw10's stride is 6 pixels, and aligned to 16 bytes.
2244 for (int32_t ys = dim.height - 1; ys >= 0; ys--) {
2245 uint32_t y = (uint32_t)ys;
2246 uint64_t* row_start = (uint64_t *)frame->buffer +
2247 y * (uint32_t)offset.mp[0].stride_in_bytes / 8;
2248 for (int32_t xs = dim.width - 1; xs >= 0; xs--) {
2249 uint32_t x = (uint32_t)xs;
2250 uint16_t raw16_pixel = 0x3FF & (row_start[x/6] >> (10*(x%6)));
2251 raw16_buffer[y*raw16_stride+x] = raw16_pixel;
2252 }
2253 }
2254 } else {
2255 LOGE("Could not find stream");
2256 }
2257
2258 }
2259
convertMipiToRaw16(mm_camera_buf_def_t * frame)2260 void QCamera3RawChannel::convertMipiToRaw16(mm_camera_buf_def_t *frame)
2261 {
2262 // Convert image buffer from mipi10 raw format to RAW16 format
2263 // mipi10 opaque raw is stored in the format of:
2264 // P3(1:0) P2(1:0) P1(1:0) P0(1:0) P3(9:2) P2(9:2) P1(9:2) P0(9:2)
2265 // 4 pixels occupy 5 bytes, no padding needed
2266
2267 QCamera3Stream *stream = getStreamByIndex(0);
2268 if (stream != NULL) {
2269 cam_dimension_t dim;
2270 memset(&dim, 0, sizeof(dim));
2271 stream->getFrameDimension(dim);
2272
2273 cam_frame_len_offset_t offset;
2274 memset(&offset, 0, sizeof(cam_frame_len_offset_t));
2275 stream->getFrameOffset(offset);
2276
2277 uint32_t raw16_stride = ((uint32_t)dim.width + 15U) & ~15U;
2278 uint16_t* raw16_buffer = (uint16_t *)frame->buffer;
2279
2280 // In-place format conversion.
2281 // Raw16 format always occupy more memory than opaque raw10.
2282 // Convert to Raw16 by iterating through all pixels from bottom-right
2283 // to top-left of the image.
2284 // One special notes:
2285 // 1. Cross-platform raw16's stride is 16 pixels.
2286 // 2. mipi raw10's stride is 4 pixels, and aligned to 16 bytes.
2287 for (int32_t ys = dim.height - 1; ys >= 0; ys--) {
2288 uint32_t y = (uint32_t)ys;
2289 uint8_t* row_start = (uint8_t *)frame->buffer +
2290 y * (uint32_t)offset.mp[0].stride_in_bytes;
2291 for (int32_t xs = dim.width - 1; xs >= 0; xs--) {
2292 uint32_t x = (uint32_t)xs;
2293 uint8_t upper_8bit = row_start[5*(x/4)+x%4];
2294 uint8_t lower_2bit = ((row_start[5*(x/4)+4] >> (x%4)) & 0x3);
2295 uint16_t raw16_pixel =
2296 (uint16_t)(((uint16_t)upper_8bit)<<2 |
2297 (uint16_t)lower_2bit);
2298 raw16_buffer[y*raw16_stride+x] = raw16_pixel;
2299 }
2300 }
2301 } else {
2302 LOGE("Could not find stream");
2303 }
2304
2305 }
2306
2307 /*===========================================================================
2308 * FUNCTION : getReprocessType
2309 *
2310 * DESCRIPTION: get the type of reprocess output supported by this channel
2311 *
2312 * PARAMETERS : NONE
2313 *
2314 * RETURN : reprocess_type_t : type of reprocess
2315 *==========================================================================*/
getReprocessType()2316 reprocess_type_t QCamera3RawChannel::getReprocessType()
2317 {
2318 return REPROCESS_TYPE_RAW;
2319 }
2320
2321
2322 /*************************************************************************************/
2323 // RAW Dump Channel related functions
2324
2325 /*===========================================================================
2326 * FUNCTION : QCamera3RawDumpChannel
2327 *
2328 * DESCRIPTION: Constructor for RawDumpChannel
2329 *
2330 * PARAMETERS :
2331 * @cam_handle : Handle for Camera
2332 * @cam_ops : Function pointer table
2333 * @rawDumpSize : Dimensions for the Raw stream
2334 * @paddinginfo : Padding information for stream
2335 * @userData : Cookie for parent
2336 * @pp mask : PP feature mask for this stream
2337 * @numBuffers : number of max dequeued buffers
2338 *
2339 * RETURN : NA
2340 *==========================================================================*/
QCamera3RawDumpChannel(uint32_t cam_handle,uint32_t channel_handle,mm_camera_ops_t * cam_ops,cam_dimension_t rawDumpSize,cam_padding_info_t * paddingInfo,void * userData,cam_feature_mask_t postprocess_mask,uint32_t numBuffers)2341 QCamera3RawDumpChannel::QCamera3RawDumpChannel(uint32_t cam_handle,
2342 uint32_t channel_handle,
2343 mm_camera_ops_t *cam_ops,
2344 cam_dimension_t rawDumpSize,
2345 cam_padding_info_t *paddingInfo,
2346 void *userData,
2347 cam_feature_mask_t postprocess_mask, uint32_t numBuffers) :
2348 QCamera3Channel(cam_handle, channel_handle, cam_ops, NULL,
2349 NULL, paddingInfo, postprocess_mask,
2350 userData, numBuffers),
2351 mDim(rawDumpSize),
2352 mMemory(NULL)
2353 {
2354 char prop[PROPERTY_VALUE_MAX];
2355 property_get("persist.camera.raw.dump", prop, "0");
2356 mRawDump = atoi(prop);
2357 }
2358
2359 /*===========================================================================
2360 * FUNCTION : QCamera3RawDumpChannel
2361 *
2362 * DESCRIPTION: Destructor for RawDumpChannel
2363 *
2364 * PARAMETERS :
2365 *
2366 * RETURN : NA
2367 *==========================================================================*/
2368
~QCamera3RawDumpChannel()2369 QCamera3RawDumpChannel::~QCamera3RawDumpChannel()
2370 {
2371 destroy();
2372 }
2373
2374 /*===========================================================================
2375 * FUNCTION : dumpRawSnapshot
2376 *
2377 * DESCRIPTION: Helper function to dump Raw frames
2378 *
2379 * PARAMETERS :
2380 * @frame : stream buf frame to be dumped
2381 *
2382 * RETURN : NA
2383 *==========================================================================*/
dumpRawSnapshot(mm_camera_buf_def_t * frame)2384 void QCamera3RawDumpChannel::dumpRawSnapshot(mm_camera_buf_def_t *frame)
2385 {
2386 QCamera3Stream *stream = getStreamByIndex(0);
2387 if (stream != NULL) {
2388 char buf[FILENAME_MAX];
2389 struct timeval tv;
2390 struct tm timeinfo_data;
2391 struct tm *timeinfo;
2392
2393 cam_dimension_t dim;
2394 memset(&dim, 0, sizeof(dim));
2395 stream->getFrameDimension(dim);
2396
2397 cam_frame_len_offset_t offset;
2398 memset(&offset, 0, sizeof(cam_frame_len_offset_t));
2399 stream->getFrameOffset(offset);
2400
2401 gettimeofday(&tv, NULL);
2402 timeinfo = localtime_r(&tv.tv_sec, &timeinfo_data);
2403
2404 if (NULL != timeinfo) {
2405 memset(buf, 0, sizeof(buf));
2406 /* Consistent naming for Jpeg+meta+raw: Raw name */
2407 snprintf(buf, sizeof(buf),
2408 QCAMERA_DUMP_FRM_LOCATION
2409 "IMG_%04d%02d%02d_%02d%02d%02d_%dx%d.raw",
2410 timeinfo->tm_year + 1900, timeinfo->tm_mon + 1,
2411 timeinfo->tm_mday, timeinfo->tm_hour,
2412 timeinfo->tm_min, timeinfo->tm_sec,
2413 dim.width, dim.height);
2414 /* Consistent naming for Jpeg+meta+raw: Raw name end*/
2415 int file_fd = open(buf, O_RDWR| O_CREAT, 0777);
2416 if (file_fd >= 0) {
2417 ssize_t written_len =
2418 write(file_fd, frame->buffer, offset.frame_len);
2419 LOGD("written number of bytes %zd", written_len);
2420 close(file_fd);
2421 } else {
2422 LOGE("failed to open file to dump image");
2423 }
2424 } else {
2425 LOGE("localtime_r() error");
2426 }
2427 } else {
2428 LOGE("Could not find stream");
2429 }
2430
2431 }
2432
2433 /*===========================================================================
2434 * FUNCTION : streamCbRoutine
2435 *
2436 * DESCRIPTION: Callback routine invoked for each frame generated for
2437 * Rawdump channel
2438 *
2439 * PARAMETERS :
2440 * @super_frame : stream buf frame generated
2441 * @stream : Underlying Stream object cookie
2442 *
2443 * RETURN : NA
2444 *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,__unused QCamera3Stream * stream)2445 void QCamera3RawDumpChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
2446 __unused QCamera3Stream *stream)
2447 {
2448 LOGD("E");
2449 if (super_frame == NULL || super_frame->num_bufs != 1) {
2450 LOGE("super_frame is not valid");
2451 return;
2452 }
2453
2454 if (mRawDump)
2455 dumpRawSnapshot(super_frame->bufs[0]);
2456
2457 bufDone(super_frame);
2458 free(super_frame);
2459 }
2460
2461 /*===========================================================================
2462 * FUNCTION : getStreamBufs
2463 *
2464 * DESCRIPTION: Callback function provided to interface to get buffers.
2465 *
2466 * PARAMETERS :
2467 * @len : Length of each buffer to be allocated
2468 *
2469 * RETURN : NULL on buffer allocation failure
2470 * QCamera3StreamMem object on sucess
2471 *==========================================================================*/
getStreamBufs(uint32_t len)2472 QCamera3StreamMem* QCamera3RawDumpChannel::getStreamBufs(uint32_t len)
2473 {
2474 int rc;
2475 mMemory = new QCamera3StreamMem(mNumBuffers);
2476
2477 if (!mMemory) {
2478 LOGE("unable to create heap memory");
2479 return NULL;
2480 }
2481 rc = mMemory->allocateAll((size_t)len);
2482 if (rc < 0) {
2483 LOGE("unable to allocate heap memory");
2484 delete mMemory;
2485 mMemory = NULL;
2486 return NULL;
2487 }
2488 return mMemory;
2489 }
2490
2491 /*===========================================================================
2492 * FUNCTION : putStreamBufs
2493 *
2494 * DESCRIPTION: Callback function provided to interface to return buffers.
2495 * Although no handles are actually returned, implicitl assumption
2496 * that interface will no longer use buffers and channel can
2497 * deallocated if necessary.
2498 *
2499 * PARAMETERS : NA
2500 *
2501 * RETURN : NA
2502 *==========================================================================*/
putStreamBufs()2503 void QCamera3RawDumpChannel::putStreamBufs()
2504 {
2505 mMemory->deallocate();
2506 delete mMemory;
2507 mMemory = NULL;
2508 }
2509
2510 /*===========================================================================
2511 * FUNCTION : request
2512 *
2513 * DESCRIPTION: Request function used as trigger
2514 *
2515 * PARAMETERS :
2516 * @recvd_frame : buffer- this will be NULL since this is internal channel
2517 * @frameNumber : Undefined again since this is internal stream
2518 *
2519 * RETURN : int32_t type of status
2520 * NO_ERROR -- success
2521 * none-zero failure code
2522 *==========================================================================*/
request(buffer_handle_t *,uint32_t,int &)2523 int32_t QCamera3RawDumpChannel::request(buffer_handle_t * /*buffer*/,
2524 uint32_t /*frameNumber*/,
2525 int & /*indexUsed*/)
2526 {
2527 if (!m_bIsActive) {
2528 return QCamera3Channel::start();
2529 }
2530 else
2531 return 0;
2532 }
2533
2534 /*===========================================================================
2535 * FUNCTION : intialize
2536 *
2537 * DESCRIPTION: Initializes channel params and creates underlying stream
2538 *
2539 * PARAMETERS :
2540 * @isType : type of image stabilization required on this stream
2541 *
2542 * RETURN : int32_t type of status
2543 * NO_ERROR -- success
2544 * none-zero failure code
2545 *==========================================================================*/
initialize(cam_is_type_t isType)2546 int32_t QCamera3RawDumpChannel::initialize(cam_is_type_t isType)
2547 {
2548 int32_t rc;
2549
2550 mIsType = isType;
2551 rc = QCamera3Channel::addStream(CAM_STREAM_TYPE_RAW,
2552 CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG, mDim, ROTATE_0, (uint8_t)mNumBuffers,
2553 mPostProcMask, mIsType);
2554 if (rc < 0) {
2555 LOGE("addStream failed");
2556 }
2557 return rc;
2558 }
2559 /*************************************************************************************/
2560
2561 /* QCamera3YUVChannel methods */
2562
2563 /*===========================================================================
2564 * FUNCTION : QCamera3YUVChannel
2565 *
2566 * DESCRIPTION: constructor of QCamera3YUVChannel
2567 *
2568 * PARAMETERS :
2569 * @cam_handle : camera handle
2570 * @cam_ops : ptr to camera ops table
2571 * @cb_routine : callback routine to frame aggregator
2572 * @paddingInfo : padding information for the stream
2573 * @stream : camera3_stream_t structure
2574 * @stream_type: Channel stream type
2575 * @postprocess_mask: the postprocess mask for streams of this channel
2576 * @metadataChannel: handle to the metadataChannel
2577 * RETURN : none
2578 *==========================================================================*/
QCamera3YUVChannel(uint32_t cam_handle,uint32_t channel_handle,mm_camera_ops_t * cam_ops,channel_cb_routine cb_routine,channel_cb_buffer_err cb_buf_err,cam_padding_info_t * paddingInfo,void * userData,camera3_stream_t * stream,cam_stream_type_t stream_type,cam_feature_mask_t postprocess_mask,QCamera3Channel * metadataChannel)2579 QCamera3YUVChannel::QCamera3YUVChannel(uint32_t cam_handle,
2580 uint32_t channel_handle,
2581 mm_camera_ops_t *cam_ops,
2582 channel_cb_routine cb_routine,
2583 channel_cb_buffer_err cb_buf_err,
2584 cam_padding_info_t *paddingInfo,
2585 void *userData,
2586 camera3_stream_t *stream,
2587 cam_stream_type_t stream_type,
2588 cam_feature_mask_t postprocess_mask,
2589 QCamera3Channel *metadataChannel) :
2590 QCamera3ProcessingChannel(cam_handle, channel_handle, cam_ops,
2591 cb_routine, cb_buf_err, paddingInfo, userData, stream, stream_type,
2592 postprocess_mask, metadataChannel)
2593 {
2594
2595 mBypass = (postprocess_mask == CAM_QCOM_FEATURE_NONE);
2596 mFrameLen = 0;
2597 mEdgeMode.edge_mode = CAM_EDGE_MODE_OFF;
2598 mEdgeMode.sharpness = 0;
2599 mNoiseRedMode = CAM_NOISE_REDUCTION_MODE_OFF;
2600 memset(&mCropRegion, 0, sizeof(mCropRegion));
2601 }
2602
2603 /*===========================================================================
2604 * FUNCTION : ~QCamera3YUVChannel
2605 *
2606 * DESCRIPTION: destructor of QCamera3YUVChannel
2607 *
2608 * PARAMETERS : none
2609 *
2610 *
2611 * RETURN : none
2612 *==========================================================================*/
~QCamera3YUVChannel()2613 QCamera3YUVChannel::~QCamera3YUVChannel()
2614 {
2615 // Deallocation of heap buffers allocated in mMemory is freed
2616 // automatically by its destructor
2617 }
2618
2619 /*===========================================================================
2620 * FUNCTION : initialize
2621 *
2622 * DESCRIPTION: Initialize and add camera channel & stream
2623 *
2624 * PARAMETERS :
2625 * @isType : the image stabilization type
2626 *
2627 * RETURN : int32_t type of status
2628 * NO_ERROR -- success
2629 * none-zero failure code
2630 *==========================================================================*/
initialize(cam_is_type_t isType)2631 int32_t QCamera3YUVChannel::initialize(cam_is_type_t isType)
2632 {
2633 ATRACE_CALL();
2634 int32_t rc = NO_ERROR;
2635 cam_dimension_t streamDim;
2636
2637 if (NULL == mCamera3Stream) {
2638 LOGE("Camera stream uninitialized");
2639 return NO_INIT;
2640 }
2641
2642 if (1 <= m_numStreams) {
2643 // Only one stream per channel supported in v3 Hal
2644 return NO_ERROR;
2645 }
2646
2647 mIsType = isType;
2648 mStreamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_CALLBACK,
2649 mCamera3Stream->width, mCamera3Stream->height);
2650 streamDim.width = mCamera3Stream->width;
2651 streamDim.height = mCamera3Stream->height;
2652
2653 rc = QCamera3Channel::addStream(mStreamType,
2654 mStreamFormat,
2655 streamDim,
2656 ROTATE_0,
2657 mNumBufs,
2658 mPostProcMask,
2659 mIsType);
2660 if (rc < 0) {
2661 LOGE("addStream failed");
2662 return rc;
2663 }
2664
2665 cam_stream_buf_plane_info_t buf_planes;
2666 cam_padding_info_t paddingInfo = mPaddingInfo;
2667
2668 memset(&buf_planes, 0, sizeof(buf_planes));
2669 //to ensure a big enough buffer size set the height and width
2670 //padding to max(height padding, width padding)
2671 paddingInfo.width_padding = MAX(paddingInfo.width_padding, paddingInfo.height_padding);
2672 paddingInfo.height_padding = paddingInfo.width_padding;
2673
2674 rc = mm_stream_calc_offset_snapshot(mStreamFormat, &streamDim, &paddingInfo,
2675 &buf_planes);
2676 if (rc < 0) {
2677 LOGE("mm_stream_calc_offset_preview failed");
2678 return rc;
2679 }
2680
2681 mFrameLen = buf_planes.plane_info.frame_len;
2682
2683 if (NO_ERROR != rc) {
2684 LOGE("Initialize failed, rc = %d", rc);
2685 return rc;
2686 }
2687
2688 /* initialize offline meta memory for input reprocess */
2689 rc = QCamera3ProcessingChannel::initialize(isType);
2690 if (NO_ERROR != rc) {
2691 LOGE("Processing Channel initialize failed, rc = %d",
2692 rc);
2693 }
2694
2695 return rc;
2696 }
2697
2698 /*===========================================================================
2699 * FUNCTION : request
2700 *
2701 * DESCRIPTION: entry function for a request on a YUV stream. This function
2702 * has the logic to service a request based on its type
2703 *
2704 * PARAMETERS :
2705 * @buffer : pointer to the output buffer
2706 * @frameNumber : frame number of the request
2707 * @pInputBuffer : pointer to input buffer if an input request
2708 * @metadata : parameters associated with the request
2709 *
2710 * RETURN : 0 on a success start of capture
2711 * -EINVAL on invalid input
2712 * -ENODEV on serious error
2713 *==========================================================================*/
request(buffer_handle_t * buffer,uint32_t frameNumber,camera3_stream_buffer_t * pInputBuffer,metadata_buffer_t * metadata,bool & needMetadata,int & indexUsed)2714 int32_t QCamera3YUVChannel::request(buffer_handle_t *buffer,
2715 uint32_t frameNumber,
2716 camera3_stream_buffer_t* pInputBuffer,
2717 metadata_buffer_t* metadata, bool &needMetadata,
2718 int &indexUsed)
2719 {
2720 int32_t rc = NO_ERROR;
2721 Mutex::Autolock lock(mOfflinePpLock);
2722
2723 LOGD("pInputBuffer is %p frame number %d", pInputBuffer, frameNumber);
2724 if (NULL == buffer || NULL == metadata) {
2725 LOGE("Invalid buffer/metadata in channel request");
2726 return BAD_VALUE;
2727 }
2728
2729 PpInfo ppInfo;
2730 memset(&ppInfo, 0, sizeof(ppInfo));
2731 ppInfo.frameNumber = frameNumber;
2732 ppInfo.offlinePpFlag = false;
2733 if (mBypass && !pInputBuffer ) {
2734 ppInfo.offlinePpFlag = needsFramePostprocessing(metadata);
2735 ppInfo.output = buffer;
2736 mOfflinePpInfoList.push_back(ppInfo);
2737 }
2738
2739 LOGD("offlinePpFlag is %d", ppInfo.offlinePpFlag);
2740 needMetadata = ppInfo.offlinePpFlag;
2741 if (!ppInfo.offlinePpFlag) {
2742 // regular request
2743 return QCamera3ProcessingChannel::request(buffer, frameNumber,
2744 pInputBuffer, metadata, indexUsed);
2745 } else {
2746 if(!m_bIsActive) {
2747 rc = start();
2748 if (NO_ERROR != rc)
2749 return rc;
2750 } else {
2751 LOGD("Request on an existing stream");
2752 }
2753
2754 //we need to send this frame through the CPP
2755 //Allocate heap memory, then buf done on the buffer
2756 uint32_t bufIdx;
2757 if (mFreeHeapBufferList.empty()) {
2758 rc = mMemory.allocateOne(mFrameLen);
2759 if (rc < 0) {
2760 LOGE("Failed allocating heap buffer. Fatal");
2761 return BAD_VALUE;
2762 } else {
2763 bufIdx = (uint32_t)rc;
2764 }
2765 } else {
2766 bufIdx = *(mFreeHeapBufferList.begin());
2767 mFreeHeapBufferList.erase(mFreeHeapBufferList.begin());
2768 }
2769
2770 /* Configure and start postproc if necessary */
2771 reprocess_config_t reproc_cfg;
2772 cam_dimension_t dim;
2773 memset(&reproc_cfg, 0, sizeof(reprocess_config_t));
2774 memset(&dim, 0, sizeof(dim));
2775 mStreams[0]->getFrameDimension(dim);
2776 setReprocConfig(reproc_cfg, NULL, metadata, mStreamFormat, dim);
2777
2778 // Start postprocessor without input buffer
2779 startPostProc(reproc_cfg);
2780
2781 LOGD("erasing %d", bufIdx);
2782
2783 mMemory.markFrameNumber(bufIdx, frameNumber);
2784 indexUsed = bufIdx;
2785 mStreams[0]->bufDone(bufIdx);
2786
2787 }
2788 return rc;
2789 }
2790
2791 /*===========================================================================
2792 * FUNCTION : streamCbRoutine
2793 *
2794 * DESCRIPTION:
2795 *
2796 * PARAMETERS :
2797 * @super_frame : the super frame with filled buffer
2798 * @stream : stream on which the buffer was requested and filled
2799 *
2800 * RETURN : none
2801 *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream)2802 void QCamera3YUVChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
2803 QCamera3Stream *stream)
2804 {
2805 ATRACE_CALL();
2806 uint8_t frameIndex;
2807 int32_t resultFrameNumber;
2808
2809 if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) {
2810 LOGE("Error with the stream callback");
2811 return;
2812 }
2813
2814 frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
2815 if(frameIndex >= mNumBufs) {
2816 LOGE("Error, Invalid index for buffer");
2817 stream->bufDone(frameIndex);
2818 return;
2819 }
2820
2821 if (mBypass) {
2822 List<PpInfo>::iterator ppInfo;
2823
2824 Mutex::Autolock lock(mOfflinePpLock);
2825 resultFrameNumber = mMemory.getFrameNumber(frameIndex);
2826 for (ppInfo = mOfflinePpInfoList.begin();
2827 ppInfo != mOfflinePpInfoList.end(); ppInfo++) {
2828 if (ppInfo->frameNumber == (uint32_t)resultFrameNumber) {
2829 break;
2830 }
2831 }
2832 LOGD("frame index %d, frame number %d", frameIndex, resultFrameNumber);
2833 //check the reprocessing required flag against the frame number
2834 if (ppInfo == mOfflinePpInfoList.end()) {
2835 LOGE("Error, request for frame number is a reprocess.");
2836 stream->bufDone(frameIndex);
2837 return;
2838 }
2839
2840 if (IS_BUFFER_ERROR(super_frame->bufs[0]->flags)) {
2841 mChannelCbBufErr(this, resultFrameNumber,
2842 CAMERA3_BUFFER_STATUS_ERROR, mUserData);
2843 }
2844
2845 if (ppInfo->offlinePpFlag) {
2846 mm_camera_super_buf_t *frame =
2847 (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
2848 if (frame == NULL) {
2849 LOGE("Error allocating memory to save received_frame structure.");
2850 if(stream) {
2851 stream->bufDone(frameIndex);
2852 }
2853 return;
2854 }
2855
2856 *frame = *super_frame;
2857 m_postprocessor.processData(frame, ppInfo->output, resultFrameNumber);
2858 free(super_frame);
2859 return;
2860 } else {
2861 if (ppInfo != mOfflinePpInfoList.begin()) {
2862 // There is pending reprocess buffer, cache current buffer
2863 if (ppInfo->callback_buffer != NULL) {
2864 LOGE("Fatal: cached callback_buffer is already present");
2865 }
2866 ppInfo->callback_buffer = super_frame;
2867 return;
2868 } else {
2869 mOfflinePpInfoList.erase(ppInfo);
2870 }
2871 }
2872 }
2873
2874 QCamera3ProcessingChannel::streamCbRoutine(super_frame, stream);
2875 return;
2876 }
2877
2878 /*===========================================================================
2879 * FUNCTION : reprocessCbRoutine
2880 *
2881 * DESCRIPTION: callback function for the reprocessed frame. This frame now
2882 * should be returned to the framework. This same callback is
2883 * used during input reprocessing or offline postprocessing
2884 *
2885 * PARAMETERS :
2886 * @resultBuffer : buffer containing the reprocessed data
2887 * @resultFrameNumber : frame number on which the buffer was requested
2888 *
2889 * RETURN : NONE
2890 *
2891 *==========================================================================*/
reprocessCbRoutine(buffer_handle_t * resultBuffer,uint32_t resultFrameNumber)2892 void QCamera3YUVChannel::reprocessCbRoutine(buffer_handle_t *resultBuffer,
2893 uint32_t resultFrameNumber)
2894 {
2895 LOGD("E: frame number %d", resultFrameNumber);
2896 Vector<mm_camera_super_buf_t *> pendingCbs;
2897
2898 /* release the input buffer and input metadata buffer if used */
2899 if (0 > mMemory.getHeapBufferIndex(resultFrameNumber)) {
2900 /* mOfflineMemory and mOfflineMetaMemory used only for input reprocessing */
2901 int32_t rc = releaseOfflineMemory(resultFrameNumber);
2902 if (NO_ERROR != rc) {
2903 LOGE("Error releasing offline memory rc = %d", rc);
2904 }
2905 /* Since reprocessing is done, send the callback to release the input buffer */
2906 if (mChannelCB) {
2907 mChannelCB(NULL, NULL, resultFrameNumber, true, mUserData);
2908 }
2909 }
2910
2911 if (mBypass) {
2912 int32_t rc = handleOfflinePpCallback(resultFrameNumber, pendingCbs);
2913 if (rc != NO_ERROR) {
2914 return;
2915 }
2916 }
2917
2918 issueChannelCb(resultBuffer, resultFrameNumber);
2919
2920 // Call all pending callbacks to return buffers
2921 for (size_t i = 0; i < pendingCbs.size(); i++) {
2922 QCamera3ProcessingChannel::streamCbRoutine(
2923 pendingCbs[i], mStreams[0]);
2924 }
2925
2926 }
2927
2928 /*===========================================================================
2929 * FUNCTION : needsFramePostprocessing
2930 *
2931 * DESCRIPTION:
2932 *
2933 * PARAMETERS :
2934 *
2935 * RETURN :
2936 * TRUE if frame needs to be postprocessed
2937 * FALSE is frame does not need to be postprocessed
2938 *
2939 *==========================================================================*/
needsFramePostprocessing(metadata_buffer_t * meta)2940 bool QCamera3YUVChannel::needsFramePostprocessing(metadata_buffer_t *meta)
2941 {
2942 bool ppNeeded = false;
2943
2944 //sharpness
2945 IF_META_AVAILABLE(cam_edge_application_t, edgeMode,
2946 CAM_INTF_META_EDGE_MODE, meta) {
2947 mEdgeMode = *edgeMode;
2948 }
2949
2950 //wnr
2951 IF_META_AVAILABLE(uint32_t, noiseRedMode,
2952 CAM_INTF_META_NOISE_REDUCTION_MODE, meta) {
2953 mNoiseRedMode = *noiseRedMode;
2954 }
2955
2956 //crop region
2957 IF_META_AVAILABLE(cam_crop_region_t, scalerCropRegion,
2958 CAM_INTF_META_SCALER_CROP_REGION, meta) {
2959 mCropRegion = *scalerCropRegion;
2960 }
2961
2962 if ((CAM_EDGE_MODE_OFF != mEdgeMode.edge_mode) &&
2963 (CAM_EDGE_MODE_ZERO_SHUTTER_LAG != mEdgeMode.edge_mode)) {
2964 ppNeeded = true;
2965 }
2966 if ((CAM_NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG != mNoiseRedMode) &&
2967 (CAM_NOISE_REDUCTION_MODE_OFF != mNoiseRedMode) &&
2968 (CAM_NOISE_REDUCTION_MODE_MINIMAL != mNoiseRedMode)) {
2969 ppNeeded = true;
2970 }
2971 if ((mCropRegion.width < (int32_t)mCamera3Stream->width) ||
2972 (mCropRegion.height < (int32_t)mCamera3Stream->height)) {
2973 ppNeeded = true;
2974 }
2975
2976 return ppNeeded;
2977 }
2978
2979 /*===========================================================================
2980 * FUNCTION : handleOfflinePpCallback
2981 *
2982 * DESCRIPTION: callback function for the reprocessed frame from offline
2983 * postprocessing.
2984 *
2985 * PARAMETERS :
2986 * @resultFrameNumber : frame number on which the buffer was requested
2987 * @pendingCbs : pending buffers to be returned first
2988 *
2989 * RETURN : int32_t type of status
2990 * NO_ERROR -- success
2991 * none-zero failure code
2992 *==========================================================================*/
handleOfflinePpCallback(uint32_t resultFrameNumber,Vector<mm_camera_super_buf_t * > & pendingCbs)2993 int32_t QCamera3YUVChannel::handleOfflinePpCallback(uint32_t resultFrameNumber,
2994 Vector<mm_camera_super_buf_t *>& pendingCbs)
2995 {
2996 Mutex::Autolock lock(mOfflinePpLock);
2997 List<PpInfo>::iterator ppInfo;
2998
2999 for (ppInfo = mOfflinePpInfoList.begin();
3000 ppInfo != mOfflinePpInfoList.end(); ppInfo++) {
3001 if (ppInfo->frameNumber == resultFrameNumber) {
3002 break;
3003 }
3004 }
3005
3006 if (ppInfo == mOfflinePpInfoList.end()) {
3007 LOGI("Request of frame number %d is reprocessing",
3008 resultFrameNumber);
3009 return NO_ERROR;
3010 } else if (ppInfo != mOfflinePpInfoList.begin()) {
3011 LOGE("callback for frame number %d should be head of list",
3012 resultFrameNumber);
3013 return BAD_VALUE;
3014 }
3015
3016 if (ppInfo->offlinePpFlag) {
3017 // Need to get the input buffer frame index from the
3018 // mMemory object and add that to the free heap buffers list.
3019 int32_t bufferIndex =
3020 mMemory.getHeapBufferIndex(resultFrameNumber);
3021 if (bufferIndex < 0) {
3022 LOGE("Fatal %d: no buffer index for frame number %d",
3023 bufferIndex, resultFrameNumber);
3024 return BAD_VALUE;
3025 }
3026 mMemory.markFrameNumber(bufferIndex, -1);
3027 mFreeHeapBufferList.push_back(bufferIndex);
3028 //Move heap buffer into free pool and invalidate the frame number
3029 ppInfo = mOfflinePpInfoList.erase(ppInfo);
3030
3031 // Return pending buffer callbacks
3032 while (ppInfo != mOfflinePpInfoList.end() &&
3033 !ppInfo->offlinePpFlag && ppInfo->callback_buffer) {
3034
3035 // Call stream callbacks for cached buffers
3036 pendingCbs.push_back(ppInfo->callback_buffer);
3037
3038 ppInfo = mOfflinePpInfoList.erase(ppInfo);
3039 }
3040
3041 } else {
3042 LOGE("Fatal: request of frame number %d doesn't need"
3043 " offline postprocessing. However there is"
3044 " reprocessing callback.",
3045 resultFrameNumber);
3046 return BAD_VALUE;
3047 }
3048
3049 return NO_ERROR;
3050 }
3051
3052 /*===========================================================================
3053 * FUNCTION : getReprocessType
3054 *
3055 * DESCRIPTION: get the type of reprocess output supported by this channel
3056 *
3057 * PARAMETERS : NONE
3058 *
3059 * RETURN : reprocess_type_t : type of reprocess
3060 *==========================================================================*/
getReprocessType()3061 reprocess_type_t QCamera3YUVChannel::getReprocessType()
3062 {
3063 return REPROCESS_TYPE_YUV;
3064 }
3065
3066 /* QCamera3PicChannel methods */
3067
3068 /*===========================================================================
3069 * FUNCTION : jpegEvtHandle
3070 *
3071 * DESCRIPTION: Function registerd to mm-jpeg-interface to handle jpeg events.
3072 Construct result payload and call mChannelCb to deliver buffer
3073 to framework.
3074 *
3075 * PARAMETERS :
3076 * @status : status of jpeg job
3077 * @client_hdl: jpeg client handle
3078 * @jobId : jpeg job Id
3079 * @p_ouput : ptr to jpeg output result struct
3080 * @userdata : user data ptr
3081 *
3082 * RETURN : none
3083 *==========================================================================*/
jpegEvtHandle(jpeg_job_status_t status,uint32_t,uint32_t jobId,mm_jpeg_output_t * p_output,void * userdata)3084 void QCamera3PicChannel::jpegEvtHandle(jpeg_job_status_t status,
3085 uint32_t /*client_hdl*/,
3086 uint32_t jobId,
3087 mm_jpeg_output_t *p_output,
3088 void *userdata)
3089 {
3090 ATRACE_CALL();
3091 buffer_handle_t *resultBuffer = NULL;
3092 buffer_handle_t *jpegBufferHandle = NULL;
3093 int resultStatus = CAMERA3_BUFFER_STATUS_OK;
3094 camera3_stream_buffer_t result;
3095 camera3_jpeg_blob_t jpegHeader;
3096
3097 KPI_ATRACE_INT("SNAPSHOT", 0);
3098 QCamera3PicChannel *obj = (QCamera3PicChannel *)userdata;
3099 if (obj) {
3100 //Construct payload for process_capture_result. Call mChannelCb
3101
3102 qcamera_hal3_jpeg_data_t *job = obj->m_postprocessor.findJpegJobByJobId(jobId);
3103
3104 if ((job == NULL) || (status == JPEG_JOB_STATUS_ERROR)) {
3105 LOGE("Error in jobId: (%d) with status: %d", jobId, status);
3106 resultStatus = CAMERA3_BUFFER_STATUS_ERROR;
3107 }
3108
3109 if (NULL != job) {
3110 uint32_t bufIdx = (uint32_t)job->jpeg_settings->out_buf_index;
3111 LOGD("jpeg out_buf_index: %d", bufIdx);
3112
3113 //Construct jpeg transient header of type camera3_jpeg_blob_t
3114 //Append at the end of jpeg image of buf_filled_len size
3115
3116 jpegHeader.jpeg_blob_id = CAMERA3_JPEG_BLOB_ID;
3117 if (JPEG_JOB_STATUS_DONE == status) {
3118 jpegHeader.jpeg_size = (uint32_t)p_output->buf_filled_len;
3119 char* jpeg_buf = (char *)p_output->buf_vaddr;
3120
3121 ssize_t maxJpegSize = -1;
3122
3123 // Gralloc buffer may have additional padding for 4K page size
3124 // Follow size guidelines based on spec since framework relies
3125 // on that to reach end of buffer and with it the header
3126
3127 //Handle same as resultBuffer, but for readablity
3128 jpegBufferHandle =
3129 (buffer_handle_t *)obj->mMemory.getBufferHandle(bufIdx);
3130
3131 if (NULL != jpegBufferHandle) {
3132 maxJpegSize = ((private_handle_t*)(*jpegBufferHandle))->width;
3133 if (maxJpegSize > obj->mMemory.getSize(bufIdx)) {
3134 maxJpegSize = obj->mMemory.getSize(bufIdx);
3135 }
3136
3137 size_t jpeg_eof_offset =
3138 (size_t)(maxJpegSize - (ssize_t)sizeof(jpegHeader));
3139 char *jpeg_eof = &jpeg_buf[jpeg_eof_offset];
3140 memcpy(jpeg_eof, &jpegHeader, sizeof(jpegHeader));
3141 obj->mMemory.cleanInvalidateCache(bufIdx);
3142 bool jpegDump = false;
3143 char prop[PROPERTY_VALUE_MAX];
3144 property_get("persist.camera.jpeg.dump", prop, "0");
3145 jpegDump = atoi(prop);
3146 if (jpegDump) {
3147 char buf[FILENAME_MAX];
3148 char timeBuf[FILENAME_MAX];
3149 memset(buf, 0, sizeof(buf));
3150 memset(timeBuf, 0, sizeof(timeBuf));
3151 time_t current_time;
3152 struct tm * timeinfo;
3153 time (¤t_time);
3154 timeinfo = localtime (¤t_time);
3155 if (timeinfo != NULL) {
3156 /* Consistent naming for Jpeg+meta+raw: meta name */
3157 strftime (timeBuf, sizeof(timeBuf),
3158 QCAMERA_DUMP_FRM_LOCATION"IMG_%Y%m%d_%H%M%S", timeinfo);
3159 /* Consistent naming for Jpeg+meta+raw: meta name end*/
3160 }
3161 String8 filePath(timeBuf);
3162 snprintf(buf, sizeof(buf), "_%d.jpg",
3163 obj->mMemory.getFrameNumber(bufIdx));
3164 filePath.append(buf);
3165 int file_fd = open(filePath.string(), O_RDWR | O_CREAT, 0777);
3166 ssize_t written_len = 0;
3167 if (file_fd >= 0) {
3168 fchmod(file_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
3169 written_len += write(file_fd, jpeg_buf,
3170 (size_t)maxJpegSize);
3171 LOGI("written number of bytes %ld attempted: %ld\n", written_len,
3172 maxJpegSize);
3173 close(file_fd);
3174 } else {
3175 LOGE("failed to open file to dump image");
3176 }
3177
3178 }
3179 } else {
3180 LOGE("JPEG buffer not found and index: %d",
3181 bufIdx);
3182 resultStatus = CAMERA3_BUFFER_STATUS_ERROR;
3183 }
3184 }
3185
3186 ////Use below data to issue framework callback
3187 resultBuffer =
3188 (buffer_handle_t *)obj->mMemory.getBufferHandle(bufIdx);
3189 int32_t resultFrameNumber = obj->mMemory.getFrameNumber(bufIdx);
3190 int32_t rc = obj->mMemory.unregisterBuffer(bufIdx);
3191 if (NO_ERROR != rc) {
3192 LOGE("Error %d unregistering stream buffer %d",
3193 rc, bufIdx);
3194 }
3195
3196 result.stream = obj->mCamera3Stream;
3197 result.buffer = resultBuffer;
3198 result.status = resultStatus;
3199 result.acquire_fence = -1;
3200 result.release_fence = -1;
3201
3202 // Release any snapshot buffers before calling
3203 // the user callback. The callback can potentially
3204 // unblock pending requests to snapshot stream.
3205 int32_t snapshotIdx = -1;
3206 mm_camera_super_buf_t* src_frame = NULL;
3207
3208 if (job->src_reproc_frame)
3209 src_frame = job->src_reproc_frame;
3210 else
3211 src_frame = job->src_frame;
3212
3213 if (src_frame) {
3214 if (obj->mStreams[0]->getMyHandle() ==
3215 src_frame->bufs[0]->stream_id) {
3216 snapshotIdx = (int32_t)src_frame->bufs[0]->buf_idx;
3217 if (0 <= snapshotIdx) {
3218 Mutex::Autolock lock(obj->mFreeBuffersLock);
3219 obj->mFreeBufferList.push_back((uint32_t)snapshotIdx);
3220 }
3221 }
3222 }
3223
3224 LOGI("Issue Jpeg Callback frameNumber = %d status = %d",
3225 resultFrameNumber, resultStatus);
3226 if (obj->mChannelCB) {
3227 obj->mChannelCB(NULL,
3228 &result,
3229 (uint32_t)resultFrameNumber,
3230 false,
3231 obj->mUserData);
3232 }
3233
3234 // release internal data for jpeg job
3235 if ((NULL != job->fwk_frame) || (NULL != job->fwk_src_buffer)) {
3236 /* unregister offline input buffer */
3237 int32_t inputBufIndex =
3238 obj->mOfflineMemory.getGrallocBufferIndex((uint32_t)resultFrameNumber);
3239 if (0 <= inputBufIndex) {
3240 rc = obj->mOfflineMemory.unregisterBuffer(inputBufIndex);
3241 } else {
3242 LOGE("could not find the input buf index, frame number %d",
3243 resultFrameNumber);
3244 }
3245 if (NO_ERROR != rc) {
3246 LOGE("Error %d unregistering input buffer %d",
3247 rc, bufIdx);
3248 }
3249
3250 /* unregister offline meta buffer */
3251 int32_t metaBufIndex =
3252 obj->mOfflineMetaMemory.getHeapBufferIndex((uint32_t)resultFrameNumber);
3253 if (0 <= metaBufIndex) {
3254 Mutex::Autolock lock(obj->mFreeOfflineMetaBuffersLock);
3255 obj->mFreeOfflineMetaBuffersList.push_back((uint32_t)metaBufIndex);
3256 } else {
3257 LOGE("could not find the input meta buf index, frame number %d",
3258 resultFrameNumber);
3259 }
3260 }
3261 obj->m_postprocessor.releaseOfflineBuffers(false);
3262 obj->m_postprocessor.releaseJpegJobData(job);
3263 free(job);
3264 }
3265
3266 obj->resetCppPerfParam();
3267 return;
3268 // }
3269 } else {
3270 LOGE("Null userdata in jpeg callback");
3271 }
3272 }
3273
QCamera3PicChannel(uint32_t cam_handle,uint32_t channel_handle,mm_camera_ops_t * cam_ops,channel_cb_routine cb_routine,channel_cb_buffer_err cb_buf_err,cam_padding_info_t * paddingInfo,void * userData,camera3_stream_t * stream,cam_feature_mask_t postprocess_mask,__unused bool is4KVideo,bool isInputStreamConfigured,QCamera3Channel * metadataChannel,uint32_t numBuffers)3274 QCamera3PicChannel::QCamera3PicChannel(uint32_t cam_handle,
3275 uint32_t channel_handle,
3276 mm_camera_ops_t *cam_ops,
3277 channel_cb_routine cb_routine,
3278 channel_cb_buffer_err cb_buf_err,
3279 cam_padding_info_t *paddingInfo,
3280 void *userData,
3281 camera3_stream_t *stream,
3282 cam_feature_mask_t postprocess_mask,
3283 __unused bool is4KVideo,
3284 bool isInputStreamConfigured,
3285 QCamera3Channel *metadataChannel,
3286 uint32_t numBuffers) :
3287 QCamera3ProcessingChannel(cam_handle, channel_handle,
3288 cam_ops, cb_routine, cb_buf_err, paddingInfo, userData,
3289 stream, CAM_STREAM_TYPE_SNAPSHOT,
3290 postprocess_mask, metadataChannel, numBuffers),
3291 mNumSnapshotBufs(0),
3292 mInputBufferHint(isInputStreamConfigured),
3293 mYuvMemory(NULL),
3294 mFrameLen(0)
3295 {
3296 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
3297 m_max_pic_dim = hal_obj->calcMaxJpegDim();
3298 mYuvWidth = stream->width;
3299 mYuvHeight = stream->height;
3300 mStreamType = CAM_STREAM_TYPE_SNAPSHOT;
3301 mPendingLiveSnapshotFrames = 0;
3302 // Use same pixelformat for 4K video case
3303 mStreamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_SNAPSHOT,
3304 stream->width, stream->height);
3305 int32_t rc = m_postprocessor.initJpeg(jpegEvtHandle, &m_max_pic_dim, this);
3306 if (rc != 0) {
3307 LOGE("Init Postprocessor failed");
3308 }
3309 }
3310
3311 /*===========================================================================
3312 * FUNCTION : flush
3313 *
3314 * DESCRIPTION: flush pic channel, which will stop all processing within, including
3315 * the reprocessing channel in postprocessor and YUV stream.
3316 *
3317 * PARAMETERS : none
3318 *
3319 * RETURN : int32_t type of status
3320 * NO_ERROR -- success
3321 * none-zero failure code
3322 *==========================================================================*/
flush()3323 int32_t QCamera3PicChannel::flush()
3324 {
3325 int32_t rc = NO_ERROR;
3326 if(!m_bIsActive) {
3327 LOGE("Attempt to flush inactive channel");
3328 return NO_INIT;
3329 }
3330
3331 rc = m_postprocessor.flush();
3332 if (rc == 0) {
3333 LOGE("Postprocessor flush failed, rc = %d", rc);
3334 return rc;
3335 }
3336
3337 if (0 < mOfflineMetaMemory.getCnt()) {
3338 mOfflineMetaMemory.deallocate();
3339 }
3340 if (0 < mOfflineMemory.getCnt()) {
3341 mOfflineMemory.unregisterBuffers();
3342 }
3343 Mutex::Autolock lock(mFreeBuffersLock);
3344 mFreeBufferList.clear();
3345 for (uint32_t i = 0; i < mCamera3Stream->max_buffers; i++) {
3346 mFreeBufferList.push_back(i);
3347 }
3348 return rc;
3349 }
3350
3351
~QCamera3PicChannel()3352 QCamera3PicChannel::~QCamera3PicChannel()
3353 {
3354 }
3355
initialize(cam_is_type_t isType)3356 int32_t QCamera3PicChannel::initialize(cam_is_type_t isType)
3357 {
3358 int32_t rc = NO_ERROR;
3359 cam_dimension_t streamDim;
3360 cam_stream_type_t streamType;
3361 cam_format_t streamFormat;
3362
3363 if (NULL == mCamera3Stream) {
3364 LOGE("Camera stream uninitialized");
3365 return NO_INIT;
3366 }
3367
3368 if (1 <= m_numStreams) {
3369 // Only one stream per channel supported in v3 Hal
3370 return NO_ERROR;
3371 }
3372
3373 mIsType = isType;
3374 streamType = mStreamType;
3375 streamFormat = mStreamFormat;
3376 streamDim.width = (int32_t)mYuvWidth;
3377 streamDim.height = (int32_t)mYuvHeight;
3378
3379 mNumSnapshotBufs = mCamera3Stream->max_buffers;
3380 rc = QCamera3Channel::addStream(streamType, streamFormat, streamDim,
3381 ROTATE_0, (uint8_t)mCamera3Stream->max_buffers, mPostProcMask,
3382 mIsType);
3383
3384 if (NO_ERROR != rc) {
3385 LOGE("Initialize failed, rc = %d", rc);
3386 return rc;
3387 }
3388
3389 /* initialize offline meta memory for input reprocess */
3390 rc = QCamera3ProcessingChannel::initialize(isType);
3391 if (NO_ERROR != rc) {
3392 LOGE("Processing Channel initialize failed, rc = %d",
3393 rc);
3394 }
3395
3396 return rc;
3397 }
3398
3399 /*===========================================================================
3400 * FUNCTION : request
3401 *
3402 * DESCRIPTION: handle the request - either with an input buffer or a direct
3403 * output request
3404 *
3405 * PARAMETERS :
3406 * @buffer : pointer to the output buffer
3407 * @frameNumber : frame number of the request
3408 * @pInputBuffer : pointer to input buffer if an input request
3409 * @metadata : parameters associated with the request
3410 *
3411 * RETURN : 0 on a success start of capture
3412 * -EINVAL on invalid input
3413 * -ENODEV on serious error
3414 *==========================================================================*/
request(buffer_handle_t * buffer,uint32_t frameNumber,camera3_stream_buffer_t * pInputBuffer,metadata_buffer_t * metadata,int & indexUsed)3415 int32_t QCamera3PicChannel::request(buffer_handle_t *buffer,
3416 uint32_t frameNumber,
3417 camera3_stream_buffer_t *pInputBuffer,
3418 metadata_buffer_t *metadata, int &indexUsed)
3419 {
3420 ATRACE_CALL();
3421 //FIX ME: Return buffer back in case of failures below.
3422
3423 int32_t rc = NO_ERROR;
3424
3425 reprocess_config_t reproc_cfg;
3426 cam_dimension_t dim;
3427 memset(&reproc_cfg, 0, sizeof(reprocess_config_t));
3428 //make sure to set the correct input stream dim in case of YUV size override
3429 //and recalculate the plane info
3430 dim.width = (int32_t)mYuvWidth;
3431 dim.height = (int32_t)mYuvHeight;
3432 setReprocConfig(reproc_cfg, pInputBuffer, metadata, mStreamFormat, dim);
3433
3434 // Picture stream has already been started before any request comes in
3435 if (!m_bIsActive) {
3436 LOGE("Channel not started!!");
3437 return NO_INIT;
3438 }
3439
3440 int index = mMemory.getMatchBufIndex((void*)buffer);
3441
3442 if(index < 0) {
3443 rc = registerBuffer(buffer, mIsType);
3444 if (NO_ERROR != rc) {
3445 LOGE("On-the-fly buffer registration failed %d",
3446 rc);
3447 return rc;
3448 }
3449
3450 index = mMemory.getMatchBufIndex((void*)buffer);
3451 if (index < 0) {
3452 LOGE("Could not find object among registered buffers");
3453 return DEAD_OBJECT;
3454 }
3455 }
3456 LOGD("buffer index %d, frameNumber: %u", index, frameNumber);
3457
3458 rc = mMemory.markFrameNumber((uint32_t)index, frameNumber);
3459
3460 // Start postprocessor
3461 startPostProc(reproc_cfg);
3462
3463 // Only set the perf mode for online cpp processing
3464 if (reproc_cfg.reprocess_type == REPROCESS_TYPE_NONE) {
3465 setCppPerfParam();
3466 }
3467
3468 // Queue jpeg settings
3469 rc = queueJpegSetting((uint32_t)index, metadata);
3470
3471 if (pInputBuffer == NULL) {
3472 Mutex::Autolock lock(mFreeBuffersLock);
3473 uint32_t bufIdx;
3474 if (mFreeBufferList.empty()) {
3475 rc = mYuvMemory->allocateOne(mFrameLen);
3476 if (rc < 0) {
3477 LOGE("Failed to allocate heap buffer. Fatal");
3478 return rc;
3479 } else {
3480 bufIdx = (uint32_t)rc;
3481 }
3482 } else {
3483 List<uint32_t>::iterator it = mFreeBufferList.begin();
3484 bufIdx = *it;
3485 mFreeBufferList.erase(it);
3486 }
3487 mYuvMemory->markFrameNumber(bufIdx, frameNumber);
3488 mStreams[0]->bufDone(bufIdx);
3489 indexUsed = bufIdx;
3490 } else {
3491 qcamera_fwk_input_pp_data_t *src_frame = NULL;
3492 src_frame = (qcamera_fwk_input_pp_data_t *)calloc(1,
3493 sizeof(qcamera_fwk_input_pp_data_t));
3494 if (src_frame == NULL) {
3495 LOGE("No memory for src frame");
3496 return NO_MEMORY;
3497 }
3498 rc = setFwkInputPPData(src_frame, pInputBuffer, &reproc_cfg, metadata,
3499 NULL /*fwk output buffer*/, frameNumber);
3500 if (NO_ERROR != rc) {
3501 LOGE("Error %d while setting framework input PP data", rc);
3502 free(src_frame);
3503 return rc;
3504 }
3505 LOGH("Post-process started");
3506 m_postprocessor.processData(src_frame);
3507 }
3508 return rc;
3509 }
3510
3511
3512
3513 /*===========================================================================
3514 * FUNCTION : dataNotifyCB
3515 *
3516 * DESCRIPTION: Channel Level callback used for super buffer data notify.
3517 * This function is registered with mm-camera-interface to handle
3518 * data notify
3519 *
3520 * PARAMETERS :
3521 * @recvd_frame : stream frame received
3522 * userdata : user data ptr
3523 *
3524 * RETURN : none
3525 *==========================================================================*/
dataNotifyCB(mm_camera_super_buf_t * recvd_frame,void * userdata)3526 void QCamera3PicChannel::dataNotifyCB(mm_camera_super_buf_t *recvd_frame,
3527 void *userdata)
3528 {
3529 ATRACE_CALL();
3530 LOGD("E\n");
3531 QCamera3PicChannel *channel = (QCamera3PicChannel *)userdata;
3532
3533 if (channel == NULL) {
3534 LOGE("invalid channel pointer");
3535 return;
3536 }
3537
3538 if(channel->m_numStreams != 1) {
3539 LOGE("Error: Bug: This callback assumes one stream per channel");
3540 return;
3541 }
3542
3543
3544 if(channel->mStreams[0] == NULL) {
3545 LOGE("Error: Invalid Stream object");
3546 return;
3547 }
3548
3549 channel->QCamera3PicChannel::streamCbRoutine(recvd_frame, channel->mStreams[0]);
3550
3551 LOGD("X\n");
3552 return;
3553 }
3554
3555 /*===========================================================================
3556 * FUNCTION : streamCbRoutine
3557 *
3558 * DESCRIPTION:
3559 *
3560 * PARAMETERS :
3561 * @super_frame : the super frame with filled buffer
3562 * @stream : stream on which the buffer was requested and filled
3563 *
3564 * RETURN : none
3565 *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream)3566 void QCamera3PicChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
3567 QCamera3Stream *stream)
3568 {
3569 ATRACE_CALL();
3570 //TODO
3571 //Used only for getting YUV. Jpeg callback will be sent back from channel
3572 //directly to HWI. Refer to func jpegEvtHandle
3573
3574 //Got the yuv callback. Calling yuv callback handler in PostProc
3575 uint8_t frameIndex;
3576 mm_camera_super_buf_t* frame = NULL;
3577 cam_dimension_t dim;
3578 cam_frame_len_offset_t offset;
3579
3580 memset(&dim, 0, sizeof(dim));
3581 memset(&offset, 0, sizeof(cam_frame_len_offset_t));
3582
3583 if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) {
3584 LOGE("Error with the stream callback");
3585 return;
3586 }
3587
3588 frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
3589 LOGD("recvd buf_idx: %u for further processing",
3590 (uint32_t)frameIndex);
3591 if(frameIndex >= mNumSnapshotBufs) {
3592 LOGE("Error, Invalid index for buffer");
3593 if(stream) {
3594 Mutex::Autolock lock(mFreeBuffersLock);
3595 mFreeBufferList.push_back(frameIndex);
3596 stream->bufDone(frameIndex);
3597 }
3598 return;
3599 }
3600
3601 frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
3602 if (frame == NULL) {
3603 LOGE("Error allocating memory to save received_frame structure.");
3604 if(stream) {
3605 Mutex::Autolock lock(mFreeBuffersLock);
3606 mFreeBufferList.push_back(frameIndex);
3607 stream->bufDone(frameIndex);
3608 }
3609 return;
3610 }
3611 *frame = *super_frame;
3612 stream->getFrameDimension(dim);
3613 stream->getFrameOffset(offset);
3614 dumpYUV(frame->bufs[0], dim, offset, QCAMERA_DUMP_FRM_INPUT_REPROCESS);
3615
3616 if (IS_BUFFER_ERROR(super_frame->bufs[0]->flags)) {
3617 mChannelCbBufErr(this, mYuvMemory->getFrameNumber(frameIndex),
3618 CAMERA3_BUFFER_STATUS_ERROR, mUserData);
3619 }
3620
3621 m_postprocessor.processData(frame);
3622 free(super_frame);
3623 return;
3624 }
3625
getStreamBufs(uint32_t len)3626 QCamera3StreamMem* QCamera3PicChannel::getStreamBufs(uint32_t len)
3627 {
3628 mYuvMemory = new QCamera3StreamMem(mCamera3Stream->max_buffers, false);
3629 if (!mYuvMemory) {
3630 LOGE("unable to create metadata memory");
3631 return NULL;
3632 }
3633 mFrameLen = len;
3634
3635 return mYuvMemory;
3636 }
3637
putStreamBufs()3638 void QCamera3PicChannel::putStreamBufs()
3639 {
3640 QCamera3ProcessingChannel::putStreamBufs();
3641
3642 mYuvMemory->deallocate();
3643 delete mYuvMemory;
3644 mYuvMemory = NULL;
3645 mFreeBufferList.clear();
3646 }
3647
queueJpegSetting(uint32_t index,metadata_buffer_t * metadata)3648 int32_t QCamera3PicChannel::queueJpegSetting(uint32_t index, metadata_buffer_t *metadata)
3649 {
3650 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
3651 jpeg_settings_t *settings =
3652 (jpeg_settings_t *)malloc(sizeof(jpeg_settings_t));
3653
3654 if (!settings) {
3655 LOGE("out of memory allocating jpeg_settings");
3656 return -ENOMEM;
3657 }
3658
3659 memset(settings, 0, sizeof(jpeg_settings_t));
3660
3661 settings->out_buf_index = index;
3662
3663 settings->jpeg_orientation = 0;
3664 IF_META_AVAILABLE(int32_t, orientation, CAM_INTF_META_JPEG_ORIENTATION, metadata) {
3665 settings->jpeg_orientation = *orientation;
3666 }
3667
3668 settings->jpeg_quality = 85;
3669 IF_META_AVAILABLE(uint32_t, quality1, CAM_INTF_META_JPEG_QUALITY, metadata) {
3670 settings->jpeg_quality = (uint8_t) *quality1;
3671 }
3672
3673 IF_META_AVAILABLE(uint32_t, quality2, CAM_INTF_META_JPEG_THUMB_QUALITY, metadata) {
3674 settings->jpeg_thumb_quality = (uint8_t) *quality2;
3675 }
3676
3677 IF_META_AVAILABLE(cam_dimension_t, dimension, CAM_INTF_META_JPEG_THUMB_SIZE, metadata) {
3678 settings->thumbnail_size = *dimension;
3679 }
3680
3681 settings->gps_timestamp_valid = 0;
3682 IF_META_AVAILABLE(int64_t, timestamp, CAM_INTF_META_JPEG_GPS_TIMESTAMP, metadata) {
3683 settings->gps_timestamp = *timestamp;
3684 settings->gps_timestamp_valid = 1;
3685 }
3686
3687 settings->gps_coordinates_valid = 0;
3688 IF_META_AVAILABLE(double, coordinates, CAM_INTF_META_JPEG_GPS_COORDINATES, metadata) {
3689 memcpy(settings->gps_coordinates, coordinates, 3*sizeof(double));
3690 settings->gps_coordinates_valid = 1;
3691 }
3692
3693 IF_META_AVAILABLE(uint8_t, proc_methods, CAM_INTF_META_JPEG_GPS_PROC_METHODS, metadata) {
3694 memset(settings->gps_processing_method, 0,
3695 sizeof(settings->gps_processing_method));
3696 strlcpy(settings->gps_processing_method, (const char *)proc_methods,
3697 sizeof(settings->gps_processing_method));
3698 }
3699
3700 // Image description
3701 const char *eepromVersion = hal_obj->getEepromVersionInfo();
3702 const uint32_t *ldafCalib = hal_obj->getLdafCalib();
3703 if ((eepromVersion && strlen(eepromVersion)) ||
3704 ldafCalib) {
3705 int len = 0;
3706 settings->image_desc_valid = true;
3707 if (eepromVersion && strlen(eepromVersion)) {
3708 len = snprintf(settings->image_desc, sizeof(settings->image_desc),
3709 "M:%s ", eepromVersion);
3710 }
3711 if (ldafCalib) {
3712 snprintf(settings->image_desc + len,
3713 sizeof(settings->image_desc) - len, "L:%u-%u",
3714 ldafCalib[0], ldafCalib[1]);
3715 }
3716 }
3717
3718 return m_postprocessor.processJpegSettingData(settings);
3719 }
3720
3721
overrideYuvSize(uint32_t width,uint32_t height)3722 void QCamera3PicChannel::overrideYuvSize(uint32_t width, uint32_t height)
3723 {
3724 mYuvWidth = width;
3725 mYuvHeight = height;
3726 }
3727
3728 /*===========================================================================
3729 * FUNCTION : getReprocessType
3730 *
3731 * DESCRIPTION: get the type of reprocess output supported by this channel
3732 *
3733 * PARAMETERS : NONE
3734 *
3735 * RETURN : reprocess_type_t : type of reprocess
3736 *==========================================================================*/
getReprocessType()3737 reprocess_type_t QCamera3PicChannel::getReprocessType()
3738 {
3739 /* a picture channel could either use the postprocessor for reprocess+jpeg
3740 or only for reprocess */
3741 reprocess_type_t expectedReprocess;
3742 if (mPostProcMask == CAM_QCOM_FEATURE_NONE || mInputBufferHint) {
3743 expectedReprocess = REPROCESS_TYPE_JPEG;
3744 } else {
3745 expectedReprocess = REPROCESS_TYPE_NONE;
3746 }
3747 LOGH("expectedReprocess from Pic Channel is %d", expectedReprocess);
3748 return expectedReprocess;
3749 }
3750
3751 /*===========================================================================
3752 * FUNCTION : setCppPerfParam
3753 *
3754 * DESCRIPTION: set the performance related stream params
3755 *
3756 * PARAMETERS : NONE
3757 *
3758 * RETURN : NONE
3759 *==========================================================================*/
3760
setCppPerfParam()3761 void QCamera3PicChannel::setCppPerfParam()
3762 {
3763 if (mPendingLiveSnapshotFrames == 0) {
3764 int32_t rc = 0;
3765 QCamera3Stream *pStream = mStreams[0];
3766 cam_stream_parm_buffer_t param;
3767 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t));
3768 param.type = CAM_STREAM_PARAM_TYPE_REQUEST_OPS_MODE;
3769 param.perf_mode = CAM_PERF_SET;
3770 rc = pStream->setParameter(param);
3771 if (rc != NO_ERROR) {
3772 LOGE("%s: setParameter for CAM_PERF_SET failed",
3773 __func__);
3774 }
3775 }
3776 mPendingLiveSnapshotFrames++;
3777 }
3778
3779 /*===========================================================================
3780 * FUNCTION : resetCppPerfParam
3781 *
3782 * DESCRIPTION: reset the performance related stream params
3783 *
3784 * PARAMETERS : NONE
3785 *
3786 * RETURN : NONE
3787 *==========================================================================*/
3788
resetCppPerfParam()3789 void QCamera3PicChannel::resetCppPerfParam()
3790 {
3791 if (mPendingLiveSnapshotFrames > 0) {
3792 int32_t rc = NO_ERROR;
3793 QCamera3Stream *pStream = mStreams[0];
3794 cam_stream_parm_buffer_t param;
3795 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t));
3796 param.type = CAM_STREAM_PARAM_TYPE_REQUEST_OPS_MODE;
3797 param.perf_mode = CAM_PERF_RESET;
3798 rc = pStream->setParameter(param);
3799 if (rc != NO_ERROR) {
3800 LOGE("%s: setParameter for CAM_PERF_RESET failed",
3801 __func__);
3802 }
3803 mPendingLiveSnapshotFrames--;
3804 }
3805 }
3806
3807 /*===========================================================================
3808 * FUNCTION : timeoutFrame
3809 *
3810 * DESCRIPTION: Method to indicate to channel that a given frame has take too
3811 * long to be generated
3812 *
3813 * PARAMETERS : framenumber indicating the framenumber of the buffer timingout
3814 *
3815 * RETURN : int32_t type of status
3816 * NO_ERROR -- success
3817 * none-zero failure code
3818 *==========================================================================*/
timeoutFrame(uint32_t frameNumber)3819 int32_t QCamera3PicChannel::timeoutFrame(uint32_t frameNumber)
3820 {
3821 int32_t bufIdx;
3822
3823 bufIdx = mYuvMemory->getBufferIndex(frameNumber);
3824
3825 if (bufIdx < 0) {
3826 ALOGE("%s: Buffer not found for frame:%d", __func__, frameNumber);
3827 return -1;
3828 }
3829
3830 mStreams[0]->timeoutFrame(bufIdx);
3831
3832 return NO_ERROR;
3833 }
3834
3835 /*===========================================================================
3836 * FUNCTION : QCamera3ReprocessChannel
3837 *
3838 * DESCRIPTION: constructor of QCamera3ReprocessChannel
3839 *
3840 * PARAMETERS :
3841 * @cam_handle : camera handle
3842 * @cam_ops : ptr to camera ops table
3843 * @pp_mask : post-proccess feature mask
3844 *
3845 * RETURN : none
3846 *==========================================================================*/
QCamera3ReprocessChannel(uint32_t cam_handle,uint32_t channel_handle,mm_camera_ops_t * cam_ops,channel_cb_routine cb_routine,channel_cb_buffer_err cb_buf_err,cam_padding_info_t * paddingInfo,cam_feature_mask_t postprocess_mask,void * userData,void * ch_hdl)3847 QCamera3ReprocessChannel::QCamera3ReprocessChannel(uint32_t cam_handle,
3848 uint32_t channel_handle,
3849 mm_camera_ops_t *cam_ops,
3850 channel_cb_routine cb_routine,
3851 channel_cb_buffer_err cb_buf_err,
3852 cam_padding_info_t *paddingInfo,
3853 cam_feature_mask_t postprocess_mask,
3854 void *userData, void *ch_hdl) :
3855 /* In case of framework reprocessing, pproc and jpeg operations could be
3856 * parallelized by allowing 1 extra buffer for reprocessing output:
3857 * ch_hdl->getNumBuffers() + 1 */
3858 QCamera3Channel(cam_handle, channel_handle, cam_ops, cb_routine, cb_buf_err, paddingInfo,
3859 postprocess_mask, userData,
3860 ((QCamera3ProcessingChannel *)ch_hdl)->getNumBuffers()
3861 + (MAX_REPROCESS_PIPELINE_STAGES - 1)),
3862 inputChHandle(ch_hdl),
3863 mOfflineBuffersIndex(-1),
3864 mFrameLen(0),
3865 mReprocessType(REPROCESS_TYPE_NONE),
3866 m_pSrcChannel(NULL),
3867 m_pMetaChannel(NULL),
3868 mMemory(NULL),
3869 mGrallocMemory(0),
3870 mReprocessPerfMode(false)
3871 {
3872 memset(mSrcStreamHandles, 0, sizeof(mSrcStreamHandles));
3873 mOfflineBuffersIndex = mNumBuffers -1;
3874 mOfflineMetaIndex = (int32_t) (2*mNumBuffers -1);
3875 }
3876
3877
3878 /*===========================================================================
3879 * FUNCTION : QCamera3ReprocessChannel
3880 *
3881 * DESCRIPTION: constructor of QCamera3ReprocessChannel
3882 *
3883 * PARAMETERS :
3884 * @cam_handle : camera handle
3885 * @cam_ops : ptr to camera ops table
3886 * @pp_mask : post-proccess feature mask
3887 *
3888 * RETURN : none
3889 *==========================================================================*/
initialize(cam_is_type_t isType)3890 int32_t QCamera3ReprocessChannel::initialize(cam_is_type_t isType)
3891 {
3892 int32_t rc = NO_ERROR;
3893 mm_camera_channel_attr_t attr;
3894
3895 memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
3896 attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS;
3897 attr.max_unmatched_frames = 1;
3898
3899 m_handle = m_camOps->add_channel(m_camHandle,
3900 &attr,
3901 NULL,
3902 this);
3903 if (m_handle == 0) {
3904 LOGE("Add channel failed");
3905 return UNKNOWN_ERROR;
3906 }
3907
3908 mIsType = isType;
3909 return rc;
3910 }
3911
3912 /*===========================================================================
3913 * FUNCTION : registerBuffer
3914 *
3915 * DESCRIPTION: register streaming buffer to the channel object
3916 *
3917 * PARAMETERS :
3918 * @buffer : buffer to be registered
3919 * @isType : the image stabilization type for the buffer
3920 *
3921 * RETURN : int32_t type of status
3922 * NO_ERROR -- success
3923 * none-zero failure code
3924 *==========================================================================*/
registerBuffer(buffer_handle_t * buffer,cam_is_type_t isType)3925 int32_t QCamera3ReprocessChannel::registerBuffer(buffer_handle_t *buffer,
3926 cam_is_type_t isType)
3927 {
3928 ATRACE_CALL();
3929 int rc = 0;
3930 mIsType = isType;
3931 cam_stream_type_t streamType;
3932
3933 if (buffer == NULL) {
3934 LOGE("Error: Cannot register a NULL buffer");
3935 return BAD_VALUE;
3936 }
3937
3938 if ((uint32_t)mGrallocMemory.getCnt() > (mNumBuffers - 1)) {
3939 LOGE("Trying to register more buffers than initially requested");
3940 return BAD_VALUE;
3941 }
3942
3943 if (0 == m_numStreams) {
3944 rc = initialize(mIsType);
3945 if (rc != NO_ERROR) {
3946 LOGE("Couldn't initialize camera stream %d",
3947 rc);
3948 return rc;
3949 }
3950 }
3951
3952 streamType = mStreams[0]->getMyType();
3953 rc = mGrallocMemory.registerBuffer(buffer, streamType);
3954 if (ALREADY_EXISTS == rc) {
3955 return NO_ERROR;
3956 } else if (NO_ERROR != rc) {
3957 LOGE("Buffer %p couldn't be registered %d", buffer, rc);
3958 return rc;
3959 }
3960
3961 return rc;
3962 }
3963
3964 /*===========================================================================
3965 * FUNCTION : QCamera3ReprocessChannel
3966 *
3967 * DESCRIPTION: constructor of QCamera3ReprocessChannel
3968 *
3969 * PARAMETERS :
3970 * @cam_handle : camera handle
3971 * @cam_ops : ptr to camera ops table
3972 * @pp_mask : post-proccess feature mask
3973 *
3974 * RETURN : none
3975 *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream)3976 void QCamera3ReprocessChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
3977 QCamera3Stream *stream)
3978 {
3979 //Got the pproc data callback. Now send to jpeg encoding
3980 uint8_t frameIndex;
3981 uint32_t resultFrameNumber;
3982 mm_camera_super_buf_t* frame = NULL;
3983 QCamera3ProcessingChannel *obj = (QCamera3ProcessingChannel *)inputChHandle;
3984 cam_dimension_t dim;
3985 cam_frame_len_offset_t offset;
3986
3987 memset(&dim, 0, sizeof(dim));
3988 memset(&offset, 0, sizeof(cam_frame_len_offset_t));
3989 if(!super_frame) {
3990 LOGE("Invalid Super buffer");
3991 return;
3992 }
3993
3994 if(super_frame->num_bufs != 1) {
3995 LOGE("Multiple streams are not supported");
3996 return;
3997 }
3998 if(super_frame->bufs[0] == NULL ) {
3999 LOGE("Error, Super buffer frame does not contain valid buffer");
4000 return;
4001 }
4002 frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
4003
4004
4005 if (mReprocessType == REPROCESS_TYPE_JPEG) {
4006 resultFrameNumber = mMemory->getFrameNumber(frameIndex);
4007 frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
4008 if (frame == NULL) {
4009 LOGE("Error allocating memory to save received_frame structure.");
4010 if(stream) {
4011 stream->bufDone(frameIndex);
4012 }
4013 return;
4014 }
4015 LOGI("bufIndex: %u recvd from post proc",
4016 (uint32_t)frameIndex);
4017 *frame = *super_frame;
4018
4019 stream->getFrameDimension(dim);
4020 stream->getFrameOffset(offset);
4021 dumpYUV(frame->bufs[0], dim, offset, QCAMERA_DUMP_FRM_SNAPSHOT);
4022 /* Since reprocessing is done, send the callback to release the input buffer */
4023 if (mChannelCB) {
4024 mChannelCB(NULL, NULL, resultFrameNumber, true, mUserData);
4025 }
4026 obj->m_postprocessor.processPPData(frame);
4027 } else {
4028 buffer_handle_t *resultBuffer;
4029 frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
4030 resultBuffer = (buffer_handle_t *)mGrallocMemory.getBufferHandle(frameIndex);
4031 resultFrameNumber = mGrallocMemory.getFrameNumber(frameIndex);
4032 int32_t rc = stream->bufRelease(frameIndex);
4033 if (NO_ERROR != rc) {
4034 LOGE("Error %d releasing stream buffer %d",
4035 rc, frameIndex);
4036 }
4037 rc = mGrallocMemory.unregisterBuffer(frameIndex);
4038 if (NO_ERROR != rc) {
4039 LOGE("Error %d unregistering stream buffer %d",
4040 rc, frameIndex);
4041 }
4042 obj->reprocessCbRoutine(resultBuffer, resultFrameNumber);
4043
4044 obj->m_postprocessor.releaseOfflineBuffers(false);
4045 qcamera_hal3_pp_data_t *pp_job = obj->m_postprocessor.dequeuePPJob(resultFrameNumber);
4046 if (pp_job != NULL) {
4047 obj->m_postprocessor.releasePPJobData(pp_job);
4048 }
4049 free(pp_job);
4050 }
4051 resetToCamPerfNormal(resultFrameNumber);
4052 free(super_frame);
4053 return;
4054 }
4055
4056 /*===========================================================================
4057 * FUNCTION : resetToCamPerfNormal
4058 *
4059 * DESCRIPTION: Set the perf mode to normal if all the priority frames
4060 * have been reprocessed
4061 *
4062 * PARAMETERS :
4063 * @frameNumber: Frame number of the reprocess completed frame
4064 *
4065 * RETURN : QCamera3StreamMem *
4066 *==========================================================================*/
resetToCamPerfNormal(uint32_t frameNumber)4067 int32_t QCamera3ReprocessChannel::resetToCamPerfNormal(uint32_t frameNumber)
4068 {
4069 int32_t rc = NO_ERROR;
4070 bool resetToPerfNormal = false;
4071 {
4072 Mutex::Autolock lock(mPriorityFramesLock);
4073 /* remove the priority frame number from the list */
4074 for (size_t i = 0; i < mPriorityFrames.size(); i++) {
4075 if (mPriorityFrames[i] == frameNumber) {
4076 mPriorityFrames.removeAt(i);
4077 }
4078 }
4079 /* reset the perf mode if pending priority frame list is empty */
4080 if (mReprocessPerfMode && mPriorityFrames.empty()) {
4081 resetToPerfNormal = true;
4082 }
4083 }
4084 if (resetToPerfNormal) {
4085 QCamera3Stream *pStream = mStreams[0];
4086 cam_stream_parm_buffer_t param;
4087 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t));
4088
4089 param.type = CAM_STREAM_PARAM_TYPE_REQUEST_OPS_MODE;
4090 param.perf_mode = CAM_PERF_NORMAL;
4091 rc = pStream->setParameter(param);
4092 {
4093 Mutex::Autolock lock(mPriorityFramesLock);
4094 mReprocessPerfMode = false;
4095 }
4096 }
4097 return rc;
4098 }
4099
4100 /*===========================================================================
4101 * FUNCTION : getStreamBufs
4102 *
4103 * DESCRIPTION: register the buffers of the reprocess channel
4104 *
4105 * PARAMETERS : none
4106 *
4107 * RETURN : QCamera3StreamMem *
4108 *==========================================================================*/
getStreamBufs(uint32_t len)4109 QCamera3StreamMem* QCamera3ReprocessChannel::getStreamBufs(uint32_t len)
4110 {
4111 if (mReprocessType == REPROCESS_TYPE_JPEG) {
4112 mMemory = new QCamera3StreamMem(mNumBuffers, false);
4113 if (!mMemory) {
4114 LOGE("unable to create reproc memory");
4115 return NULL;
4116 }
4117 mFrameLen = len;
4118 return mMemory;
4119 }
4120 return &mGrallocMemory;
4121 }
4122
4123 /*===========================================================================
4124 * FUNCTION : putStreamBufs
4125 *
4126 * DESCRIPTION: release the reprocess channel buffers
4127 *
4128 * PARAMETERS : none
4129 *
4130 * RETURN :
4131 *==========================================================================*/
putStreamBufs()4132 void QCamera3ReprocessChannel::putStreamBufs()
4133 {
4134 if (mReprocessType == REPROCESS_TYPE_JPEG) {
4135 mMemory->deallocate();
4136 delete mMemory;
4137 mMemory = NULL;
4138 mFreeBufferList.clear();
4139 } else {
4140 mGrallocMemory.unregisterBuffers();
4141 }
4142 }
4143
4144 /*===========================================================================
4145 * FUNCTION : ~QCamera3ReprocessChannel
4146 *
4147 * DESCRIPTION: destructor of QCamera3ReprocessChannel
4148 *
4149 * PARAMETERS : none
4150 *
4151 * RETURN : none
4152 *==========================================================================*/
~QCamera3ReprocessChannel()4153 QCamera3ReprocessChannel::~QCamera3ReprocessChannel()
4154 {
4155 destroy();
4156
4157 if (m_handle) {
4158 m_camOps->delete_channel(m_camHandle, m_handle);
4159 LOGD("deleting channel %d", m_handle);
4160 m_handle = 0;
4161 }
4162 }
4163
4164 /*===========================================================================
4165 * FUNCTION : start
4166 *
4167 * DESCRIPTION: start reprocess channel.
4168 *
4169 * PARAMETERS :
4170 *
4171 * RETURN : int32_t type of status
4172 * NO_ERROR -- success
4173 * none-zero failure code
4174 *==========================================================================*/
start()4175 int32_t QCamera3ReprocessChannel::start()
4176 {
4177 ATRACE_CALL();
4178 int32_t rc = NO_ERROR;
4179
4180 rc = QCamera3Channel::start();
4181
4182 if (rc == NO_ERROR) {
4183 rc = m_camOps->start_channel(m_camHandle, m_handle);
4184
4185 // Check failure
4186 if (rc != NO_ERROR) {
4187 LOGE("start_channel failed %d", rc);
4188 QCamera3Channel::stop();
4189 }
4190 }
4191 return rc;
4192 }
4193
4194 /*===========================================================================
4195 * FUNCTION : stop
4196 *
4197 * DESCRIPTION: stop reprocess channel.
4198 *
4199 * PARAMETERS : none
4200 *
4201 * RETURN : int32_t type of status
4202 * NO_ERROR -- success
4203 * none-zero failure code
4204 *==========================================================================*/
stop()4205 int32_t QCamera3ReprocessChannel::stop()
4206 {
4207 ATRACE_CALL();
4208 int32_t rc = NO_ERROR;
4209
4210 rc = QCamera3Channel::stop();
4211 unmapOfflineBuffers(true);
4212
4213 rc |= m_camOps->stop_channel(m_camHandle, m_handle);
4214
4215 return rc;
4216 }
4217
4218 /*===========================================================================
4219 * FUNCTION : getStreamBySrcHandle
4220 *
4221 * DESCRIPTION: find reprocess stream by its source stream handle
4222 *
4223 * PARAMETERS :
4224 * @srcHandle : source stream handle
4225 *
4226 * RETURN : ptr to reprocess stream if found. NULL if not found
4227 *==========================================================================*/
getStreamBySrcHandle(uint32_t srcHandle)4228 QCamera3Stream * QCamera3ReprocessChannel::getStreamBySrcHandle(uint32_t srcHandle)
4229 {
4230 QCamera3Stream *pStream = NULL;
4231
4232 for (uint32_t i = 0; i < m_numStreams; i++) {
4233 if (mSrcStreamHandles[i] == srcHandle) {
4234 pStream = mStreams[i];
4235 break;
4236 }
4237 }
4238 return pStream;
4239 }
4240
4241 /*===========================================================================
4242 * FUNCTION : getSrcStreamBySrcHandle
4243 *
4244 * DESCRIPTION: find source stream by source stream handle
4245 *
4246 * PARAMETERS :
4247 * @srcHandle : source stream handle
4248 *
4249 * RETURN : ptr to reprocess stream if found. NULL if not found
4250 *==========================================================================*/
getSrcStreamBySrcHandle(uint32_t srcHandle)4251 QCamera3Stream * QCamera3ReprocessChannel::getSrcStreamBySrcHandle(uint32_t srcHandle)
4252 {
4253 QCamera3Stream *pStream = NULL;
4254
4255 if (NULL == m_pSrcChannel) {
4256 return NULL;
4257 }
4258
4259 for (uint32_t i = 0; i < m_numStreams; i++) {
4260 if (mSrcStreamHandles[i] == srcHandle) {
4261 pStream = m_pSrcChannel->getStreamByIndex(i);
4262 break;
4263 }
4264 }
4265 return pStream;
4266 }
4267
4268 /*===========================================================================
4269 * FUNCTION : unmapOfflineBuffers
4270 *
4271 * DESCRIPTION: Unmaps offline buffers
4272 *
4273 * PARAMETERS : none
4274 *
4275 * RETURN : int32_t type of status
4276 * NO_ERROR -- success
4277 * none-zero failure code
4278 *==========================================================================*/
unmapOfflineBuffers(bool all)4279 int32_t QCamera3ReprocessChannel::unmapOfflineBuffers(bool all)
4280 {
4281 int rc = NO_ERROR;
4282 if (!mOfflineBuffers.empty()) {
4283 QCamera3Stream *stream = NULL;
4284 List<OfflineBuffer>::iterator it = mOfflineBuffers.begin();
4285 for (; it != mOfflineBuffers.end(); it++) {
4286 stream = (*it).stream;
4287 if (NULL != stream) {
4288 rc = stream->unmapBuf((*it).type,
4289 (*it).index,
4290 -1);
4291 if (NO_ERROR != rc) {
4292 LOGE("Error during offline buffer unmap %d",
4293 rc);
4294 }
4295 LOGD("Unmapped buffer with index %d", (*it).index);
4296 }
4297 if (!all) {
4298 mOfflineBuffers.erase(it);
4299 break;
4300 }
4301 }
4302 if (all) {
4303 mOfflineBuffers.clear();
4304 }
4305 }
4306
4307 if (!mOfflineMetaBuffers.empty()) {
4308 QCamera3Stream *stream = NULL;
4309 List<OfflineBuffer>::iterator it = mOfflineMetaBuffers.begin();
4310 for (; it != mOfflineMetaBuffers.end(); it++) {
4311 stream = (*it).stream;
4312 if (NULL != stream) {
4313 rc = stream->unmapBuf((*it).type,
4314 (*it).index,
4315 -1);
4316 if (NO_ERROR != rc) {
4317 LOGE("Error during offline buffer unmap %d",
4318 rc);
4319 }
4320 LOGD("Unmapped meta buffer with index %d", (*it).index);
4321 }
4322 if (!all) {
4323 mOfflineMetaBuffers.erase(it);
4324 break;
4325 }
4326 }
4327 if (all) {
4328 mOfflineMetaBuffers.clear();
4329 }
4330 }
4331 return rc;
4332 }
4333
4334 /*===========================================================================
4335 * FUNCTION : bufDone
4336 *
4337 * DESCRIPTION: Return reprocess stream buffer to free buffer list.
4338 * Note that this function doesn't queue buffer back to kernel.
4339 * It's up to doReprocessOffline to do that instead.
4340 * PARAMETERS :
4341 * @recvd_frame : stream buf frame to be returned
4342 *
4343 * RETURN : int32_t type of status
4344 * NO_ERROR -- success
4345 * none-zero failure code
4346 *==========================================================================*/
bufDone(mm_camera_super_buf_t * recvd_frame)4347 int32_t QCamera3ReprocessChannel::bufDone(mm_camera_super_buf_t *recvd_frame)
4348 {
4349 int rc = NO_ERROR;
4350 if (recvd_frame && recvd_frame->num_bufs == 1) {
4351 Mutex::Autolock lock(mFreeBuffersLock);
4352 uint32_t buf_idx = recvd_frame->bufs[0]->buf_idx;
4353 mFreeBufferList.push_back(buf_idx);
4354
4355 } else {
4356 LOGE("Fatal. Not supposed to be here");
4357 rc = BAD_VALUE;
4358 }
4359
4360 return rc;
4361 }
4362
4363 /*===========================================================================
4364 * FUNCTION : overrideMetadata
4365 *
4366 * DESCRIPTION: Override metadata entry such as rotation, crop, and CDS info.
4367 *
4368 * PARAMETERS :
4369 * @frame : input frame from source stream
4370 * meta_buffer: metadata buffer
4371 * @metadata : corresponding metadata
4372 * @fwk_frame :
4373 *
4374 * RETURN : int32_t type of status
4375 * NO_ERROR -- success
4376 * none-zero failure code
4377 *==========================================================================*/
overrideMetadata(qcamera_hal3_pp_buffer_t * pp_buffer,mm_camera_buf_def_t * meta_buffer,jpeg_settings_t * jpeg_settings,qcamera_fwk_input_pp_data_t & fwk_frame)4378 int32_t QCamera3ReprocessChannel::overrideMetadata(qcamera_hal3_pp_buffer_t *pp_buffer,
4379 mm_camera_buf_def_t *meta_buffer, jpeg_settings_t *jpeg_settings,
4380 qcamera_fwk_input_pp_data_t &fwk_frame)
4381 {
4382 int32_t rc = NO_ERROR;
4383 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
4384 if ((NULL == meta_buffer) || (NULL == pp_buffer) || (NULL == pp_buffer->input) ||
4385 (NULL == hal_obj)) {
4386 return BAD_VALUE;
4387 }
4388
4389 metadata_buffer_t *meta = (metadata_buffer_t *)meta_buffer->buffer;
4390 mm_camera_super_buf_t *frame = pp_buffer->input;
4391 if (NULL == meta) {
4392 return BAD_VALUE;
4393 }
4394
4395 for (uint32_t i = 0; i < frame->num_bufs; i++) {
4396 QCamera3Stream *pStream = getStreamBySrcHandle(frame->bufs[i]->stream_id);
4397 QCamera3Stream *pSrcStream = getSrcStreamBySrcHandle(frame->bufs[i]->stream_id);
4398
4399 if (pStream != NULL && pSrcStream != NULL) {
4400 if (jpeg_settings) {
4401 // Find rotation info for reprocess stream
4402 cam_rotation_info_t rotation_info;
4403 memset(&rotation_info, 0, sizeof(rotation_info));
4404 if (jpeg_settings->jpeg_orientation == 0) {
4405 rotation_info.rotation = ROTATE_0;
4406 } else if (jpeg_settings->jpeg_orientation == 90) {
4407 rotation_info.rotation = ROTATE_90;
4408 } else if (jpeg_settings->jpeg_orientation == 180) {
4409 rotation_info.rotation = ROTATE_180;
4410 } else if (jpeg_settings->jpeg_orientation == 270) {
4411 rotation_info.rotation = ROTATE_270;
4412 }
4413 rotation_info.device_rotation = ROTATE_0;
4414 rotation_info.streamId = mStreams[0]->getMyServerID();
4415 ADD_SET_PARAM_ENTRY_TO_BATCH(meta, CAM_INTF_PARM_ROTATION, rotation_info);
4416 }
4417
4418 // Find and insert crop info for reprocess stream
4419 IF_META_AVAILABLE(cam_crop_data_t, crop_data, CAM_INTF_META_CROP_DATA, meta) {
4420 if (MAX_NUM_STREAMS > crop_data->num_of_streams) {
4421 for (int j = 0; j < crop_data->num_of_streams; j++) {
4422 if (crop_data->crop_info[j].stream_id ==
4423 pSrcStream->getMyServerID()) {
4424
4425 // Store crop/roi information for offline reprocess
4426 // in the reprocess stream slot
4427 crop_data->crop_info[crop_data->num_of_streams].crop =
4428 crop_data->crop_info[j].crop;
4429 crop_data->crop_info[crop_data->num_of_streams].roi_map =
4430 crop_data->crop_info[j].roi_map;
4431 crop_data->crop_info[crop_data->num_of_streams].stream_id =
4432 mStreams[0]->getMyServerID();
4433 crop_data->num_of_streams++;
4434
4435 LOGD("Reprocess stream server id: %d",
4436 mStreams[0]->getMyServerID());
4437 LOGD("Found offline reprocess crop %dx%d %dx%d",
4438 crop_data->crop_info[j].crop.left,
4439 crop_data->crop_info[j].crop.top,
4440 crop_data->crop_info[j].crop.width,
4441 crop_data->crop_info[j].crop.height);
4442 LOGD("Found offline reprocess roimap %dx%d %dx%d",
4443 crop_data->crop_info[j].roi_map.left,
4444 crop_data->crop_info[j].roi_map.top,
4445 crop_data->crop_info[j].roi_map.width,
4446 crop_data->crop_info[j].roi_map.height);
4447
4448 break;
4449 }
4450 }
4451 } else {
4452 LOGE("No space to add reprocess stream crop/roi information");
4453 }
4454 }
4455
4456 IF_META_AVAILABLE(cam_cds_data_t, cdsInfo, CAM_INTF_META_CDS_DATA, meta) {
4457 uint8_t cnt = cdsInfo->num_of_streams;
4458 if (cnt <= MAX_NUM_STREAMS) {
4459 cam_stream_cds_info_t repro_cds_info;
4460 memset(&repro_cds_info, 0, sizeof(repro_cds_info));
4461 repro_cds_info.stream_id = mStreams[0]->getMyServerID();
4462 for (size_t i = 0; i < cnt; i++) {
4463 if (cdsInfo->cds_info[i].stream_id ==
4464 pSrcStream->getMyServerID()) {
4465 repro_cds_info.cds_enable =
4466 cdsInfo->cds_info[i].cds_enable;
4467 break;
4468 }
4469 }
4470 cdsInfo->num_of_streams = 1;
4471 cdsInfo->cds_info[0] = repro_cds_info;
4472 } else {
4473 LOGE("No space to add reprocess stream cds information");
4474 }
4475 }
4476
4477 fwk_frame.input_buffer = *frame->bufs[i];
4478 fwk_frame.metadata_buffer = *meta_buffer;
4479 fwk_frame.output_buffer = pp_buffer->output;
4480 break;
4481 } else {
4482 LOGE("Source/Re-process streams are invalid");
4483 rc |= BAD_VALUE;
4484 }
4485 }
4486
4487 return rc;
4488 }
4489
4490 /*===========================================================================
4491 * FUNCTION : overrideFwkMetadata
4492 *
4493 * DESCRIPTION: Override frameworks metadata such as crop, and CDS data.
4494 *
4495 * PARAMETERS :
4496 * @frame : input frame for reprocessing
4497 *
4498 * RETURN : int32_t type of status
4499 * NO_ERROR -- success
4500 * none-zero failure code
4501 *==========================================================================*/
overrideFwkMetadata(qcamera_fwk_input_pp_data_t * frame)4502 int32_t QCamera3ReprocessChannel::overrideFwkMetadata(
4503 qcamera_fwk_input_pp_data_t *frame)
4504 {
4505 if (NULL == frame) {
4506 LOGE("Incorrect input frame");
4507 return BAD_VALUE;
4508 }
4509
4510 if (NULL == frame->metadata_buffer.buffer) {
4511 LOGE("No metadata available");
4512 return BAD_VALUE;
4513 }
4514
4515 // Find and insert crop info for reprocess stream
4516 metadata_buffer_t *meta = (metadata_buffer_t *) frame->metadata_buffer.buffer;
4517 IF_META_AVAILABLE(cam_crop_data_t, crop_data, CAM_INTF_META_CROP_DATA, meta) {
4518 if (1 == crop_data->num_of_streams) {
4519 // Store crop/roi information for offline reprocess
4520 // in the reprocess stream slot
4521 crop_data->crop_info[crop_data->num_of_streams].crop =
4522 crop_data->crop_info[0].crop;
4523 crop_data->crop_info[crop_data->num_of_streams].roi_map =
4524 crop_data->crop_info[0].roi_map;
4525 crop_data->crop_info[crop_data->num_of_streams].stream_id =
4526 mStreams[0]->getMyServerID();
4527 crop_data->num_of_streams++;
4528
4529 LOGD("Reprocess stream server id: %d",
4530 mStreams[0]->getMyServerID());
4531 LOGD("Found offline reprocess crop %dx%d %dx%d",
4532 crop_data->crop_info[0].crop.left,
4533 crop_data->crop_info[0].crop.top,
4534 crop_data->crop_info[0].crop.width,
4535 crop_data->crop_info[0].crop.height);
4536 LOGD("Found offline reprocess roi map %dx%d %dx%d",
4537 crop_data->crop_info[0].roi_map.left,
4538 crop_data->crop_info[0].roi_map.top,
4539 crop_data->crop_info[0].roi_map.width,
4540 crop_data->crop_info[0].roi_map.height);
4541 } else {
4542 LOGE("Incorrect number of offline crop data entries %d",
4543 crop_data->num_of_streams);
4544 return BAD_VALUE;
4545 }
4546 } else {
4547 LOGW("Crop data not present");
4548 }
4549
4550 IF_META_AVAILABLE(cam_cds_data_t, cdsInfo, CAM_INTF_META_CDS_DATA, meta) {
4551 if (1 == cdsInfo->num_of_streams) {
4552 cdsInfo->cds_info[0].stream_id = mStreams[0]->getMyServerID();
4553 } else {
4554 LOGE("Incorrect number of offline cds info entries %d",
4555 cdsInfo->num_of_streams);
4556 return BAD_VALUE;
4557 }
4558 }
4559
4560 return NO_ERROR;
4561 }
4562
4563 /*===========================================================================
4564 * FUNCTION : doReprocessOffline
4565 *
4566 * DESCRIPTION: request to do a reprocess on the frame
4567 *
4568 * PARAMETERS :
4569 * @frame : input frame for reprocessing
4570 * @isPriorityFrame: Hint that this frame is of priority, equivalent to
4571 * real time, even though it is processed in offline mechanism
4572 *
4573 * RETURN : int32_t type of status
4574 * NO_ERROR -- success
4575 * none-zero failure code
4576 *==========================================================================*/
doReprocessOffline(qcamera_fwk_input_pp_data_t * frame,bool isPriorityFrame)4577 int32_t QCamera3ReprocessChannel::doReprocessOffline(
4578 qcamera_fwk_input_pp_data_t *frame, bool isPriorityFrame)
4579 {
4580 int32_t rc = 0;
4581 int index;
4582 OfflineBuffer mappedBuffer;
4583
4584 if (m_numStreams < 1) {
4585 LOGE("No reprocess stream is created");
4586 return -1;
4587 }
4588
4589 if (NULL == frame) {
4590 LOGE("Incorrect input frame");
4591 return BAD_VALUE;
4592 }
4593
4594 if (NULL == frame->metadata_buffer.buffer) {
4595 LOGE("No metadata available");
4596 return BAD_VALUE;
4597 }
4598
4599 if (NULL == frame->input_buffer.buffer) {
4600 LOGE("No input buffer available");
4601 return BAD_VALUE;
4602 }
4603
4604 if ((0 == m_numStreams) || (NULL == mStreams[0])) {
4605 LOGE("Reprocess stream not initialized!");
4606 return NO_INIT;
4607 }
4608
4609 QCamera3Stream *pStream = mStreams[0];
4610
4611 //qbuf the output buffer if it was allocated by the framework
4612 if (mReprocessType != REPROCESS_TYPE_JPEG && frame->output_buffer != NULL) {
4613 if(!m_bIsActive) {
4614 rc = registerBuffer(frame->output_buffer, mIsType);
4615 if (NO_ERROR != rc) {
4616 LOGE("On-the-fly buffer registration failed %d",
4617 rc);
4618 return rc;
4619 }
4620
4621 rc = start();
4622 if (NO_ERROR != rc) {
4623 return rc;
4624 }
4625 }
4626 index = mGrallocMemory.getMatchBufIndex((void*)frame->output_buffer);
4627 if(index < 0) {
4628 rc = registerBuffer(frame->output_buffer, mIsType);
4629 if (NO_ERROR != rc) {
4630 LOGE("On-the-fly buffer registration failed %d",
4631 rc);
4632 return rc;
4633 }
4634
4635 index = mGrallocMemory.getMatchBufIndex((void*)frame->output_buffer);
4636 if (index < 0) {
4637 LOGE("Could not find object among registered buffers");
4638 return DEAD_OBJECT;
4639 }
4640 }
4641 rc = mGrallocMemory.markFrameNumber(index, frame->frameNumber);
4642 if(rc != NO_ERROR) {
4643 LOGE("Failed to mark frame#:%d, index:%d",frame->frameNumber,index);
4644 return rc;
4645 }
4646 rc = pStream->bufDone(index);
4647 if(rc != NO_ERROR) {
4648 LOGE("Failed to Q new buffer to stream");
4649 mGrallocMemory.markFrameNumber(index, -1);
4650 return rc;
4651 }
4652
4653 } else if (mReprocessType == REPROCESS_TYPE_JPEG) {
4654 Mutex::Autolock lock(mFreeBuffersLock);
4655 uint32_t bufIdx;
4656 if (mFreeBufferList.empty()) {
4657 rc = mMemory->allocateOne(mFrameLen);
4658 if (rc < 0) {
4659 LOGE("Failed allocating heap buffer. Fatal");
4660 return BAD_VALUE;
4661 } else {
4662 bufIdx = (uint32_t)rc;
4663 }
4664 } else {
4665 bufIdx = *(mFreeBufferList.begin());
4666 mFreeBufferList.erase(mFreeBufferList.begin());
4667 }
4668
4669 mMemory->markFrameNumber(bufIdx, frame->frameNumber);
4670 rc = pStream->bufDone(bufIdx);
4671 if (rc != NO_ERROR) {
4672 LOGE("Failed to queue new buffer to stream");
4673 return rc;
4674 }
4675 }
4676
4677 int32_t max_idx = (int32_t) (mNumBuffers - 1);
4678 //loop back the indices if max burst count reached
4679 if (mOfflineBuffersIndex == max_idx) {
4680 mOfflineBuffersIndex = -1;
4681 }
4682 uint32_t buf_idx = (uint32_t)(mOfflineBuffersIndex + 1);
4683 rc = pStream->mapBuf(
4684 CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
4685 buf_idx, -1,
4686 frame->input_buffer.fd, frame->input_buffer.buffer,
4687 frame->input_buffer.frame_len);
4688 if (NO_ERROR == rc) {
4689 mappedBuffer.index = buf_idx;
4690 mappedBuffer.stream = pStream;
4691 mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF;
4692 mOfflineBuffers.push_back(mappedBuffer);
4693 mOfflineBuffersIndex = (int32_t)buf_idx;
4694 LOGD("Mapped buffer with index %d", mOfflineBuffersIndex);
4695 }
4696
4697 max_idx = (int32_t) ((mNumBuffers * 2) - 1);
4698 //loop back the indices if max burst count reached
4699 if (mOfflineMetaIndex == max_idx) {
4700 mOfflineMetaIndex = (int32_t) (mNumBuffers - 1);
4701 }
4702 uint32_t meta_buf_idx = (uint32_t)(mOfflineMetaIndex + 1);
4703 rc |= pStream->mapBuf(
4704 CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF,
4705 meta_buf_idx, -1,
4706 frame->metadata_buffer.fd, frame->metadata_buffer.buffer,
4707 frame->metadata_buffer.frame_len);
4708 if (NO_ERROR == rc) {
4709 mappedBuffer.index = meta_buf_idx;
4710 mappedBuffer.stream = pStream;
4711 mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF;
4712 mOfflineMetaBuffers.push_back(mappedBuffer);
4713 mOfflineMetaIndex = (int32_t)meta_buf_idx;
4714 LOGD("Mapped meta buffer with index %d", mOfflineMetaIndex);
4715 }
4716
4717 if (rc == NO_ERROR) {
4718 cam_stream_parm_buffer_t param;
4719 uint32_t numPendingPriorityFrames = 0;
4720
4721 if(isPriorityFrame) {
4722 Mutex::Autolock lock(mPriorityFramesLock);
4723 /* read the length before pushing the frame number to check if
4724 * vector is empty */
4725 numPendingPriorityFrames = mPriorityFrames.size();
4726 mPriorityFrames.push(frame->frameNumber);
4727 }
4728
4729 if(isPriorityFrame && !numPendingPriorityFrames) {
4730 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t));
4731 param.type = CAM_STREAM_PARAM_TYPE_REQUEST_OPS_MODE;
4732 param.perf_mode = CAM_PERF_HIGH_PERFORMANCE;
4733 rc = pStream->setParameter(param);
4734
4735 if (rc != NO_ERROR) {
4736 ALOGE("%s: setParameter for CAM_PERF_HIGH_PERFORMANCE failed",
4737 __func__);
4738 }
4739 {
4740 Mutex::Autolock lock(mPriorityFramesLock);
4741 mReprocessPerfMode = true;
4742 }
4743 }
4744
4745 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t));
4746 param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
4747 param.reprocess.buf_index = buf_idx;
4748 param.reprocess.frame_idx = frame->input_buffer.frame_idx;
4749 param.reprocess.meta_present = 1;
4750 param.reprocess.meta_buf_index = meta_buf_idx;
4751
4752 LOGI("Offline reprocessing id = %d buf Id = %d meta index = %d",
4753 param.reprocess.frame_idx, param.reprocess.buf_index,
4754 param.reprocess.meta_buf_index);
4755 rc = pStream->setParameter(param);
4756 if (rc != NO_ERROR) {
4757 LOGE("stream setParameter for reprocess failed");
4758 resetToCamPerfNormal(frame->frameNumber);
4759 }
4760 } else {
4761 LOGE("Input buffer memory map failed: %d", rc);
4762 }
4763
4764 return rc;
4765 }
4766
4767 /*===========================================================================
4768 * FUNCTION : doReprocess
4769 *
4770 * DESCRIPTION: request to do a reprocess on the frame
4771 *
4772 * PARAMETERS :
4773 * @buf_fd : fd to the input buffer that needs reprocess
4774 * @buffer : Buffer ptr
4775 * @buf_lenght : length of the input buffer
4776 * @ret_val : result of reprocess.
4777 * Example: Could be faceID in case of register face image.
4778 * @meta_frame : metadata frame.
4779 *
4780 * RETURN : int32_t type of status
4781 * NO_ERROR -- success
4782 * none-zero failure code
4783 *==========================================================================*/
doReprocess(int buf_fd,void * buffer,size_t buf_length,int32_t & ret_val,mm_camera_super_buf_t * meta_frame)4784 int32_t QCamera3ReprocessChannel::doReprocess(int buf_fd, void *buffer, size_t buf_length,
4785 int32_t &ret_val, mm_camera_super_buf_t *meta_frame)
4786 {
4787 int32_t rc = 0;
4788 if (m_numStreams < 1) {
4789 LOGE("No reprocess stream is created");
4790 return -1;
4791 }
4792 if (meta_frame == NULL) {
4793 LOGE("Did not get corresponding metadata in time");
4794 return -1;
4795 }
4796
4797 uint8_t buf_idx = 0;
4798 for (uint32_t i = 0; i < m_numStreams; i++) {
4799 rc = mStreams[i]->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
4800 buf_idx, -1,
4801 buf_fd, buffer, buf_length);
4802
4803 if (rc == NO_ERROR) {
4804 cam_stream_parm_buffer_t param;
4805 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t));
4806 param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
4807 param.reprocess.buf_index = buf_idx;
4808 param.reprocess.meta_present = 1;
4809 param.reprocess.meta_stream_handle = m_pMetaChannel->mStreams[0]->getMyServerID();
4810 param.reprocess.meta_buf_index = meta_frame->bufs[0]->buf_idx;
4811
4812 LOGI("Online reprocessing id = %d buf Id = %d meta index = %d",
4813 param.reprocess.frame_idx, param.reprocess.buf_index,
4814 param.reprocess.meta_buf_index);
4815 rc = mStreams[i]->setParameter(param);
4816 if (rc == NO_ERROR) {
4817 ret_val = param.reprocess.ret_val;
4818 }
4819 mStreams[i]->unmapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
4820 buf_idx, -1);
4821 }
4822 }
4823 return rc;
4824 }
4825
4826 /*===========================================================================
4827 * FUNCTION : addReprocStreamsFromSource
4828 *
4829 * DESCRIPTION: add reprocess streams from input source channel
4830 *
4831 * PARAMETERS :
4832 * @config : pp feature configuration
4833 * @src_config : source reprocess configuration
4834 * @isType : type of image stabilization required on this stream
4835 * @pMetaChannel : ptr to metadata channel to get corresp. metadata
4836 *
4837 *
4838 * RETURN : int32_t type of status
4839 * NO_ERROR -- success
4840 * none-zero failure code
4841 *==========================================================================*/
addReprocStreamsFromSource(cam_pp_feature_config_t & pp_config,const reprocess_config_t & src_config,cam_is_type_t is_type,QCamera3Channel * pMetaChannel)4842 int32_t QCamera3ReprocessChannel::addReprocStreamsFromSource(cam_pp_feature_config_t &pp_config,
4843 const reprocess_config_t &src_config , cam_is_type_t is_type,
4844 QCamera3Channel *pMetaChannel)
4845 {
4846 int32_t rc = 0;
4847 cam_stream_reproc_config_t reprocess_config;
4848 cam_stream_type_t streamType;
4849
4850 cam_dimension_t streamDim = src_config.output_stream_dim;
4851
4852 if (NULL != src_config.src_channel) {
4853 QCamera3Stream *pSrcStream = src_config.src_channel->getStreamByIndex(0);
4854 if (pSrcStream == NULL) {
4855 LOGE("source channel doesn't have a stream");
4856 return BAD_VALUE;
4857 }
4858 mSrcStreamHandles[m_numStreams] = pSrcStream->getMyHandle();
4859 }
4860
4861 streamType = CAM_STREAM_TYPE_OFFLINE_PROC;
4862 reprocess_config.pp_type = CAM_OFFLINE_REPROCESS_TYPE;
4863
4864 reprocess_config.offline.input_fmt = src_config.stream_format;
4865 reprocess_config.offline.input_dim = src_config.input_stream_dim;
4866 reprocess_config.offline.input_buf_planes.plane_info =
4867 src_config.input_stream_plane_info.plane_info;
4868 reprocess_config.offline.num_of_bufs = (uint8_t)mNumBuffers;
4869 reprocess_config.offline.input_type = src_config.stream_type;
4870
4871 reprocess_config.pp_feature_config = pp_config;
4872 QCamera3Stream *pStream = new QCamera3Stream(m_camHandle,
4873 m_handle,
4874 m_camOps,
4875 &mPaddingInfo,
4876 (QCamera3Channel*)this);
4877 if (pStream == NULL) {
4878 LOGE("No mem for Stream");
4879 return NO_MEMORY;
4880 }
4881
4882 rc = pStream->init(streamType, src_config.stream_format,
4883 streamDim, ROTATE_0, &reprocess_config,
4884 (uint8_t)mNumBuffers,
4885 reprocess_config.pp_feature_config.feature_mask,
4886 is_type,
4887 0,/* batchSize */
4888 QCamera3Channel::streamCbRoutine, this);
4889
4890 if (rc == 0) {
4891 mStreams[m_numStreams] = pStream;
4892 m_numStreams++;
4893 } else {
4894 LOGE("failed to create reprocess stream");
4895 delete pStream;
4896 }
4897
4898 if (rc == NO_ERROR) {
4899 m_pSrcChannel = src_config.src_channel;
4900 m_pMetaChannel = pMetaChannel;
4901 mReprocessType = src_config.reprocess_type;
4902 LOGD("mReprocessType is %d", mReprocessType);
4903 }
4904 mm_camera_req_buf_t buf;
4905 memset(&buf, 0x0, sizeof(buf));
4906 buf.type = MM_CAMERA_REQ_SUPER_BUF;
4907 buf.num_buf_requested = 1;
4908 if(m_camOps->request_super_buf(m_camHandle,m_handle, &buf) < 0) {
4909 LOGE("Request for super buffer failed");
4910 }
4911 return rc;
4912 }
4913
4914 /* QCamera3SupportChannel methods */
4915
4916 cam_dimension_t QCamera3SupportChannel::kDim = {640, 480};
4917
QCamera3SupportChannel(uint32_t cam_handle,uint32_t channel_handle,mm_camera_ops_t * cam_ops,cam_padding_info_t * paddingInfo,cam_feature_mask_t postprocess_mask,cam_stream_type_t streamType,cam_dimension_t * dim,cam_format_t streamFormat,uint8_t hw_analysis_supported,void * userData,uint32_t numBuffers)4918 QCamera3SupportChannel::QCamera3SupportChannel(uint32_t cam_handle,
4919 uint32_t channel_handle,
4920 mm_camera_ops_t *cam_ops,
4921 cam_padding_info_t *paddingInfo,
4922 cam_feature_mask_t postprocess_mask,
4923 cam_stream_type_t streamType,
4924 cam_dimension_t *dim,
4925 cam_format_t streamFormat,
4926 uint8_t hw_analysis_supported,
4927 void *userData, uint32_t numBuffers) :
4928 QCamera3Channel(cam_handle, channel_handle, cam_ops,
4929 NULL, NULL, paddingInfo, postprocess_mask,
4930 userData, numBuffers),
4931 mMemory(NULL)
4932 {
4933 memcpy(&mDim, dim, sizeof(cam_dimension_t));
4934 mStreamType = streamType;
4935 mStreamFormat = streamFormat;
4936 // Make Analysis same as Preview format
4937 if (!hw_analysis_supported && mStreamType == CAM_STREAM_TYPE_ANALYSIS) {
4938 mStreamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_PREVIEW,
4939 dim->width, dim->height);
4940 }
4941 }
4942
~QCamera3SupportChannel()4943 QCamera3SupportChannel::~QCamera3SupportChannel()
4944 {
4945 destroy();
4946
4947 if (mMemory) {
4948 mMemory->deallocate();
4949 delete mMemory;
4950 mMemory = NULL;
4951 }
4952 }
4953
initialize(cam_is_type_t isType)4954 int32_t QCamera3SupportChannel::initialize(cam_is_type_t isType)
4955 {
4956 int32_t rc;
4957
4958 if (mMemory || m_numStreams > 0) {
4959 LOGE("metadata channel already initialized");
4960 return -EINVAL;
4961 }
4962
4963 mIsType = isType;
4964 rc = QCamera3Channel::addStream(mStreamType,
4965 mStreamFormat, mDim, ROTATE_0, MIN_STREAMING_BUFFER_NUM,
4966 mPostProcMask, mIsType);
4967 if (rc < 0) {
4968 LOGE("addStream failed");
4969 }
4970 return rc;
4971 }
4972
request(buffer_handle_t *,uint32_t,int &)4973 int32_t QCamera3SupportChannel::request(buffer_handle_t * /*buffer*/,
4974 uint32_t /*frameNumber*/,
4975 int & /*indexUsed*/)
4976 {
4977 return NO_ERROR;
4978 }
4979
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream *)4980 void QCamera3SupportChannel::streamCbRoutine(
4981 mm_camera_super_buf_t *super_frame,
4982 QCamera3Stream * /*stream*/)
4983 {
4984 if (super_frame == NULL || super_frame->num_bufs != 1) {
4985 LOGE("super_frame is not valid");
4986 return;
4987 }
4988 bufDone(super_frame);
4989 free(super_frame);
4990 }
4991
getStreamBufs(uint32_t len)4992 QCamera3StreamMem* QCamera3SupportChannel::getStreamBufs(uint32_t len)
4993 {
4994 int rc;
4995 mMemory = new QCamera3StreamMem(mNumBuffers);
4996 if (!mMemory) {
4997 LOGE("unable to create heap memory");
4998 return NULL;
4999 }
5000 rc = mMemory->allocateAll(len);
5001 if (rc < 0) {
5002 LOGE("unable to allocate heap memory");
5003 delete mMemory;
5004 mMemory = NULL;
5005 return NULL;
5006 }
5007 return mMemory;
5008 }
5009
putStreamBufs()5010 void QCamera3SupportChannel::putStreamBufs()
5011 {
5012 mMemory->deallocate();
5013 delete mMemory;
5014 mMemory = NULL;
5015 }
5016
5017 }; // namespace qcamera
5018