diff options
author | Vishal Bhoj <vishal.bhoj@linaro.org> | 2012-01-31 22:13:09 +0530 |
---|---|---|
committer | Vishal Bhoj <vishal.bhoj@linaro.org> | 2012-01-31 22:16:05 +0530 |
commit | 1ad0e928edf6f046572b3f32eb5ee23d8d7f3f79 (patch) | |
tree | 5c4a1c48e7f64ddccbe801a6ba3d16d69e7464ea | |
parent | 120c22ceb513ca37685854e467fb4cb482840d1c (diff) | |
download | common-linaro_android_4.0.3.tar.gz |
camera: Initial changes for ICS supportlinaro_android_4.0.3
Preview,Image capture and apps like
skype, linphone, hangouts are working.
Recording fails.
Change-Id: I4587c31014e40b87146a2cafb294cc33e532a26f
Signed-off-by: Vishal Bhoj <vishal.bhoj@linaro.org>
-rw-r--r-- | libcamera/Android.mk | 59 | ||||
-rw-r--r-- | libcamera/CameraHal.h | 1266 | ||||
-rw-r--r-- | libcamera/CameraHal_Module.cpp | 429 | ||||
-rw-r--r-- | libcamera/CameraHardware.cpp | 163 | ||||
-rw-r--r-- | libcamera/CameraHardware.h | 56 | ||||
-rw-r--r-- | libcamera/CameraHardwareInterface.h | 231 | ||||
-rw-r--r-- | libcamera/V4L2Camera.cpp | 28 | ||||
-rw-r--r-- | libcamera/V4L2Camera.h | 6 | ||||
-rw-r--r-- | libcamera/V4L2CameraHal.h | 151 | ||||
-rw-r--r-- | libcamera/rgbconvert.c | 50 |
10 files changed, 2319 insertions, 120 deletions
diff --git a/libcamera/Android.mk b/libcamera/Android.mk index 9e7dc3e..1275cfa 100644 --- a/libcamera/Android.mk +++ b/libcamera/Android.mk @@ -1,28 +1,37 @@ -ifneq ($(USE_CAMERA_STUB),true) - -LOCAL_PATH := $(call my-dir) - +LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) - -LOCAL_SRC_FILES := \ - CameraHardware.cpp \ - V4L2Camera.cpp \ - convert.S - -LOCAL_C_INCLUDES += external/jpeg - -LOCAL_MODULE := libcamera -LOCAL_MODULE_TAGS := optional -LOCAL_PRELINK_MODULE := false - -LOCAL_SHARED_LIBRARIES := \ - libui \ - libjpeg \ - libutils \ - libbinder \ - libcutils \ - libcamera_client +LOCAL_SRC_FILES:= \ + CameraHal_Module.cpp \ + V4L2Camera.cpp \ + CameraHardware.cpp \ + convert.S \ + rgbconvert.c + +LOCAL_C_INCLUDES += \ + $(LOCAL_PATH)/inc/ \ + hardware/ti/omap4xxx/hwc \ + frameworks/base/include/ui \ + frameworks/base/include/utils \ + hardware/ti/omap4xxx/domx/omx_core/inc \ + hardware/ti/omap4xxx/domx/mm_osal/inc \ + frameworks/base/include/media/stagefright \ + frameworks/base/include/media/stagefright/openmax \ + external/jpeg \ + external/jhead + +LOCAL_SHARED_LIBRARIES:= \ + libui \ + libbinder \ + libutils \ + libcutils \ + libcamera_client \ + libcameraservice \ + libgui \ + libjpeg \ + libexif + +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw +LOCAL_MODULE:= camera.$(TARGET_BOARD_PLATFORM) +LOCAL_MODULE_TAGS:= optional include $(BUILD_SHARED_LIBRARY) - -endif diff --git a/libcamera/CameraHal.h b/libcamera/CameraHal.h new file mode 100644 index 0000000..1ec08cf --- /dev/null +++ b/libcamera/CameraHal.h @@ -0,0 +1,1266 @@ +/* + * Copyright (C) Texas Instruments - http://www.ti.com/ + * + * 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 ANDROID_HARDWARE_CAMERA_HARDWARE_H +#define ANDROID_HARDWARE_CAMERA_HARDWARE_H + +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <time.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <utils/Log.h> +#include <utils/threads.h> +#include <linux/videodev2.h> +#include "binder/MemoryBase.h" +#include "binder/MemoryHeapBase.h" +#include <utils/threads.h> +#include <camera/CameraParameters.h> +#include <hardware/camera.h> +//#include "MessageQueue.h" +//#include "Semaphore.h" +//#include "CameraProperties.h" +//#include "DebugUtils.h" +//#include "SensorListener.h" + +#include <ui/GraphicBufferAllocator.h> +#include <ui/GraphicBuffer.h> + +#define MIN_WIDTH 640 +#define MIN_HEIGHT 480 +#define PICTURE_WIDTH 3264 /* 5mp - 2560. 8mp - 3280 */ /* Make sure it is a multiple of 16. */ +#define PICTURE_HEIGHT 2448 /* 5mp - 2048. 8mp - 2464 */ /* Make sure it is a multiple of 16. */ +#define PREVIEW_WIDTH 176 +#define PREVIEW_HEIGHT 144 +#define PIXEL_FORMAT V4L2_PIX_FMT_UYVY + +#define VIDEO_FRAME_COUNT_MAX 8 //NUM_OVERLAY_BUFFERS_REQUESTED +#define MAX_CAMERA_BUFFERS 8 //NUM_OVERLAY_BUFFERS_REQUESTED +#define MAX_ZOOM 3 +#define THUMB_WIDTH 80 +#define THUMB_HEIGHT 60 +#define PIX_YUV422I 0 +#define PIX_YUV420P 1 + +#define SATURATION_OFFSET 100 +#define SHARPNESS_OFFSET 100 +#define CONTRAST_OFFSET 100 + +#define CAMHAL_GRALLOC_USAGE GRALLOC_USAGE_HW_TEXTURE | \ + GRALLOC_USAGE_HW_RENDER | \ + GRALLOC_USAGE_SW_READ_RARELY | \ + GRALLOC_USAGE_SW_WRITE_NEVER + +//Enables Absolute PPM measurements in logcat +#define PPM_INSTRUMENTATION_ABS 1 + +#define LOCK_BUFFER_TRIES 5 +#define HAL_PIXEL_FORMAT_NV12 0x100 + +#define CAMHAL_LOGI LOGI + +//Uncomment to enable more verbose/debug logs +//#define DEBUG_LOG + +///Camera HAL Logging Functions +#ifndef DEBUG_LOG + +#define CAMHAL_LOGDA(str) +#define CAMHAL_LOGDB(str, ...) +#define CAMHAL_LOGVA(str) +#define CAMHAL_LOGVB(str, ...) + +#define CAMHAL_LOGEA LOGE +#define CAMHAL_LOGEB LOGE + +#undef LOG_FUNCTION_NAME +#undef LOG_FUNCTION_NAME_EXIT +#define LOG_FUNCTION_NAME +#define LOG_FUNCTION_NAME_EXIT + +#else + +#define CAMHAL_LOGDA DBGUTILS_LOGDA +#define CAMHAL_LOGDB DBGUTILS_LOGDB +#define CAMHAL_LOGVA DBGUTILS_LOGVA +#define CAMHAL_LOGVB DBGUTILS_LOGVB + +#define CAMHAL_LOGEA DBGUTILS_LOGEA +#define CAMHAL_LOGEB DBGUTILS_LOGEB + +#endif + + + +#define NONNEG_ASSIGN(x,y) \ + if(x > -1) \ + y = x + +namespace android { + +#define PARAM_BUFFER 6000 + +///Forward declarations +class CameraHal; +class CameraFrame; +class CameraHalEvent; +class DisplayFrame; + +class CameraArea : public RefBase +{ +public: + + CameraArea(ssize_t top, + ssize_t left, + ssize_t bottom, + ssize_t right, + size_t weight) : mTop(top), + mLeft(left), + mBottom(bottom), + mRight(right), + mWeight(weight) {} + + status_t transfrom(size_t width, + size_t height, + size_t &top, + size_t &left, + size_t &areaWidth, + size_t &areaHeight); + + bool isValid() + { + return ( ( 0 != mTop ) || ( 0 != mLeft ) || ( 0 != mBottom ) || ( 0 != mRight) ); + } + + bool isZeroArea() + { + return ( (0 == mTop ) && ( 0 == mLeft ) && ( 0 == mBottom ) + && ( 0 == mRight ) && ( 0 == mWeight )); + } + + size_t getWeight() + { + return mWeight; + } + + bool compare(const sp<CameraArea> &area); + + static status_t parseAreas(const char *area, + size_t areaLength, + Vector< sp<CameraArea> > &areas); + + static status_t checkArea(ssize_t top, + ssize_t left, + ssize_t bottom, + ssize_t right, + ssize_t weight); + + static bool areAreasDifferent(Vector< sp<CameraArea> > &, Vector< sp<CameraArea> > &); + +protected: + static const ssize_t TOP = -1000; + static const ssize_t LEFT = -1000; + static const ssize_t BOTTOM = 1000; + static const ssize_t RIGHT = 1000; + static const ssize_t WEIGHT_MIN = 1; + static const ssize_t WEIGHT_MAX = 1000; + + ssize_t mTop; + ssize_t mLeft; + ssize_t mBottom; + ssize_t mRight; + size_t mWeight; +}; + +class CameraFDResult : public RefBase +{ +public: + + CameraFDResult() : mFaceData(NULL) {}; + CameraFDResult(camera_frame_metadata_t *faces) : mFaceData(faces) {}; + + virtual ~CameraFDResult() { + if ( ( NULL != mFaceData ) && ( NULL != mFaceData->faces ) ) { + free(mFaceData->faces); + free(mFaceData); + mFaceData=NULL; + } + + if(( NULL != mFaceData )) + { + free(mFaceData); + mFaceData = NULL; + } + } + + camera_frame_metadata_t *getFaceResult() { return mFaceData; }; + + static const ssize_t TOP = -1000; + static const ssize_t LEFT = -1000; + static const ssize_t BOTTOM = 1000; + static const ssize_t RIGHT = 1000; + static const ssize_t INVALID_DATA = -2000; + +private: + + camera_frame_metadata_t *mFaceData; +}; + +class CameraFrame +{ + public: + + enum FrameType + { + PREVIEW_FRAME_SYNC = 0x1, ///SYNC implies that the frame needs to be explicitly returned after consuming in order to be filled by camera again + PREVIEW_FRAME = 0x2 , ///Preview frame includes viewfinder and snapshot frames + IMAGE_FRAME_SYNC = 0x4, ///Image Frame is the image capture output frame + IMAGE_FRAME = 0x8, + VIDEO_FRAME_SYNC = 0x10, ///Timestamp will be updated for these frames + VIDEO_FRAME = 0x20, + FRAME_DATA_SYNC = 0x40, ///Any extra data assosicated with the frame. Always synced with the frame + FRAME_DATA= 0x80, + RAW_FRAME = 0x100, + SNAPSHOT_FRAME = 0x200, + ALL_FRAMES = 0xFFFF ///Maximum of 16 frame types supported + }; + + enum FrameQuirks + { + ENCODE_RAW_YUV422I_TO_JPEG = 0x1 << 0, + HAS_EXIF_DATA = 0x1 << 1, + }; + + //default contrustor + CameraFrame(): + mCookie(NULL), + mCookie2(NULL), + mBuffer(NULL), + mFrameType(0), + mTimestamp(0), + mWidth(0), + mHeight(0), + mOffset(0), + mAlignment(0), + mFd(0), + mLength(0), + mFrameMask(0), + mQuirks(0) { + + mYuv[0] = NULL; + mYuv[1] = NULL; + } + + //copy constructor + CameraFrame(const CameraFrame &frame) : + mCookie(frame.mCookie), + mCookie2(frame.mCookie2), + mBuffer(frame.mBuffer), + mFrameType(frame.mFrameType), + mTimestamp(frame.mTimestamp), + mWidth(frame.mWidth), + mHeight(frame.mHeight), + mOffset(frame.mOffset), + mAlignment(frame.mAlignment), + mFd(frame.mFd), + mLength(frame.mLength), + mFrameMask(frame.mFrameMask), + mQuirks(frame.mQuirks) { + + mYuv[0] = frame.mYuv[0]; + mYuv[1] = frame.mYuv[1]; + } + + void *mCookie; + void *mCookie2; + void *mBuffer; + int mFrameType; + nsecs_t mTimestamp; + unsigned int mWidth, mHeight; + uint32_t mOffset; + unsigned int mAlignment; + int mFd; + size_t mLength; + unsigned mFrameMask; + unsigned int mQuirks; + unsigned int mYuv[2]; + ///@todo add other member vars like stride etc +}; + +enum CameraHalError +{ + CAMERA_ERROR_FATAL = 0x1, //Fatal errors can only be recovered by restarting media server + CAMERA_ERROR_HARD = 0x2, // Hard errors are hardware hangs that may be recoverable by resetting the hardware internally within the adapter + CAMERA_ERROR_SOFT = 0x4, // Soft errors are non fatal errors that can be recovered from without needing to stop use-case +}; + +///Common Camera Hal Event class which is visible to CameraAdapter,DisplayAdapter and AppCallbackNotifier +///@todo Rename this class to CameraEvent +class CameraHalEvent +{ +public: + //Enums + enum CameraHalEventType { + NO_EVENTS = 0x0, + EVENT_FOCUS_LOCKED = 0x1, + EVENT_FOCUS_ERROR = 0x2, + EVENT_ZOOM_INDEX_REACHED = 0x4, + EVENT_SHUTTER = 0x8, + EVENT_FACE = 0x10, + ///@remarks Future enum related to display, like frame displayed event, could be added here + ALL_EVENTS = 0xFFFF ///Maximum of 16 event types supported + }; + + ///Class declarations + ///@remarks Add a new class for a new event type added above + + //Shutter event specific data + typedef struct ShutterEventData_t { + bool shutterClosed; + }ShutterEventData; + + ///Focus event specific data + typedef struct FocusEventData_t { + bool focusLocked; + bool focusError; + int currentFocusValue; + } FocusEventData; + + ///Zoom specific event data + typedef struct ZoomEventData_t { + int currentZoomIndex; + bool targetZoomIndexReached; + } ZoomEventData; + + typedef struct FaceData_t { + ssize_t top; + ssize_t left; + ssize_t bottom; + ssize_t right; + size_t score; + } FaceData; + + typedef sp<CameraFDResult> FaceEventData; + + class CameraHalEventData : public RefBase{ + + public: + + CameraHalEvent::FocusEventData focusEvent; + CameraHalEvent::ZoomEventData zoomEvent; + CameraHalEvent::ShutterEventData shutterEvent; + CameraHalEvent::FaceEventData faceEvent; + }; + + //default contrustor + CameraHalEvent(): + mCookie(NULL), + mEventType(NO_EVENTS) {} + + //copy constructor + CameraHalEvent(const CameraHalEvent &event) : + mCookie(event.mCookie), + mEventType(event.mEventType), + mEventData(event.mEventData) {}; + + void* mCookie; + CameraHalEventType mEventType; + sp<CameraHalEventData> mEventData; + +}; + +/// Have a generic callback class based on template - to adapt CameraFrame and Event +typedef void (*frame_callback) (CameraFrame *cameraFrame); +typedef void (*event_callback) (CameraHalEvent *event); + +//signals CameraHAL to relase image buffers +typedef void (*release_image_buffers_callback) (void *userData); +typedef void (*end_image_capture_callback) (void *userData); + +/** + * Interface class implemented by classes that have some events to communicate to dependendent classes + * Dependent classes use this interface for registering for events + */ +class MessageNotifier +{ +public: + static const uint32_t EVENT_BIT_FIELD_POSITION; + static const uint32_t FRAME_BIT_FIELD_POSITION; + + ///@remarks Msg type comes from CameraFrame and CameraHalEvent classes + /// MSB 16 bits is for events and LSB 16 bits is for frame notifications + /// FrameProvider and EventProvider classes act as helpers to event/frame + /// consumers to call this api + virtual void enableMsgType(int32_t msgs, frame_callback frameCb=NULL, event_callback eventCb=NULL, void* cookie=NULL) = 0; + virtual void disableMsgType(int32_t msgs, void* cookie) = 0; + + virtual ~MessageNotifier() {}; +}; + +class ErrorNotifier : public virtual RefBase +{ +public: + virtual void errorNotify(int error) = 0; + + virtual ~ErrorNotifier() {}; +}; + + +/** + * Interace class abstraction for Camera Adapter to act as a frame provider + * This interface is fully implemented by Camera Adapter + */ +class FrameNotifier : public MessageNotifier +{ +public: + virtual void returnFrame(void* frameBuf, CameraFrame::FrameType frameType) = 0; + virtual void addFramePointers(void *frameBuf, void *buf) = 0; + virtual void removeFramePointers() = 0; + + virtual ~FrameNotifier() {}; +}; + +/** * Wrapper class around Frame Notifier, which is used by display and notification classes for interacting with Camera Adapter + */ +class FrameProvider +{ + FrameNotifier* mFrameNotifier; + void* mCookie; + frame_callback mFrameCallback; + +public: + FrameProvider(FrameNotifier *fn, void* cookie, frame_callback frameCallback) + :mFrameNotifier(fn), mCookie(cookie),mFrameCallback(frameCallback) { } + + int enableFrameNotification(int32_t frameTypes); + int disableFrameNotification(int32_t frameTypes); + int returnFrame(void *frameBuf, CameraFrame::FrameType frameType); + void addFramePointers(void *frameBuf, void *buf); + void removeFramePointers(); +}; + +/** Wrapper class around MessageNotifier, which is used by display and notification classes for interacting with + * Camera Adapter + */ +class EventProvider +{ +public: + MessageNotifier* mEventNotifier; + void* mCookie; + event_callback mEventCallback; + +public: + EventProvider(MessageNotifier *mn, void* cookie, event_callback eventCallback) + :mEventNotifier(mn), mCookie(cookie), mEventCallback(eventCallback) {} + + int enableEventNotification(int32_t eventTypes); + int disableEventNotification(int32_t eventTypes); +}; + +/* + * Interface for providing buffers + */ +class BufferProvider +{ +public: + virtual void* allocateBuffer(int width, int height, const char* format, int &bytes, int numBufs) = 0; + + //additional methods used for memory mapping + virtual uint32_t * getOffsets() = 0; + virtual int getFd() = 0; + + virtual int freeBuffer(void* buf) = 0; + + virtual ~BufferProvider() {} +}; + +/** + * Class for handling data and notify callbacks to application + */ +class AppCallbackNotifier: public ErrorNotifier , public virtual RefBase +{ + +public: + + ///Constants + static const int NOTIFIER_TIMEOUT; + static const int32_t MAX_BUFFERS = 8; + + enum NotifierCommands + { + NOTIFIER_CMD_PROCESS_EVENT, + NOTIFIER_CMD_PROCESS_FRAME, + NOTIFIER_CMD_PROCESS_ERROR + }; + + enum NotifierState + { + NOTIFIER_STOPPED, + NOTIFIER_STARTED, + NOTIFIER_EXITED + }; + +public: + + ~AppCallbackNotifier(); + + ///Initialzes the callback notifier, creates any resources required + status_t initialize(); + + ///Starts the callbacks to application + status_t start(); + + ///Stops the callbacks from going to application + status_t stop(); + + void setEventProvider(int32_t eventMask, MessageNotifier * eventProvider); + void setFrameProvider(FrameNotifier *frameProvider); + + //All sub-components of Camera HAL call this whenever any error happens + virtual void errorNotify(int error); + + status_t startPreviewCallbacks(CameraParameters ¶ms, void *buffers, uint32_t *offsets, int fd, size_t length, size_t count); + status_t stopPreviewCallbacks(); + + status_t enableMsgType(int32_t msgType); + status_t disableMsgType(int32_t msgType); + + //API for enabling/disabling measurement data + void setMeasurements(bool enable); + + //thread loops + bool notificationThread(); + + ///Notification callback functions + static void frameCallbackRelay(CameraFrame* caFrame); + static void eventCallbackRelay(CameraHalEvent* chEvt); + void frameCallback(CameraFrame* caFrame); + void eventCallback(CameraHalEvent* chEvt); + void flushAndReturnFrames(); + + void setCallbacks(CameraHal *cameraHal, + camera_notify_callback notify_cb, + camera_data_callback data_cb, + camera_data_timestamp_callback data_cb_timestamp, + camera_request_memory get_memory, + void *user); + + //Set Burst mode + void setBurst(bool burst); + + //Notifications from CameraHal for video recording case + status_t startRecording(); + status_t stopRecording(); + status_t initSharedVideoBuffers(void *buffers, uint32_t *offsets, int fd, size_t length, size_t count, void *vidBufs); + status_t releaseRecordingFrame(const void *opaque); + + status_t useMetaDataBufferMode(bool enable); + + void EncoderDoneCb(void*, void*, CameraFrame::FrameType type, void* cookie1, void* cookie2); + + void useVideoBuffers(bool useVideoBuffers); + + bool getUesVideoBuffers(); + void setVideoRes(int width, int height); + + void flushEventQueue(); + + //Internal class definitions + class NotificationThread : public Thread { + AppCallbackNotifier* mAppCallbackNotifier; + TIUTILS::MessageQueue mNotificationThreadQ; + public: + enum NotificationThreadCommands + { + NOTIFIER_START, + NOTIFIER_STOP, + NOTIFIER_EXIT, + }; + public: + NotificationThread(AppCallbackNotifier* nh) + : Thread(false), mAppCallbackNotifier(nh) { } + virtual bool threadLoop() { + return mAppCallbackNotifier->notificationThread(); + } + + TIUTILS::MessageQueue &msgQ() { return mNotificationThreadQ;} + }; + + //Friend declarations + friend class NotificationThread; + +private: + void notifyEvent(); + void notifyFrame(); + bool processMessage(); + void releaseSharedVideoBuffers(); + status_t dummyRaw(); + void copyAndSendPictureFrame(CameraFrame* frame, int32_t msgType); + void copyAndSendPreviewFrame(CameraFrame* frame, int32_t msgType); + +private: + mutable Mutex mLock; + mutable Mutex mBurstLock; + CameraHal* mCameraHal; + camera_notify_callback mNotifyCb; + camera_data_callback mDataCb; + camera_data_timestamp_callback mDataCbTimestamp; + camera_request_memory mRequestMemory; + void *mCallbackCookie; + + //Keeps Video MemoryHeaps and Buffers within + //these objects + KeyedVector<unsigned int, unsigned int> mVideoHeaps; + KeyedVector<unsigned int, unsigned int> mVideoBuffers; + KeyedVector<unsigned int, unsigned int> mVideoMap; + + //Keeps list of Gralloc handles and associated Video Metadata Buffers + KeyedVector<uint32_t, uint32_t> mVideoMetadataBufferMemoryMap; + KeyedVector<uint32_t, uint32_t> mVideoMetadataBufferReverseMap; + + bool mBufferReleased; + + sp< NotificationThread> mNotificationThread; + EventProvider *mEventProvider; + FrameProvider *mFrameProvider; + TIUTILS::MessageQueue mEventQ; + TIUTILS::MessageQueue mFrameQ; + NotifierState mNotifierState; + + bool mPreviewing; + camera_memory_t* mPreviewMemory; + unsigned char* mPreviewBufs[MAX_BUFFERS]; + int mPreviewBufCount; + const char *mPreviewPixelFormat; + KeyedVector<unsigned int, sp<MemoryHeapBase> > mSharedPreviewHeaps; + KeyedVector<unsigned int, sp<MemoryBase> > mSharedPreviewBuffers; + + //Burst mode active + bool mBurst; + mutable Mutex mRecordingLock; + bool mRecording; + bool mMeasurementEnabled; + + bool mUseMetaDataBufferMode; + bool mRawAvailable; + + bool mUseVideoBuffers; + + int mVideoWidth; + int mVideoHeight; + +}; + + +/** + * Class used for allocating memory for JPEG bit stream buffers, output buffers of camera in no overlay case + */ +class MemoryManager : public BufferProvider, public virtual RefBase +{ +public: + MemoryManager():mIonFd(0){ } + + ///Initializes the memory manager creates any resources required + status_t initialize() { return NO_ERROR; } + + int setErrorHandler(ErrorNotifier *errorNotifier); + virtual void* allocateBuffer(int width, int height, const char* format, int &bytes, int numBufs); + virtual uint32_t * getOffsets(); + virtual int getFd() ; + virtual int freeBuffer(void* buf); + +private: + + sp<ErrorNotifier> mErrorNotifier; + int mIonFd; + KeyedVector<unsigned int, unsigned int> mIonHandleMap; + KeyedVector<unsigned int, unsigned int> mIonFdMap; + KeyedVector<unsigned int, unsigned int> mIonBufLength; +}; + + + + +/** + * CameraAdapter interface class + * Concrete classes derive from this class and provide implementations based on the specific camera h/w interface + */ + +class CameraAdapter: public FrameNotifier, public virtual RefBase +{ +protected: + enum AdapterActiveStates { + INTIALIZED_ACTIVE = 1 << 0, + LOADED_PREVIEW_ACTIVE = 1 << 1, + PREVIEW_ACTIVE = 1 << 2, + LOADED_CAPTURE_ACTIVE = 1 << 3, + CAPTURE_ACTIVE = 1 << 4, + BRACKETING_ACTIVE = 1 << 5, + AF_ACTIVE = 1 << 6, + ZOOM_ACTIVE = 1 << 7, + VIDEO_ACTIVE = 1 << 8, + }; +public: + typedef struct + { + void *mBuffers; + uint32_t *mOffsets; + int mFd; + size_t mLength; + size_t mCount; + size_t mMaxQueueable; + } BuffersDescriptor; + + enum CameraCommands + { + CAMERA_START_PREVIEW = 0, + CAMERA_STOP_PREVIEW = 1, + CAMERA_START_VIDEO = 2, + CAMERA_STOP_VIDEO = 3, + CAMERA_START_IMAGE_CAPTURE = 4, + CAMERA_STOP_IMAGE_CAPTURE = 5, + CAMERA_PERFORM_AUTOFOCUS = 6, + CAMERA_CANCEL_AUTOFOCUS = 7, + CAMERA_PREVIEW_FLUSH_BUFFERS = 8, + CAMERA_START_SMOOTH_ZOOM = 9, + CAMERA_STOP_SMOOTH_ZOOM = 10, + CAMERA_USE_BUFFERS_PREVIEW = 11, + CAMERA_SET_TIMEOUT = 12, + CAMERA_CANCEL_TIMEOUT = 13, + CAMERA_START_BRACKET_CAPTURE = 14, + CAMERA_STOP_BRACKET_CAPTURE = 15, + CAMERA_QUERY_RESOLUTION_PREVIEW = 16, + CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE = 17, + CAMERA_QUERY_BUFFER_SIZE_PREVIEW_DATA = 18, + CAMERA_USE_BUFFERS_IMAGE_CAPTURE = 19, + CAMERA_USE_BUFFERS_PREVIEW_DATA = 20, + CAMERA_TIMEOUT_EXPIRED = 21, + CAMERA_START_FD = 22, + CAMERA_STOP_FD = 23, + CAMERA_SWITCH_TO_EXECUTING = 24, + }; + + enum CameraMode + { + CAMERA_PREVIEW, + CAMERA_IMAGE_CAPTURE, + CAMERA_VIDEO, + CAMERA_MEASUREMENT + }; + + enum AdapterState { + INTIALIZED_STATE = INTIALIZED_ACTIVE, + LOADED_PREVIEW_STATE = LOADED_PREVIEW_ACTIVE | INTIALIZED_ACTIVE, + PREVIEW_STATE = PREVIEW_ACTIVE | INTIALIZED_ACTIVE, + LOADED_CAPTURE_STATE = LOADED_CAPTURE_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE, + CAPTURE_STATE = CAPTURE_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE, + BRACKETING_STATE = BRACKETING_ACTIVE | CAPTURE_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE , + AF_STATE = AF_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE, + ZOOM_STATE = ZOOM_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE, + VIDEO_STATE = VIDEO_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE, + VIDEO_AF_STATE = VIDEO_ACTIVE | AF_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE, + VIDEO_ZOOM_STATE = VIDEO_ACTIVE | ZOOM_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE, + VIDEO_LOADED_CAPTURE_STATE = VIDEO_ACTIVE | LOADED_CAPTURE_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE, + VIDEO_CAPTURE_STATE = VIDEO_ACTIVE | CAPTURE_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE, + AF_ZOOM_STATE = AF_ACTIVE | ZOOM_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE, + BRACKETING_ZOOM_STATE = BRACKETING_ACTIVE | ZOOM_ACTIVE | PREVIEW_ACTIVE | INTIALIZED_ACTIVE, + }; + +public: + + ///Initialzes the camera adapter creates any resources required + virtual int initialize(CameraProperties::Properties*) = 0; + + virtual int setErrorHandler(ErrorNotifier *errorNotifier) = 0; + + //Message/Frame notification APIs + virtual void enableMsgType(int32_t msgs, + frame_callback callback = NULL, + event_callback eventCb = NULL, + void *cookie = NULL) = 0; + virtual void disableMsgType(int32_t msgs, void* cookie) = 0; + virtual void returnFrame(void* frameBuf, CameraFrame::FrameType frameType) = 0; + virtual void addFramePointers(void *frameBuf, void *buf) = 0; + virtual void removeFramePointers() = 0; + + //APIs to configure Camera adapter and get the current parameter set + virtual int setParameters(const CameraParameters& params) = 0; + virtual void getParameters(CameraParameters& params) = 0; + + //API to flush the buffers from Camera + status_t flushBuffers() + { + return sendCommand(CameraAdapter::CAMERA_PREVIEW_FLUSH_BUFFERS); + } + + //Registers callback for returning image buffers back to CameraHAL + virtual int registerImageReleaseCallback(release_image_buffers_callback callback, void *user_data) = 0; + + //Registers callback, which signals a completed image capture + virtual int registerEndCaptureCallback(end_image_capture_callback callback, void *user_data) = 0; + + //API to send a command to the camera + virtual status_t sendCommand(CameraCommands operation, int value1=0, int value2=0, int value3=0) = 0; + + virtual ~CameraAdapter() {}; + + //Retrieves the current Adapter state + virtual AdapterState getState() = 0; + + //Retrieves the next Adapter state + virtual AdapterState getNextState() = 0; + + // Receive orientation events from CameraHal + virtual void onOrientationEvent(uint32_t orientation, uint32_t tilt) = 0; + + // Rolls the state machine back to INTIALIZED_STATE from the current state + virtual status_t rollbackToInitializedState() = 0; + + // Retrieves the current Adapter state - for internal use (not locked) + virtual status_t getState(AdapterState &state) = 0; + // Retrieves the next Adapter state - for internal use (not locked) + virtual status_t getNextState(AdapterState &state) = 0; + +protected: + //The first two methods will try to switch the adapter state. + //Every call to setState() should be followed by a corresponding + //call to commitState(). If the state switch fails, then it will + //get reset to the previous state via rollbackState(). + virtual status_t setState(CameraCommands operation) = 0; + virtual status_t commitState() = 0; + virtual status_t rollbackState() = 0; +}; + +class DisplayAdapter : public BufferProvider, public virtual RefBase +{ +public: + typedef struct S3DParameters_t + { + int mode; + int framePacking; + int order; + int subSampling; + } S3DParameters; + + ///Initializes the display adapter creates any resources required + virtual int initialize() = 0; + + virtual int setPreviewWindow(struct preview_stream_ops *window) = 0; + virtual int setFrameProvider(FrameNotifier *frameProvider) = 0; + virtual int setErrorHandler(ErrorNotifier *errorNotifier) = 0; + virtual int enableDisplay(int width, int height, struct timeval *refTime = NULL, S3DParameters *s3dParams = NULL) = 0; + virtual int disableDisplay(bool cancel_buffer = true) = 0; + //Used for Snapshot review temp. pause + virtual int pauseDisplay(bool pause) = 0; + +#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS + //Used for shot to snapshot measurement + virtual int setSnapshotTimeRef(struct timeval *refTime = NULL) = 0; +#endif + + virtual int useBuffers(void *bufArr, int num) = 0; + virtual bool supportsExternalBuffering() = 0; + + // Get max queueable buffers display supports + // This function should only be called after + // allocateBuffer + virtual int maxQueueableBuffers(unsigned int& queueable) = 0; +}; + +static void releaseImageBuffers(void *userData); + +static void endImageCapture(void *userData); + + /** + Implementation of the Android Camera hardware abstraction layer + + This class implements the interface methods defined in CameraHardwareInterface + for the OMAP4 platform + +*/ +class CameraHal + +{ + +public: + ///Constants + static const int NO_BUFFERS_PREVIEW; + static const int NO_BUFFERS_IMAGE_CAPTURE; + static const uint32_t VFR_SCALE = 1000; + + + /*--------------------Interface Methods---------------------------------*/ + + //@{ +public: + + /** Set the notification and data callbacks */ + void setCallbacks(camera_notify_callback notify_cb, + camera_data_callback data_cb, + camera_data_timestamp_callback data_cb_timestamp, + camera_request_memory get_memory, + void *user); + + /** Receives orientation events from SensorListener **/ + void onOrientationEvent(uint32_t orientation, uint32_t tilt); + + /** + * The following three functions all take a msgtype, + * which is a bitmask of the messages defined in + * include/ui/Camera.h + */ + + /** + * Enable a message, or set of messages. + */ + void enableMsgType(int32_t msgType); + + /** + * Disable a message, or a set of messages. + */ + void disableMsgType(int32_t msgType); + + /** + * Query whether a message, or a set of messages, is enabled. + * Note that this is operates as an AND, if any of the messages + * queried are off, this will return false. + */ + int msgTypeEnabled(int32_t msgType); + + /** + * Start preview mode. + */ + int startPreview(); + + /** + * Only used if overlays are used for camera preview. + */ + int setPreviewWindow(struct preview_stream_ops *window); + + /** + * Stop a previously started preview. + */ + void stopPreview(); + + /** + * Returns true if preview is enabled. + */ + bool previewEnabled(); + + /** + * Start record mode. When a record image is available a CAMERA_MSG_VIDEO_FRAME + * message is sent with the corresponding frame. Every record frame must be released + * by calling releaseRecordingFrame(). + */ + int startRecording(); + + /** + * Stop a previously started recording. + */ + void stopRecording(); + + /** + * Returns true if recording is enabled. + */ + int recordingEnabled(); + + /** + * Release a record frame previously returned by CAMERA_MSG_VIDEO_FRAME. + */ + void releaseRecordingFrame(const void *opaque); + + /** + * Start auto focus, the notification callback routine is called + * with CAMERA_MSG_FOCUS once when focusing is complete. autoFocus() + * will be called again if another auto focus is needed. + */ + int autoFocus(); + + /** + * Cancels auto-focus function. If the auto-focus is still in progress, + * this function will cancel it. Whether the auto-focus is in progress + * or not, this function will return the focus position to the default. + * If the camera does not support auto-focus, this is a no-op. + */ + int cancelAutoFocus(); + + /** + * Take a picture. + */ + int takePicture(); + + /** + * Cancel a picture that was started with takePicture. Calling this + * method when no picture is being taken is a no-op. + */ + int cancelPicture(); + + /** Set the camera parameters. */ + int setParameters(const char* params); + int setParameters(const CameraParameters& params); + + /** Return the camera parameters. */ + char* getParameters(); + void putParameters(char *); + + /** + * Send command to camera driver. + */ + int sendCommand(int32_t cmd, int32_t arg1, int32_t arg2); + + /** + * Release the hardware resources owned by this object. Note that this is + * *not* done in the destructor. + */ + void release(); + + /** + * Dump state of the camera hardware + */ + int dump(int fd) const; + + + status_t storeMetaDataInBuffers(bool enable); + + //@} + +/*--------------------Internal Member functions - Public---------------------------------*/ + +public: + /** @name internalFunctionsPublic */ + //@{ + + /** Constructor of CameraHal */ + CameraHal(int cameraId); + + // Destructor of CameraHal + ~CameraHal(); + + /** Initialize CameraHal */ + status_t initialize(CameraProperties::Properties*); + + /** Deinitialize CameraHal */ + void deinitialize(); + +#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS + + //Uses the constructor timestamp as a reference to calcluate the + // elapsed time + static void PPM(const char *); + //Uses a user provided timestamp as a reference to calcluate the + // elapsed time + static void PPM(const char *, struct timeval*, ...); + +#endif + + /** Free image bufs */ + status_t freeImageBufs(); + + //Signals the end of image capture + status_t signalEndImageCapture(); + + //Events + static void eventCallbackRelay(CameraHalEvent* event); + void eventCallback(CameraHalEvent* event); + void setEventProvider(int32_t eventMask, MessageNotifier * eventProvider); + +/*--------------------Internal Member functions - Private---------------------------------*/ +private: + + /** @name internalFunctionsPrivate */ + //@{ + + /** Set the camera parameters specific to Video Recording. */ + bool setVideoModeParameters(const CameraParameters&); + + /** Reset the camera parameters specific to Video Recording. */ + bool resetVideoModeParameters(); + + /** Restart the preview with setParameter. */ + status_t restartPreview(); + + status_t parseResolution(const char *resStr, int &width, int &height); + + void insertSupportedParams(); + + /** Allocate preview data buffers */ + status_t allocPreviewDataBufs(size_t size, size_t bufferCount); + + /** Free preview data buffers */ + status_t freePreviewDataBufs(); + + /** Allocate preview buffers */ + status_t allocPreviewBufs(int width, int height, const char* previewFormat, unsigned int bufferCount, unsigned int &max_queueable); + + /** Allocate video buffers */ + status_t allocVideoBufs(uint32_t width, uint32_t height, uint32_t bufferCount); + + /** Allocate image capture buffers */ + status_t allocImageBufs(unsigned int width, unsigned int height, size_t length, const char* previewFormat, unsigned int bufferCount); + + /** Free preview buffers */ + status_t freePreviewBufs(); + + /** Free video bufs */ + status_t freeVideoBufs(void *bufs); + + //Check if a given resolution is supported by the current camera + //instance + bool isResolutionValid(unsigned int width, unsigned int height, const char *supportedResolutions); + + //Check if a given parameter is supported by the current camera + // instance + bool isParameterValid(const char *param, const char *supportedParams); + bool isParameterValid(int param, const char *supportedParams); + status_t doesSetParameterNeedUpdate(const char *new_param, const char *old_params, bool &update); + + /** Initialize default parameters */ + void initDefaultParameters(); + + void dumpProperties(CameraProperties::Properties& cameraProps); + + status_t startImageBracketing(); + + status_t stopImageBracketing(); + + void setShutter(bool enable); + + void forceStopPreview(); + + void selectFPSRange(int framerate, int *min_fps, int *max_fps); + + void setPreferredPreviewRes(int width, int height); + void resetPreviewRes(CameraParameters *mParams, int width, int height); + + //@} + + +/*----------Member variables - Public ---------------------*/ +public: + int32_t mMsgEnabled; + bool mRecordEnabled; + nsecs_t mCurrentTime; + bool mFalsePreview; + bool mPreviewEnabled; + uint32_t mTakePictureQueue; + bool mBracketingEnabled; + bool mBracketingRunning; + //User shutter override + bool mShutterEnabled; + bool mMeasurementEnabled; + //Google's parameter delimiter + static const char PARAMS_DELIMITER[]; + + CameraAdapter *mCameraAdapter; + sp<AppCallbackNotifier> mAppCallbackNotifier; + sp<DisplayAdapter> mDisplayAdapter; + sp<MemoryManager> mMemoryManager; + + sp<IMemoryHeap> mPictureHeap; + + int* mGrallocHandles; + bool mFpsRangeChangedByApp; + + + + + +///static member vars + +#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS + + //Timestamp from the CameraHal constructor + static struct timeval ppm_start; + //Timestamp of the autoFocus command + static struct timeval mStartFocus; + //Timestamp of the startPreview command + static struct timeval mStartPreview; + //Timestamp of the takePicture command + static struct timeval mStartCapture; + +#endif + +/*----------Member variables - Private ---------------------*/ +private: + bool mDynamicPreviewSwitch; + //keeps paused state of display + bool mDisplayPaused; + //Index of current camera adapter + int mCameraIndex; + + mutable Mutex mLock; + + sp<SensorListener> mSensorListener; + + void* mCameraAdapterHandle; + + CameraParameters mParameters; + bool mPreviewRunning; + bool mPreviewStateOld; + bool mRecordingEnabled; + EventProvider *mEventProvider; + + int32_t *mPreviewDataBufs; + uint32_t *mPreviewDataOffsets; + int mPreviewDataFd; + int mPreviewDataLength; + int32_t *mImageBufs; + uint32_t *mImageOffsets; + int mImageFd; + int mImageLength; + int32_t *mPreviewBufs; + uint32_t *mPreviewOffsets; + int mPreviewLength; + int mPreviewFd; + int32_t *mVideoBufs; + uint32_t *mVideoOffsets; + int mVideoFd; + int mVideoLength; + + int mBracketRangePositive; + int mBracketRangeNegative; + + ///@todo Rename this as preview buffer provider + BufferProvider *mBufProvider; + BufferProvider *mVideoBufProvider; + + + CameraProperties::Properties* mCameraProperties; + + bool mPreviewStartInProgress; + + bool mSetPreviewWindowCalled; + + uint32_t mPreviewWidth; + uint32_t mPreviewHeight; + int32_t mMaxZoomSupported; + + int mVideoWidth; + int mVideoHeight; + +}; + + +}; // namespace android + +#endif diff --git a/libcamera/CameraHal_Module.cpp b/libcamera/CameraHal_Module.cpp new file mode 100644 index 0000000..d322673 --- /dev/null +++ b/libcamera/CameraHal_Module.cpp @@ -0,0 +1,429 @@ +/* + * Copyright (C) Texas Instruments - http://www.ti.com/ + * + * 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. + */ + +/** +* @file CameraHal.cpp +* +* This file maps the Camera Hardware Interface to V4L2. +* +*/ + +#define LOG_TAG "****CameraHAL" + +#include <utils/threads.h> +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <time.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <utils/Log.h> +#include <utils/threads.h> +#include <linux/videodev2.h> +#include "binder/MemoryBase.h" +#include "binder/MemoryHeapBase.h" +#include <utils/threads.h> +#include <camera/CameraParameters.h> +#include <hardware/camera.h> +#include <sys/ioctl.h> +#include <utils/threads.h> +#include "CameraHardware.h" +#include <binder/MemoryBase.h> +#include <binder/MemoryHeapBase.h> +#include <utils/threads.h> +#include "V4L2Camera.h" +#define LOG_FUNCTION_NAME LOGD("%d: %s() ENTER", __LINE__, __FUNCTION__); + +using namespace android; +static CameraHardware *V4L2CameraHardware; +static int camera_device_open(const hw_module_t* module, const char* name, + hw_device_t** device); +static int camera_device_close(hw_device_t* device); +static int camera_get_number_of_cameras(void); +static int camera_get_camera_info(int camera_id, struct camera_info *info); +static struct hw_module_methods_t camera_module_methods = { + open: camera_device_open +}; + +camera_module_t HAL_MODULE_INFO_SYM = { + common: { + tag: HARDWARE_MODULE_TAG, + version_major: 1, + version_minor: 0, + id: CAMERA_HARDWARE_MODULE_ID, + name: "V4L2 CameraHal Module", + author: "Linaro", + methods: &camera_module_methods, + dso: NULL, /* remove compilation warnings */ + reserved: {0}, /* remove compilation warnings */ + }, + get_number_of_cameras: camera_get_number_of_cameras, + get_camera_info: camera_get_camera_info, +}; + +typedef struct V4L2_camera_device { + camera_device_t base; + /* TI specific "private" data can go here (base.priv) */ + int cameraid; +} V4l2_camera_device_t; + + +/******************************************************************* + * implementation of camera_device_ops functions + *******************************************************************/ + +int camera_set_preview_window(struct camera_device * device, + struct preview_stream_ops *window) +{ + int rv = -EINVAL; + LOG_FUNCTION_NAME + if(!device) + return rv; + + if(window==NULL) + { + LOGW("window is NULL"); + V4L2CameraHardware->setPreviewWindow(window); + return -1; + } + + V4L2CameraHardware->setPreviewWindow(window); + LOGD("Exiting the function"); + return 0; +} + +void camera_set_callbacks(struct camera_device * device, + camera_notify_callback notify_cb, + camera_data_callback data_cb, + camera_data_timestamp_callback data_cb_timestamp, + camera_request_memory get_memory, + void *user) +{ + V4l2_camera_device_t* V4l2_dev = NULL; + LOG_FUNCTION_NAME + V4L2CameraHardware->setCallbacks(notify_cb,data_cb,data_cb_timestamp,get_memory,user); +} + +void camera_enable_msg_type(struct camera_device * device, int32_t msg_type) +{ + V4l2_camera_device_t* V4l2_dev = NULL; + + LOG_FUNCTION_NAME + V4L2CameraHardware->enableMsgType(msg_type); +} + +void camera_disable_msg_type(struct camera_device * device, int32_t msg_type) +{ + V4l2_camera_device_t* V4l2_dev = NULL; + LOG_FUNCTION_NAME + V4L2CameraHardware->disableMsgType(msg_type); +} + +int camera_msg_type_enabled(struct camera_device * device, int32_t msg_type) +{ + V4l2_camera_device_t* V4l2_dev = NULL; + LOG_FUNCTION_NAME + return V4L2CameraHardware->msgTypeEnabled(msg_type); +} + +int camera_start_preview(struct camera_device * device) +{ + LOG_FUNCTION_NAME + return V4L2CameraHardware->startPreview(); +} + +void camera_stop_preview(struct camera_device * device) +{ +LOG_FUNCTION_NAME +V4L2CameraHardware->stopPreview(); +} + +int camera_preview_enabled(struct camera_device * device) +{ + LOG_FUNCTION_NAME + if(V4L2CameraHardware->previewEnabled()) + { + LOGW("----Preview Enabled----"); + return 1; + } + else + { + LOGW("----Preview not Enabled----"); + return 0; + } +} + +int camera_store_meta_data_in_buffers(struct camera_device * device, int enable) +{ + int rv = -EINVAL; + LOG_FUNCTION_NAME + return rv; +} + +int camera_start_recording(struct camera_device * device) +{ +LOG_FUNCTION_NAME + return V4L2CameraHardware->startRecording(); +} + +void camera_stop_recording(struct camera_device * device) +{ +LOG_FUNCTION_NAME + V4L2CameraHardware->stopRecording(); +} + +int camera_recording_enabled(struct camera_device * device) +{ + LOG_FUNCTION_NAME + return V4L2CameraHardware->recordingEnabled(); +} + +void camera_release_recording_frame(struct camera_device * device, + const void *opaque) +{ + LOG_FUNCTION_NAME + return V4L2CameraHardware->releaseRecordingFrame(opaque); +} + +int camera_auto_focus(struct camera_device * device) +{ + LOG_FUNCTION_NAME + return V4L2CameraHardware->autoFocus(); +} + +int camera_cancel_auto_focus(struct camera_device * device) +{ +LOG_FUNCTION_NAME + return V4L2CameraHardware->cancelAutoFocus(); +} + +int camera_take_picture(struct camera_device * device) +{ +LOG_FUNCTION_NAME + return V4L2CameraHardware->takePicture(); +} + +int camera_cancel_picture(struct camera_device * device) +{ + int rv = 0;// -EINVAL; + LOG_FUNCTION_NAME + return V4L2CameraHardware->cancelPicture(); +} + +int camera_set_parameters(struct camera_device * device, const char *params) +{ + LOG_FUNCTION_NAME + CameraParameters *camParams = new CameraParameters(); + String8 *params_str8 = new String8(params); + camParams->unflatten(*params_str8); + return V4L2CameraHardware->setParameters(*camParams); +} + +char* camera_get_parameters(struct camera_device * device) +{ + char* param = NULL ; +#if 1 + String8 params_str8 = V4L2CameraHardware->getParameters().flatten(); + // camera service frees this string... + param = (char*) malloc(sizeof(char) * (params_str8.length()+1)); + strcpy(param, params_str8.string()); + LOGD("%s",param); +#endif + LOG_FUNCTION_NAME + return param; +} + +static void camera_put_parameters(struct camera_device *device, char *params) +{ + LOG_FUNCTION_NAME + CameraParameters *camParams = new CameraParameters(); + String8 *params_str8 = new String8(params); + camParams->unflatten(*params_str8); + V4L2CameraHardware->setParameters(*camParams); +} + +int camera_send_command(struct camera_device * device, + int32_t cmd, int32_t arg1, int32_t arg2) +{ + int rv =0;// -EINVAL; + LOG_FUNCTION_NAME + return rv; +} + +void camera_release(struct camera_device * device) +{ +LOG_FUNCTION_NAME + V4L2CameraHardware->release(); +} + + +int camera_dump(struct camera_device * device, int fd) +{ + int rv = 0;//-EINVAL; + LOG_FUNCTION_NAME + return rv; +} + +extern "C" void heaptracker_free_leaked_memory(void); + +int camera_device_close(hw_device_t* device) +{ + int ret = 0; + LOG_FUNCTION_NAME + delete V4L2CameraHardware; + V4L2CameraHardware=NULL; + return ret; +} + +/******************************************************************* + * implementation of camera_module functions + *******************************************************************/ + +/* open device handle to one of the cameras + * + * assume camera service will keep singleton of each camera + * so this function will always only be called once per camera instance + */ + +int camera_device_open(const hw_module_t* module, const char* name, + hw_device_t** device) +{ + int rv = 0; + int num_cameras = 1; + int cameraid; + V4l2_camera_device_t* camera_device = NULL; + camera_device_ops_t* camera_ops = NULL; + + LOG_FUNCTION_NAME + + + LOGI("camera_device open"); + + if (name != NULL) { + cameraid = atoi(name); + + if(cameraid > num_cameras) + { + LOGE("camera service provided cameraid out of bounds, " + "cameraid = %d, num supported = %d", + cameraid, num_cameras); + rv = -EINVAL; + goto fail; + } + + + camera_device = (V4l2_camera_device_t*)malloc(sizeof(*camera_device)); + if(!camera_device) + { + LOGE("camera_device allocation fail"); + rv = -ENOMEM; + goto fail; + } + + camera_ops = (camera_device_ops_t*)malloc(sizeof(*camera_ops)); + if(!camera_ops) + { + LOGE("camera_ops allocation fail"); + rv = -ENOMEM; + goto fail; + } + + memset(camera_device, 0, sizeof(*camera_device)); + memset(camera_ops, 0, sizeof(*camera_ops)); + + camera_device->base.common.tag = HARDWARE_DEVICE_TAG; + camera_device->base.common.version = 0; + camera_device->base.common.module = (hw_module_t *)(module); + camera_device->base.common.close = camera_device_close; + camera_device->base.ops = camera_ops; + + camera_ops->set_preview_window = camera_set_preview_window; + camera_ops->set_callbacks = camera_set_callbacks; + camera_ops->enable_msg_type = camera_enable_msg_type; + camera_ops->disable_msg_type = camera_disable_msg_type; + camera_ops->msg_type_enabled = camera_msg_type_enabled; + camera_ops->start_preview = camera_start_preview; + camera_ops->stop_preview = camera_stop_preview; + camera_ops->preview_enabled = camera_preview_enabled; + camera_ops->store_meta_data_in_buffers = camera_store_meta_data_in_buffers; + camera_ops->start_recording = camera_start_recording; + camera_ops->stop_recording = camera_stop_recording; + camera_ops->recording_enabled = camera_recording_enabled; + camera_ops->release_recording_frame = camera_release_recording_frame; + camera_ops->auto_focus = camera_auto_focus; + camera_ops->cancel_auto_focus = camera_cancel_auto_focus; + camera_ops->take_picture = camera_take_picture; + camera_ops->cancel_picture = camera_cancel_picture; + camera_ops->set_parameters = camera_set_parameters; + camera_ops->get_parameters = camera_get_parameters; + camera_ops->put_parameters = camera_put_parameters; + camera_ops->send_command = camera_send_command; + camera_ops->release = camera_release; + camera_ops->dump = camera_dump; + + *device = &camera_device->base.common; + + // -------- TI specific stuff -------- + + camera_device->cameraid = cameraid; + V4L2CameraHardware = new CameraHardware(0); + } + + return rv; + +fail: + if(camera_device) { + free(camera_device); + camera_device = NULL; + } + if(camera_ops) { + free(camera_ops); + camera_ops = NULL; + } + *device = NULL; + return rv; +} + +int camera_get_number_of_cameras(void) +{ +LOG_FUNCTION_NAME + int num_cameras =2;// MAX_CAMERAS_SUPPORTED; + return num_cameras; +} + +int camera_get_camera_info(int camera_id, struct camera_info *info) +{ + LOG_FUNCTION_NAME + int rv = 0; + int face_value = CAMERA_FACING_FRONT; + int orientation = 0; + const char *valstr = NULL; + if(camera_id == 0) { + info->facing = CAMERA_FACING_BACK; + LOGD("cameraHal BACK %d",camera_id); + } + else { + LOGD("cameraHal Front %d",camera_id); + info->facing = face_value; + } + info->orientation = orientation; + LOGD("cameraHal %d",camera_id); + return rv; +} diff --git a/libcamera/CameraHardware.cpp b/libcamera/CameraHardware.cpp index 1c30f0d..8c90fa4 100644 --- a/libcamera/CameraHardware.cpp +++ b/libcamera/CameraHardware.cpp @@ -24,18 +24,26 @@ #include "CameraHardware.h" #include <fcntl.h> #include <sys/mman.h> - +#include <cutils/native_handle.h> +#include <hal_public.h> +#include <ui/GraphicBufferMapper.h> +#include <gui/ISurfaceTexture.h> #define MIN_WIDTH 320 #define MIN_HEIGHT 240 #define CAM_SIZE "320x240" #define PIXEL_FORMAT V4L2_PIX_FMT_YUYV +#define CAMHAL_GRALLOC_USAGE GRALLOC_USAGE_HW_TEXTURE | \ + GRALLOC_USAGE_HW_RENDER | \ + GRALLOC_USAGE_SW_READ_RARELY | \ + GRALLOC_USAGE_SW_WRITE_NEVER + extern "C" { void yuyv422_to_yuv420sp(unsigned char*,unsigned char*,int,int); + void convertYUYVtoRGB565(unsigned char *buf, unsigned char *rgb, int width, int height); } namespace android { -wp<CameraHardwareInterface> CameraHardware::singleton; const char supportedFpsRanges [] = "(8000,8000),(8000,10000),(10000,10000),(8000,15000),(15000,15000),(8000,20000),(20000,20000),(24000,24000),(25000,25000),(8000,30000),(30000,30000)"; @@ -59,6 +67,7 @@ CameraHardware::CameraHardware(int cameraId) mMsgEnabled(0) { initDefaultParameters(); + mNativeWindow=NULL; } void CameraHardware::initDefaultParameters() @@ -71,6 +80,7 @@ void CameraHardware::initDefaultParameters() p.set(p.KEY_SUPPORTED_PREVIEW_SIZES, CAM_SIZE); p.set(p.KEY_SUPPORTED_PREVIEW_SIZES, "640x480"); p.set(CameraParameters::KEY_VIDEO_FRAME_FORMAT,CameraParameters::PIXEL_FORMAT_YUV420SP); + p.set(CameraParameters::KEY_FOCUS_MODE,0); p.setPictureSize(MIN_WIDTH, MIN_HEIGHT); p.setPictureFormat("jpeg"); p.set(p.KEY_SUPPORTED_PICTURE_SIZES, CAM_SIZE); @@ -82,7 +92,6 @@ void CameraHardware::initDefaultParameters() CameraHardware::~CameraHardware() { - singleton.clear(); } sp<IMemoryHeap> CameraHardware::getPreviewHeap() const @@ -97,18 +106,53 @@ sp<IMemoryHeap> CameraHardware::getRawHeap() const // --------------------------------------------------------------------------- -void CameraHardware::setCallbacks(notify_callback notify_cb, - data_callback data_cb, - data_callback_timestamp data_cb_timestamp, +void CameraHardware::setCallbacks(camera_notify_callback notify_cb, + camera_data_callback data_cb, + camera_data_timestamp_callback data_cb_timestamp, + camera_request_memory get_memory, void *arg) { Mutex::Autolock lock(mLock); mNotifyFn = notify_cb; mDataFn = data_cb; + mRequestMemory = get_memory; mTimestampFn = data_cb_timestamp; mUser = arg; } +int CameraHardware::setPreviewWindow( preview_stream_ops_t *window) +{ + int err; + Mutex::Autolock lock(mLock); + if(mNativeWindow) + mNativeWindow=NULL; + if(window==NULL) + { + LOGW("Window is Null"); + return 0; + } + int width, height; + mParameters.getPreviewSize(&width, &height); + mNativeWindow=window; + mNativeWindow->set_usage(mNativeWindow,CAMHAL_GRALLOC_USAGE); + mNativeWindow->set_buffers_geometry( + mNativeWindow, + width, + height, + HAL_PIXEL_FORMAT_RGB_565); + err = mNativeWindow->set_buffer_count(mNativeWindow, 3); + if (err != 0) { + LOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err), -err); + + if ( ENODEV == err ) { + LOGE("Preview surface abandoned!"); + mNativeWindow = NULL; + } + } + + return 0; +} + void CameraHardware::enableMsgType(int32_t msgType) { Mutex::Autolock lock(mLock); @@ -132,19 +176,48 @@ bool CameraHardware::msgTypeEnabled(int32_t msgType) int CameraHardware::previewThread() { int width, height; + int err; + IMG_native_handle_t** hndl2hndl; + IMG_native_handle_t* handle; + int stride; mParameters.getPreviewSize(&width, &height); - if (!previewStopped) { + int framesize= width * height * 1.5 ; //yuv420sp + + if (!previewStopped) { + mLock.lock(); + if (mNativeWindow != NULL) + { + if ((err = mNativeWindow->dequeue_buffer(mNativeWindow,(buffer_handle_t**) &hndl2hndl,&stride)) != 0) { + LOGW("Surface::dequeueBuffer returned error %d", err); + return -1; + } + mNativeWindow->lock_buffer(mNativeWindow, (buffer_handle_t*) hndl2hndl); + GraphicBufferMapper &mapper = GraphicBufferMapper::get(); + + Rect bounds(width, height); + void *tempbuf; + void *dst; + if(0 == mapper.lock((buffer_handle_t)*hndl2hndl,CAMHAL_GRALLOC_USAGE, bounds, &dst)); + { // Get preview frame - camera.GrabPreviewFrame(mHeap->getBase()); + tempbuf=camera.GrabPreviewFrame(); + convertYUYVtoRGB565((unsigned char *)tempbuf,(unsigned char *)dst, width, height); + mapper.unlock((buffer_handle_t)*hndl2hndl); + mNativeWindow->enqueue_buffer(mNativeWindow,(buffer_handle_t*) hndl2hndl); if ((mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) || (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) { + camera_memory_t* picture = mRequestMemory(-1, framesize, 1, NULL); + yuyv422_to_yuv420sp((unsigned char *)tempbuf,(unsigned char *) picture->data, width, height); if ((mMsgEnabled & CAMERA_MSG_VIDEO_FRAME ) && mRecordRunning ) { - yuyv422_to_yuv420sp((unsigned char *)mHeap->getBase(), (unsigned char*)mRecordHeap->getBase(), width, height); nsecs_t timeStamp = systemTime(SYSTEM_TIME_MONOTONIC); - mTimestampFn(timeStamp, CAMERA_MSG_VIDEO_FRAME,mRecordBuffer, mUser); + //mTimestampFn(timeStamp, CAMERA_MSG_VIDEO_FRAME,mRecordBuffer, mUser); } - mDataFn(CAMERA_MSG_PREVIEW_FRAME,mBuffer, mUser); + mDataFn(CAMERA_MSG_PREVIEW_FRAME,picture,0,NULL,mUser); } + camera.ReleasePreviewFrame(); + } + } + mLock.unlock(); } return NO_ERROR; @@ -155,12 +228,16 @@ status_t CameraHardware::startPreview() int ret; int width, height; int i; + IMG_native_handle_t** hndl2hndl; + IMG_native_handle_t* handle; + int stride; char devnode[12]; Mutex::Autolock lock(mLock); if (mPreviewThread != 0) { //already running return INVALID_OPERATION; } +#if 1 LOGI("startPreview: in startpreview \n"); mParameters.getPreviewSize(&width, &height); for( i=0; i<10; i++) { @@ -197,6 +274,7 @@ status_t CameraHardware::startPreview() previewStopped = false; mPreviewThread = new PreviewThread(this); +#endif return NO_ERROR; } @@ -230,7 +308,8 @@ void CameraHardware::stopPreview() bool CameraHardware::previewEnabled() { - return mPreviewThread != 0; + Mutex::Autolock lock(mLock); + return ((mPreviewThread != 0) ); } status_t CameraHardware::startRecording() @@ -254,8 +333,9 @@ bool CameraHardware::recordingEnabled() return mRecordRunning; } -void CameraHardware::releaseRecordingFrame(const sp<IMemory>& mem) +void CameraHardware::releaseRecordingFrame(const void *opaque) { + } // --------------------------------------------------------------------------- @@ -305,6 +385,7 @@ int CameraHardware::pictureThread() struct v4l2_capability cap; int i; char devnode[12]; + camera_memory_t* picture = NULL; if (mMsgEnabled & CAMERA_MSG_SHUTTER) @@ -330,10 +411,11 @@ int CameraHardware::pictureThread() camera.Init(); camera.StartStreaming(); - + //TODO xxx : Optimize the memory capture call. Too many memcpy if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE) { LOGD ("mJpegPictureCallback"); - mDataFn(CAMERA_MSG_COMPRESSED_IMAGE, camera.GrabJpegFrame(),mUser); + picture = camera.GrabJpegFrame(mRequestMemory); + mDataFn(CAMERA_MSG_COMPRESSED_IMAGE,picture,0,NULL ,mUser); } camera.Uninit(); @@ -347,8 +429,6 @@ status_t CameraHardware::takePicture() { LOGD ("takepicture"); stopPreview(); - //if (createThread(beginPictureThread, this) == false) - // return -1; pictureThread(); @@ -370,11 +450,6 @@ status_t CameraHardware::setParameters(const CameraParameters& params) { Mutex::Autolock lock(mLock); - if (strcmp(params.getPreviewFormat(), "yuv422sp") != 0) { - LOGE("Only yuv422sp preview is supported"); - return -1; - } - if (strcmp(params.getPictureFormat(), "jpeg") != 0) { LOGE("Only jpeg still pictures are supported"); return -1; @@ -393,6 +468,7 @@ status_t CameraHardware::setParameters(const CameraParameters& params) mParameters = params; mParameters.setPreviewSize(w,h); mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, supportedFpsRanges); + mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, "320x240,352x288,640x480,720x480,720x576,848x480"); return NO_ERROR; } @@ -417,47 +493,4 @@ void CameraHardware::release() close(camera_device); } -sp<CameraHardwareInterface> CameraHardware::createInstance(int cameraId) -{ - if (singleton != 0) { - sp<CameraHardwareInterface> hardware = singleton.promote(); - if (hardware != 0) { - return hardware; - } - } - sp<CameraHardwareInterface> hardware(new CameraHardware(cameraId)); - singleton = hardware; - return hardware; -} - -static CameraInfo sCameraInfo[] = { - { - facing: CAMERA_FACING_BACK, - orientation: 0 - }, -/* - { - facing: CAMERA_FACING_FRONT, - orientation: 0 - } -*/ -}; - -extern "C" int HAL_getNumberOfCameras() -{ - return sizeof(sCameraInfo) / sizeof(sCameraInfo[0]); -} - -extern "C" void HAL_getCameraInfo(int cameraId, struct CameraInfo* cameraInfo) -{ -LOGD("HAL_getCameraInfo: %d", cameraId); - memcpy(cameraInfo, &sCameraInfo[cameraId], sizeof(CameraInfo)); -} - -extern "C" sp<CameraHardwareInterface> HAL_openCameraHardware(int cameraId) -{ -LOGD("HAL_openCameraHardware: %d", cameraId); - return CameraHardware::createInstance(cameraId); -} - }; // namespace android diff --git a/libcamera/CameraHardware.h b/libcamera/CameraHardware.h index 7491cce..b523668 100644 --- a/libcamera/CameraHardware.h +++ b/libcamera/CameraHardware.h @@ -22,31 +22,60 @@ #define ANDROID_HARDWARE_CAMERA_HARDWARE_H #include <utils/threads.h> -#include <camera/CameraHardwareInterface.h> #include <binder/MemoryBase.h> #include <binder/MemoryHeapBase.h> #include <utils/threads.h> +#include <utils/threads.h> +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <time.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <utils/Log.h> +#include <utils/threads.h> +#include <linux/videodev2.h> +#include "binder/MemoryBase.h" +#include "binder/MemoryHeapBase.h" +#include <utils/threads.h> +#include <camera/CameraParameters.h> +#include <hardware/camera.h> +#include <sys/ioctl.h> +#include <utils/threads.h> +#include <binder/MemoryBase.h> +#include <binder/MemoryHeapBase.h> +#include <utils/threads.h> +#include "V4L2Camera.h" + +#include <hardware/camera.h> + #include <sys/ioctl.h> #include "V4L2Camera.h" namespace android { -class CameraHardware : public CameraHardwareInterface { +class CameraHardware { public: virtual sp<IMemoryHeap> getPreviewHeap() const; virtual sp<IMemoryHeap> getRawHeap() const; virtual status_t startPreview(); - virtual void setCallbacks(notify_callback notify_cb, - data_callback data_cb, - data_callback_timestamp data_cb_timestamp, + virtual void setCallbacks(camera_notify_callback notify_cb, + camera_data_callback data_cb, + camera_data_timestamp_callback data_cb_timestamp, + camera_request_memory get_memory, void* arg); /** * Enable a message, or set of messages. */ virtual void enableMsgType(int32_t msgType); + virtual int setPreviewWindow( struct preview_stream_ops *window); /** * Disable a message, or a set of messages. */ @@ -65,7 +94,7 @@ public: virtual status_t startRecording(); virtual void stopRecording(); virtual bool recordingEnabled(); - virtual void releaseRecordingFrame(const sp<IMemory>& mem); + virtual void releaseRecordingFrame(const void* opaque); virtual status_t autoFocus(); virtual status_t cancelAutoFocus(); @@ -76,14 +105,12 @@ public: virtual CameraParameters getParameters() const; virtual void release(); virtual status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2); + CameraHardware(int cameraId); - static sp<CameraHardwareInterface> createInstance(int cameraId); + virtual ~CameraHardware(); private: - CameraHardware(int cameraId); - virtual ~CameraHardware(); - static wp<CameraHardwareInterface> singleton; static const int kBufferCount = 4; @@ -112,8 +139,9 @@ private: static int beginPictureThread(void *cookie); int pictureThread(); - + camera_request_memory mRequestMemory; mutable Mutex mLock; + preview_stream_ops_t* mNativeWindow; int mCameraId; CameraParameters mParameters; @@ -143,9 +171,9 @@ private: int nQueued; int nDequeued; V4L2Camera camera; - notify_callback mNotifyFn; - data_callback mDataFn; - data_callback_timestamp mTimestampFn; + camera_notify_callback mNotifyFn; + camera_data_callback mDataFn; + camera_data_timestamp_callback mTimestampFn; void* mUser; int32_t mMsgEnabled; diff --git a/libcamera/CameraHardwareInterface.h b/libcamera/CameraHardwareInterface.h new file mode 100644 index 0000000..35c5aa1 --- /dev/null +++ b/libcamera/CameraHardwareInterface.h @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2008 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 ANDROID_HARDWARE_CAMERA_HARDWARE_INTERFACE_H +#define ANDROID_HARDWARE_CAMERA_HARDWARE_INTERFACE_H + +#include <binder/IMemory.h> +#include <utils/RefBase.h> +#include <surfaceflinger/ISurface.h> +#include <camera/Camera.h> +#include <camera/CameraParameters.h> + +namespace android { + +class Overlay; + +/** + * The size of image for display. + */ +typedef struct image_rect_struct +{ + uint32_t width; /* Image width */ + uint32_t height; /* Image height */ +} image_rect_type; + + +typedef void (*notify_callback)(int32_t msgType, + int32_t ext1, + int32_t ext2, + void* user); + +typedef void (*data_callback)(int32_t msgType, + const sp<IMemory>& dataPtr, + void* user); + +typedef void (*data_callback_timestamp)(nsecs_t timestamp, + int32_t msgType, + const sp<IMemory>& dataPtr, + void* user); + +/** + * CameraHardwareInterface.h defines the interface to the + * camera hardware abstraction layer, used for setting and getting + * parameters, live previewing, and taking pictures. + * + * It is a referenced counted interface with RefBase as its base class. + * CameraService calls openCameraHardware() to retrieve a strong pointer to the + * instance of this interface and may be called multiple times. The + * following steps describe a typical sequence: + * + * -# After CameraService calls openCameraHardware(), getParameters() and + * setParameters() are used to initialize the camera instance. + * CameraService calls getPreviewHeap() to establish access to the + * preview heap so it can be registered with SurfaceFlinger for + * efficient display updating while in preview mode. + * -# startPreview() is called. The camera instance then periodically + * sends the message CAMERA_MSG_PREVIEW_FRAME (if enabled) each time + * a new preview frame is available. If data callback code needs to use + * this memory after returning, it must copy the data. + * + * Prior to taking a picture, CameraService calls autofocus(). When auto + * focusing has completed, the camera instance sends a CAMERA_MSG_FOCUS notification, + * which informs the application whether focusing was successful. The camera instance + * only sends this message once and it is up to the application to call autoFocus() + * again if refocusing is desired. + * + * CameraService calls takePicture() to request the camera instance take a + * picture. At this point, if a shutter, postview, raw, and/or compressed callback + * is desired, the corresponding message must be enabled. As with CAMERA_MSG_PREVIEW_FRAME, + * any memory provided in a data callback must be copied if it's needed after returning. + */ +class CameraHardwareInterface : public virtual RefBase { +public: + virtual ~CameraHardwareInterface() { } + + /** Return the IMemoryHeap for the preview image heap */ + virtual sp<IMemoryHeap> getPreviewHeap() const = 0; + + /** Return the IMemoryHeap for the raw image heap */ + virtual sp<IMemoryHeap> getRawHeap() const = 0; + + /** Set the notification and data callbacks */ + virtual void setCallbacks(notify_callback notify_cb, + data_callback data_cb, + data_callback_timestamp data_cb_timestamp, + void* user) = 0; + + /** + * The following three functions all take a msgtype, + * which is a bitmask of the messages defined in + * include/ui/Camera.h + */ + + /** + * Enable a message, or set of messages. + */ + virtual void enableMsgType(int32_t msgType) = 0; + + /** + * Disable a message, or a set of messages. + */ + virtual void disableMsgType(int32_t msgType) = 0; + + /** + * Query whether a message, or a set of messages, is enabled. + * Note that this is operates as an AND, if any of the messages + * queried are off, this will return false. + */ + virtual bool msgTypeEnabled(int32_t msgType) = 0; + + /** + * Start preview mode. + */ + virtual status_t startPreview() = 0; + + /** + * Only used if overlays are used for camera preview. + */ + virtual bool useOverlay() {return false;} + virtual status_t setOverlay(const sp<Overlay> &overlay) {return BAD_VALUE;} + + /** + * Stop a previously started preview. + */ + virtual void stopPreview() = 0; + + /** + * Returns true if preview is enabled. + */ + virtual bool previewEnabled() = 0; + + /** + * Start record mode. When a record image is available a CAMERA_MSG_VIDEO_FRAME + * message is sent with the corresponding frame. Every record frame must be released + * by calling releaseRecordingFrame(). + */ + virtual status_t startRecording() = 0; + + /** + * Stop a previously started recording. + */ + virtual void stopRecording() = 0; + + /** + * Returns true if recording is enabled. + */ + virtual bool recordingEnabled() = 0; + + /** + * Release a record frame previously returned by CAMERA_MSG_VIDEO_FRAME. + */ + virtual void releaseRecordingFrame(const sp<IMemory>& mem) = 0; + + /** + * Start auto focus, the notification callback routine is called + * with CAMERA_MSG_FOCUS once when focusing is complete. autoFocus() + * will be called again if another auto focus is needed. + */ + virtual status_t autoFocus() = 0; + + /** + * Cancels auto-focus function. If the auto-focus is still in progress, + * this function will cancel it. Whether the auto-focus is in progress + * or not, this function will return the focus position to the default. + * If the camera does not support auto-focus, this is a no-op. + */ + virtual status_t cancelAutoFocus() = 0; + + /** + * Take a picture. + */ + virtual status_t takePicture() = 0; + + /** + * Cancel a picture that was started with takePicture. Calling this + * method when no picture is being taken is a no-op. + */ + virtual status_t cancelPicture() = 0; + + /** + * Set the camera parameters. This returns BAD_VALUE if any parameter is + * invalid or not supported. */ + virtual status_t setParameters(const CameraParameters& params) = 0; + + /** Return the camera parameters. */ + virtual CameraParameters getParameters() const = 0; + + /** + * Send command to camera driver. + */ + virtual status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) = 0; + + /** + * Release the hardware resources owned by this object. Note that this is + * *not* done in the destructor. + */ + virtual void release() = 0; + + /** + * Dump state of the camera hardware + */ + virtual status_t dump(int fd, const Vector<String16>& args) const = 0; +}; + +/** + * The functions need to be provided by the camera HAL. + * + * If getNumberOfCameras() returns N, the valid cameraId for getCameraInfo() + * and openCameraHardware() is 0 to N-1. + */ +extern "C" int HAL_getNumberOfCameras(); +extern "C" void HAL_getCameraInfo(int cameraId, struct CameraInfo* cameraInfo); +/* HAL should return NULL if it fails to open camera hardware. */ +extern "C" sp<CameraHardwareInterface> HAL_openCameraHardware(int cameraId); + +}; // namespace android + +#endif diff --git a/libcamera/V4L2Camera.cpp b/libcamera/V4L2Camera.cpp index 78e17b0..90fc123 100644 --- a/libcamera/V4L2Camera.cpp +++ b/libcamera/V4L2Camera.cpp @@ -17,6 +17,7 @@ extern "C" { /* Android jpeglib.h missed extern "C" */ #include <jpeglib.h> + void convertYUYVtoRGB565(unsigned char *buf, unsigned char *rgb, int width, int height); } namespace android { @@ -198,7 +199,7 @@ int V4L2Camera::StopStreaming () return 0; } -void V4L2Camera::GrabPreviewFrame (void *previewBuffer) +void * V4L2Camera::GrabPreviewFrame () { unsigned char *tmpBuffer; int ret; @@ -209,21 +210,22 @@ void V4L2Camera::GrabPreviewFrame (void *previewBuffer) /* DQ */ ret = ioctl(fd, VIDIOC_DQBUF, &videoIn->buf); if (ret < 0) { - //LOGE("GrabPreviewFrame: VIDIOC_DQBUF Failed"); - - return; + LOGE("GrabPreviewFrame: VIDIOC_DQBUF Failed"); + return NULL; } nDequeued++; + return videoIn->mem[videoIn->buf.index]; +} - memcpy (previewBuffer, videoIn->mem[videoIn->buf.index], (size_t) videoIn->buf.bytesused); +void V4L2Camera::ReleasePreviewFrame () +{ + int ret; ret = ioctl(fd, VIDIOC_QBUF, &videoIn->buf); + nQueued++; if (ret < 0) { LOGE("GrabPreviewFrame: VIDIOC_QBUF Failed"); return; } - - nQueued++; - } @@ -296,7 +298,7 @@ int MemoryStream::readPipe() return 0; } -sp<IMemory> V4L2Camera::GrabJpegFrame () +camera_memory_t* V4L2Camera::GrabJpegFrame (camera_request_memory mRequestMemory) { int ret; @@ -327,13 +329,11 @@ sp<IMemory> V4L2Camera::GrabJpegFrame () saveYUYVtoJPEG((unsigned char *)videoIn->mem[videoIn->buf.index], videoIn->width, videoIn->height, strm, 100); strm.closeStream(); size_t fileSize = strm.getOffset(); - - sp<MemoryHeapBase> mjpegPictureHeap = new MemoryHeapBase(fileSize); - sp<MemoryBase> jpegmemBase = new MemoryBase(mjpegPictureHeap, 0, fileSize); - memcpy(mjpegPictureHeap->base(), tmpBuf, fileSize); + camera_memory_t* picture = mRequestMemory(-1,fileSize,1,NULL); + memcpy(picture->data, tmpBuf, fileSize); delete[] tmpBuf; - return jpegmemBase; + return picture; } return NULL; diff --git a/libcamera/V4L2Camera.h b/libcamera/V4L2Camera.h index 97255ec..03aa0c7 100644 --- a/libcamera/V4L2Camera.h +++ b/libcamera/V4L2Camera.h @@ -17,6 +17,7 @@ #include <binder/MemoryHeapBase.h> #include <linux/videodev.h> +#include <hardware/camera.h> namespace android { struct vdIn { @@ -47,9 +48,10 @@ public: int StartStreaming (); int StopStreaming (); - void GrabPreviewFrame (void *previewBuffer); + void * GrabPreviewFrame (); + void ReleasePreviewFrame (); sp<IMemory> GrabRawFrame (); - sp<IMemory> GrabJpegFrame (); + camera_memory_t* GrabJpegFrame (camera_request_memory mRequestMemory); private: struct vdIn *videoIn; diff --git a/libcamera/V4L2CameraHal.h b/libcamera/V4L2CameraHal.h new file mode 100644 index 0000000..e55d78d --- /dev/null +++ b/libcamera/V4L2CameraHal.h @@ -0,0 +1,151 @@ + +#include <utils/threads.h> +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <time.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <utils/Log.h> +#include <utils/threads.h> +#include <linux/videodev2.h> +#include "binder/MemoryBase.h" +#include "binder/MemoryHeapBase.h" +#include <utils/threads.h> +#include <camera/CameraParameters.h> +#include <hardware/camera.h> +#include <sys/ioctl.h> +#include <utils/threads.h> + +using namespace android; + class PreviewThread : public Thread { + //CameraHardware* mHardware; + public: + PreviewThread(/*CameraHardware* hw*/) + : Thread(false)/*, mHardware(hw)*/ { } + virtual void onFirstRef() { + run("CameraPreviewThread", PRIORITY_URGENT_DISPLAY); + } + virtual bool threadLoop() { + //mHardware->previewThread(); + // loop until we need to quit + return true; + } + }; +class V4L2CameraHal : public RefBase +{ + V4L2Camera camera; + + // protected by mLock + sp<PreviewThread> mPreviewThread; + static CameraParameters mParameters; + static int32_t mMsgEnabled; +/** + * Enable a message, or set of messages. + */ + virtual void enableMsgType(int32_t msgType); + + /** + * Disable a message, or a set of messages. + */ + virtual void disableMsgType(int32_t msgType); + + /** + * Query whether a message, or a set of messages, is enabled. + * Note that this is operates as an AND, if any of the messages + * queried are off, this will return false. + */ + virtual bool msgTypeEnabled(int32_t msgType); + + virtual void stopPreview(); + virtual bool previewEnabled(); + + virtual status_t startRecording(); + virtual void stopRecording(); + virtual bool recordingEnabled(); + virtual void releaseRecordingFrame(const sp<IMemory>& mem); + + virtual status_t autoFocus(); + virtual status_t cancelAutoFocus(); + virtual status_t takePicture(); + virtual status_t cancelPicture(); + virtual status_t dump(int fd, const Vector<String16>& args) const; + virtual status_t setParameters(const CameraParameters& params); + virtual CameraParameters getParameters() const; + virtual void release(); + virtual status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2); +private: + virtual ~CameraHardware(); + + static wp<CameraHardwareInterface> singleton; + + static const int kBufferCount = 4; + + class PreviewThread : public Thread { + CameraHardware* mHardware; + public: + PreviewThread(CameraHardware* hw) + : Thread(false), mHardware(hw) { } + virtual void onFirstRef() { + run("CameraPreviewThread", PRIORITY_URGENT_DISPLAY); + } + virtual bool threadLoop() { + mHardware->previewThread(); + // loop until we need to quit + return true; + } + }; + + void initDefaultParameters(); + bool initHeapLocked(); + + int previewThread(); + + static int beginAutoFocusThread(void *cookie); + int autoFocusThread(); + + static int beginPictureThread(void *cookie); + int pictureThread(); + + mutable Mutex mLock; + + int mCameraId; + CameraParameters mParameters; + + sp<MemoryHeapBase> mHeap; + sp<MemoryBase> mBuffer; + + sp<MemoryHeapBase> mPreviewHeap; + sp<MemoryHeapBase> mRawHeap; + sp<MemoryHeapBase> mRecordHeap; + sp<MemoryBase> mRecordBuffer; + + bool mPreviewRunning; + bool mRecordRunning; + int mPreviewFrameSize; + + // protected by mLock + sp<PreviewThread> mPreviewThread; + + // only used from PreviewThread + int mCurrentPreviewFrame; + + void * framebuffer; + bool previewStopped; + int camera_device; + void* mem[4]; + int nQueued; + int nDequeued; + V4L2Camera camera; + notify_callback mNotifyFn; + data_callback mDataFn; + data_callback_timestamp mTimestampFn; + void* mUser; + int32_t mMsgEnabled; + + +} diff --git a/libcamera/rgbconvert.c b/libcamera/rgbconvert.c new file mode 100644 index 0000000..d1e832b --- /dev/null +++ b/libcamera/rgbconvert.c @@ -0,0 +1,50 @@ +static void yuv_to_rgb16(unsigned char y, unsigned char u, unsigned char v, unsigned char *rgb) +{ + int r,g,b; + int z; + int rgb16; + + z = 0; + + r = 1.164 * (y - 16) + 1.596 * (v - 128); + g = 1.164 * (y - 16) - 0.813 * (v - 128) - 0.391 * (u -128); + b = 1.164 * (y - 16) + 2.018 * (u - 128); + + if (r > 255) r = 255; + if (g > 255) g = 255; + if (b > 255) b = 255; + + if (r < 0) r = 0; + if (g < 0) g = 0; + if (b < 0) b = 0; + + rgb16 = (int)(((r >> 3)<<11) | ((g >> 2) << 5)| ((b >> 3) << 0)); + + *rgb = (unsigned char)(rgb16 & 0xFF); + rgb++; + *rgb = (unsigned char)((rgb16 & 0xFF00) >> 8); + +} + + +void convertYUYVtoRGB565(unsigned char *buf, unsigned char *rgb, int width, int height) +{ + int x,y,z=0; + int blocks; + + blocks = (width * height) * 2; + + for (y = 0; y < blocks; y+=4) { + unsigned char Y1, Y2, U, V; + + Y1 = buf[y + 0]; + U = buf[y + 1]; + Y2 = buf[y + 2]; + V = buf[y + 3]; + + yuv_to_rgb16(Y1, U, V, &rgb[y]); + yuv_to_rgb16(Y2, U, V, &rgb[y + 2]); + } + +} + |