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 mYUVDump = property_get_int32("persist.camera.dumpimg", 0);
101 }
102
103 /*===========================================================================
104 * FUNCTION : ~QCamera3Channel
105 *
106 * DESCRIPTION: destructor of QCamera3Channel
107 *
108 * PARAMETERS : none
109 *
110 * RETURN : none
111 *==========================================================================*/
~QCamera3Channel()112 QCamera3Channel::~QCamera3Channel()
113 {
114 }
115
116 /*===========================================================================
117 * FUNCTION : destroy
118 *
119 * DESCRIPTION: internal destructor of QCamera3Channel called by the subclasses
120 * this destructor will call pure virtual functions. stop will eventuall call
121 * QCamera3Stream::putBufs. The putBufs function will
122 * call QCamera3Channel::putStreamBufs which is pure virtual
123 *
124 * PARAMETERS : none
125 *
126 * RETURN : none
127 *==========================================================================*/
destroy()128 void QCamera3Channel::destroy()
129 {
130 if (m_bIsActive)
131 stop();
132
133 for (uint32_t i = 0; i < m_numStreams; i++) {
134 if (mStreams[i] != NULL) {
135 delete mStreams[i];
136 mStreams[i] = 0;
137 }
138 }
139 m_numStreams = 0;
140 }
141
142 /*===========================================================================
143 * FUNCTION : addStream
144 *
145 * DESCRIPTION: add a stream into channel
146 *
147 * PARAMETERS :
148 * @streamType : stream type
149 * @streamFormat : stream format
150 * @streamDim : stream dimension
151 * @streamRotation : rotation of the stream
152 * @minStreamBufNum : minimal buffer count for particular stream type
153 * @postprocessMask : post-proccess feature mask
154 * @isType : type of image stabilization required on the stream
155 *
156 * RETURN : int32_t type of status
157 * NO_ERROR -- success
158 * none-zero failure code
159 *==========================================================================*/
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)160 int32_t QCamera3Channel::addStream(cam_stream_type_t streamType,
161 cam_format_t streamFormat,
162 cam_dimension_t streamDim,
163 cam_rotation_t streamRotation,
164 uint8_t minStreamBufNum,
165 cam_feature_mask_t postprocessMask,
166 cam_is_type_t isType,
167 uint32_t batchSize)
168 {
169 int32_t rc = NO_ERROR;
170
171 if (m_numStreams >= 1) {
172 LOGE("Only one stream per channel supported in v3 Hal");
173 return BAD_VALUE;
174 }
175
176 if (m_numStreams >= MAX_STREAM_NUM_IN_BUNDLE) {
177 LOGE("stream number (%d) exceeds max limit (%d)",
178 m_numStreams, MAX_STREAM_NUM_IN_BUNDLE);
179 return BAD_VALUE;
180 }
181 QCamera3Stream *pStream = new QCamera3Stream(m_camHandle,
182 m_handle,
183 m_camOps,
184 &mPaddingInfo,
185 this);
186 if (pStream == NULL) {
187 LOGE("No mem for Stream");
188 return NO_MEMORY;
189 }
190 LOGD("batch size is %d", batchSize);
191
192 rc = pStream->init(streamType, streamFormat, streamDim, streamRotation,
193 NULL, minStreamBufNum, postprocessMask, isType, batchSize,
194 streamCbRoutine, this);
195 if (rc == 0) {
196 mStreams[m_numStreams] = pStream;
197 m_numStreams++;
198 } else {
199 delete pStream;
200 }
201 return rc;
202 }
203
204 /*===========================================================================
205 * FUNCTION : start
206 *
207 * DESCRIPTION: start channel, which will start all streams belong to this channel
208 *
209 * PARAMETERS :
210 *
211 * RETURN : int32_t type of status
212 * NO_ERROR -- success
213 * none-zero failure code
214 *==========================================================================*/
start()215 int32_t QCamera3Channel::start()
216 {
217 ATRACE_CALL();
218 int32_t rc = NO_ERROR;
219
220 if (m_numStreams > 1) {
221 LOGW("bundle not supported");
222 } else if (m_numStreams == 0) {
223 return NO_INIT;
224 }
225
226 if(m_bIsActive) {
227 LOGW("Attempt to start active channel");
228 return rc;
229 }
230
231 for (uint32_t i = 0; i < m_numStreams; i++) {
232 if (mStreams[i] != NULL) {
233 mStreams[i]->start();
234 }
235 }
236
237 m_bIsActive = true;
238
239 return rc;
240 }
241
242 /*===========================================================================
243 * FUNCTION : stop
244 *
245 * DESCRIPTION: stop a channel, which will stop all streams belong to this channel
246 *
247 * PARAMETERS : none
248 *
249 * RETURN : int32_t type of status
250 * NO_ERROR -- success
251 * none-zero failure code
252 *==========================================================================*/
stop()253 int32_t QCamera3Channel::stop()
254 {
255 ATRACE_CALL();
256 int32_t rc = NO_ERROR;
257 if(!m_bIsActive) {
258 LOGE("Attempt to stop inactive channel");
259 return rc;
260 }
261
262 for (uint32_t i = 0; i < m_numStreams; i++) {
263 if (mStreams[i] != NULL) {
264 mStreams[i]->stop();
265 }
266 }
267
268 m_bIsActive = false;
269 return rc;
270 }
271
272 /*===========================================================================
273 * FUNCTION : setBatchSize
274 *
275 * DESCRIPTION: Set batch size for the channel. This is a dummy implementation
276 * for the base class
277 *
278 * PARAMETERS :
279 * @batchSize : Number of image buffers in a batch
280 *
281 * RETURN : int32_t type of status
282 * NO_ERROR -- success always
283 * none-zero failure code
284 *==========================================================================*/
setBatchSize(uint32_t batchSize)285 int32_t QCamera3Channel::setBatchSize(uint32_t batchSize)
286 {
287 LOGD("Dummy method. batchSize: %d unused ", batchSize);
288 return NO_ERROR;
289 }
290
291 /*===========================================================================
292 * FUNCTION : queueBatchBuf
293 *
294 * DESCRIPTION: This is a dummy implementation for the base class
295 *
296 * PARAMETERS :
297 *
298 * RETURN : int32_t type of status
299 * NO_ERROR -- success always
300 * none-zero failure code
301 *==========================================================================*/
queueBatchBuf()302 int32_t QCamera3Channel::queueBatchBuf()
303 {
304 LOGD("Dummy method. Unused ");
305 return NO_ERROR;
306 }
307
308 /*===========================================================================
309 * FUNCTION : setPerFrameMapUnmap
310 *
311 * DESCRIPTION: Sets internal enable flag
312 *
313 * PARAMETERS :
314 * @enable : Bool value for the enable flag
315 *
316 * RETURN : int32_t type of status
317 * NO_ERROR -- success always
318 * none-zero failure code
319 *==========================================================================*/
setPerFrameMapUnmap(bool enable)320 int32_t QCamera3Channel::setPerFrameMapUnmap(bool enable)
321 {
322 mPerFrameMapUnmapEnable = enable;
323 return NO_ERROR;
324 }
325
326 /*===========================================================================
327 * FUNCTION : flush
328 *
329 * DESCRIPTION: flush a channel
330 *
331 * PARAMETERS : none
332 *
333 * RETURN : int32_t type of status
334 * NO_ERROR -- success
335 * none-zero failure code
336 *==========================================================================*/
flush()337 int32_t QCamera3Channel::flush()
338 {
339 ATRACE_CALL();
340 return NO_ERROR;
341 }
342
343 /*===========================================================================
344 * FUNCTION : bufDone
345 *
346 * DESCRIPTION: return a stream buf back to kernel
347 *
348 * PARAMETERS :
349 * @recvd_frame : stream buf frame to be returned
350 *
351 * RETURN : int32_t type of status
352 * NO_ERROR -- success
353 * none-zero failure code
354 *==========================================================================*/
bufDone(mm_camera_super_buf_t * recvd_frame)355 int32_t QCamera3Channel::bufDone(mm_camera_super_buf_t *recvd_frame)
356 {
357 int32_t rc = NO_ERROR;
358 for (uint32_t i = 0; i < recvd_frame->num_bufs; i++) {
359 if (recvd_frame->bufs[i] != NULL) {
360 for (uint32_t j = 0; j < m_numStreams; j++) {
361 if (mStreams[j] != NULL &&
362 mStreams[j]->getMyHandle() == recvd_frame->bufs[i]->stream_id) {
363 rc = mStreams[j]->bufDone(recvd_frame->bufs[i]->buf_idx);
364 break; // break loop j
365 }
366 }
367 }
368 }
369
370 return rc;
371 }
372
setBundleInfo(const cam_bundle_config_t & bundleInfo)373 int32_t QCamera3Channel::setBundleInfo(const cam_bundle_config_t &bundleInfo)
374 {
375 int32_t rc = NO_ERROR;
376 cam_stream_parm_buffer_t param;
377 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t));
378 param.type = CAM_STREAM_PARAM_TYPE_SET_BUNDLE_INFO;
379 param.bundleInfo = bundleInfo;
380 rc = mStreams[0]->setParameter(param);
381 if (rc != NO_ERROR) {
382 LOGE("stream setParameter for set bundle failed");
383 }
384
385 return rc;
386 }
387
388 /*===========================================================================
389 * FUNCTION : getStreamTypeMask
390 *
391 * DESCRIPTION: Get bit mask of all stream types in this channel
392 *
393 * PARAMETERS : None
394 *
395 * RETURN : Bit mask of all stream types in this channel
396 *==========================================================================*/
getStreamTypeMask()397 uint32_t QCamera3Channel::getStreamTypeMask()
398 {
399 uint32_t mask = 0;
400 for (uint32_t i = 0; i < m_numStreams; i++) {
401 mask |= (1U << mStreams[i]->getMyType());
402 }
403 return mask;
404 }
405
406 /*===========================================================================
407 * FUNCTION : getStreamID
408 *
409 * DESCRIPTION: Get StreamID of requested stream type
410 *
411 * PARAMETERS : streamMask
412 *
413 * RETURN : Stream ID
414 *==========================================================================*/
getStreamID(uint32_t streamMask)415 uint32_t QCamera3Channel::getStreamID(uint32_t streamMask)
416 {
417 uint32_t streamID = 0;
418 for (uint32_t i = 0; i < m_numStreams; i++) {
419 if (streamMask == (uint32_t )(0x1 << mStreams[i]->getMyType())) {
420 streamID = mStreams[i]->getMyServerID();
421 break;
422 }
423 }
424 return streamID;
425 }
426
427 /*===========================================================================
428 * FUNCTION : getStreamByHandle
429 *
430 * DESCRIPTION: return stream object by stream handle
431 *
432 * PARAMETERS :
433 * @streamHandle : stream handle
434 *
435 * RETURN : stream object. NULL if not found
436 *==========================================================================*/
getStreamByHandle(uint32_t streamHandle)437 QCamera3Stream *QCamera3Channel::getStreamByHandle(uint32_t streamHandle)
438 {
439 for (uint32_t i = 0; i < m_numStreams; i++) {
440 if (mStreams[i] != NULL && mStreams[i]->getMyHandle() == streamHandle) {
441 return mStreams[i];
442 }
443 }
444 return NULL;
445 }
446
447 /*===========================================================================
448 * FUNCTION : getStreamByIndex
449 *
450 * DESCRIPTION: return stream object by index
451 *
452 * PARAMETERS :
453 * @streamHandle : stream handle
454 *
455 * RETURN : stream object. NULL if not found
456 *==========================================================================*/
getStreamByIndex(uint32_t index)457 QCamera3Stream *QCamera3Channel::getStreamByIndex(uint32_t index)
458 {
459 if (index < m_numStreams) {
460 return mStreams[index];
461 }
462 return NULL;
463 }
464
465 /*===========================================================================
466 * FUNCTION : streamCbRoutine
467 *
468 * DESCRIPTION: callback routine for stream
469 *
470 * PARAMETERS :
471 * @streamHandle : stream handle
472 *
473 * RETURN : stream object. NULL if not found
474 *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream,void * userdata)475 void QCamera3Channel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
476 QCamera3Stream *stream, void *userdata)
477 {
478 QCamera3Channel *channel = (QCamera3Channel *)userdata;
479 if (channel == NULL) {
480 LOGE("invalid channel pointer");
481 return;
482 }
483 channel->streamCbRoutine(super_frame, stream);
484 }
485
486 /*===========================================================================
487 * FUNCTION : dumpYUV
488 *
489 * DESCRIPTION: function to dump the YUV data from ISP/pproc
490 *
491 * PARAMETERS :
492 * @frame : frame to be dumped
493 * @dim : dimension of the stream
494 * @offset : offset of the data
495 * @name : 1 if it is ISP output/pproc input, 2 if it is pproc output
496 *
497 * RETURN :
498 *==========================================================================*/
dumpYUV(mm_camera_buf_def_t * frame,cam_dimension_t dim,cam_frame_len_offset_t offset,uint8_t dump_type)499 void QCamera3Channel::dumpYUV(mm_camera_buf_def_t *frame, cam_dimension_t dim,
500 cam_frame_len_offset_t offset, uint8_t dump_type)
501 {
502 char buf[FILENAME_MAX];
503 memset(buf, 0, sizeof(buf));
504 static int counter = 0;
505 if (mYUVDump & dump_type) {
506 mFrmNum = ((mYUVDump & 0xffff0000) >> 16);
507 if (mFrmNum == 0) {
508 mFrmNum = 10;
509 }
510 if (mFrmNum > 256) {
511 mFrmNum = 256;
512 }
513 mSkipMode = ((mYUVDump & 0x0000ff00) >> 8);
514 if (mSkipMode == 0) {
515 mSkipMode = 1;
516 }
517 if (mDumpSkipCnt == 0) {
518 mDumpSkipCnt = 1;
519 }
520 if (mDumpSkipCnt % mSkipMode == 0) {
521 if (mDumpFrmCnt <= mFrmNum) {
522 /* Note that the image dimension will be the unrotated stream dimension.
523 * If you feel that the image would have been rotated during reprocess
524 * then swap the dimensions while opening the file
525 * */
526 switch (dump_type) {
527 case QCAMERA_DUMP_FRM_PREVIEW:
528 snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"p_%d_%d_%dx%d.yuv",
529 counter, frame->frame_idx, dim.width, dim.height);
530 break;
531 case QCAMERA_DUMP_FRM_VIDEO:
532 snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"v_%d_%d_%dx%d.yuv",
533 counter, frame->frame_idx, dim.width, dim.height);
534 break;
535 case QCAMERA_DUMP_FRM_SNAPSHOT:
536 snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"s_%d_%d_%dx%d.yuv",
537 counter, frame->frame_idx, dim.width, dim.height);
538 break;
539 case QCAMERA_DUMP_FRM_INPUT_REPROCESS:
540 snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"ir_%d_%d_%dx%d.yuv",
541 counter, frame->frame_idx, dim.width, dim.height);
542 break;
543 case QCAMERA_DUMP_FRM_CALLBACK:
544 snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"c_%d_%d_%dx%d.yuv",
545 counter, frame->frame_idx, dim.width, dim.height);
546 break;
547 default :
548 LOGE("dumping not enabled for stream type %d",dump_type);
549 break;
550 }
551 counter++;
552 int file_fd = open(buf, O_RDWR | O_CREAT, 0777);
553 ssize_t written_len = 0;
554 if (file_fd >= 0) {
555 void *data = NULL;
556 fchmod(file_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
557 for (uint32_t i = 0; i < offset.num_planes; i++) {
558 uint32_t index = offset.mp[i].offset;
559 if (i > 0) {
560 index += offset.mp[i-1].len;
561 }
562 for (int j = 0; j < offset.mp[i].height; j++) {
563 data = (void *)((uint8_t *)frame->buffer + index);
564 written_len += write(file_fd, data,
565 (size_t)offset.mp[i].width);
566 index += (uint32_t)offset.mp[i].stride;
567 }
568 }
569 LOGH("written number of bytes %ld\n", written_len);
570 mDumpFrmCnt++;
571 frame->cache_flags |= CPU_HAS_READ;
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 //Make sure cache coherence because extra processing is done
2199 mMemory.cleanCache(super_frame->bufs[0]->buf_idx);
2200 }
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 frame->cache_flags |= CPU_HAS_READ;
2227 close(file_fd);
2228 } else {
2229 LOGE("failed to open file to dump image");
2230 }
2231 } else {
2232 LOGE("Could not find stream");
2233 }
2234
2235 }
2236
convertLegacyToRaw16(mm_camera_buf_def_t * frame)2237 void QCamera3RawChannel::convertLegacyToRaw16(mm_camera_buf_def_t *frame)
2238 {
2239 // Convert image buffer from Opaque raw format to RAW16 format
2240 // 10bit Opaque raw is stored in the format of:
2241 // 0000 - p5 - p4 - p3 - p2 - p1 - p0
2242 // where p0 to p5 are 6 pixels (each is 10bit)_and most significant
2243 // 4 bits are 0s. Each 64bit word contains 6 pixels.
2244
2245 QCamera3Stream *stream = getStreamByIndex(0);
2246 if (stream != NULL) {
2247 cam_dimension_t dim;
2248 memset(&dim, 0, sizeof(dim));
2249 stream->getFrameDimension(dim);
2250
2251 cam_frame_len_offset_t offset;
2252 memset(&offset, 0, sizeof(cam_frame_len_offset_t));
2253 stream->getFrameOffset(offset);
2254
2255 uint32_t raw16_stride = ((uint32_t)dim.width + 15U) & ~15U;
2256 uint16_t* raw16_buffer = (uint16_t *)frame->buffer;
2257
2258 // In-place format conversion.
2259 // Raw16 format always occupy more memory than opaque raw10.
2260 // Convert to Raw16 by iterating through all pixels from bottom-right
2261 // to top-left of the image.
2262 // One special notes:
2263 // 1. Cross-platform raw16's stride is 16 pixels.
2264 // 2. Opaque raw10's stride is 6 pixels, and aligned to 16 bytes.
2265 for (int32_t ys = dim.height - 1; ys >= 0; ys--) {
2266 uint32_t y = (uint32_t)ys;
2267 uint64_t* row_start = (uint64_t *)frame->buffer +
2268 y * (uint32_t)offset.mp[0].stride_in_bytes / 8;
2269 for (int32_t xs = dim.width - 1; xs >= 0; xs--) {
2270 uint32_t x = (uint32_t)xs;
2271 uint16_t raw16_pixel = 0x3FF & (row_start[x/6] >> (10*(x%6)));
2272 raw16_buffer[y*raw16_stride+x] = raw16_pixel;
2273 }
2274 }
2275 } else {
2276 LOGE("Could not find stream");
2277 }
2278
2279 }
2280
convertMipiToRaw16(mm_camera_buf_def_t * frame)2281 void QCamera3RawChannel::convertMipiToRaw16(mm_camera_buf_def_t *frame)
2282 {
2283 // Convert image buffer from mipi10 raw format to RAW16 format
2284 // mipi10 opaque raw is stored in the format of:
2285 // P3(1:0) P2(1:0) P1(1:0) P0(1:0) P3(9:2) P2(9:2) P1(9:2) P0(9:2)
2286 // 4 pixels occupy 5 bytes, no padding needed
2287
2288 QCamera3Stream *stream = getStreamByIndex(0);
2289 if (stream != NULL) {
2290 cam_dimension_t dim;
2291 memset(&dim, 0, sizeof(dim));
2292 stream->getFrameDimension(dim);
2293
2294 cam_frame_len_offset_t offset;
2295 memset(&offset, 0, sizeof(cam_frame_len_offset_t));
2296 stream->getFrameOffset(offset);
2297
2298 uint32_t raw16_stride = ((uint32_t)dim.width + 15U) & ~15U;
2299 uint16_t* raw16_buffer = (uint16_t *)frame->buffer;
2300 uint8_t first_quintuple[5];
2301 memcpy(first_quintuple, raw16_buffer, sizeof(first_quintuple));
2302
2303 // In-place format conversion.
2304 // Raw16 format always occupy more memory than opaque raw10.
2305 // Convert to Raw16 by iterating through all pixels from bottom-right
2306 // to top-left of the image.
2307 // One special notes:
2308 // 1. Cross-platform raw16's stride is 16 pixels.
2309 // 2. mipi raw10's stride is 4 pixels, and aligned to 16 bytes.
2310 for (int32_t ys = dim.height - 1; ys >= 0; ys--) {
2311 uint32_t y = (uint32_t)ys;
2312 uint8_t* row_start = (uint8_t *)frame->buffer +
2313 y * (uint32_t)offset.mp[0].stride_in_bytes;
2314 for (int32_t xs = dim.width - 1; xs >= 0; xs--) {
2315 uint32_t x = (uint32_t)xs;
2316 uint8_t upper_8bit = row_start[5*(x/4)+x%4];
2317 uint8_t lower_2bit = ((row_start[5*(x/4)+4] >> ((x%4) << 1)) & 0x3);
2318 uint16_t raw16_pixel =
2319 (uint16_t)(((uint16_t)upper_8bit)<<2 |
2320 (uint16_t)lower_2bit);
2321 raw16_buffer[y*raw16_stride+x] = raw16_pixel;
2322 }
2323 }
2324
2325 // Re-convert the first 2 pixels of the buffer because the loop above messes
2326 // them up by reading the first quintuple while modifying it.
2327 raw16_buffer[0] = ((uint16_t)first_quintuple[0]<<2) | (first_quintuple[4] & 0x3);
2328 raw16_buffer[1] = ((uint16_t)first_quintuple[1]<<2) | ((first_quintuple[4] >> 2) & 0x3);
2329
2330 } else {
2331 LOGE("Could not find stream");
2332 }
2333
2334 }
2335
2336 /*===========================================================================
2337 * FUNCTION : getReprocessType
2338 *
2339 * DESCRIPTION: get the type of reprocess output supported by this channel
2340 *
2341 * PARAMETERS : NONE
2342 *
2343 * RETURN : reprocess_type_t : type of reprocess
2344 *==========================================================================*/
getReprocessType()2345 reprocess_type_t QCamera3RawChannel::getReprocessType()
2346 {
2347 return REPROCESS_TYPE_RAW;
2348 }
2349
2350
2351 /*************************************************************************************/
2352 // RAW Dump Channel related functions
2353
2354 /*===========================================================================
2355 * FUNCTION : QCamera3RawDumpChannel
2356 *
2357 * DESCRIPTION: Constructor for RawDumpChannel
2358 *
2359 * PARAMETERS :
2360 * @cam_handle : Handle for Camera
2361 * @cam_ops : Function pointer table
2362 * @rawDumpSize : Dimensions for the Raw stream
2363 * @paddinginfo : Padding information for stream
2364 * @userData : Cookie for parent
2365 * @pp mask : PP feature mask for this stream
2366 * @numBuffers : number of max dequeued buffers
2367 *
2368 * RETURN : NA
2369 *==========================================================================*/
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)2370 QCamera3RawDumpChannel::QCamera3RawDumpChannel(uint32_t cam_handle,
2371 uint32_t channel_handle,
2372 mm_camera_ops_t *cam_ops,
2373 cam_dimension_t rawDumpSize,
2374 cam_padding_info_t *paddingInfo,
2375 void *userData,
2376 cam_feature_mask_t postprocess_mask, uint32_t numBuffers) :
2377 QCamera3Channel(cam_handle, channel_handle, cam_ops, NULL,
2378 NULL, paddingInfo, postprocess_mask,
2379 userData, numBuffers),
2380 mDim(rawDumpSize),
2381 mMemory(NULL)
2382 {
2383 char prop[PROPERTY_VALUE_MAX];
2384 property_get("persist.camera.raw.dump", prop, "0");
2385 mRawDump = atoi(prop);
2386 }
2387
2388 /*===========================================================================
2389 * FUNCTION : QCamera3RawDumpChannel
2390 *
2391 * DESCRIPTION: Destructor for RawDumpChannel
2392 *
2393 * PARAMETERS :
2394 *
2395 * RETURN : NA
2396 *==========================================================================*/
2397
~QCamera3RawDumpChannel()2398 QCamera3RawDumpChannel::~QCamera3RawDumpChannel()
2399 {
2400 destroy();
2401 }
2402
2403 /*===========================================================================
2404 * FUNCTION : dumpRawSnapshot
2405 *
2406 * DESCRIPTION: Helper function to dump Raw frames
2407 *
2408 * PARAMETERS :
2409 * @frame : stream buf frame to be dumped
2410 *
2411 * RETURN : NA
2412 *==========================================================================*/
dumpRawSnapshot(mm_camera_buf_def_t * frame)2413 void QCamera3RawDumpChannel::dumpRawSnapshot(mm_camera_buf_def_t *frame)
2414 {
2415 QCamera3Stream *stream = getStreamByIndex(0);
2416 if (stream != NULL) {
2417 char buf[FILENAME_MAX];
2418 struct timeval tv;
2419 struct tm timeinfo_data;
2420 struct tm *timeinfo;
2421
2422 cam_dimension_t dim;
2423 memset(&dim, 0, sizeof(dim));
2424 stream->getFrameDimension(dim);
2425
2426 cam_frame_len_offset_t offset;
2427 memset(&offset, 0, sizeof(cam_frame_len_offset_t));
2428 stream->getFrameOffset(offset);
2429
2430 gettimeofday(&tv, NULL);
2431 timeinfo = localtime_r(&tv.tv_sec, &timeinfo_data);
2432
2433 if (NULL != timeinfo) {
2434 memset(buf, 0, sizeof(buf));
2435 /* Consistent naming for Jpeg+meta+raw: Raw name */
2436 snprintf(buf, sizeof(buf),
2437 QCAMERA_DUMP_FRM_LOCATION
2438 "IMG_%04d%02d%02d_%02d%02d%02d_%dx%d.raw",
2439 timeinfo->tm_year + 1900, timeinfo->tm_mon + 1,
2440 timeinfo->tm_mday, timeinfo->tm_hour,
2441 timeinfo->tm_min, timeinfo->tm_sec,
2442 dim.width, dim.height);
2443 /* Consistent naming for Jpeg+meta+raw: Raw name end*/
2444 int file_fd = open(buf, O_RDWR| O_CREAT, 0777);
2445 if (file_fd >= 0) {
2446 ssize_t written_len =
2447 write(file_fd, frame->buffer, offset.frame_len);
2448 LOGD("written number of bytes %zd", written_len);
2449 frame->cache_flags |= CPU_HAS_READ;
2450 close(file_fd);
2451 } else {
2452 LOGE("failed to open file to dump image");
2453 }
2454 } else {
2455 LOGE("localtime_r() error");
2456 }
2457 } else {
2458 LOGE("Could not find stream");
2459 }
2460
2461 }
2462
2463 /*===========================================================================
2464 * FUNCTION : streamCbRoutine
2465 *
2466 * DESCRIPTION: Callback routine invoked for each frame generated for
2467 * Rawdump channel
2468 *
2469 * PARAMETERS :
2470 * @super_frame : stream buf frame generated
2471 * @stream : Underlying Stream object cookie
2472 *
2473 * RETURN : NA
2474 *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,__unused QCamera3Stream * stream)2475 void QCamera3RawDumpChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
2476 __unused QCamera3Stream *stream)
2477 {
2478 LOGD("E");
2479 if (super_frame == NULL || super_frame->num_bufs != 1) {
2480 LOGE("super_frame is not valid");
2481 return;
2482 }
2483
2484 if (mRawDump)
2485 dumpRawSnapshot(super_frame->bufs[0]);
2486
2487 bufDone(super_frame);
2488 free(super_frame);
2489 }
2490
2491 /*===========================================================================
2492 * FUNCTION : getStreamBufs
2493 *
2494 * DESCRIPTION: Callback function provided to interface to get buffers.
2495 *
2496 * PARAMETERS :
2497 * @len : Length of each buffer to be allocated
2498 *
2499 * RETURN : NULL on buffer allocation failure
2500 * QCamera3StreamMem object on sucess
2501 *==========================================================================*/
getStreamBufs(uint32_t len)2502 QCamera3StreamMem* QCamera3RawDumpChannel::getStreamBufs(uint32_t len)
2503 {
2504 int rc;
2505 mMemory = new QCamera3StreamMem(mNumBuffers);
2506
2507 if (!mMemory) {
2508 LOGE("unable to create heap memory");
2509 return NULL;
2510 }
2511 rc = mMemory->allocateAll((size_t)len);
2512 if (rc < 0) {
2513 LOGE("unable to allocate heap memory");
2514 delete mMemory;
2515 mMemory = NULL;
2516 return NULL;
2517 }
2518 return mMemory;
2519 }
2520
2521 /*===========================================================================
2522 * FUNCTION : putStreamBufs
2523 *
2524 * DESCRIPTION: Callback function provided to interface to return buffers.
2525 * Although no handles are actually returned, implicitl assumption
2526 * that interface will no longer use buffers and channel can
2527 * deallocated if necessary.
2528 *
2529 * PARAMETERS : NA
2530 *
2531 * RETURN : NA
2532 *==========================================================================*/
putStreamBufs()2533 void QCamera3RawDumpChannel::putStreamBufs()
2534 {
2535 mMemory->deallocate();
2536 delete mMemory;
2537 mMemory = NULL;
2538 }
2539
2540 /*===========================================================================
2541 * FUNCTION : request
2542 *
2543 * DESCRIPTION: Request function used as trigger
2544 *
2545 * PARAMETERS :
2546 * @recvd_frame : buffer- this will be NULL since this is internal channel
2547 * @frameNumber : Undefined again since this is internal stream
2548 *
2549 * RETURN : int32_t type of status
2550 * NO_ERROR -- success
2551 * none-zero failure code
2552 *==========================================================================*/
request(buffer_handle_t *,uint32_t,int &)2553 int32_t QCamera3RawDumpChannel::request(buffer_handle_t * /*buffer*/,
2554 uint32_t /*frameNumber*/,
2555 int & /*indexUsed*/)
2556 {
2557 if (!m_bIsActive) {
2558 return QCamera3Channel::start();
2559 }
2560 else
2561 return 0;
2562 }
2563
2564 /*===========================================================================
2565 * FUNCTION : intialize
2566 *
2567 * DESCRIPTION: Initializes channel params and creates underlying stream
2568 *
2569 * PARAMETERS :
2570 * @isType : type of image stabilization required on this stream
2571 *
2572 * RETURN : int32_t type of status
2573 * NO_ERROR -- success
2574 * none-zero failure code
2575 *==========================================================================*/
initialize(cam_is_type_t isType)2576 int32_t QCamera3RawDumpChannel::initialize(cam_is_type_t isType)
2577 {
2578 int32_t rc;
2579
2580 mIsType = isType;
2581 rc = QCamera3Channel::addStream(CAM_STREAM_TYPE_RAW,
2582 CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG, mDim, ROTATE_0, (uint8_t)mNumBuffers,
2583 mPostProcMask, mIsType);
2584 if (rc < 0) {
2585 LOGE("addStream failed");
2586 }
2587 return rc;
2588 }
2589 /*************************************************************************************/
2590
2591 /* QCamera3YUVChannel methods */
2592
2593 /*===========================================================================
2594 * FUNCTION : QCamera3YUVChannel
2595 *
2596 * DESCRIPTION: constructor of QCamera3YUVChannel
2597 *
2598 * PARAMETERS :
2599 * @cam_handle : camera handle
2600 * @cam_ops : ptr to camera ops table
2601 * @cb_routine : callback routine to frame aggregator
2602 * @paddingInfo : padding information for the stream
2603 * @stream : camera3_stream_t structure
2604 * @stream_type: Channel stream type
2605 * @postprocess_mask: the postprocess mask for streams of this channel
2606 * @metadataChannel: handle to the metadataChannel
2607 * RETURN : none
2608 *==========================================================================*/
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)2609 QCamera3YUVChannel::QCamera3YUVChannel(uint32_t cam_handle,
2610 uint32_t channel_handle,
2611 mm_camera_ops_t *cam_ops,
2612 channel_cb_routine cb_routine,
2613 channel_cb_buffer_err cb_buf_err,
2614 cam_padding_info_t *paddingInfo,
2615 void *userData,
2616 camera3_stream_t *stream,
2617 cam_stream_type_t stream_type,
2618 cam_feature_mask_t postprocess_mask,
2619 QCamera3Channel *metadataChannel) :
2620 QCamera3ProcessingChannel(cam_handle, channel_handle, cam_ops,
2621 cb_routine, cb_buf_err, paddingInfo, userData, stream, stream_type,
2622 postprocess_mask, metadataChannel)
2623 {
2624
2625 mBypass = (postprocess_mask == CAM_QCOM_FEATURE_NONE);
2626 mFrameLen = 0;
2627 mEdgeMode.edge_mode = CAM_EDGE_MODE_OFF;
2628 mEdgeMode.sharpness = 0;
2629 mNoiseRedMode = CAM_NOISE_REDUCTION_MODE_OFF;
2630 memset(&mCropRegion, 0, sizeof(mCropRegion));
2631 }
2632
2633 /*===========================================================================
2634 * FUNCTION : ~QCamera3YUVChannel
2635 *
2636 * DESCRIPTION: destructor of QCamera3YUVChannel
2637 *
2638 * PARAMETERS : none
2639 *
2640 *
2641 * RETURN : none
2642 *==========================================================================*/
~QCamera3YUVChannel()2643 QCamera3YUVChannel::~QCamera3YUVChannel()
2644 {
2645 // Deallocation of heap buffers allocated in mMemory is freed
2646 // automatically by its destructor
2647 }
2648
2649 /*===========================================================================
2650 * FUNCTION : initialize
2651 *
2652 * DESCRIPTION: Initialize and add camera channel & stream
2653 *
2654 * PARAMETERS :
2655 * @isType : the image stabilization type
2656 *
2657 * RETURN : int32_t type of status
2658 * NO_ERROR -- success
2659 * none-zero failure code
2660 *==========================================================================*/
initialize(cam_is_type_t isType)2661 int32_t QCamera3YUVChannel::initialize(cam_is_type_t isType)
2662 {
2663 ATRACE_CALL();
2664 int32_t rc = NO_ERROR;
2665 cam_dimension_t streamDim;
2666
2667 if (NULL == mCamera3Stream) {
2668 LOGE("Camera stream uninitialized");
2669 return NO_INIT;
2670 }
2671
2672 if (1 <= m_numStreams) {
2673 // Only one stream per channel supported in v3 Hal
2674 return NO_ERROR;
2675 }
2676
2677 mIsType = isType;
2678 mStreamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_CALLBACK,
2679 mCamera3Stream->width, mCamera3Stream->height);
2680 streamDim.width = mCamera3Stream->width;
2681 streamDim.height = mCamera3Stream->height;
2682
2683 rc = QCamera3Channel::addStream(mStreamType,
2684 mStreamFormat,
2685 streamDim,
2686 ROTATE_0,
2687 mNumBufs,
2688 mPostProcMask,
2689 mIsType);
2690 if (rc < 0) {
2691 LOGE("addStream failed");
2692 return rc;
2693 }
2694
2695 cam_stream_buf_plane_info_t buf_planes;
2696 cam_padding_info_t paddingInfo = mPaddingInfo;
2697
2698 memset(&buf_planes, 0, sizeof(buf_planes));
2699 //to ensure a big enough buffer size set the height and width
2700 //padding to max(height padding, width padding)
2701 paddingInfo.width_padding = MAX(paddingInfo.width_padding, paddingInfo.height_padding);
2702 paddingInfo.height_padding = paddingInfo.width_padding;
2703
2704 rc = mm_stream_calc_offset_snapshot(mStreamFormat, &streamDim, &paddingInfo,
2705 &buf_planes);
2706 if (rc < 0) {
2707 LOGE("mm_stream_calc_offset_preview failed");
2708 return rc;
2709 }
2710
2711 mFrameLen = buf_planes.plane_info.frame_len;
2712
2713 if (NO_ERROR != rc) {
2714 LOGE("Initialize failed, rc = %d", rc);
2715 return rc;
2716 }
2717
2718 /* initialize offline meta memory for input reprocess */
2719 rc = QCamera3ProcessingChannel::initialize(isType);
2720 if (NO_ERROR != rc) {
2721 LOGE("Processing Channel initialize failed, rc = %d",
2722 rc);
2723 }
2724
2725 return rc;
2726 }
2727
2728 /*===========================================================================
2729 * FUNCTION : request
2730 *
2731 * DESCRIPTION: entry function for a request on a YUV stream. This function
2732 * has the logic to service a request based on its type
2733 *
2734 * PARAMETERS :
2735 * @buffer : pointer to the output buffer
2736 * @frameNumber : frame number of the request
2737 * @pInputBuffer : pointer to input buffer if an input request
2738 * @metadata : parameters associated with the request
2739 *
2740 * RETURN : 0 on a success start of capture
2741 * -EINVAL on invalid input
2742 * -ENODEV on serious error
2743 *==========================================================================*/
request(buffer_handle_t * buffer,uint32_t frameNumber,camera3_stream_buffer_t * pInputBuffer,metadata_buffer_t * metadata,bool & needMetadata,int & indexUsed)2744 int32_t QCamera3YUVChannel::request(buffer_handle_t *buffer,
2745 uint32_t frameNumber,
2746 camera3_stream_buffer_t* pInputBuffer,
2747 metadata_buffer_t* metadata, bool &needMetadata,
2748 int &indexUsed)
2749 {
2750 int32_t rc = NO_ERROR;
2751 Mutex::Autolock lock(mOfflinePpLock);
2752
2753 LOGD("pInputBuffer is %p frame number %d", pInputBuffer, frameNumber);
2754 if (NULL == buffer || NULL == metadata) {
2755 LOGE("Invalid buffer/metadata in channel request");
2756 return BAD_VALUE;
2757 }
2758
2759 PpInfo ppInfo;
2760 memset(&ppInfo, 0, sizeof(ppInfo));
2761 ppInfo.frameNumber = frameNumber;
2762 ppInfo.offlinePpFlag = false;
2763 if (mBypass && !pInputBuffer ) {
2764 ppInfo.offlinePpFlag = needsFramePostprocessing(metadata);
2765 ppInfo.output = buffer;
2766 mOfflinePpInfoList.push_back(ppInfo);
2767 }
2768
2769 LOGD("offlinePpFlag is %d", ppInfo.offlinePpFlag);
2770 needMetadata = ppInfo.offlinePpFlag;
2771 if (!ppInfo.offlinePpFlag) {
2772 // regular request
2773 return QCamera3ProcessingChannel::request(buffer, frameNumber,
2774 pInputBuffer, metadata, indexUsed);
2775 } else {
2776 if(!m_bIsActive) {
2777 rc = start();
2778 if (NO_ERROR != rc)
2779 return rc;
2780 } else {
2781 LOGD("Request on an existing stream");
2782 }
2783
2784 //we need to send this frame through the CPP
2785 //Allocate heap memory, then buf done on the buffer
2786 uint32_t bufIdx;
2787 if (mFreeHeapBufferList.empty()) {
2788 rc = mMemory.allocateOne(mFrameLen);
2789 if (rc < 0) {
2790 LOGE("Failed allocating heap buffer. Fatal");
2791 return BAD_VALUE;
2792 } else {
2793 bufIdx = (uint32_t)rc;
2794 }
2795 } else {
2796 bufIdx = *(mFreeHeapBufferList.begin());
2797 mFreeHeapBufferList.erase(mFreeHeapBufferList.begin());
2798 }
2799
2800 /* Configure and start postproc if necessary */
2801 reprocess_config_t reproc_cfg;
2802 cam_dimension_t dim;
2803 memset(&reproc_cfg, 0, sizeof(reprocess_config_t));
2804 memset(&dim, 0, sizeof(dim));
2805 mStreams[0]->getFrameDimension(dim);
2806 setReprocConfig(reproc_cfg, NULL, metadata, mStreamFormat, dim);
2807
2808 // Start postprocessor without input buffer
2809 startPostProc(reproc_cfg);
2810
2811 LOGD("erasing %d", bufIdx);
2812
2813 mMemory.markFrameNumber(bufIdx, frameNumber);
2814 indexUsed = bufIdx;
2815 mStreams[0]->bufDone(bufIdx);
2816
2817 }
2818 return rc;
2819 }
2820
2821 /*===========================================================================
2822 * FUNCTION : streamCbRoutine
2823 *
2824 * DESCRIPTION:
2825 *
2826 * PARAMETERS :
2827 * @super_frame : the super frame with filled buffer
2828 * @stream : stream on which the buffer was requested and filled
2829 *
2830 * RETURN : none
2831 *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream)2832 void QCamera3YUVChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
2833 QCamera3Stream *stream)
2834 {
2835 ATRACE_CALL();
2836 uint8_t frameIndex;
2837 int32_t resultFrameNumber;
2838
2839 if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) {
2840 LOGE("Error with the stream callback");
2841 return;
2842 }
2843
2844 frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
2845 if(frameIndex >= mNumBufs) {
2846 LOGE("Error, Invalid index for buffer");
2847 stream->bufDone(frameIndex);
2848 return;
2849 }
2850
2851 if (mBypass) {
2852 {
2853 List<PpInfo>::iterator ppInfo;
2854
2855 Mutex::Autolock lock(mOfflinePpLock);
2856 resultFrameNumber = mMemory.getFrameNumber(frameIndex);
2857 for (ppInfo = mOfflinePpInfoList.begin();
2858 ppInfo != mOfflinePpInfoList.end(); ppInfo++) {
2859 if (ppInfo->frameNumber == (uint32_t)resultFrameNumber) {
2860 break;
2861 }
2862 }
2863 LOGD("frame index %d, frame number %d", frameIndex,
2864 resultFrameNumber);
2865 //check the reprocessing required flag against the frame number
2866 if (ppInfo == mOfflinePpInfoList.end()) {
2867 LOGE("Error, request for frame number is a reprocess.");
2868 stream->bufDone(frameIndex);
2869 return;
2870 }
2871
2872 if (ppInfo->offlinePpFlag) {
2873 mm_camera_super_buf_t *frame =
2874 (mm_camera_super_buf_t *)malloc(sizeof(
2875 mm_camera_super_buf_t));
2876 if (frame == NULL) {
2877 LOGE("Error allocating memory to save received_frame structure.");
2878 if(stream) {
2879 stream->bufDone(frameIndex);
2880 }
2881 return;
2882 }
2883
2884 *frame = *super_frame;
2885 m_postprocessor.processData(frame, ppInfo->output,
2886 resultFrameNumber);
2887 free(super_frame);
2888 return;
2889 } else {
2890 if (ppInfo != mOfflinePpInfoList.begin()) {
2891 // There is pending reprocess buffer, cache current buffer
2892 if (ppInfo->callback_buffer != NULL) {
2893 LOGE("Fatal: cached callback_buffer is already present");
2894 }
2895 ppInfo->callback_buffer = super_frame;
2896 return;
2897 } else {
2898 mOfflinePpInfoList.erase(ppInfo);
2899 }
2900 }
2901 }
2902
2903 if (IS_BUFFER_ERROR(super_frame->bufs[0]->flags)) {
2904 mChannelCbBufErr(this, resultFrameNumber,
2905 CAMERA3_BUFFER_STATUS_ERROR, mUserData);
2906 }
2907
2908 }
2909
2910 QCamera3ProcessingChannel::streamCbRoutine(super_frame, stream);
2911
2912 /* return any pending buffers that were received out of order earlier */
2913 while((super_frame = getNextPendingCbBuffer())) {
2914 QCamera3ProcessingChannel::streamCbRoutine(super_frame, stream);
2915 }
2916
2917 return;
2918 }
2919
2920 /*===========================================================================
2921 * FUNCTION : getNextPendingCbBuffer
2922 *
2923 * DESCRIPTION: Returns the callback_buffer from the first entry of
2924 * mOfflinePpInfoList
2925 *
2926 * PARAMETERS : none
2927 *
2928 * RETURN : callback_buffer
2929 *==========================================================================*/
getNextPendingCbBuffer()2930 mm_camera_super_buf_t* QCamera3YUVChannel::getNextPendingCbBuffer() {
2931 mm_camera_super_buf_t* super_frame = NULL;
2932 if (mOfflinePpInfoList.size()) {
2933 if ((super_frame = mOfflinePpInfoList.begin()->callback_buffer)) {
2934 mOfflinePpInfoList.erase(mOfflinePpInfoList.begin());
2935 }
2936 }
2937 return super_frame;
2938 }
2939
2940 /*===========================================================================
2941 * FUNCTION : reprocessCbRoutine
2942 *
2943 * DESCRIPTION: callback function for the reprocessed frame. This frame now
2944 * should be returned to the framework. This same callback is
2945 * used during input reprocessing or offline postprocessing
2946 *
2947 * PARAMETERS :
2948 * @resultBuffer : buffer containing the reprocessed data
2949 * @resultFrameNumber : frame number on which the buffer was requested
2950 *
2951 * RETURN : NONE
2952 *
2953 *==========================================================================*/
reprocessCbRoutine(buffer_handle_t * resultBuffer,uint32_t resultFrameNumber)2954 void QCamera3YUVChannel::reprocessCbRoutine(buffer_handle_t *resultBuffer,
2955 uint32_t resultFrameNumber)
2956 {
2957 LOGD("E: frame number %d", resultFrameNumber);
2958 Vector<mm_camera_super_buf_t *> pendingCbs;
2959
2960 /* release the input buffer and input metadata buffer if used */
2961 if (0 > mMemory.getHeapBufferIndex(resultFrameNumber)) {
2962 /* mOfflineMemory and mOfflineMetaMemory used only for input reprocessing */
2963 int32_t rc = releaseOfflineMemory(resultFrameNumber);
2964 if (NO_ERROR != rc) {
2965 LOGE("Error releasing offline memory rc = %d", rc);
2966 }
2967 /* Since reprocessing is done, send the callback to release the input buffer */
2968 if (mChannelCB) {
2969 mChannelCB(NULL, NULL, resultFrameNumber, true, mUserData);
2970 }
2971 }
2972
2973 if (mBypass) {
2974 int32_t rc = handleOfflinePpCallback(resultFrameNumber, pendingCbs);
2975 if (rc != NO_ERROR) {
2976 return;
2977 }
2978 }
2979
2980 issueChannelCb(resultBuffer, resultFrameNumber);
2981
2982 // Call all pending callbacks to return buffers
2983 for (size_t i = 0; i < pendingCbs.size(); i++) {
2984 QCamera3ProcessingChannel::streamCbRoutine(
2985 pendingCbs[i], mStreams[0]);
2986 }
2987
2988 }
2989
2990 /*===========================================================================
2991 * FUNCTION : needsFramePostprocessing
2992 *
2993 * DESCRIPTION:
2994 *
2995 * PARAMETERS :
2996 *
2997 * RETURN :
2998 * TRUE if frame needs to be postprocessed
2999 * FALSE is frame does not need to be postprocessed
3000 *
3001 *==========================================================================*/
needsFramePostprocessing(metadata_buffer_t * meta)3002 bool QCamera3YUVChannel::needsFramePostprocessing(metadata_buffer_t *meta)
3003 {
3004 bool ppNeeded = false;
3005
3006 //sharpness
3007 IF_META_AVAILABLE(cam_edge_application_t, edgeMode,
3008 CAM_INTF_META_EDGE_MODE, meta) {
3009 mEdgeMode = *edgeMode;
3010 }
3011
3012 //wnr
3013 IF_META_AVAILABLE(uint32_t, noiseRedMode,
3014 CAM_INTF_META_NOISE_REDUCTION_MODE, meta) {
3015 mNoiseRedMode = *noiseRedMode;
3016 }
3017
3018 //crop region
3019 IF_META_AVAILABLE(cam_crop_region_t, scalerCropRegion,
3020 CAM_INTF_META_SCALER_CROP_REGION, meta) {
3021 mCropRegion = *scalerCropRegion;
3022 }
3023
3024 if ((CAM_EDGE_MODE_OFF != mEdgeMode.edge_mode) &&
3025 (CAM_EDGE_MODE_ZERO_SHUTTER_LAG != mEdgeMode.edge_mode)) {
3026 ppNeeded = true;
3027 }
3028 if ((CAM_NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG != mNoiseRedMode) &&
3029 (CAM_NOISE_REDUCTION_MODE_OFF != mNoiseRedMode) &&
3030 (CAM_NOISE_REDUCTION_MODE_MINIMAL != mNoiseRedMode)) {
3031 ppNeeded = true;
3032 }
3033 if ((mCropRegion.width < (int32_t)mCamera3Stream->width) ||
3034 (mCropRegion.height < (int32_t)mCamera3Stream->height)) {
3035 ppNeeded = true;
3036 }
3037
3038 return ppNeeded;
3039 }
3040
3041 /*===========================================================================
3042 * FUNCTION : handleOfflinePpCallback
3043 *
3044 * DESCRIPTION: callback function for the reprocessed frame from offline
3045 * postprocessing.
3046 *
3047 * PARAMETERS :
3048 * @resultFrameNumber : frame number on which the buffer was requested
3049 * @pendingCbs : pending buffers to be returned first
3050 *
3051 * RETURN : int32_t type of status
3052 * NO_ERROR -- success
3053 * none-zero failure code
3054 *==========================================================================*/
handleOfflinePpCallback(uint32_t resultFrameNumber,Vector<mm_camera_super_buf_t * > & pendingCbs)3055 int32_t QCamera3YUVChannel::handleOfflinePpCallback(uint32_t resultFrameNumber,
3056 Vector<mm_camera_super_buf_t *>& pendingCbs)
3057 {
3058 Mutex::Autolock lock(mOfflinePpLock);
3059 List<PpInfo>::iterator ppInfo;
3060
3061 for (ppInfo = mOfflinePpInfoList.begin();
3062 ppInfo != mOfflinePpInfoList.end(); ppInfo++) {
3063 if (ppInfo->frameNumber == resultFrameNumber) {
3064 break;
3065 }
3066 }
3067
3068 if (ppInfo == mOfflinePpInfoList.end()) {
3069 LOGI("Request of frame number %d is reprocessing",
3070 resultFrameNumber);
3071 return NO_ERROR;
3072 } else if (ppInfo != mOfflinePpInfoList.begin()) {
3073 LOGE("callback for frame number %d should be head of list",
3074 resultFrameNumber);
3075 return BAD_VALUE;
3076 }
3077
3078 if (ppInfo->offlinePpFlag) {
3079 // Need to get the input buffer frame index from the
3080 // mMemory object and add that to the free heap buffers list.
3081 int32_t bufferIndex =
3082 mMemory.getHeapBufferIndex(resultFrameNumber);
3083 if (bufferIndex < 0) {
3084 LOGE("Fatal %d: no buffer index for frame number %d",
3085 bufferIndex, resultFrameNumber);
3086 return BAD_VALUE;
3087 }
3088 mMemory.markFrameNumber(bufferIndex, -1);
3089 mFreeHeapBufferList.push_back(bufferIndex);
3090 //Move heap buffer into free pool and invalidate the frame number
3091 ppInfo = mOfflinePpInfoList.erase(ppInfo);
3092
3093 /* return any pending buffers that were received out of order
3094 earlier */
3095 mm_camera_super_buf_t* super_frame;
3096 while((super_frame = getNextPendingCbBuffer())) {
3097 pendingCbs.push_back(super_frame);
3098 }
3099 } else {
3100 LOGE("Fatal: request of frame number %d doesn't need"
3101 " offline postprocessing. However there is"
3102 " reprocessing callback.",
3103 resultFrameNumber);
3104 return BAD_VALUE;
3105 }
3106
3107 return NO_ERROR;
3108 }
3109
3110 /*===========================================================================
3111 * FUNCTION : getReprocessType
3112 *
3113 * DESCRIPTION: get the type of reprocess output supported by this channel
3114 *
3115 * PARAMETERS : NONE
3116 *
3117 * RETURN : reprocess_type_t : type of reprocess
3118 *==========================================================================*/
getReprocessType()3119 reprocess_type_t QCamera3YUVChannel::getReprocessType()
3120 {
3121 return REPROCESS_TYPE_YUV;
3122 }
3123
3124 /* QCamera3PicChannel methods */
3125
3126 /*===========================================================================
3127 * FUNCTION : jpegEvtHandle
3128 *
3129 * DESCRIPTION: Function registerd to mm-jpeg-interface to handle jpeg events.
3130 Construct result payload and call mChannelCb to deliver buffer
3131 to framework.
3132 *
3133 * PARAMETERS :
3134 * @status : status of jpeg job
3135 * @client_hdl: jpeg client handle
3136 * @jobId : jpeg job Id
3137 * @p_ouput : ptr to jpeg output result struct
3138 * @userdata : user data ptr
3139 *
3140 * RETURN : none
3141 *==========================================================================*/
jpegEvtHandle(jpeg_job_status_t status,uint32_t,uint32_t jobId,mm_jpeg_output_t * p_output,void * userdata)3142 void QCamera3PicChannel::jpegEvtHandle(jpeg_job_status_t status,
3143 uint32_t /*client_hdl*/,
3144 uint32_t jobId,
3145 mm_jpeg_output_t *p_output,
3146 void *userdata)
3147 {
3148 ATRACE_CALL();
3149 buffer_handle_t *resultBuffer = NULL;
3150 buffer_handle_t *jpegBufferHandle = NULL;
3151 int resultStatus = CAMERA3_BUFFER_STATUS_OK;
3152 camera3_stream_buffer_t result;
3153 camera3_jpeg_blob_t jpegHeader;
3154
3155 QCamera3PicChannel *obj = (QCamera3PicChannel *)userdata;
3156 if (obj) {
3157 //Construct payload for process_capture_result. Call mChannelCb
3158
3159 qcamera_hal3_jpeg_data_t *job = obj->m_postprocessor.findJpegJobByJobId(jobId);
3160
3161 if ((job == NULL) || (status == JPEG_JOB_STATUS_ERROR)) {
3162 LOGE("Error in jobId: (%d) with status: %d", jobId, status);
3163 resultStatus = CAMERA3_BUFFER_STATUS_ERROR;
3164 }
3165
3166 if (NULL != job) {
3167 uint32_t bufIdx = (uint32_t)job->jpeg_settings->out_buf_index;
3168 LOGD("jpeg out_buf_index: %d", bufIdx);
3169
3170 //Construct jpeg transient header of type camera3_jpeg_blob_t
3171 //Append at the end of jpeg image of buf_filled_len size
3172
3173 jpegHeader.jpeg_blob_id = CAMERA3_JPEG_BLOB_ID;
3174 if (JPEG_JOB_STATUS_DONE == status) {
3175 jpegHeader.jpeg_size = (uint32_t)p_output->buf_filled_len;
3176 char* jpeg_buf = (char *)p_output->buf_vaddr;
3177
3178 ssize_t maxJpegSize = -1;
3179
3180 // Gralloc buffer may have additional padding for 4K page size
3181 // Follow size guidelines based on spec since framework relies
3182 // on that to reach end of buffer and with it the header
3183
3184 //Handle same as resultBuffer, but for readablity
3185 jpegBufferHandle =
3186 (buffer_handle_t *)obj->mMemory.getBufferHandle(bufIdx);
3187
3188 if (NULL != jpegBufferHandle) {
3189 maxJpegSize = ((private_handle_t*)(*jpegBufferHandle))->width;
3190 if (maxJpegSize > obj->mMemory.getSize(bufIdx)) {
3191 maxJpegSize = obj->mMemory.getSize(bufIdx);
3192 }
3193
3194 size_t jpeg_eof_offset =
3195 (size_t)(maxJpegSize - (ssize_t)sizeof(jpegHeader));
3196 char *jpeg_eof = &jpeg_buf[jpeg_eof_offset];
3197 memcpy(jpeg_eof, &jpegHeader, sizeof(jpegHeader));
3198 obj->mMemory.cleanInvalidateCache(bufIdx);
3199 bool jpegDump = false;
3200 char prop[PROPERTY_VALUE_MAX];
3201 property_get("persist.camera.jpeg.dump", prop, "0");
3202 jpegDump = atoi(prop);
3203 if (jpegDump) {
3204 char buf[FILENAME_MAX];
3205 char timeBuf[FILENAME_MAX];
3206 memset(buf, 0, sizeof(buf));
3207 memset(timeBuf, 0, sizeof(timeBuf));
3208 time_t current_time;
3209 struct tm * timeinfo;
3210 time (¤t_time);
3211 timeinfo = localtime (¤t_time);
3212 if (timeinfo != NULL) {
3213 /* Consistent naming for Jpeg+meta+raw: meta name */
3214 strftime (timeBuf, sizeof(timeBuf),
3215 QCAMERA_DUMP_FRM_LOCATION"IMG_%Y%m%d_%H%M%S", timeinfo);
3216 /* Consistent naming for Jpeg+meta+raw: meta name end*/
3217 }
3218 String8 filePath(timeBuf);
3219 snprintf(buf, sizeof(buf), "_%d.jpg",
3220 obj->mMemory.getFrameNumber(bufIdx));
3221 filePath.append(buf);
3222 int file_fd = open(filePath.string(), O_RDWR | O_CREAT, 0777);
3223 ssize_t written_len = 0;
3224 if (file_fd >= 0) {
3225 fchmod(file_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
3226 written_len += write(file_fd, jpeg_buf,
3227 (size_t)maxJpegSize);
3228 LOGI("written number of bytes %ld attempted: %ld\n", written_len,
3229 maxJpegSize);
3230 close(file_fd);
3231 } else {
3232 LOGE("failed to open file to dump image");
3233 }
3234
3235 }
3236 } else {
3237 LOGE("JPEG buffer not found and index: %d",
3238 bufIdx);
3239 resultStatus = CAMERA3_BUFFER_STATUS_ERROR;
3240 }
3241 }
3242
3243 ////Use below data to issue framework callback
3244 resultBuffer =
3245 (buffer_handle_t *)obj->mMemory.getBufferHandle(bufIdx);
3246 int32_t resultFrameNumber = obj->mMemory.getFrameNumber(bufIdx);
3247 int32_t rc = obj->mMemory.unregisterBuffer(bufIdx);
3248 if (NO_ERROR != rc) {
3249 LOGE("Error %d unregistering stream buffer %d",
3250 rc, bufIdx);
3251 }
3252
3253 result.stream = obj->mCamera3Stream;
3254 result.buffer = resultBuffer;
3255 result.status = resultStatus;
3256 result.acquire_fence = -1;
3257 result.release_fence = -1;
3258
3259 // Release any snapshot buffers before calling
3260 // the user callback. The callback can potentially
3261 // unblock pending requests to snapshot stream.
3262 int32_t snapshotIdx = -1;
3263 mm_camera_super_buf_t* src_frame = NULL;
3264
3265 if (job->src_reproc_frame)
3266 src_frame = job->src_reproc_frame;
3267 else
3268 src_frame = job->src_frame;
3269
3270 if (src_frame) {
3271 if (obj->mStreams[0]->getMyHandle() ==
3272 src_frame->bufs[0]->stream_id) {
3273 snapshotIdx = (int32_t)src_frame->bufs[0]->buf_idx;
3274 if (0 <= snapshotIdx) {
3275 Mutex::Autolock lock(obj->mFreeBuffersLock);
3276 obj->mFreeBufferList.push_back((uint32_t)snapshotIdx);
3277 }
3278 }
3279 }
3280
3281 LOGI("Issue Jpeg Callback frameNumber = %d status = %d",
3282 resultFrameNumber, resultStatus);
3283 KPI_ATRACE_ASYNC_END("SNAPSHOT", resultFrameNumber);
3284 if (obj->mChannelCB) {
3285 obj->mChannelCB(NULL,
3286 &result,
3287 (uint32_t)resultFrameNumber,
3288 false,
3289 obj->mUserData);
3290 }
3291
3292 // release internal data for jpeg job
3293 if ((NULL != job->fwk_frame) || (NULL != job->fwk_src_buffer)) {
3294 /* unregister offline input buffer */
3295 int32_t inputBufIndex =
3296 obj->mOfflineMemory.getGrallocBufferIndex((uint32_t)resultFrameNumber);
3297 if (0 <= inputBufIndex) {
3298 rc = obj->mOfflineMemory.unregisterBuffer(inputBufIndex);
3299 } else {
3300 LOGE("could not find the input buf index, frame number %d",
3301 resultFrameNumber);
3302 }
3303 if (NO_ERROR != rc) {
3304 LOGE("Error %d unregistering input buffer %d",
3305 rc, bufIdx);
3306 }
3307
3308 /* unregister offline meta buffer */
3309 int32_t metaBufIndex =
3310 obj->mOfflineMetaMemory.getHeapBufferIndex((uint32_t)resultFrameNumber);
3311 if (0 <= metaBufIndex) {
3312 Mutex::Autolock lock(obj->mFreeOfflineMetaBuffersLock);
3313 obj->mFreeOfflineMetaBuffersList.push_back((uint32_t)metaBufIndex);
3314 } else {
3315 LOGE("could not find the input meta buf index, frame number %d",
3316 resultFrameNumber);
3317 }
3318 }
3319 obj->m_postprocessor.releaseOfflineBuffers(false);
3320 obj->m_postprocessor.releaseJpegJobData(job);
3321 free(job);
3322 }
3323
3324 obj->resetCppPerfParam();
3325 return;
3326 // }
3327 } else {
3328 LOGE("Null userdata in jpeg callback");
3329 }
3330 }
3331
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)3332 QCamera3PicChannel::QCamera3PicChannel(uint32_t cam_handle,
3333 uint32_t channel_handle,
3334 mm_camera_ops_t *cam_ops,
3335 channel_cb_routine cb_routine,
3336 channel_cb_buffer_err cb_buf_err,
3337 cam_padding_info_t *paddingInfo,
3338 void *userData,
3339 camera3_stream_t *stream,
3340 cam_feature_mask_t postprocess_mask,
3341 __unused bool is4KVideo,
3342 bool isInputStreamConfigured,
3343 QCamera3Channel *metadataChannel,
3344 uint32_t numBuffers) :
3345 QCamera3ProcessingChannel(cam_handle, channel_handle,
3346 cam_ops, cb_routine, cb_buf_err, paddingInfo, userData,
3347 stream, CAM_STREAM_TYPE_SNAPSHOT,
3348 postprocess_mask, metadataChannel, numBuffers),
3349 mNumSnapshotBufs(0),
3350 mInputBufferHint(isInputStreamConfigured),
3351 mYuvMemory(NULL),
3352 mFrameLen(0)
3353 {
3354 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
3355 m_max_pic_dim = hal_obj->calcMaxJpegDim();
3356 mYuvWidth = stream->width;
3357 mYuvHeight = stream->height;
3358 mStreamType = CAM_STREAM_TYPE_SNAPSHOT;
3359 mPendingLiveSnapshotFrames = 0;
3360 // Use same pixelformat for 4K video case
3361 mStreamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_SNAPSHOT,
3362 stream->width, stream->height);
3363 int32_t rc = m_postprocessor.initJpeg(jpegEvtHandle, &m_max_pic_dim, this);
3364 if (rc != 0) {
3365 LOGE("Init Postprocessor failed");
3366 }
3367 }
3368
3369 /*===========================================================================
3370 * FUNCTION : flush
3371 *
3372 * DESCRIPTION: flush pic channel, which will stop all processing within, including
3373 * the reprocessing channel in postprocessor and YUV stream.
3374 *
3375 * PARAMETERS : none
3376 *
3377 * RETURN : int32_t type of status
3378 * NO_ERROR -- success
3379 * none-zero failure code
3380 *==========================================================================*/
flush()3381 int32_t QCamera3PicChannel::flush()
3382 {
3383 int32_t rc = NO_ERROR;
3384 if(!m_bIsActive) {
3385 LOGE("Attempt to flush inactive channel");
3386 return NO_INIT;
3387 }
3388
3389 rc = m_postprocessor.flush();
3390 if (rc == 0) {
3391 LOGE("Postprocessor flush failed, rc = %d", rc);
3392 return rc;
3393 }
3394
3395 if (0 < mOfflineMetaMemory.getCnt()) {
3396 mOfflineMetaMemory.deallocate();
3397 }
3398 if (0 < mOfflineMemory.getCnt()) {
3399 mOfflineMemory.unregisterBuffers();
3400 }
3401 Mutex::Autolock lock(mFreeBuffersLock);
3402 mFreeBufferList.clear();
3403 for (uint32_t i = 0; i < mCamera3Stream->max_buffers; i++) {
3404 mFreeBufferList.push_back(i);
3405 }
3406 return rc;
3407 }
3408
3409
~QCamera3PicChannel()3410 QCamera3PicChannel::~QCamera3PicChannel()
3411 {
3412 }
3413
initialize(cam_is_type_t isType)3414 int32_t QCamera3PicChannel::initialize(cam_is_type_t isType)
3415 {
3416 int32_t rc = NO_ERROR;
3417 cam_dimension_t streamDim;
3418 cam_stream_type_t streamType;
3419 cam_format_t streamFormat;
3420
3421 if (NULL == mCamera3Stream) {
3422 LOGE("Camera stream uninitialized");
3423 return NO_INIT;
3424 }
3425
3426 if (1 <= m_numStreams) {
3427 // Only one stream per channel supported in v3 Hal
3428 return NO_ERROR;
3429 }
3430
3431 mIsType = isType;
3432 streamType = mStreamType;
3433 streamFormat = mStreamFormat;
3434 streamDim.width = (int32_t)mYuvWidth;
3435 streamDim.height = (int32_t)mYuvHeight;
3436
3437 mNumSnapshotBufs = mCamera3Stream->max_buffers;
3438 rc = QCamera3Channel::addStream(streamType, streamFormat, streamDim,
3439 ROTATE_0, (uint8_t)mCamera3Stream->max_buffers, mPostProcMask,
3440 mIsType);
3441
3442 if (NO_ERROR != rc) {
3443 LOGE("Initialize failed, rc = %d", rc);
3444 return rc;
3445 }
3446
3447 /* initialize offline meta memory for input reprocess */
3448 rc = QCamera3ProcessingChannel::initialize(isType);
3449 if (NO_ERROR != rc) {
3450 LOGE("Processing Channel initialize failed, rc = %d",
3451 rc);
3452 }
3453
3454 return rc;
3455 }
3456
3457 /*===========================================================================
3458 * FUNCTION : request
3459 *
3460 * DESCRIPTION: handle the request - either with an input buffer or a direct
3461 * output request
3462 *
3463 * PARAMETERS :
3464 * @buffer : pointer to the output buffer
3465 * @frameNumber : frame number of the request
3466 * @pInputBuffer : pointer to input buffer if an input request
3467 * @metadata : parameters associated with the request
3468 *
3469 * RETURN : 0 on a success start of capture
3470 * -EINVAL on invalid input
3471 * -ENODEV on serious error
3472 *==========================================================================*/
request(buffer_handle_t * buffer,uint32_t frameNumber,camera3_stream_buffer_t * pInputBuffer,metadata_buffer_t * metadata,int & indexUsed)3473 int32_t QCamera3PicChannel::request(buffer_handle_t *buffer,
3474 uint32_t frameNumber,
3475 camera3_stream_buffer_t *pInputBuffer,
3476 metadata_buffer_t *metadata, int &indexUsed)
3477 {
3478 ATRACE_CALL();
3479 //FIX ME: Return buffer back in case of failures below.
3480
3481 int32_t rc = NO_ERROR;
3482
3483 reprocess_config_t reproc_cfg;
3484 cam_dimension_t dim;
3485 memset(&reproc_cfg, 0, sizeof(reprocess_config_t));
3486 //make sure to set the correct input stream dim in case of YUV size override
3487 //and recalculate the plane info
3488 dim.width = (int32_t)mYuvWidth;
3489 dim.height = (int32_t)mYuvHeight;
3490 setReprocConfig(reproc_cfg, pInputBuffer, metadata, mStreamFormat, dim);
3491
3492 // Picture stream has already been started before any request comes in
3493 if (!m_bIsActive) {
3494 LOGE("Channel not started!!");
3495 return NO_INIT;
3496 }
3497
3498 int index = mMemory.getMatchBufIndex((void*)buffer);
3499
3500 if(index < 0) {
3501 rc = registerBuffer(buffer, mIsType);
3502 if (NO_ERROR != rc) {
3503 LOGE("On-the-fly buffer registration failed %d",
3504 rc);
3505 return rc;
3506 }
3507
3508 index = mMemory.getMatchBufIndex((void*)buffer);
3509 if (index < 0) {
3510 LOGE("Could not find object among registered buffers");
3511 return DEAD_OBJECT;
3512 }
3513 }
3514 LOGD("buffer index %d, frameNumber: %u", index, frameNumber);
3515
3516 rc = mMemory.markFrameNumber((uint32_t)index, frameNumber);
3517
3518 // Start postprocessor
3519 startPostProc(reproc_cfg);
3520
3521 // Only set the perf mode for online cpp processing
3522 if (reproc_cfg.reprocess_type == REPROCESS_TYPE_NONE) {
3523 setCppPerfParam();
3524 }
3525
3526 // Queue jpeg settings
3527 rc = queueJpegSetting((uint32_t)index, metadata);
3528
3529 if (pInputBuffer == NULL) {
3530 Mutex::Autolock lock(mFreeBuffersLock);
3531 uint32_t bufIdx;
3532 if (mFreeBufferList.empty()) {
3533 rc = mYuvMemory->allocateOne(mFrameLen);
3534 if (rc < 0) {
3535 LOGE("Failed to allocate heap buffer. Fatal");
3536 return rc;
3537 } else {
3538 bufIdx = (uint32_t)rc;
3539 }
3540 } else {
3541 List<uint32_t>::iterator it = mFreeBufferList.begin();
3542 bufIdx = *it;
3543 mFreeBufferList.erase(it);
3544 }
3545 mYuvMemory->markFrameNumber(bufIdx, frameNumber);
3546 mStreams[0]->bufDone(bufIdx);
3547 indexUsed = bufIdx;
3548 } else {
3549 qcamera_fwk_input_pp_data_t *src_frame = NULL;
3550 src_frame = (qcamera_fwk_input_pp_data_t *)calloc(1,
3551 sizeof(qcamera_fwk_input_pp_data_t));
3552 if (src_frame == NULL) {
3553 LOGE("No memory for src frame");
3554 return NO_MEMORY;
3555 }
3556 rc = setFwkInputPPData(src_frame, pInputBuffer, &reproc_cfg, metadata,
3557 NULL /*fwk output buffer*/, frameNumber);
3558 if (NO_ERROR != rc) {
3559 LOGE("Error %d while setting framework input PP data", rc);
3560 free(src_frame);
3561 return rc;
3562 }
3563 LOGH("Post-process started");
3564 m_postprocessor.processData(src_frame);
3565 }
3566 return rc;
3567 }
3568
3569
3570
3571 /*===========================================================================
3572 * FUNCTION : dataNotifyCB
3573 *
3574 * DESCRIPTION: Channel Level callback used for super buffer data notify.
3575 * This function is registered with mm-camera-interface to handle
3576 * data notify
3577 *
3578 * PARAMETERS :
3579 * @recvd_frame : stream frame received
3580 * userdata : user data ptr
3581 *
3582 * RETURN : none
3583 *==========================================================================*/
dataNotifyCB(mm_camera_super_buf_t * recvd_frame,void * userdata)3584 void QCamera3PicChannel::dataNotifyCB(mm_camera_super_buf_t *recvd_frame,
3585 void *userdata)
3586 {
3587 ATRACE_CALL();
3588 LOGD("E\n");
3589 QCamera3PicChannel *channel = (QCamera3PicChannel *)userdata;
3590
3591 if (channel == NULL) {
3592 LOGE("invalid channel pointer");
3593 return;
3594 }
3595
3596 if(channel->m_numStreams != 1) {
3597 LOGE("Error: Bug: This callback assumes one stream per channel");
3598 return;
3599 }
3600
3601
3602 if(channel->mStreams[0] == NULL) {
3603 LOGE("Error: Invalid Stream object");
3604 return;
3605 }
3606
3607 channel->QCamera3PicChannel::streamCbRoutine(recvd_frame, channel->mStreams[0]);
3608
3609 LOGD("X\n");
3610 return;
3611 }
3612
3613 /*===========================================================================
3614 * FUNCTION : streamCbRoutine
3615 *
3616 * DESCRIPTION:
3617 *
3618 * PARAMETERS :
3619 * @super_frame : the super frame with filled buffer
3620 * @stream : stream on which the buffer was requested and filled
3621 *
3622 * RETURN : none
3623 *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream)3624 void QCamera3PicChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
3625 QCamera3Stream *stream)
3626 {
3627 ATRACE_CALL();
3628 //TODO
3629 //Used only for getting YUV. Jpeg callback will be sent back from channel
3630 //directly to HWI. Refer to func jpegEvtHandle
3631
3632 //Got the yuv callback. Calling yuv callback handler in PostProc
3633 uint8_t frameIndex;
3634 mm_camera_super_buf_t* frame = NULL;
3635 cam_dimension_t dim;
3636 cam_frame_len_offset_t offset;
3637
3638 memset(&dim, 0, sizeof(dim));
3639 memset(&offset, 0, sizeof(cam_frame_len_offset_t));
3640
3641 if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) {
3642 LOGE("Error with the stream callback");
3643 return;
3644 }
3645
3646 frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
3647 LOGD("recvd buf_idx: %u for further processing",
3648 (uint32_t)frameIndex);
3649 if(frameIndex >= mNumSnapshotBufs) {
3650 LOGE("Error, Invalid index for buffer");
3651 if(stream) {
3652 Mutex::Autolock lock(mFreeBuffersLock);
3653 mFreeBufferList.push_back(frameIndex);
3654 stream->bufDone(frameIndex);
3655 }
3656 return;
3657 }
3658
3659 frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
3660 if (frame == NULL) {
3661 LOGE("Error allocating memory to save received_frame structure.");
3662 if(stream) {
3663 Mutex::Autolock lock(mFreeBuffersLock);
3664 mFreeBufferList.push_back(frameIndex);
3665 stream->bufDone(frameIndex);
3666 }
3667 return;
3668 }
3669 *frame = *super_frame;
3670 stream->getFrameDimension(dim);
3671 stream->getFrameOffset(offset);
3672 dumpYUV(frame->bufs[0], dim, offset, QCAMERA_DUMP_FRM_INPUT_REPROCESS);
3673
3674 if (IS_BUFFER_ERROR(super_frame->bufs[0]->flags)) {
3675 mChannelCbBufErr(this, mYuvMemory->getFrameNumber(frameIndex),
3676 CAMERA3_BUFFER_STATUS_ERROR, mUserData);
3677 }
3678
3679 m_postprocessor.processData(frame);
3680 free(super_frame);
3681 return;
3682 }
3683
getStreamBufs(uint32_t len)3684 QCamera3StreamMem* QCamera3PicChannel::getStreamBufs(uint32_t len)
3685 {
3686 mYuvMemory = new QCamera3StreamMem(mCamera3Stream->max_buffers, false);
3687 if (!mYuvMemory) {
3688 LOGE("unable to create metadata memory");
3689 return NULL;
3690 }
3691 mFrameLen = len;
3692
3693 return mYuvMemory;
3694 }
3695
putStreamBufs()3696 void QCamera3PicChannel::putStreamBufs()
3697 {
3698 QCamera3ProcessingChannel::putStreamBufs();
3699
3700 mYuvMemory->deallocate();
3701 delete mYuvMemory;
3702 mYuvMemory = NULL;
3703 mFreeBufferList.clear();
3704 }
3705
queueJpegSetting(uint32_t index,metadata_buffer_t * metadata)3706 int32_t QCamera3PicChannel::queueJpegSetting(uint32_t index, metadata_buffer_t *metadata)
3707 {
3708 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
3709 jpeg_settings_t *settings =
3710 (jpeg_settings_t *)malloc(sizeof(jpeg_settings_t));
3711
3712 if (!settings) {
3713 LOGE("out of memory allocating jpeg_settings");
3714 return -ENOMEM;
3715 }
3716
3717 memset(settings, 0, sizeof(jpeg_settings_t));
3718
3719 settings->out_buf_index = index;
3720
3721 settings->jpeg_orientation = 0;
3722 IF_META_AVAILABLE(int32_t, orientation, CAM_INTF_META_JPEG_ORIENTATION, metadata) {
3723 settings->jpeg_orientation = *orientation;
3724 }
3725
3726 settings->jpeg_quality = 85;
3727 IF_META_AVAILABLE(uint32_t, quality1, CAM_INTF_META_JPEG_QUALITY, metadata) {
3728 settings->jpeg_quality = (uint8_t) *quality1;
3729 }
3730
3731 IF_META_AVAILABLE(uint32_t, quality2, CAM_INTF_META_JPEG_THUMB_QUALITY, metadata) {
3732 settings->jpeg_thumb_quality = (uint8_t) *quality2;
3733 }
3734
3735 IF_META_AVAILABLE(cam_dimension_t, dimension, CAM_INTF_META_JPEG_THUMB_SIZE, metadata) {
3736 settings->thumbnail_size = *dimension;
3737 }
3738
3739 settings->gps_timestamp_valid = 0;
3740 IF_META_AVAILABLE(int64_t, timestamp, CAM_INTF_META_JPEG_GPS_TIMESTAMP, metadata) {
3741 settings->gps_timestamp = *timestamp;
3742 settings->gps_timestamp_valid = 1;
3743 }
3744
3745 settings->gps_coordinates_valid = 0;
3746 IF_META_AVAILABLE(double, coordinates, CAM_INTF_META_JPEG_GPS_COORDINATES, metadata) {
3747 memcpy(settings->gps_coordinates, coordinates, 3*sizeof(double));
3748 settings->gps_coordinates_valid = 1;
3749 }
3750
3751 IF_META_AVAILABLE(uint8_t, proc_methods, CAM_INTF_META_JPEG_GPS_PROC_METHODS, metadata) {
3752 memset(settings->gps_processing_method, 0,
3753 sizeof(settings->gps_processing_method));
3754 strlcpy(settings->gps_processing_method, (const char *)proc_methods,
3755 sizeof(settings->gps_processing_method));
3756 }
3757
3758 // Image description
3759 const char *eepromVersion = hal_obj->getEepromVersionInfo();
3760 const uint32_t *ldafCalib = hal_obj->getLdafCalib();
3761 if ((eepromVersion && strlen(eepromVersion)) ||
3762 ldafCalib) {
3763 int len = 0;
3764 settings->image_desc_valid = true;
3765 if (eepromVersion && strlen(eepromVersion)) {
3766 len = snprintf(settings->image_desc, sizeof(settings->image_desc),
3767 "M:%s ", eepromVersion);
3768 }
3769 if (ldafCalib) {
3770 snprintf(settings->image_desc + len,
3771 sizeof(settings->image_desc) - len, "L:%u-%u",
3772 ldafCalib[0], ldafCalib[1]);
3773 }
3774 }
3775
3776 return m_postprocessor.processJpegSettingData(settings);
3777 }
3778
3779
overrideYuvSize(uint32_t width,uint32_t height)3780 void QCamera3PicChannel::overrideYuvSize(uint32_t width, uint32_t height)
3781 {
3782 mYuvWidth = width;
3783 mYuvHeight = height;
3784 }
3785
3786 /*===========================================================================
3787 * FUNCTION : getReprocessType
3788 *
3789 * DESCRIPTION: get the type of reprocess output supported by this channel
3790 *
3791 * PARAMETERS : NONE
3792 *
3793 * RETURN : reprocess_type_t : type of reprocess
3794 *==========================================================================*/
getReprocessType()3795 reprocess_type_t QCamera3PicChannel::getReprocessType()
3796 {
3797 /* a picture channel could either use the postprocessor for reprocess+jpeg
3798 or only for reprocess */
3799 reprocess_type_t expectedReprocess;
3800 if (mPostProcMask == CAM_QCOM_FEATURE_NONE || mInputBufferHint) {
3801 expectedReprocess = REPROCESS_TYPE_JPEG;
3802 } else {
3803 expectedReprocess = REPROCESS_TYPE_NONE;
3804 }
3805 LOGH("expectedReprocess from Pic Channel is %d", expectedReprocess);
3806 return expectedReprocess;
3807 }
3808
3809 /*===========================================================================
3810 * FUNCTION : setCppPerfParam
3811 *
3812 * DESCRIPTION: set the performance related stream params
3813 *
3814 * PARAMETERS : NONE
3815 *
3816 * RETURN : NONE
3817 *==========================================================================*/
3818
setCppPerfParam()3819 void QCamera3PicChannel::setCppPerfParam()
3820 {
3821 if (mPendingLiveSnapshotFrames == 0) {
3822 int32_t rc = 0;
3823 QCamera3Stream *pStream = mStreams[0];
3824 cam_stream_parm_buffer_t param;
3825 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t));
3826 param.type = CAM_STREAM_PARAM_TYPE_REQUEST_OPS_MODE;
3827 param.perf_mode = CAM_PERF_SET;
3828 rc = pStream->setParameter(param);
3829 if (rc != NO_ERROR) {
3830 LOGE("%s: setParameter for CAM_PERF_SET failed",
3831 __func__);
3832 }
3833 }
3834 mPendingLiveSnapshotFrames++;
3835 }
3836
3837 /*===========================================================================
3838 * FUNCTION : resetCppPerfParam
3839 *
3840 * DESCRIPTION: reset the performance related stream params
3841 *
3842 * PARAMETERS : NONE
3843 *
3844 * RETURN : NONE
3845 *==========================================================================*/
3846
resetCppPerfParam()3847 void QCamera3PicChannel::resetCppPerfParam()
3848 {
3849 if (mPendingLiveSnapshotFrames > 0) {
3850 int32_t rc = NO_ERROR;
3851 QCamera3Stream *pStream = mStreams[0];
3852 cam_stream_parm_buffer_t param;
3853 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t));
3854 param.type = CAM_STREAM_PARAM_TYPE_REQUEST_OPS_MODE;
3855 param.perf_mode = CAM_PERF_RESET;
3856 rc = pStream->setParameter(param);
3857 if (rc != NO_ERROR) {
3858 LOGE("%s: setParameter for CAM_PERF_RESET failed",
3859 __func__);
3860 }
3861 mPendingLiveSnapshotFrames--;
3862 }
3863 }
3864
3865 /*===========================================================================
3866 * FUNCTION : timeoutFrame
3867 *
3868 * DESCRIPTION: Method to indicate to channel that a given frame has take too
3869 * long to be generated
3870 *
3871 * PARAMETERS : framenumber indicating the framenumber of the buffer timingout
3872 *
3873 * RETURN : int32_t type of status
3874 * NO_ERROR -- success
3875 * none-zero failure code
3876 *==========================================================================*/
timeoutFrame(uint32_t frameNumber)3877 int32_t QCamera3PicChannel::timeoutFrame(uint32_t frameNumber)
3878 {
3879 int32_t bufIdx;
3880
3881 bufIdx = mYuvMemory->getBufferIndex(frameNumber);
3882
3883 if (bufIdx < 0) {
3884 ALOGE("%s: Buffer not found for frame:%d", __func__, frameNumber);
3885 return -1;
3886 }
3887
3888 mStreams[0]->timeoutFrame(bufIdx);
3889
3890 return NO_ERROR;
3891 }
3892
3893 /*===========================================================================
3894 * FUNCTION : QCamera3ReprocessChannel
3895 *
3896 * DESCRIPTION: constructor of QCamera3ReprocessChannel
3897 *
3898 * PARAMETERS :
3899 * @cam_handle : camera handle
3900 * @cam_ops : ptr to camera ops table
3901 * @pp_mask : post-proccess feature mask
3902 *
3903 * RETURN : none
3904 *==========================================================================*/
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)3905 QCamera3ReprocessChannel::QCamera3ReprocessChannel(uint32_t cam_handle,
3906 uint32_t channel_handle,
3907 mm_camera_ops_t *cam_ops,
3908 channel_cb_routine cb_routine,
3909 channel_cb_buffer_err cb_buf_err,
3910 cam_padding_info_t *paddingInfo,
3911 cam_feature_mask_t postprocess_mask,
3912 void *userData, void *ch_hdl) :
3913 /* In case of framework reprocessing, pproc and jpeg operations could be
3914 * parallelized by allowing 1 extra buffer for reprocessing output:
3915 * ch_hdl->getNumBuffers() + 1 */
3916 QCamera3Channel(cam_handle, channel_handle, cam_ops, cb_routine, cb_buf_err, paddingInfo,
3917 postprocess_mask, userData,
3918 ((QCamera3ProcessingChannel *)ch_hdl)->getNumBuffers()
3919 + (MAX_REPROCESS_PIPELINE_STAGES - 1)),
3920 inputChHandle(ch_hdl),
3921 mOfflineBuffersIndex(-1),
3922 mFrameLen(0),
3923 mReprocessType(REPROCESS_TYPE_NONE),
3924 m_pSrcChannel(NULL),
3925 m_pMetaChannel(NULL),
3926 mMemory(NULL),
3927 mGrallocMemory(0),
3928 mReprocessPerfMode(false)
3929 {
3930 memset(mSrcStreamHandles, 0, sizeof(mSrcStreamHandles));
3931 mOfflineBuffersIndex = mNumBuffers -1;
3932 mOfflineMetaIndex = (int32_t) (2*mNumBuffers -1);
3933 }
3934
3935
3936 /*===========================================================================
3937 * FUNCTION : QCamera3ReprocessChannel
3938 *
3939 * DESCRIPTION: constructor of QCamera3ReprocessChannel
3940 *
3941 * PARAMETERS :
3942 * @cam_handle : camera handle
3943 * @cam_ops : ptr to camera ops table
3944 * @pp_mask : post-proccess feature mask
3945 *
3946 * RETURN : none
3947 *==========================================================================*/
initialize(cam_is_type_t isType)3948 int32_t QCamera3ReprocessChannel::initialize(cam_is_type_t isType)
3949 {
3950 int32_t rc = NO_ERROR;
3951 mm_camera_channel_attr_t attr;
3952
3953 memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
3954 attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS;
3955 attr.max_unmatched_frames = 1;
3956
3957 m_handle = m_camOps->add_channel(m_camHandle,
3958 &attr,
3959 NULL,
3960 this);
3961 if (m_handle == 0) {
3962 LOGE("Add channel failed");
3963 return UNKNOWN_ERROR;
3964 }
3965
3966 mIsType = isType;
3967 return rc;
3968 }
3969
3970 /*===========================================================================
3971 * FUNCTION : registerBuffer
3972 *
3973 * DESCRIPTION: register streaming buffer to the channel object
3974 *
3975 * PARAMETERS :
3976 * @buffer : buffer to be registered
3977 * @isType : the image stabilization type for the buffer
3978 *
3979 * RETURN : int32_t type of status
3980 * NO_ERROR -- success
3981 * none-zero failure code
3982 *==========================================================================*/
registerBuffer(buffer_handle_t * buffer,cam_is_type_t isType)3983 int32_t QCamera3ReprocessChannel::registerBuffer(buffer_handle_t *buffer,
3984 cam_is_type_t isType)
3985 {
3986 ATRACE_CALL();
3987 int rc = 0;
3988 mIsType = isType;
3989 cam_stream_type_t streamType;
3990
3991 if (buffer == NULL) {
3992 LOGE("Error: Cannot register a NULL buffer");
3993 return BAD_VALUE;
3994 }
3995
3996 if ((uint32_t)mGrallocMemory.getCnt() > (mNumBuffers - 1)) {
3997 LOGE("Trying to register more buffers than initially requested");
3998 return BAD_VALUE;
3999 }
4000
4001 if (0 == m_numStreams) {
4002 rc = initialize(mIsType);
4003 if (rc != NO_ERROR) {
4004 LOGE("Couldn't initialize camera stream %d",
4005 rc);
4006 return rc;
4007 }
4008 }
4009
4010 streamType = mStreams[0]->getMyType();
4011 rc = mGrallocMemory.registerBuffer(buffer, streamType);
4012 if (ALREADY_EXISTS == rc) {
4013 return NO_ERROR;
4014 } else if (NO_ERROR != rc) {
4015 LOGE("Buffer %p couldn't be registered %d", buffer, rc);
4016 return rc;
4017 }
4018
4019 return rc;
4020 }
4021
4022 /*===========================================================================
4023 * FUNCTION : QCamera3ReprocessChannel
4024 *
4025 * DESCRIPTION: constructor of QCamera3ReprocessChannel
4026 *
4027 * PARAMETERS :
4028 * @cam_handle : camera handle
4029 * @cam_ops : ptr to camera ops table
4030 * @pp_mask : post-proccess feature mask
4031 *
4032 * RETURN : none
4033 *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream)4034 void QCamera3ReprocessChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
4035 QCamera3Stream *stream)
4036 {
4037 //Got the pproc data callback. Now send to jpeg encoding
4038 uint8_t frameIndex;
4039 uint32_t resultFrameNumber;
4040 ATRACE_CALL();
4041 mm_camera_super_buf_t* frame = NULL;
4042 QCamera3ProcessingChannel *obj = (QCamera3ProcessingChannel *)inputChHandle;
4043 cam_dimension_t dim;
4044 cam_frame_len_offset_t offset;
4045
4046 memset(&dim, 0, sizeof(dim));
4047 memset(&offset, 0, sizeof(cam_frame_len_offset_t));
4048 if(!super_frame) {
4049 LOGE("Invalid Super buffer");
4050 return;
4051 }
4052
4053 if(super_frame->num_bufs != 1) {
4054 LOGE("Multiple streams are not supported");
4055 return;
4056 }
4057 if(super_frame->bufs[0] == NULL ) {
4058 LOGE("Error, Super buffer frame does not contain valid buffer");
4059 return;
4060 }
4061 frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
4062
4063
4064 if (mReprocessType == REPROCESS_TYPE_JPEG) {
4065 resultFrameNumber = mMemory->getFrameNumber(frameIndex);
4066 frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
4067 if (frame == NULL) {
4068 LOGE("Error allocating memory to save received_frame structure.");
4069 if(stream) {
4070 stream->bufDone(frameIndex);
4071 }
4072 return;
4073 }
4074 LOGI("bufIndex: %u recvd from post proc",
4075 (uint32_t)frameIndex);
4076 *frame = *super_frame;
4077
4078 stream->getFrameDimension(dim);
4079 stream->getFrameOffset(offset);
4080 dumpYUV(frame->bufs[0], dim, offset, QCAMERA_DUMP_FRM_SNAPSHOT);
4081 /* Since reprocessing is done, send the callback to release the input buffer */
4082 // Release offline buffers.
4083 obj->releaseOfflineMemory(resultFrameNumber);
4084 if (mChannelCB) {
4085 mChannelCB(NULL, NULL, resultFrameNumber, true, mUserData);
4086 }
4087 obj->m_postprocessor.processPPData(frame);
4088 } else {
4089 buffer_handle_t *resultBuffer;
4090 frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
4091 resultBuffer = (buffer_handle_t *)mGrallocMemory.getBufferHandle(frameIndex);
4092 resultFrameNumber = mGrallocMemory.getFrameNumber(frameIndex);
4093 int32_t rc = stream->bufRelease(frameIndex);
4094 if (NO_ERROR != rc) {
4095 LOGE("Error %d releasing stream buffer %d",
4096 rc, frameIndex);
4097 }
4098 rc = mGrallocMemory.unregisterBuffer(frameIndex);
4099 if (NO_ERROR != rc) {
4100 LOGE("Error %d unregistering stream buffer %d",
4101 rc, frameIndex);
4102 }
4103 obj->reprocessCbRoutine(resultBuffer, resultFrameNumber);
4104
4105 obj->m_postprocessor.releaseOfflineBuffers(false);
4106 qcamera_hal3_pp_data_t *pp_job = obj->m_postprocessor.dequeuePPJob(resultFrameNumber);
4107 if (pp_job != NULL) {
4108 obj->m_postprocessor.releasePPJobData(pp_job);
4109 }
4110 free(pp_job);
4111 }
4112 resetToCamPerfNormal(resultFrameNumber);
4113 free(super_frame);
4114 return;
4115 }
4116
4117 /*===========================================================================
4118 * FUNCTION : resetToCamPerfNormal
4119 *
4120 * DESCRIPTION: Set the perf mode to normal if all the priority frames
4121 * have been reprocessed
4122 *
4123 * PARAMETERS :
4124 * @frameNumber: Frame number of the reprocess completed frame
4125 *
4126 * RETURN : QCamera3StreamMem *
4127 *==========================================================================*/
resetToCamPerfNormal(uint32_t frameNumber)4128 int32_t QCamera3ReprocessChannel::resetToCamPerfNormal(uint32_t frameNumber)
4129 {
4130 int32_t rc = NO_ERROR;
4131 bool resetToPerfNormal = false;
4132 {
4133 Mutex::Autolock lock(mPriorityFramesLock);
4134 /* remove the priority frame number from the list */
4135 for (size_t i = 0; i < mPriorityFrames.size(); i++) {
4136 if (mPriorityFrames[i] == frameNumber) {
4137 mPriorityFrames.removeAt(i);
4138 }
4139 }
4140 /* reset the perf mode if pending priority frame list is empty */
4141 if (mReprocessPerfMode && mPriorityFrames.empty()) {
4142 resetToPerfNormal = true;
4143 }
4144 }
4145 if (resetToPerfNormal) {
4146 QCamera3Stream *pStream = mStreams[0];
4147 cam_stream_parm_buffer_t param;
4148 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t));
4149
4150 param.type = CAM_STREAM_PARAM_TYPE_REQUEST_OPS_MODE;
4151 param.perf_mode = CAM_PERF_NORMAL;
4152 rc = pStream->setParameter(param);
4153 {
4154 Mutex::Autolock lock(mPriorityFramesLock);
4155 mReprocessPerfMode = false;
4156 }
4157 }
4158 return rc;
4159 }
4160
4161 /*===========================================================================
4162 * FUNCTION : getStreamBufs
4163 *
4164 * DESCRIPTION: register the buffers of the reprocess channel
4165 *
4166 * PARAMETERS : none
4167 *
4168 * RETURN : QCamera3StreamMem *
4169 *==========================================================================*/
getStreamBufs(uint32_t len)4170 QCamera3StreamMem* QCamera3ReprocessChannel::getStreamBufs(uint32_t len)
4171 {
4172 if (mReprocessType == REPROCESS_TYPE_JPEG) {
4173 mMemory = new QCamera3StreamMem(mNumBuffers, false);
4174 if (!mMemory) {
4175 LOGE("unable to create reproc memory");
4176 return NULL;
4177 }
4178 mFrameLen = len;
4179 return mMemory;
4180 }
4181 return &mGrallocMemory;
4182 }
4183
4184 /*===========================================================================
4185 * FUNCTION : putStreamBufs
4186 *
4187 * DESCRIPTION: release the reprocess channel buffers
4188 *
4189 * PARAMETERS : none
4190 *
4191 * RETURN :
4192 *==========================================================================*/
putStreamBufs()4193 void QCamera3ReprocessChannel::putStreamBufs()
4194 {
4195 if (mReprocessType == REPROCESS_TYPE_JPEG) {
4196 mMemory->deallocate();
4197 delete mMemory;
4198 mMemory = NULL;
4199 mFreeBufferList.clear();
4200 } else {
4201 mGrallocMemory.unregisterBuffers();
4202 }
4203 }
4204
4205 /*===========================================================================
4206 * FUNCTION : ~QCamera3ReprocessChannel
4207 *
4208 * DESCRIPTION: destructor of QCamera3ReprocessChannel
4209 *
4210 * PARAMETERS : none
4211 *
4212 * RETURN : none
4213 *==========================================================================*/
~QCamera3ReprocessChannel()4214 QCamera3ReprocessChannel::~QCamera3ReprocessChannel()
4215 {
4216 destroy();
4217
4218 if (m_handle) {
4219 m_camOps->delete_channel(m_camHandle, m_handle);
4220 LOGD("deleting channel %d", m_handle);
4221 m_handle = 0;
4222 }
4223 }
4224
4225 /*===========================================================================
4226 * FUNCTION : start
4227 *
4228 * DESCRIPTION: start reprocess channel.
4229 *
4230 * PARAMETERS :
4231 *
4232 * RETURN : int32_t type of status
4233 * NO_ERROR -- success
4234 * none-zero failure code
4235 *==========================================================================*/
start()4236 int32_t QCamera3ReprocessChannel::start()
4237 {
4238 ATRACE_CALL();
4239 int32_t rc = NO_ERROR;
4240
4241 rc = QCamera3Channel::start();
4242
4243 if (rc == NO_ERROR) {
4244 rc = m_camOps->start_channel(m_camHandle, m_handle);
4245
4246 // Check failure
4247 if (rc != NO_ERROR) {
4248 LOGE("start_channel failed %d", rc);
4249 QCamera3Channel::stop();
4250 }
4251 }
4252 return rc;
4253 }
4254
4255 /*===========================================================================
4256 * FUNCTION : stop
4257 *
4258 * DESCRIPTION: stop reprocess channel.
4259 *
4260 * PARAMETERS : none
4261 *
4262 * RETURN : int32_t type of status
4263 * NO_ERROR -- success
4264 * none-zero failure code
4265 *==========================================================================*/
stop()4266 int32_t QCamera3ReprocessChannel::stop()
4267 {
4268 ATRACE_CALL();
4269 int32_t rc = NO_ERROR;
4270
4271 rc = QCamera3Channel::stop();
4272 unmapOfflineBuffers(true);
4273
4274 rc |= m_camOps->stop_channel(m_camHandle, m_handle);
4275
4276 return rc;
4277 }
4278
4279 /*===========================================================================
4280 * FUNCTION : getStreamBySrcHandle
4281 *
4282 * DESCRIPTION: find reprocess stream by its source stream handle
4283 *
4284 * PARAMETERS :
4285 * @srcHandle : source stream handle
4286 *
4287 * RETURN : ptr to reprocess stream if found. NULL if not found
4288 *==========================================================================*/
getStreamBySrcHandle(uint32_t srcHandle)4289 QCamera3Stream * QCamera3ReprocessChannel::getStreamBySrcHandle(uint32_t srcHandle)
4290 {
4291 QCamera3Stream *pStream = NULL;
4292
4293 for (uint32_t i = 0; i < m_numStreams; i++) {
4294 if (mSrcStreamHandles[i] == srcHandle) {
4295 pStream = mStreams[i];
4296 break;
4297 }
4298 }
4299 return pStream;
4300 }
4301
4302 /*===========================================================================
4303 * FUNCTION : getSrcStreamBySrcHandle
4304 *
4305 * DESCRIPTION: find source stream by source stream handle
4306 *
4307 * PARAMETERS :
4308 * @srcHandle : source stream handle
4309 *
4310 * RETURN : ptr to reprocess stream if found. NULL if not found
4311 *==========================================================================*/
getSrcStreamBySrcHandle(uint32_t srcHandle)4312 QCamera3Stream * QCamera3ReprocessChannel::getSrcStreamBySrcHandle(uint32_t srcHandle)
4313 {
4314 QCamera3Stream *pStream = NULL;
4315
4316 if (NULL == m_pSrcChannel) {
4317 return NULL;
4318 }
4319
4320 for (uint32_t i = 0; i < m_numStreams; i++) {
4321 if (mSrcStreamHandles[i] == srcHandle) {
4322 pStream = m_pSrcChannel->getStreamByIndex(i);
4323 break;
4324 }
4325 }
4326 return pStream;
4327 }
4328
4329 /*===========================================================================
4330 * FUNCTION : unmapOfflineBuffers
4331 *
4332 * DESCRIPTION: Unmaps offline buffers
4333 *
4334 * PARAMETERS : none
4335 *
4336 * RETURN : int32_t type of status
4337 * NO_ERROR -- success
4338 * none-zero failure code
4339 *==========================================================================*/
unmapOfflineBuffers(bool all)4340 int32_t QCamera3ReprocessChannel::unmapOfflineBuffers(bool all)
4341 {
4342 int rc = NO_ERROR;
4343 Mutex::Autolock l(mOfflineBuffersLock);
4344 if (!mOfflineBuffers.empty()) {
4345 QCamera3Stream *stream = NULL;
4346 List<OfflineBuffer>::iterator it = mOfflineBuffers.begin();
4347 for (; it != mOfflineBuffers.end(); it++) {
4348 stream = (*it).stream;
4349 if (NULL != stream) {
4350 rc = stream->unmapBuf((*it).type,
4351 (*it).index,
4352 -1);
4353 if (NO_ERROR != rc) {
4354 LOGE("Error during offline buffer unmap %d",
4355 rc);
4356 }
4357 LOGD("Unmapped buffer with index %d", (*it).index);
4358 }
4359 if (!all) {
4360 mOfflineBuffers.erase(it);
4361 break;
4362 }
4363 }
4364 if (all) {
4365 mOfflineBuffers.clear();
4366 }
4367 }
4368
4369 if (!mOfflineMetaBuffers.empty()) {
4370 QCamera3Stream *stream = NULL;
4371 List<OfflineBuffer>::iterator it = mOfflineMetaBuffers.begin();
4372 for (; it != mOfflineMetaBuffers.end(); it++) {
4373 stream = (*it).stream;
4374 if (NULL != stream) {
4375 rc = stream->unmapBuf((*it).type,
4376 (*it).index,
4377 -1);
4378 if (NO_ERROR != rc) {
4379 LOGE("Error during offline buffer unmap %d",
4380 rc);
4381 }
4382 LOGD("Unmapped meta buffer with index %d", (*it).index);
4383 }
4384 if (!all) {
4385 mOfflineMetaBuffers.erase(it);
4386 break;
4387 }
4388 }
4389 if (all) {
4390 mOfflineMetaBuffers.clear();
4391 }
4392 }
4393 return rc;
4394 }
4395
4396 /*===========================================================================
4397 * FUNCTION : bufDone
4398 *
4399 * DESCRIPTION: Return reprocess stream buffer to free buffer list.
4400 * Note that this function doesn't queue buffer back to kernel.
4401 * It's up to doReprocessOffline to do that instead.
4402 * PARAMETERS :
4403 * @recvd_frame : stream buf frame to be returned
4404 *
4405 * RETURN : int32_t type of status
4406 * NO_ERROR -- success
4407 * none-zero failure code
4408 *==========================================================================*/
bufDone(mm_camera_super_buf_t * recvd_frame)4409 int32_t QCamera3ReprocessChannel::bufDone(mm_camera_super_buf_t *recvd_frame)
4410 {
4411 int rc = NO_ERROR;
4412 if (recvd_frame && recvd_frame->num_bufs == 1) {
4413 Mutex::Autolock lock(mFreeBuffersLock);
4414 uint32_t buf_idx = recvd_frame->bufs[0]->buf_idx;
4415 mFreeBufferList.push_back(buf_idx);
4416
4417 } else {
4418 LOGE("Fatal. Not supposed to be here");
4419 rc = BAD_VALUE;
4420 }
4421
4422 return rc;
4423 }
4424
4425 /*===========================================================================
4426 * FUNCTION : overrideMetadata
4427 *
4428 * DESCRIPTION: Override metadata entry such as rotation, crop, and CDS info.
4429 *
4430 * PARAMETERS :
4431 * @frame : input frame from source stream
4432 * meta_buffer: metadata buffer
4433 * @metadata : corresponding metadata
4434 * @fwk_frame :
4435 *
4436 * RETURN : int32_t type of status
4437 * NO_ERROR -- success
4438 * none-zero failure code
4439 *==========================================================================*/
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)4440 int32_t QCamera3ReprocessChannel::overrideMetadata(qcamera_hal3_pp_buffer_t *pp_buffer,
4441 mm_camera_buf_def_t *meta_buffer, jpeg_settings_t *jpeg_settings,
4442 qcamera_fwk_input_pp_data_t &fwk_frame)
4443 {
4444 int32_t rc = NO_ERROR;
4445 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
4446 if ((NULL == meta_buffer) || (NULL == pp_buffer) || (NULL == pp_buffer->input) ||
4447 (NULL == hal_obj)) {
4448 return BAD_VALUE;
4449 }
4450
4451 metadata_buffer_t *meta = (metadata_buffer_t *)meta_buffer->buffer;
4452 mm_camera_super_buf_t *frame = pp_buffer->input;
4453 if (NULL == meta) {
4454 return BAD_VALUE;
4455 }
4456
4457 for (uint32_t i = 0; i < frame->num_bufs; i++) {
4458 QCamera3Stream *pStream = getStreamBySrcHandle(frame->bufs[i]->stream_id);
4459 QCamera3Stream *pSrcStream = getSrcStreamBySrcHandle(frame->bufs[i]->stream_id);
4460
4461 if (pStream != NULL && pSrcStream != NULL) {
4462 if (jpeg_settings) {
4463 // Find rotation info for reprocess stream
4464 cam_rotation_info_t rotation_info;
4465 memset(&rotation_info, 0, sizeof(rotation_info));
4466 if (jpeg_settings->jpeg_orientation == 0) {
4467 rotation_info.rotation = ROTATE_0;
4468 } else if (jpeg_settings->jpeg_orientation == 90) {
4469 rotation_info.rotation = ROTATE_90;
4470 } else if (jpeg_settings->jpeg_orientation == 180) {
4471 rotation_info.rotation = ROTATE_180;
4472 } else if (jpeg_settings->jpeg_orientation == 270) {
4473 rotation_info.rotation = ROTATE_270;
4474 }
4475 rotation_info.device_rotation = ROTATE_0;
4476 rotation_info.streamId = mStreams[0]->getMyServerID();
4477 ADD_SET_PARAM_ENTRY_TO_BATCH(meta, CAM_INTF_PARM_ROTATION, rotation_info);
4478 }
4479
4480 // Find and insert crop info for reprocess stream
4481 IF_META_AVAILABLE(cam_crop_data_t, crop_data, CAM_INTF_META_CROP_DATA, meta) {
4482 if (MAX_NUM_STREAMS > crop_data->num_of_streams) {
4483 for (int j = 0; j < crop_data->num_of_streams; j++) {
4484 if (crop_data->crop_info[j].stream_id ==
4485 pSrcStream->getMyServerID()) {
4486
4487 // Store crop/roi information for offline reprocess
4488 // in the reprocess stream slot
4489 crop_data->crop_info[crop_data->num_of_streams].crop =
4490 crop_data->crop_info[j].crop;
4491 crop_data->crop_info[crop_data->num_of_streams].roi_map =
4492 crop_data->crop_info[j].roi_map;
4493 crop_data->crop_info[crop_data->num_of_streams].stream_id =
4494 mStreams[0]->getMyServerID();
4495 crop_data->num_of_streams++;
4496
4497 LOGD("Reprocess stream server id: %d",
4498 mStreams[0]->getMyServerID());
4499 LOGD("Found offline reprocess crop %dx%d %dx%d",
4500 crop_data->crop_info[j].crop.left,
4501 crop_data->crop_info[j].crop.top,
4502 crop_data->crop_info[j].crop.width,
4503 crop_data->crop_info[j].crop.height);
4504 LOGD("Found offline reprocess roimap %dx%d %dx%d",
4505 crop_data->crop_info[j].roi_map.left,
4506 crop_data->crop_info[j].roi_map.top,
4507 crop_data->crop_info[j].roi_map.width,
4508 crop_data->crop_info[j].roi_map.height);
4509
4510 break;
4511 }
4512 }
4513 } else {
4514 LOGE("No space to add reprocess stream crop/roi information");
4515 }
4516 }
4517
4518 IF_META_AVAILABLE(cam_cds_data_t, cdsInfo, CAM_INTF_META_CDS_DATA, meta) {
4519 uint8_t cnt = cdsInfo->num_of_streams;
4520 if (cnt <= MAX_NUM_STREAMS) {
4521 cam_stream_cds_info_t repro_cds_info;
4522 memset(&repro_cds_info, 0, sizeof(repro_cds_info));
4523 repro_cds_info.stream_id = mStreams[0]->getMyServerID();
4524 for (size_t i = 0; i < cnt; i++) {
4525 if (cdsInfo->cds_info[i].stream_id ==
4526 pSrcStream->getMyServerID()) {
4527 repro_cds_info.cds_enable =
4528 cdsInfo->cds_info[i].cds_enable;
4529 break;
4530 }
4531 }
4532 cdsInfo->num_of_streams = 1;
4533 cdsInfo->cds_info[0] = repro_cds_info;
4534 } else {
4535 LOGE("No space to add reprocess stream cds information");
4536 }
4537 }
4538
4539 fwk_frame.input_buffer = *frame->bufs[i];
4540 fwk_frame.metadata_buffer = *meta_buffer;
4541 fwk_frame.output_buffer = pp_buffer->output;
4542 break;
4543 } else {
4544 LOGE("Source/Re-process streams are invalid");
4545 rc |= BAD_VALUE;
4546 }
4547 }
4548
4549 return rc;
4550 }
4551
4552 /*===========================================================================
4553 * FUNCTION : overrideFwkMetadata
4554 *
4555 * DESCRIPTION: Override frameworks metadata such as crop, and CDS data.
4556 *
4557 * PARAMETERS :
4558 * @frame : input frame for reprocessing
4559 *
4560 * RETURN : int32_t type of status
4561 * NO_ERROR -- success
4562 * none-zero failure code
4563 *==========================================================================*/
overrideFwkMetadata(qcamera_fwk_input_pp_data_t * frame)4564 int32_t QCamera3ReprocessChannel::overrideFwkMetadata(
4565 qcamera_fwk_input_pp_data_t *frame)
4566 {
4567 if (NULL == frame) {
4568 LOGE("Incorrect input frame");
4569 return BAD_VALUE;
4570 }
4571
4572 if (NULL == frame->metadata_buffer.buffer) {
4573 LOGE("No metadata available");
4574 return BAD_VALUE;
4575 }
4576
4577 // Find and insert crop info for reprocess stream
4578 metadata_buffer_t *meta = (metadata_buffer_t *) frame->metadata_buffer.buffer;
4579 IF_META_AVAILABLE(cam_crop_data_t, crop_data, CAM_INTF_META_CROP_DATA, meta) {
4580 if (1 == crop_data->num_of_streams) {
4581 // Store crop/roi information for offline reprocess
4582 // in the reprocess stream slot
4583 crop_data->crop_info[crop_data->num_of_streams].crop =
4584 crop_data->crop_info[0].crop;
4585 crop_data->crop_info[crop_data->num_of_streams].roi_map =
4586 crop_data->crop_info[0].roi_map;
4587 crop_data->crop_info[crop_data->num_of_streams].stream_id =
4588 mStreams[0]->getMyServerID();
4589 crop_data->num_of_streams++;
4590
4591 LOGD("Reprocess stream server id: %d",
4592 mStreams[0]->getMyServerID());
4593 LOGD("Found offline reprocess crop %dx%d %dx%d",
4594 crop_data->crop_info[0].crop.left,
4595 crop_data->crop_info[0].crop.top,
4596 crop_data->crop_info[0].crop.width,
4597 crop_data->crop_info[0].crop.height);
4598 LOGD("Found offline reprocess roi map %dx%d %dx%d",
4599 crop_data->crop_info[0].roi_map.left,
4600 crop_data->crop_info[0].roi_map.top,
4601 crop_data->crop_info[0].roi_map.width,
4602 crop_data->crop_info[0].roi_map.height);
4603 } else {
4604 LOGE("Incorrect number of offline crop data entries %d",
4605 crop_data->num_of_streams);
4606 return BAD_VALUE;
4607 }
4608 } else {
4609 LOGW("Crop data not present");
4610 }
4611
4612 IF_META_AVAILABLE(cam_cds_data_t, cdsInfo, CAM_INTF_META_CDS_DATA, meta) {
4613 if (1 == cdsInfo->num_of_streams) {
4614 cdsInfo->cds_info[0].stream_id = mStreams[0]->getMyServerID();
4615 } else {
4616 LOGE("Incorrect number of offline cds info entries %d",
4617 cdsInfo->num_of_streams);
4618 return BAD_VALUE;
4619 }
4620 }
4621
4622 return NO_ERROR;
4623 }
4624
4625 /*===========================================================================
4626 * FUNCTION : doReprocessOffline
4627 *
4628 * DESCRIPTION: request to do a reprocess on the frame
4629 *
4630 * PARAMETERS :
4631 * @frame : input frame for reprocessing
4632 * @isPriorityFrame: Hint that this frame is of priority, equivalent to
4633 * real time, even though it is processed in offline mechanism
4634 *
4635 * RETURN : int32_t type of status
4636 * NO_ERROR -- success
4637 * none-zero failure code
4638 *==========================================================================*/
doReprocessOffline(qcamera_fwk_input_pp_data_t * frame,bool isPriorityFrame)4639 int32_t QCamera3ReprocessChannel::doReprocessOffline(
4640 qcamera_fwk_input_pp_data_t *frame, bool isPriorityFrame)
4641 {
4642 int32_t rc = 0;
4643 int index;
4644 OfflineBuffer mappedBuffer;
4645 ATRACE_CALL();
4646
4647 if (m_numStreams < 1) {
4648 LOGE("No reprocess stream is created");
4649 return -1;
4650 }
4651
4652 if (NULL == frame) {
4653 LOGE("Incorrect input frame");
4654 return BAD_VALUE;
4655 }
4656
4657 if (NULL == frame->metadata_buffer.buffer) {
4658 LOGE("No metadata available");
4659 return BAD_VALUE;
4660 }
4661
4662 if (NULL == frame->input_buffer.buffer) {
4663 LOGE("No input buffer available");
4664 return BAD_VALUE;
4665 }
4666
4667 if ((0 == m_numStreams) || (NULL == mStreams[0])) {
4668 LOGE("Reprocess stream not initialized!");
4669 return NO_INIT;
4670 }
4671
4672 QCamera3Stream *pStream = mStreams[0];
4673
4674 //qbuf the output buffer if it was allocated by the framework
4675 if (mReprocessType != REPROCESS_TYPE_JPEG && frame->output_buffer != NULL) {
4676 if(!m_bIsActive) {
4677 rc = registerBuffer(frame->output_buffer, mIsType);
4678 if (NO_ERROR != rc) {
4679 LOGE("On-the-fly buffer registration failed %d",
4680 rc);
4681 return rc;
4682 }
4683
4684 rc = start();
4685 if (NO_ERROR != rc) {
4686 return rc;
4687 }
4688 }
4689 index = mGrallocMemory.getMatchBufIndex((void*)frame->output_buffer);
4690 if(index < 0) {
4691 rc = registerBuffer(frame->output_buffer, mIsType);
4692 if (NO_ERROR != rc) {
4693 LOGE("On-the-fly buffer registration failed %d",
4694 rc);
4695 return rc;
4696 }
4697
4698 index = mGrallocMemory.getMatchBufIndex((void*)frame->output_buffer);
4699 if (index < 0) {
4700 LOGE("Could not find object among registered buffers");
4701 return DEAD_OBJECT;
4702 }
4703 }
4704 rc = mGrallocMemory.markFrameNumber(index, frame->frameNumber);
4705 if(rc != NO_ERROR) {
4706 LOGE("Failed to mark frame#:%d, index:%d",frame->frameNumber,index);
4707 return rc;
4708 }
4709 rc = pStream->bufDone(index);
4710 if(rc != NO_ERROR) {
4711 LOGE("Failed to Q new buffer to stream");
4712 mGrallocMemory.markFrameNumber(index, -1);
4713 return rc;
4714 }
4715
4716 } else if (mReprocessType == REPROCESS_TYPE_JPEG) {
4717 Mutex::Autolock lock(mFreeBuffersLock);
4718 uint32_t bufIdx;
4719 if (mFreeBufferList.empty()) {
4720 rc = mMemory->allocateOne(mFrameLen);
4721 if (rc < 0) {
4722 LOGE("Failed allocating heap buffer. Fatal");
4723 return BAD_VALUE;
4724 } else {
4725 bufIdx = (uint32_t)rc;
4726 }
4727 } else {
4728 bufIdx = *(mFreeBufferList.begin());
4729 mFreeBufferList.erase(mFreeBufferList.begin());
4730 }
4731
4732 mMemory->markFrameNumber(bufIdx, frame->frameNumber);
4733 rc = pStream->bufDone(bufIdx);
4734 if (rc != NO_ERROR) {
4735 LOGE("Failed to queue new buffer to stream");
4736 return rc;
4737 }
4738 }
4739
4740 int32_t max_idx = (int32_t) (mNumBuffers - 1);
4741 //loop back the indices if max burst count reached
4742 if (mOfflineBuffersIndex == max_idx) {
4743 mOfflineBuffersIndex = -1;
4744 }
4745 uint32_t buf_idx = (uint32_t)(mOfflineBuffersIndex + 1);
4746
4747 //Do cache ops before sending for reprocess
4748 if (mMemory != NULL) {
4749 mMemory->cleanInvalidateCache(buf_idx);
4750 }
4751
4752 rc = pStream->mapBuf(
4753 CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
4754 buf_idx, -1,
4755 frame->input_buffer.fd, frame->input_buffer.buffer,
4756 frame->input_buffer.frame_len);
4757 if (NO_ERROR == rc) {
4758 Mutex::Autolock l(mOfflineBuffersLock);
4759 mappedBuffer.index = buf_idx;
4760 mappedBuffer.stream = pStream;
4761 mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF;
4762 mOfflineBuffers.push_back(mappedBuffer);
4763 mOfflineBuffersIndex = (int32_t)buf_idx;
4764 LOGD("Mapped buffer with index %d", mOfflineBuffersIndex);
4765 }
4766
4767 max_idx = (int32_t) ((mNumBuffers * 2) - 1);
4768 //loop back the indices if max burst count reached
4769 if (mOfflineMetaIndex == max_idx) {
4770 mOfflineMetaIndex = (int32_t) (mNumBuffers - 1);
4771 }
4772 uint32_t meta_buf_idx = (uint32_t)(mOfflineMetaIndex + 1);
4773 rc |= pStream->mapBuf(
4774 CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF,
4775 meta_buf_idx, -1,
4776 frame->metadata_buffer.fd, frame->metadata_buffer.buffer,
4777 frame->metadata_buffer.frame_len);
4778 if (NO_ERROR == rc) {
4779 Mutex::Autolock l(mOfflineBuffersLock);
4780 mappedBuffer.index = meta_buf_idx;
4781 mappedBuffer.stream = pStream;
4782 mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF;
4783 mOfflineMetaBuffers.push_back(mappedBuffer);
4784 mOfflineMetaIndex = (int32_t)meta_buf_idx;
4785 LOGD("Mapped meta buffer with index %d", mOfflineMetaIndex);
4786 }
4787
4788 if (rc == NO_ERROR) {
4789 cam_stream_parm_buffer_t param;
4790 uint32_t numPendingPriorityFrames = 0;
4791
4792 if(isPriorityFrame) {
4793 Mutex::Autolock lock(mPriorityFramesLock);
4794 /* read the length before pushing the frame number to check if
4795 * vector is empty */
4796 numPendingPriorityFrames = mPriorityFrames.size();
4797 mPriorityFrames.push(frame->frameNumber);
4798 }
4799
4800 if(isPriorityFrame && !numPendingPriorityFrames) {
4801 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t));
4802 param.type = CAM_STREAM_PARAM_TYPE_REQUEST_OPS_MODE;
4803 param.perf_mode = CAM_PERF_HIGH_PERFORMANCE;
4804 rc = pStream->setParameter(param);
4805
4806 if (rc != NO_ERROR) {
4807 ALOGE("%s: setParameter for CAM_PERF_HIGH_PERFORMANCE failed",
4808 __func__);
4809 }
4810 {
4811 Mutex::Autolock lock(mPriorityFramesLock);
4812 mReprocessPerfMode = true;
4813 }
4814 }
4815
4816 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t));
4817 param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
4818 param.reprocess.buf_index = buf_idx;
4819 param.reprocess.frame_idx = frame->input_buffer.frame_idx;
4820 param.reprocess.meta_present = 1;
4821 param.reprocess.meta_buf_index = meta_buf_idx;
4822
4823 LOGI("Offline reprocessing id = %d buf Id = %d meta index = %d",
4824 param.reprocess.frame_idx, param.reprocess.buf_index,
4825 param.reprocess.meta_buf_index);
4826 rc = pStream->setParameter(param);
4827 if (rc != NO_ERROR) {
4828 LOGE("stream setParameter for reprocess failed");
4829 resetToCamPerfNormal(frame->frameNumber);
4830 }
4831 } else {
4832 LOGE("Input buffer memory map failed: %d", rc);
4833 }
4834
4835 return rc;
4836 }
4837
4838 /*===========================================================================
4839 * FUNCTION : doReprocess
4840 *
4841 * DESCRIPTION: request to do a reprocess on the frame
4842 *
4843 * PARAMETERS :
4844 * @buf_fd : fd to the input buffer that needs reprocess
4845 * @buffer : Buffer ptr
4846 * @buf_lenght : length of the input buffer
4847 * @ret_val : result of reprocess.
4848 * Example: Could be faceID in case of register face image.
4849 * @meta_frame : metadata frame.
4850 *
4851 * RETURN : int32_t type of status
4852 * NO_ERROR -- success
4853 * none-zero failure code
4854 *==========================================================================*/
doReprocess(int buf_fd,void * buffer,size_t buf_length,int32_t & ret_val,mm_camera_super_buf_t * meta_frame)4855 int32_t QCamera3ReprocessChannel::doReprocess(int buf_fd, void *buffer, size_t buf_length,
4856 int32_t &ret_val, mm_camera_super_buf_t *meta_frame)
4857 {
4858 int32_t rc = 0;
4859 if (m_numStreams < 1) {
4860 LOGE("No reprocess stream is created");
4861 return -1;
4862 }
4863 if (meta_frame == NULL) {
4864 LOGE("Did not get corresponding metadata in time");
4865 return -1;
4866 }
4867
4868 uint8_t buf_idx = 0;
4869 for (uint32_t i = 0; i < m_numStreams; i++) {
4870 rc = mStreams[i]->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
4871 buf_idx, -1,
4872 buf_fd, buffer, buf_length);
4873
4874 //Do cache ops before sending for reprocess
4875 if (mMemory != NULL) {
4876 mMemory->cleanInvalidateCache(buf_idx);
4877 }
4878
4879 if (rc == NO_ERROR) {
4880 cam_stream_parm_buffer_t param;
4881 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t));
4882 param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
4883 param.reprocess.buf_index = buf_idx;
4884 param.reprocess.meta_present = 1;
4885 param.reprocess.meta_stream_handle = m_pMetaChannel->mStreams[0]->getMyServerID();
4886 param.reprocess.meta_buf_index = meta_frame->bufs[0]->buf_idx;
4887
4888 LOGI("Online reprocessing id = %d buf Id = %d meta index = %d",
4889 param.reprocess.frame_idx, param.reprocess.buf_index,
4890 param.reprocess.meta_buf_index);
4891 rc = mStreams[i]->setParameter(param);
4892 if (rc == NO_ERROR) {
4893 ret_val = param.reprocess.ret_val;
4894 }
4895 mStreams[i]->unmapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
4896 buf_idx, -1);
4897 }
4898 }
4899 return rc;
4900 }
4901
4902 /*===========================================================================
4903 * FUNCTION : addReprocStreamsFromSource
4904 *
4905 * DESCRIPTION: add reprocess streams from input source channel
4906 *
4907 * PARAMETERS :
4908 * @config : pp feature configuration
4909 * @src_config : source reprocess configuration
4910 * @isType : type of image stabilization required on this stream
4911 * @pMetaChannel : ptr to metadata channel to get corresp. metadata
4912 *
4913 *
4914 * RETURN : int32_t type of status
4915 * NO_ERROR -- success
4916 * none-zero failure code
4917 *==========================================================================*/
addReprocStreamsFromSource(cam_pp_feature_config_t & pp_config,const reprocess_config_t & src_config,cam_is_type_t is_type,QCamera3Channel * pMetaChannel)4918 int32_t QCamera3ReprocessChannel::addReprocStreamsFromSource(cam_pp_feature_config_t &pp_config,
4919 const reprocess_config_t &src_config , cam_is_type_t is_type,
4920 QCamera3Channel *pMetaChannel)
4921 {
4922 int32_t rc = 0;
4923 cam_stream_reproc_config_t reprocess_config;
4924 cam_stream_type_t streamType;
4925
4926 cam_dimension_t streamDim = src_config.output_stream_dim;
4927
4928 if (NULL != src_config.src_channel) {
4929 QCamera3Stream *pSrcStream = src_config.src_channel->getStreamByIndex(0);
4930 if (pSrcStream == NULL) {
4931 LOGE("source channel doesn't have a stream");
4932 return BAD_VALUE;
4933 }
4934 mSrcStreamHandles[m_numStreams] = pSrcStream->getMyHandle();
4935 }
4936
4937 streamType = CAM_STREAM_TYPE_OFFLINE_PROC;
4938 reprocess_config.pp_type = CAM_OFFLINE_REPROCESS_TYPE;
4939
4940 reprocess_config.offline.input_fmt = src_config.stream_format;
4941 reprocess_config.offline.input_dim = src_config.input_stream_dim;
4942 reprocess_config.offline.input_buf_planes.plane_info =
4943 src_config.input_stream_plane_info.plane_info;
4944 reprocess_config.offline.num_of_bufs = (uint8_t)mNumBuffers;
4945 reprocess_config.offline.input_type = src_config.stream_type;
4946
4947 reprocess_config.pp_feature_config = pp_config;
4948 QCamera3Stream *pStream = new QCamera3Stream(m_camHandle,
4949 m_handle,
4950 m_camOps,
4951 &mPaddingInfo,
4952 (QCamera3Channel*)this);
4953 if (pStream == NULL) {
4954 LOGE("No mem for Stream");
4955 return NO_MEMORY;
4956 }
4957
4958 rc = pStream->init(streamType, src_config.stream_format,
4959 streamDim, ROTATE_0, &reprocess_config,
4960 (uint8_t)mNumBuffers,
4961 reprocess_config.pp_feature_config.feature_mask,
4962 is_type,
4963 0,/* batchSize */
4964 QCamera3Channel::streamCbRoutine, this);
4965
4966 if (rc == 0) {
4967 mStreams[m_numStreams] = pStream;
4968 m_numStreams++;
4969 } else {
4970 LOGE("failed to create reprocess stream");
4971 delete pStream;
4972 }
4973
4974 if (rc == NO_ERROR) {
4975 m_pSrcChannel = src_config.src_channel;
4976 m_pMetaChannel = pMetaChannel;
4977 mReprocessType = src_config.reprocess_type;
4978 LOGD("mReprocessType is %d", mReprocessType);
4979 }
4980 mm_camera_req_buf_t buf;
4981 memset(&buf, 0x0, sizeof(buf));
4982 buf.type = MM_CAMERA_REQ_SUPER_BUF;
4983 buf.num_buf_requested = 1;
4984 if(m_camOps->request_super_buf(m_camHandle,m_handle, &buf) < 0) {
4985 LOGE("Request for super buffer failed");
4986 }
4987 return rc;
4988 }
4989
4990 /* QCamera3SupportChannel methods */
4991
4992 cam_dimension_t QCamera3SupportChannel::kDim = {640, 480};
4993
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)4994 QCamera3SupportChannel::QCamera3SupportChannel(uint32_t cam_handle,
4995 uint32_t channel_handle,
4996 mm_camera_ops_t *cam_ops,
4997 cam_padding_info_t *paddingInfo,
4998 cam_feature_mask_t postprocess_mask,
4999 cam_stream_type_t streamType,
5000 cam_dimension_t *dim,
5001 cam_format_t streamFormat,
5002 uint8_t hw_analysis_supported,
5003 void *userData, uint32_t numBuffers) :
5004 QCamera3Channel(cam_handle, channel_handle, cam_ops,
5005 NULL, NULL, paddingInfo, postprocess_mask,
5006 userData, numBuffers),
5007 mMemory(NULL)
5008 {
5009 memcpy(&mDim, dim, sizeof(cam_dimension_t));
5010 mStreamType = streamType;
5011 mStreamFormat = streamFormat;
5012 // Make Analysis same as Preview format
5013 if (!hw_analysis_supported && mStreamType == CAM_STREAM_TYPE_ANALYSIS) {
5014 mStreamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_PREVIEW,
5015 dim->width, dim->height);
5016 }
5017 }
5018
~QCamera3SupportChannel()5019 QCamera3SupportChannel::~QCamera3SupportChannel()
5020 {
5021 destroy();
5022
5023 if (mMemory) {
5024 mMemory->deallocate();
5025 delete mMemory;
5026 mMemory = NULL;
5027 }
5028 }
5029
initialize(cam_is_type_t isType)5030 int32_t QCamera3SupportChannel::initialize(cam_is_type_t isType)
5031 {
5032 int32_t rc;
5033
5034 if (mMemory || m_numStreams > 0) {
5035 LOGE("metadata channel already initialized");
5036 return -EINVAL;
5037 }
5038
5039 mIsType = isType;
5040 rc = QCamera3Channel::addStream(mStreamType,
5041 mStreamFormat, mDim, ROTATE_0, MIN_STREAMING_BUFFER_NUM,
5042 mPostProcMask, mIsType);
5043 if (rc < 0) {
5044 LOGE("addStream failed");
5045 }
5046 return rc;
5047 }
5048
request(buffer_handle_t *,uint32_t,int &)5049 int32_t QCamera3SupportChannel::request(buffer_handle_t * /*buffer*/,
5050 uint32_t /*frameNumber*/,
5051 int & /*indexUsed*/)
5052 {
5053 return NO_ERROR;
5054 }
5055
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream *)5056 void QCamera3SupportChannel::streamCbRoutine(
5057 mm_camera_super_buf_t *super_frame,
5058 QCamera3Stream * /*stream*/)
5059 {
5060 if (super_frame == NULL || super_frame->num_bufs != 1) {
5061 LOGE("super_frame is not valid");
5062 return;
5063 }
5064 bufDone(super_frame);
5065 free(super_frame);
5066 }
5067
getStreamBufs(uint32_t len)5068 QCamera3StreamMem* QCamera3SupportChannel::getStreamBufs(uint32_t len)
5069 {
5070 int rc;
5071 mMemory = new QCamera3StreamMem(mNumBuffers);
5072 if (!mMemory) {
5073 LOGE("unable to create heap memory");
5074 return NULL;
5075 }
5076 rc = mMemory->allocateAll(len);
5077 if (rc < 0) {
5078 LOGE("unable to allocate heap memory");
5079 delete mMemory;
5080 mMemory = NULL;
5081 return NULL;
5082 }
5083 return mMemory;
5084 }
5085
putStreamBufs()5086 void QCamera3SupportChannel::putStreamBufs()
5087 {
5088 mMemory->deallocate();
5089 delete mMemory;
5090 mMemory = NULL;
5091 }
5092
5093 }; // namespace qcamera
5094