CameraSource.cpp revision 5c9523154d106b555db6c41f85ab205a4f189b02
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 int32_t frameWidthActual = -1; 351 int32_t frameHeightActual = -1; 352 params.getPreviewSize(&frameWidthActual, &frameHeightActual); 353 if (frameWidthActual < 0 || frameHeightActual < 0) { 354 LOGE("Failed to retrieve video frame size (%dx%d)", 355 frameWidthActual, frameHeightActual); 356 return UNKNOWN_ERROR; 357 } 358 359 // Check the actual video frame size against the target/requested 360 // video frame size. 361 if (width != -1 && height != -1) { 362 if (frameWidthActual != width || frameHeightActual != height) { 363 LOGE("Failed to set video frame size to %dx%d. " 364 "The actual video size is %dx%d ", width, height, 365 frameWidthActual, frameHeightActual); 366 return UNKNOWN_ERROR; 367 } 368 } 369 370 // Good now. 371 mVideoSize.width = frameWidthActual; 372 mVideoSize.height = frameHeightActual; 373 return OK; 374} 375 376/* 377 * Check the requested frame rate has been successfully configured or not. 378 * If the target frameRate is -1, check on the current frame rate value 379 * setting is performed. 380 * 381 * @param params CameraParameters to retrieve the information 382 * @param the target video frame rate to check against 383 * @return OK if no error. 384 */ 385status_t CameraSource::checkFrameRate( 386 const CameraParameters& params, 387 int32_t frameRate) { 388 389 int32_t frameRateActual = params.getPreviewFrameRate(); 390 if (frameRateActual < 0) { 391 LOGE("Failed to retrieve preview frame rate (%d)", frameRateActual); 392 return UNKNOWN_ERROR; 393 } 394 395 // Check the actual video frame rate against the target/requested 396 // video frame rate. 397 if (frameRate != -1 && (frameRateActual - frameRate) != 0) { 398 LOGE("Failed to set preview frame rate to %d fps. The actual " 399 "frame rate is %d", frameRate, frameRateActual); 400 return UNKNOWN_ERROR; 401 } 402 403 // Good now. 404 mVideoFrameRate = frameRateActual; 405 return OK; 406} 407 408/* 409 * Initialize the CameraSource to so that it becomes 410 * ready for providing the video input streams as requested. 411 * @param camera the camera object used for the video source 412 * @param cameraId if camera == 0, use camera with this id 413 * as the video source 414 * @param videoSize the target video frame size. If both 415 * width and height in videoSize is -1, use the current 416 * width and heigth settings by the camera 417 * @param frameRate the target frame rate in frames per second. 418 * if it is -1, use the current camera frame rate setting. 419 * @param storeMetaDataInVideoBuffers request to store meta 420 * data or real YUV data in video buffers. Request to 421 * store meta data in video buffers may not be honored 422 * if the source does not support this feature. 423 * 424 * @return OK if no error. 425 */ 426status_t CameraSource::init( 427 const sp<ICamera>& camera, 428 int32_t cameraId, 429 Size videoSize, 430 int32_t frameRate, 431 bool storeMetaDataInVideoBuffers) { 432 433 status_t err = OK; 434 int64_t token = IPCThreadState::self()->clearCallingIdentity(); 435 436 if ((err = isCameraAvailable(camera, cameraId)) != OK) { 437 return err; 438 } 439 CameraParameters params(mCamera->getParameters()); 440 if ((err = isCameraColorFormatSupported(params)) != OK) { 441 return err; 442 } 443 444 // Set the camera to use the requested video frame size 445 // and/or frame rate. 446 if ((err = configureCamera(¶ms, 447 videoSize.width, videoSize.height, 448 frameRate))) { 449 return err; 450 } 451 452 // Check on video frame size and frame rate. 453 CameraParameters newCameraParams(mCamera->getParameters()); 454 if ((err = checkVideoSize(newCameraParams, 455 videoSize.width, videoSize.height)) != OK) { 456 return err; 457 } 458 if ((err = checkFrameRate(newCameraParams, frameRate)) != OK) { 459 return err; 460 } 461 462 // This CHECK is good, since we just passed the lock/unlock 463 // check earlier by calling mCamera->setParameters(). 464 CHECK_EQ(OK, mCamera->setPreviewDisplay(mSurface)); 465 466 mIsMetaDataStoredInVideoBuffers = false; 467 if (storeMetaDataInVideoBuffers && 468 OK == mCamera->storeMetaDataInBuffers(true)) { 469 mIsMetaDataStoredInVideoBuffers = true; 470 } 471 472 /* 473 * mCamera->startRecording() signals camera hal to make 474 * available the video buffers (for instance, allocation 475 * of the video buffers may be triggered when camera hal's 476 * startRecording() method is called). Making available these 477 * video buffers earlier (before calling start()) is critical, 478 * if one wants to configure omx video encoders to use these 479 * buffers for passing video frame data during video recording 480 * without the need to memcpy the video frame data stored 481 * in these buffers. Eliminating memcpy for video frame data 482 * is crucial in performance for HD quality video recording 483 * applications. 484 * 485 * Based on OMX IL spec, configuring the omx video encoders 486 * must occur in loaded state. When start() is called, omx 487 * video encoders are already in idle state, which is too 488 * late. Thus, we must call mCamera->startRecording() earlier. 489 */ 490 startCameraRecording(); 491 492 IPCThreadState::self()->restoreCallingIdentity(token); 493 494 int64_t glitchDurationUs = (1000000LL / mVideoFrameRate); 495 if (glitchDurationUs > mGlitchDurationThresholdUs) { 496 mGlitchDurationThresholdUs = glitchDurationUs; 497 } 498 499 // XXX: query camera for the stride and slice height 500 // when the capability becomes available. 501 mMeta = new MetaData; 502 mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW); 503 mMeta->setInt32(kKeyColorFormat, mColorFormat); 504 mMeta->setInt32(kKeyWidth, mVideoSize.width); 505 mMeta->setInt32(kKeyHeight, mVideoSize.height); 506 mMeta->setInt32(kKeyStride, mVideoSize.width); 507 mMeta->setInt32(kKeySliceHeight, mVideoSize.height); 508 return OK; 509} 510 511CameraSource::~CameraSource() { 512 if (mStarted) { 513 stop(); 514 } 515} 516 517void CameraSource::startCameraRecording() { 518 CHECK_EQ(OK, mCamera->startRecording()); 519 CHECK(mCamera->recordingEnabled()); 520} 521 522status_t CameraSource::start(MetaData *meta) { 523 CHECK(!mStarted); 524 if (mInitCheck != OK) { 525 LOGE("CameraSource is not initialized yet"); 526 return mInitCheck; 527 } 528 529 char value[PROPERTY_VALUE_MAX]; 530 if (property_get("media.stagefright.record-stats", value, NULL) 531 && (!strcmp(value, "1") || !strcasecmp(value, "true"))) { 532 mCollectStats = true; 533 } 534 535 mStartTimeUs = 0; 536 int64_t startTimeUs; 537 if (meta && meta->findInt64(kKeyTime, &startTimeUs)) { 538 mStartTimeUs = startTimeUs; 539 } 540 541 int64_t token = IPCThreadState::self()->clearCallingIdentity(); 542 mCamera->setListener(new CameraSourceListener(this)); 543 IPCThreadState::self()->restoreCallingIdentity(token); 544 545 mStarted = true; 546 return OK; 547} 548 549void CameraSource::stopCameraRecording() { 550 mCamera->setListener(NULL); 551 mCamera->stopRecording(); 552} 553 554status_t CameraSource::stop() { 555 LOGV("stop"); 556 Mutex::Autolock autoLock(mLock); 557 mStarted = false; 558 mFrameAvailableCondition.signal(); 559 560 int64_t token = IPCThreadState::self()->clearCallingIdentity(); 561 stopCameraRecording(); 562 releaseQueuedFrames(); 563 while (!mFramesBeingEncoded.empty()) { 564 LOGI("Waiting for outstanding frames being encoded: %d", 565 mFramesBeingEncoded.size()); 566 mFrameCompleteCondition.wait(mLock); 567 } 568 569 LOGV("Disconnect camera"); 570 if ((mCameraFlags & FLAGS_HOT_CAMERA) == 0) { 571 LOGV("Camera was cold when we started, stopping preview"); 572 mCamera->stopPreview(); 573 } 574 mCamera->unlock(); 575 mCamera.clear(); 576 mCamera = 0; 577 mCameraFlags = 0; 578 IPCThreadState::self()->restoreCallingIdentity(token); 579 580 if (mCollectStats) { 581 LOGI("Frames received/encoded/dropped: %d/%d/%d in %lld us", 582 mNumFramesReceived, mNumFramesEncoded, mNumFramesDropped, 583 mLastFrameTimestampUs - mFirstFrameTimeUs); 584 } 585 586 CHECK_EQ(mNumFramesReceived, mNumFramesEncoded + mNumFramesDropped); 587 return OK; 588} 589 590void CameraSource::releaseRecordingFrame(const sp<IMemory>& frame) { 591 mCamera->releaseRecordingFrame(frame); 592} 593 594void CameraSource::releaseQueuedFrames() { 595 List<sp<IMemory> >::iterator it; 596 while (!mFramesReceived.empty()) { 597 it = mFramesReceived.begin(); 598 releaseRecordingFrame(*it); 599 mFramesReceived.erase(it); 600 ++mNumFramesDropped; 601 } 602} 603 604sp<MetaData> CameraSource::getFormat() { 605 return mMeta; 606} 607 608void CameraSource::releaseOneRecordingFrame(const sp<IMemory>& frame) { 609 int64_t token = IPCThreadState::self()->clearCallingIdentity(); 610 releaseRecordingFrame(frame); 611 IPCThreadState::self()->restoreCallingIdentity(token); 612} 613 614void CameraSource::signalBufferReturned(MediaBuffer *buffer) { 615 LOGV("signalBufferReturned: %p", buffer->data()); 616 Mutex::Autolock autoLock(mLock); 617 for (List<sp<IMemory> >::iterator it = mFramesBeingEncoded.begin(); 618 it != mFramesBeingEncoded.end(); ++it) { 619 if ((*it)->pointer() == buffer->data()) { 620 releaseOneRecordingFrame((*it)); 621 mFramesBeingEncoded.erase(it); 622 ++mNumFramesEncoded; 623 buffer->setObserver(0); 624 buffer->release(); 625 mFrameCompleteCondition.signal(); 626 return; 627 } 628 } 629 CHECK_EQ(0, "signalBufferReturned: bogus buffer"); 630} 631 632status_t CameraSource::read( 633 MediaBuffer **buffer, const ReadOptions *options) { 634 LOGV("read"); 635 636 *buffer = NULL; 637 638 int64_t seekTimeUs; 639 ReadOptions::SeekMode mode; 640 if (options && options->getSeekTo(&seekTimeUs, &mode)) { 641 return ERROR_UNSUPPORTED; 642 } 643 644 sp<IMemory> frame; 645 int64_t frameTime; 646 647 { 648 Mutex::Autolock autoLock(mLock); 649 while (mStarted) { 650 while(mFramesReceived.empty()) { 651 mFrameAvailableCondition.wait(mLock); 652 } 653 654 if (!mStarted) { 655 return OK; 656 } 657 658 frame = *mFramesReceived.begin(); 659 mFramesReceived.erase(mFramesReceived.begin()); 660 661 frameTime = *mFrameTimes.begin(); 662 mFrameTimes.erase(mFrameTimes.begin()); 663 int64_t skipTimeUs; 664 if (!options || !options->getSkipFrame(&skipTimeUs)) { 665 skipTimeUs = frameTime; 666 } 667 if (skipTimeUs > frameTime) { 668 LOGV("skipTimeUs: %lld us > frameTime: %lld us", 669 skipTimeUs, frameTime); 670 releaseOneRecordingFrame(frame); 671 ++mNumFramesDropped; 672 // Safeguard against the abuse of the kSkipFrame_Option. 673 if (skipTimeUs - frameTime >= 1E6) { 674 LOGE("Frame skipping requested is way too long: %lld us", 675 skipTimeUs - frameTime); 676 return UNKNOWN_ERROR; 677 } 678 } else { 679 mFramesBeingEncoded.push_back(frame); 680 *buffer = new MediaBuffer(frame->pointer(), frame->size()); 681 (*buffer)->setObserver(this); 682 (*buffer)->add_ref(); 683 (*buffer)->meta_data()->setInt64(kKeyTime, frameTime); 684 685 return OK; 686 } 687 } 688 } 689 return OK; 690} 691 692void CameraSource::dataCallbackTimestamp(int64_t timestampUs, 693 int32_t msgType, const sp<IMemory> &data) { 694 LOGV("dataCallbackTimestamp: timestamp %lld us", timestampUs); 695 Mutex::Autolock autoLock(mLock); 696 if (!mStarted) { 697 releaseOneRecordingFrame(data); 698 ++mNumFramesReceived; 699 ++mNumFramesDropped; 700 return; 701 } 702 703 if (mNumFramesReceived > 0 && 704 timestampUs - mLastFrameTimestampUs > mGlitchDurationThresholdUs) { 705 if (mNumGlitches % 10 == 0) { // Don't spam the log 706 LOGW("Long delay detected in video recording"); 707 } 708 ++mNumGlitches; 709 } 710 711 // May need to skip frame or modify timestamp. Currently implemented 712 // by the subclass CameraSourceTimeLapse. 713 if(skipCurrentFrame(timestampUs)) { 714 releaseOneRecordingFrame(data); 715 return; 716 } 717 718 mLastFrameTimestampUs = timestampUs; 719 if (mNumFramesReceived == 0) { 720 mFirstFrameTimeUs = timestampUs; 721 // Initial delay 722 if (mStartTimeUs > 0) { 723 if (timestampUs < mStartTimeUs) { 724 // Frame was captured before recording was started 725 // Drop it without updating the statistical data. 726 releaseOneRecordingFrame(data); 727 return; 728 } 729 mStartTimeUs = timestampUs - mStartTimeUs; 730 } 731 } 732 ++mNumFramesReceived; 733 734 mFramesReceived.push_back(data); 735 int64_t timeUs = mStartTimeUs + (timestampUs - mFirstFrameTimeUs); 736 mFrameTimes.push_back(timeUs); 737 LOGV("initial delay: %lld, current time stamp: %lld", 738 mStartTimeUs, timeUs); 739 mFrameAvailableCondition.signal(); 740} 741 742size_t CameraSource::getNumberOfVideoBuffers() const { 743 LOGV("getNumberOfVideoBuffers"); 744 size_t nBuffers = 0; 745 int64_t token = IPCThreadState::self()->clearCallingIdentity(); 746 if (mInitCheck == OK && mCamera != 0) { 747 nBuffers = mCamera->getNumberOfVideoBuffers(); 748 } 749 IPCThreadState::self()->restoreCallingIdentity(token); 750 return nBuffers; 751} 752 753sp<IMemory> CameraSource::getVideoBuffer(size_t index) const { 754 LOGV("getVideoBuffer: %d", index); 755 sp<IMemory> buffer = 0; 756 int64_t token = IPCThreadState::self()->clearCallingIdentity(); 757 if (mInitCheck == OK && mCamera != 0) { 758 buffer = mCamera->getVideoBuffer(index); 759 } 760 IPCThreadState::self()->restoreCallingIdentity(token); 761 return buffer; 762} 763 764bool CameraSource::isMetaDataStoredInVideoBuffers() const { 765 LOGV("isMetaDataStoredInVideoBuffers"); 766 return mIsMetaDataStoredInVideoBuffers; 767} 768 769} // namespace android 770