QCamera3Channel.cpp revision 33cb7276f6c4d2eda72253d11cd9242e1f82bf7d
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 = 3; 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((metadata_buffer_t *)(super_frame->bufs[0]->buffer), 689 NULL, requestNumber, mUserData); 690 691 //Return the buffer 692 stream->bufDone(super_frame->bufs[0]->buf_idx); 693} 694 695QCamera3Memory* QCamera3MetadataChannel::getStreamBufs(uint32_t len) 696{ 697 int rc; 698 if (len != sizeof(metadata_buffer_t)) { 699 ALOGE("%s: size doesn't match %d vs %d", __func__, 700 len, sizeof(metadata_buffer_t)); 701 return NULL; 702 } 703 mMemory = new QCamera3HeapMemory(); 704 if (!mMemory) { 705 ALOGE("%s: unable to create metadata memory", __func__); 706 return NULL; 707 } 708 rc = mMemory->allocate(MIN_STREAMING_BUFFER_NUM, len, true); 709 if (rc < 0) { 710 ALOGE("%s: unable to allocate metadata memory", __func__); 711 delete mMemory; 712 mMemory = NULL; 713 return NULL; 714 } 715 memset(mMemory->getPtr(0), 0, sizeof(metadata_buffer_t)); 716 return mMemory; 717} 718 719void QCamera3MetadataChannel::putStreamBufs() 720{ 721 mMemory->deallocate(); 722 delete mMemory; 723 mMemory = NULL; 724} 725 726/*=========================================================================== 727 * FUNCTION : jpegEvtHandle 728 * 729 * DESCRIPTION: Function registerd to mm-jpeg-interface to handle jpeg events. 730 Construct result payload and call mChannelCb to deliver buffer 731 to framework. 732 * 733 * PARAMETERS : 734 * @status : status of jpeg job 735 * @client_hdl: jpeg client handle 736 * @jobId : jpeg job Id 737 * @p_ouput : ptr to jpeg output result struct 738 * @userdata : user data ptr 739 * 740 * RETURN : none 741 *==========================================================================*/ 742void QCamera3PicChannel::jpegEvtHandle(jpeg_job_status_t status, 743 uint32_t /*client_hdl*/, 744 uint32_t jobId, 745 mm_jpeg_output_t *p_output, 746 void *userdata) 747{ 748 buffer_handle_t *resultBuffer; 749 int32_t resultFrameNumber; 750 int resultStatus = CAMERA3_BUFFER_STATUS_OK; 751 camera3_stream_buffer_t result; 752 camera3_jpeg_blob_t jpegHeader; 753 char* jpeg_eof = 0; 754 QCamera3PicChannel *obj = (QCamera3PicChannel *)userdata; 755 if (obj) { 756 //Construct payload for process_capture_result. Call mChannelCb 757 758 qcamera_jpeg_data_t *job = obj->m_postprocessor.findJpegJobByJobId(jobId); 759 760 if ((job == NULL) || (status == JPEG_JOB_STATUS_ERROR)) { 761 ALOGE("%s: Error in jobId: (%d) with status: %d", __func__, jobId, status); 762 resultStatus = CAMERA3_BUFFER_STATUS_ERROR; 763 } 764 765 //Construct jpeg transient header of type camera3_jpeg_blob_t 766 //Append at the end of jpeg image of buf_filled_len size 767 768 jpegHeader.jpeg_blob_id = CAMERA3_JPEG_BLOB_ID; 769 jpegHeader.jpeg_size = p_output->buf_filled_len; 770 771 772 char* jpeg_buf = (char *)p_output->buf_vaddr; 773 774 jpeg_eof = &jpeg_buf[p_output->buf_filled_len]; 775 memcpy(jpeg_eof, &jpegHeader, sizeof(jpegHeader)); 776 777 ////Use below data to issue framework callback 778 779 resultBuffer = obj->mCamera3Buffers[0]; 780 resultFrameNumber = obj->mMemory->getFrameNumber(0); 781 782 result.stream = obj->mCamera3Stream; 783 result.buffer = resultBuffer; 784 result.status = resultStatus; 785 result.acquire_fence = -1; 786 result.release_fence = -1; 787 788 obj->mChannelCB(NULL, &result, resultFrameNumber, obj->mUserData); 789 790 // release internal data for jpeg job 791 if (job != NULL) { 792 obj->m_postprocessor.releaseJpegJobData(job); 793 free(job); 794 } 795 return; 796 // } 797 } else { 798 ALOGE("%s: Null userdata in jpeg callback", __func__); 799 } 800} 801 802QCamera3PicChannel::QCamera3PicChannel(uint32_t cam_handle, 803 mm_camera_ops_t *cam_ops, 804 channel_cb_routine cb_routine, 805 cam_padding_info_t *paddingInfo, 806 void *userData, 807 camera3_stream_t *stream) : 808 QCamera3Channel(cam_handle, cam_ops, cb_routine, paddingInfo, userData), 809 mCamera3Stream(stream), 810 m_postprocessor(this), 811 mCamera3Buffers(NULL), 812 mMemory(NULL), 813 mYuvMemory(NULL) 814{ 815 //TODO 816} 817 818QCamera3PicChannel::~QCamera3PicChannel() 819{ 820 if (mCamera3Buffers) { 821 delete[] mCamera3Buffers; 822 } 823} 824 825int32_t QCamera3PicChannel::initialize() 826{ 827 int32_t rc = m_postprocessor.init(jpegEvtHandle, this); 828 if (rc != 0) { 829 ALOGE("Init Postprocessor failed"); 830 return UNKNOWN_ERROR; 831 } 832 return rc; 833} 834 835int32_t QCamera3PicChannel::request(buffer_handle_t *buffer, uint32_t frameNumber, jpeg_settings_t* jpegSettings) 836{ 837 //FIX ME: Return buffer back in case of failures below. 838 839 int32_t rc = NO_ERROR; 840 int index; 841 mJpegSettings = jpegSettings; 842 if(!m_bIsActive) { 843 ALOGD("%s: First request on this channel starting stream",__func__); 844 //Stream on for main image. YUV buffer is queued to the kernel at the end of this call. 845 rc = start(); 846 } else { 847 ALOGV("%s: Request on an existing stream",__func__); 848 } 849 850 if(rc != NO_ERROR) { 851 ALOGE("%s: Failed to start the stream on the request",__func__); 852 return rc; 853 } 854 855 856 if(!mMemory) { 857 ALOGE("%s: error, Gralloc Memory object not yet created for this stream",__func__); 858 return NO_MEMORY; 859 } 860 861 index = mMemory->getMatchBufIndex((void*)buffer); 862 if(index < 0) { 863 ALOGE("%s: Could not find object among registered buffers",__func__); 864 return DEAD_OBJECT; 865 } 866 867 rc = mMemory->markFrameNumber(index, frameNumber); 868 869 //Start the postprocessor for jpeg encoding. Pass mMemory as destination buffer 870 m_postprocessor.start(mMemory); 871 return rc; 872} 873 874int32_t QCamera3PicChannel::registerBuffers(uint32_t num_buffers, 875 buffer_handle_t **buffers) 876{ 877 int rc = 0; 878 struct private_handle_t *priv_handle = (struct private_handle_t *)(*buffers[0]); 879 cam_stream_type_t streamType; 880 cam_format_t streamFormat; 881 cam_dimension_t streamDim; 882 883 rc = init(NULL, NULL); 884 if (rc < 0) { 885 ALOGE("%s: init failed", __func__); 886 return rc; 887 } 888 889 if (mCamera3Stream->format == HAL_PIXEL_FORMAT_BLOB) { 890 streamType = CAM_STREAM_TYPE_SNAPSHOT; 891 streamFormat = CAM_FORMAT_YUV_420_NV21; 892 } else { 893 //TODO: Fail for other types of streams for now 894 ALOGE("%s: format is not BLOB", __func__); 895 return -EINVAL; 896 } 897 /* Bookkeep buffer set because they go out of scope after register call */ 898 mNumBufs = num_buffers; 899 if(mNumBufs > 1) { 900 ALOGE("%s: currently no support for multiple snapshot buffers"); 901 return -EINVAL; 902 } 903 904 mCamera3Buffers = new buffer_handle_t*[num_buffers]; 905 if (mCamera3Buffers == NULL) { 906 ALOGE("%s: Failed to allocate buffer_handle_t*", __func__); 907 return -ENOMEM; 908 } 909 for (size_t i = 0; i < num_buffers; i++) 910 mCamera3Buffers[i] = buffers[i]; 911 912 streamDim.width = mCamera3Stream->width; 913 streamDim.height = mCamera3Stream->height; 914 rc = QCamera3Channel::addStream(streamType, streamFormat, streamDim, 915 num_buffers); 916 917 return rc; 918} 919 920void QCamera3PicChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame, 921 QCamera3Stream *stream) 922{ 923 //TODO 924 //Used only for getting YUV. Jpeg callback will be sent back from channel directly to HWI. 925 //Refer to func jpegEvtHandle 926 927 //Got the yuv callback. Calling yuv callback handler in PostProc 928 uint8_t frameIndex; 929 if(!super_frame) { 930 ALOGE("%s: Invalid Super buffer",__func__); 931 return; 932 } 933 934 if(super_frame->num_bufs != 1) { 935 ALOGE("%s: Multiple streams are not supported",__func__); 936 return; 937 } 938 if(super_frame->bufs[0] == NULL ) { 939 ALOGE("%s: Error, Super buffer frame does not contain valid buffer", 940 __func__); 941 return; 942 } 943 944 frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx; 945 if(frameIndex >= mNumBufs) { 946 ALOGE("%s: Error, Invalid index for buffer",__func__); 947 if(stream) { 948 stream->bufDone(frameIndex); 949 } 950 return; 951 } 952 953 m_postprocessor.processData(super_frame); 954 return; 955} 956 957QCamera3Memory* QCamera3PicChannel::getStreamBufs(uint32_t len) 958{ 959 int rc = 0; 960 961 if (mNumBufs == 0 || mCamera3Buffers == NULL) { 962 ALOGE("%s: buffers not registered yet", __func__); 963 return NULL; 964 } 965 966 mMemory = new QCamera3GrallocMemory(); 967 if (mMemory == NULL) { 968 return NULL; 969 } 970 971 //Registering Jpeg output buffer 972 if (mMemory->registerBuffers(mNumBufs, mCamera3Buffers) < 0) { 973 delete mMemory; 974 mMemory = NULL; 975 return NULL; 976 } 977 978 mYuvMemory = new QCamera3HeapMemory(); 979 if (!mYuvMemory) { 980 ALOGE("%s: unable to create metadata memory", __func__); 981 return NULL; 982 } 983 984 //Queue YUV buffers in the beginning mQueueAll = true 985 rc = mYuvMemory->allocate(1, len, true); 986 if (rc < 0) { 987 ALOGE("%s: unable to allocate metadata memory", __func__); 988 delete mYuvMemory; 989 mYuvMemory = NULL; 990 return NULL; 991 } 992 return mYuvMemory; 993} 994 995void QCamera3PicChannel::putStreamBufs() 996{ 997 mMemory->unregisterBuffers(); 998 delete mMemory; 999 mMemory = NULL; 1000 1001 mYuvMemory->deallocate(); 1002 delete mYuvMemory; 1003 mYuvMemory = NULL; 1004} 1005 1006/*=========================================================================== 1007 * FUNCTION : needRotationReprocess 1008 * 1009 * DESCRIPTION: if online rotation needs to be done by cpp 1010 * 1011 * PARAMETERS : none 1012 * 1013 * RETURN : true: needed 1014 * false: no need 1015 *==========================================================================*/ 1016bool QCamera3PicChannel::needOnlineRotation() 1017{ 1018 //TBD_Later 1019 //if ((gCamCapability[mCameraId]->qcom_supported_feature_mask & CAM_QCOM_FEATURE_ROTATION) > 0 && 1020 if (mJpegSettings->jpeg_orientation > 0) { 1021 // current rotation is not zero, and pp has the capability to process rotation 1022 ALOGD("%s: need do online rotation", __func__); 1023 return true; 1024 } 1025 return false; 1026} 1027 1028/*=========================================================================== 1029 * FUNCTION : getThumbnailSize 1030 * 1031 * DESCRIPTION: get user set thumbnail size 1032 * 1033 * PARAMETERS : 1034 * @dim : output of thumbnail dimension 1035 * 1036 * RETURN : none 1037 *==========================================================================*/ 1038void QCamera3PicChannel::getThumbnailSize(cam_dimension_t &dim) 1039{ 1040 dim = mJpegSettings->thumbnail_size; 1041} 1042 1043/*=========================================================================== 1044 * FUNCTION : getJpegQuality 1045 * 1046 * DESCRIPTION: get user set jpeg quality 1047 * 1048 * PARAMETERS : none 1049 * 1050 * RETURN : jpeg quality setting 1051 *==========================================================================*/ 1052int QCamera3PicChannel::getJpegQuality() 1053{ 1054 int quality = mJpegSettings->jpeg_quality; 1055 if (quality < 0) { 1056 quality = 85; //set to default quality value 1057 } 1058 return quality; 1059} 1060 1061/*=========================================================================== 1062 * FUNCTION : getJpegRotation 1063 * 1064 * DESCRIPTION: get rotation information to be passed into jpeg encoding 1065 * 1066 * PARAMETERS : none 1067 * 1068 * RETURN : rotation information 1069 *==========================================================================*/ 1070int QCamera3PicChannel::getJpegRotation() { 1071 int rotation = mJpegSettings->jpeg_orientation; 1072 if (rotation < 0) { 1073 rotation = 0; 1074 } 1075 return rotation; 1076} 1077 1078/*=========================================================================== 1079 * FUNCTION : getRational 1080 * 1081 * DESCRIPTION: compose rational struct 1082 * 1083 * PARAMETERS : 1084 * @rat : ptr to struct to store rational info 1085 * @num :num of the rational 1086 * @denom : denom of the rational 1087 * 1088 * RETURN : int32_t type of status 1089 * NO_ERROR -- success 1090 * none-zero failure code 1091 *==========================================================================*/ 1092int32_t getRational(rat_t *rat, int num, int denom) 1093{ 1094 if (NULL == rat) { 1095 ALOGE("%s: NULL rat input", __func__); 1096 return BAD_VALUE; 1097 } 1098 rat->num = num; 1099 rat->denom = denom; 1100 return NO_ERROR; 1101} 1102 1103/*=========================================================================== 1104 * FUNCTION : parseGPSCoordinate 1105 * 1106 * DESCRIPTION: parse GPS coordinate string 1107 * 1108 * PARAMETERS : 1109 * @coord_str : [input] coordinate string 1110 * @coord : [output] ptr to struct to store coordinate 1111 * 1112 * RETURN : int32_t type of status 1113 * NO_ERROR -- success 1114 * none-zero failure code 1115 *==========================================================================*/ 1116int parseGPSCoordinate(const char *coord_str, rat_t* coord) 1117{ 1118 if(coord == NULL) { 1119 ALOGE("%s: error, invalid argument coord == NULL", __func__); 1120 return BAD_VALUE; 1121 } 1122 float degF = atof(coord_str); 1123 if (degF < 0) { 1124 degF = -degF; 1125 } 1126 float minF = (degF - (int) degF) * 60; 1127 float secF = (minF - (int) minF) * 60; 1128 1129 getRational(&coord[0], (int)degF, 1); 1130 getRational(&coord[1], (int)minF, 1); 1131 getRational(&coord[2], (int)(secF * 10000), 10000); 1132 return NO_ERROR; 1133} 1134 1135/*=========================================================================== 1136 * FUNCTION : getExifDateTime 1137 * 1138 * DESCRIPTION: query exif date time 1139 * 1140 * PARAMETERS : 1141 * @dateTime : string to store exif date time 1142 * @count : lenght of the dateTime string 1143 * 1144 * RETURN : int32_t type of status 1145 * NO_ERROR -- success 1146 * none-zero failure code 1147 *==========================================================================*/ 1148int32_t getExifDateTime(char *dateTime, uint32_t &count) 1149{ 1150 //get time and date from system 1151 time_t rawtime; 1152 struct tm * timeinfo; 1153 time(&rawtime); 1154 timeinfo = localtime (&rawtime); 1155 //Write datetime according to EXIF Spec 1156 //"YYYY:MM:DD HH:MM:SS" (20 chars including \0) 1157 snprintf(dateTime, 20, "%04d:%02d:%02d %02d:%02d:%02d", 1158 timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, 1159 timeinfo->tm_mday, timeinfo->tm_hour, 1160 timeinfo->tm_min, timeinfo->tm_sec); 1161 count = 20; 1162 1163 return NO_ERROR; 1164} 1165 1166/*=========================================================================== 1167 * FUNCTION : getExifFocalLength 1168 * 1169 * DESCRIPTION: get exif focal lenght 1170 * 1171 * PARAMETERS : 1172 * @focalLength : ptr to rational strcut to store focal lenght 1173 * 1174 * RETURN : int32_t type of status 1175 * NO_ERROR -- success 1176 * none-zero failure code 1177 *==========================================================================*/ 1178int32_t getExifFocalLength(rat_t *focalLength, float value) 1179{ 1180 int focalLengthValue = 1181 (int)(value * FOCAL_LENGTH_DECIMAL_PRECISION); 1182 return getRational(focalLength, focalLengthValue, FOCAL_LENGTH_DECIMAL_PRECISION); 1183} 1184 1185/*=========================================================================== 1186 * FUNCTION : getExifGpsProcessingMethod 1187 * 1188 * DESCRIPTION: get GPS processing method 1189 * 1190 * PARAMETERS : 1191 * @gpsProcessingMethod : string to store GPS process method 1192 * @count : lenght of the string 1193 * 1194 * RETURN : int32_t type of status 1195 * NO_ERROR -- success 1196 * none-zero failure code 1197 *==========================================================================*/ 1198int32_t getExifGpsProcessingMethod(char *gpsProcessingMethod, 1199 uint32_t &count, int value) 1200{ 1201 char str[30]; 1202 snprintf(str, sizeof(str), "%d", value); 1203 if(str != NULL) { 1204 memcpy(gpsProcessingMethod, ExifAsciiPrefix, EXIF_ASCII_PREFIX_SIZE); 1205 count = EXIF_ASCII_PREFIX_SIZE; 1206 strncpy(gpsProcessingMethod + EXIF_ASCII_PREFIX_SIZE, str, strlen(str)); 1207 count += strlen(str); 1208 gpsProcessingMethod[count++] = '\0'; // increase 1 for the last NULL char 1209 return NO_ERROR; 1210 } else { 1211 return BAD_VALUE; 1212 } 1213} 1214 1215/*=========================================================================== 1216 * FUNCTION : getExifLatitude 1217 * 1218 * DESCRIPTION: get exif latitude 1219 * 1220 * PARAMETERS : 1221 * @latitude : ptr to rational struct to store latitude info 1222 * @ladRef : charater to indicate latitude reference 1223 * 1224 * RETURN : int32_t type of status 1225 * NO_ERROR -- success 1226 * none-zero failure code 1227 *==========================================================================*/ 1228int32_t getExifLatitude(rat_t *latitude, 1229 char *latRef, double value) 1230{ 1231 char str[30]; 1232 snprintf(str, sizeof(str), "%f", value); 1233 if(str != NULL) { 1234 parseGPSCoordinate(str, latitude); 1235 1236 //set Latitude Ref 1237 float latitudeValue = strtof(str, 0); 1238 if(latitudeValue < 0.0f) { 1239 latRef[0] = 'S'; 1240 } else { 1241 latRef[0] = 'N'; 1242 } 1243 latRef[1] = '\0'; 1244 return NO_ERROR; 1245 }else{ 1246 return BAD_VALUE; 1247 } 1248} 1249 1250/*=========================================================================== 1251 * FUNCTION : getExifLongitude 1252 * 1253 * DESCRIPTION: get exif longitude 1254 * 1255 * PARAMETERS : 1256 * @longitude : ptr to rational struct to store longitude info 1257 * @lonRef : charater to indicate longitude reference 1258 * 1259 * RETURN : int32_t type of status 1260 * NO_ERROR -- success 1261 * none-zero failure code 1262 *==========================================================================*/ 1263int32_t getExifLongitude(rat_t *longitude, 1264 char *lonRef, double value) 1265{ 1266 char str[30]; 1267 snprintf(str, sizeof(str), "%f", value); 1268 if(str != NULL) { 1269 parseGPSCoordinate(str, longitude); 1270 1271 //set Longitude Ref 1272 float longitudeValue = strtof(str, 0); 1273 if(longitudeValue < 0.0f) { 1274 lonRef[0] = 'W'; 1275 } else { 1276 lonRef[0] = 'E'; 1277 } 1278 lonRef[1] = '\0'; 1279 return NO_ERROR; 1280 }else{ 1281 return BAD_VALUE; 1282 } 1283} 1284 1285/*=========================================================================== 1286 * FUNCTION : getExifAltitude 1287 * 1288 * DESCRIPTION: get exif altitude 1289 * 1290 * PARAMETERS : 1291 * @altitude : ptr to rational struct to store altitude info 1292 * @altRef : charater to indicate altitude reference 1293 * 1294 * RETURN : int32_t type of status 1295 * NO_ERROR -- success 1296 * none-zero failure code 1297 *==========================================================================*/ 1298int32_t getExifAltitude(rat_t *altitude, 1299 char *altRef, double value) 1300{ 1301 char str[30]; 1302 snprintf(str, sizeof(str), "%f", value); 1303 if(str != NULL) { 1304 double value = atof(str); 1305 *altRef = 0; 1306 if(value < 0){ 1307 *altRef = 1; 1308 value = -value; 1309 } 1310 return getRational(altitude, value*1000, 1000); 1311 }else{ 1312 return BAD_VALUE; 1313 } 1314} 1315 1316/*=========================================================================== 1317 * FUNCTION : getExifGpsDateTimeStamp 1318 * 1319 * DESCRIPTION: get exif GPS date time stamp 1320 * 1321 * PARAMETERS : 1322 * @gpsDateStamp : GPS date time stamp string 1323 * @bufLen : length of the string 1324 * @gpsTimeStamp : ptr to rational struct to store time stamp info 1325 * 1326 * RETURN : int32_t type of status 1327 * NO_ERROR -- success 1328 * none-zero failure code 1329 *==========================================================================*/ 1330int32_t getExifGpsDateTimeStamp(char *gpsDateStamp, 1331 uint32_t bufLen, 1332 rat_t *gpsTimeStamp, int64_t value) 1333{ 1334 char str[30]; 1335 snprintf(str, sizeof(str), "%d", value); 1336 if(str != NULL) { 1337 time_t unixTime = (time_t)atol(str); 1338 struct tm *UTCTimestamp = gmtime(&unixTime); 1339 1340 strftime(gpsDateStamp, bufLen, "%Y:%m:%d", UTCTimestamp); 1341 1342 getRational(&gpsTimeStamp[0], UTCTimestamp->tm_hour, 1); 1343 getRational(&gpsTimeStamp[1], UTCTimestamp->tm_min, 1); 1344 getRational(&gpsTimeStamp[2], UTCTimestamp->tm_sec, 1); 1345 1346 return NO_ERROR; 1347 } else { 1348 return BAD_VALUE; 1349 } 1350} 1351/*=========================================================================== 1352 * FUNCTION : getExifData 1353 * 1354 * DESCRIPTION: get exif data to be passed into jpeg encoding 1355 * 1356 * PARAMETERS : none 1357 * 1358 * RETURN : exif data from user setting and GPS 1359 *==========================================================================*/ 1360QCamera3Exif *QCamera3PicChannel::getExifData() 1361{ 1362 QCamera3Exif *exif = new QCamera3Exif(); 1363 if (exif == NULL) { 1364 ALOGE("%s: No memory for QCamera3Exif", __func__); 1365 return NULL; 1366 } 1367 1368 int32_t rc = NO_ERROR; 1369 uint32_t count = 0; 1370 1371 // add exif entries 1372 char dateTime[20]; 1373 memset(dateTime, 0, sizeof(dateTime)); 1374 count = 20; 1375 rc = getExifDateTime(dateTime, count); 1376 if(rc == NO_ERROR) { 1377 exif->addEntry(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL, 1378 EXIF_ASCII, 1379 count, 1380 (void *)dateTime); 1381 } else { 1382 ALOGE("%s: getExifDateTime failed", __func__); 1383 } 1384 1385 rat_t focalLength; 1386 rc = getExifFocalLength(&focalLength, mJpegSettings->lens_focal_length); 1387 if (rc == NO_ERROR) { 1388 exif->addEntry(EXIFTAGID_FOCAL_LENGTH, 1389 EXIF_RATIONAL, 1390 1, 1391 (void *)&(focalLength)); 1392 } else { 1393 ALOGE("%s: getExifFocalLength failed", __func__); 1394 } 1395 1396 //TBD_Later 1397 /*uint16_t isoSpeed = mParameters.getExifIsoSpeed(); 1398 exif->addEntry(EXIFTAGID_ISO_SPEED_RATING, 1399 EXIF_SHORT, 1400 1, 1401 (void *)&(isoSpeed)); 1402 */ 1403 char gpsProcessingMethod[EXIF_ASCII_PREFIX_SIZE + GPS_PROCESSING_METHOD_SIZE]; 1404 count = 0; 1405 rc = getExifGpsProcessingMethod(gpsProcessingMethod, count, mJpegSettings->gps_processing_method); 1406 if(rc == NO_ERROR) { 1407 exif->addEntry(EXIFTAGID_GPS_PROCESSINGMETHOD, 1408 EXIF_ASCII, 1409 count, 1410 (void *)gpsProcessingMethod); 1411 } else { 1412 ALOGE("%s: getExifGpsProcessingMethod failed", __func__); 1413 } 1414 1415 rat_t latitude[3]; 1416 char latRef[2]; 1417 rc = getExifLatitude(latitude, latRef, mJpegSettings->gps_coordinates[0]); 1418 if(rc == NO_ERROR) { 1419 exif->addEntry(EXIFTAGID_GPS_LATITUDE, 1420 EXIF_RATIONAL, 1421 3, 1422 (void *)latitude); 1423 exif->addEntry(EXIFTAGID_GPS_LATITUDE_REF, 1424 EXIF_ASCII, 1425 2, 1426 (void *)latRef); 1427 } else { 1428 ALOGE("%s: getExifLatitude failed", __func__); 1429 } 1430 1431 rat_t longitude[3]; 1432 char lonRef[2]; 1433 rc = getExifLongitude(longitude, lonRef, mJpegSettings->gps_coordinates[1]); 1434 if(rc == NO_ERROR) { 1435 exif->addEntry(EXIFTAGID_GPS_LONGITUDE, 1436 EXIF_RATIONAL, 1437 3, 1438 (void *)longitude); 1439 1440 exif->addEntry(EXIFTAGID_GPS_LONGITUDE_REF, 1441 EXIF_ASCII, 1442 2, 1443 (void *)lonRef); 1444 } else { 1445 ALOGE("%s: getExifLongitude failed", __func__); 1446 } 1447 1448 rat_t altitude; 1449 char altRef; 1450 rc = getExifAltitude(&altitude, &altRef, mJpegSettings->gps_coordinates[2]); 1451 if(rc == NO_ERROR) { 1452 exif->addEntry(EXIFTAGID_GPS_ALTITUDE, 1453 EXIF_RATIONAL, 1454 1, 1455 (void *)&(altitude)); 1456 1457 exif->addEntry(EXIFTAGID_GPS_ALTITUDE_REF, 1458 EXIF_BYTE, 1459 1, 1460 (void *)&altRef); 1461 } else { 1462 ALOGE("%s: getExifAltitude failed", __func__); 1463 } 1464 1465 char gpsDateStamp[20]; 1466 rat_t gpsTimeStamp[3]; 1467 rc = getExifGpsDateTimeStamp(gpsDateStamp, 20, gpsTimeStamp, mJpegSettings->gps_timestamp); 1468 if(rc == NO_ERROR) { 1469 exif->addEntry(EXIFTAGID_GPS_DATESTAMP, 1470 EXIF_ASCII, 1471 strlen(gpsDateStamp) + 1, 1472 (void *)gpsDateStamp); 1473 1474 exif->addEntry(EXIFTAGID_GPS_TIMESTAMP, 1475 EXIF_RATIONAL, 1476 3, 1477 (void *)gpsTimeStamp); 1478 } else { 1479 ALOGE("%s: getExifGpsDataTimeStamp failed", __func__); 1480 } 1481 1482 return exif; 1483} 1484 1485int QCamera3PicChannel::kMaxBuffers = 1; 1486}; // namespace qcamera 1487