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