QCamera3Channel.cpp revision 1c6fa865f97afe06b8b9d9520390a37dd86f55e1
1/* Copyright (c) 2012-2013, 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 LOG_TAG "QCamera3Channel" 31 32#include <stdlib.h> 33#include <cstdlib> 34#include <stdio.h> 35#include <string.h> 36#include <hardware/camera3.h> 37#include <system/camera_metadata.h> 38#include <gralloc_priv.h> 39#include <utils/Log.h> 40#include <utils/Errors.h> 41#include "QCamera3Channel.h" 42 43using namespace android; 44 45#define MIN_STREAMING_BUFFER_NUM 3 46 47namespace qcamera { 48static const char ExifAsciiPrefix[] = 49 { 0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0 }; // "ASCII\0\0\0" 50static const char ExifUndefinedPrefix[] = 51 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // "\0\0\0\0\0\0\0\0" 52 53#define GPS_PROCESSING_METHOD_SIZE 101 54#define EXIF_ASCII_PREFIX_SIZE 8 //(sizeof(ExifAsciiPrefix)) 55#define FOCAL_LENGTH_DECIMAL_PRECISION 100 56 57/*=========================================================================== 58 * FUNCTION : QCamera3Channel 59 * 60 * DESCRIPTION: constrcutor of QCamera3Channel 61 * 62 * PARAMETERS : 63 * @cam_handle : camera handle 64 * @cam_ops : ptr to camera ops table 65 * 66 * RETURN : none 67 *==========================================================================*/ 68QCamera3Channel::QCamera3Channel(uint32_t cam_handle, 69 mm_camera_ops_t *cam_ops, 70 channel_cb_routine cb_routine, 71 cam_padding_info_t *paddingInfo, 72 void *userData) 73{ 74 m_camHandle = cam_handle; 75 m_camOps = cam_ops; 76 mChannelCB = cb_routine; 77 mPaddingInfo = paddingInfo; 78 mUserData = userData; 79 m_bIsActive = false; 80 81 m_handle = 0; 82 m_numStreams = 0; 83 memset(mStreams, 0, sizeof(mStreams)); 84} 85 86/*=========================================================================== 87 * FUNCTION : QCamera3Channel 88 * 89 * DESCRIPTION: default constrcutor of QCamera3Channel 90 * 91 * PARAMETERS : none 92 * 93 * RETURN : none 94 *==========================================================================*/ 95QCamera3Channel::QCamera3Channel() 96{ 97 m_camHandle = 0; 98 m_camOps = NULL; 99 mPaddingInfo = NULL; 100 mUserData = NULL; 101 m_bIsActive = false; 102 103 m_handle = 0; 104 m_numStreams = 0; 105 memset(mStreams, 0, sizeof(mStreams)); 106} 107 108/*=========================================================================== 109 * FUNCTION : ~QCamera3Channel 110 * 111 * DESCRIPTION: destructor of QCamera3Channel 112 * 113 * PARAMETERS : none 114 * 115 * RETURN : none 116 *==========================================================================*/ 117QCamera3Channel::~QCamera3Channel() 118{ 119 if (m_bIsActive) 120 stop(); 121 122 for (int i = 0; i < m_numStreams; i++) { 123 if (mStreams[i] != NULL) { 124 delete mStreams[i]; 125 mStreams[i] = 0; 126 } 127 } 128 m_numStreams = 0; 129 m_camOps->delete_channel(m_camHandle, m_handle); 130 m_handle = 0; 131} 132 133/*=========================================================================== 134 * FUNCTION : init 135 * 136 * DESCRIPTION: initialization of channel 137 * 138 * PARAMETERS : 139 * @attr : channel bundle attribute setting 140 * @dataCB : data notify callback 141 * @userData: user data ptr 142 * 143 * RETURN : int32_t type of status 144 * NO_ERROR -- success 145 * none-zero failure code 146 *==========================================================================*/ 147int32_t QCamera3Channel::init(mm_camera_channel_attr_t *attr, 148 mm_camera_buf_notify_t dataCB) 149{ 150 m_handle = m_camOps->add_channel(m_camHandle, 151 attr, 152 dataCB, 153 mUserData); 154 if (m_handle == 0) { 155 ALOGE("%s: Add channel failed", __func__); 156 return UNKNOWN_ERROR; 157 } 158 return NO_ERROR; 159} 160 161/*=========================================================================== 162 * FUNCTION : addStream 163 * 164 * DESCRIPTION: add a stream into channel 165 * 166 * PARAMETERS : 167 * @allocator : stream related buffer allocator 168 * @streamInfoBuf : ptr to buf that constains stream info 169 * @minStreamBufNum: number of stream buffers needed 170 * @paddingInfo : padding information 171 * @stream_cb : stream data notify callback 172 * @userdata : user data ptr 173 * 174 * RETURN : int32_t type of status 175 * NO_ERROR -- success 176 * none-zero failure code 177 *==========================================================================*/ 178int32_t QCamera3Channel::addStream(cam_stream_type_t streamType, 179 cam_format_t streamFormat, 180 cam_dimension_t streamDim, 181 uint8_t minStreamBufNum) 182{ 183 int32_t rc = NO_ERROR; 184 if (m_numStreams >= MAX_STREAM_NUM_IN_BUNDLE) { 185 ALOGE("%s: stream number (%d) exceeds max limit (%d)", 186 __func__, m_numStreams, MAX_STREAM_NUM_IN_BUNDLE); 187 return BAD_VALUE; 188 } 189 QCamera3Stream *pStream = new QCamera3Stream(m_camHandle, 190 m_handle, 191 m_camOps, 192 mPaddingInfo, 193 this); 194 if (pStream == NULL) { 195 ALOGE("%s: No mem for Stream", __func__); 196 return NO_MEMORY; 197 } 198 199 rc = pStream->init(streamType, streamFormat, streamDim, minStreamBufNum, 200 streamCbRoutine, this); 201 if (rc == 0) { 202 mStreams[m_numStreams] = pStream; 203 m_numStreams++; 204 } else { 205 delete pStream; 206 } 207 return rc; 208} 209 210/*=========================================================================== 211 * FUNCTION : start 212 * 213 * DESCRIPTION: start channel, which will start all streams belong to this channel 214 * 215 * PARAMETERS : 216 * 217 * RETURN : int32_t type of status 218 * NO_ERROR -- success 219 * none-zero failure code 220 *==========================================================================*/ 221int32_t QCamera3Channel::start() 222{ 223 int32_t rc = NO_ERROR; 224 225 if (m_numStreams > 1) { 226 ALOGE("%s: bundle not supported", __func__); 227 } 228 229 for (int i = 0; i < m_numStreams; i++) { 230 if (mStreams[i] != NULL) { 231 mStreams[i]->start(); 232 } 233 } 234 rc = m_camOps->start_channel(m_camHandle, m_handle); 235 236 if (rc != NO_ERROR) { 237 for (int i = 0; i < m_numStreams; i++) { 238 if (mStreams[i] != NULL) { 239 mStreams[i]->stop(); 240 } 241 } 242 } else { 243 m_bIsActive = true; 244 } 245 246 return rc; 247} 248 249/*=========================================================================== 250 * FUNCTION : stop 251 * 252 * DESCRIPTION: stop a channel, which will stop all streams belong to this channel 253 * 254 * PARAMETERS : none 255 * 256 * RETURN : int32_t type of status 257 * NO_ERROR -- success 258 * none-zero failure code 259 *==========================================================================*/ 260int32_t QCamera3Channel::stop() 261{ 262 int32_t rc = NO_ERROR; 263 rc = m_camOps->stop_channel(m_camHandle, m_handle); 264 265 for (int i = 0; i < m_numStreams; i++) { 266 if (mStreams[i] != NULL) { 267 mStreams[i]->stop(); 268 } 269 } 270 271 m_bIsActive = false; 272 return rc; 273} 274 275/*=========================================================================== 276 * FUNCTION : bufDone 277 * 278 * DESCRIPTION: return a stream buf back to kernel 279 * 280 * PARAMETERS : 281 * @recvd_frame : stream buf frame to be returned 282 * 283 * RETURN : int32_t type of status 284 * NO_ERROR -- success 285 * none-zero failure code 286 *==========================================================================*/ 287int32_t QCamera3Channel::bufDone(mm_camera_super_buf_t *recvd_frame) 288{ 289 int32_t rc = NO_ERROR; 290 for (int i = 0; i < recvd_frame->num_bufs; i++) { 291 if (recvd_frame->bufs[i] != NULL) { 292 for (int j = 0; j < m_numStreams; j++) { 293 if (mStreams[j] != NULL && 294 mStreams[j]->getMyHandle() == recvd_frame->bufs[i]->stream_id) { 295 rc = mStreams[j]->bufDone(recvd_frame->bufs[i]->buf_idx); 296 break; // break loop j 297 } 298 } 299 } 300 } 301 302 return rc; 303} 304 305/*=========================================================================== 306 * FUNCTION : getStreamByHandle 307 * 308 * DESCRIPTION: return stream object by stream handle 309 * 310 * PARAMETERS : 311 * @streamHandle : stream handle 312 * 313 * RETURN : stream object. NULL if not found 314 *==========================================================================*/ 315QCamera3Stream *QCamera3Channel::getStreamByHandle(uint32_t streamHandle) 316{ 317 for (int i = 0; i < m_numStreams; i++) { 318 if (mStreams[i] != NULL && mStreams[i]->getMyHandle() == streamHandle) { 319 return mStreams[i]; 320 } 321 } 322 return NULL; 323} 324 325/*=========================================================================== 326 * FUNCTION : getStreamByHandle 327 * 328 * DESCRIPTION: return stream object by stream handle 329 * 330 * PARAMETERS : 331 * @streamHandle : stream handle 332 * 333 * RETURN : stream object. NULL if not found 334 *==========================================================================*/ 335QCamera3Stream *QCamera3Channel::getStreamByIndex(uint8_t index) 336{ 337 if (index < m_numStreams) { 338 return mStreams[index]; 339 } 340 return NULL; 341} 342 343/*=========================================================================== 344 * FUNCTION : streamCbRoutine 345 * 346 * DESCRIPTION: callback routine for stream 347 * 348 * PARAMETERS : 349 * @streamHandle : stream handle 350 * 351 * RETURN : stream object. NULL if not found 352 *==========================================================================*/ 353void QCamera3Channel::streamCbRoutine(mm_camera_super_buf_t *super_frame, 354 QCamera3Stream *stream, void *userdata) 355{ 356 QCamera3Channel *channel = (QCamera3Channel *)userdata; 357 if (channel == NULL) { 358 ALOGE("%s: invalid channel pointer", __func__); 359 return; 360 } 361 channel->streamCbRoutine(super_frame, stream); 362} 363 364/*=========================================================================== 365 * FUNCTION : QCamera3RegularChannel 366 * 367 * DESCRIPTION: constrcutor of QCamera3RegularChannel 368 * 369 * PARAMETERS : 370 * @cam_handle : camera handle 371 * @cam_ops : ptr to camera ops table 372 * @cb_routine : callback routine to frame aggregator 373 * @stream : camera3_stream_t structure 374 * 375 * RETURN : none 376 *==========================================================================*/ 377QCamera3RegularChannel::QCamera3RegularChannel(uint32_t cam_handle, 378 mm_camera_ops_t *cam_ops, 379 channel_cb_routine cb_routine, 380 cam_padding_info_t *paddingInfo, 381 void *userData, 382 camera3_stream_t *stream) : 383 QCamera3Channel(cam_handle, cam_ops, cb_routine, 384 paddingInfo, userData), 385 mCamera3Stream(stream), 386 mNumBufs(0), 387 mCamera3Buffers(NULL), 388 mMemory(NULL) 389{ 390} 391 392/*=========================================================================== 393 * FUNCTION : ~QCamera3RegularChannel 394 * 395 * DESCRIPTION: destructor of QCamera3RegularChannel 396 * 397 * PARAMETERS : none 398 * 399 * RETURN : none 400 *==========================================================================*/ 401QCamera3RegularChannel::~QCamera3RegularChannel() 402{ 403 if (mCamera3Buffers) { 404 delete[] mCamera3Buffers; 405 } 406} 407 408int32_t QCamera3RegularChannel::initialize() 409{ 410 //TO DO 411 return 0; 412} 413 414/*=========================================================================== 415 * FUNCTION : request 416 * 417 * DESCRIPTION: process a request from camera service. Stream on if ncessary. 418 * 419 * PARAMETERS : 420 * @buffer : buffer to be filled for this request 421 * 422 * RETURN : 0 on a success start of capture 423 * -EINVAL on invalid input 424 * -ENODEV on serious error 425 *==========================================================================*/ 426int32_t QCamera3RegularChannel::request(buffer_handle_t *buffer, uint32_t frameNumber) 427{ 428 //FIX ME: Return buffer back in case of failures below. 429 430 int32_t rc = NO_ERROR; 431 int index; 432 if(!m_bIsActive) { 433 ALOGD("%s: First request on this channel starting stream",__func__); 434 start(); 435 if(rc != NO_ERROR) { 436 ALOGE("%s: Failed to start the stream on the request",__func__); 437 return rc; 438 } 439 } else { 440 ALOGV("%s: Request on an existing stream",__func__); 441 } 442 443 if(!mMemory) { 444 ALOGE("%s: error, Gralloc Memory object not yet created for this stream",__func__); 445 return NO_MEMORY; 446 } 447 448 index = mMemory->getMatchBufIndex((void*)buffer); 449 if(index < 0) { 450 ALOGE("%s: Could not find object among registered buffers",__func__); 451 return DEAD_OBJECT; 452 } 453 454 rc = mStreams[0]->bufDone(index); 455 if(rc != NO_ERROR) { 456 ALOGE("%s: Failed to Q new buffer to stream",__func__); 457 return rc; 458 } 459 460 rc = mMemory->markFrameNumber(index, frameNumber); 461 return rc; 462} 463 464/*=========================================================================== 465 * FUNCTION : registerBuffers 466 * 467 * DESCRIPTION: register streaming buffers to the channel object 468 * 469 * PARAMETERS : 470 * @num_buffers : number of buffers to be registered 471 * @buffers : buffer to be registered 472 * 473 * RETURN : 0 on a success start of capture 474 * -EINVAL on invalid input 475 * -ENOMEM on failure to register the buffer 476 * -ENODEV on serious error 477 *==========================================================================*/ 478int32_t QCamera3RegularChannel::registerBuffers(uint32_t num_buffers, buffer_handle_t **buffers) 479{ 480 int rc = 0; 481 struct private_handle_t *priv_handle = (struct private_handle_t *)(*buffers[0]); 482 cam_stream_type_t streamType; 483 cam_format_t streamFormat; 484 cam_dimension_t streamDim; 485 486 rc = init(NULL, NULL); 487 if (rc < 0) { 488 ALOGE("%s: init failed", __func__); 489 return rc; 490 } 491 492 if (mCamera3Stream->format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) { 493 if (priv_handle->flags & private_handle_t::PRIV_FLAGS_VIDEO_ENCODER) { 494 streamType = CAM_STREAM_TYPE_VIDEO; 495 streamFormat = CAM_FORMAT_YUV_420_NV12; 496 } else if (priv_handle->flags & private_handle_t::PRIV_FLAGS_HW_TEXTURE) { 497 streamType = CAM_STREAM_TYPE_PREVIEW; 498 streamFormat = CAM_FORMAT_YUV_420_NV21; 499 } else { 500 ALOGE("%s: priv_handle->flags 0x%x not supported", 501 __func__, priv_handle->flags); 502 return -EINVAL; 503 } 504 } else { 505 //TODO: Fail for other types of streams for now 506 ALOGE("%s: format is not IMPLEMENTATION_DEFINED", __func__); 507 return -EINVAL; 508 } 509 510 /* Bookkeep buffer set because they go out of scope after register call */ 511 mNumBufs = num_buffers; 512 mCamera3Buffers = new buffer_handle_t*[num_buffers]; 513 if (mCamera3Buffers == NULL) { 514 ALOGE("%s: Failed to allocate buffer_handle_t*", __func__); 515 return -ENOMEM; 516 } 517 for (size_t i = 0; i < num_buffers; i++) 518 mCamera3Buffers[i] = buffers[i]; 519 520 streamDim.width = mCamera3Stream->width; 521 streamDim.height = mCamera3Stream->height; 522 rc = QCamera3Channel::addStream(streamType, streamFormat, streamDim, 523 num_buffers); 524 525 return rc; 526} 527 528void QCamera3RegularChannel::streamCbRoutine( 529 mm_camera_super_buf_t *super_frame, 530 QCamera3Stream *stream) 531{ 532 //FIXME Q Buf back in case of error? 533 uint8_t frameIndex; 534 buffer_handle_t *resultBuffer; 535 int32_t resultFrameNumber; 536 camera3_stream_buffer_t result; 537 538 if(!super_frame) { 539 ALOGE("%s: Invalid Super buffer",__func__); 540 return; 541 } 542 543 if(super_frame->num_bufs != 1) { 544 ALOGE("%s: Multiple streams are not supported",__func__); 545 return; 546 } 547 if(super_frame->bufs[0] == NULL ) { 548 ALOGE("%s: Error, Super buffer frame does not contain valid buffer", 549 __func__); 550 return; 551 } 552 553 frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx; 554 if(frameIndex >= mNumBufs) { 555 ALOGE("%s: Error, Invalid index for buffer",__func__); 556 if(stream) { 557 stream->bufDone(frameIndex); 558 } 559 return; 560 } 561 562 ////Use below data to issue framework callback 563 resultBuffer = mCamera3Buffers[frameIndex]; 564 resultFrameNumber = mMemory->getFrameNumber(frameIndex); 565 566 result.stream = mCamera3Stream; 567 result.buffer = resultBuffer; 568 result.status = CAMERA3_BUFFER_STATUS_OK; 569 result.acquire_fence = -1; 570 result.release_fence = -1; 571 572 mChannelCB(NULL, &result, resultFrameNumber, mUserData); 573 return; 574} 575 576QCamera3Memory* QCamera3RegularChannel::getStreamBufs(uint32_t len) 577{ 578 if (mNumBufs == 0 || mCamera3Buffers == NULL) { 579 ALOGE("%s: buffers not registered yet", __func__); 580 return NULL; 581 } 582 583 mMemory = new QCamera3GrallocMemory(); 584 if (mMemory == NULL) { 585 return NULL; 586 } 587 588 if (mMemory->registerBuffers(mNumBufs, mCamera3Buffers) < 0) { 589 delete mMemory; 590 mMemory = NULL; 591 return NULL; 592 } 593 return mMemory; 594} 595 596void QCamera3RegularChannel::putStreamBufs() 597{ 598 mMemory->unregisterBuffers(); 599 delete mMemory; 600 mMemory = NULL; 601} 602 603int QCamera3RegularChannel::kMaxBuffers = 7; 604 605QCamera3MetadataChannel::QCamera3MetadataChannel(uint32_t cam_handle, 606 mm_camera_ops_t *cam_ops, 607 channel_cb_routine cb_routine, 608 cam_padding_info_t *paddingInfo, 609 void *userData) : 610 QCamera3Channel(cam_handle, cam_ops, 611 cb_routine, paddingInfo, userData), 612 mMemory(NULL) 613{ 614#ifdef FAKE_FRAME_NUMBERS 615 startingFrameNumber=0; 616#endif 617} 618 619QCamera3MetadataChannel::~QCamera3MetadataChannel() 620{ 621 if (m_bIsActive) 622 stop(); 623 624 if (mMemory) { 625 mMemory->deallocate(); 626 delete mMemory; 627 mMemory = NULL; 628 } 629} 630 631int32_t QCamera3MetadataChannel::initialize() 632{ 633 int32_t rc; 634 cam_dimension_t streamDim; 635 636 if (mMemory || m_numStreams > 0) { 637 ALOGE("%s: metadata channel already initialized", __func__); 638 return -EINVAL; 639 } 640 641 rc = init(NULL, NULL); 642 if (rc < 0) { 643 ALOGE("%s: init failed", __func__); 644 return rc; 645 } 646 647 streamDim.width = sizeof(metadata_buffer_t), 648 streamDim.height = 1; 649 rc = QCamera3Channel::addStream(CAM_STREAM_TYPE_METADATA, CAM_FORMAT_MAX, 650 streamDim, MIN_STREAMING_BUFFER_NUM); 651 if (rc < 0) { 652 ALOGE("%s: addStream failed", __func__); 653 } 654 return rc; 655} 656 657int32_t QCamera3MetadataChannel::request(buffer_handle_t *buffer, uint32_t frameNumber) 658{ 659 if (!m_bIsActive) { 660#ifdef FAKE_FRAME_NUMBERS 661 startingFrameNumber=frameNumber; 662#endif 663 return start(); 664 } 665 else 666 return 0; 667} 668 669int32_t QCamera3MetadataChannel::registerBuffers(uint32_t /*num_buffers*/, 670 buffer_handle_t ** /*buffers*/) 671{ 672 // no registerBuffers are supported for metadata channel 673 return -EINVAL; 674} 675 676void QCamera3MetadataChannel::streamCbRoutine( 677 mm_camera_super_buf_t *super_frame, 678 QCamera3Stream *stream) 679{ 680 uint32_t requestNumber = 0; 681 if (super_frame == NULL || super_frame->num_bufs != 1) { 682 ALOGE("%s: super_frame is not valid", __func__); 683 return; 684 } 685#ifdef FAKE_FRAME_NUMBERS 686 requestNumber = startingFrameNumber++; 687#endif 688 mChannelCB(super_frame, NULL, requestNumber, mUserData); 689 690 //Return the buffer 691 stream->bufDone(super_frame->bufs[0]->buf_idx); 692} 693 694QCamera3Memory* QCamera3MetadataChannel::getStreamBufs(uint32_t len) 695{ 696 int rc; 697 if (len != sizeof(metadata_buffer_t)) { 698 ALOGE("%s: size doesn't match %d vs %d", __func__, 699 len, sizeof(metadata_buffer_t)); 700 return NULL; 701 } 702 mMemory = new QCamera3HeapMemory(); 703 if (!mMemory) { 704 ALOGE("%s: unable to create metadata memory", __func__); 705 return NULL; 706 } 707 rc = mMemory->allocate(MIN_STREAMING_BUFFER_NUM, len, true); 708 if (rc < 0) { 709 ALOGE("%s: unable to allocate metadata memory", __func__); 710 delete mMemory; 711 mMemory = NULL; 712 return NULL; 713 } 714 memset(mMemory->getPtr(0), 0, sizeof(metadata_buffer_t)); 715 return mMemory; 716} 717 718void QCamera3MetadataChannel::putStreamBufs() 719{ 720 mMemory->deallocate(); 721 delete mMemory; 722 mMemory = NULL; 723} 724 725/*=========================================================================== 726 * FUNCTION : jpegEvtHandle 727 * 728 * DESCRIPTION: Function registerd to mm-jpeg-interface to handle jpeg events. 729 Construct result payload and call mChannelCb to deliver buffer 730 to framework. 731 * 732 * PARAMETERS : 733 * @status : status of jpeg job 734 * @client_hdl: jpeg client handle 735 * @jobId : jpeg job Id 736 * @p_ouput : ptr to jpeg output result struct 737 * @userdata : user data ptr 738 * 739 * RETURN : none 740 *==========================================================================*/ 741void QCamera3PicChannel::jpegEvtHandle(jpeg_job_status_t status, 742 uint32_t /*client_hdl*/, 743 uint32_t jobId, 744 mm_jpeg_output_t *p_output, 745 void *userdata) 746{ 747 buffer_handle_t *resultBuffer; 748 int32_t resultFrameNumber; 749 int resultStatus = CAMERA3_BUFFER_STATUS_OK; 750 camera3_stream_buffer_t result; 751 camera3_jpeg_blob_t jpegHeader; 752 char* jpeg_eof = 0; 753 QCamera3PicChannel *obj = (QCamera3PicChannel *)userdata; 754 if (obj) { 755 //Construct payload for process_capture_result. Call mChannelCb 756 757 qcamera_jpeg_data_t *job = obj->m_postprocessor.findJpegJobByJobId(jobId); 758 759 if ((job == NULL) || (status == JPEG_JOB_STATUS_ERROR)) { 760 ALOGE("%s: Error in jobId: (%d) with status: %d", __func__, jobId, status); 761 resultStatus = CAMERA3_BUFFER_STATUS_ERROR; 762 } 763 764 //Construct jpeg transient header of type camera3_jpeg_blob_t 765 //Append at the end of jpeg image of buf_filled_len size 766 767 jpegHeader.jpeg_blob_id = CAMERA3_JPEG_BLOB_ID; 768 jpegHeader.jpeg_size = p_output->buf_filled_len; 769 770 771 char* jpeg_buf = (char *)p_output->buf_vaddr; 772 773 jpeg_eof = &jpeg_buf[p_output->buf_filled_len]; 774 memcpy(jpeg_eof, &jpegHeader, sizeof(jpegHeader)); 775 776 ////Use below data to issue framework callback 777 778 resultBuffer = obj->mCamera3Buffers[0]; 779 resultFrameNumber = obj->mMemory->getFrameNumber(0); 780 781 result.stream = obj->mCamera3Stream; 782 result.buffer = resultBuffer; 783 result.status = resultStatus; 784 result.acquire_fence = -1; 785 result.release_fence = -1; 786 787 obj->mChannelCB(NULL, &result, resultFrameNumber, obj->mUserData); 788 789 // release internal data for jpeg job 790 if (job != NULL) { 791 obj->m_postprocessor.releaseJpegJobData(job); 792 free(job); 793 } 794 return; 795 // } 796 } else { 797 ALOGE("%s: Null userdata in jpeg callback", __func__); 798 } 799} 800 801QCamera3PicChannel::QCamera3PicChannel(uint32_t cam_handle, 802 mm_camera_ops_t *cam_ops, 803 channel_cb_routine cb_routine, 804 cam_padding_info_t *paddingInfo, 805 void *userData, 806 camera3_stream_t *stream) : 807 QCamera3Channel(cam_handle, cam_ops, cb_routine, paddingInfo, userData), 808 mCamera3Stream(stream), 809 m_postprocessor(this), 810 mCamera3Buffers(NULL), 811 mMemory(NULL), 812 mYuvMemory(NULL) 813{ 814 //TODO 815} 816 817QCamera3PicChannel::~QCamera3PicChannel() 818{ 819 if (mCamera3Buffers) { 820 delete[] mCamera3Buffers; 821 } 822} 823 824int32_t QCamera3PicChannel::initialize() 825{ 826 int32_t rc = m_postprocessor.init(jpegEvtHandle, this); 827 if (rc != 0) { 828 ALOGE("Init Postprocessor failed"); 829 return UNKNOWN_ERROR; 830 } 831 return rc; 832} 833 834int32_t QCamera3PicChannel::request(buffer_handle_t *buffer, uint32_t frameNumber, jpeg_settings_t* jpegSettings) 835{ 836 //FIX ME: Return buffer back in case of failures below. 837 838 int32_t rc = NO_ERROR; 839 int index; 840 mJpegSettings = jpegSettings; 841 if(!m_bIsActive) { 842 ALOGD("%s: First request on this channel starting stream",__func__); 843 //Stream on for main image. YUV buffer is queued to the kernel at the end of this call. 844 rc = start(); 845 } else { 846 ALOGV("%s: Request on an existing stream",__func__); 847 } 848 849 if(rc != NO_ERROR) { 850 ALOGE("%s: Failed to start the stream on the request",__func__); 851 return rc; 852 } 853 854 855 if(!mMemory) { 856 ALOGE("%s: error, Gralloc Memory object not yet created for this stream",__func__); 857 return NO_MEMORY; 858 } 859 860 index = mMemory->getMatchBufIndex((void*)buffer); 861 if(index < 0) { 862 ALOGE("%s: Could not find object among registered buffers",__func__); 863 return DEAD_OBJECT; 864 } 865 866 rc = mMemory->markFrameNumber(index, frameNumber); 867 868 //Start the postprocessor for jpeg encoding. Pass mMemory as destination buffer 869 m_postprocessor.start(mMemory); 870 return rc; 871} 872 873int32_t QCamera3PicChannel::registerBuffers(uint32_t num_buffers, 874 buffer_handle_t **buffers) 875{ 876 int rc = 0; 877 struct private_handle_t *priv_handle = (struct private_handle_t *)(*buffers[0]); 878 cam_stream_type_t streamType; 879 cam_format_t streamFormat; 880 cam_dimension_t streamDim; 881 882 rc = init(NULL, NULL); 883 if (rc < 0) { 884 ALOGE("%s: init failed", __func__); 885 return rc; 886 } 887 888 if (mCamera3Stream->format == HAL_PIXEL_FORMAT_BLOB) { 889 streamType = CAM_STREAM_TYPE_SNAPSHOT; 890 streamFormat = CAM_FORMAT_YUV_420_NV21; 891 } else { 892 //TODO: Fail for other types of streams for now 893 ALOGE("%s: format is not BLOB", __func__); 894 return -EINVAL; 895 } 896 /* Bookkeep buffer set because they go out of scope after register call */ 897 mNumBufs = num_buffers; 898 if(mNumBufs > 1) { 899 ALOGE("%s: currently no support for multiple snapshot buffers", __func__); 900 return -EINVAL; 901 } 902 903 mCamera3Buffers = new buffer_handle_t*[num_buffers]; 904 if (mCamera3Buffers == NULL) { 905 ALOGE("%s: Failed to allocate buffer_handle_t*", __func__); 906 return -ENOMEM; 907 } 908 for (size_t i = 0; i < num_buffers; i++) 909 mCamera3Buffers[i] = buffers[i]; 910 911 streamDim.width = mCamera3Stream->width; 912 streamDim.height = mCamera3Stream->height; 913 rc = QCamera3Channel::addStream(streamType, streamFormat, streamDim, 914 num_buffers); 915 916 return rc; 917} 918 919void QCamera3PicChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame, 920 QCamera3Stream *stream) 921{ 922 //TODO 923 //Used only for getting YUV. Jpeg callback will be sent back from channel directly to HWI. 924 //Refer to func jpegEvtHandle 925 926 //Got the yuv callback. Calling yuv callback handler in PostProc 927 uint8_t frameIndex; 928 if(!super_frame) { 929 ALOGE("%s: Invalid Super buffer",__func__); 930 return; 931 } 932 933 if(super_frame->num_bufs != 1) { 934 ALOGE("%s: Multiple streams are not supported",__func__); 935 return; 936 } 937 if(super_frame->bufs[0] == NULL ) { 938 ALOGE("%s: Error, Super buffer frame does not contain valid buffer", 939 __func__); 940 return; 941 } 942 943 frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx; 944 if(frameIndex >= mNumBufs) { 945 ALOGE("%s: Error, Invalid index for buffer",__func__); 946 if(stream) { 947 stream->bufDone(frameIndex); 948 } 949 return; 950 } 951 952 m_postprocessor.processData(super_frame); 953 return; 954} 955 956QCamera3Memory* QCamera3PicChannel::getStreamBufs(uint32_t len) 957{ 958 int rc = 0; 959 960 if (mNumBufs == 0 || mCamera3Buffers == NULL) { 961 ALOGE("%s: buffers not registered yet", __func__); 962 return NULL; 963 } 964 965 mMemory = new QCamera3GrallocMemory(); 966 if (mMemory == NULL) { 967 return NULL; 968 } 969 970 //Registering Jpeg output buffer 971 if (mMemory->registerBuffers(mNumBufs, mCamera3Buffers) < 0) { 972 delete mMemory; 973 mMemory = NULL; 974 return NULL; 975 } 976 977 mYuvMemory = new QCamera3HeapMemory(); 978 if (!mYuvMemory) { 979 ALOGE("%s: unable to create metadata memory", __func__); 980 return NULL; 981 } 982 983 //Queue YUV buffers in the beginning mQueueAll = true 984 rc = mYuvMemory->allocate(1, len, true); 985 if (rc < 0) { 986 ALOGE("%s: unable to allocate metadata memory", __func__); 987 delete mYuvMemory; 988 mYuvMemory = NULL; 989 return NULL; 990 } 991 return mYuvMemory; 992} 993 994void QCamera3PicChannel::putStreamBufs() 995{ 996 mMemory->unregisterBuffers(); 997 delete mMemory; 998 mMemory = NULL; 999 1000 mYuvMemory->deallocate(); 1001 delete mYuvMemory; 1002 mYuvMemory = NULL; 1003} 1004 1005/*=========================================================================== 1006 * FUNCTION : needRotationReprocess 1007 * 1008 * DESCRIPTION: if online rotation needs to be done by cpp 1009 * 1010 * PARAMETERS : none 1011 * 1012 * RETURN : true: needed 1013 * false: no need 1014 *==========================================================================*/ 1015bool QCamera3PicChannel::needOnlineRotation() 1016{ 1017 //TBD_Later 1018 //if ((gCamCapability[mCameraId]->qcom_supported_feature_mask & CAM_QCOM_FEATURE_ROTATION) > 0 && 1019 if (mJpegSettings->jpeg_orientation > 0) { 1020 // current rotation is not zero, and pp has the capability to process rotation 1021 ALOGD("%s: need do online rotation", __func__); 1022 return true; 1023 } 1024 return false; 1025} 1026 1027/*=========================================================================== 1028 * FUNCTION : getThumbnailSize 1029 * 1030 * DESCRIPTION: get user set thumbnail size 1031 * 1032 * PARAMETERS : 1033 * @dim : output of thumbnail dimension 1034 * 1035 * RETURN : none 1036 *==========================================================================*/ 1037void QCamera3PicChannel::getThumbnailSize(cam_dimension_t &dim) 1038{ 1039 dim = mJpegSettings->thumbnail_size; 1040} 1041 1042/*=========================================================================== 1043 * FUNCTION : getJpegQuality 1044 * 1045 * DESCRIPTION: get user set jpeg quality 1046 * 1047 * PARAMETERS : none 1048 * 1049 * RETURN : jpeg quality setting 1050 *==========================================================================*/ 1051int QCamera3PicChannel::getJpegQuality() 1052{ 1053 int quality = mJpegSettings->jpeg_quality; 1054 if (quality < 0) { 1055 quality = 85; //set to default quality value 1056 } 1057 return quality; 1058} 1059 1060/*=========================================================================== 1061 * FUNCTION : getJpegRotation 1062 * 1063 * DESCRIPTION: get rotation information to be passed into jpeg encoding 1064 * 1065 * PARAMETERS : none 1066 * 1067 * RETURN : rotation information 1068 *==========================================================================*/ 1069int QCamera3PicChannel::getJpegRotation() { 1070 int rotation = mJpegSettings->jpeg_orientation; 1071 if (rotation < 0) { 1072 rotation = 0; 1073 } 1074 return rotation; 1075} 1076 1077/*=========================================================================== 1078 * FUNCTION : getRational 1079 * 1080 * DESCRIPTION: compose rational struct 1081 * 1082 * PARAMETERS : 1083 * @rat : ptr to struct to store rational info 1084 * @num :num of the rational 1085 * @denom : denom of the rational 1086 * 1087 * RETURN : int32_t type of status 1088 * NO_ERROR -- success 1089 * none-zero failure code 1090 *==========================================================================*/ 1091int32_t getRational(rat_t *rat, int num, int denom) 1092{ 1093 if (NULL == rat) { 1094 ALOGE("%s: NULL rat input", __func__); 1095 return BAD_VALUE; 1096 } 1097 rat->num = num; 1098 rat->denom = denom; 1099 return NO_ERROR; 1100} 1101 1102/*=========================================================================== 1103 * FUNCTION : parseGPSCoordinate 1104 * 1105 * DESCRIPTION: parse GPS coordinate string 1106 * 1107 * PARAMETERS : 1108 * @coord_str : [input] coordinate string 1109 * @coord : [output] ptr to struct to store coordinate 1110 * 1111 * RETURN : int32_t type of status 1112 * NO_ERROR -- success 1113 * none-zero failure code 1114 *==========================================================================*/ 1115int parseGPSCoordinate(const char *coord_str, rat_t* coord) 1116{ 1117 if(coord == NULL) { 1118 ALOGE("%s: error, invalid argument coord == NULL", __func__); 1119 return BAD_VALUE; 1120 } 1121 float degF = atof(coord_str); 1122 if (degF < 0) { 1123 degF = -degF; 1124 } 1125 float minF = (degF - (int) degF) * 60; 1126 float secF = (minF - (int) minF) * 60; 1127 1128 getRational(&coord[0], (int)degF, 1); 1129 getRational(&coord[1], (int)minF, 1); 1130 getRational(&coord[2], (int)(secF * 10000), 10000); 1131 return NO_ERROR; 1132} 1133 1134/*=========================================================================== 1135 * FUNCTION : getExifDateTime 1136 * 1137 * DESCRIPTION: query exif date time 1138 * 1139 * PARAMETERS : 1140 * @dateTime : string to store exif date time 1141 * @count : lenght of the dateTime string 1142 * 1143 * RETURN : int32_t type of status 1144 * NO_ERROR -- success 1145 * none-zero failure code 1146 *==========================================================================*/ 1147int32_t getExifDateTime(char *dateTime, uint32_t &count) 1148{ 1149 //get time and date from system 1150 time_t rawtime; 1151 struct tm * timeinfo; 1152 time(&rawtime); 1153 timeinfo = localtime (&rawtime); 1154 //Write datetime according to EXIF Spec 1155 //"YYYY:MM:DD HH:MM:SS" (20 chars including \0) 1156 snprintf(dateTime, 20, "%04d:%02d:%02d %02d:%02d:%02d", 1157 timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, 1158 timeinfo->tm_mday, timeinfo->tm_hour, 1159 timeinfo->tm_min, timeinfo->tm_sec); 1160 count = 20; 1161 1162 return NO_ERROR; 1163} 1164 1165/*=========================================================================== 1166 * FUNCTION : getExifFocalLength 1167 * 1168 * DESCRIPTION: get exif focal lenght 1169 * 1170 * PARAMETERS : 1171 * @focalLength : ptr to rational strcut to store focal lenght 1172 * 1173 * RETURN : int32_t type of status 1174 * NO_ERROR -- success 1175 * none-zero failure code 1176 *==========================================================================*/ 1177int32_t getExifFocalLength(rat_t *focalLength, float value) 1178{ 1179 int focalLengthValue = 1180 (int)(value * FOCAL_LENGTH_DECIMAL_PRECISION); 1181 return getRational(focalLength, focalLengthValue, FOCAL_LENGTH_DECIMAL_PRECISION); 1182} 1183 1184/*=========================================================================== 1185 * FUNCTION : getExifGpsProcessingMethod 1186 * 1187 * DESCRIPTION: get GPS processing method 1188 * 1189 * PARAMETERS : 1190 * @gpsProcessingMethod : string to store GPS process method 1191 * @count : lenght of the string 1192 * 1193 * RETURN : int32_t type of status 1194 * NO_ERROR -- success 1195 * none-zero failure code 1196 *==========================================================================*/ 1197int32_t getExifGpsProcessingMethod(char *gpsProcessingMethod, 1198 uint32_t &count, int value) 1199{ 1200 char str[30]; 1201 snprintf(str, sizeof(str), "%d", value); 1202 if(str != NULL) { 1203 memcpy(gpsProcessingMethod, ExifAsciiPrefix, EXIF_ASCII_PREFIX_SIZE); 1204 count = EXIF_ASCII_PREFIX_SIZE; 1205 strncpy(gpsProcessingMethod + EXIF_ASCII_PREFIX_SIZE, str, strlen(str)); 1206 count += strlen(str); 1207 gpsProcessingMethod[count++] = '\0'; // increase 1 for the last NULL char 1208 return NO_ERROR; 1209 } else { 1210 return BAD_VALUE; 1211 } 1212} 1213 1214/*=========================================================================== 1215 * FUNCTION : getExifLatitude 1216 * 1217 * DESCRIPTION: get exif latitude 1218 * 1219 * PARAMETERS : 1220 * @latitude : ptr to rational struct to store latitude info 1221 * @ladRef : charater to indicate latitude reference 1222 * 1223 * RETURN : int32_t type of status 1224 * NO_ERROR -- success 1225 * none-zero failure code 1226 *==========================================================================*/ 1227int32_t getExifLatitude(rat_t *latitude, 1228 char *latRef, double value) 1229{ 1230 char str[30]; 1231 snprintf(str, sizeof(str), "%f", value); 1232 if(str != NULL) { 1233 parseGPSCoordinate(str, latitude); 1234 1235 //set Latitude Ref 1236 float latitudeValue = strtof(str, 0); 1237 if(latitudeValue < 0.0f) { 1238 latRef[0] = 'S'; 1239 } else { 1240 latRef[0] = 'N'; 1241 } 1242 latRef[1] = '\0'; 1243 return NO_ERROR; 1244 }else{ 1245 return BAD_VALUE; 1246 } 1247} 1248 1249/*=========================================================================== 1250 * FUNCTION : getExifLongitude 1251 * 1252 * DESCRIPTION: get exif longitude 1253 * 1254 * PARAMETERS : 1255 * @longitude : ptr to rational struct to store longitude info 1256 * @lonRef : charater to indicate longitude reference 1257 * 1258 * RETURN : int32_t type of status 1259 * NO_ERROR -- success 1260 * none-zero failure code 1261 *==========================================================================*/ 1262int32_t getExifLongitude(rat_t *longitude, 1263 char *lonRef, double value) 1264{ 1265 char str[30]; 1266 snprintf(str, sizeof(str), "%f", value); 1267 if(str != NULL) { 1268 parseGPSCoordinate(str, longitude); 1269 1270 //set Longitude Ref 1271 float longitudeValue = strtof(str, 0); 1272 if(longitudeValue < 0.0f) { 1273 lonRef[0] = 'W'; 1274 } else { 1275 lonRef[0] = 'E'; 1276 } 1277 lonRef[1] = '\0'; 1278 return NO_ERROR; 1279 }else{ 1280 return BAD_VALUE; 1281 } 1282} 1283 1284/*=========================================================================== 1285 * FUNCTION : getExifAltitude 1286 * 1287 * DESCRIPTION: get exif altitude 1288 * 1289 * PARAMETERS : 1290 * @altitude : ptr to rational struct to store altitude info 1291 * @altRef : charater to indicate altitude reference 1292 * 1293 * RETURN : int32_t type of status 1294 * NO_ERROR -- success 1295 * none-zero failure code 1296 *==========================================================================*/ 1297int32_t getExifAltitude(rat_t *altitude, 1298 char *altRef, double value) 1299{ 1300 char str[30]; 1301 snprintf(str, sizeof(str), "%f", value); 1302 if(str != NULL) { 1303 double value = atof(str); 1304 *altRef = 0; 1305 if(value < 0){ 1306 *altRef = 1; 1307 value = -value; 1308 } 1309 return getRational(altitude, value*1000, 1000); 1310 }else{ 1311 return BAD_VALUE; 1312 } 1313} 1314 1315/*=========================================================================== 1316 * FUNCTION : getExifGpsDateTimeStamp 1317 * 1318 * DESCRIPTION: get exif GPS date time stamp 1319 * 1320 * PARAMETERS : 1321 * @gpsDateStamp : GPS date time stamp string 1322 * @bufLen : length of the string 1323 * @gpsTimeStamp : ptr to rational struct to store time stamp info 1324 * 1325 * RETURN : int32_t type of status 1326 * NO_ERROR -- success 1327 * none-zero failure code 1328 *==========================================================================*/ 1329int32_t getExifGpsDateTimeStamp(char *gpsDateStamp, 1330 uint32_t bufLen, 1331 rat_t *gpsTimeStamp, int64_t value) 1332{ 1333 char str[30]; 1334 snprintf(str, sizeof(str), "%d", value); 1335 if(str != NULL) { 1336 time_t unixTime = (time_t)atol(str); 1337 struct tm *UTCTimestamp = gmtime(&unixTime); 1338 1339 strftime(gpsDateStamp, bufLen, "%Y:%m:%d", UTCTimestamp); 1340 1341 getRational(&gpsTimeStamp[0], UTCTimestamp->tm_hour, 1); 1342 getRational(&gpsTimeStamp[1], UTCTimestamp->tm_min, 1); 1343 getRational(&gpsTimeStamp[2], UTCTimestamp->tm_sec, 1); 1344 1345 return NO_ERROR; 1346 } else { 1347 return BAD_VALUE; 1348 } 1349} 1350/*=========================================================================== 1351 * FUNCTION : getExifData 1352 * 1353 * DESCRIPTION: get exif data to be passed into jpeg encoding 1354 * 1355 * PARAMETERS : none 1356 * 1357 * RETURN : exif data from user setting and GPS 1358 *==========================================================================*/ 1359QCamera3Exif *QCamera3PicChannel::getExifData() 1360{ 1361 QCamera3Exif *exif = new QCamera3Exif(); 1362 if (exif == NULL) { 1363 ALOGE("%s: No memory for QCamera3Exif", __func__); 1364 return NULL; 1365 } 1366 1367 int32_t rc = NO_ERROR; 1368 uint32_t count = 0; 1369 1370 // add exif entries 1371 char dateTime[20]; 1372 memset(dateTime, 0, sizeof(dateTime)); 1373 count = 20; 1374 rc = getExifDateTime(dateTime, count); 1375 if(rc == NO_ERROR) { 1376 exif->addEntry(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL, 1377 EXIF_ASCII, 1378 count, 1379 (void *)dateTime); 1380 } else { 1381 ALOGE("%s: getExifDateTime failed", __func__); 1382 } 1383 1384 rat_t focalLength; 1385 rc = getExifFocalLength(&focalLength, mJpegSettings->lens_focal_length); 1386 if (rc == NO_ERROR) { 1387 exif->addEntry(EXIFTAGID_FOCAL_LENGTH, 1388 EXIF_RATIONAL, 1389 1, 1390 (void *)&(focalLength)); 1391 } else { 1392 ALOGE("%s: getExifFocalLength failed", __func__); 1393 } 1394 1395 //TBD_Later 1396 /*uint16_t isoSpeed = mParameters.getExifIsoSpeed(); 1397 exif->addEntry(EXIFTAGID_ISO_SPEED_RATING, 1398 EXIF_SHORT, 1399 1, 1400 (void *)&(isoSpeed)); 1401 */ 1402 char gpsProcessingMethod[EXIF_ASCII_PREFIX_SIZE + GPS_PROCESSING_METHOD_SIZE]; 1403 count = 0; 1404 rc = getExifGpsProcessingMethod(gpsProcessingMethod, count, mJpegSettings->gps_processing_method); 1405 if(rc == NO_ERROR) { 1406 exif->addEntry(EXIFTAGID_GPS_PROCESSINGMETHOD, 1407 EXIF_ASCII, 1408 count, 1409 (void *)gpsProcessingMethod); 1410 } else { 1411 ALOGE("%s: getExifGpsProcessingMethod failed", __func__); 1412 } 1413 1414 rat_t latitude[3]; 1415 char latRef[2]; 1416 rc = getExifLatitude(latitude, latRef, mJpegSettings->gps_coordinates[0]); 1417 if(rc == NO_ERROR) { 1418 exif->addEntry(EXIFTAGID_GPS_LATITUDE, 1419 EXIF_RATIONAL, 1420 3, 1421 (void *)latitude); 1422 exif->addEntry(EXIFTAGID_GPS_LATITUDE_REF, 1423 EXIF_ASCII, 1424 2, 1425 (void *)latRef); 1426 } else { 1427 ALOGE("%s: getExifLatitude failed", __func__); 1428 } 1429 1430 rat_t longitude[3]; 1431 char lonRef[2]; 1432 rc = getExifLongitude(longitude, lonRef, mJpegSettings->gps_coordinates[1]); 1433 if(rc == NO_ERROR) { 1434 exif->addEntry(EXIFTAGID_GPS_LONGITUDE, 1435 EXIF_RATIONAL, 1436 3, 1437 (void *)longitude); 1438 1439 exif->addEntry(EXIFTAGID_GPS_LONGITUDE_REF, 1440 EXIF_ASCII, 1441 2, 1442 (void *)lonRef); 1443 } else { 1444 ALOGE("%s: getExifLongitude failed", __func__); 1445 } 1446 1447 rat_t altitude; 1448 char altRef; 1449 rc = getExifAltitude(&altitude, &altRef, mJpegSettings->gps_coordinates[2]); 1450 if(rc == NO_ERROR) { 1451 exif->addEntry(EXIFTAGID_GPS_ALTITUDE, 1452 EXIF_RATIONAL, 1453 1, 1454 (void *)&(altitude)); 1455 1456 exif->addEntry(EXIFTAGID_GPS_ALTITUDE_REF, 1457 EXIF_BYTE, 1458 1, 1459 (void *)&altRef); 1460 } else { 1461 ALOGE("%s: getExifAltitude failed", __func__); 1462 } 1463 1464 char gpsDateStamp[20]; 1465 rat_t gpsTimeStamp[3]; 1466 rc = getExifGpsDateTimeStamp(gpsDateStamp, 20, gpsTimeStamp, mJpegSettings->gps_timestamp); 1467 if(rc == NO_ERROR) { 1468 exif->addEntry(EXIFTAGID_GPS_DATESTAMP, 1469 EXIF_ASCII, 1470 strlen(gpsDateStamp) + 1, 1471 (void *)gpsDateStamp); 1472 1473 exif->addEntry(EXIFTAGID_GPS_TIMESTAMP, 1474 EXIF_RATIONAL, 1475 3, 1476 (void *)gpsTimeStamp); 1477 } else { 1478 ALOGE("%s: getExifGpsDataTimeStamp failed", __func__); 1479 } 1480 1481 return exif; 1482} 1483 1484int QCamera3PicChannel::kMaxBuffers = 1; 1485}; // namespace qcamera 1486