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