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