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