Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0c128b67 authored by James Dong's avatar James Dong
Browse files

Move Camera specific logic out from StagefrightRecorder to CameraSource

o updated comments and streamlined the logic in
  checkVideoSize() and checkFrameRate() as suggested

Change-Id: I49d04ac7998d4a215997aa63555dfb6e814e38d3
parent 54ca811b
Loading
Loading
Loading
Loading
+79 −4
Original line number Diff line number Diff line
@@ -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:
    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 &);
};
+14 −13
Original line number Diff line number Diff line
@@ -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
+11 −161
Original line number Diff line number Diff line
@@ -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);
+2 −11
Original line number Diff line number Diff line
@@ -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(
+345 −37

File changed.

Preview size limit exceeded, changes collapsed.

Loading