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