CameraSource.cpp revision f96c9d193c70c7216b34e6c65f046a09a2a81f14
1/* 2 * Copyright (C) 2009 The Android Open Source Project 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//#define LOG_NDEBUG 0 18#define LOG_TAG "CameraSource" 19#include <utils/Log.h> 20 21#include <OMX_Component.h> 22#include <binder/IPCThreadState.h> 23#include <media/stagefright/CameraSource.h> 24#include <media/stagefright/MediaDebug.h> 25#include <media/stagefright/MediaDefs.h> 26#include <media/stagefright/MediaErrors.h> 27#include <media/stagefright/MetaData.h> 28#include <camera/Camera.h> 29#include <camera/CameraParameters.h> 30#include <surfaceflinger/Surface.h> 31#include <utils/String8.h> 32#include <cutils/properties.h> 33 34namespace android { 35 36struct CameraSourceListener : public CameraListener { 37 CameraSourceListener(const sp<CameraSource> &source); 38 39 virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2); 40 virtual void postData(int32_t msgType, const sp<IMemory> &dataPtr); 41 42 virtual void postDataTimestamp( 43 nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr); 44 45protected: 46 virtual ~CameraSourceListener(); 47 48private: 49 wp<CameraSource> mSource; 50 51 CameraSourceListener(const CameraSourceListener &); 52 CameraSourceListener &operator=(const CameraSourceListener &); 53}; 54 55CameraSourceListener::CameraSourceListener(const sp<CameraSource> &source) 56 : mSource(source) { 57} 58 59CameraSourceListener::~CameraSourceListener() { 60} 61 62void CameraSourceListener::notify(int32_t msgType, int32_t ext1, int32_t ext2) { 63 LOGV("notify(%d, %d, %d)", msgType, ext1, ext2); 64} 65 66void CameraSourceListener::postData(int32_t msgType, const sp<IMemory> &dataPtr) { 67 LOGV("postData(%d, ptr:%p, size:%d)", 68 msgType, dataPtr->pointer(), dataPtr->size()); 69 70 sp<CameraSource> source = mSource.promote(); 71 if (source.get() != NULL) { 72 source->dataCallback(msgType, dataPtr); 73 } 74} 75 76void CameraSourceListener::postDataTimestamp( 77 nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) { 78 79 sp<CameraSource> source = mSource.promote(); 80 if (source.get() != NULL) { 81 source->dataCallbackTimestamp(timestamp/1000, msgType, dataPtr); 82 } 83} 84 85static int32_t getColorFormat(const char* colorFormat) { 86 if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420P)) { 87 return OMX_COLOR_FormatYUV420Planar; 88 } 89 90 if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422SP)) { 91 return OMX_COLOR_FormatYUV422SemiPlanar; 92 } 93 94 if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420SP)) { 95 return OMX_COLOR_FormatYUV420SemiPlanar; 96 } 97 98 if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422I)) { 99 return OMX_COLOR_FormatYCbYCr; 100 } 101 102 if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_RGB565)) { 103 return OMX_COLOR_Format16bitRGB565; 104 } 105 106 LOGE("Uknown color format (%s), please add it to " 107 "CameraSource::getColorFormat", colorFormat); 108 109 CHECK_EQ(0, "Unknown color format"); 110} 111 112CameraSource *CameraSource::Create() { 113 Size size; 114 size.width = -1; 115 size.height = -1; 116 117 sp<ICamera> camera; 118 return new CameraSource(camera, 0, size, -1, NULL, false); 119} 120 121// static 122CameraSource *CameraSource::CreateFromCamera( 123 const sp<ICamera>& camera, 124 int32_t cameraId, 125 Size videoSize, 126 int32_t frameRate, 127 const sp<Surface>& surface, 128 bool storeMetaDataInVideoBuffers) { 129 130 CameraSource *source = new CameraSource(camera, cameraId, 131 videoSize, frameRate, surface, 132 storeMetaDataInVideoBuffers); 133 134 if (source != NULL) { 135 if (source->initCheck() != OK) { 136 delete source; 137 return NULL; 138 } 139 } 140 return source; 141} 142 143CameraSource::CameraSource( 144 const sp<ICamera>& camera, 145 int32_t cameraId, 146 Size videoSize, 147 int32_t frameRate, 148 const sp<Surface>& surface, 149 bool storeMetaDataInVideoBuffers) 150 : mCameraFlags(0), 151 mVideoFrameRate(-1), 152 mCamera(0), 153 mSurface(surface), 154 mNumFramesReceived(0), 155 mLastFrameTimestampUs(0), 156 mStarted(false), 157 mFirstFrameTimeUs(0), 158 mNumFramesEncoded(0), 159 mNumFramesDropped(0), 160 mNumGlitches(0), 161 mGlitchDurationThresholdUs(200000), 162 mCollectStats(false) { 163 164 mVideoSize.width = -1; 165 mVideoSize.height = -1; 166 167 mInitCheck = init(camera, cameraId, 168 videoSize, frameRate, 169 storeMetaDataInVideoBuffers); 170} 171 172status_t CameraSource::initCheck() const { 173 return mInitCheck; 174} 175 176status_t CameraSource::isCameraAvailable( 177 const sp<ICamera>& camera, int32_t cameraId) { 178 179 if (camera == 0) { 180 mCamera = Camera::connect(cameraId); 181 mCameraFlags &= ~FLAGS_HOT_CAMERA; 182 } else { 183 mCamera = Camera::create(camera); 184 mCameraFlags |= FLAGS_HOT_CAMERA; 185 } 186 187 // Is camera available? 188 if (mCamera == 0) { 189 LOGE("Camera connection could not be established."); 190 return -EBUSY; 191 } 192 if (!(mCameraFlags & FLAGS_HOT_CAMERA)) { 193 mCamera->lock(); 194 } 195 return OK; 196} 197 198 199/* 200 * Check to see whether the requested video width and height is one 201 * of the supported sizes. 202 * @param width the video frame width in pixels 203 * @param height the video frame height in pixels 204 * @param suppportedSizes the vector of sizes that we check against 205 * @return true if the dimension (width and height) is supported. 206 */ 207static bool isVideoSizeSupported( 208 int32_t width, int32_t height, 209 const Vector<Size>& supportedSizes) { 210 211 LOGV("isVideoSizeSupported"); 212 for (size_t i = 0; i < supportedSizes.size(); ++i) { 213 if (width == supportedSizes[i].width && 214 height == supportedSizes[i].height) { 215 return true; 216 } 217 } 218 return false; 219} 220 221/* 222 * If the preview and video output is separate, we only set the 223 * the video size, and applications should set the preview size 224 * to some proper value, and the recording framework will not 225 * change the preview size; otherwise, if the video and preview 226 * output is the same, we need to set the preview to be the same 227 * as the requested video size. 228 * 229 */ 230/* 231 * Query the camera to retrieve the supported video frame sizes 232 * and also to see whether CameraParameters::setVideoSize() 233 * is supported or not. 234 * @param params CameraParameters to retrieve the information 235 * @@param isSetVideoSizeSupported retunrs whether method 236 * CameraParameters::setVideoSize() is supported or not. 237 * @param sizes returns the vector of Size objects for the 238 * supported video frame sizes advertised by the camera. 239 */ 240static void getSupportedVideoSizes( 241 const CameraParameters& params, 242 bool *isSetVideoSizeSupported, 243 Vector<Size>& sizes) { 244 245 *isSetVideoSizeSupported = true; 246 params.getSupportedVideoSizes(sizes); 247 if (sizes.size() == 0) { 248 LOGD("Camera does not support setVideoSize()"); 249 params.getSupportedPreviewSizes(sizes); 250 *isSetVideoSizeSupported = false; 251 } 252} 253 254/* 255 * Check whether the camera has the supported color format 256 * @param params CameraParameters to retrieve the information 257 * @return OK if no error. 258 */ 259status_t CameraSource::isCameraColorFormatSupported( 260 const CameraParameters& params) { 261 mColorFormat = getColorFormat(params.get( 262 CameraParameters::KEY_VIDEO_FRAME_FORMAT)); 263 if (mColorFormat == -1) { 264 return BAD_VALUE; 265 } 266 return OK; 267} 268 269/* 270 * Configure the camera to use the requested video size 271 * (width and height) and/or frame rate. If both width and 272 * height are -1, configuration on the video size is skipped. 273 * if frameRate is -1, configuration on the frame rate 274 * is skipped. Skipping the configuration allows one to 275 * use the current camera setting without the need to 276 * actually know the specific values (see Create() method). 277 * 278 * @param params the CameraParameters to be configured 279 * @param width the target video frame width in pixels 280 * @param height the target video frame height in pixels 281 * @param frameRate the target frame rate in frames per second. 282 * @return OK if no error. 283 */ 284status_t CameraSource::configureCamera( 285 CameraParameters* params, 286 int32_t width, int32_t height, 287 int32_t frameRate) { 288 289 Vector<Size> sizes; 290 bool isSetVideoSizeSupportedByCamera = true; 291 getSupportedVideoSizes(*params, &isSetVideoSizeSupportedByCamera, sizes); 292 bool isCameraParamChanged = false; 293 if (width != -1 && height != -1) { 294 if (!isVideoSizeSupported(width, height, sizes)) { 295 LOGE("Video dimension (%dx%d) is unsupported", width, height); 296 return BAD_VALUE; 297 } 298 if (isSetVideoSizeSupportedByCamera) { 299 params->setVideoSize(width, height); 300 } else { 301 params->setPreviewSize(width, height); 302 } 303 isCameraParamChanged = true; 304 } else if ((width == -1 && height != -1) || 305 (width != -1 && height == -1)) { 306 // If one and only one of the width and height is -1 307 // we reject such a request. 308 LOGE("Requested video size (%dx%d) is not supported", width, height); 309 return BAD_VALUE; 310 } else { // width == -1 && height == -1 311 // Do not configure the camera. 312 // Use the current width and height value setting from the camera. 313 } 314 315 if (frameRate != -1) { 316 params->setPreviewFrameRate(frameRate); 317 isCameraParamChanged = true; 318 } else { // frameRate == -1 319 // Do not configure the camera. 320 // Use the current frame rate value setting from the camera 321 } 322 323 if (isCameraParamChanged) { 324 // Either frame rate or frame size needs to be changed. 325 String8 s = params->flatten(); 326 if (OK != mCamera->setParameters(s)) { 327 LOGE("Could not change settings." 328 " Someone else is using camera %p?", mCamera.get()); 329 return -EBUSY; 330 } 331 } 332 return OK; 333} 334 335/* 336 * Check whether the requested video frame size 337 * has been successfully configured or not. If both width and height 338 * are -1, check on the current width and height value setting 339 * is performed. 340 * 341 * @param params CameraParameters to retrieve the information 342 * @param the target video frame width in pixels to check against 343 * @param the target video frame height in pixels to check against 344 * @return OK if no error 345 */ 346status_t CameraSource::checkVideoSize( 347 const CameraParameters& params, 348 int32_t width, int32_t height) { 349 350 // The actual video size is the same as the preview size 351 // if the camera hal does not support separate video and 352 // preview output. In this case, we retrieve the video 353 // size from preview. 354 int32_t frameWidthActual = -1; 355 int32_t frameHeightActual = -1; 356 Vector<Size> sizes; 357 params.getSupportedVideoSizes(sizes); 358 if (sizes.size() == 0) { 359 // video size is the same as preview size 360 params.getPreviewSize(&frameWidthActual, &frameHeightActual); 361 } else { 362 // video size may not be the same as preview 363 params.getVideoSize(&frameWidthActual, &frameHeightActual); 364 } 365 if (frameWidthActual < 0 || frameHeightActual < 0) { 366 LOGE("Failed to retrieve video frame size (%dx%d)", 367 frameWidthActual, frameHeightActual); 368 return UNKNOWN_ERROR; 369 } 370 371 // Check the actual video frame size against the target/requested 372 // video frame size. 373 if (width != -1 && height != -1) { 374 if (frameWidthActual != width || frameHeightActual != height) { 375 LOGE("Failed to set video frame size to %dx%d. " 376 "The actual video size is %dx%d ", width, height, 377 frameWidthActual, frameHeightActual); 378 return UNKNOWN_ERROR; 379 } 380 } 381 382 // Good now. 383 mVideoSize.width = frameWidthActual; 384 mVideoSize.height = frameHeightActual; 385 return OK; 386} 387 388/* 389 * Check the requested frame rate has been successfully configured or not. 390 * If the target frameRate is -1, check on the current frame rate value 391 * setting is performed. 392 * 393 * @param params CameraParameters to retrieve the information 394 * @param the target video frame rate to check against 395 * @return OK if no error. 396 */ 397status_t CameraSource::checkFrameRate( 398 const CameraParameters& params, 399 int32_t frameRate) { 400 401 int32_t frameRateActual = params.getPreviewFrameRate(); 402 if (frameRateActual < 0) { 403 LOGE("Failed to retrieve preview frame rate (%d)", frameRateActual); 404 return UNKNOWN_ERROR; 405 } 406 407 // Check the actual video frame rate against the target/requested 408 // video frame rate. 409 if (frameRate != -1 && (frameRateActual - frameRate) != 0) { 410 LOGE("Failed to set preview frame rate to %d fps. The actual " 411 "frame rate is %d", frameRate, frameRateActual); 412 return UNKNOWN_ERROR; 413 } 414 415 // Good now. 416 mVideoFrameRate = frameRateActual; 417 return OK; 418} 419 420/* 421 * Initialize the CameraSource to so that it becomes 422 * ready for providing the video input streams as requested. 423 * @param camera the camera object used for the video source 424 * @param cameraId if camera == 0, use camera with this id 425 * as the video source 426 * @param videoSize the target video frame size. If both 427 * width and height in videoSize is -1, use the current 428 * width and heigth settings by the camera 429 * @param frameRate the target frame rate in frames per second. 430 * if it is -1, use the current camera frame rate setting. 431 * @param storeMetaDataInVideoBuffers request to store meta 432 * data or real YUV data in video buffers. Request to 433 * store meta data in video buffers may not be honored 434 * if the source does not support this feature. 435 * 436 * @return OK if no error. 437 */ 438status_t CameraSource::init( 439 const sp<ICamera>& camera, 440 int32_t cameraId, 441 Size videoSize, 442 int32_t frameRate, 443 bool storeMetaDataInVideoBuffers) { 444 445 status_t err = OK; 446 int64_t token = IPCThreadState::self()->clearCallingIdentity(); 447 448 if ((err = isCameraAvailable(camera, cameraId)) != OK) { 449 return err; 450 } 451 CameraParameters params(mCamera->getParameters()); 452 if ((err = isCameraColorFormatSupported(params)) != OK) { 453 return err; 454 } 455 456 // Set the camera to use the requested video frame size 457 // and/or frame rate. 458 if ((err = configureCamera(¶ms, 459 videoSize.width, videoSize.height, 460 frameRate))) { 461 return err; 462 } 463 464 // Check on video frame size and frame rate. 465 CameraParameters newCameraParams(mCamera->getParameters()); 466 if ((err = checkVideoSize(newCameraParams, 467 videoSize.width, videoSize.height)) != OK) { 468 return err; 469 } 470 if ((err = checkFrameRate(newCameraParams, frameRate)) != OK) { 471 return err; 472 } 473 474 // This CHECK is good, since we just passed the lock/unlock 475 // check earlier by calling mCamera->setParameters(). 476 CHECK_EQ(OK, mCamera->setPreviewDisplay(mSurface)); 477 478 mIsMetaDataStoredInVideoBuffers = false; 479 if (storeMetaDataInVideoBuffers && 480 OK == mCamera->storeMetaDataInBuffers(true)) { 481 mIsMetaDataStoredInVideoBuffers = true; 482 } 483 484 /* 485 * mCamera->startRecording() signals camera hal to make 486 * available the video buffers (for instance, allocation 487 * of the video buffers may be triggered when camera hal's 488 * startRecording() method is called). Making available these 489 * video buffers earlier (before calling start()) is critical, 490 * if one wants to configure omx video encoders to use these 491 * buffers for passing video frame data during video recording 492 * without the need to memcpy the video frame data stored 493 * in these buffers. Eliminating memcpy for video frame data 494 * is crucial in performance for HD quality video recording 495 * applications. 496 * 497 * Based on OMX IL spec, configuring the omx video encoders 498 * must occur in loaded state. When start() is called, omx 499 * video encoders are already in idle state, which is too 500 * late. Thus, we must call mCamera->startRecording() earlier. 501 */ 502 startCameraRecording(); 503 504 IPCThreadState::self()->restoreCallingIdentity(token); 505 506 int64_t glitchDurationUs = (1000000LL / mVideoFrameRate); 507 if (glitchDurationUs > mGlitchDurationThresholdUs) { 508 mGlitchDurationThresholdUs = glitchDurationUs; 509 } 510 511 // XXX: query camera for the stride and slice height 512 // when the capability becomes available. 513 mMeta = new MetaData; 514 mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW); 515 mMeta->setInt32(kKeyColorFormat, mColorFormat); 516 mMeta->setInt32(kKeyWidth, mVideoSize.width); 517 mMeta->setInt32(kKeyHeight, mVideoSize.height); 518 mMeta->setInt32(kKeyStride, mVideoSize.width); 519 mMeta->setInt32(kKeySliceHeight, mVideoSize.height); 520 return OK; 521} 522 523CameraSource::~CameraSource() { 524 if (mStarted) { 525 stop(); 526 } 527} 528 529void CameraSource::startCameraRecording() { 530 CHECK_EQ(OK, mCamera->startRecording()); 531 CHECK(mCamera->recordingEnabled()); 532} 533 534status_t CameraSource::start(MetaData *meta) { 535 CHECK(!mStarted); 536 if (mInitCheck != OK) { 537 LOGE("CameraSource is not initialized yet"); 538 return mInitCheck; 539 } 540 541 char value[PROPERTY_VALUE_MAX]; 542 if (property_get("media.stagefright.record-stats", value, NULL) 543 && (!strcmp(value, "1") || !strcasecmp(value, "true"))) { 544 mCollectStats = true; 545 } 546 547 mStartTimeUs = 0; 548 int64_t startTimeUs; 549 if (meta && meta->findInt64(kKeyTime, &startTimeUs)) { 550 mStartTimeUs = startTimeUs; 551 } 552 553 int64_t token = IPCThreadState::self()->clearCallingIdentity(); 554 mCamera->setListener(new CameraSourceListener(this)); 555 IPCThreadState::self()->restoreCallingIdentity(token); 556 557 mStarted = true; 558 return OK; 559} 560 561void CameraSource::stopCameraRecording() { 562 mCamera->setListener(NULL); 563 mCamera->stopRecording(); 564} 565 566status_t CameraSource::stop() { 567 LOGV("stop"); 568 Mutex::Autolock autoLock(mLock); 569 mStarted = false; 570 mFrameAvailableCondition.signal(); 571 572 int64_t token = IPCThreadState::self()->clearCallingIdentity(); 573 stopCameraRecording(); 574 releaseQueuedFrames(); 575 while (!mFramesBeingEncoded.empty()) { 576 LOGI("Waiting for outstanding frames being encoded: %d", 577 mFramesBeingEncoded.size()); 578 mFrameCompleteCondition.wait(mLock); 579 } 580 581 LOGV("Disconnect camera"); 582 if ((mCameraFlags & FLAGS_HOT_CAMERA) == 0) { 583 LOGV("Camera was cold when we started, stopping preview"); 584 mCamera->stopPreview(); 585 } 586 mCamera->unlock(); 587 mCamera.clear(); 588 mCamera = 0; 589 mCameraFlags = 0; 590 IPCThreadState::self()->restoreCallingIdentity(token); 591 592 if (mCollectStats) { 593 LOGI("Frames received/encoded/dropped: %d/%d/%d in %lld us", 594 mNumFramesReceived, mNumFramesEncoded, mNumFramesDropped, 595 mLastFrameTimestampUs - mFirstFrameTimeUs); 596 } 597 598 CHECK_EQ(mNumFramesReceived, mNumFramesEncoded + mNumFramesDropped); 599 return OK; 600} 601 602void CameraSource::releaseRecordingFrame(const sp<IMemory>& frame) { 603 mCamera->releaseRecordingFrame(frame); 604} 605 606void CameraSource::releaseQueuedFrames() { 607 List<sp<IMemory> >::iterator it; 608 while (!mFramesReceived.empty()) { 609 it = mFramesReceived.begin(); 610 releaseRecordingFrame(*it); 611 mFramesReceived.erase(it); 612 ++mNumFramesDropped; 613 } 614} 615 616sp<MetaData> CameraSource::getFormat() { 617 return mMeta; 618} 619 620void CameraSource::releaseOneRecordingFrame(const sp<IMemory>& frame) { 621 int64_t token = IPCThreadState::self()->clearCallingIdentity(); 622 releaseRecordingFrame(frame); 623 IPCThreadState::self()->restoreCallingIdentity(token); 624} 625 626void CameraSource::signalBufferReturned(MediaBuffer *buffer) { 627 LOGV("signalBufferReturned: %p", buffer->data()); 628 Mutex::Autolock autoLock(mLock); 629 for (List<sp<IMemory> >::iterator it = mFramesBeingEncoded.begin(); 630 it != mFramesBeingEncoded.end(); ++it) { 631 if ((*it)->pointer() == buffer->data()) { 632 releaseOneRecordingFrame((*it)); 633 mFramesBeingEncoded.erase(it); 634 ++mNumFramesEncoded; 635 buffer->setObserver(0); 636 buffer->release(); 637 mFrameCompleteCondition.signal(); 638 return; 639 } 640 } 641 CHECK_EQ(0, "signalBufferReturned: bogus buffer"); 642} 643 644status_t CameraSource::read( 645 MediaBuffer **buffer, const ReadOptions *options) { 646 LOGV("read"); 647 648 *buffer = NULL; 649 650 int64_t seekTimeUs; 651 ReadOptions::SeekMode mode; 652 if (options && options->getSeekTo(&seekTimeUs, &mode)) { 653 return ERROR_UNSUPPORTED; 654 } 655 656 sp<IMemory> frame; 657 int64_t frameTime; 658 659 { 660 Mutex::Autolock autoLock(mLock); 661 while (mStarted) { 662 while(mFramesReceived.empty()) { 663 mFrameAvailableCondition.wait(mLock); 664 } 665 666 if (!mStarted) { 667 return OK; 668 } 669 670 frame = *mFramesReceived.begin(); 671 mFramesReceived.erase(mFramesReceived.begin()); 672 673 frameTime = *mFrameTimes.begin(); 674 mFrameTimes.erase(mFrameTimes.begin()); 675 int64_t skipTimeUs; 676 if (!options || !options->getSkipFrame(&skipTimeUs)) { 677 skipTimeUs = frameTime; 678 } 679 if (skipTimeUs > frameTime) { 680 LOGV("skipTimeUs: %lld us > frameTime: %lld us", 681 skipTimeUs, frameTime); 682 releaseOneRecordingFrame(frame); 683 ++mNumFramesDropped; 684 // Safeguard against the abuse of the kSkipFrame_Option. 685 if (skipTimeUs - frameTime >= 1E6) { 686 LOGE("Frame skipping requested is way too long: %lld us", 687 skipTimeUs - frameTime); 688 return UNKNOWN_ERROR; 689 } 690 } else { 691 mFramesBeingEncoded.push_back(frame); 692 *buffer = new MediaBuffer(frame->pointer(), frame->size()); 693 (*buffer)->setObserver(this); 694 (*buffer)->add_ref(); 695 (*buffer)->meta_data()->setInt64(kKeyTime, frameTime); 696 697 return OK; 698 } 699 } 700 } 701 return OK; 702} 703 704void CameraSource::dataCallbackTimestamp(int64_t timestampUs, 705 int32_t msgType, const sp<IMemory> &data) { 706 LOGV("dataCallbackTimestamp: timestamp %lld us", timestampUs); 707 Mutex::Autolock autoLock(mLock); 708 if (!mStarted) { 709 releaseOneRecordingFrame(data); 710 ++mNumFramesReceived; 711 ++mNumFramesDropped; 712 return; 713 } 714 715 if (mNumFramesReceived > 0 && 716 timestampUs - mLastFrameTimestampUs > mGlitchDurationThresholdUs) { 717 if (mNumGlitches % 10 == 0) { // Don't spam the log 718 LOGW("Long delay detected in video recording"); 719 } 720 ++mNumGlitches; 721 } 722 723 // May need to skip frame or modify timestamp. Currently implemented 724 // by the subclass CameraSourceTimeLapse. 725 if(skipCurrentFrame(timestampUs)) { 726 releaseOneRecordingFrame(data); 727 return; 728 } 729 730 mLastFrameTimestampUs = timestampUs; 731 if (mNumFramesReceived == 0) { 732 mFirstFrameTimeUs = timestampUs; 733 // Initial delay 734 if (mStartTimeUs > 0) { 735 if (timestampUs < mStartTimeUs) { 736 // Frame was captured before recording was started 737 // Drop it without updating the statistical data. 738 releaseOneRecordingFrame(data); 739 return; 740 } 741 mStartTimeUs = timestampUs - mStartTimeUs; 742 } 743 } 744 ++mNumFramesReceived; 745 746 mFramesReceived.push_back(data); 747 int64_t timeUs = mStartTimeUs + (timestampUs - mFirstFrameTimeUs); 748 mFrameTimes.push_back(timeUs); 749 LOGV("initial delay: %lld, current time stamp: %lld", 750 mStartTimeUs, timeUs); 751 mFrameAvailableCondition.signal(); 752} 753 754size_t CameraSource::getNumberOfVideoBuffers() const { 755 LOGV("getNumberOfVideoBuffers"); 756 size_t nBuffers = 0; 757 int64_t token = IPCThreadState::self()->clearCallingIdentity(); 758 if (mInitCheck == OK && mCamera != 0) { 759 nBuffers = mCamera->getNumberOfVideoBuffers(); 760 } 761 IPCThreadState::self()->restoreCallingIdentity(token); 762 return nBuffers; 763} 764 765sp<IMemory> CameraSource::getVideoBuffer(size_t index) const { 766 LOGV("getVideoBuffer: %d", index); 767 sp<IMemory> buffer = 0; 768 int64_t token = IPCThreadState::self()->clearCallingIdentity(); 769 if (mInitCheck == OK && mCamera != 0) { 770 buffer = mCamera->getVideoBuffer(index); 771 } 772 IPCThreadState::self()->restoreCallingIdentity(token); 773 return buffer; 774} 775 776bool CameraSource::isMetaDataStoredInVideoBuffers() const { 777 LOGV("isMetaDataStoredInVideoBuffers"); 778 return mIsMetaDataStoredInVideoBuffers; 779} 780 781} // namespace android 782