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