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