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 1978 // Some raw processing may be needed prior to conversion. 1979 static bool raw_proc_lib_load_attempted = false; 1980 static void *raw_proc_lib = NULL; 1981 static void *raw_proc_fn = NULL; 1982 if (! raw_proc_lib && ! raw_proc_lib_load_attempted) { 1983 raw_proc_lib_load_attempted = true; 1984 raw_proc_lib = dlopen("libgoog_rownr.so", RTLD_NOW); 1985 if (raw_proc_lib) { 1986 *(void **)&raw_proc_fn = dlsym(raw_proc_lib, "rownr_process_bayer10"); 1987 } 1988 } 1989 if (raw_proc_fn) { 1990 int (*raw_proc)(unsigned char*,int,int,int,int) = 1991 (int (*)(unsigned char*,int,int,int,int))(raw_proc_fn); 1992 raw_proc((unsigned char*)(frame->buffer), 0, dim.width, dim.height, 1993 offset.mp[0].stride_in_bytes); 1994 } 1995 1996 // In-place format conversion. 1997 // Raw16 format always occupy more memory than opaque raw10. 1998 // Convert to Raw16 by iterating through all pixels from bottom-right 1999 // to top-left of the image. 2000 // One special notes: 2001 // 1. Cross-platform raw16's stride is 16 pixels. 2002 // 2. mipi raw10's stride is 4 pixels, and aligned to 16 bytes. 2003 for (int32_t ys = dim.height - 1; ys >= 0; ys--) { 2004 uint32_t y = (uint32_t)ys; 2005 uint8_t* row_start = (uint8_t *)frame->buffer + 2006 y * (uint32_t)offset.mp[0].stride_in_bytes; 2007 for (int32_t xs = dim.width - 1; xs >= 0; xs--) { 2008 uint32_t x = (uint32_t)xs; 2009 uint8_t upper_8bit = row_start[5*(x/4)+x%4]; 2010 uint8_t lower_2bit = ((row_start[5*(x/4)+4] >> (x%4)) & 0x3); 2011 uint16_t raw16_pixel = 2012 (uint16_t)(((uint16_t)upper_8bit)<<2 | 2013 (uint16_t)lower_2bit); 2014 raw16_buffer[y*raw16_stride+x] = raw16_pixel; 2015 } 2016 } 2017 } else { 2018 ALOGE("%s: Could not find stream", __func__); 2019 } 2020 2021 } 2022 2023 /*=========================================================================== 2024 * FUNCTION : getReprocessType 2025 * 2026 * DESCRIPTION: get the type of reprocess output supported by this channel 2027 * 2028 * PARAMETERS : NONE 2029 * 2030 * RETURN : reprocess_type_t : type of reprocess 2031 *==========================================================================*/ 2032 reprocess_type_t QCamera3RawChannel::getReprocessType() 2033 { 2034 return REPROCESS_TYPE_RAW; 2035 } 2036 2037 2038 /*************************************************************************************/ 2039 // RAW Dump Channel related functions 2040 2041 /*=========================================================================== 2042 * FUNCTION : QCamera3RawDumpChannel 2043 * 2044 * DESCRIPTION: Constructor for RawDumpChannel 2045 * 2046 * PARAMETERS : 2047 * @cam_handle : Handle for Camera 2048 * @cam_ops : Function pointer table 2049 * @rawDumpSize : Dimensions for the Raw stream 2050 * @paddinginfo : Padding information for stream 2051 * @userData : Cookie for parent 2052 * @pp mask : PP feature mask for this stream 2053 * @numBuffers : number of max dequeued buffers 2054 * 2055 * RETURN : NA 2056 *==========================================================================*/ 2057 QCamera3RawDumpChannel::QCamera3RawDumpChannel(uint32_t cam_handle, 2058 uint32_t channel_handle, 2059 mm_camera_ops_t *cam_ops, 2060 cam_dimension_t rawDumpSize, 2061 cam_padding_info_t *paddingInfo, 2062 void *userData, 2063 uint32_t postprocess_mask, uint32_t numBuffers) : 2064 QCamera3Channel(cam_handle, channel_handle, cam_ops, NULL, 2065 paddingInfo, postprocess_mask, 2066 userData, numBuffers), 2067 mDim(rawDumpSize), 2068 mMemory(NULL) 2069 { 2070 char prop[PROPERTY_VALUE_MAX]; 2071 property_get("persist.camera.raw.dump", prop, "0"); 2072 mRawDump = atoi(prop); 2073 } 2074 2075 /*=========================================================================== 2076 * FUNCTION : QCamera3RawDumpChannel 2077 * 2078 * DESCRIPTION: Destructor for RawDumpChannel 2079 * 2080 * PARAMETERS : 2081 * 2082 * RETURN : NA 2083 *==========================================================================*/ 2084 2085 QCamera3RawDumpChannel::~QCamera3RawDumpChannel() 2086 { 2087 } 2088 2089 /*=========================================================================== 2090 * FUNCTION : dumpRawSnapshot 2091 * 2092 * DESCRIPTION: Helper function to dump Raw frames 2093 * 2094 * PARAMETERS : 2095 * @frame : stream buf frame to be dumped 2096 * 2097 * RETURN : NA 2098 *==========================================================================*/ 2099 void QCamera3RawDumpChannel::dumpRawSnapshot(mm_camera_buf_def_t *frame) 2100 { 2101 QCamera3Stream *stream = getStreamByIndex(0); 2102 if (stream != NULL) { 2103 char buf[FILENAME_MAX]; 2104 struct timeval tv; 2105 struct tm timeinfo_data; 2106 struct tm *timeinfo; 2107 2108 cam_dimension_t dim; 2109 memset(&dim, 0, sizeof(dim)); 2110 stream->getFrameDimension(dim); 2111 2112 cam_frame_len_offset_t offset; 2113 memset(&offset, 0, sizeof(cam_frame_len_offset_t)); 2114 stream->getFrameOffset(offset); 2115 2116 gettimeofday(&tv, NULL); 2117 timeinfo = localtime_r(&tv.tv_sec, &timeinfo_data); 2118 2119 if (NULL != timeinfo) { 2120 memset(buf, 0, sizeof(buf)); 2121 snprintf(buf, sizeof(buf), 2122 QCAMERA_DUMP_FRM_LOCATION 2123 "%04d-%02d-%02d-%02d-%02d-%02d-%06ld_%d_%dx%d.raw", 2124 timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, 2125 timeinfo->tm_mday, timeinfo->tm_hour, 2126 timeinfo->tm_min, timeinfo->tm_sec,tv.tv_usec, 2127 frame->frame_idx, dim.width, dim.height); 2128 2129 int file_fd = open(buf, O_RDWR| O_CREAT, 0777); 2130 if (file_fd >= 0) { 2131 ssize_t written_len = 2132 write(file_fd, frame->buffer, offset.frame_len); 2133 CDBG("%s: written number of bytes %zd", __func__, written_len); 2134 close(file_fd); 2135 } else { 2136 ALOGE("%s: failed to open file to dump image", __func__); 2137 } 2138 } else { 2139 ALOGE("%s: localtime_r() error", __func__); 2140 } 2141 } else { 2142 ALOGE("%s: Could not find stream", __func__); 2143 } 2144 2145 } 2146 2147 /*=========================================================================== 2148 * FUNCTION : streamCbRoutine 2149 * 2150 * DESCRIPTION: Callback routine invoked for each frame generated for 2151 * Rawdump channel 2152 * 2153 * PARAMETERS : 2154 * @super_frame : stream buf frame generated 2155 * @stream : Underlying Stream object cookie 2156 * 2157 * RETURN : NA 2158 *==========================================================================*/ 2159 void QCamera3RawDumpChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame, 2160 QCamera3Stream *stream) 2161 { 2162 CDBG("%s: E",__func__); 2163 if (super_frame == NULL || super_frame->num_bufs != 1) { 2164 ALOGE("%s: super_frame is not valid", __func__); 2165 return; 2166 } 2167 2168 if (mRawDump) 2169 dumpRawSnapshot(super_frame->bufs[0]); 2170 2171 bufDone(super_frame); 2172 free(super_frame); 2173 } 2174 2175 /*=========================================================================== 2176 * FUNCTION : getStreamBufs 2177 * 2178 * DESCRIPTION: Callback function provided to interface to get buffers. 2179 * 2180 * PARAMETERS : 2181 * @len : Length of each buffer to be allocated 2182 * 2183 * RETURN : NULL on buffer allocation failure 2184 * QCamera3StreamMem object on sucess 2185 *==========================================================================*/ 2186 QCamera3StreamMem* QCamera3RawDumpChannel::getStreamBufs(uint32_t len) 2187 { 2188 int rc; 2189 mMemory = new QCamera3StreamMem(mNumBuffers); 2190 2191 if (!mMemory) { 2192 ALOGE("%s: unable to create heap memory", __func__); 2193 return NULL; 2194 } 2195 rc = mMemory->allocateAll((size_t)len); 2196 if (rc < 0) { 2197 ALOGE("%s: unable to allocate heap memory", __func__); 2198 delete mMemory; 2199 mMemory = NULL; 2200 return NULL; 2201 } 2202 return mMemory; 2203 } 2204 2205 /*=========================================================================== 2206 * FUNCTION : putStreamBufs 2207 * 2208 * DESCRIPTION: Callback function provided to interface to return buffers. 2209 * Although no handles are actually returned, implicitl assumption 2210 * that interface will no longer use buffers and channel can 2211 * deallocated if necessary. 2212 * 2213 * PARAMETERS : NA 2214 * 2215 * RETURN : NA 2216 *==========================================================================*/ 2217 void QCamera3RawDumpChannel::putStreamBufs() 2218 { 2219 mMemory->deallocate(); 2220 delete mMemory; 2221 mMemory = NULL; 2222 } 2223 2224 /*=========================================================================== 2225 * FUNCTION : request 2226 * 2227 * DESCRIPTION: Request function used as trigger 2228 * 2229 * PARAMETERS : 2230 * @recvd_frame : buffer- this will be NULL since this is internal channel 2231 * @frameNumber : Undefined again since this is internal stream 2232 * 2233 * RETURN : int32_t type of status 2234 * NO_ERROR -- success 2235 * none-zero failure code 2236 *==========================================================================*/ 2237 int32_t QCamera3RawDumpChannel::request(buffer_handle_t * /*buffer*/, 2238 uint32_t /*frameNumber*/) 2239 { 2240 if (!m_bIsActive) { 2241 return QCamera3Channel::start(); 2242 } 2243 else 2244 return 0; 2245 } 2246 2247 /*=========================================================================== 2248 * FUNCTION : intialize 2249 * 2250 * DESCRIPTION: Initializes channel params and creates underlying stream 2251 * 2252 * PARAMETERS : 2253 * @isType : type of image stabilization required on this stream 2254 * 2255 * RETURN : int32_t type of status 2256 * NO_ERROR -- success 2257 * none-zero failure code 2258 *==========================================================================*/ 2259 int32_t QCamera3RawDumpChannel::initialize(cam_is_type_t isType) 2260 { 2261 int32_t rc; 2262 2263 mIsType = isType; 2264 rc = QCamera3Channel::addStream(CAM_STREAM_TYPE_RAW, 2265 CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG, mDim, ROTATE_0, (uint8_t)mNumBuffers, 2266 mPostProcMask, mIsType); 2267 if (rc < 0) { 2268 ALOGE("%s: addStream failed", __func__); 2269 } 2270 return rc; 2271 } 2272 /*************************************************************************************/ 2273 2274 /* QCamera3YUVChannel methods */ 2275 2276 /*=========================================================================== 2277 * FUNCTION : QCamera3YUVChannel 2278 * 2279 * DESCRIPTION: constructor of QCamera3YUVChannel 2280 * 2281 * PARAMETERS : 2282 * @cam_handle : camera handle 2283 * @cam_ops : ptr to camera ops table 2284 * @cb_routine : callback routine to frame aggregator 2285 * @paddingInfo : padding information for the stream 2286 * @stream : camera3_stream_t structure 2287 * @stream_type: Channel stream type 2288 * @postprocess_mask: the postprocess mask for streams of this channel 2289 * @metadataChannel: handle to the metadataChannel 2290 * RETURN : none 2291 *==========================================================================*/ 2292 QCamera3YUVChannel::QCamera3YUVChannel(uint32_t cam_handle, 2293 uint32_t channel_handle, 2294 mm_camera_ops_t *cam_ops, 2295 channel_cb_routine cb_routine, 2296 cam_padding_info_t *paddingInfo, 2297 void *userData, 2298 camera3_stream_t *stream, 2299 cam_stream_type_t stream_type, 2300 uint32_t postprocess_mask, 2301 QCamera3Channel *metadataChannel) : 2302 QCamera3ProcessingChannel(cam_handle, channel_handle, cam_ops, 2303 cb_routine, paddingInfo, userData, stream, stream_type, 2304 postprocess_mask, metadataChannel) 2305 { 2306 2307 mBypass = (postprocess_mask == CAM_QCOM_FEATURE_NONE); 2308 mFrameLen = 0; 2309 mEdgeMode.edge_mode = CAM_EDGE_MODE_OFF; 2310 mEdgeMode.sharpness = 0; 2311 mNoiseRedMode = CAM_NOISE_REDUCTION_MODE_OFF; 2312 memset(&mCropRegion, 0, sizeof(mCropRegion)); 2313 } 2314 2315 /*=========================================================================== 2316 * FUNCTION : ~QCamera3YUVChannel 2317 * 2318 * DESCRIPTION: destructor of QCamera3YUVChannel 2319 * 2320 * PARAMETERS : none 2321 * 2322 * 2323 * RETURN : none 2324 *==========================================================================*/ 2325 QCamera3YUVChannel::~QCamera3YUVChannel() 2326 { 2327 // Deallocation of heap buffers allocated in mMemory is freed 2328 // automatically by its destructor 2329 } 2330 2331 /*=========================================================================== 2332 * FUNCTION : initialize 2333 * 2334 * DESCRIPTION: Initialize and add camera channel & stream 2335 * 2336 * PARAMETERS : 2337 * @isType : the image stabilization type 2338 * 2339 * RETURN : int32_t type of status 2340 * NO_ERROR -- success 2341 * none-zero failure code 2342 *==========================================================================*/ 2343 int32_t QCamera3YUVChannel::initialize(cam_is_type_t isType) 2344 { 2345 ATRACE_CALL(); 2346 int32_t rc = NO_ERROR; 2347 cam_dimension_t streamDim; 2348 2349 if (NULL == mCamera3Stream) { 2350 ALOGE("%s: Camera stream uninitialized", __func__); 2351 return NO_INIT; 2352 } 2353 2354 if (1 <= m_numStreams) { 2355 // Only one stream per channel supported in v3 Hal 2356 return NO_ERROR; 2357 } 2358 2359 mIsType = isType; 2360 mStreamFormat = CALLBACK_FORMAT; 2361 streamDim.width = mCamera3Stream->width; 2362 streamDim.height = mCamera3Stream->height; 2363 2364 rc = QCamera3Channel::addStream(mStreamType, 2365 mStreamFormat, 2366 streamDim, 2367 ROTATE_0, 2368 mNumBufs, 2369 mPostProcMask, 2370 mIsType); 2371 if (rc < 0) { 2372 ALOGE("%s: addStream failed", __func__); 2373 return rc; 2374 } 2375 2376 cam_stream_buf_plane_info_t buf_planes; 2377 cam_padding_info_t paddingInfo = *mPaddingInfo; 2378 2379 memset(&buf_planes, 0, sizeof(buf_planes)); 2380 //to ensure a big enough buffer size set the height and width 2381 //padding to max(height padding, width padding) 2382 paddingInfo.width_padding = MAX(paddingInfo.width_padding, paddingInfo.height_padding); 2383 paddingInfo.height_padding = paddingInfo.width_padding; 2384 2385 rc = mm_stream_calc_offset_snapshot(mStreamFormat, &streamDim, &paddingInfo, 2386 &buf_planes); 2387 if (rc < 0) { 2388 ALOGE("%s: mm_stream_calc_offset_preview failed", __func__); 2389 return rc; 2390 } 2391 2392 mFrameLen = buf_planes.plane_info.frame_len; 2393 2394 if (NO_ERROR != rc) { 2395 ALOGE("%s: Initialize failed, rc = %d", __func__, rc); 2396 return rc; 2397 } 2398 2399 /* initialize offline meta memory for input reprocess */ 2400 rc = QCamera3ProcessingChannel::initialize(isType); 2401 if (NO_ERROR != rc) { 2402 ALOGE("%s: Processing Channel initialize failed, rc = %d", 2403 __func__, rc); 2404 } 2405 2406 return rc; 2407 } 2408 2409 /*=========================================================================== 2410 * FUNCTION : request 2411 * 2412 * DESCRIPTION: entry function for a request on a YUV stream. This function 2413 * has the logic to service a request based on its type 2414 * 2415 * PARAMETERS : 2416 * @buffer : pointer to the output buffer 2417 * @frameNumber : frame number of the request 2418 * @pInputBuffer : pointer to input buffer if an input request 2419 * @metadata : parameters associated with the request 2420 * 2421 * RETURN : 0 on a success start of capture 2422 * -EINVAL on invalid input 2423 * -ENODEV on serious error 2424 *==========================================================================*/ 2425 int32_t QCamera3YUVChannel::request(buffer_handle_t *buffer, 2426 uint32_t frameNumber, 2427 camera3_stream_buffer_t* pInputBuffer, 2428 metadata_buffer_t* metadata, bool &needMetadata) 2429 { 2430 int32_t rc = NO_ERROR; 2431 int index; 2432 Mutex::Autolock lock(mOfflinePpLock); 2433 2434 CDBG("%s: pInputBuffer is %p", __func__, pInputBuffer); 2435 CDBG("%s, frame number %d", __func__, frameNumber); 2436 if (NULL == buffer || NULL == metadata) { 2437 ALOGE("%s: Invalid buffer/metadata in channel request", __func__); 2438 return BAD_VALUE; 2439 } 2440 2441 PpInfo ppInfo; 2442 memset(&ppInfo, 0, sizeof(ppInfo)); 2443 ppInfo.frameNumber = frameNumber; 2444 ppInfo.offlinePpFlag = false; 2445 if (mBypass && !pInputBuffer ) { 2446 ppInfo.offlinePpFlag = needsFramePostprocessing(metadata); 2447 ppInfo.output = buffer; 2448 mOfflinePpInfoList.push_back(ppInfo); 2449 } 2450 2451 CDBG("%s: offlinePpFlag is %d", __func__, ppInfo.offlinePpFlag); 2452 needMetadata = ppInfo.offlinePpFlag; 2453 if (!ppInfo.offlinePpFlag) { 2454 // regular request 2455 return QCamera3ProcessingChannel::request(buffer, frameNumber, 2456 pInputBuffer, metadata); 2457 } else { 2458 if(!m_bIsActive) { 2459 rc = start(); 2460 if (NO_ERROR != rc) 2461 return rc; 2462 } else { 2463 CDBG("%s: Request on an existing stream",__func__); 2464 } 2465 2466 //we need to send this frame through the CPP 2467 //Allocate heap memory, then buf done on the buffer 2468 uint32_t bufIdx; 2469 if (mFreeHeapBufferList.empty()) { 2470 rc = mMemory.allocateOne(mFrameLen); 2471 if (rc < 0) { 2472 ALOGE("%s: Failed allocating heap buffer. Fatal", __func__); 2473 return BAD_VALUE; 2474 } else { 2475 bufIdx = (uint32_t)rc; 2476 } 2477 } else { 2478 bufIdx = *(mFreeHeapBufferList.begin()); 2479 mFreeHeapBufferList.erase(mFreeHeapBufferList.begin()); 2480 } 2481 2482 /* Configure and start postproc if necessary */ 2483 reprocess_config_t reproc_cfg; 2484 cam_dimension_t dim; 2485 memset(&reproc_cfg, 0, sizeof(reprocess_config_t)); 2486 memset(&dim, 0, sizeof(dim)); 2487 mStreams[0]->getFrameDimension(dim); 2488 setReprocConfig(reproc_cfg, NULL, metadata, mStreamFormat, dim); 2489 2490 // Start postprocessor without input buffer 2491 startPostProc(reproc_cfg); 2492 2493 CDBG("%s: erasing %d", __func__, bufIdx); 2494 2495 mMemory.markFrameNumber(bufIdx, frameNumber); 2496 mStreams[0]->bufDone(bufIdx); 2497 2498 } 2499 return rc; 2500 } 2501 2502 /*=========================================================================== 2503 * FUNCTION : streamCbRoutine 2504 * 2505 * DESCRIPTION: 2506 * 2507 * PARAMETERS : 2508 * @super_frame : the super frame with filled buffer 2509 * @stream : stream on which the buffer was requested and filled 2510 * 2511 * RETURN : none 2512 *==========================================================================*/ 2513 void QCamera3YUVChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame, 2514 QCamera3Stream *stream) 2515 { 2516 ATRACE_CALL(); 2517 uint8_t frameIndex; 2518 int32_t resultFrameNumber; 2519 2520 if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) { 2521 ALOGE("%s: Error with the stream callback", __func__); 2522 return; 2523 } 2524 2525 frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx; 2526 if(frameIndex >= mNumBufs) { 2527 ALOGE("%s: Error, Invalid index for buffer",__func__); 2528 stream->bufDone(frameIndex); 2529 return; 2530 } 2531 2532 if (mBypass) { 2533 List<PpInfo>::iterator ppInfo; 2534 2535 Mutex::Autolock lock(mOfflinePpLock); 2536 resultFrameNumber = mMemory.getFrameNumber(frameIndex); 2537 for (ppInfo = mOfflinePpInfoList.begin(); 2538 ppInfo != mOfflinePpInfoList.end(); ppInfo++) { 2539 if (ppInfo->frameNumber == (uint32_t)resultFrameNumber) { 2540 break; 2541 } 2542 } 2543 CDBG("%s, frame index %d, frame number %d", __func__, frameIndex, resultFrameNumber); 2544 //check the reprocessing required flag against the frame number 2545 if (ppInfo == mOfflinePpInfoList.end()) { 2546 ALOGE("%s: Error, request for frame number is a reprocess.", __func__); 2547 stream->bufDone(frameIndex); 2548 return; 2549 } 2550 2551 if (ppInfo->offlinePpFlag) { 2552 mm_camera_super_buf_t *frame = 2553 (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t)); 2554 if (frame == NULL) { 2555 ALOGE("%s: Error allocating memory to save received_frame structure.", 2556 __func__); 2557 if(stream) { 2558 stream->bufDone(frameIndex); 2559 } 2560 return; 2561 } 2562 2563 *frame = *super_frame; 2564 m_postprocessor.processData(frame, ppInfo->output, resultFrameNumber); 2565 free(super_frame); 2566 return; 2567 } else { 2568 if (ppInfo != mOfflinePpInfoList.begin()) { 2569 // There is pending reprocess buffer, cache current buffer 2570 if (ppInfo->callback_buffer != NULL) { 2571 ALOGE("%s: Fatal: cached callback_buffer is already present", 2572 __func__); 2573 2574 } 2575 ppInfo->callback_buffer = super_frame; 2576 return; 2577 } else { 2578 mOfflinePpInfoList.erase(ppInfo); 2579 } 2580 } 2581 } 2582 2583 QCamera3ProcessingChannel::streamCbRoutine(super_frame, stream); 2584 return; 2585 } 2586 2587 /*=========================================================================== 2588 * FUNCTION : reprocessCbRoutine 2589 * 2590 * DESCRIPTION: callback function for the reprocessed frame. This frame now 2591 * should be returned to the framework. This same callback is 2592 * used during input reprocessing or offline postprocessing 2593 * 2594 * PARAMETERS : 2595 * @resultBuffer : buffer containing the reprocessed data 2596 * @resultFrameNumber : frame number on which the buffer was requested 2597 * 2598 * RETURN : NONE 2599 * 2600 *==========================================================================*/ 2601 void QCamera3YUVChannel::reprocessCbRoutine(buffer_handle_t *resultBuffer, 2602 uint32_t resultFrameNumber) 2603 { 2604 CDBG("%s E: frame number %d", __func__, resultFrameNumber); 2605 Vector<mm_camera_super_buf_t *> pendingCbs; 2606 2607 /* release the input buffer and input metadata buffer if used */ 2608 if (0 > mMemory.getHeapBufferIndex(resultFrameNumber)) { 2609 /* mOfflineMemory and mOfflineMetaMemory used only for input reprocessing */ 2610 int32_t rc = releaseOfflineMemory(resultFrameNumber); 2611 if (NO_ERROR != rc) { 2612 ALOGE("%s: Error releasing offline memory rc = %d", __func__, rc); 2613 } 2614 /* Since reprocessing is done, send the callback to release the input buffer */ 2615 if (mChannelCB) { 2616 mChannelCB(NULL, NULL, resultFrameNumber, true, mUserData); 2617 } 2618 } 2619 2620 if (mBypass) { 2621 int32_t rc = handleOfflinePpCallback(resultFrameNumber, pendingCbs); 2622 if (rc != NO_ERROR) { 2623 return; 2624 } 2625 } 2626 2627 issueChannelCb(resultBuffer, resultFrameNumber); 2628 2629 // Call all pending callbacks to return buffers 2630 for (size_t i = 0; i < pendingCbs.size(); i++) { 2631 QCamera3ProcessingChannel::streamCbRoutine( 2632 pendingCbs[i], mStreams[0]); 2633 } 2634 2635 } 2636 2637 /*=========================================================================== 2638 * FUNCTION : needsFramePostprocessing 2639 * 2640 * DESCRIPTION: 2641 * 2642 * PARAMETERS : 2643 * 2644 * RETURN : 2645 * TRUE if frame needs to be postprocessed 2646 * FALSE is frame does not need to be postprocessed 2647 * 2648 *==========================================================================*/ 2649 bool QCamera3YUVChannel::needsFramePostprocessing(metadata_buffer_t *meta) 2650 { 2651 bool ppNeeded = false; 2652 2653 //sharpness 2654 IF_META_AVAILABLE(cam_edge_application_t, edgeMode, 2655 CAM_INTF_META_EDGE_MODE, meta) { 2656 mEdgeMode = *edgeMode; 2657 } 2658 2659 //wnr 2660 IF_META_AVAILABLE(uint32_t, noiseRedMode, 2661 CAM_INTF_META_NOISE_REDUCTION_MODE, meta) { 2662 mNoiseRedMode = *noiseRedMode; 2663 } 2664 2665 //crop region 2666 IF_META_AVAILABLE(cam_crop_region_t, scalerCropRegion, 2667 CAM_INTF_META_SCALER_CROP_REGION, meta) { 2668 mCropRegion = *scalerCropRegion; 2669 } 2670 2671 if ((CAM_EDGE_MODE_OFF != mEdgeMode.edge_mode) && 2672 (CAM_EDGE_MODE_ZERO_SHUTTER_LAG != mEdgeMode.edge_mode)) { 2673 ppNeeded = true; 2674 } 2675 if ((CAM_NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG != mNoiseRedMode) && 2676 (CAM_NOISE_REDUCTION_MODE_OFF != mNoiseRedMode) && 2677 (CAM_NOISE_REDUCTION_MODE_MINIMAL != mNoiseRedMode)) { 2678 ppNeeded = true; 2679 } 2680 if ((mCropRegion.width < (int32_t)mCamera3Stream->width) || 2681 (mCropRegion.height < (int32_t)mCamera3Stream->height)) { 2682 ppNeeded = true; 2683 } 2684 2685 return ppNeeded; 2686 } 2687 2688 /*=========================================================================== 2689 * FUNCTION : handleOfflinePpCallback 2690 * 2691 * DESCRIPTION: callback function for the reprocessed frame from offline 2692 * postprocessing. 2693 * 2694 * PARAMETERS : 2695 * @resultFrameNumber : frame number on which the buffer was requested 2696 * @pendingCbs : pending buffers to be returned first 2697 * 2698 * RETURN : int32_t type of status 2699 * NO_ERROR -- success 2700 * none-zero failure code 2701 *==========================================================================*/ 2702 int32_t QCamera3YUVChannel::handleOfflinePpCallback(uint32_t resultFrameNumber, 2703 Vector<mm_camera_super_buf_t *>& pendingCbs) 2704 { 2705 Mutex::Autolock lock(mOfflinePpLock); 2706 List<PpInfo>::iterator ppInfo; 2707 2708 for (ppInfo = mOfflinePpInfoList.begin(); 2709 ppInfo != mOfflinePpInfoList.end(); ppInfo++) { 2710 if (ppInfo->frameNumber == resultFrameNumber) { 2711 break; 2712 } 2713 } 2714 2715 if (ppInfo == mOfflinePpInfoList.end()) { 2716 ALOGI("%s: Request of frame number %d is reprocessing", 2717 __func__, resultFrameNumber); 2718 return NO_ERROR; 2719 } else if (ppInfo != mOfflinePpInfoList.begin()) { 2720 ALOGE("%s: callback for frame number %d should be head of list", 2721 __func__, resultFrameNumber); 2722 return BAD_VALUE; 2723 } 2724 2725 if (ppInfo->offlinePpFlag) { 2726 // Need to get the input buffer frame index from the 2727 // mMemory object and add that to the free heap buffers list. 2728 int32_t bufferIndex = 2729 mMemory.getHeapBufferIndex(resultFrameNumber); 2730 if (bufferIndex < 0) { 2731 ALOGE("%s: Fatal %d: no buffer index for frame number %d", 2732 __func__, bufferIndex, resultFrameNumber); 2733 return BAD_VALUE; 2734 } 2735 mFreeHeapBufferList.push_back(bufferIndex); 2736 ppInfo = mOfflinePpInfoList.erase(ppInfo); 2737 2738 // Return pending buffer callbacks 2739 while (ppInfo != mOfflinePpInfoList.end() && 2740 !ppInfo->offlinePpFlag && ppInfo->callback_buffer) { 2741 2742 // Call stream callbacks for cached buffers 2743 pendingCbs.push_back(ppInfo->callback_buffer); 2744 2745 ppInfo = mOfflinePpInfoList.erase(ppInfo); 2746 } 2747 2748 } else { 2749 ALOGE("%s: Fatal: request of frame number %d doesn't need" 2750 " offline postprocessing. However there is" 2751 " reprocessing callback.", __func__, 2752 resultFrameNumber); 2753 return BAD_VALUE; 2754 } 2755 2756 return NO_ERROR; 2757 } 2758 2759 /*=========================================================================== 2760 * FUNCTION : getReprocessType 2761 * 2762 * DESCRIPTION: get the type of reprocess output supported by this channel 2763 * 2764 * PARAMETERS : NONE 2765 * 2766 * RETURN : reprocess_type_t : type of reprocess 2767 *==========================================================================*/ 2768 reprocess_type_t QCamera3YUVChannel::getReprocessType() 2769 { 2770 return REPROCESS_TYPE_YUV; 2771 } 2772 2773 /* QCamera3PicChannel methods */ 2774 2775 /*=========================================================================== 2776 * FUNCTION : jpegEvtHandle 2777 * 2778 * DESCRIPTION: Function registerd to mm-jpeg-interface to handle jpeg events. 2779 Construct result payload and call mChannelCb to deliver buffer 2780 to framework. 2781 * 2782 * PARAMETERS : 2783 * @status : status of jpeg job 2784 * @client_hdl: jpeg client handle 2785 * @jobId : jpeg job Id 2786 * @p_ouput : ptr to jpeg output result struct 2787 * @userdata : user data ptr 2788 * 2789 * RETURN : none 2790 *==========================================================================*/ 2791 void QCamera3PicChannel::jpegEvtHandle(jpeg_job_status_t status, 2792 uint32_t /*client_hdl*/, 2793 uint32_t jobId, 2794 mm_jpeg_output_t *p_output, 2795 void *userdata) 2796 { 2797 ATRACE_CALL(); 2798 buffer_handle_t *resultBuffer = NULL; 2799 buffer_handle_t *jpegBufferHandle = NULL; 2800 int resultStatus = CAMERA3_BUFFER_STATUS_OK; 2801 camera3_stream_buffer_t result; 2802 camera3_jpeg_blob_t jpegHeader; 2803 2804 QCamera3PicChannel *obj = (QCamera3PicChannel *)userdata; 2805 if (obj) { 2806 //Construct payload for process_capture_result. Call mChannelCb 2807 2808 qcamera_hal3_jpeg_data_t *job = obj->m_postprocessor.findJpegJobByJobId(jobId); 2809 2810 if ((job == NULL) || (status == JPEG_JOB_STATUS_ERROR)) { 2811 ALOGE("%s: Error in jobId: (%d) with status: %d", __func__, jobId, status); 2812 resultStatus = CAMERA3_BUFFER_STATUS_ERROR; 2813 } 2814 2815 if (NULL != job) { 2816 uint32_t bufIdx = (uint32_t)job->jpeg_settings->out_buf_index; 2817 CDBG("%s: jpeg out_buf_index: %d", __func__, bufIdx); 2818 2819 //Construct jpeg transient header of type camera3_jpeg_blob_t 2820 //Append at the end of jpeg image of buf_filled_len size 2821 2822 jpegHeader.jpeg_blob_id = CAMERA3_JPEG_BLOB_ID; 2823 if (JPEG_JOB_STATUS_DONE == status) { 2824 jpegHeader.jpeg_size = (uint32_t)p_output->buf_filled_len; 2825 char* jpeg_buf = (char *)p_output->buf_vaddr; 2826 2827 ssize_t maxJpegSize = -1; 2828 2829 // Gralloc buffer may have additional padding for 4K page size 2830 // Follow size guidelines based on spec since framework relies 2831 // on that to reach end of buffer and with it the header 2832 2833 //Handle same as resultBuffer, but for readablity 2834 jpegBufferHandle = 2835 (buffer_handle_t *)obj->mMemory.getBufferHandle(bufIdx); 2836 2837 if (NULL != jpegBufferHandle) { 2838 maxJpegSize = ((private_handle_t*)(*jpegBufferHandle))->width; 2839 if (maxJpegSize > obj->mMemory.getSize(bufIdx)) { 2840 maxJpegSize = obj->mMemory.getSize(bufIdx); 2841 } 2842 2843 size_t jpeg_eof_offset = 2844 (size_t)(maxJpegSize - (ssize_t)sizeof(jpegHeader)); 2845 char *jpeg_eof = &jpeg_buf[jpeg_eof_offset]; 2846 memcpy(jpeg_eof, &jpegHeader, sizeof(jpegHeader)); 2847 obj->mMemory.cleanInvalidateCache(bufIdx); 2848 } else { 2849 ALOGE("%s: JPEG buffer not found and index: %d", 2850 __func__, 2851 bufIdx); 2852 resultStatus = CAMERA3_BUFFER_STATUS_ERROR; 2853 } 2854 } 2855 2856 ////Use below data to issue framework callback 2857 resultBuffer = 2858 (buffer_handle_t *)obj->mMemory.getBufferHandle(bufIdx); 2859 int32_t resultFrameNumber = obj->mMemory.getFrameNumber(bufIdx); 2860 int32_t rc = obj->mMemory.unregisterBuffer(bufIdx); 2861 if (NO_ERROR != rc) { 2862 ALOGE("%s: Error %d unregistering stream buffer %d", 2863 __func__, rc, bufIdx); 2864 } 2865 2866 result.stream = obj->mCamera3Stream; 2867 result.buffer = resultBuffer; 2868 result.status = resultStatus; 2869 result.acquire_fence = -1; 2870 result.release_fence = -1; 2871 2872 // Release any snapshot buffers before calling 2873 // the user callback. The callback can potentially 2874 // unblock pending requests to snapshot stream. 2875 int32_t snapshotIdx = -1; 2876 mm_camera_super_buf_t* src_frame = NULL; 2877 2878 if (job->src_reproc_frame) 2879 src_frame = job->src_reproc_frame; 2880 else 2881 src_frame = job->src_frame; 2882 2883 if (src_frame) { 2884 if (obj->mStreams[0]->getMyHandle() == 2885 src_frame->bufs[0]->stream_id) { 2886 snapshotIdx = (int32_t)src_frame->bufs[0]->buf_idx; 2887 2888 if (0 <= snapshotIdx) { 2889 Mutex::Autolock lock(obj->mFreeBuffersLock); 2890 obj->mFreeBufferList.push_back((uint32_t)snapshotIdx); 2891 } 2892 } 2893 } 2894 2895 CDBG("%s: Issue Callback", __func__); 2896 if (obj->mChannelCB) { 2897 obj->mChannelCB(NULL, 2898 &result, 2899 (uint32_t)resultFrameNumber, 2900 false, 2901 obj->mUserData); 2902 } 2903 2904 // release internal data for jpeg job 2905 if ((NULL != job->fwk_frame) || (NULL != job->fwk_src_buffer)) { 2906 /* unregister offline input buffer */ 2907 int32_t inputBufIndex = 2908 obj->mOfflineMemory.getGrallocBufferIndex((uint32_t)resultFrameNumber); 2909 if (0 <= inputBufIndex) { 2910 rc = obj->mOfflineMemory.unregisterBuffer(inputBufIndex); 2911 } else { 2912 ALOGE("%s: could not find the input buf index, frame number %d", 2913 __func__, resultFrameNumber); 2914 } 2915 if (NO_ERROR != rc) { 2916 ALOGE("%s: Error %d unregistering input buffer %d", 2917 __func__, rc, bufIdx); 2918 } 2919 2920 /* unregister offline meta buffer */ 2921 int32_t metaBufIndex = 2922 obj->mOfflineMetaMemory.getHeapBufferIndex((uint32_t)resultFrameNumber); 2923 if (0 <= metaBufIndex) { 2924 Mutex::Autolock lock(obj->mFreeOfflineMetaBuffersLock); 2925 obj->mFreeOfflineMetaBuffersList.push_back((uint32_t)metaBufIndex); 2926 } else { 2927 ALOGE("%s: could not find the input meta buf index, frame number %d", 2928 __func__, resultFrameNumber); 2929 } 2930 } 2931 obj->m_postprocessor.releaseOfflineBuffers(); 2932 obj->m_postprocessor.releaseJpegJobData(job); 2933 free(job); 2934 } 2935 2936 return; 2937 // } 2938 } else { 2939 ALOGE("%s: Null userdata in jpeg callback", __func__); 2940 } 2941 } 2942 2943 QCamera3PicChannel::QCamera3PicChannel(uint32_t cam_handle, 2944 uint32_t channel_handle, 2945 mm_camera_ops_t *cam_ops, 2946 channel_cb_routine cb_routine, 2947 cam_padding_info_t *paddingInfo, 2948 void *userData, 2949 camera3_stream_t *stream, 2950 uint32_t postprocess_mask, 2951 bool is4KVideo, 2952 bool isInputStreamConfigured, 2953 QCamera3Channel *metadataChannel, 2954 uint32_t numBuffers) : 2955 QCamera3ProcessingChannel(cam_handle, channel_handle, 2956 cam_ops, cb_routine, paddingInfo, userData, 2957 stream, CAM_STREAM_TYPE_SNAPSHOT, 2958 postprocess_mask, metadataChannel, numBuffers), 2959 mNumSnapshotBufs(0), 2960 mInputBufferHint(isInputStreamConfigured), 2961 mYuvMemory(NULL), 2962 mFrameLen(0) 2963 { 2964 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData; 2965 m_max_pic_dim = hal_obj->calcMaxJpegDim(); 2966 mYuvWidth = stream->width; 2967 mYuvHeight = stream->height; 2968 mStreamType = CAM_STREAM_TYPE_SNAPSHOT; 2969 // Use same pixelformat for 4K video case 2970 mStreamFormat = is4KVideo ? VIDEO_FORMAT : SNAPSHOT_FORMAT; 2971 int32_t rc = m_postprocessor.initJpeg(jpegEvtHandle, &m_max_pic_dim, this); 2972 if (rc != 0) { 2973 ALOGE("Init Postprocessor failed"); 2974 } 2975 } 2976 2977 QCamera3PicChannel::~QCamera3PicChannel() 2978 { 2979 } 2980 2981 int32_t QCamera3PicChannel::initialize(cam_is_type_t isType) 2982 { 2983 int32_t rc = NO_ERROR; 2984 cam_dimension_t streamDim; 2985 cam_stream_type_t streamType; 2986 cam_format_t streamFormat; 2987 mm_camera_channel_attr_t attr; 2988 2989 if (NULL == mCamera3Stream) { 2990 ALOGE("%s: Camera stream uninitialized", __func__); 2991 return NO_INIT; 2992 } 2993 2994 if (1 <= m_numStreams) { 2995 // Only one stream per channel supported in v3 Hal 2996 return NO_ERROR; 2997 } 2998 2999 mIsType = isType; 3000 streamType = mStreamType; 3001 streamFormat = mStreamFormat; 3002 streamDim.width = (int32_t)mYuvWidth; 3003 streamDim.height = (int32_t)mYuvHeight; 3004 3005 mNumSnapshotBufs = mCamera3Stream->max_buffers; 3006 rc = QCamera3Channel::addStream(streamType, streamFormat, streamDim, 3007 ROTATE_0, (uint8_t)mCamera3Stream->max_buffers, mPostProcMask, 3008 mIsType); 3009 3010 if (NO_ERROR != rc) { 3011 ALOGE("%s: Initialize failed, rc = %d", __func__, rc); 3012 return rc; 3013 } 3014 3015 /* initialize offline meta memory for input reprocess */ 3016 rc = QCamera3ProcessingChannel::initialize(isType); 3017 if (NO_ERROR != rc) { 3018 ALOGE("%s: Processing Channel initialize failed, rc = %d", 3019 __func__, rc); 3020 } 3021 3022 return rc; 3023 } 3024 3025 /*=========================================================================== 3026 * FUNCTION : request 3027 * 3028 * DESCRIPTION: handle the request - either with an input buffer or a direct 3029 * output request 3030 * 3031 * PARAMETERS : 3032 * @buffer : pointer to the output buffer 3033 * @frameNumber : frame number of the request 3034 * @pInputBuffer : pointer to input buffer if an input request 3035 * @metadata : parameters associated with the request 3036 * 3037 * RETURN : 0 on a success start of capture 3038 * -EINVAL on invalid input 3039 * -ENODEV on serious error 3040 *==========================================================================*/ 3041 int32_t QCamera3PicChannel::request(buffer_handle_t *buffer, 3042 uint32_t frameNumber, 3043 camera3_stream_buffer_t *pInputBuffer, 3044 metadata_buffer_t *metadata) 3045 { 3046 ATRACE_CALL(); 3047 //FIX ME: Return buffer back in case of failures below. 3048 3049 int32_t rc = NO_ERROR; 3050 3051 reprocess_config_t reproc_cfg; 3052 cam_dimension_t dim; 3053 memset(&reproc_cfg, 0, sizeof(reprocess_config_t)); 3054 //make sure to set the correct input stream dim in case of YUV size override 3055 //and recalculate the plane info 3056 dim.width = (int32_t)mYuvWidth; 3057 dim.height = (int32_t)mYuvHeight; 3058 setReprocConfig(reproc_cfg, pInputBuffer, metadata, mStreamFormat, dim); 3059 3060 // Picture stream has already been started before any request comes in 3061 if (!m_bIsActive) { 3062 ALOGE("%s: Channel not started!!", __func__); 3063 return NO_INIT; 3064 } 3065 3066 int index = mMemory.getMatchBufIndex((void*)buffer); 3067 3068 if(index < 0) { 3069 rc = registerBuffer(buffer, mIsType); 3070 if (NO_ERROR != rc) { 3071 ALOGE("%s: On-the-fly buffer registration failed %d", 3072 __func__, rc); 3073 return rc; 3074 } 3075 3076 index = mMemory.getMatchBufIndex((void*)buffer); 3077 if (index < 0) { 3078 ALOGE("%s: Could not find object among registered buffers",__func__); 3079 return DEAD_OBJECT; 3080 } 3081 } 3082 CDBG("%s: buffer index %d, frameNumber: %u", __func__, index, frameNumber); 3083 3084 rc = mMemory.markFrameNumber((uint32_t)index, frameNumber); 3085 3086 // Start postprocessor 3087 startPostProc(reproc_cfg); 3088 3089 // Queue jpeg settings 3090 rc = queueJpegSetting((uint32_t)index, metadata); 3091 3092 if (pInputBuffer == NULL) { 3093 Mutex::Autolock lock(mFreeBuffersLock); 3094 uint32_t bufIdx; 3095 if (mFreeBufferList.empty()) { 3096 rc = mYuvMemory->allocateOne(mFrameLen); 3097 if (rc < 0) { 3098 ALOGE("%s: Failed to allocate heap buffer. Fatal", __func__); 3099 return rc; 3100 } else { 3101 bufIdx = (uint32_t)rc; 3102 } 3103 } else { 3104 List<uint32_t>::iterator it = mFreeBufferList.begin(); 3105 bufIdx = *it; 3106 mFreeBufferList.erase(it); 3107 } 3108 mYuvMemory->markFrameNumber(bufIdx, frameNumber); 3109 mStreams[0]->bufDone(bufIdx); 3110 } else { 3111 qcamera_fwk_input_pp_data_t *src_frame = NULL; 3112 src_frame = (qcamera_fwk_input_pp_data_t *)calloc(1, 3113 sizeof(qcamera_fwk_input_pp_data_t)); 3114 if (src_frame == NULL) { 3115 ALOGE("%s: No memory for src frame", __func__); 3116 return NO_MEMORY; 3117 } 3118 rc = setFwkInputPPData(src_frame, pInputBuffer, &reproc_cfg, metadata, 3119 NULL /*fwk output buffer*/, frameNumber); 3120 if (NO_ERROR != rc) { 3121 ALOGE("%s: Error %d while setting framework input PP data", __func__, rc); 3122 free(src_frame); 3123 return rc; 3124 } 3125 CDBG_HIGH("%s: Post-process started", __func__); 3126 CDBG_HIGH("%s: Issue call to reprocess", __func__); 3127 m_postprocessor.processData(src_frame); 3128 } 3129 return rc; 3130 } 3131 3132 3133 /*=========================================================================== 3134 * FUNCTION : dataNotifyCB 3135 * 3136 * DESCRIPTION: Channel Level callback used for super buffer data notify. 3137 * This function is registered with mm-camera-interface to handle 3138 * data notify 3139 * 3140 * PARAMETERS : 3141 * @recvd_frame : stream frame received 3142 * userdata : user data ptr 3143 * 3144 * RETURN : none 3145 *==========================================================================*/ 3146 void QCamera3PicChannel::dataNotifyCB(mm_camera_super_buf_t *recvd_frame, 3147 void *userdata) 3148 { 3149 ATRACE_CALL(); 3150 CDBG("%s: E\n", __func__); 3151 QCamera3PicChannel *channel = (QCamera3PicChannel *)userdata; 3152 3153 if (channel == NULL) { 3154 ALOGE("%s: invalid channel pointer", __func__); 3155 return; 3156 } 3157 3158 if(channel->m_numStreams != 1) { 3159 ALOGE("%s: Error: Bug: This callback assumes one stream per channel",__func__); 3160 return; 3161 } 3162 3163 3164 if(channel->mStreams[0] == NULL) { 3165 ALOGE("%s: Error: Invalid Stream object",__func__); 3166 return; 3167 } 3168 3169 channel->QCamera3PicChannel::streamCbRoutine(recvd_frame, channel->mStreams[0]); 3170 3171 CDBG("%s: X\n", __func__); 3172 return; 3173 } 3174 3175 /*=========================================================================== 3176 * FUNCTION : streamCbRoutine 3177 * 3178 * DESCRIPTION: 3179 * 3180 * PARAMETERS : 3181 * @super_frame : the super frame with filled buffer 3182 * @stream : stream on which the buffer was requested and filled 3183 * 3184 * RETURN : none 3185 *==========================================================================*/ 3186 void QCamera3PicChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame, 3187 QCamera3Stream *stream) 3188 { 3189 ATRACE_CALL(); 3190 //TODO 3191 //Used only for getting YUV. Jpeg callback will be sent back from channel 3192 //directly to HWI. Refer to func jpegEvtHandle 3193 3194 //Got the yuv callback. Calling yuv callback handler in PostProc 3195 uint8_t frameIndex; 3196 mm_camera_super_buf_t* frame = NULL; 3197 3198 if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) { 3199 ALOGE("%s: Error with the stream callback", __func__); 3200 return; 3201 } 3202 3203 frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx; 3204 CDBG("%s: recvd buf_idx: %u for further processing", 3205 __func__, (uint32_t)frameIndex); 3206 if(frameIndex >= mNumSnapshotBufs) { 3207 ALOGE("%s: Error, Invalid index for buffer",__func__); 3208 if(stream) { 3209 Mutex::Autolock lock(mFreeBuffersLock); 3210 mFreeBufferList.push_back(frameIndex); 3211 stream->bufDone(frameIndex); 3212 } 3213 return; 3214 } 3215 3216 frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t)); 3217 if (frame == NULL) { 3218 ALOGE("%s: Error allocating memory to save received_frame structure.", 3219 __func__); 3220 if(stream) { 3221 Mutex::Autolock lock(mFreeBuffersLock); 3222 mFreeBufferList.push_back(frameIndex); 3223 stream->bufDone(frameIndex); 3224 } 3225 return; 3226 } 3227 *frame = *super_frame; 3228 3229 if (mYUVDump) { 3230 cam_dimension_t dim; 3231 memset(&dim, 0, sizeof(dim)); 3232 stream->getFrameDimension(dim); 3233 cam_frame_len_offset_t offset; 3234 memset(&offset, 0, sizeof(cam_frame_len_offset_t)); 3235 stream->getFrameOffset(offset); 3236 dumpYUV(frame->bufs[0], dim, offset, 1); 3237 } 3238 3239 m_postprocessor.processData(frame); 3240 free(super_frame); 3241 return; 3242 } 3243 3244 QCamera3StreamMem* QCamera3PicChannel::getStreamBufs(uint32_t len) 3245 { 3246 int rc = 0; 3247 3248 mYuvMemory = new QCamera3StreamMem(mCamera3Stream->max_buffers, false); 3249 if (!mYuvMemory) { 3250 ALOGE("%s: unable to create metadata memory", __func__); 3251 return NULL; 3252 } 3253 mFrameLen = len; 3254 3255 return mYuvMemory; 3256 } 3257 3258 void QCamera3PicChannel::putStreamBufs() 3259 { 3260 QCamera3ProcessingChannel::putStreamBufs(); 3261 3262 mYuvMemory->deallocate(); 3263 delete mYuvMemory; 3264 mYuvMemory = NULL; 3265 mFreeBufferList.clear(); 3266 } 3267 3268 int32_t QCamera3PicChannel::queueJpegSetting(uint32_t index, metadata_buffer_t *metadata) 3269 { 3270 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData; 3271 jpeg_settings_t *settings = 3272 (jpeg_settings_t *)malloc(sizeof(jpeg_settings_t)); 3273 3274 if (!settings) { 3275 ALOGE("%s: out of memory allocating jpeg_settings", __func__); 3276 return -ENOMEM; 3277 } 3278 3279 memset(settings, 0, sizeof(jpeg_settings_t)); 3280 3281 settings->out_buf_index = index; 3282 3283 settings->jpeg_orientation = 0; 3284 IF_META_AVAILABLE(int32_t, orientation, CAM_INTF_META_JPEG_ORIENTATION, metadata) { 3285 settings->jpeg_orientation = *orientation; 3286 } 3287 3288 settings->jpeg_quality = 85; 3289 IF_META_AVAILABLE(uint32_t, quality1, CAM_INTF_META_JPEG_QUALITY, metadata) { 3290 settings->jpeg_quality = (uint8_t) *quality1; 3291 } 3292 3293 IF_META_AVAILABLE(uint32_t, quality2, CAM_INTF_META_JPEG_THUMB_QUALITY, metadata) { 3294 settings->jpeg_thumb_quality = (uint8_t) *quality2; 3295 } 3296 3297 IF_META_AVAILABLE(cam_dimension_t, dimension, CAM_INTF_META_JPEG_THUMB_SIZE, metadata) { 3298 settings->thumbnail_size = *dimension; 3299 } 3300 3301 settings->gps_timestamp_valid = 0; 3302 IF_META_AVAILABLE(int64_t, timestamp, CAM_INTF_META_JPEG_GPS_TIMESTAMP, metadata) { 3303 settings->gps_timestamp = *timestamp; 3304 settings->gps_timestamp_valid = 1; 3305 } 3306 3307 settings->gps_coordinates_valid = 0; 3308 IF_META_AVAILABLE(double, coordinates, CAM_INTF_META_JPEG_GPS_COORDINATES, metadata) { 3309 memcpy(settings->gps_coordinates, coordinates, 3*sizeof(double)); 3310 settings->gps_coordinates_valid = 1; 3311 } 3312 3313 IF_META_AVAILABLE(uint8_t, proc_methods, CAM_INTF_META_JPEG_GPS_PROC_METHODS, metadata) { 3314 memset(settings->gps_processing_method, 0, 3315 sizeof(settings->gps_processing_method)); 3316 strlcpy(settings->gps_processing_method, (const char *)proc_methods, 3317 sizeof(settings->gps_processing_method)); 3318 } 3319 3320 // Image description 3321 const char *eepromVersion = hal_obj->getEepromVersionInfo(); 3322 const uint32_t *ldafCalib = hal_obj->getLdafCalib(); 3323 if ((eepromVersion && strlen(eepromVersion)) || 3324 ldafCalib) { 3325 int len = 0; 3326 settings->image_desc_valid = true; 3327 if (eepromVersion && strlen(eepromVersion)) { 3328 len = snprintf(settings->image_desc, sizeof(settings->image_desc), 3329 "M:%s ", eepromVersion); 3330 } 3331 if (ldafCalib) { 3332 snprintf(settings->image_desc + len, 3333 sizeof(settings->image_desc) - len, "L:%u-%u", 3334 ldafCalib[0], ldafCalib[1]); 3335 } 3336 } 3337 3338 return m_postprocessor.processJpegSettingData(settings); 3339 } 3340 3341 /*=========================================================================== 3342 * FUNCTION : overrideYuvSize 3343 * 3344 * DESCRIPTION: constructor of QCamera3ReprocessChannel 3345 * 3346 * PARAMETERS : 3347 * @width : new width 3348 * @height : new height 3349 * 3350 * RETURN : none 3351 *==========================================================================*/ 3352 void QCamera3PicChannel::overrideYuvSize(uint32_t width, uint32_t height) 3353 { 3354 mYuvWidth = width; 3355 mYuvHeight = height; 3356 } 3357 3358 /*=========================================================================== 3359 * FUNCTION : getReprocessType 3360 * 3361 * DESCRIPTION: get the type of reprocess output supported by this channel 3362 * 3363 * PARAMETERS : NONE 3364 * 3365 * RETURN : reprocess_type_t : type of reprocess 3366 *==========================================================================*/ 3367 reprocess_type_t QCamera3PicChannel::getReprocessType() 3368 { 3369 /* a picture channel could either use the postprocessor for reprocess+jpeg 3370 or only for reprocess */ 3371 reprocess_type_t expectedReprocess; 3372 if (mPostProcMask == CAM_QCOM_FEATURE_NONE || mInputBufferHint) { 3373 expectedReprocess = REPROCESS_TYPE_JPEG; 3374 } else { 3375 expectedReprocess = REPROCESS_TYPE_NONE; 3376 } 3377 CDBG_HIGH("%s: expectedReprocess from Pic Channel is %d", __func__, expectedReprocess); 3378 return expectedReprocess; 3379 } 3380 3381 /* Reprocess Channel methods */ 3382 3383 /*=========================================================================== 3384 * FUNCTION : QCamera3ReprocessChannel 3385 * 3386 * DESCRIPTION: constructor of QCamera3ReprocessChannel 3387 * 3388 * PARAMETERS : 3389 * @cam_handle : camera handle 3390 * @cam_ops : ptr to camera ops table 3391 * @pp_mask : post-proccess feature mask 3392 * 3393 * RETURN : none 3394 *==========================================================================*/ 3395 QCamera3ReprocessChannel::QCamera3ReprocessChannel(uint32_t cam_handle, 3396 uint32_t channel_handle, 3397 mm_camera_ops_t *cam_ops, 3398 channel_cb_routine cb_routine, 3399 cam_padding_info_t *paddingInfo, 3400 uint32_t postprocess_mask, 3401 void *userData, void *ch_hdl) : 3402 /* In case of framework reprocessing, pproc and jpeg operations could be 3403 * parallelized by allowing 1 extra buffer for reprocessing output: 3404 * ch_hdl->getNumBuffers() + 1 */ 3405 QCamera3Channel(cam_handle, channel_handle, cam_ops, cb_routine, paddingInfo, 3406 postprocess_mask, userData, 3407 ((QCamera3ProcessingChannel *)ch_hdl)->getNumBuffers() 3408 + (MAX_REPROCESS_PIPELINE_STAGES - 1)), 3409 inputChHandle(ch_hdl), 3410 mOfflineBuffersIndex(-1), 3411 mFrameLen(0), 3412 mReprocessType(REPROCESS_TYPE_NONE), 3413 m_pSrcChannel(NULL), 3414 m_pMetaChannel(NULL), 3415 mMemory(NULL), 3416 mGrallocMemory(0) 3417 { 3418 memset(mSrcStreamHandles, 0, sizeof(mSrcStreamHandles)); 3419 mOfflineBuffersIndex = mNumBuffers -1; 3420 mOfflineMetaIndex = (int32_t) (2*mNumBuffers -1); 3421 } 3422 3423 3424 /*=========================================================================== 3425 * FUNCTION : QCamera3ReprocessChannel 3426 * 3427 * DESCRIPTION: constructor of QCamera3ReprocessChannel 3428 * 3429 * PARAMETERS : 3430 * @cam_handle : camera handle 3431 * @cam_ops : ptr to camera ops table 3432 * @pp_mask : post-proccess feature mask 3433 * 3434 * RETURN : none 3435 *==========================================================================*/ 3436 int32_t QCamera3ReprocessChannel::initialize(cam_is_type_t isType) 3437 { 3438 int32_t rc = NO_ERROR; 3439 mm_camera_channel_attr_t attr; 3440 3441 memset(&attr, 0, sizeof(mm_camera_channel_attr_t)); 3442 attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS; 3443 attr.max_unmatched_frames = 1; 3444 3445 m_handle = m_camOps->add_channel(m_camHandle, 3446 &attr, 3447 NULL, 3448 this); 3449 if (m_handle == 0) { 3450 ALOGE("%s: Add channel failed", __func__); 3451 return UNKNOWN_ERROR; 3452 } 3453 3454 mIsType = isType; 3455 return rc; 3456 } 3457 3458 /*=========================================================================== 3459 * FUNCTION : registerBuffer 3460 * 3461 * DESCRIPTION: register streaming buffer to the channel object 3462 * 3463 * PARAMETERS : 3464 * @buffer : buffer to be registered 3465 * @isType : the image stabilization type for the buffer 3466 * 3467 * RETURN : int32_t type of status 3468 * NO_ERROR -- success 3469 * none-zero failure code 3470 *==========================================================================*/ 3471 int32_t QCamera3ReprocessChannel::registerBuffer(buffer_handle_t *buffer, 3472 cam_is_type_t isType) 3473 { 3474 ATRACE_CALL(); 3475 int rc = 0; 3476 mIsType = isType; 3477 cam_stream_type_t streamType; 3478 3479 if (buffer == NULL) { 3480 ALOGE("%s: Error: Cannot register a NULL buffer", __func__); 3481 return BAD_VALUE; 3482 } 3483 3484 if ((uint32_t)mGrallocMemory.getCnt() > (mNumBuffers - 1)) { 3485 ALOGE("%s: Trying to register more buffers than initially requested", 3486 __func__); 3487 return BAD_VALUE; 3488 } 3489 3490 if (0 == m_numStreams) { 3491 rc = initialize(mIsType); 3492 if (rc != NO_ERROR) { 3493 ALOGE("%s: Couldn't initialize camera stream %d", 3494 __func__, rc); 3495 return rc; 3496 } 3497 } 3498 3499 streamType = mStreams[0]->getMyType(); 3500 rc = mGrallocMemory.registerBuffer(buffer, streamType); 3501 if (ALREADY_EXISTS == rc) { 3502 return NO_ERROR; 3503 } else if (NO_ERROR != rc) { 3504 ALOGE("%s: Buffer %p couldn't be registered %d", __func__, buffer, rc); 3505 return rc; 3506 } 3507 3508 return rc; 3509 } 3510 3511 /*=========================================================================== 3512 * FUNCTION : QCamera3ReprocessChannel 3513 * 3514 * DESCRIPTION: constructor of QCamera3ReprocessChannel 3515 * 3516 * PARAMETERS : 3517 * @cam_handle : camera handle 3518 * @cam_ops : ptr to camera ops table 3519 * @pp_mask : post-proccess feature mask 3520 * 3521 * RETURN : none 3522 *==========================================================================*/ 3523 void QCamera3ReprocessChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame, 3524 QCamera3Stream *stream) 3525 { 3526 //Got the pproc data callback. Now send to jpeg encoding 3527 uint8_t frameIndex; 3528 uint32_t resultFrameNumber; 3529 mm_camera_super_buf_t* frame = NULL; 3530 QCamera3ProcessingChannel *obj = (QCamera3ProcessingChannel *)inputChHandle; 3531 3532 if(!super_frame) { 3533 ALOGE("%s: Invalid Super buffer",__func__); 3534 return; 3535 } 3536 3537 if(super_frame->num_bufs != 1) { 3538 ALOGE("%s: Multiple streams are not supported",__func__); 3539 return; 3540 } 3541 if(super_frame->bufs[0] == NULL ) { 3542 ALOGE("%s: Error, Super buffer frame does not contain valid buffer", 3543 __func__); 3544 return; 3545 } 3546 frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx; 3547 3548 if (mYUVDump) { 3549 cam_dimension_t dim; 3550 memset(&dim, 0, sizeof(dim)); 3551 stream->getFrameDimension(dim); 3552 cam_frame_len_offset_t offset; 3553 memset(&offset, 0, sizeof(cam_frame_len_offset_t)); 3554 stream->getFrameOffset(offset); 3555 dumpYUV(super_frame->bufs[0], dim, offset, 2); 3556 } 3557 3558 if (mReprocessType == REPROCESS_TYPE_JPEG) { 3559 resultFrameNumber = mMemory->getFrameNumber(frameIndex); 3560 frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t)); 3561 if (frame == NULL) { 3562 ALOGE("%s: Error allocating memory to save received_frame structure.", 3563 __func__); 3564 if(stream) { 3565 stream->bufDone(frameIndex); 3566 } 3567 return; 3568 } 3569 CDBG("%s: bufIndex: %u recvd from post proc", 3570 __func__, (uint32_t)frameIndex); 3571 *frame = *super_frame; 3572 3573 /* Since reprocessing is done, send the callback to release the input buffer */ 3574 if (mChannelCB) { 3575 mChannelCB(NULL, NULL, resultFrameNumber, true, mUserData); 3576 } 3577 obj->m_postprocessor.processPPData(frame); 3578 } else { 3579 buffer_handle_t *resultBuffer; 3580 frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx; 3581 resultBuffer = (buffer_handle_t *)mGrallocMemory.getBufferHandle(frameIndex); 3582 resultFrameNumber = mGrallocMemory.getFrameNumber(frameIndex); 3583 int32_t rc = stream->bufRelease(frameIndex); 3584 if (NO_ERROR != rc) { 3585 ALOGE("%s: Error %d releasing stream buffer %d", 3586 __func__, rc, frameIndex); 3587 } 3588 rc = mGrallocMemory.unregisterBuffer(frameIndex); 3589 if (NO_ERROR != rc) { 3590 ALOGE("%s: Error %d unregistering stream buffer %d", 3591 __func__, rc, frameIndex); 3592 } 3593 obj->reprocessCbRoutine(resultBuffer, resultFrameNumber); 3594 3595 obj->m_postprocessor.releaseOfflineBuffers(); 3596 qcamera_hal3_pp_data_t *pp_job = obj->m_postprocessor.dequeuePPJob(resultFrameNumber); 3597 if (pp_job != NULL) { 3598 obj->m_postprocessor.releasePPJobData(pp_job); 3599 } 3600 free(pp_job); 3601 } 3602 free(super_frame); 3603 return; 3604 } 3605 3606 /*=========================================================================== 3607 * FUNCTION : getStreamBufs 3608 * 3609 * DESCRIPTION: register the buffers of the reprocess channel 3610 * 3611 * PARAMETERS : none 3612 * 3613 * RETURN : QCamera3StreamMem * 3614 *==========================================================================*/ 3615 QCamera3StreamMem* QCamera3ReprocessChannel::getStreamBufs(uint32_t len) 3616 { 3617 int rc = 0; 3618 if (mReprocessType == REPROCESS_TYPE_JPEG) { 3619 mMemory = new QCamera3StreamMem(mNumBuffers, false); 3620 if (!mMemory) { 3621 ALOGE("%s: unable to create reproc memory", __func__); 3622 return NULL; 3623 } 3624 mFrameLen = len; 3625 return mMemory; 3626 } 3627 return &mGrallocMemory; 3628 } 3629 3630 /*=========================================================================== 3631 * FUNCTION : putStreamBufs 3632 * 3633 * DESCRIPTION: release the reprocess channel buffers 3634 * 3635 * PARAMETERS : none 3636 * 3637 * RETURN : 3638 *==========================================================================*/ 3639 void QCamera3ReprocessChannel::putStreamBufs() 3640 { 3641 if (mReprocessType == REPROCESS_TYPE_JPEG) { 3642 mMemory->deallocate(); 3643 delete mMemory; 3644 mMemory = NULL; 3645 mFreeBufferList.clear(); 3646 } else { 3647 mGrallocMemory.unregisterBuffers(); 3648 } 3649 } 3650 3651 /*=========================================================================== 3652 * FUNCTION : ~QCamera3ReprocessChannel 3653 * 3654 * DESCRIPTION: destructor of QCamera3ReprocessChannel 3655 * 3656 * PARAMETERS : none 3657 * 3658 * RETURN : none 3659 *==========================================================================*/ 3660 QCamera3ReprocessChannel::~QCamera3ReprocessChannel() 3661 { 3662 if (m_bIsActive) 3663 stop(); 3664 3665 for (uint32_t i = 0; i < m_numStreams; i++) { 3666 if (mStreams[i] != NULL) { 3667 delete mStreams[i]; 3668 mStreams[i] = 0; 3669 } 3670 } 3671 if (m_handle) { 3672 m_camOps->delete_channel(m_camHandle, m_handle); 3673 ALOGE("%s: deleting channel %d", __func__, m_handle); 3674 m_handle = 0; 3675 } 3676 m_numStreams = 0; 3677 } 3678 3679 /*=========================================================================== 3680 * FUNCTION : start 3681 * 3682 * DESCRIPTION: start reprocess channel. 3683 * 3684 * PARAMETERS : 3685 * 3686 * RETURN : int32_t type of status 3687 * NO_ERROR -- success 3688 * none-zero failure code 3689 *==========================================================================*/ 3690 int32_t QCamera3ReprocessChannel::start() 3691 { 3692 ATRACE_CALL(); 3693 int32_t rc = NO_ERROR; 3694 3695 rc = QCamera3Channel::start(); 3696 3697 if (rc == NO_ERROR) { 3698 rc = m_camOps->start_channel(m_camHandle, m_handle); 3699 3700 // Check failure 3701 if (rc != NO_ERROR) { 3702 ALOGE("%s: start_channel failed %d", __func__, rc); 3703 QCamera3Channel::stop(); 3704 } 3705 } 3706 return rc; 3707 } 3708 3709 /*=========================================================================== 3710 * FUNCTION : stop 3711 * 3712 * DESCRIPTION: stop reprocess channel. 3713 * 3714 * PARAMETERS : none 3715 * 3716 * RETURN : int32_t type of status 3717 * NO_ERROR -- success 3718 * none-zero failure code 3719 *==========================================================================*/ 3720 int32_t QCamera3ReprocessChannel::stop() 3721 { 3722 ATRACE_CALL(); 3723 int32_t rc = NO_ERROR; 3724 3725 rc = QCamera3Channel::stop(); 3726 3727 rc != m_camOps->stop_channel(m_camHandle, m_handle); 3728 3729 unmapOfflineBuffers(true); 3730 3731 return rc; 3732 } 3733 3734 /*=========================================================================== 3735 * FUNCTION : getStreamBySrcHandle 3736 * 3737 * DESCRIPTION: find reprocess stream by its source stream handle 3738 * 3739 * PARAMETERS : 3740 * @srcHandle : source stream handle 3741 * 3742 * RETURN : ptr to reprocess stream if found. NULL if not found 3743 *==========================================================================*/ 3744 QCamera3Stream * QCamera3ReprocessChannel::getStreamBySrcHandle(uint32_t srcHandle) 3745 { 3746 QCamera3Stream *pStream = NULL; 3747 3748 for (uint32_t i = 0; i < m_numStreams; i++) { 3749 if (mSrcStreamHandles[i] == srcHandle) { 3750 pStream = mStreams[i]; 3751 break; 3752 } 3753 } 3754 return pStream; 3755 } 3756 3757 /*=========================================================================== 3758 * FUNCTION : getSrcStreamBySrcHandle 3759 * 3760 * DESCRIPTION: find source stream by source stream handle 3761 * 3762 * PARAMETERS : 3763 * @srcHandle : source stream handle 3764 * 3765 * RETURN : ptr to reprocess stream if found. NULL if not found 3766 *==========================================================================*/ 3767 QCamera3Stream * QCamera3ReprocessChannel::getSrcStreamBySrcHandle(uint32_t srcHandle) 3768 { 3769 QCamera3Stream *pStream = NULL; 3770 3771 if (NULL == m_pSrcChannel) { 3772 return NULL; 3773 } 3774 3775 for (uint32_t i = 0; i < m_numStreams; i++) { 3776 if (mSrcStreamHandles[i] == srcHandle) { 3777 pStream = m_pSrcChannel->getStreamByIndex(i); 3778 break; 3779 } 3780 } 3781 return pStream; 3782 } 3783 3784 /*=========================================================================== 3785 * FUNCTION : unmapOfflineBuffers 3786 * 3787 * DESCRIPTION: Unmaps offline buffers 3788 * 3789 * PARAMETERS : none 3790 * 3791 * RETURN : int32_t type of status 3792 * NO_ERROR -- success 3793 * none-zero failure code 3794 *==========================================================================*/ 3795 int32_t QCamera3ReprocessChannel::unmapOfflineBuffers(bool all) 3796 { 3797 int rc = NO_ERROR; 3798 if (!mOfflineBuffers.empty()) { 3799 QCamera3Stream *stream = NULL; 3800 List<OfflineBuffer>::iterator it = mOfflineBuffers.begin(); 3801 for (; it != mOfflineBuffers.end(); it++) { 3802 stream = (*it).stream; 3803 if (NULL != stream) { 3804 rc = stream->unmapBuf((*it).type, 3805 (*it).index, 3806 -1); 3807 if (NO_ERROR != rc) { 3808 ALOGE("%s: Error during offline buffer unmap %d", 3809 __func__, rc); 3810 } 3811 CDBG("%s: Unmapped buffer with index %d", __func__, (*it).index); 3812 } 3813 if (!all) { 3814 mOfflineBuffers.erase(it); 3815 break; 3816 } 3817 } 3818 if (all) { 3819 mOfflineBuffers.clear(); 3820 } 3821 } 3822 3823 if (!mOfflineMetaBuffers.empty()) { 3824 QCamera3Stream *stream = NULL; 3825 List<OfflineBuffer>::iterator it = mOfflineMetaBuffers.begin(); 3826 for (; it != mOfflineMetaBuffers.end(); it++) { 3827 stream = (*it).stream; 3828 if (NULL != stream) { 3829 rc = stream->unmapBuf((*it).type, 3830 (*it).index, 3831 -1); 3832 if (NO_ERROR != rc) { 3833 ALOGE("%s: Error during offline buffer unmap %d", 3834 __func__, rc); 3835 } 3836 CDBG("%s: Unmapped meta buffer with index %d", __func__, (*it).index); 3837 } 3838 if (!all) { 3839 mOfflineMetaBuffers.erase(it); 3840 break; 3841 } 3842 } 3843 if (all) { 3844 mOfflineMetaBuffers.clear(); 3845 } 3846 } 3847 return rc; 3848 } 3849 3850 /*=========================================================================== 3851 * FUNCTION : bufDone 3852 * 3853 * DESCRIPTION: Return reprocess stream buffer to free buffer list. 3854 * Note that this function doesn't queue buffer back to kernel. 3855 * It's up to doReprocessOffline to do that instead. 3856 * PARAMETERS : 3857 * @recvd_frame : stream buf frame to be returned 3858 * 3859 * RETURN : int32_t type of status 3860 * NO_ERROR -- success 3861 * none-zero failure code 3862 *==========================================================================*/ 3863 int32_t QCamera3ReprocessChannel::bufDone(mm_camera_super_buf_t *recvd_frame) 3864 { 3865 int rc = NO_ERROR; 3866 if (recvd_frame && recvd_frame->num_bufs == 1) { 3867 Mutex::Autolock lock(mFreeBuffersLock); 3868 uint32_t buf_idx = recvd_frame->bufs[0]->buf_idx; 3869 mFreeBufferList.push_back(buf_idx); 3870 3871 } else { 3872 ALOGE("%s: Fatal. Not supposed to be here", __func__); 3873 rc = BAD_VALUE; 3874 } 3875 3876 return rc; 3877 } 3878 3879 /*=========================================================================== 3880 * FUNCTION : overrideMetadata 3881 * 3882 * DESCRIPTION: Override metadata entry such as rotation, crop, and CDS info. 3883 * 3884 * PARAMETERS : 3885 * @frame : input frame from source stream 3886 * meta_buffer: metadata buffer 3887 * @metadata : corresponding metadata 3888 * @fwk_frame : 3889 * 3890 * RETURN : int32_t type of status 3891 * NO_ERROR -- success 3892 * none-zero failure code 3893 *==========================================================================*/ 3894 int32_t QCamera3ReprocessChannel::overrideMetadata(qcamera_hal3_pp_buffer_t *pp_buffer, 3895 mm_camera_buf_def_t *meta_buffer, jpeg_settings_t *jpeg_settings, 3896 qcamera_fwk_input_pp_data_t &fwk_frame) 3897 { 3898 int32_t rc = NO_ERROR; 3899 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData; 3900 if ((NULL == meta_buffer) || (NULL == pp_buffer) || (NULL == pp_buffer->input) || 3901 (NULL == hal_obj)) { 3902 return BAD_VALUE; 3903 } 3904 3905 metadata_buffer_t *meta = (metadata_buffer_t *)meta_buffer->buffer; 3906 mm_camera_super_buf_t *frame = pp_buffer->input; 3907 if (NULL == meta) { 3908 return BAD_VALUE; 3909 } 3910 3911 for (uint32_t i = 0; i < frame->num_bufs; i++) { 3912 QCamera3Stream *pStream = getStreamBySrcHandle(frame->bufs[i]->stream_id); 3913 QCamera3Stream *pSrcStream = getSrcStreamBySrcHandle(frame->bufs[i]->stream_id); 3914 3915 if (pStream != NULL && pSrcStream != NULL) { 3916 if (jpeg_settings) { 3917 // Find rotation info for reprocess stream 3918 cam_rotation_info_t rotation_info; 3919 memset(&rotation_info, 0, sizeof(rotation_info)); 3920 if (jpeg_settings->jpeg_orientation == 0) { 3921 rotation_info.rotation = ROTATE_0; 3922 } else if (jpeg_settings->jpeg_orientation == 90) { 3923 rotation_info.rotation = ROTATE_90; 3924 } else if (jpeg_settings->jpeg_orientation == 180) { 3925 rotation_info.rotation = ROTATE_180; 3926 } else if (jpeg_settings->jpeg_orientation == 270) { 3927 rotation_info.rotation = ROTATE_270; 3928 } 3929 rotation_info.streamId = mStreams[0]->getMyServerID(); 3930 ADD_SET_PARAM_ENTRY_TO_BATCH(meta, CAM_INTF_PARM_ROTATION, rotation_info); 3931 } 3932 3933 // Find and insert crop info for reprocess stream 3934 IF_META_AVAILABLE(cam_crop_data_t, crop_data, CAM_INTF_META_CROP_DATA, meta) { 3935 if (MAX_NUM_STREAMS > crop_data->num_of_streams) { 3936 for (int j = 0; j < crop_data->num_of_streams; j++) { 3937 if (crop_data->crop_info[j].stream_id == 3938 pSrcStream->getMyServerID()) { 3939 3940 // Store crop/roi information for offline reprocess 3941 // in the reprocess stream slot 3942 crop_data->crop_info[crop_data->num_of_streams].crop = 3943 crop_data->crop_info[j].crop; 3944 crop_data->crop_info[crop_data->num_of_streams].roi_map = 3945 crop_data->crop_info[j].roi_map; 3946 crop_data->crop_info[crop_data->num_of_streams].stream_id = 3947 mStreams[0]->getMyServerID(); 3948 crop_data->num_of_streams++; 3949 3950 CDBG("%s: Reprocess stream server id: %d", 3951 __func__, mStreams[0]->getMyServerID()); 3952 CDBG("%s: Found offline reprocess crop %dx%d %dx%d", 3953 __func__, 3954 crop_data->crop_info[j].crop.left, 3955 crop_data->crop_info[j].crop.top, 3956 crop_data->crop_info[j].crop.width, 3957 crop_data->crop_info[j].crop.height); 3958 CDBG("%s: Found offline reprocess roimap %dx%d %dx%d", 3959 __func__, 3960 crop_data->crop_info[j].roi_map.left, 3961 crop_data->crop_info[j].roi_map.top, 3962 crop_data->crop_info[j].roi_map.width, 3963 crop_data->crop_info[j].roi_map.height); 3964 3965 break; 3966 } 3967 } 3968 } else { 3969 ALOGE("%s: No space to add reprocess stream crop/roi information", 3970 __func__); 3971 } 3972 } 3973 3974 IF_META_AVAILABLE(cam_cds_data_t, cdsInfo, CAM_INTF_META_CDS_DATA, meta) { 3975 uint8_t cnt = cdsInfo->num_of_streams; 3976 if (cnt <= MAX_NUM_STREAMS) { 3977 cam_stream_cds_info_t repro_cds_info; 3978 memset(&repro_cds_info, 0, sizeof(repro_cds_info)); 3979 repro_cds_info.stream_id = mStreams[0]->getMyServerID(); 3980 for (size_t i = 0; i < cnt; i++) { 3981 if (cdsInfo->cds_info[i].stream_id == 3982 pSrcStream->getMyServerID()) { 3983 repro_cds_info.cds_enable = 3984 cdsInfo->cds_info[i].cds_enable; 3985 break; 3986 } 3987 } 3988 cdsInfo->num_of_streams = 1; 3989 cdsInfo->cds_info[0] = repro_cds_info; 3990 } else { 3991 ALOGE("%s: No space to add reprocess stream cds information", 3992 __func__); 3993 } 3994 } 3995 3996 fwk_frame.input_buffer = *frame->bufs[i]; 3997 fwk_frame.metadata_buffer = *meta_buffer; 3998 fwk_frame.output_buffer = pp_buffer->output; 3999 break; 4000 } else { 4001 ALOGE("%s: Source/Re-process streams are invalid", __func__); 4002 rc |= BAD_VALUE; 4003 } 4004 } 4005 4006 return rc; 4007 } 4008 4009 /*=========================================================================== 4010 * FUNCTION : overrideFwkMetadata 4011 * 4012 * DESCRIPTION: Override frameworks metadata such as crop, and CDS data. 4013 * 4014 * PARAMETERS : 4015 * @frame : input frame for reprocessing 4016 * 4017 * RETURN : int32_t type of status 4018 * NO_ERROR -- success 4019 * none-zero failure code 4020 *==========================================================================*/ 4021 int32_t QCamera3ReprocessChannel::overrideFwkMetadata( 4022 qcamera_fwk_input_pp_data_t *frame) 4023 { 4024 if (NULL == frame) { 4025 ALOGE("%s: Incorrect input frame", __func__); 4026 return BAD_VALUE; 4027 } 4028 4029 4030 if (NULL == frame->metadata_buffer.buffer) { 4031 ALOGE("%s: No metadata available", __func__); 4032 return BAD_VALUE; 4033 } 4034 4035 // Find and insert crop info for reprocess stream 4036 metadata_buffer_t *meta = (metadata_buffer_t *) frame->metadata_buffer.buffer; 4037 IF_META_AVAILABLE(cam_crop_data_t, crop_data, CAM_INTF_META_CROP_DATA, meta) { 4038 if (1 == crop_data->num_of_streams) { 4039 // Store crop/roi information for offline reprocess 4040 // in the reprocess stream slot 4041 crop_data->crop_info[crop_data->num_of_streams].crop = 4042 crop_data->crop_info[0].crop; 4043 crop_data->crop_info[crop_data->num_of_streams].roi_map = 4044 crop_data->crop_info[0].roi_map; 4045 crop_data->crop_info[crop_data->num_of_streams].stream_id = 4046 mStreams[0]->getMyServerID(); 4047 crop_data->num_of_streams++; 4048 4049 CDBG("%s: Reprocess stream server id: %d", 4050 __func__, mStreams[0]->getMyServerID()); 4051 CDBG("%s: Found offline reprocess crop %dx%d %dx%d", __func__, 4052 crop_data->crop_info[0].crop.left, 4053 crop_data->crop_info[0].crop.top, 4054 crop_data->crop_info[0].crop.width, 4055 crop_data->crop_info[0].crop.height); 4056 CDBG("%s: Found offline reprocess roi map %dx%d %dx%d", __func__, 4057 crop_data->crop_info[0].roi_map.left, 4058 crop_data->crop_info[0].roi_map.top, 4059 crop_data->crop_info[0].roi_map.width, 4060 crop_data->crop_info[0].roi_map.height); 4061 } else { 4062 ALOGE("%s: Incorrect number of offline crop data entries %d", 4063 __func__, 4064 crop_data->num_of_streams); 4065 return BAD_VALUE; 4066 } 4067 } else { 4068 CDBG_HIGH("%s: Crop data not present", __func__); 4069 } 4070 4071 IF_META_AVAILABLE(cam_cds_data_t, cdsInfo, CAM_INTF_META_CDS_DATA, meta) { 4072 if (1 == cdsInfo->num_of_streams) { 4073 cdsInfo->cds_info[0].stream_id = mStreams[0]->getMyServerID(); 4074 } else { 4075 ALOGE("%s: Incorrect number of offline cds info entries %d", 4076 __func__, cdsInfo->num_of_streams); 4077 return BAD_VALUE; 4078 } 4079 } 4080 4081 return NO_ERROR; 4082 } 4083 4084 /*=========================================================================== 4085 * FUNCTION : doReprocessOffline 4086 * 4087 * DESCRIPTION: request to do a reprocess on the frame 4088 * 4089 * PARAMETERS : 4090 * @frame : input frame for reprocessing 4091 * 4092 * RETURN : int32_t type of status 4093 * NO_ERROR -- success 4094 * none-zero failure code 4095 *==========================================================================*/ 4096 int32_t QCamera3ReprocessChannel::doReprocessOffline(qcamera_fwk_input_pp_data_t *frame) 4097 { 4098 int32_t rc = 0; 4099 int index; 4100 OfflineBuffer mappedBuffer; 4101 4102 if (m_numStreams < 1) { 4103 ALOGE("%s: No reprocess stream is created", __func__); 4104 return -1; 4105 } 4106 4107 if (NULL == frame) { 4108 ALOGE("%s: Incorrect input frame", __func__); 4109 return BAD_VALUE; 4110 } 4111 4112 if (NULL == frame->metadata_buffer.buffer) { 4113 ALOGE("%s: No metadata available", __func__); 4114 return BAD_VALUE; 4115 } 4116 4117 if (NULL == frame->input_buffer.buffer) { 4118 ALOGE("%s: No input buffer available", __func__); 4119 return BAD_VALUE; 4120 } 4121 4122 if ((0 == m_numStreams) || (NULL == mStreams[0])) { 4123 ALOGE("%s: Reprocess stream not initialized!", __func__); 4124 return NO_INIT; 4125 } 4126 4127 QCamera3Stream *pStream = mStreams[0]; 4128 4129 //qbuf the output buffer if it was allocated by the framework 4130 if (mReprocessType != REPROCESS_TYPE_JPEG && frame->output_buffer != NULL) { 4131 if(!m_bIsActive) { 4132 rc = registerBuffer(frame->output_buffer, mIsType); 4133 if (NO_ERROR != rc) { 4134 ALOGE("%s: On-the-fly buffer registration failed %d", 4135 __func__, rc); 4136 return rc; 4137 } 4138 4139 rc = start(); 4140 if (NO_ERROR != rc) { 4141 return rc; 4142 } 4143 } 4144 index = mGrallocMemory.getMatchBufIndex((void*)frame->output_buffer); 4145 if(index < 0) { 4146 rc = registerBuffer(frame->output_buffer, mIsType); 4147 if (NO_ERROR != rc) { 4148 ALOGE("%s: On-the-fly buffer registration failed %d", 4149 __func__, rc); 4150 return rc; 4151 } 4152 4153 index = mGrallocMemory.getMatchBufIndex((void*)frame->output_buffer); 4154 if (index < 0) { 4155 ALOGE("%s: Could not find object among registered buffers", 4156 __func__); 4157 return DEAD_OBJECT; 4158 } 4159 } 4160 rc = pStream->bufDone(index); 4161 if(rc != NO_ERROR) { 4162 ALOGE("%s: Failed to Q new buffer to stream",__func__); 4163 return rc; 4164 } 4165 rc = mGrallocMemory.markFrameNumber(index, frame->frameNumber); 4166 4167 } else if (mReprocessType == REPROCESS_TYPE_JPEG) { 4168 Mutex::Autolock lock(mFreeBuffersLock); 4169 uint32_t bufIdx; 4170 if (mFreeBufferList.empty()) { 4171 rc = mMemory->allocateOne(mFrameLen); 4172 if (rc < 0) { 4173 ALOGE("%s: Failed allocating heap buffer. Fatal", __func__); 4174 return BAD_VALUE; 4175 } else { 4176 bufIdx = (uint32_t)rc; 4177 } 4178 } else { 4179 bufIdx = *(mFreeBufferList.begin()); 4180 mFreeBufferList.erase(mFreeBufferList.begin()); 4181 } 4182 4183 mMemory->markFrameNumber(bufIdx, frame->frameNumber); 4184 rc = pStream->bufDone(bufIdx); 4185 if (rc != NO_ERROR) { 4186 ALOGE("%s: Failed to queue new buffer to stream", __func__); 4187 return rc; 4188 } 4189 } 4190 4191 int32_t max_idx = (int32_t) (mNumBuffers - 1); 4192 //loop back the indices if max burst count reached 4193 if (mOfflineBuffersIndex == max_idx) { 4194 mOfflineBuffersIndex = -1; 4195 } 4196 uint32_t buf_idx = (uint32_t)(mOfflineBuffersIndex + 1); 4197 rc = pStream->mapBuf( 4198 CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF, 4199 buf_idx, -1, 4200 frame->input_buffer.fd, frame->input_buffer.frame_len); 4201 if (NO_ERROR == rc) { 4202 mappedBuffer.index = buf_idx; 4203 mappedBuffer.stream = pStream; 4204 mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF; 4205 mOfflineBuffers.push_back(mappedBuffer); 4206 mOfflineBuffersIndex = (int32_t)buf_idx; 4207 CDBG("%s: Mapped buffer with index %d", __func__, mOfflineBuffersIndex); 4208 } 4209 4210 max_idx = (int32_t) ((mNumBuffers * 2) - 1); 4211 //loop back the indices if max burst count reached 4212 if (mOfflineMetaIndex == max_idx) { 4213 mOfflineMetaIndex = (int32_t) (mNumBuffers - 1); 4214 } 4215 uint32_t meta_buf_idx = (uint32_t)(mOfflineMetaIndex + 1); 4216 rc |= pStream->mapBuf( 4217 CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF, 4218 meta_buf_idx, -1, 4219 frame->metadata_buffer.fd, frame->metadata_buffer.frame_len); 4220 if (NO_ERROR == rc) { 4221 mappedBuffer.index = meta_buf_idx; 4222 mappedBuffer.stream = pStream; 4223 mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF; 4224 mOfflineMetaBuffers.push_back(mappedBuffer); 4225 mOfflineMetaIndex = (int32_t)meta_buf_idx; 4226 CDBG("%s: Mapped meta buffer with index %d", __func__, mOfflineMetaIndex); 4227 } 4228 4229 if (rc == NO_ERROR) { 4230 cam_stream_parm_buffer_t param; 4231 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t)); 4232 param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS; 4233 param.reprocess.buf_index = buf_idx; 4234 param.reprocess.frame_idx = frame->input_buffer.frame_idx; 4235 param.reprocess.meta_present = 1; 4236 param.reprocess.meta_buf_index = meta_buf_idx; 4237 rc = pStream->setParameter(param); 4238 if (rc != NO_ERROR) { 4239 ALOGE("%s: stream setParameter for reprocess failed", __func__); 4240 } 4241 } else { 4242 ALOGE("%s: Input buffer memory map failed: %d", __func__, rc); 4243 } 4244 4245 return rc; 4246 } 4247 4248 /*=========================================================================== 4249 * FUNCTION : doReprocess 4250 * 4251 * DESCRIPTION: request to do a reprocess on the frame 4252 * 4253 * PARAMETERS : 4254 * @buf_fd : fd to the input buffer that needs reprocess 4255 * @buf_lenght : length of the input buffer 4256 * @ret_val : result of reprocess. 4257 * Example: Could be faceID in case of register face image. 4258 * @meta_frame : metadata frame. 4259 * 4260 * RETURN : int32_t type of status 4261 * NO_ERROR -- success 4262 * none-zero failure code 4263 *==========================================================================*/ 4264 int32_t QCamera3ReprocessChannel::doReprocess(int buf_fd, size_t buf_length, 4265 int32_t &ret_val, mm_camera_super_buf_t *meta_frame) 4266 { 4267 int32_t rc = 0; 4268 if (m_numStreams < 1) { 4269 ALOGE("%s: No reprocess stream is created", __func__); 4270 return -1; 4271 } 4272 if (meta_frame == NULL) { 4273 ALOGE("%s: Did not get corresponding metadata in time", __func__); 4274 return -1; 4275 } 4276 4277 uint8_t buf_idx = 0; 4278 for (uint32_t i = 0; i < m_numStreams; i++) { 4279 rc = mStreams[i]->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF, 4280 buf_idx, -1, 4281 buf_fd, buf_length); 4282 4283 if (rc == NO_ERROR) { 4284 cam_stream_parm_buffer_t param; 4285 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t)); 4286 param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS; 4287 param.reprocess.buf_index = buf_idx; 4288 param.reprocess.meta_present = 1; 4289 param.reprocess.meta_stream_handle = m_pMetaChannel->mStreams[0]->getMyServerID(); 4290 param.reprocess.meta_buf_index = meta_frame->bufs[0]->buf_idx; 4291 rc = mStreams[i]->setParameter(param); 4292 if (rc == NO_ERROR) { 4293 ret_val = param.reprocess.ret_val; 4294 } 4295 mStreams[i]->unmapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF, 4296 buf_idx, -1); 4297 } 4298 } 4299 return rc; 4300 } 4301 4302 /*=========================================================================== 4303 * FUNCTION : addReprocStreamsFromSource 4304 * 4305 * DESCRIPTION: add reprocess streams from input source channel 4306 * 4307 * PARAMETERS : 4308 * @config : pp feature configuration 4309 * @src_config : source reprocess configuration 4310 * @isType : type of image stabilization required on this stream 4311 * @pMetaChannel : ptr to metadata channel to get corresp. metadata 4312 * 4313 * 4314 * RETURN : int32_t type of status 4315 * NO_ERROR -- success 4316 * none-zero failure code 4317 *==========================================================================*/ 4318 int32_t QCamera3ReprocessChannel::addReprocStreamsFromSource(cam_pp_feature_config_t &pp_config, 4319 const reprocess_config_t &src_config , cam_is_type_t is_type, 4320 QCamera3Channel *pMetaChannel) 4321 { 4322 int32_t rc = 0; 4323 cam_stream_reproc_config_t reprocess_config; 4324 cam_stream_type_t streamType; 4325 4326 cam_dimension_t streamDim = src_config.output_stream_dim; 4327 4328 if (NULL != src_config.src_channel) { 4329 QCamera3Stream *pSrcStream = src_config.src_channel->getStreamByIndex(0); 4330 if (pSrcStream == NULL) { 4331 ALOGE("%s: source channel doesn't have a stream", __func__); 4332 return BAD_VALUE; 4333 } 4334 mSrcStreamHandles[m_numStreams] = pSrcStream->getMyHandle(); 4335 } 4336 4337 streamType = CAM_STREAM_TYPE_OFFLINE_PROC; 4338 reprocess_config.pp_type = CAM_OFFLINE_REPROCESS_TYPE; 4339 4340 reprocess_config.offline.input_fmt = src_config.stream_format; 4341 reprocess_config.offline.input_dim = src_config.input_stream_dim; 4342 reprocess_config.offline.input_buf_planes.plane_info = 4343 src_config.input_stream_plane_info.plane_info; 4344 reprocess_config.offline.num_of_bufs = (uint8_t)mNumBuffers; 4345 reprocess_config.offline.input_type = src_config.stream_type; 4346 4347 reprocess_config.pp_feature_config = pp_config; 4348 QCamera3Stream *pStream = new QCamera3Stream(m_camHandle, 4349 m_handle, 4350 m_camOps, 4351 mPaddingInfo, 4352 (QCamera3Channel*)this); 4353 if (pStream == NULL) { 4354 ALOGE("%s: No mem for Stream", __func__); 4355 return NO_MEMORY; 4356 } 4357 4358 rc = pStream->init(streamType, src_config.stream_format, 4359 streamDim, ROTATE_0, &reprocess_config, 4360 (uint8_t)mNumBuffers, 4361 reprocess_config.pp_feature_config.feature_mask, 4362 is_type, 4363 0,/* batchSize */ 4364 QCamera3Channel::streamCbRoutine, this); 4365 4366 if (rc == 0) { 4367 mStreams[m_numStreams] = pStream; 4368 m_numStreams++; 4369 } else { 4370 ALOGE("%s: failed to create reprocess stream", __func__); 4371 delete pStream; 4372 } 4373 4374 if (rc == NO_ERROR) { 4375 m_pSrcChannel = src_config.src_channel; 4376 m_pMetaChannel = pMetaChannel; 4377 mReprocessType = src_config.reprocess_type; 4378 CDBG("%s: mReprocessType is %d", __func__, mReprocessType); 4379 } 4380 if(m_camOps->request_super_buf(m_camHandle,m_handle,1,0) < 0) { 4381 ALOGE("%s: Request for super buffer failed",__func__); 4382 } 4383 return rc; 4384 } 4385 4386 /* QCamera3SupportChannel methods */ 4387 4388 cam_dimension_t QCamera3SupportChannel::kDim = {640, 480}; 4389 4390 QCamera3SupportChannel::QCamera3SupportChannel(uint32_t cam_handle, 4391 uint32_t channel_handle, 4392 mm_camera_ops_t *cam_ops, 4393 cam_padding_info_t *paddingInfo, 4394 uint32_t postprocess_mask, 4395 cam_stream_type_t streamType, 4396 cam_dimension_t *dim, 4397 cam_format_t streamFormat, 4398 void *userData, uint32_t numBuffers) : 4399 QCamera3Channel(cam_handle, channel_handle, cam_ops, 4400 NULL, paddingInfo, postprocess_mask, 4401 userData, numBuffers), 4402 mMemory(NULL) 4403 { 4404 memcpy(&mDim, dim, sizeof(cam_dimension_t)); 4405 mStreamType = streamType; 4406 mStreamFormat = streamFormat; 4407 } 4408 4409 QCamera3SupportChannel::~QCamera3SupportChannel() 4410 { 4411 if (m_bIsActive) 4412 stop(); 4413 4414 if (mMemory) { 4415 mMemory->deallocate(); 4416 delete mMemory; 4417 mMemory = NULL; 4418 } 4419 } 4420 4421 int32_t QCamera3SupportChannel::initialize(cam_is_type_t isType) 4422 { 4423 int32_t rc; 4424 4425 if (mMemory || m_numStreams > 0) { 4426 ALOGE("%s: metadata channel already initialized", __func__); 4427 return -EINVAL; 4428 } 4429 4430 mIsType = isType; 4431 rc = QCamera3Channel::addStream(mStreamType, 4432 mStreamFormat, mDim, ROTATE_0, MIN_STREAMING_BUFFER_NUM, 4433 mPostProcMask, mIsType); 4434 if (rc < 0) { 4435 ALOGE("%s: addStream failed", __func__); 4436 } 4437 return rc; 4438 } 4439 4440 int32_t QCamera3SupportChannel::request(buffer_handle_t * /*buffer*/, 4441 uint32_t /*frameNumber*/) 4442 { 4443 return NO_ERROR; 4444 } 4445 4446 void QCamera3SupportChannel::streamCbRoutine( 4447 mm_camera_super_buf_t *super_frame, 4448 QCamera3Stream * /*stream*/) 4449 { 4450 if (super_frame == NULL || super_frame->num_bufs != 1) { 4451 ALOGE("%s: super_frame is not valid", __func__); 4452 return; 4453 } 4454 bufDone(super_frame); 4455 free(super_frame); 4456 } 4457 4458 QCamera3StreamMem* QCamera3SupportChannel::getStreamBufs(uint32_t len) 4459 { 4460 int rc; 4461 mMemory = new QCamera3StreamMem(mNumBuffers); 4462 if (!mMemory) { 4463 ALOGE("%s: unable to create heap memory", __func__); 4464 return NULL; 4465 } 4466 rc = mMemory->allocateAll(len); 4467 if (rc < 0) { 4468 ALOGE("%s: unable to allocate heap memory", __func__); 4469 delete mMemory; 4470 mMemory = NULL; 4471 return NULL; 4472 } 4473 return mMemory; 4474 } 4475 4476 void QCamera3SupportChannel::putStreamBufs() 4477 { 4478 mMemory->deallocate(); 4479 delete mMemory; 4480 mMemory = NULL; 4481 } 4482 4483 }; // namespace qcamera 4484