Merge "Move Camera specific logic out from StagefrightRecorder to CameraSource"

This commit is contained in:
James Dong
2010-10-08 18:39:13 -07:00
committed by Android (Google) Code Review
6 changed files with 484 additions and 261 deletions

View File

@@ -20,25 +20,71 @@
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaSource.h>
#include <camera/ICamera.h>
#include <camera/CameraParameters.h>
#include <utils/List.h>
#include <utils/RefBase.h>
namespace android {
class ICamera;
class IMemory;
class Camera;
class Surface;
class CameraSource : public MediaSource, public MediaBufferObserver {
public:
/**
* Factory method to create a new CameraSource using the current
* settings (such as video size, frame rate, color format, etc)
* from the default camera.
*
* @return NULL on error.
*/
static CameraSource *Create();
static CameraSource *CreateFromCamera(const sp<Camera> &camera);
/**
* Factory method to create a new CameraSource.
*
* @param camera the video input frame data source. If it is NULL,
* we will try to connect to the camera with the given
* cameraId.
*
* @param cameraId the id of the camera that the source will connect
* to if camera is NULL; otherwise ignored.
*
* @param videoSize the dimension (in pixels) of the video frame
* @param frameRate the target frames per second
* @param surface the preview surface for display where preview
* frames are sent to
*
* @return NULL on error.
*/
static CameraSource *CreateFromCamera(const sp<ICamera> &camera,
int32_t cameraId,
Size videoSize,
int32_t frameRate,
const sp<Surface>& surface);
virtual ~CameraSource();
virtual status_t start(MetaData *params = NULL);
virtual status_t stop();
/**
* Check whether a CameraSource object is properly initialized.
* Must call this method before stop().
* @return OK if initialization has successfully completed.
*/
virtual status_t initCheck() const;
/**
* Returns the MetaData associated with the CameraSource,
* including:
* kKeyColorFormat: YUV color format of the video frames
* kKeyWidth, kKeyHeight: dimension (in pixels) of the video frames
* kKeySampleRate: frame rate in frames per second
* kKeyMimeType: always fixed
*/
virtual sp<MetaData> getFormat();
virtual status_t read(
@@ -47,7 +93,19 @@ public:
virtual void signalBufferReturned(MediaBuffer* buffer);
protected:
sp<Camera> mCamera;
enum CameraFlags {
FLAGS_SET_CAMERA = 1L << 0,
FLAGS_HOT_CAMERA = 1L << 1,
};
int32_t mCameraFlags;
Size mVideoSize;
int32_t mVideoFrameRate;
int32_t mColorFormat;
status_t mInitCheck;
sp<Camera> mCamera;
sp<Surface> mSurface;
sp<MetaData> mMeta;
int64_t mStartTimeUs;
@@ -55,7 +113,9 @@ protected:
int64_t mLastFrameTimestampUs;
bool mStarted;
CameraSource(const sp<Camera> &camera);
CameraSource(const sp<ICamera>& camera, int32_t cameraId,
Size videoSize, int32_t frameRate,
const sp<Surface>& surface);
virtual void startCameraRecording();
virtual void stopCameraRecording();
@@ -91,6 +151,21 @@ private:
void releaseQueuedFrames();
void releaseOneRecordingFrame(const sp<IMemory>& frame);
status_t init(const sp<ICamera>& camera, int32_t cameraId,
Size videoSize, int32_t frameRate);
status_t isCameraAvailable(const sp<ICamera>& camera, int32_t cameraId);
status_t isCameraColorFormatSupported(const CameraParameters& params);
status_t configureCamera(CameraParameters* params,
int32_t width, int32_t height,
int32_t frameRate);
status_t checkVideoSize(const CameraParameters& params,
int32_t width, int32_t height);
status_t checkFrameRate(const CameraParameters& params,
int32_t frameRate);
CameraSource(const CameraSource &);
CameraSource &operator=(const CameraSource &);
};

View File

@@ -31,15 +31,13 @@ class Camera;
class CameraSourceTimeLapse : public CameraSource {
public:
static CameraSourceTimeLapse *Create(
int64_t timeBetweenTimeLapseFrameCaptureUs,
int32_t width, int32_t height,
int32_t videoFrameRate);
static CameraSourceTimeLapse *CreateFromCamera(const sp<Camera> &camera,
int64_t timeBetweenTimeLapseFrameCaptureUs,
int32_t width, int32_t height,
int32_t videoFrameRate);
static CameraSourceTimeLapse *CreateFromCamera(
const sp<ICamera> &camera,
int32_t cameraId,
Size videoSize,
int32_t videoFrameRate,
const sp<Surface>& surface,
int64_t timeBetweenTimeLapseFrameCaptureUs);
virtual ~CameraSourceTimeLapse();
@@ -132,10 +130,13 @@ private:
// Status code for last read.
status_t mLastReadStatus;
CameraSourceTimeLapse(const sp<Camera> &camera,
int64_t timeBetweenTimeLapseFrameCaptureUs,
int32_t width, int32_t height,
int32_t videoFrameRate);
CameraSourceTimeLapse(
const sp<ICamera> &camera,
int32_t cameraId,
Size videoSize,
int32_t videoFrameRate,
const sp<Surface>& surface,
int64_t timeBetweenTimeLapseFrameCaptureUs);
// Wrapper over CameraSource::signalBufferReturned() to implement quick stop.
// It only handles the case when mLastReadBufferCopy is signalled. Otherwise

View File

@@ -20,7 +20,6 @@
#include "StagefrightRecorder.h"
#include <binder/IPCThreadState.h>
#include <media/stagefright/AudioSource.h>
#include <media/stagefright/AMRWriter.h>
#include <media/stagefright/CameraSource.h>
@@ -35,7 +34,6 @@
#include <media/stagefright/OMXCodec.h>
#include <media/MediaProfiles.h>
#include <camera/ICamera.h>
#include <camera/Camera.h>
#include <camera/CameraParameters.h>
#include <surfaceflinger/Surface.h>
#include <utils/Errors.h>
@@ -184,22 +182,7 @@ status_t StagefrightRecorder::setCamera(const sp<ICamera> &camera) {
return BAD_VALUE;
}
int64_t token = IPCThreadState::self()->clearCallingIdentity();
mFlags &= ~FLAGS_HOT_CAMERA;
mCamera = Camera::create(camera);
if (mCamera == 0) {
LOGE("Unable to connect to camera");
IPCThreadState::self()->restoreCallingIdentity(token);
return -EBUSY;
}
LOGV("Connected to camera");
if (mCamera->previewEnabled()) {
LOGV("camera is hot");
mFlags |= FLAGS_HOT_CAMERA;
}
IPCThreadState::self()->restoreCallingIdentity(token);
mCamera = camera;
return OK;
}
@@ -966,66 +949,7 @@ void StagefrightRecorder::clipVideoFrameWidth() {
}
}
/*
* Check to see whether the requested video width and height is one
* of the supported sizes. It returns true if so; otherwise, it
* returns false.
*/
bool StagefrightRecorder::isVideoSizeSupported(
const Vector<Size>& supportedSizes) const {
LOGV("isVideoSizeSupported");
for (size_t i = 0; i < supportedSizes.size(); ++i) {
if (mVideoWidth == supportedSizes[i].width &&
mVideoHeight == supportedSizes[i].height) {
return true;
}
}
return false;
}
/*
* If the preview and video output is separate, we only set the
* the video size, and applications should set the preview size
* to some proper value, and the recording framework will not
* change the preview size; otherwise, if the video and preview
* output is the same, we need to set the preview to be the same
* as the requested video size.
*
* On return, it also returns whether the setVideoSize() is
* supported.
*/
status_t StagefrightRecorder::setCameraVideoSize(
CameraParameters* params,
bool* isSetVideoSizeSupported) {
LOGV("setCameraVideoSize: %dx%d", mVideoWidth, mVideoHeight);
// Check whether the requested video size is supported
Vector<Size> sizes;
params->getSupportedVideoSizes(sizes);
*isSetVideoSizeSupported = true;
if (sizes.size() == 0) {
LOGD("Camera does not support setVideoSize()");
params->getSupportedPreviewSizes(sizes);
*isSetVideoSizeSupported = false;
}
if (!isVideoSizeSupported(sizes)) {
LOGE("Camera does not support video size (%dx%d)!",
mVideoWidth, mVideoHeight);
return BAD_VALUE;
}
// Actually set the video size
if (isSetVideoSizeSupported) {
params->setVideoSize(mVideoWidth, mVideoHeight);
} else {
params->setPreviewSize(mVideoWidth, mVideoHeight);
}
return OK;
}
status_t StagefrightRecorder::setupCamera() {
status_t StagefrightRecorder::checkVideoEncoderCapabilities() {
if (!mCaptureTimeLapse) {
// Dont clip for time lapse capture as encoder will have enough
// time to encode because of slow capture rate of time lapse.
@@ -1034,67 +958,6 @@ status_t StagefrightRecorder::setupCamera() {
clipVideoFrameWidth();
clipVideoFrameHeight();
}
int64_t token = IPCThreadState::self()->clearCallingIdentity();
if (mCamera == 0) {
mCamera = Camera::connect(mCameraId);
if (mCamera == 0) {
LOGE("Camera connection could not be established.");
return -EBUSY;
}
mFlags &= ~FLAGS_HOT_CAMERA;
mCamera->lock();
}
// Set the actual video recording frame size
CameraParameters params(mCamera->getParameters());
// dont change the preview size because time lapse may be using still camera
// as mVideoWidth, mVideoHeight may correspond to HD resolution not
// supported by the video camera.
bool isSetVideoSizeSupported = false;
if (!mCaptureTimeLapse) {
if (OK != setCameraVideoSize(&params, &isSetVideoSizeSupported)) {
return BAD_VALUE;
}
}
params.setPreviewFrameRate(mFrameRate);
String8 s = params.flatten();
if (OK != mCamera->setParameters(s)) {
LOGE("Could not change settings."
" Someone else is using camera %d?", mCameraId);
return -EBUSY;
}
CameraParameters newCameraParams(mCamera->getParameters());
// Check on video frame size
int frameWidth = 0, frameHeight = 0;
if (isSetVideoSizeSupported) {
newCameraParams.getVideoSize(&frameWidth, &frameHeight);
} else {
newCameraParams.getPreviewSize(&frameWidth, &frameHeight);
}
if (!mCaptureTimeLapse &&
(frameWidth < 0 || frameWidth != mVideoWidth ||
frameHeight < 0 || frameHeight != mVideoHeight)) {
LOGE("Failed to set the video frame size to %dx%d",
mVideoWidth, mVideoHeight);
IPCThreadState::self()->restoreCallingIdentity(token);
return UNKNOWN_ERROR;
}
// Check on video frame rate
int frameRate = newCameraParams.getPreviewFrameRate();
if (frameRate < 0 || (frameRate - mFrameRate) != 0) {
LOGE("Failed to set frame rate to %d fps. The actual "
"frame rate is %d", mFrameRate, frameRate);
}
// This CHECK is good, since we just passed the lock/unlock
// check earlier by calling mCamera->setParameters().
CHECK_EQ(OK, mCamera->setPreviewDisplay(mPreviewSurface));
IPCThreadState::self()->restoreCallingIdentity(token);
return OK;
}
@@ -1116,15 +979,18 @@ void StagefrightRecorder::clipVideoFrameHeight() {
}
status_t StagefrightRecorder::setupCameraSource(sp<CameraSource> *cameraSource) {
status_t err = setupCamera();
if (err != OK) return err;
Size videoSize;
videoSize.width = mVideoWidth;
videoSize.height = mVideoHeight;
if (mCaptureTimeLapse) {
mCameraSourceTimeLapse = CameraSourceTimeLapse::CreateFromCamera(mCamera,
mTimeBetweenTimeLapseFrameCaptureUs, mVideoWidth, mVideoHeight, mFrameRate);
mCameraSourceTimeLapse = CameraSourceTimeLapse::CreateFromCamera(
mCamera, mCameraId,
videoSize, mFrameRate, mPreviewSurface,
mTimeBetweenTimeLapseFrameCaptureUs);
*cameraSource = mCameraSourceTimeLapse;
} else {
*cameraSource = CameraSource::CreateFromCamera(mCamera);
*cameraSource = CameraSource::CreateFromCamera(
mCamera, mCameraId, videoSize, mFrameRate, mPreviewSurface);
}
CHECK(*cameraSource != NULL);
@@ -1411,19 +1277,6 @@ status_t StagefrightRecorder::stop() {
mWriter.clear();
}
if (mCamera != 0) {
LOGV("Disconnect camera");
int64_t token = IPCThreadState::self()->clearCallingIdentity();
if ((mFlags & FLAGS_HOT_CAMERA) == 0) {
LOGV("Camera was cold when we started, stopping preview");
mCamera->stopPreview();
}
mCamera->unlock();
mCamera.clear();
IPCThreadState::self()->restoreCallingIdentity(token);
mFlags = 0;
}
if (mOutputFd >= 0) {
::close(mOutputFd);
mOutputFd = -1;
@@ -1490,7 +1343,6 @@ status_t StagefrightRecorder::reset() {
mOutputFd = -1;
mOutputFdAux = -1;
mFlags = 0;
return OK;
}
@@ -1561,8 +1413,6 @@ status_t StagefrightRecorder::dump(
result.append(buffer);
snprintf(buffer, SIZE, " Camera Id: %d\n", mCameraId);
result.append(buffer);
snprintf(buffer, SIZE, " Camera flags: %d\n", mFlags);
result.append(buffer);
snprintf(buffer, SIZE, " Encoder: %d\n", mVideoEncoder);
result.append(buffer);
snprintf(buffer, SIZE, " Encoder profile: %d\n", mVideoEncoderProfile);

View File

@@ -63,12 +63,7 @@ struct StagefrightRecorder : public MediaRecorderBase {
virtual status_t dump(int fd, const Vector<String16>& args) const;
private:
enum CameraFlags {
FLAGS_SET_CAMERA = 1L << 0,
FLAGS_HOT_CAMERA = 1L << 1,
};
sp<Camera> mCamera;
sp<ICamera> mCamera;
sp<Surface> mPreviewSurface;
sp<IMediaRecorderClient> mListener;
sp<MediaWriter> mWriter, mWriterAux;
@@ -107,7 +102,6 @@ private:
String8 mParams;
int mOutputFd, mOutputFdAux;
int32_t mFlags;
MediaProfiles *mEncoderProfiles;
@@ -125,10 +119,7 @@ private:
status_t startAACRecording();
status_t startRTPRecording();
sp<MediaSource> createAudioSource();
status_t setupCamera();
bool isVideoSizeSupported(const Vector<Size>& supportedSizes) const;
status_t setCameraVideoSize(CameraParameters* params,
bool *isSetVideoSizeSupported);
status_t checkVideoEncoderCapabilities();
status_t setupCameraSource(sp<CameraSource> *cameraSource);
status_t setupAudioEncoder(const sp<MediaWriter>& writer);
status_t setupVideoEncoder(

View File

@@ -27,6 +27,7 @@
#include <media/stagefright/MetaData.h>
#include <camera/Camera.h>
#include <camera/CameraParameters.h>
#include <surfaceflinger/Surface.h>
#include <utils/String8.h>
#include <cutils/properties.h>
@@ -108,28 +109,45 @@ static int32_t getColorFormat(const char* colorFormat) {
CHECK_EQ(0, "Unknown color format");
}
// static
CameraSource *CameraSource::Create() {
sp<Camera> camera = Camera::connect(0);
Size size;
size.width = -1;
size.height = -1;
if (camera.get() == NULL) {
return NULL;
}
return new CameraSource(camera);
sp<ICamera> camera;
return new CameraSource(camera, 0, size, -1, NULL);
}
// static
CameraSource *CameraSource::CreateFromCamera(const sp<Camera> &camera) {
if (camera.get() == NULL) {
return NULL;
}
CameraSource *CameraSource::CreateFromCamera(
const sp<ICamera>& camera,
int32_t cameraId,
Size videoSize,
int32_t frameRate,
const sp<Surface>& surface) {
return new CameraSource(camera);
CameraSource *source = new CameraSource(camera, cameraId,
videoSize, frameRate, surface);
if (source != NULL) {
if (source->initCheck() != OK) {
delete source;
return NULL;
}
}
return source;
}
CameraSource::CameraSource(const sp<Camera> &camera)
: mCamera(camera),
CameraSource::CameraSource(
const sp<ICamera>& camera,
int32_t cameraId,
Size videoSize,
int32_t frameRate,
const sp<Surface>& surface)
: mCameraFlags(0),
mVideoFrameRate(-1),
mCamera(0),
mSurface(surface),
mNumFramesReceived(0),
mLastFrameTimestampUs(0),
mStarted(false),
@@ -140,39 +158,316 @@ CameraSource::CameraSource(const sp<Camera> &camera)
mGlitchDurationThresholdUs(200000),
mCollectStats(false) {
mVideoSize.width = -1;
mVideoSize.height = -1;
mInitCheck = init(camera, cameraId, videoSize, frameRate);
}
status_t CameraSource::initCheck() const {
return mInitCheck;
}
status_t CameraSource::isCameraAvailable(
const sp<ICamera>& camera, int32_t cameraId) {
if (camera == 0) {
mCamera = Camera::connect(cameraId);
mCameraFlags &= ~FLAGS_HOT_CAMERA;
} else {
mCamera = Camera::create(camera);
mCameraFlags |= FLAGS_HOT_CAMERA;
}
// Is camera available?
if (mCamera == 0) {
LOGE("Camera connection could not be established.");
return -EBUSY;
}
if (!(mCameraFlags & FLAGS_HOT_CAMERA)) {
mCamera->lock();
}
return OK;
}
/*
* Check to see whether the requested video width and height is one
* of the supported sizes.
* @param width the video frame width in pixels
* @param height the video frame height in pixels
* @param suppportedSizes the vector of sizes that we check against
* @return true if the dimension (width and height) is supported.
*/
static bool isVideoSizeSupported(
int32_t width, int32_t height,
const Vector<Size>& supportedSizes) {
LOGV("isVideoSizeSupported");
for (size_t i = 0; i < supportedSizes.size(); ++i) {
if (width == supportedSizes[i].width &&
height == supportedSizes[i].height) {
return true;
}
}
return false;
}
/*
* If the preview and video output is separate, we only set the
* the video size, and applications should set the preview size
* to some proper value, and the recording framework will not
* change the preview size; otherwise, if the video and preview
* output is the same, we need to set the preview to be the same
* as the requested video size.
*
*/
/*
* Query the camera to retrieve the supported video frame sizes
* and also to see whether CameraParameters::setVideoSize()
* is supported or not.
* @param params CameraParameters to retrieve the information
* @@param isSetVideoSizeSupported retunrs whether method
* CameraParameters::setVideoSize() is supported or not.
* @param sizes returns the vector of Size objects for the
* supported video frame sizes advertised by the camera.
*/
static void getSupportedVideoSizes(
const CameraParameters& params,
bool *isSetVideoSizeSupported,
Vector<Size>& sizes) {
*isSetVideoSizeSupported = true;
params.getSupportedVideoSizes(sizes);
if (sizes.size() == 0) {
LOGD("Camera does not support setVideoSize()");
params.getSupportedPreviewSizes(sizes);
*isSetVideoSizeSupported = false;
}
}
/*
* Check whether the camera has the supported color format
* @param params CameraParameters to retrieve the information
* @return OK if no error.
*/
status_t CameraSource::isCameraColorFormatSupported(
const CameraParameters& params) {
mColorFormat = getColorFormat(params.get(
CameraParameters::KEY_VIDEO_FRAME_FORMAT));
if (mColorFormat == -1) {
return BAD_VALUE;
}
return OK;
}
/*
* Configure the camera to use the requested video size
* (width and height) and/or frame rate. If both width and
* height are -1, configuration on the video size is skipped.
* if frameRate is -1, configuration on the frame rate
* is skipped. Skipping the configuration allows one to
* use the current camera setting without the need to
* actually know the specific values (see Create() method).
*
* @param params the CameraParameters to be configured
* @param width the target video frame width in pixels
* @param height the target video frame height in pixels
* @param frameRate the target frame rate in frames per second.
* @return OK if no error.
*/
status_t CameraSource::configureCamera(
CameraParameters* params,
int32_t width, int32_t height,
int32_t frameRate) {
Vector<Size> sizes;
bool isSetVideoSizeSupportedByCamera = true;
getSupportedVideoSizes(*params, &isSetVideoSizeSupportedByCamera, sizes);
bool isCameraParamChanged = false;
if (width != -1 && height != -1) {
if (!isVideoSizeSupported(width, height, sizes)) {
LOGE("Video dimension (%dx%d) is unsupported", width, height);
return BAD_VALUE;
}
if (isSetVideoSizeSupportedByCamera) {
params->setVideoSize(width, height);
} else {
params->setPreviewSize(width, height);
}
isCameraParamChanged = true;
} else if ((width == -1 && height != -1) ||
(width != -1 && height == -1)) {
// If one and only one of the width and height is -1
// we reject such a request.
LOGE("Requested video size (%dx%d) is not supported", width, height);
return BAD_VALUE;
} else { // width == -1 && height == -1
// Do not configure the camera.
// Use the current width and height value setting from the camera.
}
if (frameRate != -1) {
params->setPreviewFrameRate(frameRate);
isCameraParamChanged = true;
} else { // frameRate == -1
// Do not configure the camera.
// Use the current frame rate value setting from the camera
}
if (isCameraParamChanged) {
// Either frame rate or frame size needs to be changed.
String8 s = params->flatten();
if (OK != mCamera->setParameters(s)) {
LOGE("Could not change settings."
" Someone else is using camera %p?", mCamera.get());
return -EBUSY;
}
}
return OK;
}
/*
* Check whether the requested video frame size
* has been successfully configured or not. If both width and height
* are -1, check on the current width and height value setting
* is performed.
*
* @param params CameraParameters to retrieve the information
* @param the target video frame width in pixels to check against
* @param the target video frame height in pixels to check against
* @return OK if no error
*/
status_t CameraSource::checkVideoSize(
const CameraParameters& params,
int32_t width, int32_t height) {
int32_t frameWidthActual = -1;
int32_t frameHeightActual = -1;
params.getPreviewSize(&frameWidthActual, &frameHeightActual);
if (frameWidthActual < 0 || frameHeightActual < 0) {
LOGE("Failed to retrieve video frame size (%dx%d)",
frameWidthActual, frameHeightActual);
return UNKNOWN_ERROR;
}
// Check the actual video frame size against the target/requested
// video frame size.
if (width != -1 && height != -1) {
if (frameWidthActual != width || frameHeightActual != height) {
LOGE("Failed to set video frame size to %dx%d. "
"The actual video size is %dx%d ", width, height,
frameWidthActual, frameHeightActual);
return UNKNOWN_ERROR;
}
}
// Good now.
mVideoSize.width = frameWidthActual;
mVideoSize.height = frameHeightActual;
return OK;
}
/*
* Check the requested frame rate has been successfully configured or not.
* If the target frameRate is -1, check on the current frame rate value
* setting is performed.
*
* @param params CameraParameters to retrieve the information
* @param the target video frame rate to check against
* @return OK if no error.
*/
status_t CameraSource::checkFrameRate(
const CameraParameters& params,
int32_t frameRate) {
int32_t frameRateActual = params.getPreviewFrameRate();
if (frameRateActual < 0) {
LOGE("Failed to retrieve preview frame rate (%d)", frameRateActual);
return UNKNOWN_ERROR;
}
// Check the actual video frame rate against the target/requested
// video frame rate.
if (frameRate != -1 && (frameRateActual - frameRate) != 0) {
LOGE("Failed to set preview frame rate to %d fps. The actual "
"frame rate is %d", frameRate, frameRateActual);
return UNKNOWN_ERROR;
}
// Good now.
mVideoFrameRate = frameRateActual;
return OK;
}
/*
* Initialize the CameraSource to so that it becomes
* ready for providing the video input streams as requested.
* @param camera the camera object used for the video source
* @param cameraId if camera == 0, use camera with this id
* as the video source
* @param videoSize the target video frame size. If both
* width and height in videoSize is -1, use the current
* width and heigth settings by the camera
* @param frameRate the target frame rate in frames per second.
* if it is -1, use the current camera frame rate setting.
* @return OK if no error.
*/
status_t CameraSource::init(
const sp<ICamera>& camera,
int32_t cameraId,
Size videoSize,
int32_t frameRate) {
status_t err = OK;
int64_t token = IPCThreadState::self()->clearCallingIdentity();
String8 s = mCamera->getParameters();
if ((err = isCameraAvailable(camera, cameraId)) != OK) {
return err;
}
CameraParameters params(mCamera->getParameters());
if ((err = isCameraColorFormatSupported(params)) != OK) {
return err;
}
// Set the camera to use the requested video frame size
// and/or frame rate.
if ((err = configureCamera(&params,
videoSize.width, videoSize.height,
frameRate))) {
return err;
}
// Check on video frame size and frame rate.
CameraParameters newCameraParams(mCamera->getParameters());
if ((err = checkVideoSize(newCameraParams,
videoSize.width, videoSize.height)) != OK) {
return err;
}
if ((err = checkFrameRate(newCameraParams, frameRate)) != OK) {
return err;
}
// This CHECK is good, since we just passed the lock/unlock
// check earlier by calling mCamera->setParameters().
CHECK_EQ(OK, mCamera->setPreviewDisplay(mSurface));
IPCThreadState::self()->restoreCallingIdentity(token);
printf("params: \"%s\"\n", s.string());
int32_t width, height, stride, sliceHeight;
CameraParameters params(s);
params.getPreviewSize(&width, &height);
// Calculate glitch duraton threshold based on frame rate
int32_t frameRate = params.getPreviewFrameRate();
int64_t glitchDurationUs = (1000000LL / frameRate);
int64_t glitchDurationUs = (1000000LL / mVideoFrameRate);
if (glitchDurationUs > mGlitchDurationThresholdUs) {
mGlitchDurationThresholdUs = glitchDurationUs;
}
const char *colorFormatStr = params.get(CameraParameters::KEY_VIDEO_FRAME_FORMAT);
CHECK(colorFormatStr != NULL);
int32_t colorFormat = getColorFormat(colorFormatStr);
// XXX: query camera for the stride and slice height
// when the capability becomes available.
stride = width;
sliceHeight = height;
mMeta = new MetaData;
mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
mMeta->setInt32(kKeyColorFormat, colorFormat);
mMeta->setInt32(kKeyWidth, width);
mMeta->setInt32(kKeyHeight, height);
mMeta->setInt32(kKeyStride, stride);
mMeta->setInt32(kKeySliceHeight, sliceHeight);
mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
mMeta->setInt32(kKeyColorFormat, mColorFormat);
mMeta->setInt32(kKeyWidth, mVideoSize.width);
mMeta->setInt32(kKeyHeight, mVideoSize.height);
mMeta->setInt32(kKeyStride, mVideoSize.width);
mMeta->setInt32(kKeySliceHeight, mVideoSize.height);
return OK;
}
CameraSource::~CameraSource() {
@@ -187,6 +482,10 @@ void CameraSource::startCameraRecording() {
status_t CameraSource::start(MetaData *meta) {
CHECK(!mStarted);
if (mInitCheck != OK) {
LOGE("CameraSource is not initialized yet");
return mInitCheck;
}
char value[PROPERTY_VALUE_MAX];
if (property_get("media.stagefright.record-stats", value, NULL)
@@ -228,7 +527,16 @@ status_t CameraSource::stop() {
mFramesBeingEncoded.size());
mFrameCompleteCondition.wait(mLock);
}
mCamera = NULL;
LOGV("Disconnect camera");
if ((mCameraFlags & FLAGS_HOT_CAMERA) == 0) {
LOGV("Camera was cold when we started, stopping preview");
mCamera->stopPreview();
}
mCamera->unlock();
mCamera.clear();
mCamera = 0;
mCameraFlags = 0;
IPCThreadState::self()->restoreCallingIdentity(token);
if (mCollectStats) {

View File

@@ -37,57 +37,55 @@
namespace android {
// static
CameraSourceTimeLapse *CameraSourceTimeLapse::Create(
int64_t timeBetweenTimeLapseFrameCaptureUs,
int32_t width, int32_t height,
int32_t videoFrameRate) {
sp<Camera> camera = Camera::connect(0);
CameraSourceTimeLapse *CameraSourceTimeLapse::CreateFromCamera(
const sp<ICamera> &camera,
int32_t cameraId,
Size videoSize,
int32_t videoFrameRate,
const sp<Surface>& surface,
int64_t timeBetweenTimeLapseFrameCaptureUs) {
if (camera.get() == NULL) {
return NULL;
CameraSourceTimeLapse *source = new
CameraSourceTimeLapse(camera, cameraId,
videoSize, videoFrameRate, surface,
timeBetweenTimeLapseFrameCaptureUs);
if (source != NULL) {
if (source->initCheck() != OK) {
delete source;
return NULL;
}
}
return new CameraSourceTimeLapse(camera, timeBetweenTimeLapseFrameCaptureUs,
width, height, videoFrameRate);
return source;
}
// static
CameraSourceTimeLapse *CameraSourceTimeLapse::CreateFromCamera(const sp<Camera> &camera,
int64_t timeBetweenTimeLapseFrameCaptureUs,
int32_t width, int32_t height,
int32_t videoFrameRate) {
if (camera.get() == NULL) {
return NULL;
}
return new CameraSourceTimeLapse(camera, timeBetweenTimeLapseFrameCaptureUs,
width, height, videoFrameRate);
}
CameraSourceTimeLapse::CameraSourceTimeLapse(const sp<Camera> &camera,
int64_t timeBetweenTimeLapseFrameCaptureUs,
int32_t width, int32_t height,
int32_t videoFrameRate)
: CameraSource(camera),
CameraSourceTimeLapse::CameraSourceTimeLapse(
const sp<ICamera>& camera,
int32_t cameraId,
Size videoSize,
int32_t videoFrameRate,
const sp<Surface>& surface,
int64_t timeBetweenTimeLapseFrameCaptureUs)
: CameraSource(camera, cameraId, videoSize, videoFrameRate, surface),
mTimeBetweenTimeLapseFrameCaptureUs(timeBetweenTimeLapseFrameCaptureUs),
mTimeBetweenTimeLapseVideoFramesUs(1E6/videoFrameRate),
mLastTimeLapseFrameRealTimestampUs(0),
mSkipCurrentFrame(false) {
LOGV("starting time lapse mode");
mVideoWidth = width;
mVideoHeight = height;
mVideoWidth = videoSize.width;
mVideoHeight = videoSize.height;
if (trySettingPreviewSize(width, height)) {
if (trySettingPreviewSize(videoSize.width, videoSize.height)) {
mUseStillCameraForTimeLapse = false;
} else {
// TODO: Add a check to see that mTimeBetweenTimeLapseFrameCaptureUs is greater
// than the fastest rate at which the still camera can take pictures.
mUseStillCameraForTimeLapse = true;
CHECK(setPictureSizeToClosestSupported(width, height));
CHECK(setPictureSizeToClosestSupported(videoSize.width, videoSize.height));
mNeedCropping = computeCropRectangleOffset();
mMeta->setInt32(kKeyWidth, width);
mMeta->setInt32(kKeyHeight, height);
mMeta->setInt32(kKeyWidth, videoSize.width);
mMeta->setInt32(kKeyHeight, videoSize.height);
}
// Initialize quick stop variables.