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