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