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