blob: c2e75a61c602e0a18ff202e3d68edc7a21f79ffd [file] [log] [blame]
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef CAMERA_SOURCE_H_
#define CAMERA_SOURCE_H_
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaSource.h>
#include <camera/android/hardware/ICamera.h>
#include <camera/ICameraRecordingProxy.h>
#include <camera/ICameraRecordingProxyListener.h>
#include <camera/CameraParameters.h>
#include <gui/BufferItemConsumer.h>
#include <utils/List.h>
#include <utils/RefBase.h>
#include <utils/String16.h>
#include <MetadataBufferType.h>
namespace android {
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.
*
* @param clientName The package/process name of the client application.
* This is used for permissions checking.
* @return NULL on error.
*/
static CameraSource *Create(const String16 &clientName);
/**
* 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 clientName the package/process name of the camera-using
* application if camera is NULL; otherwise ignored. Used for
* permissions checking.
* @param clientUid the UID of the camera-using application if camera is
* NULL; otherwise ignored. Used for permissions checking.
* @param clientPid the PID of the camera-using application if camera is
* NULL; otherwise ignored. Used for permissions checking.
* @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
* @param storeMetaDataInVideoBuffers true to request the camera
* source to store meta data in video buffers; false to
* request the camera source to store real YUV frame data
* in the video buffers. The camera source may not support
* storing meta data in video buffers, if so, a request
* to do that will NOT be honored. To find out whether
* meta data is actually being stored in video buffers
* during recording, call isMetaDataStoredInVideoBuffers().
*
* @return NULL on error.
*/
static CameraSource *CreateFromCamera(const sp<hardware::ICamera> &camera,
const sp<ICameraRecordingProxy> &proxy,
int32_t cameraId,
const String16& clientName,
uid_t clientUid,
pid_t clientPid,
Size videoSize,
int32_t frameRate,
const sp<IGraphicBufferProducer>& surface,
bool storeMetaDataInVideoBuffers = true);
virtual ~CameraSource();
virtual status_t start(MetaData *params = NULL);
virtual status_t stop() { return reset(); }
virtual status_t read(
MediaBuffer **buffer, const ReadOptions *options = NULL);
/**
* 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 to be MEDIA_MIMETYPE_VIDEO_RAW
*/
virtual sp<MetaData> getFormat();
/**
* Tell whether this camera source stores meta data or real YUV
* frame data in video buffers.
*
* @return a valid type if meta data is stored in the video
* buffers; kMetadataBufferTypeInvalid if real YUV data is stored in
* the video buffers.
*/
MetadataBufferType metaDataStoredInVideoBuffers() const;
virtual void signalBufferReturned(MediaBuffer* buffer);
protected:
/**
* The class for listening to BnCameraRecordingProxyListener. This is used to receive video
* buffers in VIDEO_BUFFER_MODE_DATA_CALLBACK_YUV and VIDEO_BUFFER_MODE_DATA_CALLBACK_METADATA
* mode. When a frame is available, CameraSource::dataCallbackTimestamp() will be called.
*/
class ProxyListener: public BnCameraRecordingProxyListener {
public:
ProxyListener(const sp<CameraSource>& source);
virtual void dataCallbackTimestamp(int64_t timestampUs, int32_t msgType,
const sp<IMemory> &data);
virtual void recordingFrameHandleCallbackTimestamp(int64_t timestampUs,
native_handle_t* handle);
private:
sp<CameraSource> mSource;
};
/**
* The class for listening to BufferQueue's onFrameAvailable. This is used to receive video
* buffers in VIDEO_BUFFER_MODE_BUFFER_QUEUE mode. When a frame is available,
* CameraSource::processBufferQueueFrame() will be called.
*/
class BufferQueueListener : public Thread, public BufferItemConsumer::FrameAvailableListener {
public:
BufferQueueListener(const sp<BufferItemConsumer> &consumer,
const sp<CameraSource> &cameraSource);
virtual void onFrameAvailable(const BufferItem& item);
virtual bool threadLoop();
private:
static const nsecs_t kFrameAvailableTimeout = 50000000; // 50ms
sp<BufferItemConsumer> mConsumer;
sp<CameraSource> mCameraSource;
Mutex mLock;
Condition mFrameAvailableSignal;
bool mFrameAvailable;
};
// isBinderAlive needs linkToDeath to work.
class DeathNotifier: public IBinder::DeathRecipient {
public:
DeathNotifier() {}
virtual void binderDied(const wp<IBinder>& who);
};
enum CameraFlags {
FLAGS_SET_CAMERA = 1L << 0,
FLAGS_HOT_CAMERA = 1L << 1,
};
int32_t mCameraFlags;
Size mVideoSize;
int32_t mNumInputBuffers;
int32_t mVideoFrameRate;
int32_t mColorFormat;
int32_t mEncoderFormat;
int32_t mEncoderDataSpace;
status_t mInitCheck;
sp<Camera> mCamera;
sp<ICameraRecordingProxy> mCameraRecordingProxy;
sp<DeathNotifier> mDeathNotifier;
sp<IGraphicBufferProducer> mSurface;
sp<MetaData> mMeta;
int64_t mStartTimeUs;
int32_t mNumFramesReceived;
int64_t mLastFrameTimestampUs;
bool mStarted;
int32_t mNumFramesEncoded;
// Time between capture of two frames.
int64_t mTimeBetweenFrameCaptureUs;
CameraSource(const sp<hardware::ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
int32_t cameraId, const String16& clientName, uid_t clientUid, pid_t clientPid,
Size videoSize, int32_t frameRate,
const sp<IGraphicBufferProducer>& surface,
bool storeMetaDataInVideoBuffers);
virtual status_t startCameraRecording();
virtual void releaseRecordingFrame(const sp<IMemory>& frame);
virtual void releaseRecordingFrameHandle(native_handle_t* handle);
// Returns true if need to skip the current frame.
// Called from dataCallbackTimestamp.
virtual bool skipCurrentFrame(int64_t timestampUs) {return false;}
// Callback called when still camera raw data is available.
virtual void dataCallback(int32_t msgType, const sp<IMemory> &data) {}
virtual void dataCallbackTimestamp(int64_t timestampUs, int32_t msgType,
const sp<IMemory> &data);
virtual void recordingFrameHandleCallbackTimestamp(int64_t timestampUs,
native_handle_t* handle);
// Process a buffer item received in BufferQueueListener.
virtual void processBufferQueueFrame(BufferItem& buffer);
void releaseCamera();
private:
friend struct CameraSourceListener;
Mutex mLock;
Condition mFrameAvailableCondition;
Condition mFrameCompleteCondition;
List<sp<IMemory> > mFramesReceived;
List<sp<IMemory> > mFramesBeingEncoded;
List<int64_t> mFrameTimes;
int64_t mFirstFrameTimeUs;
int32_t mNumFramesDropped;
int32_t mNumGlitches;
int64_t mGlitchDurationThresholdUs;
bool mCollectStats;
// The mode video buffers are received from camera. One of VIDEO_BUFFER_MODE_*.
int32_t mVideoBufferMode;
static const uint32_t kDefaultVideoBufferCount = 32;
/**
* The following variables are used in VIDEO_BUFFER_MODE_BUFFER_QUEUE mode.
*/
static const size_t kConsumerBufferCount = 8;
static const nsecs_t kMemoryBaseAvailableTimeoutNs = 200000000; // 200ms
// Consumer and producer of the buffer queue between this class and camera.
sp<BufferItemConsumer> mVideoBufferConsumer;
sp<IGraphicBufferProducer> mVideoBufferProducer;
// Memory used to send the buffers to encoder, where sp<IMemory> stores VideoNativeMetadata.
sp<IMemoryHeap> mMemoryHeapBase;
List<sp<IMemory>> mMemoryBases;
// The condition that will be signaled when there is an entry available in mMemoryBases.
Condition mMemoryBaseAvailableCond;
// A mapping from ANativeWindowBuffer sent to encoder to BufferItem received from camera.
// This is protected by mLock.
KeyedVector<ANativeWindowBuffer*, BufferItem> mReceivedBufferItemMap;
sp<BufferQueueListener> mBufferQueueListener;
void releaseQueuedFrames();
void releaseOneRecordingFrame(const sp<IMemory>& frame);
void createVideoBufferMemoryHeap(size_t size, uint32_t bufferCount);
status_t init(const sp<hardware::ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
int32_t cameraId, const String16& clientName, uid_t clientUid, pid_t clientPid,
Size videoSize, int32_t frameRate, bool storeMetaDataInVideoBuffers);
status_t initWithCameraAccess(
const sp<hardware::ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
int32_t cameraId, const String16& clientName, uid_t clientUid, pid_t clientPid,
Size videoSize, int32_t frameRate, bool storeMetaDataInVideoBuffers);
// Initialize the buffer queue used in VIDEO_BUFFER_MODE_BUFFER_QUEUE mode.
status_t initBufferQueue(uint32_t width, uint32_t height, uint32_t format,
android_dataspace dataSpace, uint32_t bufferCount);
status_t isCameraAvailable(const sp<hardware::ICamera>& camera,
const sp<ICameraRecordingProxy>& proxy,
int32_t cameraId,
const String16& clientName,
uid_t clientUid,
pid_t clientPid);
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);
// Check if this frame should be skipped based on the frame's timestamp in microsecond.
// mLock must be locked before calling this function.
bool shouldSkipFrameLocked(int64_t timestampUs);
void stopCameraRecording();
status_t reset();
CameraSource(const CameraSource &);
CameraSource &operator=(const CameraSource &);
};
} // namespace android
#endif // CAMERA_SOURCE_H_