1/* 2 * Copyright (C) Texas Instruments - http://www.ti.com/ 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 18 19 20#define LOG_TAG "CameraHAL" 21 22 23#include "CameraHal.h" 24#include "VideoMetadata.h" 25#include "Encoder_libjpeg.h" 26#include <MetadataBufferType.h> 27#include <ui/GraphicBuffer.h> 28#include <ui/GraphicBufferMapper.h> 29#include "NV12_resize.h" 30 31namespace android { 32 33const int AppCallbackNotifier::NOTIFIER_TIMEOUT = -1; 34KeyedVector<void*, sp<Encoder_libjpeg> > gEncoderQueue; 35 36void AppCallbackNotifierEncoderCallback(void* main_jpeg, 37 void* thumb_jpeg, 38 CameraFrame::FrameType type, 39 void* cookie1, 40 void* cookie2, 41 void* cookie3, 42 bool canceled) 43{ 44 if (cookie1 && !canceled) { 45 AppCallbackNotifier* cb = (AppCallbackNotifier*) cookie1; 46 cb->EncoderDoneCb(main_jpeg, thumb_jpeg, type, cookie2, cookie3); 47 } 48 49 if (main_jpeg) { 50 free(main_jpeg); 51 } 52 53 if (thumb_jpeg) { 54 if (((Encoder_libjpeg::params *) thumb_jpeg)->dst) { 55 free(((Encoder_libjpeg::params *) thumb_jpeg)->dst); 56 } 57 free(thumb_jpeg); 58 } 59} 60 61/*--------------------NotificationHandler Class STARTS here-----------------------------*/ 62 63void AppCallbackNotifier::EncoderDoneCb(void* main_jpeg, void* thumb_jpeg, CameraFrame::FrameType type, void* cookie1, void* cookie2) 64{ 65 camera_memory_t* encoded_mem = NULL; 66 Encoder_libjpeg::params *main_param = NULL, *thumb_param = NULL; 67 size_t jpeg_size; 68 uint8_t* src = NULL; 69 sp<Encoder_libjpeg> encoder = NULL; 70 71 LOG_FUNCTION_NAME; 72 73 camera_memory_t* picture = NULL; 74 75 { 76 Mutex::Autolock lock(mLock); 77 78 if (!main_jpeg) { 79 goto exit; 80 } 81 82 encoded_mem = (camera_memory_t*) cookie1; 83 main_param = (Encoder_libjpeg::params *) main_jpeg; 84 jpeg_size = main_param->jpeg_size; 85 src = main_param->src; 86 87 if(encoded_mem && encoded_mem->data && (jpeg_size > 0)) { 88 if (cookie2) { 89 ExifElementsTable* exif = (ExifElementsTable*) cookie2; 90 Section_t* exif_section = NULL; 91 92 exif->insertExifToJpeg((unsigned char*) encoded_mem->data, jpeg_size); 93 94 if(thumb_jpeg) { 95 thumb_param = (Encoder_libjpeg::params *) thumb_jpeg; 96 exif->insertExifThumbnailImage((const char*)thumb_param->dst, 97 (int)thumb_param->jpeg_size); 98 } 99 100 exif_section = FindSection(M_EXIF); 101 102 if (exif_section) { 103 picture = mRequestMemory(-1, jpeg_size + exif_section->Size, 1, NULL); 104 if (picture && picture->data) { 105 exif->saveJpeg((unsigned char*) picture->data, jpeg_size + exif_section->Size); 106 } 107 } 108 delete exif; 109 cookie2 = NULL; 110 } else { 111 picture = mRequestMemory(-1, jpeg_size, 1, NULL); 112 if (picture && picture->data) { 113 memcpy(picture->data, encoded_mem->data, jpeg_size); 114 } 115 } 116 } 117 } // scope for mutex lock 118 119 if (!mRawAvailable) { 120 dummyRaw(); 121 } else { 122 mRawAvailable = false; 123 } 124 125 // Send the callback to the application only if the notifier is started and the message is enabled 126 if(picture && (mNotifierState==AppCallbackNotifier::NOTIFIER_STARTED) && 127 (mCameraHal->msgTypeEnabled(CAMERA_MSG_COMPRESSED_IMAGE))) 128 { 129 Mutex::Autolock lock(mBurstLock); 130#if 0 //TODO: enable burst mode later 131 if ( mBurst ) 132 { 133 `(CAMERA_MSG_BURST_IMAGE, JPEGPictureMemBase, mCallbackCookie); 134 } 135 else 136#endif 137 { 138 mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, picture, 0, NULL, mCallbackCookie); 139 } 140 } 141 142 exit: 143 144 if (picture) { 145 picture->release(picture); 146 } 147 148 if (mNotifierState == AppCallbackNotifier::NOTIFIER_STARTED) { 149 if (encoded_mem) { 150 encoded_mem->release(encoded_mem); 151 } 152 if (cookie2) { 153 delete (ExifElementsTable*) cookie2; 154 } 155 encoder = gEncoderQueue.valueFor(src); 156 if (encoder.get()) { 157 gEncoderQueue.removeItem(src); 158 encoder.clear(); 159 } 160 mFrameProvider->returnFrame(src, type); 161 } 162 163 LOG_FUNCTION_NAME_EXIT; 164} 165 166/** 167 * NotificationHandler class 168 */ 169 170///Initialization function for AppCallbackNotifier 171status_t AppCallbackNotifier::initialize() 172{ 173 LOG_FUNCTION_NAME; 174 175 mMeasurementEnabled = false; 176 177 ///Create the app notifier thread 178 mNotificationThread = new NotificationThread(this); 179 if(!mNotificationThread.get()) 180 { 181 CAMHAL_LOGEA("Couldn't create Notification thread"); 182 return NO_MEMORY; 183 } 184 185 ///Start the display thread 186 status_t ret = mNotificationThread->run("NotificationThread", PRIORITY_URGENT_DISPLAY); 187 if(ret!=NO_ERROR) 188 { 189 CAMHAL_LOGEA("Couldn't run NotificationThread"); 190 mNotificationThread.clear(); 191 return ret; 192 } 193 194 mUseMetaDataBufferMode = true; 195 mRawAvailable = false; 196 197 LOG_FUNCTION_NAME_EXIT; 198 199 return ret; 200} 201 202void AppCallbackNotifier::setCallbacks(CameraHal* cameraHal, 203 camera_notify_callback notify_cb, 204 camera_data_callback data_cb, 205 camera_data_timestamp_callback data_cb_timestamp, 206 camera_request_memory get_memory, 207 void *user) 208{ 209 Mutex::Autolock lock(mLock); 210 211 LOG_FUNCTION_NAME; 212 213 mCameraHal = cameraHal; 214 mNotifyCb = notify_cb; 215 mDataCb = data_cb; 216 mDataCbTimestamp = data_cb_timestamp; 217 mRequestMemory = get_memory; 218 mCallbackCookie = user; 219 220 LOG_FUNCTION_NAME_EXIT; 221} 222 223void AppCallbackNotifier::setMeasurements(bool enable) 224{ 225 Mutex::Autolock lock(mLock); 226 227 LOG_FUNCTION_NAME; 228 229 mMeasurementEnabled = enable; 230 231 if ( enable ) 232 { 233 mFrameProvider->enableFrameNotification(CameraFrame::FRAME_DATA_SYNC); 234 } 235 236 LOG_FUNCTION_NAME_EXIT; 237} 238 239 240//All sub-components of Camera HAL call this whenever any error happens 241void AppCallbackNotifier::errorNotify(int error) 242{ 243 LOG_FUNCTION_NAME; 244 245 CAMHAL_LOGEB("AppCallbackNotifier received error %d", error); 246 247 // If it is a fatal error abort here! 248 if((error == CAMERA_ERROR_FATAL) || (error == CAMERA_ERROR_HARD)) { 249 //We kill media server if we encounter these errors as there is 250 //no point continuing and apps also don't handle errors other 251 //than media server death always. 252 abort(); 253 return; 254 } 255 256 if ( ( NULL != mCameraHal ) && 257 ( NULL != mNotifyCb ) && 258 ( mCameraHal->msgTypeEnabled(CAMERA_MSG_ERROR) ) ) 259 { 260 CAMHAL_LOGEB("AppCallbackNotifier mNotifyCb %d", error); 261 mNotifyCb(CAMERA_MSG_ERROR, CAMERA_ERROR_UNKNOWN, 0, mCallbackCookie); 262 } 263 264 LOG_FUNCTION_NAME_EXIT; 265} 266 267bool AppCallbackNotifier::notificationThread() 268{ 269 bool shouldLive = true; 270 status_t ret; 271 272 LOG_FUNCTION_NAME; 273 274 //CAMHAL_LOGDA("Notification Thread waiting for message"); 275 ret = TIUTILS::MessageQueue::waitForMsg(&mNotificationThread->msgQ(), 276 &mEventQ, 277 &mFrameQ, 278 AppCallbackNotifier::NOTIFIER_TIMEOUT); 279 280 //CAMHAL_LOGDA("Notification Thread received message"); 281 282 if (mNotificationThread->msgQ().hasMsg()) { 283 ///Received a message from CameraHal, process it 284 CAMHAL_LOGDA("Notification Thread received message from Camera HAL"); 285 shouldLive = processMessage(); 286 if(!shouldLive) { 287 CAMHAL_LOGDA("Notification Thread exiting."); 288 return shouldLive; 289 } 290 } 291 292 if(mEventQ.hasMsg()) { 293 ///Received an event from one of the event providers 294 CAMHAL_LOGDA("Notification Thread received an event from event provider (CameraAdapter)"); 295 notifyEvent(); 296 } 297 298 if(mFrameQ.hasMsg()) { 299 ///Received a frame from one of the frame providers 300 //CAMHAL_LOGDA("Notification Thread received a frame from frame provider (CameraAdapter)"); 301 notifyFrame(); 302 } 303 304 LOG_FUNCTION_NAME_EXIT; 305 return shouldLive; 306} 307 308void AppCallbackNotifier::notifyEvent() 309{ 310 ///Receive and send the event notifications to app 311 TIUTILS::Message msg; 312 LOG_FUNCTION_NAME; 313 { 314 Mutex::Autolock lock(mLock); 315 if(!mEventQ.isEmpty()) { 316 mEventQ.get(&msg); 317 } else { 318 return; 319 } 320 } 321 bool ret = true; 322 CameraHalEvent *evt = NULL; 323 CameraHalEvent::FocusEventData *focusEvtData; 324 CameraHalEvent::ZoomEventData *zoomEvtData; 325 CameraHalEvent::FaceEventData faceEvtData; 326 327 if(mNotifierState != AppCallbackNotifier::NOTIFIER_STARTED) 328 { 329 return; 330 } 331 332 switch(msg.command) 333 { 334 case AppCallbackNotifier::NOTIFIER_CMD_PROCESS_EVENT: 335 336 evt = ( CameraHalEvent * ) msg.arg1; 337 338 if ( NULL == evt ) 339 { 340 CAMHAL_LOGEA("Invalid CameraHalEvent"); 341 return; 342 } 343 344 switch(evt->mEventType) 345 { 346 case CameraHalEvent::EVENT_SHUTTER: 347 348 if ( ( NULL != mCameraHal ) && 349 ( NULL != mNotifyCb ) && 350 ( mCameraHal->msgTypeEnabled(CAMERA_MSG_SHUTTER) ) ) 351 { 352 mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie); 353 } 354 mRawAvailable = false; 355 356 break; 357 358 case CameraHalEvent::EVENT_FOCUS_LOCKED: 359 case CameraHalEvent::EVENT_FOCUS_ERROR: 360 focusEvtData = &evt->mEventData->focusEvent; 361 if ( ( focusEvtData->focusStatus == CameraHalEvent::FOCUS_STATUS_SUCCESS ) && 362 ( NULL != mCameraHal ) && 363 ( NULL != mNotifyCb ) && 364 ( mCameraHal->msgTypeEnabled(CAMERA_MSG_FOCUS) ) ) 365 { 366 mCameraHal->disableMsgType(CAMERA_MSG_FOCUS); 367 mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie); 368 } 369 else if ( ( focusEvtData->focusStatus == CameraHalEvent::FOCUS_STATUS_FAIL ) && 370 ( NULL != mCameraHal ) && 371 ( NULL != mNotifyCb ) && 372 ( mCameraHal->msgTypeEnabled(CAMERA_MSG_FOCUS) ) ) 373 { 374 mCameraHal->disableMsgType(CAMERA_MSG_FOCUS); 375 mNotifyCb(CAMERA_MSG_FOCUS, false, 0, mCallbackCookie); 376 } 377 else if ( ( focusEvtData->focusStatus == CameraHalEvent::FOCUS_STATUS_PENDING ) && 378 ( NULL != mCameraHal ) && 379 ( NULL != mNotifyCb ) && 380 ( mCameraHal->msgTypeEnabled(CAMERA_MSG_FOCUS_MOVE) ) ) 381 { 382 mNotifyCb(CAMERA_MSG_FOCUS_MOVE, true, 0, mCallbackCookie); 383 } 384 else if ( ( focusEvtData->focusStatus == CameraHalEvent::FOCUS_STATUS_DONE ) && 385 ( NULL != mCameraHal ) && 386 ( NULL != mNotifyCb ) && 387 ( mCameraHal->msgTypeEnabled(CAMERA_MSG_FOCUS_MOVE) ) ) 388 { 389 mNotifyCb(CAMERA_MSG_FOCUS_MOVE, false, 0, mCallbackCookie); 390 } 391 392 break; 393 394 case CameraHalEvent::EVENT_ZOOM_INDEX_REACHED: 395 396 zoomEvtData = &evt->mEventData->zoomEvent; 397 398 if ( ( NULL != mCameraHal ) && 399 ( NULL != mNotifyCb) && 400 ( mCameraHal->msgTypeEnabled(CAMERA_MSG_ZOOM) ) ) 401 { 402 mNotifyCb(CAMERA_MSG_ZOOM, zoomEvtData->currentZoomIndex, zoomEvtData->targetZoomIndexReached, mCallbackCookie); 403 } 404 405 break; 406 407 case CameraHalEvent::EVENT_FACE: 408 409 faceEvtData = evt->mEventData->faceEvent; 410 411 if ( ( NULL != mCameraHal ) && 412 ( NULL != mNotifyCb) && 413 ( mCameraHal->msgTypeEnabled(CAMERA_MSG_PREVIEW_METADATA) ) ) 414 { 415 // WA for an issue inside CameraService 416 camera_memory_t *tmpBuffer = mRequestMemory(-1, 1, 1, NULL); 417 418 mDataCb(CAMERA_MSG_PREVIEW_METADATA, 419 tmpBuffer, 420 0, 421 faceEvtData->getFaceResult(), 422 mCallbackCookie); 423 424 faceEvtData.clear(); 425 426 if ( NULL != tmpBuffer ) { 427 tmpBuffer->release(tmpBuffer); 428 } 429 430 } 431 432 break; 433 434 case CameraHalEvent::ALL_EVENTS: 435 break; 436 default: 437 break; 438 } 439 440 break; 441 } 442 443 if ( NULL != evt ) 444 { 445 delete evt; 446 } 447 448 449 LOG_FUNCTION_NAME_EXIT; 450 451} 452 453static void alignYV12(int width, 454 int height, 455 int &yStride, 456 int &uvStride, 457 int &ySize, 458 int &uvSize, 459 int &size) 460{ 461 yStride = ( width + 0xF ) & ~0xF; 462 uvStride = ( yStride / 2 + 0xF ) & ~0xF; 463 ySize = yStride * height; 464 uvSize = uvStride * height / 2; 465 size = ySize + uvSize * 2; 466} 467 468static void copy2Dto1D(void *dst, 469 void *src, 470 int width, 471 int height, 472 size_t stride, 473 uint32_t offset, 474 unsigned int bytesPerPixel, 475 size_t length, 476 const char *pixelFormat) 477{ 478 unsigned int alignedRow, row; 479 unsigned char *bufferDst, *bufferSrc; 480 unsigned char *bufferDstEnd, *bufferSrcEnd; 481 uint16_t *bufferSrc_UV; 482 483 unsigned int *y_uv = (unsigned int *)src; 484 485 CAMHAL_LOGVB("copy2Dto1D() y= %p ; uv=%p.",y_uv[0], y_uv[1]); 486 CAMHAL_LOGVB("pixelFormat= %s; offset=%d", pixelFormat,offset); 487 488 if (pixelFormat!=NULL) { 489 if (strcmp(pixelFormat, CameraParameters::PIXEL_FORMAT_YUV422I) == 0) { 490 bytesPerPixel = 2; 491 bufferSrc = ( unsigned char * ) y_uv[0] + offset; 492 uint32_t xOff = offset % stride; 493 uint32_t yOff = offset / stride; 494 uint8_t *bufferSrcUV = ((uint8_t*)y_uv[1] + (stride/2)*yOff + xOff); 495 uint8_t *bufferSrcUVEven = bufferSrcUV; 496 497 uint8_t *bufferDstY = ( uint8_t * ) dst; 498 uint8_t *bufferDstU = bufferDstY + 1; 499 uint8_t *bufferDstV = bufferDstY + 3; 500 501 // going to convert from NV12 here and return 502 for ( int i = 0 ; i < height; i ++ ) { 503 for ( int j = 0 ; j < width / 2 ; j++ ) { 504 505 // Y 506 *bufferDstY = *bufferSrc; 507 bufferSrc++; 508 bufferDstY += 2; 509 510 *bufferDstY = *bufferSrc; 511 bufferSrc++; 512 bufferDstY += 2; 513 514 // V 515 *bufferDstV = *(bufferSrcUV + 1); 516 bufferDstV += 4; 517 518 // U 519 *bufferDstU = *bufferSrcUV; 520 bufferDstU += 4; 521 522 bufferSrcUV += 2; 523 } 524 if ( i % 2 ) { 525 bufferSrcUV += ( stride - width); 526 bufferSrcUVEven = bufferSrcUV; 527 } else { 528 bufferSrcUV = bufferSrcUVEven; 529 } 530 bufferSrc += ( stride - width); 531 } 532 533 return; 534 } else if (strcmp(pixelFormat, CameraParameters::PIXEL_FORMAT_YUV420SP) == 0 || 535 strcmp(pixelFormat, CameraParameters::PIXEL_FORMAT_YUV420P) == 0) { 536 bytesPerPixel = 1; 537 bufferDst = ( unsigned char * ) dst; 538 bufferDstEnd = ( unsigned char * ) dst + width*height*bytesPerPixel; 539 bufferSrc = ( unsigned char * ) y_uv[0] + offset; 540 bufferSrcEnd = ( unsigned char * ) ( ( size_t ) y_uv[0] + length + offset); 541 row = width*bytesPerPixel; 542 alignedRow = stride-width; 543 int stride_bytes = stride / 8; 544 uint32_t xOff = offset % stride; 545 uint32_t yOff = offset / stride; 546 547 // going to convert from NV12 here and return 548 // Step 1: Y plane: iterate through each row and copy 549 for ( int i = 0 ; i < height ; i++) { 550 memcpy(bufferDst, bufferSrc, row); 551 bufferSrc += stride; 552 bufferDst += row; 553 if ( ( bufferSrc > bufferSrcEnd ) || ( bufferDst > bufferDstEnd ) ) { 554 break; 555 } 556 } 557 558 bufferSrc_UV = ( uint16_t * ) ((uint8_t*)y_uv[1] + (stride/2)*yOff + xOff); 559 560 if (strcmp(pixelFormat, CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) { 561 uint16_t *bufferDst_UV; 562 563 // Step 2: UV plane: convert NV12 to NV21 by swapping U & V 564 bufferDst_UV = (uint16_t *) (((uint8_t*)dst)+row*height); 565 566 for (int i = 0 ; i < height/2 ; i++, bufferSrc_UV += alignedRow/2) { 567 int n = width; 568 asm volatile ( 569 " pld [%[src], %[src_stride], lsl #2] \n\t" 570 " cmp %[n], #32 \n\t" 571 " blt 1f \n\t" 572 "0: @ 32 byte swap \n\t" 573 " sub %[n], %[n], #32 \n\t" 574 " vld2.8 {q0, q1} , [%[src]]! \n\t" 575 " vswp q0, q1 \n\t" 576 " cmp %[n], #32 \n\t" 577 " vst2.8 {q0,q1},[%[dst]]! \n\t" 578 " bge 0b \n\t" 579 "1: @ Is there enough data? \n\t" 580 " cmp %[n], #16 \n\t" 581 " blt 3f \n\t" 582 "2: @ 16 byte swap \n\t" 583 " sub %[n], %[n], #16 \n\t" 584 " vld2.8 {d0, d1} , [%[src]]! \n\t" 585 " vswp d0, d1 \n\t" 586 " cmp %[n], #16 \n\t" 587 " vst2.8 {d0,d1},[%[dst]]! \n\t" 588 " bge 2b \n\t" 589 "3: @ Is there enough data? \n\t" 590 " cmp %[n], #8 \n\t" 591 " blt 5f \n\t" 592 "4: @ 8 byte swap \n\t" 593 " sub %[n], %[n], #8 \n\t" 594 " vld2.8 {d0, d1} , [%[src]]! \n\t" 595 " vswp d0, d1 \n\t" 596 " cmp %[n], #8 \n\t" 597 " vst2.8 {d0[0],d1[0]},[%[dst]]! \n\t" 598 " bge 4b \n\t" 599 "5: @ end \n\t" 600#ifdef NEEDS_ARM_ERRATA_754319_754320 601 " vmov s0,s0 @ add noop for errata item \n\t" 602#endif 603 : [dst] "+r" (bufferDst_UV), [src] "+r" (bufferSrc_UV), [n] "+r" (n) 604 : [src_stride] "r" (stride_bytes) 605 : "cc", "memory", "q0", "q1" 606 ); 607 } 608 } else if (strcmp(pixelFormat, CameraParameters::PIXEL_FORMAT_YUV420P) == 0) { 609 uint16_t *bufferDst_U; 610 uint16_t *bufferDst_V; 611 612 // Step 2: UV plane: convert NV12 to YV12 by de-interleaving U & V 613 // TODO(XXX): This version of CameraHal assumes NV12 format it set at 614 // camera adapter to support YV12. Need to address for 615 // USBCamera 616 617 int yStride, uvStride, ySize, uvSize, size; 618 alignYV12(width, height, yStride, uvStride, ySize, uvSize, size); 619 620 bufferDst_V = (uint16_t *) (((uint8_t*)dst) + ySize); 621 bufferDst_U = (uint16_t *) (((uint8_t*)dst) + ySize + uvSize); 622 int inc = (uvStride - width/2)/2; 623 624 for (int i = 0 ; i < height/2 ; i++, bufferSrc_UV += alignedRow/2) { 625 int n = width; 626 asm volatile ( 627 " pld [%[src], %[src_stride], lsl #2] \n\t" 628 " cmp %[n], #32 \n\t" 629 " blt 1f \n\t" 630 "0: @ 32 byte swap \n\t" 631 " sub %[n], %[n], #32 \n\t" 632 " vld2.8 {q0, q1} , [%[src]]! \n\t" 633 " cmp %[n], #32 \n\t" 634 " vst1.8 {q1},[%[dst_v]]! \n\t" 635 " vst1.8 {q0},[%[dst_u]]! \n\t" 636 " bge 0b \n\t" 637 "1: @ Is there enough data? \n\t" 638 " cmp %[n], #16 \n\t" 639 " blt 3f \n\t" 640 "2: @ 16 byte swap \n\t" 641 " sub %[n], %[n], #16 \n\t" 642 " vld2.8 {d0, d1} , [%[src]]! \n\t" 643 " cmp %[n], #16 \n\t" 644 " vst1.8 {d1},[%[dst_v]]! \n\t" 645 " vst1.8 {d0},[%[dst_u]]! \n\t" 646 " bge 2b \n\t" 647 "3: @ Is there enough data? \n\t" 648 " cmp %[n], #8 \n\t" 649 " blt 5f \n\t" 650 "4: @ 8 byte swap \n\t" 651 " sub %[n], %[n], #8 \n\t" 652 " vld2.8 {d0, d1} , [%[src]]! \n\t" 653 " cmp %[n], #8 \n\t" 654 " vst1.8 {d1[0]},[%[dst_v]]! \n\t" 655 " vst1.8 {d0[0]},[%[dst_u]]! \n\t" 656 " bge 4b \n\t" 657 "5: @ end \n\t" 658#ifdef NEEDS_ARM_ERRATA_754319_754320 659 " vmov s0,s0 @ add noop for errata item \n\t" 660#endif 661 : [dst_u] "+r" (bufferDst_U), [dst_v] "+r" (bufferDst_V), 662 [src] "+r" (bufferSrc_UV), [n] "+r" (n) 663 : [src_stride] "r" (stride_bytes) 664 : "cc", "memory", "q0", "q1" 665 ); 666 667 bufferDst_U += inc; 668 bufferDst_V += inc; 669 } 670 671 } 672 return ; 673 674 } else if(strcmp(pixelFormat, CameraParameters::PIXEL_FORMAT_RGB565) == 0) { 675 bytesPerPixel = 2; 676 } 677 } 678 679 bufferDst = ( unsigned char * ) dst; 680 bufferSrc = ( unsigned char * ) y_uv[0]; 681 row = width*bytesPerPixel; 682 alignedRow = ( row + ( stride -1 ) ) & ( ~ ( stride -1 ) ); 683 684 //iterate through each row 685 for ( int i = 0 ; i < height ; i++, bufferSrc += alignedRow, bufferDst += row) { 686 memcpy(bufferDst, bufferSrc, row); 687 } 688} 689 690void AppCallbackNotifier::copyAndSendPictureFrame(CameraFrame* frame, int32_t msgType) 691{ 692 camera_memory_t* picture = NULL; 693 void *dest = NULL, *src = NULL; 694 695 // scope for lock 696 { 697 Mutex::Autolock lock(mLock); 698 699 if(mNotifierState != AppCallbackNotifier::NOTIFIER_STARTED) { 700 goto exit; 701 } 702 703 picture = mRequestMemory(-1, frame->mLength, 1, NULL); 704 705 if (NULL != picture) { 706 dest = picture->data; 707 if (NULL != dest) { 708 src = (void *) ((unsigned int) frame->mBuffer + frame->mOffset); 709 memcpy(dest, src, frame->mLength); 710 } 711 } 712 } 713 714 exit: 715 mFrameProvider->returnFrame(frame->mBuffer, (CameraFrame::FrameType) frame->mFrameType); 716 717 if(picture) { 718 if((mNotifierState == AppCallbackNotifier::NOTIFIER_STARTED) && 719 mCameraHal->msgTypeEnabled(msgType)) { 720 mDataCb(msgType, picture, 0, NULL, mCallbackCookie); 721 } 722 picture->release(picture); 723 } 724} 725 726void AppCallbackNotifier::copyAndSendPreviewFrame(CameraFrame* frame, int32_t msgType) 727{ 728 camera_memory_t* picture = NULL; 729 void* dest = NULL; 730 731 // scope for lock 732 { 733 Mutex::Autolock lock(mLock); 734 735 if(mNotifierState != AppCallbackNotifier::NOTIFIER_STARTED) { 736 goto exit; 737 } 738 739 if (!mPreviewMemory || !frame->mBuffer) { 740 CAMHAL_LOGDA("Error! One of the buffer is NULL"); 741 goto exit; 742 } 743 744 745 dest = (void*) mPreviewBufs[mPreviewBufCount]; 746 747 CAMHAL_LOGVB("%d:copy2Dto1D(%p, %p, %d, %d, %d, %d, %d,%s)", 748 __LINE__, 749 buf, 750 frame->mBuffer, 751 frame->mWidth, 752 frame->mHeight, 753 frame->mAlignment, 754 2, 755 frame->mLength, 756 mPreviewPixelFormat); 757 758 if ( NULL != dest ) { 759 // data sync frames don't need conversion 760 if (CameraFrame::FRAME_DATA_SYNC == frame->mFrameType) { 761 if ( (mPreviewMemory->size / MAX_BUFFERS) >= frame->mLength ) { 762 memcpy(dest, (void*) frame->mBuffer, frame->mLength); 763 } else { 764 memset(dest, 0, (mPreviewMemory->size / MAX_BUFFERS)); 765 } 766 } else { 767 if ((NULL == frame->mYuv[0]) || (NULL == frame->mYuv[1])){ 768 CAMHAL_LOGEA("Error! One of the YUV Pointer is NULL"); 769 goto exit; 770 } 771 else{ 772 copy2Dto1D(dest, 773 frame->mYuv, 774 frame->mWidth, 775 frame->mHeight, 776 frame->mAlignment, 777 frame->mOffset, 778 2, 779 frame->mLength, 780 mPreviewPixelFormat); 781 } 782 } 783 } 784 } 785 786 exit: 787 mFrameProvider->returnFrame(frame->mBuffer, (CameraFrame::FrameType) frame->mFrameType); 788 789 if((mNotifierState == AppCallbackNotifier::NOTIFIER_STARTED) && 790 mCameraHal->msgTypeEnabled(msgType) && 791 (dest != NULL)) { 792 mDataCb(msgType, mPreviewMemory, mPreviewBufCount, NULL, mCallbackCookie); 793 } 794 795 // increment for next buffer 796 mPreviewBufCount = (mPreviewBufCount + 1) % AppCallbackNotifier::MAX_BUFFERS; 797} 798 799status_t AppCallbackNotifier::dummyRaw() 800{ 801 LOG_FUNCTION_NAME; 802 803 if ( NULL == mRequestMemory ) { 804 CAMHAL_LOGEA("Can't allocate memory for dummy raw callback!"); 805 return NO_INIT; 806 } 807 808 if ( ( NULL != mCameraHal ) && 809 ( NULL != mDataCb) && 810 ( NULL != mNotifyCb ) ){ 811 812 if ( mCameraHal->msgTypeEnabled(CAMERA_MSG_RAW_IMAGE) ) { 813 camera_memory_t *dummyRaw = mRequestMemory(-1, 1, 1, NULL); 814 815 if ( NULL == dummyRaw ) { 816 CAMHAL_LOGEA("Dummy raw buffer allocation failed!"); 817 return NO_MEMORY; 818 } 819 820 mDataCb(CAMERA_MSG_RAW_IMAGE, dummyRaw, 0, NULL, mCallbackCookie); 821 822 dummyRaw->release(dummyRaw); 823 } else if ( mCameraHal->msgTypeEnabled(CAMERA_MSG_RAW_IMAGE_NOTIFY) ) { 824 mNotifyCb(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, mCallbackCookie); 825 } 826 } 827 828 LOG_FUNCTION_NAME_EXIT; 829 830 return NO_ERROR; 831} 832 833void AppCallbackNotifier::notifyFrame() 834{ 835 ///Receive and send the frame notifications to app 836 TIUTILS::Message msg; 837 CameraFrame *frame; 838 MemoryHeapBase *heap; 839 MemoryBase *buffer = NULL; 840 sp<MemoryBase> memBase; 841 void *buf = NULL; 842 843 LOG_FUNCTION_NAME; 844 845 { 846 Mutex::Autolock lock(mLock); 847 if(!mFrameQ.isEmpty()) { 848 mFrameQ.get(&msg); 849 } else { 850 return; 851 } 852 } 853 854 bool ret = true; 855 856 frame = NULL; 857 switch(msg.command) 858 { 859 case AppCallbackNotifier::NOTIFIER_CMD_PROCESS_FRAME: 860 861 frame = (CameraFrame *) msg.arg1; 862 if(!frame) 863 { 864 break; 865 } 866 867 if ( (CameraFrame::RAW_FRAME == frame->mFrameType )&& 868 ( NULL != mCameraHal ) && 869 ( NULL != mDataCb) && 870 ( NULL != mNotifyCb ) ) 871 { 872 873 if ( mCameraHal->msgTypeEnabled(CAMERA_MSG_RAW_IMAGE) ) 874 { 875#ifdef COPY_IMAGE_BUFFER 876 copyAndSendPictureFrame(frame, CAMERA_MSG_RAW_IMAGE); 877#else 878 //TODO: Find a way to map a Tiler buffer to a MemoryHeapBase 879#endif 880 } 881 else { 882 if ( mCameraHal->msgTypeEnabled(CAMERA_MSG_RAW_IMAGE_NOTIFY) ) { 883 mNotifyCb(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, mCallbackCookie); 884 } 885 mFrameProvider->returnFrame(frame->mBuffer, 886 (CameraFrame::FrameType) frame->mFrameType); 887 } 888 889 mRawAvailable = true; 890 891 } 892 else if ( (CameraFrame::IMAGE_FRAME == frame->mFrameType) && 893 (NULL != mCameraHal) && 894 (NULL != mDataCb) && 895 (CameraFrame::ENCODE_RAW_YUV422I_TO_JPEG & frame->mQuirks) ) 896 { 897 898 int encode_quality = 100, tn_quality = 100; 899 int tn_width, tn_height; 900 unsigned int current_snapshot = 0; 901 Encoder_libjpeg::params *main_jpeg = NULL, *tn_jpeg = NULL; 902 void* exif_data = NULL; 903 camera_memory_t* raw_picture = mRequestMemory(-1, frame->mLength, 1, NULL); 904 905 if(raw_picture) { 906 buf = raw_picture->data; 907 } 908 909 CameraParameters parameters; 910 char *params = mCameraHal->getParameters(); 911 const String8 strParams(params); 912 parameters.unflatten(strParams); 913 914 encode_quality = parameters.getInt(CameraParameters::KEY_JPEG_QUALITY); 915 if (encode_quality < 0 || encode_quality > 100) { 916 encode_quality = 100; 917 } 918 919 tn_quality = parameters.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY); 920 if (tn_quality < 0 || tn_quality > 100) { 921 tn_quality = 100; 922 } 923 924 if (CameraFrame::HAS_EXIF_DATA & frame->mQuirks) { 925 exif_data = frame->mCookie2; 926 } 927 928 main_jpeg = (Encoder_libjpeg::params*) 929 malloc(sizeof(Encoder_libjpeg::params)); 930 931 // Video snapshot with LDCNSF on adds a few bytes start offset 932 // and a few bytes on every line. They must be skipped. 933 int rightCrop = frame->mAlignment/2 - frame->mWidth; 934 935 CAMHAL_LOGDB("Video snapshot right crop = %d", rightCrop); 936 CAMHAL_LOGDB("Video snapshot offset = %d", frame->mOffset); 937 938 if (main_jpeg) { 939 main_jpeg->src = (uint8_t*) frame->mBuffer; 940 main_jpeg->src_size = frame->mLength; 941 main_jpeg->dst = (uint8_t*) buf; 942 main_jpeg->dst_size = frame->mLength; 943 main_jpeg->quality = encode_quality; 944 main_jpeg->in_width = frame->mAlignment/2; // use stride here 945 main_jpeg->in_height = frame->mHeight; 946 main_jpeg->out_width = frame->mAlignment/2; 947 main_jpeg->out_height = frame->mHeight; 948 main_jpeg->right_crop = rightCrop; 949 main_jpeg->start_offset = frame->mOffset; 950 main_jpeg->format = CameraParameters::PIXEL_FORMAT_YUV422I; 951 } 952 953 tn_width = parameters.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH); 954 tn_height = parameters.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT); 955 956 if ((tn_width > 0) && (tn_height > 0)) { 957 tn_jpeg = (Encoder_libjpeg::params*) 958 malloc(sizeof(Encoder_libjpeg::params)); 959 // if malloc fails just keep going and encode main jpeg 960 if (!tn_jpeg) { 961 tn_jpeg = NULL; 962 } 963 } 964 965 if (tn_jpeg) { 966 int width, height; 967 parameters.getPreviewSize(&width,&height); 968 current_snapshot = (mPreviewBufCount + MAX_BUFFERS - 1) % MAX_BUFFERS; 969 tn_jpeg->src = (uint8_t*) mPreviewBufs[current_snapshot]; 970 tn_jpeg->src_size = mPreviewMemory->size / MAX_BUFFERS; 971 tn_jpeg->dst = (uint8_t*) malloc(tn_jpeg->src_size); 972 tn_jpeg->dst_size = tn_jpeg->src_size; 973 tn_jpeg->quality = tn_quality; 974 tn_jpeg->in_width = width; 975 tn_jpeg->in_height = height; 976 tn_jpeg->out_width = tn_width; 977 tn_jpeg->out_height = tn_height; 978 tn_jpeg->right_crop = 0; 979 tn_jpeg->start_offset = 0; 980 tn_jpeg->format = CameraParameters::PIXEL_FORMAT_YUV420SP;; 981 } 982 983 sp<Encoder_libjpeg> encoder = new Encoder_libjpeg(main_jpeg, 984 tn_jpeg, 985 AppCallbackNotifierEncoderCallback, 986 (CameraFrame::FrameType)frame->mFrameType, 987 this, 988 raw_picture, 989 exif_data); 990 encoder->run(); 991 gEncoderQueue.add(frame->mBuffer, encoder); 992 encoder.clear(); 993 if (params != NULL) 994 { 995 mCameraHal->putParameters(params); 996 } 997 } 998 else if ( ( CameraFrame::IMAGE_FRAME == frame->mFrameType ) && 999 ( NULL != mCameraHal ) && 1000 ( NULL != mDataCb) ) 1001 { 1002 1003 // CTS, MTS requirements: Every 'takePicture()' call 1004 // who registers a raw callback should receive one 1005 // as well. This is not always the case with 1006 // CameraAdapters though. 1007 if (!mRawAvailable) { 1008 dummyRaw(); 1009 } else { 1010 mRawAvailable = false; 1011 } 1012 1013#ifdef COPY_IMAGE_BUFFER 1014 { 1015 Mutex::Autolock lock(mBurstLock); 1016#if 0 //TODO: enable burst mode later 1017 if ( mBurst ) 1018 { 1019 `(CAMERA_MSG_BURST_IMAGE, JPEGPictureMemBase, mCallbackCookie); 1020 } 1021 else 1022#endif 1023 { 1024 copyAndSendPictureFrame(frame, CAMERA_MSG_COMPRESSED_IMAGE); 1025 } 1026 } 1027#else 1028 //TODO: Find a way to map a Tiler buffer to a MemoryHeapBase 1029#endif 1030 } 1031 else if ( ( CameraFrame::VIDEO_FRAME_SYNC == frame->mFrameType ) && 1032 ( NULL != mCameraHal ) && 1033 ( NULL != mDataCb) && 1034 ( mCameraHal->msgTypeEnabled(CAMERA_MSG_VIDEO_FRAME) ) ) 1035 { 1036 mRecordingLock.lock(); 1037 if(mRecording) 1038 { 1039 if(mUseMetaDataBufferMode) 1040 { 1041 camera_memory_t *videoMedatadaBufferMemory = 1042 (camera_memory_t *) mVideoMetadataBufferMemoryMap.valueFor((uint32_t) frame->mBuffer); 1043 video_metadata_t *videoMetadataBuffer = (video_metadata_t *) videoMedatadaBufferMemory->data; 1044 1045 if( (NULL == videoMedatadaBufferMemory) || (NULL == videoMetadataBuffer) || (NULL == frame->mBuffer) ) 1046 { 1047 CAMHAL_LOGEA("Error! One of the video buffers is NULL"); 1048 break; 1049 } 1050 1051 if ( mUseVideoBuffers ) 1052 { 1053 int vBuf = mVideoMap.valueFor((uint32_t) frame->mBuffer); 1054 GraphicBufferMapper &mapper = GraphicBufferMapper::get(); 1055 Rect bounds; 1056 bounds.left = 0; 1057 bounds.top = 0; 1058 bounds.right = mVideoWidth; 1059 bounds.bottom = mVideoHeight; 1060 1061 void *y_uv[2]; 1062 mapper.lock((buffer_handle_t)vBuf, CAMHAL_GRALLOC_USAGE, bounds, y_uv); 1063 1064 structConvImage input = {frame->mWidth, 1065 frame->mHeight, 1066 4096, 1067 IC_FORMAT_YCbCr420_lp, 1068 (mmByte *)frame->mYuv[0], 1069 (mmByte *)frame->mYuv[1], 1070 frame->mOffset}; 1071 1072 structConvImage output = {mVideoWidth, 1073 mVideoHeight, 1074 4096, 1075 IC_FORMAT_YCbCr420_lp, 1076 (mmByte *)y_uv[0], 1077 (mmByte *)y_uv[1], 1078 0}; 1079 1080 VT_resizeFrame_Video_opt2_lp(&input, &output, NULL, 0); 1081 mapper.unlock((buffer_handle_t)vBuf); 1082 videoMetadataBuffer->metadataBufferType = (int) kMetadataBufferTypeCameraSource; 1083 videoMetadataBuffer->handle = (void *)vBuf; 1084 videoMetadataBuffer->offset = 0; 1085 } 1086 else 1087 { 1088 videoMetadataBuffer->metadataBufferType = (int) kMetadataBufferTypeCameraSource; 1089 videoMetadataBuffer->handle = frame->mBuffer; 1090 videoMetadataBuffer->offset = frame->mOffset; 1091 } 1092 1093 CAMHAL_LOGVB("mDataCbTimestamp : frame->mBuffer=0x%x, videoMetadataBuffer=0x%x, videoMedatadaBufferMemory=0x%x", 1094 frame->mBuffer, videoMetadataBuffer, videoMedatadaBufferMemory); 1095 1096 mDataCbTimestamp(frame->mTimestamp, CAMERA_MSG_VIDEO_FRAME, 1097 videoMedatadaBufferMemory, 0, mCallbackCookie); 1098 } 1099 else 1100 { 1101 //TODO: Need to revisit this, should ideally be mapping the TILER buffer using mRequestMemory 1102 camera_memory_t* fakebuf = mRequestMemory(-1, 4, 1, NULL); 1103 if( (NULL == fakebuf) || ( NULL == fakebuf->data) || ( NULL == frame->mBuffer)) 1104 { 1105 CAMHAL_LOGEA("Error! One of the video buffers is NULL"); 1106 break; 1107 } 1108 1109 fakebuf->data = frame->mBuffer; 1110 mDataCbTimestamp(frame->mTimestamp, CAMERA_MSG_VIDEO_FRAME, fakebuf, 0, mCallbackCookie); 1111 fakebuf->release(fakebuf); 1112 } 1113 } 1114 mRecordingLock.unlock(); 1115 1116 } 1117 else if(( CameraFrame::SNAPSHOT_FRAME == frame->mFrameType ) && 1118 ( NULL != mCameraHal ) && 1119 ( NULL != mDataCb) && 1120 ( NULL != mNotifyCb)) { 1121 //When enabled, measurement data is sent instead of video data 1122 if ( !mMeasurementEnabled ) { 1123 copyAndSendPreviewFrame(frame, CAMERA_MSG_POSTVIEW_FRAME); 1124 } else { 1125 mFrameProvider->returnFrame(frame->mBuffer, 1126 (CameraFrame::FrameType) frame->mFrameType); 1127 } 1128 } 1129 else if ( ( CameraFrame::PREVIEW_FRAME_SYNC== frame->mFrameType ) && 1130 ( NULL != mCameraHal ) && 1131 ( NULL != mDataCb) && 1132 ( mCameraHal->msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME)) ) { 1133 //When enabled, measurement data is sent instead of video data 1134 if ( !mMeasurementEnabled ) { 1135 copyAndSendPreviewFrame(frame, CAMERA_MSG_PREVIEW_FRAME); 1136 } else { 1137 mFrameProvider->returnFrame(frame->mBuffer, 1138 (CameraFrame::FrameType) frame->mFrameType); 1139 } 1140 } 1141 else if ( ( CameraFrame::FRAME_DATA_SYNC == frame->mFrameType ) && 1142 ( NULL != mCameraHal ) && 1143 ( NULL != mDataCb) && 1144 ( mCameraHal->msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME)) ) { 1145 copyAndSendPreviewFrame(frame, CAMERA_MSG_PREVIEW_FRAME); 1146 } else { 1147 mFrameProvider->returnFrame(frame->mBuffer, 1148 ( CameraFrame::FrameType ) frame->mFrameType); 1149 CAMHAL_LOGDB("Frame type 0x%x is still unsupported!", frame->mFrameType); 1150 } 1151 1152 break; 1153 1154 default: 1155 1156 break; 1157 1158 }; 1159 1160exit: 1161 1162 if ( NULL != frame ) 1163 { 1164 delete frame; 1165 } 1166 1167 LOG_FUNCTION_NAME_EXIT; 1168} 1169 1170void AppCallbackNotifier::frameCallbackRelay(CameraFrame* caFrame) 1171{ 1172 LOG_FUNCTION_NAME; 1173 AppCallbackNotifier *appcbn = (AppCallbackNotifier*) (caFrame->mCookie); 1174 appcbn->frameCallback(caFrame); 1175 LOG_FUNCTION_NAME_EXIT; 1176} 1177 1178void AppCallbackNotifier::frameCallback(CameraFrame* caFrame) 1179{ 1180 ///Post the event to the event queue of AppCallbackNotifier 1181 TIUTILS::Message msg; 1182 CameraFrame *frame; 1183 1184 LOG_FUNCTION_NAME; 1185 1186 if ( NULL != caFrame ) 1187 { 1188 1189 frame = new CameraFrame(*caFrame); 1190 if ( NULL != frame ) 1191 { 1192 msg.command = AppCallbackNotifier::NOTIFIER_CMD_PROCESS_FRAME; 1193 msg.arg1 = frame; 1194 mFrameQ.put(&msg); 1195 } 1196 else 1197 { 1198 CAMHAL_LOGEA("Not enough resources to allocate CameraFrame"); 1199 } 1200 1201 } 1202 1203 LOG_FUNCTION_NAME_EXIT; 1204} 1205 1206void AppCallbackNotifier::flushAndReturnFrames() 1207{ 1208 TIUTILS::Message msg; 1209 CameraFrame *frame; 1210 1211 Mutex::Autolock lock(mLock); 1212 while (!mFrameQ.isEmpty()) { 1213 mFrameQ.get(&msg); 1214 frame = (CameraFrame*) msg.arg1; 1215 if (frame) { 1216 mFrameProvider->returnFrame(frame->mBuffer, 1217 (CameraFrame::FrameType) frame->mFrameType); 1218 } 1219 } 1220 1221 LOG_FUNCTION_NAME_EXIT; 1222} 1223 1224void AppCallbackNotifier::eventCallbackRelay(CameraHalEvent* chEvt) 1225{ 1226 LOG_FUNCTION_NAME; 1227 AppCallbackNotifier *appcbn = (AppCallbackNotifier*) (chEvt->mCookie); 1228 appcbn->eventCallback(chEvt); 1229 LOG_FUNCTION_NAME_EXIT; 1230} 1231 1232void AppCallbackNotifier::eventCallback(CameraHalEvent* chEvt) 1233{ 1234 1235 ///Post the event to the event queue of AppCallbackNotifier 1236 TIUTILS::Message msg; 1237 CameraHalEvent *event; 1238 1239 1240 LOG_FUNCTION_NAME; 1241 1242 if ( NULL != chEvt ) 1243 { 1244 1245 event = new CameraHalEvent(*chEvt); 1246 if ( NULL != event ) 1247 { 1248 msg.command = AppCallbackNotifier::NOTIFIER_CMD_PROCESS_EVENT; 1249 msg.arg1 = event; 1250 { 1251 Mutex::Autolock lock(mLock); 1252 mEventQ.put(&msg); 1253 } 1254 } 1255 else 1256 { 1257 CAMHAL_LOGEA("Not enough resources to allocate CameraHalEvent"); 1258 } 1259 1260 } 1261 1262 LOG_FUNCTION_NAME_EXIT; 1263} 1264 1265 1266void AppCallbackNotifier::flushEventQueue() 1267{ 1268 1269 { 1270 Mutex::Autolock lock(mLock); 1271 mEventQ.clear(); 1272 } 1273} 1274 1275 1276bool AppCallbackNotifier::processMessage() 1277{ 1278 ///Retrieve the command from the command queue and process it 1279 TIUTILS::Message msg; 1280 1281 LOG_FUNCTION_NAME; 1282 1283 CAMHAL_LOGDA("+Msg get..."); 1284 mNotificationThread->msgQ().get(&msg); 1285 CAMHAL_LOGDA("-Msg get..."); 1286 bool ret = true; 1287 1288 switch(msg.command) 1289 { 1290 case NotificationThread::NOTIFIER_EXIT: 1291 { 1292 CAMHAL_LOGDA("Received NOTIFIER_EXIT command from Camera HAL"); 1293 mNotifierState = AppCallbackNotifier::NOTIFIER_EXITED; 1294 ret = false; 1295 break; 1296 } 1297 default: 1298 { 1299 CAMHAL_LOGEA("Error: ProcessMsg() command from Camera HAL"); 1300 break; 1301 } 1302 } 1303 1304 LOG_FUNCTION_NAME_EXIT; 1305 1306 return ret; 1307 1308 1309} 1310 1311AppCallbackNotifier::~AppCallbackNotifier() 1312{ 1313 LOG_FUNCTION_NAME; 1314 1315 ///Stop app callback notifier if not already stopped 1316 stop(); 1317 1318 ///Unregister with the frame provider 1319 if ( NULL != mFrameProvider ) 1320 { 1321 mFrameProvider->disableFrameNotification(CameraFrame::ALL_FRAMES); 1322 } 1323 1324 //unregister with the event provider 1325 if ( NULL != mEventProvider ) 1326 { 1327 mEventProvider->disableEventNotification(CameraHalEvent::ALL_EVENTS); 1328 } 1329 1330 TIUTILS::Message msg = {0,0,0,0,0,0}; 1331 msg.command = NotificationThread::NOTIFIER_EXIT; 1332 1333 ///Post the message to display thread 1334 mNotificationThread->msgQ().put(&msg); 1335 1336 //Exit and cleanup the thread 1337 mNotificationThread->requestExit(); 1338 mNotificationThread->join(); 1339 1340 //Delete the display thread 1341 mNotificationThread.clear(); 1342 1343 1344 ///Free the event and frame providers 1345 if ( NULL != mEventProvider ) 1346 { 1347 ///Deleting the event provider 1348 CAMHAL_LOGDA("Stopping Event Provider"); 1349 delete mEventProvider; 1350 mEventProvider = NULL; 1351 } 1352 1353 if ( NULL != mFrameProvider ) 1354 { 1355 ///Deleting the frame provider 1356 CAMHAL_LOGDA("Stopping Frame Provider"); 1357 delete mFrameProvider; 1358 mFrameProvider = NULL; 1359 } 1360 1361 releaseSharedVideoBuffers(); 1362 1363 LOG_FUNCTION_NAME_EXIT; 1364} 1365 1366//Free all video heaps and buffers 1367void AppCallbackNotifier::releaseSharedVideoBuffers() 1368{ 1369 LOG_FUNCTION_NAME; 1370 1371 if(mUseMetaDataBufferMode) 1372 { 1373 camera_memory_t* videoMedatadaBufferMemory; 1374 for (unsigned int i = 0; i < mVideoMetadataBufferMemoryMap.size(); i++) 1375 { 1376 videoMedatadaBufferMemory = (camera_memory_t*) mVideoMetadataBufferMemoryMap.valueAt(i); 1377 if(NULL != videoMedatadaBufferMemory) 1378 { 1379 videoMedatadaBufferMemory->release(videoMedatadaBufferMemory); 1380 CAMHAL_LOGDB("Released videoMedatadaBufferMemory=0x%x", videoMedatadaBufferMemory); 1381 } 1382 } 1383 1384 mVideoMetadataBufferMemoryMap.clear(); 1385 mVideoMetadataBufferReverseMap.clear(); 1386 if (mUseVideoBuffers) 1387 { 1388 mVideoMap.clear(); 1389 } 1390 } 1391 1392 LOG_FUNCTION_NAME_EXIT; 1393} 1394 1395void AppCallbackNotifier::setEventProvider(int32_t eventMask, MessageNotifier * eventNotifier) 1396{ 1397 1398 LOG_FUNCTION_NAME; 1399 ///@remarks There is no NULL check here. We will check 1400 ///for NULL when we get start command from CameraHal 1401 ///@Remarks Currently only one event provider (CameraAdapter) is supported 1402 ///@todo Have an array of event providers for each event bitmask 1403 mEventProvider = new EventProvider(eventNotifier, this, eventCallbackRelay); 1404 if ( NULL == mEventProvider ) 1405 { 1406 CAMHAL_LOGEA("Error in creating EventProvider"); 1407 } 1408 else 1409 { 1410 mEventProvider->enableEventNotification(eventMask); 1411 } 1412 1413 LOG_FUNCTION_NAME_EXIT; 1414} 1415 1416void AppCallbackNotifier::setFrameProvider(FrameNotifier *frameNotifier) 1417{ 1418 LOG_FUNCTION_NAME; 1419 ///@remarks There is no NULL check here. We will check 1420 ///for NULL when we get the start command from CameraAdapter 1421 mFrameProvider = new FrameProvider(frameNotifier, this, frameCallbackRelay); 1422 if ( NULL == mFrameProvider ) 1423 { 1424 CAMHAL_LOGEA("Error in creating FrameProvider"); 1425 } 1426 else 1427 { 1428 //Register only for captured images and RAW for now 1429 //TODO: Register for and handle all types of frames 1430 mFrameProvider->enableFrameNotification(CameraFrame::IMAGE_FRAME); 1431 mFrameProvider->enableFrameNotification(CameraFrame::RAW_FRAME); 1432 } 1433 1434 LOG_FUNCTION_NAME_EXIT; 1435} 1436 1437status_t AppCallbackNotifier::startPreviewCallbacks(CameraParameters ¶ms, void *buffers, uint32_t *offsets, int fd, size_t length, size_t count) 1438{ 1439 sp<MemoryHeapBase> heap; 1440 sp<MemoryBase> buffer; 1441 unsigned int *bufArr; 1442 int size = 0; 1443 1444 LOG_FUNCTION_NAME; 1445 1446 Mutex::Autolock lock(mLock); 1447 1448 if ( NULL == mFrameProvider ) 1449 { 1450 CAMHAL_LOGEA("Trying to start video recording without FrameProvider"); 1451 return -EINVAL; 1452 } 1453 1454 if ( mPreviewing ) 1455 { 1456 CAMHAL_LOGDA("+Already previewing"); 1457 return NO_INIT; 1458 } 1459 1460 int w,h; 1461 ///Get preview size 1462 params.getPreviewSize(&w, &h); 1463 1464 //Get the preview pixel format 1465 mPreviewPixelFormat = params.getPreviewFormat(); 1466 1467 if(strcmp(mPreviewPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_YUV422I) == 0) 1468 { 1469 size = w*h*2; 1470 mPreviewPixelFormat = CameraParameters::PIXEL_FORMAT_YUV422I; 1471 } 1472 else if(strcmp(mPreviewPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_YUV420SP) == 0 ) 1473 { 1474 size = (w*h*3)/2; 1475 mPreviewPixelFormat = CameraParameters::PIXEL_FORMAT_YUV420SP; 1476 } 1477 else if(strcmp(mPreviewPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_RGB565) == 0) 1478 { 1479 size = w*h*2; 1480 mPreviewPixelFormat = CameraParameters::PIXEL_FORMAT_RGB565; 1481 } 1482 else if(strcmp(mPreviewPixelFormat, (const char *) CameraParameters::PIXEL_FORMAT_YUV420P) == 0) 1483 { 1484 int yStride, uvStride, ySize, uvSize; 1485 alignYV12(w, h, yStride, uvStride, ySize, uvSize, size); 1486 mPreviewPixelFormat = CameraParameters::PIXEL_FORMAT_YUV420P; 1487 } 1488 1489 mPreviewMemory = mRequestMemory(-1, size, AppCallbackNotifier::MAX_BUFFERS, NULL); 1490 if (!mPreviewMemory) { 1491 return NO_MEMORY; 1492 } 1493 1494 for (int i=0; i < AppCallbackNotifier::MAX_BUFFERS; i++) { 1495 mPreviewBufs[i] = (unsigned char*) mPreviewMemory->data + (i*size); 1496 } 1497 1498 if ( mCameraHal->msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME ) ) { 1499 mFrameProvider->enableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC); 1500 } 1501 1502 mPreviewBufCount = 0; 1503 1504 mPreviewing = true; 1505 1506 LOG_FUNCTION_NAME; 1507 1508 return NO_ERROR; 1509} 1510 1511void AppCallbackNotifier::setBurst(bool burst) 1512{ 1513 LOG_FUNCTION_NAME; 1514 1515 Mutex::Autolock lock(mBurstLock); 1516 1517 mBurst = burst; 1518 1519 LOG_FUNCTION_NAME_EXIT; 1520} 1521 1522void AppCallbackNotifier::useVideoBuffers(bool useVideoBuffers) 1523{ 1524 LOG_FUNCTION_NAME; 1525 1526 mUseVideoBuffers = useVideoBuffers; 1527 1528 LOG_FUNCTION_NAME_EXIT; 1529} 1530 1531bool AppCallbackNotifier::getUesVideoBuffers() 1532{ 1533 return mUseVideoBuffers; 1534} 1535 1536void AppCallbackNotifier::setVideoRes(int width, int height) 1537{ 1538 LOG_FUNCTION_NAME; 1539 1540 mVideoWidth = width; 1541 mVideoHeight = height; 1542 1543 LOG_FUNCTION_NAME_EXIT; 1544} 1545 1546status_t AppCallbackNotifier::stopPreviewCallbacks() 1547{ 1548 sp<MemoryHeapBase> heap; 1549 sp<MemoryBase> buffer; 1550 1551 LOG_FUNCTION_NAME; 1552 1553 if ( NULL == mFrameProvider ) 1554 { 1555 CAMHAL_LOGEA("Trying to stop preview callbacks without FrameProvider"); 1556 return -EINVAL; 1557 } 1558 1559 if ( !mPreviewing ) 1560 { 1561 return NO_INIT; 1562 } 1563 1564 mFrameProvider->disableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC); 1565 1566 { 1567 Mutex::Autolock lock(mLock); 1568 mPreviewMemory->release(mPreviewMemory); 1569 } 1570 1571 mPreviewing = false; 1572 1573 LOG_FUNCTION_NAME_EXIT; 1574 1575 return NO_ERROR; 1576 1577} 1578 1579status_t AppCallbackNotifier::useMetaDataBufferMode(bool enable) 1580{ 1581 mUseMetaDataBufferMode = enable; 1582 1583 return NO_ERROR; 1584} 1585 1586 1587status_t AppCallbackNotifier::startRecording() 1588{ 1589 status_t ret = NO_ERROR; 1590 1591 LOG_FUNCTION_NAME; 1592 1593 Mutex::Autolock lock(mRecordingLock); 1594 1595 if ( NULL == mFrameProvider ) 1596 { 1597 CAMHAL_LOGEA("Trying to start video recording without FrameProvider"); 1598 ret = -1; 1599 } 1600 1601 if(mRecording) 1602 { 1603 return NO_INIT; 1604 } 1605 1606 if ( NO_ERROR == ret ) 1607 { 1608 mFrameProvider->enableFrameNotification(CameraFrame::VIDEO_FRAME_SYNC); 1609 } 1610 1611 mRecording = true; 1612 1613 LOG_FUNCTION_NAME_EXIT; 1614 1615 return ret; 1616} 1617 1618//Allocate metadata buffers for video recording 1619status_t AppCallbackNotifier::initSharedVideoBuffers(void *buffers, uint32_t *offsets, int fd, size_t length, size_t count, void *vidBufs) 1620{ 1621 status_t ret = NO_ERROR; 1622 LOG_FUNCTION_NAME; 1623 1624 if(mUseMetaDataBufferMode) 1625 { 1626 uint32_t *bufArr = NULL; 1627 camera_memory_t* videoMedatadaBufferMemory = NULL; 1628 1629 if(NULL == buffers) 1630 { 1631 CAMHAL_LOGEA("Error! Video buffers are NULL"); 1632 return BAD_VALUE; 1633 } 1634 bufArr = (uint32_t *) buffers; 1635 1636 for (uint32_t i = 0; i < count; i++) 1637 { 1638 videoMedatadaBufferMemory = mRequestMemory(-1, sizeof(video_metadata_t), 1, NULL); 1639 if((NULL == videoMedatadaBufferMemory) || (NULL == videoMedatadaBufferMemory->data)) 1640 { 1641 CAMHAL_LOGEA("Error! Could not allocate memory for Video Metadata Buffers"); 1642 return NO_MEMORY; 1643 } 1644 1645 mVideoMetadataBufferMemoryMap.add(bufArr[i], (uint32_t)(videoMedatadaBufferMemory)); 1646 mVideoMetadataBufferReverseMap.add((uint32_t)(videoMedatadaBufferMemory->data), bufArr[i]); 1647 CAMHAL_LOGDB("bufArr[%d]=0x%x, videoMedatadaBufferMemory=0x%x, videoMedatadaBufferMemory->data=0x%x", 1648 i, bufArr[i], videoMedatadaBufferMemory, videoMedatadaBufferMemory->data); 1649 1650 if (vidBufs != NULL) 1651 { 1652 uint32_t *vBufArr = (uint32_t *) vidBufs; 1653 mVideoMap.add(bufArr[i], vBufArr[i]); 1654 CAMHAL_LOGVB("bufArr[%d]=0x%x, vBuffArr[%d]=0x%x", i, bufArr[i], i, vBufArr[i]); 1655 } 1656 } 1657 } 1658 1659exit: 1660 LOG_FUNCTION_NAME_EXIT; 1661 1662 return ret; 1663} 1664 1665status_t AppCallbackNotifier::stopRecording() 1666{ 1667 status_t ret = NO_ERROR; 1668 1669 LOG_FUNCTION_NAME; 1670 1671 Mutex::Autolock lock(mRecordingLock); 1672 1673 if ( NULL == mFrameProvider ) 1674 { 1675 CAMHAL_LOGEA("Trying to stop video recording without FrameProvider"); 1676 ret = -1; 1677 } 1678 1679 if(!mRecording) 1680 { 1681 return NO_INIT; 1682 } 1683 1684 if ( NO_ERROR == ret ) 1685 { 1686 mFrameProvider->disableFrameNotification(CameraFrame::VIDEO_FRAME_SYNC); 1687 } 1688 1689 ///Release the shared video buffers 1690 releaseSharedVideoBuffers(); 1691 1692 mRecording = false; 1693 1694 LOG_FUNCTION_NAME_EXIT; 1695 1696 return ret; 1697} 1698 1699status_t AppCallbackNotifier::releaseRecordingFrame(const void* mem) 1700{ 1701 status_t ret = NO_ERROR; 1702 void *frame = NULL; 1703 1704 LOG_FUNCTION_NAME; 1705 if ( NULL == mFrameProvider ) 1706 { 1707 CAMHAL_LOGEA("Trying to stop video recording without FrameProvider"); 1708 ret = -1; 1709 } 1710 1711 if ( NULL == mem ) 1712 { 1713 CAMHAL_LOGEA("Video Frame released is invalid"); 1714 ret = -1; 1715 } 1716 1717 if( NO_ERROR != ret ) 1718 { 1719 return ret; 1720 } 1721 1722 if(mUseMetaDataBufferMode) 1723 { 1724 video_metadata_t *videoMetadataBuffer = (video_metadata_t *) mem ; 1725 frame = (void*) mVideoMetadataBufferReverseMap.valueFor((uint32_t) videoMetadataBuffer); 1726 CAMHAL_LOGVB("Releasing frame with videoMetadataBuffer=0x%x, videoMetadataBuffer->handle=0x%x & frame handle=0x%x\n", 1727 videoMetadataBuffer, videoMetadataBuffer->handle, frame); 1728 } 1729 else 1730 { 1731 frame = (void*)(*((uint32_t *)mem)); 1732 } 1733 1734 if ( NO_ERROR == ret ) 1735 { 1736 ret = mFrameProvider->returnFrame(frame, CameraFrame::VIDEO_FRAME_SYNC); 1737 } 1738 1739 LOG_FUNCTION_NAME_EXIT; 1740 1741 return ret; 1742} 1743 1744status_t AppCallbackNotifier::enableMsgType(int32_t msgType) 1745{ 1746 if( msgType & (CAMERA_MSG_POSTVIEW_FRAME | CAMERA_MSG_PREVIEW_FRAME) ) { 1747 mFrameProvider->enableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC); 1748 } 1749 1750 return NO_ERROR; 1751} 1752 1753status_t AppCallbackNotifier::disableMsgType(int32_t msgType) 1754{ 1755 if( msgType & (CAMERA_MSG_PREVIEW_FRAME | CAMERA_MSG_POSTVIEW_FRAME) ) { 1756 mFrameProvider->disableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC); 1757 } 1758 1759 return NO_ERROR; 1760 1761} 1762 1763status_t AppCallbackNotifier::start() 1764{ 1765 LOG_FUNCTION_NAME; 1766 if(mNotifierState==AppCallbackNotifier::NOTIFIER_STARTED) 1767 { 1768 CAMHAL_LOGDA("AppCallbackNotifier already running"); 1769 LOG_FUNCTION_NAME_EXIT; 1770 return ALREADY_EXISTS; 1771 } 1772 1773 ///Check whether initial conditions are met for us to start 1774 ///A frame provider should be available, if not return error 1775 if(!mFrameProvider) 1776 { 1777 ///AppCallbackNotifier not properly initialized 1778 CAMHAL_LOGEA("AppCallbackNotifier not properly initialized - Frame provider is NULL"); 1779 LOG_FUNCTION_NAME_EXIT; 1780 return NO_INIT; 1781 } 1782 1783 ///At least one event notifier should be available, if not return error 1784 ///@todo Modify here when there is an array of event providers 1785 if(!mEventProvider) 1786 { 1787 CAMHAL_LOGEA("AppCallbackNotifier not properly initialized - Event provider is NULL"); 1788 LOG_FUNCTION_NAME_EXIT; 1789 ///AppCallbackNotifier not properly initialized 1790 return NO_INIT; 1791 } 1792 1793 mNotifierState = AppCallbackNotifier::NOTIFIER_STARTED; 1794 CAMHAL_LOGDA(" --> AppCallbackNotifier NOTIFIER_STARTED \n"); 1795 1796 gEncoderQueue.clear(); 1797 1798 LOG_FUNCTION_NAME_EXIT; 1799 1800 return NO_ERROR; 1801 1802} 1803 1804status_t AppCallbackNotifier::stop() 1805{ 1806 LOG_FUNCTION_NAME; 1807 1808 if(mNotifierState!=AppCallbackNotifier::NOTIFIER_STARTED) 1809 { 1810 CAMHAL_LOGDA("AppCallbackNotifier already in stopped state"); 1811 LOG_FUNCTION_NAME_EXIT; 1812 return ALREADY_EXISTS; 1813 } 1814 { 1815 Mutex::Autolock lock(mLock); 1816 1817 mNotifierState = AppCallbackNotifier::NOTIFIER_STOPPED; 1818 CAMHAL_LOGDA(" --> AppCallbackNotifier NOTIFIER_STOPPED \n"); 1819 } 1820 1821 while(!gEncoderQueue.isEmpty()) { 1822 sp<Encoder_libjpeg> encoder = gEncoderQueue.valueAt(0); 1823 camera_memory_t* encoded_mem = NULL; 1824 ExifElementsTable* exif = NULL; 1825 1826 if(encoder.get()) { 1827 encoder->cancel(); 1828 1829 encoder->getCookies(NULL, (void**) &encoded_mem, (void**) &exif); 1830 if (encoded_mem) { 1831 encoded_mem->release(encoded_mem); 1832 } 1833 if (exif) { 1834 delete exif; 1835 } 1836 1837 encoder.clear(); 1838 } 1839 gEncoderQueue.removeItemsAt(0); 1840 } 1841 1842 LOG_FUNCTION_NAME_EXIT; 1843 return NO_ERROR; 1844} 1845 1846 1847/*--------------------NotificationHandler Class ENDS here-----------------------------*/ 1848 1849 1850 1851}; 1852