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