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"
49 #include "ICameraControl.h"
51 using namespace mozilla
;
55 static const int64_t CAMERA_SOURCE_TIMEOUT_NS
= 3000000000LL;
57 struct GonkCameraSourceListener
: public GonkCameraListener
{
58 GonkCameraSourceListener(const sp
<GonkCameraSource
> &source
);
60 virtual void notify(int32_t msgType
, int32_t ext1
, int32_t ext2
);
61 virtual bool postData(int32_t msgType
, const sp
<IMemory
> &dataPtr
,
62 camera_frame_metadata_t
*metadata
);
64 virtual bool postDataTimestamp(
65 nsecs_t timestamp
, int32_t msgType
, const sp
<IMemory
>& dataPtr
);
68 virtual ~GonkCameraSourceListener();
71 wp
<GonkCameraSource
> mSource
;
73 GonkCameraSourceListener(const GonkCameraSourceListener
&);
74 GonkCameraSourceListener
&operator=(const GonkCameraSourceListener
&);
77 GonkCameraSourceListener::GonkCameraSourceListener(const sp
<GonkCameraSource
> &source
)
81 GonkCameraSourceListener::~GonkCameraSourceListener() {
84 void GonkCameraSourceListener::notify(int32_t msgType
, int32_t ext1
, int32_t ext2
) {
85 CS_LOGV("notify(%d, %d, %d)", msgType
, ext1
, ext2
);
88 bool GonkCameraSourceListener::postData(int32_t msgType
, const sp
<IMemory
> &dataPtr
,
89 camera_frame_metadata_t
*metadata
) {
90 CS_LOGV("postData(%d, ptr:%p, size:%d)",
91 msgType
, dataPtr
->pointer(), dataPtr
->size());
93 sp
<GonkCameraSource
> source
= mSource
.promote();
94 if (source
.get() != NULL
) {
95 source
->dataCallback(msgType
, dataPtr
);
101 bool GonkCameraSourceListener::postDataTimestamp(
102 nsecs_t timestamp
, int32_t msgType
, const sp
<IMemory
>& dataPtr
) {
104 sp
<GonkCameraSource
> source
= mSource
.promote();
105 if (source
.get() != NULL
) {
106 source
->dataCallbackTimestamp(timestamp
/1000, msgType
, dataPtr
);
112 static int32_t getColorFormat(const char* colorFormat
) {
113 return OMX_COLOR_FormatYUV420SemiPlanar
; //XXX nsGonkCameraControl uses only YUV420SemiPlanar
115 if (!strcmp(colorFormat
, CameraParameters::PIXEL_FORMAT_YUV420P
)) {
116 return OMX_COLOR_FormatYUV420Planar
;
119 if (!strcmp(colorFormat
, CameraParameters::PIXEL_FORMAT_YUV422SP
)) {
120 return OMX_COLOR_FormatYUV422SemiPlanar
;
123 if (!strcmp(colorFormat
, CameraParameters::PIXEL_FORMAT_YUV420SP
)) {
124 return OMX_COLOR_FormatYUV420SemiPlanar
;
127 if (!strcmp(colorFormat
, CameraParameters::PIXEL_FORMAT_YUV422I
)) {
128 return OMX_COLOR_FormatYCbYCr
;
131 if (!strcmp(colorFormat
, CameraParameters::PIXEL_FORMAT_RGB565
)) {
132 return OMX_COLOR_Format16bitRGB565
;
135 if (!strcmp(colorFormat
, "OMX_TI_COLOR_FormatYUV420PackedSemiPlanar")) {
136 return OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
;
138 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
139 if (!strcmp(colorFormat
, CameraParameters::PIXEL_FORMAT_ANDROID_OPAQUE
)) {
140 return OMX_COLOR_FormatAndroidOpaque
;
143 CS_LOGE("Uknown color format (%s), please add it to "
144 "GonkCameraSource::getColorFormat", colorFormat
);
146 CHECK(!"Unknown color format");
149 GonkCameraSource
*GonkCameraSource::Create(
150 const sp
<GonkCameraHardware
>& aCameraHw
,
153 bool storeMetaDataInVideoBuffers
) {
155 GonkCameraSource
*source
= new GonkCameraSource(aCameraHw
,
156 videoSize
, frameRate
,
157 storeMetaDataInVideoBuffers
);
161 GonkCameraSource
*GonkCameraSource::Create(
162 ICameraControl
* aControl
,
166 mozilla::nsGonkCameraControl
* control
=
167 static_cast<mozilla::nsGonkCameraControl
*>(aControl
);
168 return Create(control
->GetCameraHw(), videoSize
, frameRate
, false);
171 GonkCameraSource::GonkCameraSource(
172 const sp
<GonkCameraHardware
>& aCameraHw
,
175 bool storeMetaDataInVideoBuffers
)
179 mNumFramesReceived(0),
180 mLastFrameTimestampUs(0),
182 mNumFramesEncoded(0),
183 mTimeBetweenFrameCaptureUs(0),
185 mFirstFrameTimeUs(0),
186 mNumFramesDropped(0),
188 mGlitchDurationThresholdUs(200000),
189 mCollectStats(false),
190 mCameraHw(aCameraHw
) {
191 mVideoSize
.width
= -1;
192 mVideoSize
.height
= -1;
195 videoSize
, frameRate
,
196 storeMetaDataInVideoBuffers
);
197 if (mInitCheck
!= OK
) releaseCamera();
200 status_t
GonkCameraSource::initCheck() const {
204 //TODO: Do we need to reimplement isCameraAvailable?
207 * Check to see whether the requested video width and height is one
208 * of the supported sizes.
209 * @param width the video frame width in pixels
210 * @param height the video frame height in pixels
211 * @param suppportedSizes the vector of sizes that we check against
212 * @return true if the dimension (width and height) is supported.
214 static bool isVideoSizeSupported(
215 int32_t width
, int32_t height
,
216 const Vector
<Size
>& supportedSizes
) {
218 CS_LOGV("isVideoSizeSupported");
219 for (size_t i
= 0; i
< supportedSizes
.size(); ++i
) {
220 if (width
== supportedSizes
[i
].width
&&
221 height
== supportedSizes
[i
].height
) {
229 * If the preview and video output is separate, we only set the
230 * the video size, and applications should set the preview size
231 * to some proper value, and the recording framework will not
232 * change the preview size; otherwise, if the video and preview
233 * output is the same, we need to set the preview to be the same
234 * as the requested video size.
238 * Query the camera to retrieve the supported video frame sizes
239 * and also to see whether CameraParameters::setVideoSize()
240 * is supported or not.
241 * @param params CameraParameters to retrieve the information
242 * @@param isSetVideoSizeSupported retunrs whether method
243 * CameraParameters::setVideoSize() is supported or not.
244 * @param sizes returns the vector of Size objects for the
245 * supported video frame sizes advertised by the camera.
247 static void getSupportedVideoSizes(
248 const CameraParameters
& params
,
249 bool *isSetVideoSizeSupported
,
250 Vector
<Size
>& sizes
) {
252 *isSetVideoSizeSupported
= true;
253 params
.getSupportedVideoSizes(sizes
);
254 if (sizes
.size() == 0) {
255 CS_LOGD("Camera does not support setVideoSize()");
256 params
.getSupportedPreviewSizes(sizes
);
257 *isSetVideoSizeSupported
= false;
262 * Check whether the camera has the supported color format
263 * @param params CameraParameters to retrieve the information
264 * @return OK if no error.
266 status_t
GonkCameraSource::isCameraColorFormatSupported(
267 const CameraParameters
& params
) {
268 mColorFormat
= getColorFormat(params
.get(
269 CameraParameters::KEY_VIDEO_FRAME_FORMAT
));
270 if (mColorFormat
== -1) {
277 * Configure the camera to use the requested video size
278 * (width and height) and/or frame rate. If both width and
279 * height are -1, configuration on the video size is skipped.
280 * if frameRate is -1, configuration on the frame rate
281 * is skipped. Skipping the configuration allows one to
282 * use the current camera setting without the need to
283 * actually know the specific values (see Create() method).
285 * @param params the CameraParameters to be configured
286 * @param width the target video frame width in pixels
287 * @param height the target video frame height in pixels
288 * @param frameRate the target frame rate in frames per second.
289 * @return OK if no error.
291 status_t
GonkCameraSource::configureCamera(
292 CameraParameters
* params
,
293 int32_t width
, int32_t height
,
295 CS_LOGV("configureCamera");
297 bool isSetVideoSizeSupportedByCamera
= true;
298 getSupportedVideoSizes(*params
, &isSetVideoSizeSupportedByCamera
, sizes
);
299 bool isCameraParamChanged
= false;
300 if (width
!= -1 && height
!= -1) {
301 if (!isVideoSizeSupported(width
, height
, sizes
)) {
302 CS_LOGE("Video dimension (%dx%d) is unsupported", width
, height
);
305 if (isSetVideoSizeSupportedByCamera
) {
306 params
->setVideoSize(width
, height
);
308 params
->setPreviewSize(width
, height
);
310 isCameraParamChanged
= true;
311 } else if ((width
== -1 && height
!= -1) ||
312 (width
!= -1 && height
== -1)) {
313 // If one and only one of the width and height is -1
314 // we reject such a request.
315 CS_LOGE("Requested video size (%dx%d) is not supported", width
, height
);
317 } else { // width == -1 && height == -1
318 // Do not configure the camera.
319 // Use the current width and height value setting from the camera.
322 if (frameRate
!= -1) {
323 CHECK(frameRate
> 0 && frameRate
<= 120);
324 const char* supportedFrameRates
=
325 params
->get(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES
);
326 CHECK(supportedFrameRates
!= NULL
);
327 CS_LOGV("Supported frame rates: %s", supportedFrameRates
);
329 snprintf(buf
, 4, "%d", frameRate
);
330 if (strstr(supportedFrameRates
, buf
) == NULL
) {
331 CS_LOGE("Requested frame rate (%d) is not supported: %s",
332 frameRate
, supportedFrameRates
);
336 // The frame rate is supported, set the camera to the requested value.
337 params
->setPreviewFrameRate(frameRate
);
338 isCameraParamChanged
= true;
339 } else { // frameRate == -1
340 // Do not configure the camera.
341 // Use the current frame rate value setting from the camera
344 if (isCameraParamChanged
) {
345 // Either frame rate or frame size needs to be changed.
346 if (OK
!= mCameraHw
->PushParameters(*params
)) {
347 CS_LOGE("Could not change settings."
348 " Someone else is using camera?");
356 * Check whether the requested video frame size
357 * has been successfully configured or not. If both width and height
358 * are -1, check on the current width and height value setting
361 * @param params CameraParameters to retrieve the information
362 * @param the target video frame width in pixels to check against
363 * @param the target video frame height in pixels to check against
364 * @return OK if no error
366 status_t
GonkCameraSource::checkVideoSize(
367 const CameraParameters
& params
,
368 int32_t width
, int32_t height
) {
370 CS_LOGV("checkVideoSize");
371 // The actual video size is the same as the preview size
372 // if the camera hal does not support separate video and
373 // preview output. In this case, we retrieve the video
374 // size from preview.
375 int32_t frameWidthActual
= -1;
376 int32_t frameHeightActual
= -1;
378 params
.getSupportedVideoSizes(sizes
);
379 if (sizes
.size() == 0) {
380 // video size is the same as preview size
381 params
.getPreviewSize(&frameWidthActual
, &frameHeightActual
);
383 // video size may not be the same as preview
384 params
.getVideoSize(&frameWidthActual
, &frameHeightActual
);
386 if (frameWidthActual
< 0 || frameHeightActual
< 0) {
387 CS_LOGE("Failed to retrieve video frame size (%dx%d)",
388 frameWidthActual
, frameHeightActual
);
389 return UNKNOWN_ERROR
;
392 // Check the actual video frame size against the target/requested
394 if (width
!= -1 && height
!= -1) {
395 if (frameWidthActual
!= width
|| frameHeightActual
!= height
) {
396 CS_LOGE("Failed to set video frame size to %dx%d. "
397 "The actual video size is %dx%d ", width
, height
,
398 frameWidthActual
, frameHeightActual
);
399 return UNKNOWN_ERROR
;
404 mVideoSize
.width
= frameWidthActual
;
405 mVideoSize
.height
= frameHeightActual
;
410 * Check the requested frame rate has been successfully configured or not.
411 * If the target frameRate is -1, check on the current frame rate value
412 * setting is performed.
414 * @param params CameraParameters to retrieve the information
415 * @param the target video frame rate to check against
416 * @return OK if no error.
418 status_t
GonkCameraSource::checkFrameRate(
419 const CameraParameters
& params
,
422 CS_LOGV("checkFrameRate");
423 int32_t frameRateActual
= params
.getPreviewFrameRate();
424 if (frameRateActual
< 0) {
425 CS_LOGE("Failed to retrieve preview frame rate (%d)", frameRateActual
);
426 return UNKNOWN_ERROR
;
429 // Check the actual video frame rate against the target/requested
431 if (frameRate
!= -1 && (frameRateActual
- frameRate
) != 0) {
432 CS_LOGE("Failed to set preview frame rate to %d fps. The actual "
433 "frame rate is %d", frameRate
, frameRateActual
);
434 return UNKNOWN_ERROR
;
438 mVideoFrameRate
= frameRateActual
;
443 * Initialize the GonkCameraSource so that it becomes
444 * ready for providing the video input streams as requested.
445 * @param camera the camera object used for the video source
446 * @param cameraId if camera == 0, use camera with this id
447 * as the video source
448 * @param videoSize the target video frame size. If both
449 * width and height in videoSize is -1, use the current
450 * width and heigth settings by the camera
451 * @param frameRate the target frame rate in frames per second.
452 * if it is -1, use the current camera frame rate setting.
453 * @param storeMetaDataInVideoBuffers request to store meta
454 * data or real YUV data in video buffers. Request to
455 * store meta data in video buffers may not be honored
456 * if the source does not support this feature.
458 * @return OK if no error.
460 status_t
GonkCameraSource::init(
463 bool storeMetaDataInVideoBuffers
) {
467 //TODO: need to do something here to check the sanity of camera
469 CameraParameters params
;
470 mCameraHw
->PullParameters(params
);
471 if ((err
= isCameraColorFormatSupported(params
)) != OK
) {
475 // Set the camera to use the requested video frame size
476 // and/or frame rate.
477 if ((err
= configureCamera(¶ms
,
478 videoSize
.width
, videoSize
.height
,
483 // Check on video frame size and frame rate.
484 CameraParameters newCameraParams
;
485 mCameraHw
->PullParameters(newCameraParams
);
486 if ((err
= checkVideoSize(newCameraParams
,
487 videoSize
.width
, videoSize
.height
)) != OK
) {
490 if ((err
= checkFrameRate(newCameraParams
, frameRate
)) != OK
) {
494 // By default, do not store metadata in video buffers
495 mIsMetaDataStoredInVideoBuffers
= false;
496 mCameraHw
->StoreMetaDataInBuffers(false);
497 if (storeMetaDataInVideoBuffers
) {
498 if (OK
== mCameraHw
->StoreMetaDataInBuffers(true)) {
499 mIsMetaDataStoredInVideoBuffers
= true;
503 int64_t glitchDurationUs
= (1000000LL / mVideoFrameRate
);
504 if (glitchDurationUs
> mGlitchDurationThresholdUs
) {
505 mGlitchDurationThresholdUs
= glitchDurationUs
;
508 // XXX: query camera for the stride and slice height
509 // when the capability becomes available.
510 mMeta
= new MetaData
;
511 mMeta
->setCString(kKeyMIMEType
, MEDIA_MIMETYPE_VIDEO_RAW
);
512 mMeta
->setInt32(kKeyColorFormat
, mColorFormat
);
513 mMeta
->setInt32(kKeyWidth
, mVideoSize
.width
);
514 mMeta
->setInt32(kKeyHeight
, mVideoSize
.height
);
515 mMeta
->setInt32(kKeyStride
, mVideoSize
.width
);
516 mMeta
->setInt32(kKeySliceHeight
, mVideoSize
.height
);
517 mMeta
->setInt32(kKeyFrameRate
, mVideoFrameRate
);
521 GonkCameraSource::~GonkCameraSource() {
524 } else if (mInitCheck
== OK
) {
525 // Camera is initialized but because start() is never called,
526 // the lock on Camera is never released(). This makes sure
527 // Camera's lock is released in this case.
528 // TODO: Don't think I need to do this
533 int GonkCameraSource::startCameraRecording() {
534 CS_LOGV("startCameraRecording");
535 return mCameraHw
->StartRecording();
538 status_t
GonkCameraSource::start(MetaData
*meta
) {
543 if (mInitCheck
!= OK
) {
544 CS_LOGE("GonkCameraSource is not initialized yet");
548 char value
[PROPERTY_VALUE_MAX
];
549 if (property_get("media.stagefright.record-stats", value
, NULL
)
550 && (!strcmp(value
, "1") || !strcasecmp(value
, "true"))) {
551 mCollectStats
= true;
555 mNumInputBuffers
= 0;
558 if (meta
->findInt64(kKeyTime
, &startTimeUs
)) {
559 mStartTimeUs
= startTimeUs
;
561 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
563 if (meta
->findInt32(kKeyNumBuffers
, &nBuffers
)) {
564 CHECK_GT(nBuffers
, 0);
565 mNumInputBuffers
= nBuffers
;
570 // Register a listener with GonkCameraHardware so that we can get callbacks
571 mCameraHw
->SetListener(new GonkCameraSourceListener(this));
573 rv
= startCameraRecording();
575 mStarted
= (rv
== OK
);
579 void GonkCameraSource::stopCameraRecording() {
580 CS_LOGV("stopCameraRecording");
581 mCameraHw
->StopRecording();
584 void GonkCameraSource::releaseCamera() {
585 CS_LOGV("releaseCamera");
588 status_t
GonkCameraSource::reset() {
590 Mutex::Autolock
autoLock(mLock
);
592 mFrameAvailableCondition
.signal();
594 releaseQueuedFrames();
595 while (!mFramesBeingEncoded
.empty()) {
597 mFrameCompleteCondition
.waitRelative(mLock
,
598 mTimeBetweenFrameCaptureUs
* 1000LL + CAMERA_SOURCE_TIMEOUT_NS
)) {
599 CS_LOGW("Timed out waiting for outstanding frames being encoded: %d",
600 mFramesBeingEncoded
.size());
603 stopCameraRecording();
606 mCameraHw
->OnRateLimitPreview(false);
610 if (mDirectBufferListener
.get()) {
611 mDirectBufferListener
= nullptr;
615 CS_LOGI("Frames received/encoded/dropped: %d/%d/%d in %lld us",
616 mNumFramesReceived
, mNumFramesEncoded
, mNumFramesDropped
,
617 mLastFrameTimestampUs
- mFirstFrameTimeUs
);
620 if (mNumGlitches
> 0) {
621 CS_LOGW("%d long delays between neighboring video frames", mNumGlitches
);
624 CHECK_EQ(mNumFramesReceived
, mNumFramesEncoded
+ mNumFramesDropped
);
629 void GonkCameraSource::releaseRecordingFrame(const sp
<IMemory
>& frame
) {
630 CS_LOGV("releaseRecordingFrame");
631 mCameraHw
->ReleaseRecordingFrame(frame
);
634 void GonkCameraSource::releaseQueuedFrames() {
635 List
<sp
<IMemory
> >::iterator it
;
636 while (!mFramesReceived
.empty()) {
637 it
= mFramesReceived
.begin();
638 releaseRecordingFrame(*it
);
639 mFramesReceived
.erase(it
);
644 sp
<MetaData
> GonkCameraSource::getFormat() {
648 void GonkCameraSource::releaseOneRecordingFrame(const sp
<IMemory
>& frame
) {
649 releaseRecordingFrame(frame
);
652 void GonkCameraSource::signalBufferReturned(MediaBuffer
*buffer
) {
653 CS_LOGV("signalBufferReturned: %p", buffer
->data());
654 Mutex::Autolock
autoLock(mLock
);
655 for (List
<sp
<IMemory
> >::iterator it
= mFramesBeingEncoded
.begin();
656 it
!= mFramesBeingEncoded
.end(); ++it
) {
657 if ((*it
)->pointer() == buffer
->data()) {
658 releaseOneRecordingFrame((*it
));
659 mFramesBeingEncoded
.erase(it
);
661 buffer
->setObserver(0);
663 mFrameCompleteCondition
.signal();
667 CHECK(!"signalBufferReturned: bogus buffer");
670 status_t
GonkCameraSource::AddDirectBufferListener(DirectBufferListener
* aListener
) {
671 if (mDirectBufferListener
.get()) {
672 return UNKNOWN_ERROR
;
674 mDirectBufferListener
= aListener
;
678 status_t
GonkCameraSource::read(
679 MediaBuffer
**buffer
, const ReadOptions
*options
) {
685 ReadOptions::SeekMode mode
;
686 if (options
&& options
->getSeekTo(&seekTimeUs
, &mode
)) {
687 return ERROR_UNSUPPORTED
;
694 Mutex::Autolock
autoLock(mLock
);
695 while (mStarted
&& mFramesReceived
.empty()) {
697 mFrameAvailableCondition
.waitRelative(mLock
,
698 mTimeBetweenFrameCaptureUs
* 1000LL + CAMERA_SOURCE_TIMEOUT_NS
)) {
699 //TODO: check sanity of camera?
700 CS_LOGW("Timed out waiting for incoming camera video frames: %lld us",
701 mLastFrameTimestampUs
);
707 frame
= *mFramesReceived
.begin();
708 mFramesReceived
.erase(mFramesReceived
.begin());
710 frameTime
= *mFrameTimes
.begin();
711 mFrameTimes
.erase(mFrameTimes
.begin());
712 mFramesBeingEncoded
.push_back(frame
);
713 *buffer
= new MediaBuffer(frame
->pointer(), frame
->size());
714 (*buffer
)->setObserver(this);
715 (*buffer
)->add_ref();
716 (*buffer
)->meta_data()->setInt64(kKeyTime
, frameTime
);
721 void GonkCameraSource::dataCallbackTimestamp(int64_t timestampUs
,
722 int32_t msgType
, const sp
<IMemory
> &data
) {
725 CS_LOGV("dataCallbackTimestamp: timestamp %lld us", timestampUs
);
727 Mutex::Autolock
autoLock(mLock
);
728 if (!mStarted
|| (mNumFramesReceived
== 0 && timestampUs
< mStartTimeUs
)) {
729 CS_LOGV("Drop frame at %lld/%lld us", timestampUs
, mStartTimeUs
);
730 releaseOneRecordingFrame(data
);
734 if (mNumFramesReceived
> 0) {
735 if (timestampUs
<= mLastFrameTimestampUs
) {
736 CS_LOGE("Drop frame at %lld us, before last at %lld us",
737 timestampUs
, mLastFrameTimestampUs
);
738 releaseOneRecordingFrame(data
);
741 if (timestampUs
- mLastFrameTimestampUs
> mGlitchDurationThresholdUs
) {
746 // May need to skip frame or modify timestamp. Currently implemented
747 // by the subclass CameraSourceTimeLapse.
748 if (skipCurrentFrame(timestampUs
)) {
749 releaseOneRecordingFrame(data
);
753 mLastFrameTimestampUs
= timestampUs
;
754 if (mNumFramesReceived
== 0) {
755 mFirstFrameTimeUs
= timestampUs
;
757 if (mStartTimeUs
> 0) {
758 if (timestampUs
< mStartTimeUs
) {
759 // Frame was captured before recording was started
760 // Drop it without updating the statistical data.
761 releaseOneRecordingFrame(data
);
764 mStartTimeUs
= timestampUs
- mStartTimeUs
;
767 ++mNumFramesReceived
;
769 // If a backlog is building up in the receive queue, we are likely
770 // resource constrained and we need to throttle
771 prevRateLimit
= mRateLimit
;
772 rateLimit
= mFramesReceived
.empty();
773 mRateLimit
= rateLimit
;
775 CHECK(data
!= NULL
&& data
->size() > 0);
776 mFramesReceived
.push_back(data
);
777 int64_t timeUs
= mStartTimeUs
+ (timestampUs
- mFirstFrameTimeUs
);
778 mFrameTimes
.push_back(timeUs
);
779 CS_LOGV("initial delay: %lld, current time stamp: %lld",
780 mStartTimeUs
, timeUs
);
781 mFrameAvailableCondition
.signal();
784 if(prevRateLimit
!= rateLimit
) {
785 mCameraHw
->OnRateLimitPreview(rateLimit
);
788 if (mDirectBufferListener
.get()) {
789 MediaBuffer
* mediaBuffer
;
790 if (read(&mediaBuffer
) == OK
) {
791 mDirectBufferListener
->BufferAvailable(mediaBuffer
);
792 // read() calls MediaBuffer->add_ref() so it needs to be released here.
793 mediaBuffer
->release();
798 bool GonkCameraSource::isMetaDataStoredInVideoBuffers() const {
799 CS_LOGV("isMetaDataStoredInVideoBuffers");
800 return mIsMetaDataStoredInVideoBuffers
;
803 } // namespace android