2 * Copyright (C) 2009 The Android Open Source Project
3 * Copyright (C) 2013 Mozilla Foundation
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 #include <base/basictypes.h>
20 #define DOM_CAMERA_LOG_LEVEL 3
21 #include "CameraCommon.h"
23 #define CS_LOGD(...) DOM_CAMERA_LOGA(__VA_ARGS__)
24 #define CS_LOGV(...) DOM_CAMERA_LOGI(__VA_ARGS__)
25 #define CS_LOGI(...) DOM_CAMERA_LOGI(__VA_ARGS__)
26 #define CS_LOGW(...) DOM_CAMERA_LOGW(__VA_ARGS__)
27 #define CS_LOGE(...) DOM_CAMERA_LOGE(__VA_ARGS__)
30 #define CS_LOGD(fmt, ...) DOM_CAMERA_LOGA("[%s:%d]" fmt,__FILE__,__LINE__, ## __VA_ARGS__)
31 #define CS_LOGV(fmt, ...) DOM_CAMERA_LOGI("[%s:%d]" fmt,__FILE__,__LINE__, ## __VA_ARGS__)
32 #define CS_LOGI(fmt, ...) DOM_CAMERA_LOGI("[%s:%d]" fmt,__FILE__,__LINE__, ## __VA_ARGS__)
33 #define CS_LOGW(fmt, ...) DOM_CAMERA_LOGW("[%s:%d]" fmt,__FILE__,__LINE__, ## __VA_ARGS__)
34 #define CS_LOGE(fmt, ...) DOM_CAMERA_LOGE("[%s:%d]" fmt,__FILE__,__LINE__, ## __VA_ARGS__)
36 #include <OMX_Component.h>
37 #include <binder/IPCThreadState.h>
38 #include <media/stagefright/foundation/ADebug.h>
39 #include <media/stagefright/MediaDefs.h>
40 #include <media/stagefright/MediaErrors.h>
41 #include <media/stagefright/MetaData.h>
42 #include <camera/CameraParameters.h>
43 #include <utils/String8.h>
44 #include <cutils/properties.h>
46 #include "GonkCameraSource.h"
47 #include "GonkCameraListener.h"
48 #include "GonkCameraHwMgr.h"
50 using namespace mozilla
;
54 static const int64_t CAMERA_SOURCE_TIMEOUT_NS
= 3000000000LL;
56 struct GonkCameraSourceListener
: public GonkCameraListener
{
57 GonkCameraSourceListener(const sp
<GonkCameraSource
> &source
);
59 virtual void notify(int32_t msgType
, int32_t ext1
, int32_t ext2
);
60 virtual void postData(int32_t msgType
, const sp
<IMemory
> &dataPtr
,
61 camera_frame_metadata_t
*metadata
);
63 virtual void postDataTimestamp(
64 nsecs_t timestamp
, int32_t msgType
, const sp
<IMemory
>& dataPtr
);
67 virtual ~GonkCameraSourceListener();
70 wp
<GonkCameraSource
> mSource
;
72 GonkCameraSourceListener(const GonkCameraSourceListener
&);
73 GonkCameraSourceListener
&operator=(const GonkCameraSourceListener
&);
76 GonkCameraSourceListener::GonkCameraSourceListener(const sp
<GonkCameraSource
> &source
)
80 GonkCameraSourceListener::~GonkCameraSourceListener() {
83 void GonkCameraSourceListener::notify(int32_t msgType
, int32_t ext1
, int32_t ext2
) {
84 CS_LOGV("notify(%d, %d, %d)", msgType
, ext1
, ext2
);
87 void GonkCameraSourceListener::postData(int32_t msgType
, const sp
<IMemory
> &dataPtr
,
88 camera_frame_metadata_t
*metadata
) {
89 CS_LOGV("postData(%d, ptr:%p, size:%d)",
90 msgType
, dataPtr
->pointer(), dataPtr
->size());
92 sp
<GonkCameraSource
> source
= mSource
.promote();
93 if (source
.get() != NULL
) {
94 source
->dataCallback(msgType
, dataPtr
);
98 void GonkCameraSourceListener::postDataTimestamp(
99 nsecs_t timestamp
, int32_t msgType
, const sp
<IMemory
>& dataPtr
) {
101 sp
<GonkCameraSource
> source
= mSource
.promote();
102 if (source
.get() != NULL
) {
103 source
->dataCallbackTimestamp(timestamp
/1000, msgType
, dataPtr
);
107 static int32_t getColorFormat(const char* colorFormat
) {
108 return OMX_COLOR_FormatYUV420SemiPlanar
; //XXX nsGonkCameraControl uses only YUV420SemiPlanar
110 if (!strcmp(colorFormat
, CameraParameters::PIXEL_FORMAT_YUV420P
)) {
111 return OMX_COLOR_FormatYUV420Planar
;
114 if (!strcmp(colorFormat
, CameraParameters::PIXEL_FORMAT_YUV422SP
)) {
115 return OMX_COLOR_FormatYUV422SemiPlanar
;
118 if (!strcmp(colorFormat
, CameraParameters::PIXEL_FORMAT_YUV420SP
)) {
119 return OMX_COLOR_FormatYUV420SemiPlanar
;
122 if (!strcmp(colorFormat
, CameraParameters::PIXEL_FORMAT_YUV422I
)) {
123 return OMX_COLOR_FormatYCbYCr
;
126 if (!strcmp(colorFormat
, CameraParameters::PIXEL_FORMAT_RGB565
)) {
127 return OMX_COLOR_Format16bitRGB565
;
130 if (!strcmp(colorFormat
, "OMX_TI_COLOR_FormatYUV420PackedSemiPlanar")) {
131 return OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
;
133 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
134 if (!strcmp(colorFormat
, CameraParameters::PIXEL_FORMAT_ANDROID_OPAQUE
)) {
135 return OMX_COLOR_FormatAndroidOpaque
;
138 CS_LOGE("Uknown color format (%s), please add it to "
139 "GonkCameraSource::getColorFormat", colorFormat
);
141 CHECK(!"Unknown color format");
144 GonkCameraSource
*GonkCameraSource::Create(
145 const sp
<GonkCameraHardware
>& aCameraHw
,
148 bool storeMetaDataInVideoBuffers
) {
150 GonkCameraSource
*source
= new GonkCameraSource(aCameraHw
,
151 videoSize
, frameRate
,
152 storeMetaDataInVideoBuffers
);
156 GonkCameraSource::GonkCameraSource(
157 const sp
<GonkCameraHardware
>& aCameraHw
,
160 bool storeMetaDataInVideoBuffers
)
161 : mCameraHw(aCameraHw
),
165 mNumFramesReceived(0),
166 mLastFrameTimestampUs(0),
168 mNumFramesEncoded(0),
169 mTimeBetweenFrameCaptureUs(0),
170 mFirstFrameTimeUs(0),
171 mNumFramesDropped(0),
173 mGlitchDurationThresholdUs(200000),
174 mCollectStats(false) {
175 mVideoSize
.width
= -1;
176 mVideoSize
.height
= -1;
179 videoSize
, frameRate
,
180 storeMetaDataInVideoBuffers
);
181 if (mInitCheck
!= OK
) releaseCamera();
184 status_t
GonkCameraSource::initCheck() const {
188 //TODO: Do we need to reimplement isCameraAvailable?
191 * Check to see whether the requested video width and height is one
192 * of the supported sizes.
193 * @param width the video frame width in pixels
194 * @param height the video frame height in pixels
195 * @param suppportedSizes the vector of sizes that we check against
196 * @return true if the dimension (width and height) is supported.
198 static bool isVideoSizeSupported(
199 int32_t width
, int32_t height
,
200 const Vector
<Size
>& supportedSizes
) {
202 CS_LOGV("isVideoSizeSupported");
203 for (size_t i
= 0; i
< supportedSizes
.size(); ++i
) {
204 if (width
== supportedSizes
[i
].width
&&
205 height
== supportedSizes
[i
].height
) {
213 * If the preview and video output is separate, we only set the
214 * the video size, and applications should set the preview size
215 * to some proper value, and the recording framework will not
216 * change the preview size; otherwise, if the video and preview
217 * output is the same, we need to set the preview to be the same
218 * as the requested video size.
222 * Query the camera to retrieve the supported video frame sizes
223 * and also to see whether CameraParameters::setVideoSize()
224 * is supported or not.
225 * @param params CameraParameters to retrieve the information
226 * @@param isSetVideoSizeSupported retunrs whether method
227 * CameraParameters::setVideoSize() is supported or not.
228 * @param sizes returns the vector of Size objects for the
229 * supported video frame sizes advertised by the camera.
231 static void getSupportedVideoSizes(
232 const CameraParameters
& params
,
233 bool *isSetVideoSizeSupported
,
234 Vector
<Size
>& sizes
) {
236 *isSetVideoSizeSupported
= true;
237 params
.getSupportedVideoSizes(sizes
);
238 if (sizes
.size() == 0) {
239 CS_LOGD("Camera does not support setVideoSize()");
240 params
.getSupportedPreviewSizes(sizes
);
241 *isSetVideoSizeSupported
= false;
246 * Check whether the camera has the supported color format
247 * @param params CameraParameters to retrieve the information
248 * @return OK if no error.
250 status_t
GonkCameraSource::isCameraColorFormatSupported(
251 const CameraParameters
& params
) {
252 mColorFormat
= getColorFormat(params
.get(
253 CameraParameters::KEY_VIDEO_FRAME_FORMAT
));
254 if (mColorFormat
== -1) {
261 * Configure the camera to use the requested video size
262 * (width and height) and/or frame rate. If both width and
263 * height are -1, configuration on the video size is skipped.
264 * if frameRate is -1, configuration on the frame rate
265 * is skipped. Skipping the configuration allows one to
266 * use the current camera setting without the need to
267 * actually know the specific values (see Create() method).
269 * @param params the CameraParameters to be configured
270 * @param width the target video frame width in pixels
271 * @param height the target video frame height in pixels
272 * @param frameRate the target frame rate in frames per second.
273 * @return OK if no error.
275 status_t
GonkCameraSource::configureCamera(
276 CameraParameters
* params
,
277 int32_t width
, int32_t height
,
279 CS_LOGV("configureCamera");
281 bool isSetVideoSizeSupportedByCamera
= true;
282 getSupportedVideoSizes(*params
, &isSetVideoSizeSupportedByCamera
, sizes
);
283 bool isCameraParamChanged
= false;
284 if (width
!= -1 && height
!= -1) {
285 if (!isVideoSizeSupported(width
, height
, sizes
)) {
286 CS_LOGE("Video dimension (%dx%d) is unsupported", width
, height
);
289 if (isSetVideoSizeSupportedByCamera
) {
290 params
->setVideoSize(width
, height
);
292 params
->setPreviewSize(width
, height
);
294 isCameraParamChanged
= true;
295 } else if ((width
== -1 && height
!= -1) ||
296 (width
!= -1 && height
== -1)) {
297 // If one and only one of the width and height is -1
298 // we reject such a request.
299 CS_LOGE("Requested video size (%dx%d) is not supported", width
, height
);
301 } else { // width == -1 && height == -1
302 // Do not configure the camera.
303 // Use the current width and height value setting from the camera.
306 if (frameRate
!= -1) {
307 CHECK(frameRate
> 0 && frameRate
<= 120);
308 const char* supportedFrameRates
=
309 params
->get(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES
);
310 CHECK(supportedFrameRates
!= NULL
);
311 CS_LOGV("Supported frame rates: %s", supportedFrameRates
);
313 snprintf(buf
, 4, "%d", frameRate
);
314 if (strstr(supportedFrameRates
, buf
) == NULL
) {
315 CS_LOGE("Requested frame rate (%d) is not supported: %s",
316 frameRate
, supportedFrameRates
);
320 // The frame rate is supported, set the camera to the requested value.
321 params
->setPreviewFrameRate(frameRate
);
322 isCameraParamChanged
= true;
323 } else { // frameRate == -1
324 // Do not configure the camera.
325 // Use the current frame rate value setting from the camera
328 if (isCameraParamChanged
) {
329 // Either frame rate or frame size needs to be changed.
330 if (OK
!= mCameraHw
->PushParameters(*params
)) {
331 CS_LOGE("Could not change settings."
332 " Someone else is using camera?");
340 * Check whether the requested video frame size
341 * has been successfully configured or not. If both width and height
342 * are -1, check on the current width and height value setting
345 * @param params CameraParameters to retrieve the information
346 * @param the target video frame width in pixels to check against
347 * @param the target video frame height in pixels to check against
348 * @return OK if no error
350 status_t
GonkCameraSource::checkVideoSize(
351 const CameraParameters
& params
,
352 int32_t width
, int32_t height
) {
354 CS_LOGV("checkVideoSize");
355 // The actual video size is the same as the preview size
356 // if the camera hal does not support separate video and
357 // preview output. In this case, we retrieve the video
358 // size from preview.
359 int32_t frameWidthActual
= -1;
360 int32_t frameHeightActual
= -1;
362 params
.getSupportedVideoSizes(sizes
);
363 if (sizes
.size() == 0) {
364 // video size is the same as preview size
365 params
.getPreviewSize(&frameWidthActual
, &frameHeightActual
);
367 // video size may not be the same as preview
368 params
.getVideoSize(&frameWidthActual
, &frameHeightActual
);
370 if (frameWidthActual
< 0 || frameHeightActual
< 0) {
371 CS_LOGE("Failed to retrieve video frame size (%dx%d)",
372 frameWidthActual
, frameHeightActual
);
373 return UNKNOWN_ERROR
;
376 // Check the actual video frame size against the target/requested
378 if (width
!= -1 && height
!= -1) {
379 if (frameWidthActual
!= width
|| frameHeightActual
!= height
) {
380 CS_LOGE("Failed to set video frame size to %dx%d. "
381 "The actual video size is %dx%d ", width
, height
,
382 frameWidthActual
, frameHeightActual
);
383 return UNKNOWN_ERROR
;
388 mVideoSize
.width
= frameWidthActual
;
389 mVideoSize
.height
= frameHeightActual
;
394 * Check the requested frame rate has been successfully configured or not.
395 * If the target frameRate is -1, check on the current frame rate value
396 * setting is performed.
398 * @param params CameraParameters to retrieve the information
399 * @param the target video frame rate to check against
400 * @return OK if no error.
402 status_t
GonkCameraSource::checkFrameRate(
403 const CameraParameters
& params
,
406 CS_LOGV("checkFrameRate");
407 int32_t frameRateActual
= params
.getPreviewFrameRate();
408 if (frameRateActual
< 0) {
409 CS_LOGE("Failed to retrieve preview frame rate (%d)", frameRateActual
);
410 return UNKNOWN_ERROR
;
413 // Check the actual video frame rate against the target/requested
415 if (frameRate
!= -1 && (frameRateActual
- frameRate
) != 0) {
416 CS_LOGE("Failed to set preview frame rate to %d fps. The actual "
417 "frame rate is %d", frameRate
, frameRateActual
);
418 return UNKNOWN_ERROR
;
422 mVideoFrameRate
= frameRateActual
;
427 * Initialize the GonkCameraSource so that it becomes
428 * ready for providing the video input streams as requested.
429 * @param camera the camera object used for the video source
430 * @param cameraId if camera == 0, use camera with this id
431 * as the video source
432 * @param videoSize the target video frame size. If both
433 * width and height in videoSize is -1, use the current
434 * width and heigth settings by the camera
435 * @param frameRate the target frame rate in frames per second.
436 * if it is -1, use the current camera frame rate setting.
437 * @param storeMetaDataInVideoBuffers request to store meta
438 * data or real YUV data in video buffers. Request to
439 * store meta data in video buffers may not be honored
440 * if the source does not support this feature.
442 * @return OK if no error.
444 status_t
GonkCameraSource::init(
447 bool storeMetaDataInVideoBuffers
) {
451 //TODO: need to do something here to check the sanity of camera
453 CameraParameters params
;
454 mCameraHw
->PullParameters(params
);
455 if ((err
= isCameraColorFormatSupported(params
)) != OK
) {
459 // Set the camera to use the requested video frame size
460 // and/or frame rate.
461 if ((err
= configureCamera(¶ms
,
462 videoSize
.width
, videoSize
.height
,
467 // Check on video frame size and frame rate.
468 CameraParameters newCameraParams
;
469 mCameraHw
->PullParameters(newCameraParams
);
470 if ((err
= checkVideoSize(newCameraParams
,
471 videoSize
.width
, videoSize
.height
)) != OK
) {
474 if ((err
= checkFrameRate(newCameraParams
, frameRate
)) != OK
) {
478 // By default, do not store metadata in video buffers
479 mIsMetaDataStoredInVideoBuffers
= false;
480 mCameraHw
->StoreMetaDataInBuffers(false);
481 if (storeMetaDataInVideoBuffers
) {
482 if (OK
== mCameraHw
->StoreMetaDataInBuffers(true)) {
483 mIsMetaDataStoredInVideoBuffers
= true;
487 int64_t glitchDurationUs
= (1000000LL / mVideoFrameRate
);
488 if (glitchDurationUs
> mGlitchDurationThresholdUs
) {
489 mGlitchDurationThresholdUs
= glitchDurationUs
;
492 // XXX: query camera for the stride and slice height
493 // when the capability becomes available.
494 mMeta
= new MetaData
;
495 mMeta
->setCString(kKeyMIMEType
, MEDIA_MIMETYPE_VIDEO_RAW
);
496 mMeta
->setInt32(kKeyColorFormat
, mColorFormat
);
497 mMeta
->setInt32(kKeyWidth
, mVideoSize
.width
);
498 mMeta
->setInt32(kKeyHeight
, mVideoSize
.height
);
499 mMeta
->setInt32(kKeyStride
, mVideoSize
.width
);
500 mMeta
->setInt32(kKeySliceHeight
, mVideoSize
.height
);
501 mMeta
->setInt32(kKeyFrameRate
, mVideoFrameRate
);
505 GonkCameraSource::~GonkCameraSource() {
508 } else if (mInitCheck
== OK
) {
509 // Camera is initialized but because start() is never called,
510 // the lock on Camera is never released(). This makes sure
511 // Camera's lock is released in this case.
512 // TODO: Don't think I need to do this
517 int GonkCameraSource::startCameraRecording() {
518 CS_LOGV("startCameraRecording");
519 return mCameraHw
->StartRecording();
522 status_t
GonkCameraSource::start(MetaData
*meta
) {
527 if (mInitCheck
!= OK
) {
528 CS_LOGE("GonkCameraSource is not initialized yet");
532 char value
[PROPERTY_VALUE_MAX
];
533 if (property_get("media.stagefright.record-stats", value
, NULL
)
534 && (!strcmp(value
, "1") || !strcasecmp(value
, "true"))) {
535 mCollectStats
= true;
539 mNumInputBuffers
= 0;
542 if (meta
->findInt64(kKeyTime
, &startTimeUs
)) {
543 mStartTimeUs
= startTimeUs
;
545 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
547 if (meta
->findInt32(kKeyNumBuffers
, &nBuffers
)) {
548 CHECK_GT(nBuffers
, 0);
549 mNumInputBuffers
= nBuffers
;
554 // Register a listener with GonkCameraHardware so that we can get callbacks
555 mCameraHw
->SetListener(new GonkCameraSourceListener(this));
557 rv
= startCameraRecording();
559 mStarted
= (rv
== OK
);
563 void GonkCameraSource::stopCameraRecording() {
564 CS_LOGV("stopCameraRecording");
565 mCameraHw
->StopRecording();
568 void GonkCameraSource::releaseCamera() {
569 CS_LOGV("releaseCamera");
572 status_t
GonkCameraSource::reset() {
574 Mutex::Autolock
autoLock(mLock
);
576 mFrameAvailableCondition
.signal();
578 releaseQueuedFrames();
579 while (!mFramesBeingEncoded
.empty()) {
581 mFrameCompleteCondition
.waitRelative(mLock
,
582 mTimeBetweenFrameCaptureUs
* 1000LL + CAMERA_SOURCE_TIMEOUT_NS
)) {
583 CS_LOGW("Timed out waiting for outstanding frames being encoded: %d",
584 mFramesBeingEncoded
.size());
587 stopCameraRecording();
591 CS_LOGI("Frames received/encoded/dropped: %d/%d/%d in %lld us",
592 mNumFramesReceived
, mNumFramesEncoded
, mNumFramesDropped
,
593 mLastFrameTimestampUs
- mFirstFrameTimeUs
);
596 if (mNumGlitches
> 0) {
597 CS_LOGW("%d long delays between neighboring video frames", mNumGlitches
);
600 CHECK_EQ(mNumFramesReceived
, mNumFramesEncoded
+ mNumFramesDropped
);
605 void GonkCameraSource::releaseRecordingFrame(const sp
<IMemory
>& frame
) {
606 CS_LOGV("releaseRecordingFrame");
607 mCameraHw
->ReleaseRecordingFrame(frame
);
610 void GonkCameraSource::releaseQueuedFrames() {
611 List
<sp
<IMemory
> >::iterator it
;
612 while (!mFramesReceived
.empty()) {
613 it
= mFramesReceived
.begin();
614 releaseRecordingFrame(*it
);
615 mFramesReceived
.erase(it
);
620 sp
<MetaData
> GonkCameraSource::getFormat() {
624 void GonkCameraSource::releaseOneRecordingFrame(const sp
<IMemory
>& frame
) {
625 releaseRecordingFrame(frame
);
628 void GonkCameraSource::signalBufferReturned(MediaBuffer
*buffer
) {
629 CS_LOGV("signalBufferReturned: %p", buffer
->data());
630 Mutex::Autolock
autoLock(mLock
);
631 for (List
<sp
<IMemory
> >::iterator it
= mFramesBeingEncoded
.begin();
632 it
!= mFramesBeingEncoded
.end(); ++it
) {
633 if ((*it
)->pointer() == buffer
->data()) {
634 releaseOneRecordingFrame((*it
));
635 mFramesBeingEncoded
.erase(it
);
637 buffer
->setObserver(0);
639 mFrameCompleteCondition
.signal();
643 CHECK(!"signalBufferReturned: bogus buffer");
646 status_t
GonkCameraSource::read(
647 MediaBuffer
**buffer
, const ReadOptions
*options
) {
653 ReadOptions::SeekMode mode
;
654 if (options
&& options
->getSeekTo(&seekTimeUs
, &mode
)) {
655 return ERROR_UNSUPPORTED
;
662 Mutex::Autolock
autoLock(mLock
);
663 while (mStarted
&& mFramesReceived
.empty()) {
665 mFrameAvailableCondition
.waitRelative(mLock
,
666 mTimeBetweenFrameCaptureUs
* 1000LL + CAMERA_SOURCE_TIMEOUT_NS
)) {
667 //TODO: check sanity of camera?
668 CS_LOGW("Timed out waiting for incoming camera video frames: %lld us",
669 mLastFrameTimestampUs
);
675 frame
= *mFramesReceived
.begin();
676 mFramesReceived
.erase(mFramesReceived
.begin());
678 frameTime
= *mFrameTimes
.begin();
679 mFrameTimes
.erase(mFrameTimes
.begin());
680 mFramesBeingEncoded
.push_back(frame
);
681 *buffer
= new MediaBuffer(frame
->pointer(), frame
->size());
682 (*buffer
)->setObserver(this);
683 (*buffer
)->add_ref();
684 (*buffer
)->meta_data()->setInt64(kKeyTime
, frameTime
);
689 void GonkCameraSource::dataCallbackTimestamp(int64_t timestampUs
,
690 int32_t msgType
, const sp
<IMemory
> &data
) {
691 CS_LOGV("dataCallbackTimestamp: timestamp %lld us", timestampUs
);
692 Mutex::Autolock
autoLock(mLock
);
693 if (!mStarted
|| (mNumFramesReceived
== 0 && timestampUs
< mStartTimeUs
)) {
694 CS_LOGV("Drop frame at %lld/%lld us", timestampUs
, mStartTimeUs
);
695 releaseOneRecordingFrame(data
);
699 if (mNumFramesReceived
> 0) {
700 CHECK(timestampUs
> mLastFrameTimestampUs
);
701 if (timestampUs
- mLastFrameTimestampUs
> mGlitchDurationThresholdUs
) {
706 // May need to skip frame or modify timestamp. Currently implemented
707 // by the subclass CameraSourceTimeLapse.
708 if (skipCurrentFrame(timestampUs
)) {
709 releaseOneRecordingFrame(data
);
713 mLastFrameTimestampUs
= timestampUs
;
714 if (mNumFramesReceived
== 0) {
715 mFirstFrameTimeUs
= timestampUs
;
717 if (mStartTimeUs
> 0) {
718 if (timestampUs
< mStartTimeUs
) {
719 // Frame was captured before recording was started
720 // Drop it without updating the statistical data.
721 releaseOneRecordingFrame(data
);
724 mStartTimeUs
= timestampUs
- mStartTimeUs
;
727 ++mNumFramesReceived
;
729 CHECK(data
!= NULL
&& data
->size() > 0);
730 mFramesReceived
.push_back(data
);
731 int64_t timeUs
= mStartTimeUs
+ (timestampUs
- mFirstFrameTimeUs
);
732 mFrameTimes
.push_back(timeUs
);
733 CS_LOGV("initial delay: %lld, current time stamp: %lld",
734 mStartTimeUs
, timeUs
);
735 mFrameAvailableCondition
.signal();
738 bool GonkCameraSource::isMetaDataStoredInVideoBuffers() const {
739 CS_LOGV("isMetaDataStoredInVideoBuffers");
740 return mIsMetaDataStoredInVideoBuffers
;
743 } // namespace android