| /* |
| * Copyright (C) 2011 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 HW_EMULATOR_CAMERA_EMULATED_CAMERA_DEVICE_H |
| #define HW_EMULATOR_CAMERA_EMULATED_CAMERA_DEVICE_H |
| |
| /* |
| * Contains declaration of an abstract class EmulatedCameraDevice that defines |
| * functionality expected from an emulated physical camera device: |
| * - Obtaining and setting camera device parameters |
| * - Capturing frames |
| * - Streaming video |
| * - etc. |
| */ |
| |
| #include <utils/threads.h> |
| #include <utils/KeyedVector.h> |
| #include <utils/String8.h> |
| #include "EmulatedCameraCommon.h" |
| #include "Converters.h" |
| |
| namespace android { |
| |
| class EmulatedCamera; |
| |
| /* Encapsulates an abstract class EmulatedCameraDevice that defines |
| * functionality expected from an emulated physical camera device: |
| * - Obtaining and setting camera device parameters |
| * - Capturing frames |
| * - Streaming video |
| * - etc. |
| */ |
| class EmulatedCameraDevice { |
| public: |
| /* Constructs EmulatedCameraDevice instance. |
| * Param: |
| * camera_hal - Emulated camera that implements the camera HAL API, and |
| * manages (contains) this object. |
| */ |
| explicit EmulatedCameraDevice(EmulatedCamera* camera_hal); |
| |
| /* Destructs EmulatedCameraDevice instance. */ |
| virtual ~EmulatedCameraDevice(); |
| |
| /*************************************************************************** |
| * Emulated camera device abstract interface |
| **************************************************************************/ |
| |
| public: |
| /* Connects to the camera device. |
| * This method must be called on an initialized instance of this class. |
| * Return: |
| * NO_ERROR on success, or an appropriate error status. |
| */ |
| virtual status_t connectDevice() = 0; |
| |
| /* Disconnects from the camera device. |
| * Return: |
| * NO_ERROR on success, or an appropriate error status. If this method is |
| * called for already disconnected, or uninitialized instance of this class, |
| * a successful status must be returned from this method. If this method is |
| * called for an instance that is in the "started" state, this method must |
| * return a failure. |
| */ |
| virtual status_t disconnectDevice() = 0; |
| |
| /* Starts the camera device. |
| * This method tells the camera device to start capturing frames of the given |
| * dimensions for the given pixel format. Note that this method doesn't start |
| * the delivery of the captured frames to the emulated camera. Call |
| * startDeliveringFrames method to start delivering frames. This method must |
| * be called on a connected instance of this class. If it is called on a |
| * disconnected instance, this method must return a failure. |
| * Param: |
| * width, height - Frame dimensions to use when capturing video frames. |
| * pix_fmt - Pixel format to use when capturing video frames. |
| * Return: |
| * NO_ERROR on success, or an appropriate error status. |
| */ |
| virtual status_t startDevice(int width, int height, uint32_t pix_fmt) = 0; |
| |
| /* Stops the camera device. |
| * This method tells the camera device to stop capturing frames. Note that |
| * this method doesn't stop delivering frames to the emulated camera. Always |
| * call stopDeliveringFrames prior to calling this method. |
| * Return: |
| * NO_ERROR on success, or an appropriate error status. If this method is |
| * called for an object that is not capturing frames, or is disconnected, |
| * or is uninitialized, a successful status must be returned from this |
| * method. |
| */ |
| virtual status_t stopDevice() = 0; |
| |
| /*************************************************************************** |
| * Emulated camera device public API |
| **************************************************************************/ |
| |
| public: |
| /* Initializes EmulatedCameraDevice instance. |
| * Derived classes should override this method in order to cache static |
| * properties of the physical device (list of supported pixel formats, frame |
| * sizes, etc.) If this method is called on an already initialized instance, |
| * it must return a successful status. |
| * Return: |
| * NO_ERROR on success, or an appropriate error status. |
| */ |
| virtual status_t Initialize(); |
| |
| /* Initializes the white balance modes parameters. |
| * The parameters are passed by each individual derived camera API to |
| * represent that different camera manufacturers may have different |
| * preferences on the white balance parameters. Green channel in the RGB |
| * color space is fixed to keep the luminance to be reasonably constant. |
| * |
| * Param: |
| * mode the text describing the current white balance mode |
| * r_scale the scale factor for the R channel in RGB space |
| * b_scale the scale factor for the B channel in RGB space. |
| */ |
| void initializeWhiteBalanceModes(const char* mode, |
| const float r_scale, |
| const float b_scale); |
| |
| /* Starts delivering frames captured from the camera device. |
| * This method will start the worker thread that would be pulling frames from |
| * the camera device, and will deliver the pulled frames back to the emulated |
| * camera via onNextFrameAvailable callback. This method must be called on a |
| * connected instance of this class with a started camera device. If it is |
| * called on a disconnected instance, or camera device has not been started, |
| * this method must return a failure. |
| * Param: |
| * one_burst - Controls how many frames should be delivered. If this |
| * parameter is 'true', only one captured frame will be delivered to the |
| * emulated camera. If this parameter is 'false', frames will keep |
| * coming until stopDeliveringFrames method is called. Typically, this |
| * parameter is set to 'true' only in order to obtain a single frame |
| * that will be used as a "picture" in takePicture method of the |
| * emulated camera. |
| * Return: |
| * NO_ERROR on success, or an appropriate error status. |
| */ |
| virtual status_t startDeliveringFrames(bool one_burst); |
| |
| /* Stops delivering frames captured from the camera device. |
| * This method will stop the worker thread started by startDeliveringFrames. |
| * Return: |
| * NO_ERROR on success, or an appropriate error status. |
| */ |
| virtual status_t stopDeliveringFrames(); |
| |
| /* Sets the exposure compensation for the camera device. |
| */ |
| void setExposureCompensation(const float ev); |
| |
| /* Sets the white balance mode for the device. |
| */ |
| void setWhiteBalanceMode(const char* mode); |
| |
| /* Gets current framebuffer, converted into preview frame format. |
| * This method must be called on a connected instance of this class with a |
| * started camera device. If it is called on a disconnected instance, or |
| * camera device has not been started, this method must return a failure. |
| * Note that this method should be called only after at least one frame has |
| * been captured and delivered. Otherwise it will return garbage in the |
| * preview frame buffer. Typically, this method shuld be called from |
| * onNextFrameAvailable callback. |
| * Param: |
| * buffer - Buffer, large enough to contain the entire preview frame. |
| * Return: |
| * NO_ERROR on success, or an appropriate error status. |
| */ |
| virtual status_t getCurrentPreviewFrame(void* buffer); |
| |
| /* Gets width of the frame obtained from the physical device. |
| * Return: |
| * Width of the frame obtained from the physical device. Note that value |
| * returned from this method is valid only in case if camera device has been |
| * started. |
| */ |
| inline int getFrameWidth() const |
| { |
| ALOGE_IF(!isStarted(), "%s: Device is not started", __FUNCTION__); |
| return mFrameWidth; |
| } |
| |
| /* Gets height of the frame obtained from the physical device. |
| * Return: |
| * Height of the frame obtained from the physical device. Note that value |
| * returned from this method is valid only in case if camera device has been |
| * started. |
| */ |
| inline int getFrameHeight() const |
| { |
| ALOGE_IF(!isStarted(), "%s: Device is not started", __FUNCTION__); |
| return mFrameHeight; |
| } |
| |
| /* Gets byte size of the current frame buffer. |
| * Return: |
| * Byte size of the frame buffer. Note that value returned from this method |
| * is valid only in case if camera device has been started. |
| */ |
| inline size_t getFrameBufferSize() const |
| { |
| ALOGE_IF(!isStarted(), "%s: Device is not started", __FUNCTION__); |
| return mFrameBufferSize; |
| } |
| |
| /* Gets number of pixels in the current frame buffer. |
| * Return: |
| * Number of pixels in the frame buffer. Note that value returned from this |
| * method is valid only in case if camera device has been started. |
| */ |
| inline int getPixelNum() const |
| { |
| ALOGE_IF(!isStarted(), "%s: Device is not started", __FUNCTION__); |
| return mTotalPixels; |
| } |
| |
| /* Gets pixel format of the frame that camera device streams to this class. |
| * Throughout camera framework, there are three different forms of pixel |
| * format representation: |
| * - Original format, as reported by the actual camera device. Values for |
| * this format are declared in bionic/libc/kernel/common/linux/videodev2.h |
| * - String representation as defined in CameraParameters::PIXEL_FORMAT_XXX |
| * strings in frameworks/base/include/camera/CameraParameters.h |
| * - HAL_PIXEL_FORMAT_XXX format, as defined in system/core/include/system/graphics.h |
| * Since emulated camera device gets its data from the actual device, it gets |
| * pixel format in the original form. And that's the pixel format |
| * representation that will be returned from this method. HAL components will |
| * need to translate value returned from this method to the appropriate form. |
| * This method must be called only on started instance of this class, since |
| * it's applicable only when camera device is ready to stream frames. |
| * Param: |
| * pix_fmt - Upon success contains the original pixel format. |
| * Return: |
| * Current framebuffer's pixel format. Note that value returned from this |
| * method is valid only in case if camera device has been started. |
| */ |
| inline uint32_t getOriginalPixelFormat() const |
| { |
| ALOGE_IF(!isStarted(), "%s: Device is not started", __FUNCTION__); |
| return mPixelFormat; |
| } |
| |
| /* |
| * State checkers. |
| */ |
| |
| inline bool isInitialized() const { |
| /* Instance is initialized when the worker thread has been successfuly |
| * created (but not necessarily started). */ |
| return mWorkerThread.get() != NULL && mState != ECDS_CONSTRUCTED; |
| } |
| inline bool isConnected() const { |
| /* Instance is connected when its status is either"connected", or |
| * "started". */ |
| return mState == ECDS_CONNECTED || mState == ECDS_STARTED; |
| } |
| inline bool isStarted() const { |
| return mState == ECDS_STARTED; |
| } |
| |
| /**************************************************************************** |
| * Emulated camera device private API |
| ***************************************************************************/ |
| protected: |
| /* Performs common validation and calculation of startDevice parameters. |
| * Param: |
| * width, height, pix_fmt - Parameters passed to the startDevice method. |
| * Return: |
| * NO_ERROR on success, or an appropriate error status. |
| */ |
| virtual status_t commonStartDevice(int width, int height, uint32_t pix_fmt); |
| |
| /* Performs common cleanup on stopDevice. |
| * This method will undo what commonStartDevice had done. |
| */ |
| virtual void commonStopDevice(); |
| |
| /** Computes a luminance value after taking the exposure compensation. |
| * value into account. |
| * |
| * Param: |
| * inputY - The input luminance value. |
| * Return: |
| * The luminance value after adjusting the exposure compensation. |
| */ |
| inline uint8_t changeExposure(const uint8_t& inputY) const { |
| return static_cast<uint8_t>(clamp(static_cast<float>(inputY) * |
| mExposureCompensation)); |
| } |
| |
| /** Computes the pixel value in YUV space after adjusting to the current |
| * white balance mode. |
| */ |
| void changeWhiteBalance(uint8_t& y, uint8_t& u, uint8_t& v) const; |
| |
| /**************************************************************************** |
| * Worker thread management. |
| * Typicaly when emulated camera device starts capturing frames from the |
| * actual device, it does that in a worker thread created in StartCapturing, |
| * and terminated in StopCapturing. Since this is such a typical scenario, |
| * it makes sence to encapsulate worker thread management in the base class |
| * for all emulated camera devices. |
| ***************************************************************************/ |
| |
| protected: |
| /* Starts the worker thread. |
| * Typically, worker thread is started from startDeliveringFrames method of |
| * this class. |
| * Param: |
| * one_burst - Controls how many times thread loop should run. If this |
| * parameter is 'true', thread routine will run only once If this |
| * parameter is 'false', thread routine will run until stopWorkerThread |
| * method is called. See startDeliveringFrames for more info. |
| * Return: |
| * NO_ERROR on success, or an appropriate error status. |
| */ |
| virtual status_t startWorkerThread(bool one_burst); |
| |
| /* Stops the worker thread. |
| * Note that this method will always wait for the worker thread to terminate. |
| * Typically, worker thread is started from stopDeliveringFrames method of |
| * this class. |
| * Return: |
| * NO_ERROR on success, or an appropriate error status. |
| */ |
| virtual status_t stopWorkerThread(); |
| |
| /* Implementation of the worker thread routine. |
| * In the default implementation of the worker thread routine we simply |
| * return 'false' forcing the thread loop to exit, and the thread to |
| * terminate. Derived class should override that method to provide there the |
| * actual frame delivery. |
| * Return: |
| * true To continue thread loop (this method will be called again), or false |
| * to exit the thread loop and to terminate the thread. |
| */ |
| virtual bool inWorkerThread(); |
| |
| /* Encapsulates a worker thread used by the emulated camera device. |
| */ |
| friend class WorkerThread; |
| class WorkerThread : public Thread { |
| |
| /**************************************************************************** |
| * Public API |
| ***************************************************************************/ |
| |
| public: |
| inline explicit WorkerThread(EmulatedCameraDevice* camera_dev) |
| : Thread(true), // Callbacks may involve Java calls. |
| mCameraDevice(camera_dev), |
| mThreadControl(-1), |
| mControlFD(-1) |
| { |
| } |
| |
| inline ~WorkerThread() |
| { |
| ALOGW_IF(mThreadControl >= 0 || mControlFD >= 0, |
| "%s: Control FDs are opened in the destructor", |
| __FUNCTION__); |
| if (mThreadControl >= 0) { |
| close(mThreadControl); |
| } |
| if (mControlFD >= 0) { |
| close(mControlFD); |
| } |
| } |
| |
| /* Starts the thread |
| * Param: |
| * one_burst - Controls how many times thread loop should run. If |
| * this parameter is 'true', thread routine will run only once |
| * If this parameter is 'false', thread routine will run until |
| * stopThread method is called. See startWorkerThread for more |
| * info. |
| * Return: |
| * NO_ERROR on success, or an appropriate error status. |
| */ |
| inline status_t startThread(bool one_burst) |
| { |
| mOneBurst = one_burst; |
| return run(NULL, ANDROID_PRIORITY_URGENT_DISPLAY, 0); |
| } |
| |
| /* Overriden base class method. |
| * It is overriden in order to provide one-time initialization just |
| * prior to starting the thread routine. |
| */ |
| status_t readyToRun(); |
| |
| /* Stops the thread. */ |
| status_t stopThread(); |
| |
| /* Values returned from the Select method of this class. */ |
| enum SelectRes { |
| /* A timeout has occurred. */ |
| TIMEOUT, |
| /* Data are available for read on the provided FD. */ |
| READY, |
| /* Thread exit request has been received. */ |
| EXIT_THREAD, |
| /* An error has occurred. */ |
| ERROR |
| }; |
| |
| /* Select on an FD event, keeping in mind thread exit message. |
| * Param: |
| * fd - File descriptor on which to wait for an event. This |
| * parameter may be negative. If it is negative this method will |
| * only wait on a control message to the thread. |
| * timeout - Timeout in microseconds. 0 indicates no timeout (wait |
| * forever). |
| * Return: |
| * See SelectRes enum comments. |
| */ |
| SelectRes Select(int fd, int timeout); |
| |
| /**************************************************************************** |
| * Private API |
| ***************************************************************************/ |
| |
| private: |
| /* Implements abstract method of the base Thread class. */ |
| bool threadLoop() |
| { |
| /* Simply dispatch the call to the containing camera device. */ |
| if (mCameraDevice->inWorkerThread()) { |
| /* Respect "one burst" parameter (see startThread). */ |
| return !mOneBurst; |
| } else { |
| return false; |
| } |
| } |
| |
| /* Containing camera device object. */ |
| EmulatedCameraDevice* mCameraDevice; |
| |
| /* FD that is used to send control messages into the thread. */ |
| int mThreadControl; |
| |
| /* FD that thread uses to receive control messages. */ |
| int mControlFD; |
| |
| /* Controls number of times the thread loop runs. |
| * See startThread for more information. */ |
| bool mOneBurst; |
| |
| /* Enumerates control messages that can be sent into the thread. */ |
| enum ControlMessage { |
| /* Stop the thread. */ |
| THREAD_STOP |
| }; |
| }; |
| |
| /* Worker thread accessor. */ |
| inline WorkerThread* getWorkerThread() const |
| { |
| return mWorkerThread.get(); |
| } |
| |
| /**************************************************************************** |
| * Data members |
| ***************************************************************************/ |
| |
| protected: |
| /* Locks this instance for parameters, state, etc. change. */ |
| Mutex mObjectLock; |
| |
| /* Worker thread that is used in frame capturing. */ |
| sp<WorkerThread> mWorkerThread; |
| |
| /* Timestamp of the current frame. */ |
| nsecs_t mCurFrameTimestamp; |
| |
| /* Emulated camera object containing this instance. */ |
| EmulatedCamera* mCameraHAL; |
| |
| /* Framebuffer containing the current frame. */ |
| uint8_t* mCurrentFrame; |
| |
| /* |
| * Framebuffer properties. |
| */ |
| |
| /* Byte size of the framebuffer. */ |
| size_t mFrameBufferSize; |
| |
| /* Original pixel format (one of the V4L2_PIX_FMT_XXX values, as defined in |
| * bionic/libc/kernel/common/linux/videodev2.h */ |
| uint32_t mPixelFormat; |
| |
| /* Frame width */ |
| int mFrameWidth; |
| |
| /* Frame height */ |
| int mFrameHeight; |
| |
| /* Total number of pixels */ |
| int mTotalPixels; |
| |
| /* Exposure compensation value */ |
| float mExposureCompensation; |
| |
| float* mWhiteBalanceScale; |
| |
| DefaultKeyedVector<String8, float*> mSupportedWhiteBalanceScale; |
| |
| /* Defines possible states of the emulated camera device object. |
| */ |
| enum EmulatedCameraDeviceState { |
| /* Object has been constructed. */ |
| ECDS_CONSTRUCTED, |
| /* Object has been initialized. */ |
| ECDS_INITIALIZED, |
| /* Object has been connected to the physical device. */ |
| ECDS_CONNECTED, |
| /* Camera device has been started. */ |
| ECDS_STARTED, |
| }; |
| |
| /* Object state. */ |
| EmulatedCameraDeviceState mState; |
| }; |
| |
| }; /* namespace android */ |
| |
| #endif /* HW_EMULATOR_CAMERA_EMULATED_CAMERA_DEVICE_H */ |