Bumping gaia.json for 1 gaia revision(s) a=gaia-bump
[gecko.git] / dom / camera / GonkCameraSource.cpp
blob9cc6192b3bff267210ec0f3172486658aab99cca
1 /*
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>
19 #include "nsDebug.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;
53 namespace android {
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);
67 protected:
68 virtual ~GonkCameraSourceListener();
70 private:
71 wp<GonkCameraSource> mSource;
73 GonkCameraSourceListener(const GonkCameraSourceListener &);
74 GonkCameraSourceListener &operator=(const GonkCameraSourceListener &);
77 GonkCameraSourceListener::GonkCameraSourceListener(const sp<GonkCameraSource> &source)
78 : mSource(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);
96 return true;
98 return false;
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);
107 return true;
109 return false;
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;
142 #endif
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,
151 Size videoSize,
152 int32_t frameRate,
153 bool storeMetaDataInVideoBuffers) {
155 GonkCameraSource *source = new GonkCameraSource(aCameraHw,
156 videoSize, frameRate,
157 storeMetaDataInVideoBuffers);
158 return source;
161 GonkCameraSource *GonkCameraSource::Create(
162 ICameraControl* aControl,
163 Size videoSize,
164 int32_t frameRate)
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,
173 Size videoSize,
174 int32_t frameRate,
175 bool storeMetaDataInVideoBuffers)
176 : mCameraFlags(0),
177 mNumInputBuffers(0),
178 mVideoFrameRate(-1),
179 mNumFramesReceived(0),
180 mLastFrameTimestampUs(0),
181 mStarted(false),
182 mNumFramesEncoded(0),
183 mTimeBetweenFrameCaptureUs(0),
184 mRateLimit(false),
185 mFirstFrameTimeUs(0),
186 mNumFramesDropped(0),
187 mNumGlitches(0),
188 mGlitchDurationThresholdUs(200000),
189 mCollectStats(false),
190 mCameraHw(aCameraHw) {
191 mVideoSize.width = -1;
192 mVideoSize.height = -1;
194 mInitCheck = init(
195 videoSize, frameRate,
196 storeMetaDataInVideoBuffers);
197 if (mInitCheck != OK) releaseCamera();
200 status_t GonkCameraSource::initCheck() const {
201 return mInitCheck;
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) {
222 return true;
225 return false;
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) {
271 return BAD_VALUE;
273 return OK;
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,
294 int32_t frameRate) {
295 CS_LOGV("configureCamera");
296 Vector<Size> sizes;
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);
303 return BAD_VALUE;
305 if (isSetVideoSizeSupportedByCamera) {
306 params->setVideoSize(width, height);
307 } else {
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);
316 return BAD_VALUE;
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);
328 char buf[4];
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);
333 return BAD_VALUE;
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?");
349 return -EBUSY;
352 return OK;
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
359 * is performed.
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;
377 Vector<Size> sizes;
378 params.getSupportedVideoSizes(sizes);
379 if (sizes.size() == 0) {
380 // video size is the same as preview size
381 params.getPreviewSize(&frameWidthActual, &frameHeightActual);
382 } else {
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
393 // video frame size.
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;
403 // Good now.
404 mVideoSize.width = frameWidthActual;
405 mVideoSize.height = frameHeightActual;
406 return OK;
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,
420 int32_t frameRate) {
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
430 // video frame rate.
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;
437 // Good now.
438 mVideoFrameRate = frameRateActual;
439 return OK;
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(
461 Size videoSize,
462 int32_t frameRate,
463 bool storeMetaDataInVideoBuffers) {
465 CS_LOGV("init");
466 status_t err = OK;
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) {
472 return err;
475 // Set the camera to use the requested video frame size
476 // and/or frame rate.
477 if ((err = configureCamera(&params,
478 videoSize.width, videoSize.height,
479 frameRate))) {
480 return err;
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) {
488 return err;
490 if ((err = checkFrameRate(newCameraParams, frameRate)) != OK) {
491 return err;
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);
518 return OK;
521 GonkCameraSource::~GonkCameraSource() {
522 if (mStarted) {
523 reset();
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
529 releaseCamera();
533 int GonkCameraSource::startCameraRecording() {
534 CS_LOGV("startCameraRecording");
535 return mCameraHw->StartRecording();
538 status_t GonkCameraSource::start(MetaData *meta) {
539 int rv;
541 CS_LOGV("start");
542 CHECK(!mStarted);
543 if (mInitCheck != OK) {
544 CS_LOGE("GonkCameraSource is not initialized yet");
545 return mInitCheck;
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;
554 mStartTimeUs = 0;
555 mNumInputBuffers = 0;
556 if (meta) {
557 int64_t startTimeUs;
558 if (meta->findInt64(kKeyTime, &startTimeUs)) {
559 mStartTimeUs = startTimeUs;
561 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
562 int32_t nBuffers;
563 if (meta->findInt32(kKeyNumBuffers, &nBuffers)) {
564 CHECK_GT(nBuffers, 0);
565 mNumInputBuffers = nBuffers;
567 #endif
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);
576 return rv;
579 void GonkCameraSource::stopCameraRecording() {
580 CS_LOGV("stopCameraRecording");
581 mCameraHw->StopRecording();
584 void GonkCameraSource::releaseCamera() {
585 CS_LOGV("releaseCamera");
588 status_t GonkCameraSource::reset() {
589 CS_LOGD("reset: E");
590 Mutex::Autolock autoLock(mLock);
591 mStarted = false;
592 mFrameAvailableCondition.signal();
594 releaseQueuedFrames();
595 while (!mFramesBeingEncoded.empty()) {
596 if (NO_ERROR !=
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();
604 if (mRateLimit) {
605 mRateLimit = false;
606 mCameraHw->OnRateLimitPreview(false);
608 releaseCamera();
610 if (mDirectBufferListener.get()) {
611 mDirectBufferListener = nullptr;
614 if (mCollectStats) {
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);
625 CS_LOGD("reset: X");
626 return OK;
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);
640 ++mNumFramesDropped;
644 sp<MetaData> GonkCameraSource::getFormat() {
645 return mMeta;
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);
660 ++mNumFramesEncoded;
661 buffer->setObserver(0);
662 buffer->release();
663 mFrameCompleteCondition.signal();
664 return;
667 CHECK(!"signalBufferReturned: bogus buffer");
670 status_t GonkCameraSource::AddDirectBufferListener(DirectBufferListener* aListener) {
671 if (mDirectBufferListener.get()) {
672 return UNKNOWN_ERROR;
674 mDirectBufferListener = aListener;
675 return OK;
678 status_t GonkCameraSource::read(
679 MediaBuffer **buffer, const ReadOptions *options) {
680 CS_LOGV("read");
682 *buffer = NULL;
684 int64_t seekTimeUs;
685 ReadOptions::SeekMode mode;
686 if (options && options->getSeekTo(&seekTimeUs, &mode)) {
687 return ERROR_UNSUPPORTED;
690 sp<IMemory> frame;
691 int64_t frameTime;
694 Mutex::Autolock autoLock(mLock);
695 while (mStarted && mFramesReceived.empty()) {
696 if (NO_ERROR !=
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);
704 if (!mStarted) {
705 return OK;
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);
718 return OK;
721 void GonkCameraSource::dataCallbackTimestamp(int64_t timestampUs,
722 int32_t msgType, const sp<IMemory> &data) {
723 bool rateLimit;
724 bool prevRateLimit;
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);
731 return;
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);
739 return;
741 if (timestampUs - mLastFrameTimestampUs > mGlitchDurationThresholdUs) {
742 ++mNumGlitches;
746 // May need to skip frame or modify timestamp. Currently implemented
747 // by the subclass CameraSourceTimeLapse.
748 if (skipCurrentFrame(timestampUs)) {
749 releaseOneRecordingFrame(data);
750 return;
753 mLastFrameTimestampUs = timestampUs;
754 if (mNumFramesReceived == 0) {
755 mFirstFrameTimeUs = timestampUs;
756 // Initial delay
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);
762 return;
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