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 48 using namespace android; 49 50 51 namespace 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 *==========================================================================*/ 70 QCamera3Channel::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 *==========================================================================*/ 109 QCamera3Channel::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 *==========================================================================*/ 136 QCamera3Channel::~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 *==========================================================================*/ 169 int32_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 *==========================================================================*/ 201 int32_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 *==========================================================================*/ 256 int32_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 *==========================================================================*/ 303 int32_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 *==========================================================================*/ 337 int32_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 *==========================================================================*/ 354 int32_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 *==========================================================================*/ 372 int32_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 *==========================================================================*/ 390 int32_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 *==========================================================================*/ 417 uint32_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 *==========================================================================*/ 435 uint32_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 *==========================================================================*/ 457 QCamera3Stream *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 *==========================================================================*/ 477 QCamera3Stream *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 *==========================================================================*/ 495 void 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 *==========================================================================*/ 519 void 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 *==========================================================================*/ 562 QCamera3ProcessingChannel::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 *==========================================================================*/ 598 QCamera3ProcessingChannel::~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 *==========================================================================*/ 631 void 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 *==========================================================================*/ 716 int32_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 *==========================================================================*/ 861 int32_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 *==========================================================================*/ 879 int32_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 *==========================================================================*/ 925 QCamera3Memory* 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 *==========================================================================*/ 940 void 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 *==========================================================================*/ 958 int32_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 *==========================================================================*/ 987 void 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 *==========================================================================*/ 1012 int32_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 *==========================================================================*/ 1029 int32_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 *==========================================================================*/ 1057 int32_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 //any input buffer will be of the ZSL format so use the snapshot offset calculations 1086 reproc_cfg.stream_type = CAM_STREAM_TYPE_SNAPSHOT; 1087 reproc_cfg.stream_format = SNAPSHOT_FORMAT; 1088 rc = mm_stream_calc_offset_snapshot(streamFormat, 1089 &reproc_cfg.input_stream_dim, reproc_cfg.padding, 1090 &reproc_cfg.input_stream_plane_info); 1091 CDBG("%s: reproc_cfg.stream_type = %d, reproc_cfg.stream_format = %d", __func__, 1092 reproc_cfg.stream_type, reproc_cfg.stream_format); 1093 return rc; 1094 } 1095 1096 /*=========================================================================== 1097 * FUNCTION : reprocessCbRoutine 1098 * 1099 * DESCRIPTION: callback function for the reprocessed frame. This frame now 1100 * should be returned to the framework 1101 * 1102 * PARAMETERS : 1103 * @resultBuffer : buffer containing the reprocessed data 1104 * @resultFrameNumber : frame number on which the buffer was requested 1105 * 1106 * RETURN : NONE 1107 * 1108 *==========================================================================*/ 1109 void QCamera3ProcessingChannel::reprocessCbRoutine(buffer_handle_t *resultBuffer, 1110 uint32_t resultFrameNumber) 1111 { 1112 ATRACE_CALL(); 1113 camera3_stream_buffer_t result; 1114 int rc = 0; 1115 1116 //Use below data to issue framework callback 1117 result.stream = mCamera3Stream; 1118 result.buffer = resultBuffer; 1119 result.status = CAMERA3_BUFFER_STATUS_OK; 1120 result.acquire_fence = -1; 1121 result.release_fence = -1; 1122 1123 mChannelCB(NULL, &result, resultFrameNumber, mUserData); 1124 return; 1125 } 1126 1127 1128 /* Regular Channel methods */ 1129 1130 /*=========================================================================== 1131 * FUNCTION : QCamera3RegularChannel 1132 * 1133 * DESCRIPTION: constructor of QCamera3RegularChannel 1134 * 1135 * PARAMETERS : 1136 * @cam_handle : camera handle 1137 * @cam_ops : ptr to camera ops table 1138 * @cb_routine : callback routine to frame aggregator 1139 * @stream : camera3_stream_t structure 1140 * @stream_type: Channel stream type 1141 * @postprocess_mask: feature mask for postprocessing 1142 * @metadataChannel : metadata channel for the session 1143 * @numBuffers : number of max dequeued buffers 1144 * 1145 * RETURN : none 1146 *==========================================================================*/ 1147 QCamera3RegularChannel::QCamera3RegularChannel(uint32_t cam_handle, 1148 mm_camera_ops_t *cam_ops, 1149 channel_cb_routine cb_routine, 1150 cam_padding_info_t *paddingInfo, 1151 void *userData, 1152 camera3_stream_t *stream, 1153 cam_stream_type_t stream_type, 1154 uint32_t postprocess_mask, 1155 QCamera3Channel *metadataChannel, 1156 uint32_t numBuffers) : 1157 QCamera3ProcessingChannel(cam_handle, cam_ops, cb_routine, 1158 paddingInfo, userData, stream, stream_type, 1159 postprocess_mask, metadataChannel, numBuffers), 1160 mRotation(ROTATE_0), 1161 mBatchSize(0) 1162 { 1163 } 1164 1165 /*=========================================================================== 1166 * FUNCTION : ~QCamera3RegularChannel 1167 * 1168 * DESCRIPTION: destructor of QCamera3RegularChannel 1169 * 1170 * PARAMETERS : none 1171 * 1172 * RETURN : none 1173 *==========================================================================*/ 1174 QCamera3RegularChannel::~QCamera3RegularChannel() 1175 { 1176 } 1177 1178 /*=========================================================================== 1179 * FUNCTION : initialize 1180 * 1181 * DESCRIPTION: Initialize and add camera channel & stream 1182 * 1183 * PARAMETERS : 1184 * @isType : type of image stabilization required on this stream 1185 * 1186 * RETURN : int32_t type of status 1187 * NO_ERROR -- success 1188 * none-zero failure code 1189 *==========================================================================*/ 1190 int32_t QCamera3RegularChannel::initialize(cam_is_type_t isType) 1191 { 1192 ATRACE_CALL(); 1193 int32_t rc = NO_ERROR; 1194 cam_dimension_t streamDim; 1195 1196 if (NULL == mCamera3Stream) { 1197 ALOGE("%s: Camera stream uninitialized", __func__); 1198 return NO_INIT; 1199 } 1200 1201 if (1 <= m_numStreams) { 1202 // Only one stream per channel supported in v3 Hal 1203 return NO_ERROR; 1204 } 1205 1206 rc = init(NULL, NULL); 1207 if (rc < 0) { 1208 ALOGE("%s: init failed", __func__); 1209 return rc; 1210 } 1211 1212 mIsType = isType; 1213 1214 switch (mCamera3Stream->format) { 1215 case HAL_PIXEL_FORMAT_YCbCr_420_888: 1216 mStreamFormat = CALLBACK_FORMAT; 1217 break; 1218 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED: 1219 { 1220 if (mStreamType == CAM_STREAM_TYPE_VIDEO) { 1221 mStreamFormat = VIDEO_FORMAT; 1222 } else if (mStreamType == CAM_STREAM_TYPE_PREVIEW) { 1223 mStreamFormat = PREVIEW_FORMAT; 1224 } else { 1225 //TODO: Add a new flag in libgralloc for ZSL buffers, and 1226 //its size needs to be properly aligned and padded. 1227 mStreamFormat = DEFAULT_FORMAT; 1228 } 1229 } 1230 break; 1231 case HAL_PIXEL_FORMAT_RAW_OPAQUE: 1232 case HAL_PIXEL_FORMAT_RAW16: 1233 case HAL_PIXEL_FORMAT_RAW10: 1234 mStreamFormat = CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG; 1235 break; 1236 default: 1237 ALOGE("%s: format is not IMPLEMENTATION_DEFINED or flexible", __func__); 1238 return -EINVAL; 1239 } 1240 1241 if ((mStreamType == CAM_STREAM_TYPE_VIDEO) || 1242 (mStreamType == CAM_STREAM_TYPE_PREVIEW)) { 1243 if ((mCamera3Stream->rotation != CAMERA3_STREAM_ROTATION_0) && 1244 ((mPostProcMask & CAM_QCOM_FEATURE_ROTATION) == 0)) { 1245 ALOGE("%s: attempting rotation %d when rotation is disabled", 1246 __func__, 1247 mCamera3Stream->rotation); 1248 return -EINVAL; 1249 } 1250 1251 switch (mCamera3Stream->rotation) { 1252 case CAMERA3_STREAM_ROTATION_0: 1253 mRotation = ROTATE_0; 1254 break; 1255 case CAMERA3_STREAM_ROTATION_90: { 1256 mRotation = ROTATE_90; 1257 break; 1258 } 1259 case CAMERA3_STREAM_ROTATION_180: 1260 mRotation = ROTATE_180; 1261 break; 1262 case CAMERA3_STREAM_ROTATION_270: { 1263 mRotation = ROTATE_270; 1264 break; 1265 } 1266 default: 1267 ALOGE("%s: Unknown rotation: %d", 1268 __func__, 1269 mCamera3Stream->rotation); 1270 return -EINVAL; 1271 } 1272 } else if (mCamera3Stream->rotation != CAMERA3_STREAM_ROTATION_0) { 1273 ALOGE("%s: Rotation %d is not supported by stream type %d", 1274 __func__, 1275 mCamera3Stream->rotation, 1276 mStreamType); 1277 return -EINVAL; 1278 } 1279 1280 streamDim.width = mCamera3Stream->width; 1281 streamDim.height = mCamera3Stream->height; 1282 1283 CDBG("%s: batch size is %d", __func__, mBatchSize); 1284 rc = QCamera3Channel::addStream(mStreamType, 1285 mStreamFormat, 1286 streamDim, 1287 mRotation, 1288 mNumBufs, 1289 mPostProcMask, 1290 mIsType, 1291 mBatchSize); 1292 1293 return rc; 1294 } 1295 1296 /*=========================================================================== 1297 * FUNCTION : start 1298 * 1299 * DESCRIPTION: start a regular channel 1300 * 1301 * PARAMETERS : 1302 * 1303 * RETURN : int32_t type of status 1304 * NO_ERROR -- success 1305 * none-zero failure code 1306 *==========================================================================*/ 1307 int32_t QCamera3RegularChannel::start() 1308 { 1309 ATRACE_CALL(); 1310 int32_t rc = NO_ERROR; 1311 1312 if (0 < mMemory.getCnt()) { 1313 rc = QCamera3Channel::start(); 1314 } 1315 return rc; 1316 } 1317 1318 /*=========================================================================== 1319 * FUNCTION : setBatchSize 1320 * 1321 * DESCRIPTION: Set batch size for the channel. 1322 * 1323 * PARAMETERS : 1324 * @batchSize : Number of image buffers in a batch 1325 * 1326 * RETURN : int32_t type of status 1327 * NO_ERROR -- success always 1328 * none-zero failure code 1329 *==========================================================================*/ 1330 int32_t QCamera3RegularChannel::setBatchSize(uint32_t batchSize) 1331 { 1332 int32_t rc = NO_ERROR; 1333 1334 mBatchSize = batchSize; 1335 CDBG("%s: Batch size set: %d", __func__, mBatchSize); 1336 return rc; 1337 } 1338 1339 /*=========================================================================== 1340 * FUNCTION : getStreamTypeMask 1341 * 1342 * DESCRIPTION: Get bit mask of all stream types in this channel. 1343 * If stream is not initialized, then generate mask based on 1344 * local streamType 1345 * 1346 * PARAMETERS : None 1347 * 1348 * RETURN : Bit mask of all stream types in this channel 1349 *==========================================================================*/ 1350 uint32_t QCamera3RegularChannel::getStreamTypeMask() 1351 { 1352 if (mStreams[0]) { 1353 return QCamera3Channel::getStreamTypeMask(); 1354 } else { 1355 return (1U << mStreamType); 1356 } 1357 } 1358 1359 /*=========================================================================== 1360 * FUNCTION : queueBatchBuf 1361 * 1362 * DESCRIPTION: queue batch container to downstream 1363 * 1364 * PARAMETERS : 1365 * 1366 * RETURN : int32_t type of status 1367 * NO_ERROR -- success always 1368 * none-zero failure code 1369 *==========================================================================*/ 1370 int32_t QCamera3RegularChannel::queueBatchBuf() 1371 { 1372 int32_t rc = NO_ERROR; 1373 1374 if (mStreams[0]) { 1375 rc = mStreams[0]->queueBatchBuf(); 1376 } 1377 if (rc != NO_ERROR) { 1378 ALOGE("%s: stream->queueBatchContainer failed", __func__); 1379 } 1380 return rc; 1381 } 1382 1383 /*=========================================================================== 1384 * FUNCTION : request 1385 * 1386 * DESCRIPTION: process a request from camera service. Stream on if ncessary. 1387 * 1388 * PARAMETERS : 1389 * @buffer : buffer to be filled for this request 1390 * 1391 * RETURN : 0 on a success start of capture 1392 * -EINVAL on invalid input 1393 * -ENODEV on serious error 1394 *==========================================================================*/ 1395 int32_t QCamera3RegularChannel::request(buffer_handle_t *buffer, uint32_t frameNumber) 1396 { 1397 ATRACE_CALL(); 1398 //FIX ME: Return buffer back in case of failures below. 1399 1400 int32_t rc = NO_ERROR; 1401 int index; 1402 1403 if (NULL == buffer) { 1404 ALOGE("%s: Invalid buffer in channel request", __func__); 1405 return BAD_VALUE; 1406 } 1407 1408 if(!m_bIsActive) { 1409 rc = registerBuffer(buffer, mIsType); 1410 if (NO_ERROR != rc) { 1411 ALOGE("%s: On-the-fly buffer registration failed %d", 1412 __func__, rc); 1413 return rc; 1414 } 1415 1416 rc = start(); 1417 if (NO_ERROR != rc) { 1418 return rc; 1419 } 1420 } else { 1421 CDBG("%s: Request on an existing stream",__func__); 1422 } 1423 1424 index = mMemory.getMatchBufIndex((void*)buffer); 1425 if(index < 0) { 1426 rc = registerBuffer(buffer, mIsType); 1427 if (NO_ERROR != rc) { 1428 ALOGE("%s: On-the-fly buffer registration failed %d", 1429 __func__, rc); 1430 return rc; 1431 } 1432 1433 index = mMemory.getMatchBufIndex((void*)buffer); 1434 if (index < 0) { 1435 ALOGE("%s: Could not find object among registered buffers", 1436 __func__); 1437 return DEAD_OBJECT; 1438 } 1439 } 1440 1441 rc = mStreams[0]->bufDone((uint32_t)index); 1442 if(rc != NO_ERROR) { 1443 ALOGE("%s: Failed to Q new buffer to stream",__func__); 1444 return rc; 1445 } 1446 1447 rc = mMemory.markFrameNumber((uint32_t)index, frameNumber); 1448 return rc; 1449 } 1450 1451 /*=========================================================================== 1452 * FUNCTION : getReprocessType 1453 * 1454 * DESCRIPTION: get the type of reprocess output supported by this channel 1455 * 1456 * PARAMETERS : NONE 1457 * 1458 * RETURN : reprocess_type_t : type of reprocess 1459 *==========================================================================*/ 1460 reprocess_type_t QCamera3RegularChannel::getReprocessType() 1461 { 1462 return REPROCESS_TYPE_PRIVATE; 1463 } 1464 1465 QCamera3MetadataChannel::QCamera3MetadataChannel(uint32_t cam_handle, 1466 mm_camera_ops_t *cam_ops, 1467 channel_cb_routine cb_routine, 1468 cam_padding_info_t *paddingInfo, 1469 uint32_t postprocess_mask, 1470 void *userData, uint32_t numBuffers) : 1471 QCamera3Channel(cam_handle, cam_ops, 1472 cb_routine, paddingInfo, postprocess_mask, 1473 userData, numBuffers), 1474 mMemory(NULL) 1475 { 1476 } 1477 1478 QCamera3MetadataChannel::~QCamera3MetadataChannel() 1479 { 1480 if (m_bIsActive) 1481 stop(); 1482 1483 if (mMemory) { 1484 mMemory->deallocate(); 1485 delete mMemory; 1486 mMemory = NULL; 1487 } 1488 } 1489 1490 int32_t QCamera3MetadataChannel::initialize(cam_is_type_t isType) 1491 { 1492 ATRACE_CALL(); 1493 int32_t rc; 1494 cam_dimension_t streamDim; 1495 1496 if (mMemory || m_numStreams > 0) { 1497 ALOGE("%s: metadata channel already initialized", __func__); 1498 return -EINVAL; 1499 } 1500 1501 rc = init(NULL, NULL); 1502 if (rc < 0) { 1503 ALOGE("%s: init failed", __func__); 1504 return rc; 1505 } 1506 1507 streamDim.width = (int32_t)sizeof(metadata_buffer_t), 1508 streamDim.height = 1; 1509 1510 mIsType = isType; 1511 rc = QCamera3Channel::addStream(CAM_STREAM_TYPE_METADATA, CAM_FORMAT_MAX, 1512 streamDim, ROTATE_0, (uint8_t)mNumBuffers, mPostProcMask, mIsType); 1513 if (rc < 0) { 1514 ALOGE("%s: addStream failed", __func__); 1515 } 1516 return rc; 1517 } 1518 1519 int32_t QCamera3MetadataChannel::request(buffer_handle_t * /*buffer*/, 1520 uint32_t /*frameNumber*/) 1521 { 1522 if (!m_bIsActive) { 1523 return start(); 1524 } 1525 else 1526 return 0; 1527 } 1528 1529 void QCamera3MetadataChannel::streamCbRoutine( 1530 mm_camera_super_buf_t *super_frame, 1531 QCamera3Stream * /*stream*/) 1532 { 1533 ATRACE_CALL(); 1534 uint32_t requestNumber = 0; 1535 if (super_frame == NULL || super_frame->num_bufs != 1) { 1536 ALOGE("%s: super_frame is not valid", __func__); 1537 return; 1538 } 1539 mChannelCB(super_frame, NULL, requestNumber, mUserData); 1540 } 1541 1542 QCamera3Memory* QCamera3MetadataChannel::getStreamBufs(uint32_t len) 1543 { 1544 int rc; 1545 if (len < sizeof(metadata_buffer_t)) { 1546 ALOGE("%s: Metadata buffer size less than structure %d vs %d", 1547 __func__, 1548 len, 1549 sizeof(metadata_buffer_t)); 1550 return NULL; 1551 } 1552 mMemory = new QCamera3HeapMemory(); 1553 if (!mMemory) { 1554 ALOGE("%s: unable to create metadata memory", __func__); 1555 return NULL; 1556 } 1557 rc = mMemory->allocate(MIN_STREAMING_BUFFER_NUM, len, true); 1558 if (rc < 0) { 1559 ALOGE("%s: unable to allocate metadata memory", __func__); 1560 delete mMemory; 1561 mMemory = NULL; 1562 return NULL; 1563 } 1564 clear_metadata_buffer((metadata_buffer_t*)mMemory->getPtr(0)); 1565 return mMemory; 1566 } 1567 1568 void QCamera3MetadataChannel::putStreamBufs() 1569 { 1570 mMemory->deallocate(); 1571 delete mMemory; 1572 mMemory = NULL; 1573 } 1574 /*************************************************************************************/ 1575 // RAW Channel related functions 1576 QCamera3RawChannel::QCamera3RawChannel(uint32_t cam_handle, 1577 mm_camera_ops_t *cam_ops, 1578 channel_cb_routine cb_routine, 1579 cam_padding_info_t *paddingInfo, 1580 void *userData, 1581 camera3_stream_t *stream, 1582 uint32_t postprocess_mask, 1583 QCamera3Channel *metadataChannel, 1584 bool raw_16, uint32_t numBuffers) : 1585 QCamera3RegularChannel(cam_handle, cam_ops, 1586 cb_routine, paddingInfo, userData, stream, 1587 CAM_STREAM_TYPE_RAW, postprocess_mask, metadataChannel, numBuffers), 1588 mIsRaw16(raw_16) 1589 { 1590 char prop[PROPERTY_VALUE_MAX]; 1591 property_get("persist.camera.raw.debug.dump", prop, "0"); 1592 mRawDump = atoi(prop); 1593 } 1594 1595 QCamera3RawChannel::~QCamera3RawChannel() 1596 { 1597 } 1598 1599 /*=========================================================================== 1600 * FUNCTION : initialize 1601 * 1602 * DESCRIPTION: Initialize and add camera channel & stream 1603 * 1604 * PARAMETERS : 1605 * 1606 * RETURN : int32_t type of status 1607 * NO_ERROR -- success 1608 * none-zero failure code 1609 *==========================================================================*/ 1610 1611 int32_t QCamera3RawChannel::initialize(cam_is_type_t isType) 1612 { 1613 return QCamera3RegularChannel::initialize(isType); 1614 } 1615 1616 void QCamera3RawChannel::streamCbRoutine( 1617 mm_camera_super_buf_t *super_frame, 1618 QCamera3Stream * stream) 1619 { 1620 ATRACE_CALL(); 1621 /* Move this back down once verified */ 1622 if (mRawDump) 1623 dumpRawSnapshot(super_frame->bufs[0]); 1624 1625 if (mIsRaw16) { 1626 if (RAW_FORMAT == CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG) 1627 convertMipiToRaw16(super_frame->bufs[0]); 1628 else 1629 convertLegacyToRaw16(super_frame->bufs[0]); 1630 } 1631 1632 //Make sure cache coherence because extra processing is done 1633 mMemory.cleanInvalidateCache(super_frame->bufs[0]->buf_idx); 1634 1635 QCamera3RegularChannel::streamCbRoutine(super_frame, stream); 1636 return; 1637 } 1638 1639 void QCamera3RawChannel::dumpRawSnapshot(mm_camera_buf_def_t *frame) 1640 { 1641 QCamera3Stream *stream = getStreamByIndex(0); 1642 if (stream != NULL) { 1643 char buf[FILENAME_MAX]; 1644 memset(buf, 0, sizeof(buf)); 1645 cam_dimension_t dim; 1646 memset(&dim, 0, sizeof(dim)); 1647 stream->getFrameDimension(dim); 1648 1649 cam_frame_len_offset_t offset; 1650 memset(&offset, 0, sizeof(cam_frame_len_offset_t)); 1651 stream->getFrameOffset(offset); 1652 snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"r_%d_%dx%d.raw", 1653 frame->frame_idx, offset.mp[0].stride, offset.mp[0].scanline); 1654 1655 int file_fd = open(buf, O_RDWR| O_CREAT, 0644); 1656 if (file_fd >= 0) { 1657 ssize_t written_len = write(file_fd, frame->buffer, frame->frame_len); 1658 ALOGE("%s: written number of bytes %zd", __func__, written_len); 1659 close(file_fd); 1660 } else { 1661 ALOGE("%s: failed to open file to dump image", __func__); 1662 } 1663 } else { 1664 ALOGE("%s: Could not find stream", __func__); 1665 } 1666 1667 } 1668 1669 void QCamera3RawChannel::convertLegacyToRaw16(mm_camera_buf_def_t *frame) 1670 { 1671 // Convert image buffer from Opaque raw format to RAW16 format 1672 // 10bit Opaque raw is stored in the format of: 1673 // 0000 - p5 - p4 - p3 - p2 - p1 - p0 1674 // where p0 to p5 are 6 pixels (each is 10bit)_and most significant 1675 // 4 bits are 0s. Each 64bit word contains 6 pixels. 1676 1677 QCamera3Stream *stream = getStreamByIndex(0); 1678 if (stream != NULL) { 1679 cam_dimension_t dim; 1680 memset(&dim, 0, sizeof(dim)); 1681 stream->getFrameDimension(dim); 1682 1683 cam_frame_len_offset_t offset; 1684 memset(&offset, 0, sizeof(cam_frame_len_offset_t)); 1685 stream->getFrameOffset(offset); 1686 1687 uint32_t raw16_stride = (uint32_t)PAD_TO_SIZE(dim.width, 32); 1688 uint16_t* raw16_buffer = (uint16_t *)frame->buffer; 1689 1690 // In-place format conversion. 1691 // Raw16 format always occupy more memory than opaque raw10. 1692 // Convert to Raw16 by iterating through all pixels from bottom-right 1693 // to top-left of the image. 1694 // One special notes: 1695 // 1. Cross-platform raw16's stride is 16 pixels. 1696 // 2. Opaque raw10's stride is 6 pixels, and aligned to 16 bytes. 1697 for (int32_t ys = dim.height - 1; ys >= 0; ys--) { 1698 uint32_t y = (uint32_t)ys; 1699 uint64_t* row_start = (uint64_t *)frame->buffer + 1700 y * (uint32_t)offset.mp[0].stride_in_bytes / 8; 1701 for (int32_t xs = dim.width - 1; xs >= 0; xs--) { 1702 uint32_t x = (uint32_t)xs; 1703 uint16_t raw16_pixel = 0x3FF & (row_start[x/6] >> (10*(x%6))); 1704 raw16_buffer[y*raw16_stride+x] = raw16_pixel; 1705 } 1706 } 1707 } else { 1708 ALOGE("%s: Could not find stream", __func__); 1709 } 1710 1711 } 1712 1713 void QCamera3RawChannel::convertMipiToRaw16(mm_camera_buf_def_t *frame) 1714 { 1715 // Convert image buffer from mipi10 raw format to RAW16 format 1716 // mipi10 opaque raw is stored in the format of: 1717 // P3(1:0) P2(1:0) P1(1:0) P0(1:0) P3(9:2) P2(9:2) P1(9:2) P0(9:2) 1718 // 4 pixels occupy 5 bytes, no padding needed 1719 1720 QCamera3Stream *stream = getStreamByIndex(0); 1721 if (stream != NULL) { 1722 cam_dimension_t dim; 1723 memset(&dim, 0, sizeof(dim)); 1724 stream->getFrameDimension(dim); 1725 1726 cam_frame_len_offset_t offset; 1727 memset(&offset, 0, sizeof(cam_frame_len_offset_t)); 1728 stream->getFrameOffset(offset); 1729 1730 uint32_t raw16_stride = (uint32_t)PAD_TO_SIZE(dim.width, 32); 1731 uint16_t* raw16_buffer = (uint16_t *)frame->buffer; 1732 1733 // In-place format conversion. 1734 // Raw16 format always occupy more memory than opaque raw10. 1735 // Convert to Raw16 by iterating through all pixels from bottom-right 1736 // to top-left of the image. 1737 // One special notes: 1738 // 1. Cross-platform raw16's stride is 16 pixels. 1739 // 2. mipi raw10's stride is 4 pixels, and aligned to 16 bytes. 1740 for (int32_t ys = dim.height - 1; ys >= 0; ys--) { 1741 uint32_t y = (uint32_t)ys; 1742 uint8_t* row_start = (uint8_t *)frame->buffer + 1743 y * (uint32_t)offset.mp[0].stride_in_bytes; 1744 for (int32_t xs = dim.width - 1; xs >= 0; xs--) { 1745 uint32_t x = (uint32_t)xs; 1746 uint8_t upper_8bit = row_start[5*(x/4)+x%4]; 1747 uint8_t lower_2bit = ((row_start[5*(x/4)+4] >> (x%4)) & 0x3); 1748 uint16_t raw16_pixel = 1749 (uint16_t)(((uint16_t)upper_8bit)<<2 | 1750 (uint16_t)lower_2bit); 1751 raw16_buffer[y*raw16_stride+x] = raw16_pixel; 1752 } 1753 } 1754 } else { 1755 ALOGE("%s: Could not find stream", __func__); 1756 } 1757 1758 } 1759 1760 /*=========================================================================== 1761 * FUNCTION : getReprocessType 1762 * 1763 * DESCRIPTION: get the type of reprocess output supported by this channel 1764 * 1765 * PARAMETERS : NONE 1766 * 1767 * RETURN : reprocess_type_t : type of reprocess 1768 *==========================================================================*/ 1769 reprocess_type_t QCamera3RawChannel::getReprocessType() 1770 { 1771 return REPROCESS_TYPE_RAW; 1772 } 1773 1774 1775 /*************************************************************************************/ 1776 // RAW Dump Channel related functions 1777 1778 /*=========================================================================== 1779 * FUNCTION : QCamera3RawDumpChannel 1780 * 1781 * DESCRIPTION: Constructor for RawDumpChannel 1782 * 1783 * PARAMETERS : 1784 * @cam_handle : Handle for Camera 1785 * @cam_ops : Function pointer table 1786 * @rawDumpSize : Dimensions for the Raw stream 1787 * @paddinginfo : Padding information for stream 1788 * @userData : Cookie for parent 1789 * @pp mask : PP feature mask for this stream 1790 * @numBuffers : number of max dequeued buffers 1791 * 1792 * RETURN : NA 1793 *==========================================================================*/ 1794 QCamera3RawDumpChannel::QCamera3RawDumpChannel(uint32_t cam_handle, 1795 mm_camera_ops_t *cam_ops, 1796 cam_dimension_t rawDumpSize, 1797 cam_padding_info_t *paddingInfo, 1798 void *userData, 1799 uint32_t postprocess_mask, uint32_t numBuffers) : 1800 QCamera3Channel(cam_handle, cam_ops, NULL, 1801 paddingInfo, postprocess_mask, 1802 userData, numBuffers), 1803 mDim(rawDumpSize), 1804 mMemory(NULL) 1805 { 1806 char prop[PROPERTY_VALUE_MAX]; 1807 property_get("persist.camera.raw.dump", prop, "0"); 1808 mRawDump = atoi(prop); 1809 } 1810 1811 /*=========================================================================== 1812 * FUNCTION : QCamera3RawDumpChannel 1813 * 1814 * DESCRIPTION: Destructor for RawDumpChannel 1815 * 1816 * PARAMETERS : 1817 * 1818 * RETURN : NA 1819 *==========================================================================*/ 1820 1821 QCamera3RawDumpChannel::~QCamera3RawDumpChannel() 1822 { 1823 } 1824 1825 /*=========================================================================== 1826 * FUNCTION : dumpRawSnapshot 1827 * 1828 * DESCRIPTION: Helper function to dump Raw frames 1829 * 1830 * PARAMETERS : 1831 * @frame : stream buf frame to be dumped 1832 * 1833 * RETURN : NA 1834 *==========================================================================*/ 1835 void QCamera3RawDumpChannel::dumpRawSnapshot(mm_camera_buf_def_t *frame) 1836 { 1837 QCamera3Stream *stream = getStreamByIndex(0); 1838 if (stream != NULL) { 1839 char buf[FILENAME_MAX]; 1840 struct timeval tv; 1841 struct tm timeinfo_data; 1842 struct tm *timeinfo; 1843 1844 cam_dimension_t dim; 1845 memset(&dim, 0, sizeof(dim)); 1846 stream->getFrameDimension(dim); 1847 1848 cam_frame_len_offset_t offset; 1849 memset(&offset, 0, sizeof(cam_frame_len_offset_t)); 1850 stream->getFrameOffset(offset); 1851 1852 gettimeofday(&tv, NULL); 1853 timeinfo = localtime_r(&tv.tv_sec, &timeinfo_data); 1854 1855 if (NULL != timeinfo) { 1856 memset(buf, 0, sizeof(buf)); 1857 snprintf(buf, sizeof(buf), 1858 QCAMERA_DUMP_FRM_LOCATION 1859 "%04d-%02d-%02d-%02d-%02d-%02d-%06ld_%d_%dx%d.raw", 1860 timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, 1861 timeinfo->tm_mday, timeinfo->tm_hour, 1862 timeinfo->tm_min, timeinfo->tm_sec,tv.tv_usec, 1863 frame->frame_idx, dim.width, dim.height); 1864 1865 int file_fd = open(buf, O_RDWR| O_CREAT, 0777); 1866 if (file_fd >= 0) { 1867 ssize_t written_len = 1868 write(file_fd, frame->buffer, offset.frame_len); 1869 CDBG("%s: written number of bytes %zd", __func__, written_len); 1870 close(file_fd); 1871 } else { 1872 ALOGE("%s: failed to open file to dump image", __func__); 1873 } 1874 } else { 1875 ALOGE("%s: localtime_r() error", __func__); 1876 } 1877 } else { 1878 ALOGE("%s: Could not find stream", __func__); 1879 } 1880 1881 } 1882 1883 /*=========================================================================== 1884 * FUNCTION : streamCbRoutine 1885 * 1886 * DESCRIPTION: Callback routine invoked for each frame generated for 1887 * Rawdump channel 1888 * 1889 * PARAMETERS : 1890 * @super_frame : stream buf frame generated 1891 * @stream : Underlying Stream object cookie 1892 * 1893 * RETURN : NA 1894 *==========================================================================*/ 1895 void QCamera3RawDumpChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame, 1896 QCamera3Stream *stream) 1897 { 1898 CDBG("%s: E",__func__); 1899 if (super_frame == NULL || super_frame->num_bufs != 1) { 1900 ALOGE("%s: super_frame is not valid", __func__); 1901 return; 1902 } 1903 1904 if (mRawDump) 1905 dumpRawSnapshot(super_frame->bufs[0]); 1906 1907 bufDone(super_frame); 1908 free(super_frame); 1909 } 1910 1911 /*=========================================================================== 1912 * FUNCTION : getStreamBufs 1913 * 1914 * DESCRIPTION: Callback function provided to interface to get buffers. 1915 * 1916 * PARAMETERS : 1917 * @len : Length of each buffer to be allocated 1918 * 1919 * RETURN : NULL on buffer allocation failure 1920 * QCamera3Memory object on sucess 1921 *==========================================================================*/ 1922 QCamera3Memory* QCamera3RawDumpChannel::getStreamBufs(uint32_t len) 1923 { 1924 int rc; 1925 mMemory = new QCamera3HeapMemory(); 1926 1927 if (!mMemory) { 1928 ALOGE("%s: unable to create heap memory", __func__); 1929 return NULL; 1930 } 1931 rc = mMemory->allocate(mNumBuffers, (size_t)len, true); 1932 if (rc < 0) { 1933 ALOGE("%s: unable to allocate heap memory", __func__); 1934 delete mMemory; 1935 mMemory = NULL; 1936 return NULL; 1937 } 1938 return mMemory; 1939 } 1940 1941 /*=========================================================================== 1942 * FUNCTION : putStreamBufs 1943 * 1944 * DESCRIPTION: Callback function provided to interface to return buffers. 1945 * Although no handles are actually returned, implicitl assumption 1946 * that interface will no longer use buffers and channel can 1947 * deallocated if necessary. 1948 * 1949 * PARAMETERS : NA 1950 * 1951 * RETURN : NA 1952 *==========================================================================*/ 1953 void QCamera3RawDumpChannel::putStreamBufs() 1954 { 1955 mMemory->deallocate(); 1956 delete mMemory; 1957 mMemory = NULL; 1958 } 1959 1960 /*=========================================================================== 1961 * FUNCTION : request 1962 * 1963 * DESCRIPTION: Request function used as trigger 1964 * 1965 * PARAMETERS : 1966 * @recvd_frame : buffer- this will be NULL since this is internal channel 1967 * @frameNumber : Undefined again since this is internal stream 1968 * 1969 * RETURN : int32_t type of status 1970 * NO_ERROR -- success 1971 * none-zero failure code 1972 *==========================================================================*/ 1973 int32_t QCamera3RawDumpChannel::request(buffer_handle_t * /*buffer*/, 1974 uint32_t /*frameNumber*/) 1975 { 1976 if (!m_bIsActive) { 1977 return QCamera3Channel::start(); 1978 } 1979 else 1980 return 0; 1981 } 1982 1983 /*=========================================================================== 1984 * FUNCTION : intialize 1985 * 1986 * DESCRIPTION: Initializes channel params and creates underlying stream 1987 * 1988 * PARAMETERS : 1989 * @isType : type of image stabilization required on this stream 1990 * 1991 * RETURN : int32_t type of status 1992 * NO_ERROR -- success 1993 * none-zero failure code 1994 *==========================================================================*/ 1995 int32_t QCamera3RawDumpChannel::initialize(cam_is_type_t isType) 1996 { 1997 int32_t rc; 1998 1999 rc = init(NULL, NULL); 2000 if (rc < 0) { 2001 ALOGE("%s: init failed", __func__); 2002 return rc; 2003 } 2004 mIsType = isType; 2005 rc = QCamera3Channel::addStream(CAM_STREAM_TYPE_RAW, 2006 CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG, mDim, ROTATE_0, (uint8_t)mNumBuffers, 2007 mPostProcMask, mIsType); 2008 if (rc < 0) { 2009 ALOGE("%s: addStream failed", __func__); 2010 } 2011 return rc; 2012 } 2013 /*************************************************************************************/ 2014 2015 /* QCamera3YUVChannel methods */ 2016 2017 /*=========================================================================== 2018 * FUNCTION : QCamera3YUVChannel 2019 * 2020 * DESCRIPTION: constructor of QCamera3YUVChannel 2021 * 2022 * PARAMETERS : 2023 * @cam_handle : camera handle 2024 * @cam_ops : ptr to camera ops table 2025 * @cb_routine : callback routine to frame aggregator 2026 * @paddingInfo : padding information for the stream 2027 * @stream : camera3_stream_t structure 2028 * @stream_type: Channel stream type 2029 * @postprocess_mask: the postprocess mask for streams of this channel 2030 * @metadataChannel: handle to the metadataChannel 2031 * RETURN : none 2032 *==========================================================================*/ 2033 QCamera3YUVChannel::QCamera3YUVChannel(uint32_t cam_handle, 2034 mm_camera_ops_t *cam_ops, 2035 channel_cb_routine cb_routine, 2036 cam_padding_info_t *paddingInfo, 2037 void *userData, 2038 camera3_stream_t *stream, 2039 cam_stream_type_t stream_type, 2040 uint32_t postprocess_mask, 2041 QCamera3Channel *metadataChannel) : 2042 QCamera3ProcessingChannel(cam_handle, cam_ops, cb_routine, 2043 paddingInfo, userData, stream, stream_type, postprocess_mask, 2044 metadataChannel) 2045 { 2046 } 2047 2048 /*=========================================================================== 2049 * FUNCTION : ~QCamera3YUVChannel 2050 * 2051 * DESCRIPTION: destructor of QCamera3YUVChannel 2052 * 2053 * PARAMETERS : none 2054 * 2055 * 2056 * RETURN : none 2057 *==========================================================================*/ 2058 QCamera3YUVChannel::~QCamera3YUVChannel() 2059 { 2060 } 2061 2062 /*=========================================================================== 2063 * FUNCTION : initialize 2064 * 2065 * DESCRIPTION: Initialize and add camera channel & stream 2066 * 2067 * PARAMETERS : 2068 * @isType : the image stabilization type 2069 * 2070 * RETURN : int32_t type of status 2071 * NO_ERROR -- success 2072 * none-zero failure code 2073 *==========================================================================*/ 2074 int32_t QCamera3YUVChannel::initialize(cam_is_type_t isType) 2075 { 2076 ATRACE_CALL(); 2077 int32_t rc = NO_ERROR; 2078 cam_dimension_t streamDim; 2079 2080 if (NULL == mCamera3Stream) { 2081 ALOGE("%s: Camera stream uninitialized", __func__); 2082 return NO_INIT; 2083 } 2084 2085 if (1 <= m_numStreams) { 2086 // Only one stream per channel supported in v3 Hal 2087 return NO_ERROR; 2088 } 2089 2090 rc = init(NULL, NULL); 2091 if (rc < 0) { 2092 ALOGE("%s: init failed", __func__); 2093 return rc; 2094 } 2095 2096 mIsType = isType; 2097 mStreamFormat = CALLBACK_FORMAT; 2098 streamDim.width = mCamera3Stream->width; 2099 streamDim.height = mCamera3Stream->height; 2100 2101 rc = QCamera3Channel::addStream(mStreamType, 2102 mStreamFormat, 2103 streamDim, 2104 ROTATE_0, 2105 mNumBufs, 2106 mPostProcMask, 2107 mIsType); 2108 2109 return rc; 2110 } 2111 2112 /*=========================================================================== 2113 * FUNCTION : start 2114 * 2115 * DESCRIPTION: start a YUV channel 2116 * 2117 * PARAMETERS : 2118 * 2119 * RETURN : int32_t type of status 2120 * NO_ERROR -- success 2121 * none-zero failure code 2122 *==========================================================================*/ 2123 int32_t QCamera3YUVChannel::start() 2124 { 2125 ATRACE_CALL(); 2126 int32_t rc = NO_ERROR; 2127 2128 if (0 < mMemory.getCnt()) { 2129 rc = QCamera3Channel::start(); 2130 } 2131 return rc; 2132 } 2133 2134 /*=========================================================================== 2135 * FUNCTION : getReprocessType 2136 * 2137 * DESCRIPTION: get the type of reprocess output supported by this channel 2138 * 2139 * PARAMETERS : NONE 2140 * 2141 * RETURN : reprocess_type_t : type of reprocess 2142 *==========================================================================*/ 2143 reprocess_type_t QCamera3YUVChannel::getReprocessType() 2144 { 2145 return REPROCESS_TYPE_YUV; 2146 } 2147 2148 /* QCamera3PicChannel methods */ 2149 2150 /*=========================================================================== 2151 * FUNCTION : jpegEvtHandle 2152 * 2153 * DESCRIPTION: Function registerd to mm-jpeg-interface to handle jpeg events. 2154 Construct result payload and call mChannelCb to deliver buffer 2155 to framework. 2156 * 2157 * PARAMETERS : 2158 * @status : status of jpeg job 2159 * @client_hdl: jpeg client handle 2160 * @jobId : jpeg job Id 2161 * @p_ouput : ptr to jpeg output result struct 2162 * @userdata : user data ptr 2163 * 2164 * RETURN : none 2165 *==========================================================================*/ 2166 void QCamera3PicChannel::jpegEvtHandle(jpeg_job_status_t status, 2167 uint32_t /*client_hdl*/, 2168 uint32_t jobId, 2169 mm_jpeg_output_t *p_output, 2170 void *userdata) 2171 { 2172 ATRACE_CALL(); 2173 buffer_handle_t *resultBuffer = NULL; 2174 buffer_handle_t *jpegBufferHandle = NULL; 2175 int resultStatus = CAMERA3_BUFFER_STATUS_OK; 2176 camera3_stream_buffer_t result; 2177 camera3_jpeg_blob_t jpegHeader; 2178 2179 QCamera3PicChannel *obj = (QCamera3PicChannel *)userdata; 2180 if (obj) { 2181 //Construct payload for process_capture_result. Call mChannelCb 2182 2183 qcamera_hal3_jpeg_data_t *job = obj->m_postprocessor.findJpegJobByJobId(jobId); 2184 2185 if ((job == NULL) || (status == JPEG_JOB_STATUS_ERROR)) { 2186 ALOGE("%s: Error in jobId: (%d) with status: %d", __func__, jobId, status); 2187 resultStatus = CAMERA3_BUFFER_STATUS_ERROR; 2188 } 2189 2190 if (NULL != job) { 2191 uint32_t bufIdx = (uint32_t)job->jpeg_settings->out_buf_index; 2192 CDBG("%s: jpeg out_buf_index: %d", __func__, bufIdx); 2193 2194 //Construct jpeg transient header of type camera3_jpeg_blob_t 2195 //Append at the end of jpeg image of buf_filled_len size 2196 2197 jpegHeader.jpeg_blob_id = CAMERA3_JPEG_BLOB_ID; 2198 if (JPEG_JOB_STATUS_DONE == status) { 2199 jpegHeader.jpeg_size = (uint32_t)p_output->buf_filled_len; 2200 char* jpeg_buf = (char *)p_output->buf_vaddr; 2201 2202 ssize_t maxJpegSize = -1; 2203 2204 // Gralloc buffer may have additional padding for 4K page size 2205 // Follow size guidelines based on spec since framework relies 2206 // on that to reach end of buffer and with it the header 2207 2208 //Handle same as resultBuffer, but for readablity 2209 jpegBufferHandle = 2210 (buffer_handle_t *)obj->mMemory.getBufferHandle(bufIdx); 2211 2212 if (NULL != jpegBufferHandle) { 2213 maxJpegSize = ((private_handle_t*)(*jpegBufferHandle))->width; 2214 if (maxJpegSize > obj->mMemory.getSize(bufIdx)) { 2215 maxJpegSize = obj->mMemory.getSize(bufIdx); 2216 } 2217 2218 size_t jpeg_eof_offset = 2219 (size_t)(maxJpegSize - (ssize_t)sizeof(jpegHeader)); 2220 char *jpeg_eof = &jpeg_buf[jpeg_eof_offset]; 2221 memcpy(jpeg_eof, &jpegHeader, sizeof(jpegHeader)); 2222 obj->mMemory.cleanInvalidateCache(bufIdx); 2223 } else { 2224 ALOGE("%s: JPEG buffer not found and index: %d", 2225 __func__, 2226 bufIdx); 2227 resultStatus = CAMERA3_BUFFER_STATUS_ERROR; 2228 } 2229 } 2230 2231 ////Use below data to issue framework callback 2232 resultBuffer = 2233 (buffer_handle_t *)obj->mMemory.getBufferHandle(bufIdx); 2234 int32_t resultFrameNumber = obj->mMemory.getFrameNumber(bufIdx); 2235 int32_t rc = obj->mMemory.unregisterBuffer(bufIdx); 2236 if (NO_ERROR != rc) { 2237 ALOGE("%s: Error %d unregistering stream buffer %d", 2238 __func__, rc, bufIdx); 2239 } 2240 2241 result.stream = obj->mCamera3Stream; 2242 result.buffer = resultBuffer; 2243 result.status = resultStatus; 2244 result.acquire_fence = -1; 2245 result.release_fence = -1; 2246 2247 // Release any snapshot buffers before calling 2248 // the user callback. The callback can potentially 2249 // unblock pending requests to snapshot stream. 2250 int32_t snapshotIdx = -1; 2251 mm_camera_super_buf_t* src_frame = NULL; 2252 2253 if (job->src_reproc_frame) 2254 src_frame = job->src_reproc_frame; 2255 else 2256 src_frame = job->src_frame; 2257 2258 if (src_frame) { 2259 if (obj->mStreams[0]->getMyHandle() == 2260 src_frame->bufs[0]->stream_id) { 2261 snapshotIdx = (int32_t)src_frame->bufs[0]->buf_idx; 2262 } else { 2263 ALOGE("%s: Snapshot stream id %d and source frame %d don't match!", 2264 __func__, obj->mStreams[0]->getMyHandle(), 2265 src_frame->bufs[0]->stream_id); 2266 } 2267 } 2268 if (0 <= snapshotIdx) { 2269 Mutex::Autolock lock(obj->mFreeBuffersLock); 2270 obj->mFreeBufferList.push_back((uint32_t)snapshotIdx); 2271 } else { 2272 ALOGE("%s: Snapshot buffer not found!", __func__); 2273 } 2274 2275 CDBG("%s: Issue Callback", __func__); 2276 obj->mChannelCB(NULL, 2277 &result, 2278 (uint32_t)resultFrameNumber, 2279 obj->mUserData); 2280 2281 // release internal data for jpeg job 2282 if ((NULL != job->fwk_frame) || (NULL != job->fwk_src_buffer)) { 2283 obj->mOfflineMetaMemory.deallocate(); 2284 obj->mOfflineMemory.unregisterBuffers(); 2285 } 2286 obj->m_postprocessor.releaseOfflineBuffers(); 2287 obj->m_postprocessor.releaseJpegJobData(job); 2288 free(job); 2289 } 2290 2291 return; 2292 // } 2293 } else { 2294 ALOGE("%s: Null userdata in jpeg callback", __func__); 2295 } 2296 } 2297 2298 QCamera3PicChannel::QCamera3PicChannel(uint32_t cam_handle, 2299 mm_camera_ops_t *cam_ops, 2300 channel_cb_routine cb_routine, 2301 cam_padding_info_t *paddingInfo, 2302 void *userData, 2303 camera3_stream_t *stream, 2304 uint32_t postprocess_mask, 2305 bool is4KVideo, 2306 QCamera3Channel *metadataChannel, 2307 uint32_t numBuffers) : 2308 QCamera3ProcessingChannel(cam_handle, cam_ops, cb_routine, 2309 paddingInfo, userData, stream, CAM_STREAM_TYPE_SNAPSHOT, 2310 postprocess_mask, metadataChannel, numBuffers), 2311 mNumSnapshotBufs(0), 2312 mCurrentBufIndex(-1), 2313 mYuvMemory(NULL) 2314 { 2315 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData; 2316 m_max_pic_dim = hal_obj->calcMaxJpegDim(); 2317 mYuvWidth = stream->width; 2318 mYuvHeight = stream->height; 2319 mStreamType = CAM_STREAM_TYPE_SNAPSHOT; 2320 // Use same pixelformat for 4K video case 2321 mStreamFormat = is4KVideo ? VIDEO_FORMAT : SNAPSHOT_FORMAT; 2322 int32_t rc = m_postprocessor.initJpeg(jpegEvtHandle, &m_max_pic_dim, this); 2323 if (rc != 0) { 2324 ALOGE("Init Postprocessor failed"); 2325 } 2326 } 2327 2328 QCamera3PicChannel::~QCamera3PicChannel() 2329 { 2330 } 2331 2332 int32_t QCamera3PicChannel::initialize(cam_is_type_t isType) 2333 { 2334 int32_t rc = NO_ERROR; 2335 cam_dimension_t streamDim; 2336 cam_stream_type_t streamType; 2337 cam_format_t streamFormat; 2338 mm_camera_channel_attr_t attr; 2339 2340 if (NULL == mCamera3Stream) { 2341 ALOGE("%s: Camera stream uninitialized", __func__); 2342 return NO_INIT; 2343 } 2344 2345 if (1 <= m_numStreams) { 2346 // Only one stream per channel supported in v3 Hal 2347 return NO_ERROR; 2348 } 2349 2350 memset(&attr, 0, sizeof(mm_camera_channel_attr_t)); 2351 attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_BURST; 2352 attr.look_back = 1; 2353 attr.post_frame_skip = 1; 2354 attr.water_mark = 1; 2355 attr.max_unmatched_frames = 1; 2356 2357 rc = init(&attr, NULL); 2358 if (rc < 0) { 2359 ALOGE("%s: init failed", __func__); 2360 return rc; 2361 } 2362 mIsType = isType; 2363 streamType = mStreamType; 2364 streamFormat = mStreamFormat; 2365 streamDim.width = (int32_t)mYuvWidth; 2366 streamDim.height = (int32_t)mYuvHeight; 2367 2368 mNumSnapshotBufs = mCamera3Stream->max_buffers; 2369 rc = QCamera3Channel::addStream(streamType, streamFormat, streamDim, 2370 ROTATE_0, (uint8_t)mCamera3Stream->max_buffers, mPostProcMask, 2371 mIsType); 2372 2373 Mutex::Autolock lock(mFreeBuffersLock); 2374 mFreeBufferList.clear(); 2375 for (uint32_t i = 0; i < mCamera3Stream->max_buffers; i++) { 2376 mFreeBufferList.push_back(i); 2377 } 2378 2379 return rc; 2380 } 2381 2382 int32_t QCamera3PicChannel::request(buffer_handle_t *buffer, 2383 uint32_t frameNumber, 2384 camera3_stream_buffer_t *pInputBuffer, 2385 metadata_buffer_t *metadata) 2386 { 2387 ATRACE_CALL(); 2388 //FIX ME: Return buffer back in case of failures below. 2389 2390 int32_t rc = NO_ERROR; 2391 2392 reprocess_config_t reproc_cfg; 2393 memset(&reproc_cfg, 0, sizeof(reprocess_config_t)); 2394 setReprocConfig(reproc_cfg, pInputBuffer, metadata, mStreamFormat); 2395 //make sure to set the correct input stream dim in case of YUV size override 2396 //and recalculate the plane info 2397 if (pInputBuffer == NULL) { 2398 reproc_cfg.input_stream_dim.width = (int32_t)mYuvWidth; 2399 reproc_cfg.input_stream_dim.height = (int32_t)mYuvHeight; 2400 rc = mm_stream_calc_offset_snapshot(mStreamFormat, &reproc_cfg.input_stream_dim, 2401 reproc_cfg.padding, &reproc_cfg.input_stream_plane_info); 2402 if (rc != 0) { 2403 ALOGE("%s: Stream %d plane info calculation failed!", __func__, mStreamType); 2404 } 2405 } 2406 2407 // Picture stream has already been started before any request comes in 2408 if (!m_bIsActive) { 2409 ALOGE("%s: Channel not started!!", __func__); 2410 return NO_INIT; 2411 } 2412 2413 int index = mMemory.getMatchBufIndex((void*)buffer); 2414 2415 if(index < 0) { 2416 rc = registerBuffer(buffer, mIsType); 2417 if (NO_ERROR != rc) { 2418 ALOGE("%s: On-the-fly buffer registration failed %d", 2419 __func__, rc); 2420 return rc; 2421 } 2422 2423 index = mMemory.getMatchBufIndex((void*)buffer); 2424 if (index < 0) { 2425 ALOGE("%s: Could not find object among registered buffers",__func__); 2426 return DEAD_OBJECT; 2427 } 2428 } 2429 CDBG("%s: buffer index %d, frameNumber: %u", __func__, index, frameNumber); 2430 2431 rc = mMemory.markFrameNumber((uint32_t)index, frameNumber); 2432 2433 //Start the postprocessor for jpeg encoding. Pass mMemory as destination buffer 2434 mCurrentBufIndex = (uint32_t)index; 2435 2436 // Start postprocessor 2437 startPostProc((NULL != pInputBuffer), reproc_cfg); 2438 2439 // Queue jpeg settings 2440 rc = queueJpegSetting((uint32_t)index, metadata); 2441 2442 if (pInputBuffer == NULL) { 2443 Mutex::Autolock lock(mFreeBuffersLock); 2444 if (!mFreeBufferList.empty()) { 2445 List<uint32_t>::iterator it = mFreeBufferList.begin(); 2446 uint32_t freeBuffer = *it; 2447 mStreams[0]->bufDone(freeBuffer); 2448 mFreeBufferList.erase(it); 2449 } else { 2450 ALOGE("%s: No snapshot buffers available!", __func__); 2451 rc = NOT_ENOUGH_DATA; 2452 } 2453 } else { 2454 if (0 < mOfflineMetaMemory.getCnt()) { 2455 mOfflineMetaMemory.deallocate(); 2456 } 2457 if (0 < mOfflineMemory.getCnt()) { 2458 mOfflineMemory.unregisterBuffers(); 2459 } 2460 2461 int input_index = mOfflineMemory.getMatchBufIndex((void*)pInputBuffer->buffer); 2462 if(input_index < 0) { 2463 rc = mOfflineMemory.registerBuffer(pInputBuffer->buffer, mStreamType); 2464 if (NO_ERROR != rc) { 2465 ALOGE("%s: On-the-fly input buffer registration failed %d", 2466 __func__, rc); 2467 return rc; 2468 } 2469 2470 input_index = mOfflineMemory.getMatchBufIndex((void*)pInputBuffer->buffer); 2471 if (input_index < 0) { 2472 ALOGE("%s: Could not find object among registered buffers",__func__); 2473 return DEAD_OBJECT; 2474 } 2475 } 2476 qcamera_fwk_input_pp_data_t *src_frame = NULL; 2477 src_frame = (qcamera_fwk_input_pp_data_t *)malloc( 2478 sizeof(qcamera_fwk_input_pp_data_t)); 2479 if (src_frame == NULL) { 2480 ALOGE("%s: No memory for src frame", __func__); 2481 return NO_MEMORY; 2482 } 2483 memset(src_frame, 0, sizeof(qcamera_fwk_input_pp_data_t)); 2484 src_frame->src_frame = *pInputBuffer; 2485 rc = mOfflineMemory.getBufDef(reproc_cfg.input_stream_plane_info.plane_info, 2486 src_frame->input_buffer, (uint32_t)input_index); 2487 if (rc != 0) { 2488 free(src_frame); 2489 return rc; 2490 } 2491 if (mYUVDump) { 2492 dumpYUV(&src_frame->input_buffer, reproc_cfg.input_stream_dim, 2493 reproc_cfg.input_stream_plane_info.plane_info, 1); 2494 } 2495 cam_dimension_t dim = {(int)sizeof(metadata_buffer_t), 1}; 2496 cam_stream_buf_plane_info_t meta_planes; 2497 rc = mm_stream_calc_offset_metadata(&dim, mPaddingInfo, &meta_planes); 2498 if (rc != 0) { 2499 ALOGE("%s: Metadata stream plane info calculation failed!", __func__); 2500 free(src_frame); 2501 return rc; 2502 } 2503 2504 rc = mOfflineMetaMemory.allocate(1, sizeof(metadata_buffer_t), false); 2505 if (NO_ERROR != rc) { 2506 ALOGE("%s: Couldn't allocate offline metadata buffer!", __func__); 2507 free(src_frame); 2508 return rc; 2509 } 2510 mm_camera_buf_def_t meta_buf; 2511 cam_frame_len_offset_t offset = meta_planes.plane_info; 2512 rc = mOfflineMetaMemory.getBufDef(offset, meta_buf, 0); 2513 if (NO_ERROR != rc) { 2514 free(src_frame); 2515 return rc; 2516 } 2517 memcpy(meta_buf.buffer, metadata, sizeof(metadata_buffer_t)); 2518 src_frame->metadata_buffer = meta_buf; 2519 src_frame->reproc_config = reproc_cfg; 2520 src_frame->output_buffer = NULL; 2521 src_frame->frameNumber = frameNumber; 2522 2523 CDBG_HIGH("%s: Post-process started", __func__); 2524 CDBG_HIGH("%s: Issue call to reprocess", __func__); 2525 2526 m_postprocessor.processData(src_frame); 2527 } 2528 return rc; 2529 } 2530 2531 2532 /*=========================================================================== 2533 * FUNCTION : dataNotifyCB 2534 * 2535 * DESCRIPTION: Channel Level callback used for super buffer data notify. 2536 * This function is registered with mm-camera-interface to handle 2537 * data notify 2538 * 2539 * PARAMETERS : 2540 * @recvd_frame : stream frame received 2541 * userdata : user data ptr 2542 * 2543 * RETURN : none 2544 *==========================================================================*/ 2545 void QCamera3PicChannel::dataNotifyCB(mm_camera_super_buf_t *recvd_frame, 2546 void *userdata) 2547 { 2548 ATRACE_CALL(); 2549 CDBG("%s: E\n", __func__); 2550 QCamera3PicChannel *channel = (QCamera3PicChannel *)userdata; 2551 2552 if (channel == NULL) { 2553 ALOGE("%s: invalid channel pointer", __func__); 2554 return; 2555 } 2556 2557 if(channel->m_numStreams != 1) { 2558 ALOGE("%s: Error: Bug: This callback assumes one stream per channel",__func__); 2559 return; 2560 } 2561 2562 2563 if(channel->mStreams[0] == NULL) { 2564 ALOGE("%s: Error: Invalid Stream object",__func__); 2565 return; 2566 } 2567 2568 channel->QCamera3PicChannel::streamCbRoutine(recvd_frame, channel->mStreams[0]); 2569 2570 CDBG("%s: X\n", __func__); 2571 return; 2572 } 2573 2574 void QCamera3PicChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame, 2575 QCamera3Stream *stream) 2576 { 2577 ATRACE_CALL(); 2578 //TODO 2579 //Used only for getting YUV. Jpeg callback will be sent back from channel 2580 //directly to HWI. Refer to func jpegEvtHandle 2581 2582 //Got the yuv callback. Calling yuv callback handler in PostProc 2583 uint8_t frameIndex; 2584 mm_camera_super_buf_t* frame = NULL; 2585 if(!super_frame) { 2586 ALOGE("%s: Invalid Super buffer",__func__); 2587 return; 2588 } 2589 2590 if(super_frame->num_bufs != 1) { 2591 ALOGE("%s: Multiple streams are not supported",__func__); 2592 return; 2593 } 2594 if(super_frame->bufs[0] == NULL ) { 2595 ALOGE("%s: Error, Super buffer frame does not contain valid buffer", 2596 __func__); 2597 return; 2598 } 2599 2600 frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx; 2601 CDBG("%s: recvd buf_idx: %u for further processing", 2602 __func__, (uint32_t)frameIndex); 2603 if(frameIndex >= mNumSnapshotBufs) { 2604 ALOGE("%s: Error, Invalid index for buffer",__func__); 2605 if(stream) { 2606 Mutex::Autolock lock(mFreeBuffersLock); 2607 mFreeBufferList.push_back(frameIndex); 2608 stream->bufDone(frameIndex); 2609 } 2610 return; 2611 } 2612 2613 frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t)); 2614 if (frame == NULL) { 2615 ALOGE("%s: Error allocating memory to save received_frame structure.", 2616 __func__); 2617 if(stream) { 2618 Mutex::Autolock lock(mFreeBuffersLock); 2619 mFreeBufferList.push_back(frameIndex); 2620 stream->bufDone(frameIndex); 2621 } 2622 return; 2623 } 2624 *frame = *super_frame; 2625 2626 if (mYUVDump) { 2627 cam_dimension_t dim; 2628 memset(&dim, 0, sizeof(dim)); 2629 stream->getFrameDimension(dim); 2630 cam_frame_len_offset_t offset; 2631 memset(&offset, 0, sizeof(cam_frame_len_offset_t)); 2632 stream->getFrameOffset(offset); 2633 dumpYUV(frame->bufs[0], dim, offset, 1); 2634 } 2635 2636 m_postprocessor.processData(frame); 2637 free(super_frame); 2638 return; 2639 } 2640 2641 QCamera3Memory* QCamera3PicChannel::getStreamBufs(uint32_t len) 2642 { 2643 int rc = 0; 2644 2645 mYuvMemory = new QCamera3HeapMemory(); 2646 if (!mYuvMemory) { 2647 ALOGE("%s: unable to create metadata memory", __func__); 2648 return NULL; 2649 } 2650 2651 //Queue YUV buffers in the beginning mQueueAll = true 2652 rc = mYuvMemory->allocate(mCamera3Stream->max_buffers, len, false); 2653 if (rc < 0) { 2654 ALOGE("%s: unable to allocate metadata memory", __func__); 2655 delete mYuvMemory; 2656 mYuvMemory = NULL; 2657 return NULL; 2658 } 2659 return mYuvMemory; 2660 } 2661 2662 void QCamera3PicChannel::putStreamBufs() 2663 { 2664 mMemory.unregisterBuffers(); 2665 2666 mYuvMemory->deallocate(); 2667 delete mYuvMemory; 2668 mYuvMemory = NULL; 2669 } 2670 2671 int32_t QCamera3PicChannel::queueJpegSetting(uint32_t index, metadata_buffer_t *metadata) 2672 { 2673 jpeg_settings_t *settings = 2674 (jpeg_settings_t *)malloc(sizeof(jpeg_settings_t)); 2675 2676 if (!settings) { 2677 ALOGE("%s: out of memory allocating jpeg_settings", __func__); 2678 return -ENOMEM; 2679 } 2680 2681 memset(settings, 0, sizeof(jpeg_settings_t)); 2682 2683 settings->out_buf_index = index; 2684 2685 settings->jpeg_orientation = 0; 2686 IF_META_AVAILABLE(int32_t, orientation, CAM_INTF_META_JPEG_ORIENTATION, metadata) { 2687 settings->jpeg_orientation = *orientation; 2688 } 2689 2690 settings->jpeg_quality = 85; 2691 IF_META_AVAILABLE(uint32_t, quality1, CAM_INTF_META_JPEG_QUALITY, metadata) { 2692 settings->jpeg_quality = (uint8_t) *quality1; 2693 } 2694 2695 IF_META_AVAILABLE(uint32_t, quality2, CAM_INTF_META_JPEG_THUMB_QUALITY, metadata) { 2696 settings->jpeg_thumb_quality = (uint8_t) *quality2; 2697 } 2698 2699 IF_META_AVAILABLE(cam_dimension_t, dimension, CAM_INTF_META_JPEG_THUMB_SIZE, metadata) { 2700 settings->thumbnail_size = *dimension; 2701 } 2702 2703 settings->gps_timestamp_valid = 0; 2704 IF_META_AVAILABLE(int64_t, timestamp, CAM_INTF_META_JPEG_GPS_TIMESTAMP, metadata) { 2705 settings->gps_timestamp = *timestamp; 2706 settings->gps_timestamp_valid = 1; 2707 } 2708 2709 settings->gps_coordinates_valid = 0; 2710 IF_META_AVAILABLE(double, coordinates, CAM_INTF_META_JPEG_GPS_COORDINATES, metadata) { 2711 memcpy(settings->gps_coordinates, coordinates, 3*sizeof(double)); 2712 settings->gps_coordinates_valid = 1; 2713 } 2714 2715 IF_META_AVAILABLE(uint8_t, proc_methods, CAM_INTF_META_JPEG_GPS_PROC_METHODS, metadata) { 2716 memset(settings->gps_processing_method, 0, 2717 sizeof(settings->gps_processing_method)); 2718 strlcpy(settings->gps_processing_method, (const char *)proc_methods, 2719 sizeof(settings->gps_processing_method)+1); 2720 } 2721 2722 return m_postprocessor.processJpegSettingData(settings); 2723 } 2724 2725 /*=========================================================================== 2726 * FUNCTION : overrideYuvSize 2727 * 2728 * DESCRIPTION: constructor of QCamera3ReprocessChannel 2729 * 2730 * PARAMETERS : 2731 * @width : new width 2732 * @height : new height 2733 * 2734 * RETURN : none 2735 *==========================================================================*/ 2736 void QCamera3PicChannel::overrideYuvSize(uint32_t width, uint32_t height) 2737 { 2738 mYuvWidth = width; 2739 mYuvHeight = height; 2740 } 2741 2742 /*=========================================================================== 2743 * FUNCTION : getReprocessType 2744 * 2745 * DESCRIPTION: get the type of reprocess output supported by this channel 2746 * 2747 * PARAMETERS : NONE 2748 * 2749 * RETURN : reprocess_type_t : type of reprocess 2750 *==========================================================================*/ 2751 reprocess_type_t QCamera3PicChannel::getReprocessType() 2752 { 2753 return REPROCESS_TYPE_JPEG; 2754 } 2755 2756 /* Reprocess Channel methods */ 2757 2758 /*=========================================================================== 2759 * FUNCTION : QCamera3ReprocessChannel 2760 * 2761 * DESCRIPTION: constructor of QCamera3ReprocessChannel 2762 * 2763 * PARAMETERS : 2764 * @cam_handle : camera handle 2765 * @cam_ops : ptr to camera ops table 2766 * @pp_mask : post-proccess feature mask 2767 * 2768 * RETURN : none 2769 *==========================================================================*/ 2770 QCamera3ReprocessChannel::QCamera3ReprocessChannel(uint32_t cam_handle, 2771 mm_camera_ops_t *cam_ops, 2772 channel_cb_routine cb_routine, 2773 cam_padding_info_t *paddingInfo, 2774 uint32_t postprocess_mask, 2775 void *userData, void *ch_hdl) : 2776 QCamera3Channel(cam_handle, cam_ops, cb_routine, paddingInfo, postprocess_mask, 2777 userData, ((QCamera3ProcessingChannel *)ch_hdl)->getNumBuffers()), 2778 inputChHandle(ch_hdl), 2779 mOfflineBuffersIndex(-1), 2780 mReprocessType(REPROCESS_TYPE_NONE), 2781 m_pSrcChannel(NULL), 2782 m_pMetaChannel(NULL), 2783 mMemory(NULL) 2784 { 2785 memset(mSrcStreamHandles, 0, sizeof(mSrcStreamHandles)); 2786 mOfflineMetaIndex = (int32_t) (mNumBuffers -1); 2787 } 2788 2789 2790 /*=========================================================================== 2791 * FUNCTION : QCamera3ReprocessChannel 2792 * 2793 * DESCRIPTION: constructor of QCamera3ReprocessChannel 2794 * 2795 * PARAMETERS : 2796 * @cam_handle : camera handle 2797 * @cam_ops : ptr to camera ops table 2798 * @pp_mask : post-proccess feature mask 2799 * 2800 * RETURN : none 2801 *==========================================================================*/ 2802 int32_t QCamera3ReprocessChannel::initialize(cam_is_type_t isType) 2803 { 2804 int32_t rc = NO_ERROR; 2805 mm_camera_channel_attr_t attr; 2806 2807 memset(&attr, 0, sizeof(mm_camera_channel_attr_t)); 2808 attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS; 2809 attr.max_unmatched_frames = 1; 2810 2811 rc = init(&attr, NULL); 2812 if (rc < 0) { 2813 ALOGE("%s: init failed", __func__); 2814 } 2815 mIsType = isType; 2816 return rc; 2817 } 2818 2819 /*=========================================================================== 2820 * FUNCTION : registerBuffer 2821 * 2822 * DESCRIPTION: register streaming buffer to the channel object 2823 * 2824 * PARAMETERS : 2825 * @buffer : buffer to be registered 2826 * @isType : the image stabilization type for the buffer 2827 * 2828 * RETURN : int32_t type of status 2829 * NO_ERROR -- success 2830 * none-zero failure code 2831 *==========================================================================*/ 2832 int32_t QCamera3ReprocessChannel::registerBuffer(buffer_handle_t *buffer, 2833 cam_is_type_t isType) 2834 { 2835 ATRACE_CALL(); 2836 int rc = 0; 2837 mIsType = isType; 2838 cam_stream_type_t streamType; 2839 2840 if (buffer == NULL) { 2841 ALOGE("%s: Error: Cannot register a NULL buffer", __func__); 2842 return BAD_VALUE; 2843 } 2844 2845 if ((uint32_t)mGrallocMemory.getCnt() > (mNumBuffers - 1)) { 2846 ALOGE("%s: Trying to register more buffers than initially requested", 2847 __func__); 2848 return BAD_VALUE; 2849 } 2850 2851 if (0 == m_numStreams) { 2852 rc = initialize(mIsType); 2853 if (rc != NO_ERROR) { 2854 ALOGE("%s: Couldn't initialize camera stream %d", 2855 __func__, rc); 2856 return rc; 2857 } 2858 } 2859 2860 streamType = mStreams[0]->getMyType(); 2861 rc = mGrallocMemory.registerBuffer(buffer, streamType); 2862 if (ALREADY_EXISTS == rc) { 2863 return NO_ERROR; 2864 } else if (NO_ERROR != rc) { 2865 ALOGE("%s: Buffer %p couldn't be registered %d", __func__, buffer, rc); 2866 return rc; 2867 } 2868 2869 return rc; 2870 } 2871 2872 /*=========================================================================== 2873 * FUNCTION : QCamera3ReprocessChannel 2874 * 2875 * DESCRIPTION: constructor of QCamera3ReprocessChannel 2876 * 2877 * PARAMETERS : 2878 * @cam_handle : camera handle 2879 * @cam_ops : ptr to camera ops table 2880 * @pp_mask : post-proccess feature mask 2881 * 2882 * RETURN : none 2883 *==========================================================================*/ 2884 void QCamera3ReprocessChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame, 2885 QCamera3Stream *stream) 2886 { 2887 //Got the pproc data callback. Now send to jpeg encoding 2888 uint8_t frameIndex; 2889 mm_camera_super_buf_t* frame = NULL; 2890 QCamera3ProcessingChannel *obj = (QCamera3ProcessingChannel *)inputChHandle; 2891 2892 if(!super_frame) { 2893 ALOGE("%s: Invalid Super buffer",__func__); 2894 return; 2895 } 2896 2897 if(super_frame->num_bufs != 1) { 2898 ALOGE("%s: Multiple streams are not supported",__func__); 2899 return; 2900 } 2901 if(super_frame->bufs[0] == NULL ) { 2902 ALOGE("%s: Error, Super buffer frame does not contain valid buffer", 2903 __func__); 2904 return; 2905 } 2906 frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx; 2907 2908 if (mYUVDump) { 2909 cam_dimension_t dim; 2910 memset(&dim, 0, sizeof(dim)); 2911 stream->getFrameDimension(dim); 2912 cam_frame_len_offset_t offset; 2913 memset(&offset, 0, sizeof(cam_frame_len_offset_t)); 2914 stream->getFrameOffset(offset); 2915 dumpYUV(super_frame->bufs[0], dim, offset, 2); 2916 } 2917 2918 if (mReprocessType == REPROCESS_TYPE_JPEG) { 2919 frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t)); 2920 if (frame == NULL) { 2921 ALOGE("%s: Error allocating memory to save received_frame structure.", 2922 __func__); 2923 if(stream) { 2924 stream->bufDone(frameIndex); 2925 } 2926 return; 2927 } 2928 CDBG("%s: bufIndex: %u recvd from post proc", 2929 __func__, (uint32_t)frameIndex); 2930 *frame = *super_frame; 2931 2932 obj->m_postprocessor.processPPData(frame); 2933 } else { 2934 buffer_handle_t *resultBuffer; 2935 uint32_t resultFrameNumber; 2936 frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx; 2937 resultBuffer = (buffer_handle_t *)mGrallocMemory.getBufferHandle(frameIndex); 2938 resultFrameNumber = mGrallocMemory.getFrameNumber(frameIndex); 2939 int32_t rc = stream->bufRelease(frameIndex); 2940 if (NO_ERROR != rc) { 2941 ALOGE("%s: Error %d releasing stream buffer %d", 2942 __func__, rc, frameIndex); 2943 } 2944 rc = mGrallocMemory.unregisterBuffer(frameIndex); 2945 if (NO_ERROR != rc) { 2946 ALOGE("%s: Error %d unregistering stream buffer %d", 2947 __func__, rc, frameIndex); 2948 } 2949 obj->reprocessCbRoutine(resultBuffer, resultFrameNumber); 2950 } 2951 free(super_frame); 2952 return; 2953 } 2954 2955 /*=========================================================================== 2956 * FUNCTION : QCamera3ReprocessChannel 2957 * 2958 * DESCRIPTION: default constructor of QCamera3ReprocessChannel 2959 * 2960 * PARAMETERS : none 2961 * 2962 * RETURN : none 2963 *==========================================================================*/ 2964 QCamera3ReprocessChannel::QCamera3ReprocessChannel() : 2965 m_pSrcChannel(NULL), 2966 m_pMetaChannel(NULL) 2967 { 2968 } 2969 2970 /*=========================================================================== 2971 * FUNCTION : getStreamBufs 2972 * 2973 * DESCRIPTION: register the buffers of the reprocess channel 2974 * 2975 * PARAMETERS : none 2976 * 2977 * RETURN : QCamera3Memory * 2978 *==========================================================================*/ 2979 QCamera3Memory* QCamera3ReprocessChannel::getStreamBufs(uint32_t len) 2980 { 2981 int rc = 0; 2982 if (mReprocessType == REPROCESS_TYPE_JPEG) { 2983 mMemory = new QCamera3HeapMemory(); 2984 if (!mMemory) { 2985 ALOGE("%s: unable to create reproc memory", __func__); 2986 return NULL; 2987 } 2988 rc = mMemory->allocate(mNumBuffers, len, true); 2989 if (rc < 0) { 2990 ALOGE("%s: unable to allocate reproc memory", __func__); 2991 delete mMemory; 2992 mMemory = NULL; 2993 return NULL; 2994 } 2995 return mMemory; 2996 } 2997 return &mGrallocMemory; 2998 } 2999 3000 /*=========================================================================== 3001 * FUNCTION : putStreamBufs 3002 * 3003 * DESCRIPTION: release the reprocess channel buffers 3004 * 3005 * PARAMETERS : none 3006 * 3007 * RETURN : 3008 *==========================================================================*/ 3009 void QCamera3ReprocessChannel::putStreamBufs() 3010 { 3011 if (mReprocessType == REPROCESS_TYPE_JPEG) { 3012 mMemory->deallocate(); 3013 delete mMemory; 3014 mMemory = NULL; 3015 } else { 3016 mGrallocMemory.unregisterBuffers(); 3017 } 3018 } 3019 3020 /*=========================================================================== 3021 * FUNCTION : ~QCamera3ReprocessChannel 3022 * 3023 * DESCRIPTION: destructor of QCamera3ReprocessChannel 3024 * 3025 * PARAMETERS : none 3026 * 3027 * RETURN : none 3028 *==========================================================================*/ 3029 QCamera3ReprocessChannel::~QCamera3ReprocessChannel() 3030 { 3031 } 3032 3033 /*=========================================================================== 3034 * FUNCTION : getStreamBySrcHandle 3035 * 3036 * DESCRIPTION: find reprocess stream by its source stream handle 3037 * 3038 * PARAMETERS : 3039 * @srcHandle : source stream handle 3040 * 3041 * RETURN : ptr to reprocess stream if found. NULL if not found 3042 *==========================================================================*/ 3043 QCamera3Stream * QCamera3ReprocessChannel::getStreamBySrcHandle(uint32_t srcHandle) 3044 { 3045 QCamera3Stream *pStream = NULL; 3046 3047 for (uint32_t i = 0; i < m_numStreams; i++) { 3048 if (mSrcStreamHandles[i] == srcHandle) { 3049 pStream = mStreams[i]; 3050 break; 3051 } 3052 } 3053 return pStream; 3054 } 3055 3056 /*=========================================================================== 3057 * FUNCTION : getSrcStreamBySrcHandle 3058 * 3059 * DESCRIPTION: find source stream by source stream handle 3060 * 3061 * PARAMETERS : 3062 * @srcHandle : source stream handle 3063 * 3064 * RETURN : ptr to reprocess stream if found. NULL if not found 3065 *==========================================================================*/ 3066 QCamera3Stream * QCamera3ReprocessChannel::getSrcStreamBySrcHandle(uint32_t srcHandle) 3067 { 3068 QCamera3Stream *pStream = NULL; 3069 3070 if (NULL == m_pSrcChannel) { 3071 return NULL; 3072 } 3073 3074 for (uint32_t i = 0; i < m_numStreams; i++) { 3075 if (mSrcStreamHandles[i] == srcHandle) { 3076 pStream = m_pSrcChannel->getStreamByIndex(i); 3077 break; 3078 } 3079 } 3080 return pStream; 3081 } 3082 3083 /*=========================================================================== 3084 * FUNCTION : stop 3085 * 3086 * DESCRIPTION: stop channel 3087 * 3088 * PARAMETERS : none 3089 * 3090 * RETURN : int32_t type of status 3091 * NO_ERROR -- success 3092 * none-zero failure code 3093 *==========================================================================*/ 3094 int32_t QCamera3ReprocessChannel::stop() 3095 { 3096 unmapOfflineBuffers(true); 3097 3098 return QCamera3Channel::stop(); 3099 } 3100 3101 /*=========================================================================== 3102 * FUNCTION : unmapOfflineBuffers 3103 * 3104 * DESCRIPTION: Unmaps offline buffers 3105 * 3106 * PARAMETERS : none 3107 * 3108 * RETURN : int32_t type of status 3109 * NO_ERROR -- success 3110 * none-zero failure code 3111 *==========================================================================*/ 3112 int32_t QCamera3ReprocessChannel::unmapOfflineBuffers(bool all) 3113 { 3114 int rc = NO_ERROR; 3115 if (!mOfflineBuffers.empty()) { 3116 QCamera3Stream *stream = NULL; 3117 List<OfflineBuffer>::iterator it = mOfflineBuffers.begin(); 3118 for (; it != mOfflineBuffers.end(); it++) { 3119 stream = (*it).stream; 3120 if (NULL != stream) { 3121 rc = stream->unmapBuf((*it).type, 3122 (*it).index, 3123 -1); 3124 if (NO_ERROR != rc) { 3125 ALOGE("%s: Error during offline buffer unmap %d", 3126 __func__, rc); 3127 } 3128 CDBG("%s: Unmapped buffer with index %d", __func__, (*it).index); 3129 } 3130 if (!all) { 3131 mOfflineBuffers.erase(it); 3132 break; 3133 } 3134 } 3135 if (all) { 3136 mOfflineBuffers.clear(); 3137 } 3138 } 3139 3140 if (!mOfflineMetaBuffers.empty()) { 3141 QCamera3Stream *stream = NULL; 3142 List<OfflineBuffer>::iterator it = mOfflineMetaBuffers.begin(); 3143 for (; it != mOfflineMetaBuffers.end(); it++) { 3144 stream = (*it).stream; 3145 if (NULL != stream) { 3146 rc = stream->unmapBuf((*it).type, 3147 (*it).index, 3148 -1); 3149 if (NO_ERROR != rc) { 3150 ALOGE("%s: Error during offline buffer unmap %d", 3151 __func__, rc); 3152 } 3153 CDBG("%s: Unmapped meta buffer with index %d", __func__, (*it).index); 3154 } 3155 if (!all) { 3156 mOfflineMetaBuffers.erase(it); 3157 break; 3158 } 3159 } 3160 if (all) { 3161 mOfflineMetaBuffers.clear(); 3162 } 3163 } 3164 return rc; 3165 } 3166 3167 /*=========================================================================== 3168 * FUNCTION : extractFrameAndRotation 3169 * 3170 * DESCRIPTION: Extract output rotation and frame data if present 3171 * 3172 * PARAMETERS : 3173 * @frame : input frame from source stream 3174 * meta_buffer: metadata buffer 3175 * @metadata : corresponding metadata 3176 * @fwk_frame : 3177 * 3178 * RETURN : int32_t type of status 3179 * NO_ERROR -- success 3180 * none-zero failure code 3181 *==========================================================================*/ 3182 int32_t QCamera3ReprocessChannel::extractFrameCropAndRotation(mm_camera_super_buf_t *frame, 3183 mm_camera_buf_def_t *meta_buffer, jpeg_settings_t *jpeg_settings, 3184 qcamera_fwk_input_pp_data_t &fwk_frame) 3185 { 3186 int32_t rc = NO_ERROR; 3187 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData; 3188 if ((NULL == meta_buffer) || (NULL == frame) || (NULL == jpeg_settings) || 3189 (NULL == hal_obj)) { 3190 return BAD_VALUE; 3191 } 3192 3193 metadata_buffer_t *meta = (metadata_buffer_t *)meta_buffer->buffer; 3194 if (NULL == meta) { 3195 return BAD_VALUE; 3196 } 3197 3198 for (uint32_t i = 0; i < frame->num_bufs; i++) { 3199 QCamera3Stream *pStream = getStreamBySrcHandle(frame->bufs[i]->stream_id); 3200 QCamera3Stream *pSrcStream = getSrcStreamBySrcHandle(frame->bufs[i]->stream_id); 3201 3202 if (pStream != NULL && pSrcStream != NULL) { 3203 // Find rotation info for reprocess stream 3204 cam_rotation_info_t rotation_info; 3205 memset(&rotation_info, 0, sizeof(rotation_info)); 3206 if (jpeg_settings->jpeg_orientation == 0) { 3207 rotation_info.rotation = ROTATE_0; 3208 } else if (jpeg_settings->jpeg_orientation == 90) { 3209 rotation_info.rotation = ROTATE_90; 3210 } else if (jpeg_settings->jpeg_orientation == 180) { 3211 rotation_info.rotation = ROTATE_180; 3212 } else if (jpeg_settings->jpeg_orientation == 270) { 3213 rotation_info.rotation = ROTATE_270; 3214 } 3215 rotation_info.streamId = mStreams[0]->getMyServerID(); 3216 ADD_SET_PARAM_ENTRY_TO_BATCH(meta, CAM_INTF_PARM_ROTATION, rotation_info); 3217 3218 // Find and insert crop info for reprocess stream 3219 IF_META_AVAILABLE(cam_crop_data_t, crop_data, CAM_INTF_META_CROP_DATA, meta) { 3220 if (MAX_NUM_STREAMS > crop_data->num_of_streams) { 3221 for (int j = 0; j < crop_data->num_of_streams; j++) { 3222 if (crop_data->crop_info[j].stream_id == 3223 pSrcStream->getMyServerID()) { 3224 3225 // Store crop/roi information for offline reprocess 3226 // in the reprocess stream slot 3227 crop_data->crop_info[crop_data->num_of_streams].crop = 3228 crop_data->crop_info[j].crop; 3229 crop_data->crop_info[crop_data->num_of_streams].roi_map = 3230 crop_data->crop_info[j].roi_map; 3231 crop_data->crop_info[crop_data->num_of_streams].stream_id = 3232 mStreams[0]->getMyServerID(); 3233 crop_data->num_of_streams++; 3234 3235 CDBG("%s: Reprocess stream server id: %d", 3236 __func__, mStreams[0]->getMyServerID()); 3237 CDBG("%s: Found offline reprocess crop %dx%d %dx%d", 3238 __func__, 3239 crop_data->crop_info[j].crop.left, 3240 crop_data->crop_info[j].crop.top, 3241 crop_data->crop_info[j].crop.width, 3242 crop_data->crop_info[j].crop.height); 3243 CDBG("%s: Found offline reprocess roimap %dx%d %dx%d", 3244 __func__, 3245 crop_data->crop_info[j].roi_map.left, 3246 crop_data->crop_info[j].roi_map.top, 3247 crop_data->crop_info[j].roi_map.width, 3248 crop_data->crop_info[j].roi_map.height); 3249 3250 break; 3251 } 3252 } 3253 } else { 3254 ALOGE("%s: No space to add reprocess stream crop/roi information", 3255 __func__); 3256 } 3257 } 3258 3259 fwk_frame.input_buffer = *frame->bufs[i]; 3260 fwk_frame.metadata_buffer = *meta_buffer; 3261 break; 3262 } else { 3263 ALOGE("%s: Source/Re-process streams are invalid", __func__); 3264 rc |= BAD_VALUE; 3265 } 3266 } 3267 3268 return rc; 3269 } 3270 3271 /*=========================================================================== 3272 * FUNCTION : extractCrop 3273 * 3274 * DESCRIPTION: Extract framework output crop if present 3275 * 3276 * PARAMETERS : 3277 * @frame : input frame for reprocessing 3278 * 3279 * RETURN : int32_t type of status 3280 * NO_ERROR -- success 3281 * none-zero failure code 3282 *==========================================================================*/ 3283 int32_t QCamera3ReprocessChannel::extractCrop(qcamera_fwk_input_pp_data_t *frame) 3284 { 3285 if (NULL == frame) { 3286 ALOGE("%s: Incorrect input frame", __func__); 3287 return BAD_VALUE; 3288 } 3289 3290 3291 if (NULL == frame->metadata_buffer.buffer) { 3292 ALOGE("%s: No metadata available", __func__); 3293 return BAD_VALUE; 3294 } 3295 3296 // Find and insert crop info for reprocess stream 3297 metadata_buffer_t *meta = (metadata_buffer_t *) frame->metadata_buffer.buffer; 3298 IF_META_AVAILABLE(cam_crop_data_t, crop_data, CAM_INTF_META_CROP_DATA, meta) { 3299 if (1 == crop_data->num_of_streams) { 3300 // Store crop/roi information for offline reprocess 3301 // in the reprocess stream slot 3302 crop_data->crop_info[crop_data->num_of_streams].crop = 3303 crop_data->crop_info[0].crop; 3304 crop_data->crop_info[crop_data->num_of_streams].roi_map = 3305 crop_data->crop_info[0].roi_map; 3306 crop_data->crop_info[crop_data->num_of_streams].stream_id = 3307 mStreams[0]->getMyServerID(); 3308 crop_data->num_of_streams++; 3309 3310 CDBG("%s: Reprocess stream server id: %d", 3311 __func__, mStreams[0]->getMyServerID()); 3312 CDBG("%s: Found offline reprocess crop %dx%d %dx%d", __func__, 3313 crop_data->crop_info[0].crop.left, 3314 crop_data->crop_info[0].crop.top, 3315 crop_data->crop_info[0].crop.width, 3316 crop_data->crop_info[0].crop.height); 3317 CDBG("%s: Found offline reprocess roi map %dx%d %dx%d", __func__, 3318 crop_data->crop_info[0].roi_map.left, 3319 crop_data->crop_info[0].roi_map.top, 3320 crop_data->crop_info[0].roi_map.width, 3321 crop_data->crop_info[0].roi_map.height); 3322 } else { 3323 ALOGE("%s: Incorrect number of offline crop data entries %d", 3324 __func__, 3325 crop_data->num_of_streams); 3326 return BAD_VALUE; 3327 } 3328 } else { 3329 CDBG_HIGH("%s: Crop data not present", __func__); 3330 } 3331 3332 return NO_ERROR; 3333 } 3334 3335 /*=========================================================================== 3336 * FUNCTION : doReprocessOffline 3337 * 3338 * DESCRIPTION: request to do a reprocess on the frame 3339 * 3340 * PARAMETERS : 3341 * @frame : input frame for reprocessing 3342 * 3343 * RETURN : int32_t type of status 3344 * NO_ERROR -- success 3345 * none-zero failure code 3346 *==========================================================================*/ 3347 int32_t QCamera3ReprocessChannel::doReprocessOffline(qcamera_fwk_input_pp_data_t *frame) 3348 { 3349 int32_t rc = 0; 3350 int index; 3351 OfflineBuffer mappedBuffer; 3352 3353 if (m_numStreams < 1) { 3354 ALOGE("%s: No reprocess stream is created", __func__); 3355 return -1; 3356 } 3357 3358 if (NULL == frame) { 3359 ALOGE("%s: Incorrect input frame", __func__); 3360 return BAD_VALUE; 3361 } 3362 3363 if (NULL == frame->metadata_buffer.buffer) { 3364 ALOGE("%s: No metadata available", __func__); 3365 return BAD_VALUE; 3366 } 3367 3368 if (NULL == frame->input_buffer.buffer) { 3369 ALOGE("%s: No input buffer available", __func__); 3370 return BAD_VALUE; 3371 } 3372 3373 if ((0 == m_numStreams) || (NULL == mStreams[0])) { 3374 ALOGE("%s: Reprocess stream not initialized!", __func__); 3375 return NO_INIT; 3376 } 3377 3378 QCamera3Stream *pStream = mStreams[0]; 3379 3380 //qbuf the output buffer if it was allocated by the framework 3381 if (mReprocessType != REPROCESS_TYPE_JPEG && frame->output_buffer != NULL) { 3382 if(!m_bIsActive) { 3383 rc = registerBuffer(frame->output_buffer, mIsType); 3384 if (NO_ERROR != rc) { 3385 ALOGE("%s: On-the-fly buffer registration failed %d", 3386 __func__, rc); 3387 return rc; 3388 } 3389 3390 rc = start(); 3391 if (NO_ERROR != rc) { 3392 return rc; 3393 } 3394 } 3395 index = mGrallocMemory.getMatchBufIndex((void*)frame->output_buffer); 3396 if(index < 0) { 3397 rc = registerBuffer(frame->output_buffer, mIsType); 3398 if (NO_ERROR != rc) { 3399 ALOGE("%s: On-the-fly buffer registration failed %d", 3400 __func__, rc); 3401 return rc; 3402 } 3403 3404 index = mGrallocMemory.getMatchBufIndex((void*)frame->output_buffer); 3405 if (index < 0) { 3406 ALOGE("%s: Could not find object among registered buffers", 3407 __func__); 3408 return DEAD_OBJECT; 3409 } 3410 } 3411 rc = pStream->bufDone(index); 3412 if(rc != NO_ERROR) { 3413 ALOGE("%s: Failed to Q new buffer to stream",__func__); 3414 return rc; 3415 } 3416 rc = mGrallocMemory.markFrameNumber(index, frame->frameNumber); 3417 } 3418 3419 int32_t max_idx = (int32_t) (mNumBuffers - 1); 3420 //loop back the indices if max burst count reached 3421 if (mOfflineBuffersIndex == max_idx) { 3422 mOfflineBuffersIndex = -1; 3423 } 3424 uint32_t buf_idx = (uint32_t)(mOfflineBuffersIndex + 1); 3425 rc = pStream->mapBuf( 3426 CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF, 3427 buf_idx, -1, 3428 frame->input_buffer.fd, frame->input_buffer.frame_len); 3429 if (NO_ERROR == rc) { 3430 mappedBuffer.index = buf_idx; 3431 mappedBuffer.stream = pStream; 3432 mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF; 3433 mOfflineBuffers.push_back(mappedBuffer); 3434 mOfflineBuffersIndex = (int32_t)buf_idx; 3435 CDBG("%s: Mapped buffer with index %d", __func__, mOfflineBuffersIndex); 3436 } 3437 3438 max_idx = (int32_t) ((mNumBuffers * 2) - 1); 3439 //loop back the indices if max burst count reached 3440 if (mOfflineMetaIndex == max_idx) { 3441 mOfflineMetaIndex = (int32_t) (mNumBuffers - 1); 3442 } 3443 uint32_t meta_buf_idx = (uint32_t)(mOfflineMetaIndex + 1); 3444 rc |= pStream->mapBuf( 3445 CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF, 3446 meta_buf_idx, -1, 3447 frame->metadata_buffer.fd, frame->metadata_buffer.frame_len); 3448 if (NO_ERROR == rc) { 3449 mappedBuffer.index = meta_buf_idx; 3450 mappedBuffer.stream = pStream; 3451 mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF; 3452 mOfflineMetaBuffers.push_back(mappedBuffer); 3453 mOfflineMetaIndex = (int32_t)meta_buf_idx; 3454 CDBG("%s: Mapped meta buffer with index %d", __func__, mOfflineMetaIndex); 3455 } 3456 3457 if (rc == NO_ERROR) { 3458 cam_stream_parm_buffer_t param; 3459 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t)); 3460 param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS; 3461 param.reprocess.buf_index = buf_idx; 3462 param.reprocess.frame_idx = frame->input_buffer.frame_idx; 3463 param.reprocess.meta_present = 1; 3464 param.reprocess.meta_buf_index = meta_buf_idx; 3465 rc = pStream->setParameter(param); 3466 if (rc != NO_ERROR) { 3467 ALOGE("%s: stream setParameter for reprocess failed", __func__); 3468 } 3469 } else { 3470 ALOGE("%s: Input buffer memory map failed: %d", __func__, rc); 3471 } 3472 3473 return rc; 3474 } 3475 3476 /*=========================================================================== 3477 * FUNCTION : doReprocess 3478 * 3479 * DESCRIPTION: request to do a reprocess on the frame 3480 * 3481 * PARAMETERS : 3482 * @buf_fd : fd to the input buffer that needs reprocess 3483 * @buf_lenght : length of the input buffer 3484 * @ret_val : result of reprocess. 3485 * Example: Could be faceID in case of register face image. 3486 * @meta_frame : metadata frame. 3487 * 3488 * RETURN : int32_t type of status 3489 * NO_ERROR -- success 3490 * none-zero failure code 3491 *==========================================================================*/ 3492 int32_t QCamera3ReprocessChannel::doReprocess(int buf_fd, size_t buf_length, 3493 int32_t &ret_val, mm_camera_super_buf_t *meta_frame) 3494 { 3495 int32_t rc = 0; 3496 if (m_numStreams < 1) { 3497 ALOGE("%s: No reprocess stream is created", __func__); 3498 return -1; 3499 } 3500 if (meta_frame == NULL) { 3501 ALOGE("%s: Did not get corresponding metadata in time", __func__); 3502 return -1; 3503 } 3504 3505 uint8_t buf_idx = 0; 3506 for (uint32_t i = 0; i < m_numStreams; i++) { 3507 rc = mStreams[i]->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF, 3508 buf_idx, -1, 3509 buf_fd, buf_length); 3510 3511 if (rc == NO_ERROR) { 3512 cam_stream_parm_buffer_t param; 3513 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t)); 3514 param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS; 3515 param.reprocess.buf_index = buf_idx; 3516 param.reprocess.meta_present = 1; 3517 param.reprocess.meta_stream_handle = m_pMetaChannel->mStreams[0]->getMyServerID(); 3518 param.reprocess.meta_buf_index = meta_frame->bufs[0]->buf_idx; 3519 rc = mStreams[i]->setParameter(param); 3520 if (rc == NO_ERROR) { 3521 ret_val = param.reprocess.ret_val; 3522 } 3523 mStreams[i]->unmapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF, 3524 buf_idx, -1); 3525 } 3526 } 3527 return rc; 3528 } 3529 3530 /*=========================================================================== 3531 * FUNCTION : addReprocStreamsFromSource 3532 * 3533 * DESCRIPTION: add reprocess streams from input source channel 3534 * 3535 * PARAMETERS : 3536 * @config : pp feature configuration 3537 * @src_config : source reprocess configuration 3538 * @isType : type of image stabilization required on this stream 3539 * @pMetaChannel : ptr to metadata channel to get corresp. metadata 3540 * 3541 * 3542 * RETURN : int32_t type of status 3543 * NO_ERROR -- success 3544 * none-zero failure code 3545 *==========================================================================*/ 3546 int32_t QCamera3ReprocessChannel::addReprocStreamsFromSource(cam_pp_feature_config_t &pp_config, 3547 const reprocess_config_t &src_config , cam_is_type_t is_type, 3548 QCamera3Channel *pMetaChannel) 3549 { 3550 int32_t rc = 0; 3551 cam_stream_reproc_config_t reprocess_config; 3552 cam_stream_type_t streamType; 3553 3554 cam_dimension_t streamDim = src_config.output_stream_dim; 3555 3556 if (NULL != src_config.src_channel) { 3557 QCamera3Stream *pSrcStream = src_config.src_channel->getStreamByIndex(0); 3558 if (pSrcStream == NULL) { 3559 ALOGE("%s: source channel doesn't have a stream", __func__); 3560 return BAD_VALUE; 3561 } 3562 mSrcStreamHandles[m_numStreams] = pSrcStream->getMyHandle(); 3563 } 3564 3565 streamType = CAM_STREAM_TYPE_OFFLINE_PROC; 3566 reprocess_config.pp_type = CAM_OFFLINE_REPROCESS_TYPE; 3567 3568 reprocess_config.offline.input_fmt = src_config.stream_format; 3569 reprocess_config.offline.input_dim = src_config.input_stream_dim; 3570 reprocess_config.offline.input_buf_planes.plane_info = 3571 src_config.input_stream_plane_info.plane_info; 3572 reprocess_config.offline.num_of_bufs = (uint8_t)mNumBuffers; 3573 reprocess_config.offline.input_type = src_config.stream_type; 3574 3575 reprocess_config.pp_feature_config = pp_config; 3576 QCamera3Stream *pStream = new QCamera3Stream(m_camHandle, 3577 m_handle, 3578 m_camOps, 3579 mPaddingInfo, 3580 (QCamera3Channel*)this); 3581 if (pStream == NULL) { 3582 ALOGE("%s: No mem for Stream", __func__); 3583 return NO_MEMORY; 3584 } 3585 3586 rc = pStream->init(streamType, src_config.stream_format, 3587 streamDim, ROTATE_0, &reprocess_config, 3588 (uint8_t)mNumBuffers, 3589 reprocess_config.pp_feature_config.feature_mask, 3590 is_type, 3591 0,/* batchSize */ 3592 QCamera3Channel::streamCbRoutine, this); 3593 3594 if (rc == 0) { 3595 mStreams[m_numStreams] = pStream; 3596 m_numStreams++; 3597 } else { 3598 ALOGE("%s: failed to create reprocess stream", __func__); 3599 delete pStream; 3600 } 3601 3602 if (rc == NO_ERROR) { 3603 m_pSrcChannel = src_config.src_channel; 3604 m_pMetaChannel = pMetaChannel; 3605 mReprocessType = src_config.reprocess_type; 3606 } 3607 if(m_camOps->request_super_buf(m_camHandle,m_handle,1,0) < 0) { 3608 ALOGE("%s: Request for super buffer failed",__func__); 3609 } 3610 return rc; 3611 } 3612 3613 /* QCamera3SupportChannel methods */ 3614 3615 cam_dimension_t QCamera3SupportChannel::kDim = {640, 480}; 3616 3617 QCamera3SupportChannel::QCamera3SupportChannel(uint32_t cam_handle, 3618 mm_camera_ops_t *cam_ops, 3619 cam_padding_info_t *paddingInfo, 3620 uint32_t postprocess_mask, 3621 cam_stream_type_t streamType, 3622 cam_dimension_t *dim, 3623 void *userData, uint32_t numBuffers) : 3624 QCamera3Channel(cam_handle, cam_ops, 3625 NULL, paddingInfo, postprocess_mask, 3626 userData, numBuffers), 3627 mMemory(NULL) 3628 { 3629 memcpy(&mDim, dim, sizeof(cam_dimension_t)); 3630 mStreamType = streamType; 3631 } 3632 3633 QCamera3SupportChannel::~QCamera3SupportChannel() 3634 { 3635 if (m_bIsActive) 3636 stop(); 3637 3638 if (mMemory) { 3639 mMemory->deallocate(); 3640 delete mMemory; 3641 mMemory = NULL; 3642 } 3643 } 3644 3645 int32_t QCamera3SupportChannel::initialize(cam_is_type_t isType) 3646 { 3647 int32_t rc; 3648 3649 if (mMemory || m_numStreams > 0) { 3650 ALOGE("%s: metadata channel already initialized", __func__); 3651 return -EINVAL; 3652 } 3653 3654 rc = init(NULL, NULL); 3655 if (rc < 0) { 3656 ALOGE("%s: init failed", __func__); 3657 return rc; 3658 } 3659 mIsType = isType; 3660 rc = QCamera3Channel::addStream(mStreamType, 3661 CAM_FORMAT_YUV_420_NV21, mDim, ROTATE_0, MIN_STREAMING_BUFFER_NUM, 3662 mPostProcMask, mIsType); 3663 if (rc < 0) { 3664 ALOGE("%s: addStream failed", __func__); 3665 } 3666 return rc; 3667 } 3668 3669 int32_t QCamera3SupportChannel::request(buffer_handle_t * /*buffer*/, 3670 uint32_t /*frameNumber*/) 3671 { 3672 return NO_ERROR; 3673 } 3674 3675 void QCamera3SupportChannel::streamCbRoutine( 3676 mm_camera_super_buf_t *super_frame, 3677 QCamera3Stream * /*stream*/) 3678 { 3679 if (super_frame == NULL || super_frame->num_bufs != 1) { 3680 ALOGE("%s: super_frame is not valid", __func__); 3681 return; 3682 } 3683 bufDone(super_frame); 3684 free(super_frame); 3685 } 3686 3687 QCamera3Memory* QCamera3SupportChannel::getStreamBufs(uint32_t len) 3688 { 3689 int rc; 3690 mMemory = new QCamera3HeapMemory(); 3691 if (!mMemory) { 3692 ALOGE("%s: unable to create heap memory", __func__); 3693 return NULL; 3694 } 3695 rc = mMemory->allocate(MIN_STREAMING_BUFFER_NUM, len, true); 3696 if (rc < 0) { 3697 ALOGE("%s: unable to allocate heap memory", __func__); 3698 delete mMemory; 3699 mMemory = NULL; 3700 return NULL; 3701 } 3702 return mMemory; 3703 } 3704 3705 void QCamera3SupportChannel::putStreamBufs() 3706 { 3707 mMemory->deallocate(); 3708 delete mMemory; 3709 mMemory = NULL; 3710 } 3711 3712 }; // namespace qcamera 3713