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