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