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