/*
* Copyright (C) 2017 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_QEMU_CAMERA3_H
#define HW_EMULATOR_CAMERA_EMULATED_QEMU_CAMERA3_H
/*
* Contains declaration of a class EmulatedQemuCamera3 that encapsulates
* functionality of a video capture device that implements version 3 of the
* camera device interface.
*/
#include "EmulatedCamera3.h"
#include "fake-pipeline2/JpegCompressor.h"
#include "qemu-pipeline3/QemuSensor.h"
#include <CameraMetadata.h>
#include <utils/SortedVector.h>
#include <utils/List.h>
#include <utils/Mutex.h>
using ::android::hardware::camera::common::V1_0::helper::CameraMetadata;
namespace android {
/*
* Encapsulates functionality for a v3 HAL camera which interfaces with a video
* capture device on the host computer.
*
* NOTE: Currently, resolutions larger than 640x480 are susceptible to
* performance problems.
*
* TODO: Optimize to allow regular usage of higher resolutions.
*/
class EmulatedQemuCamera3 : public EmulatedCamera3,
private QemuSensor::QemuSensorListener {
public:
EmulatedQemuCamera3(int cameraId, struct hw_module_t* module);
virtual ~EmulatedQemuCamera3();
/*
* Args:
* deviceName: File path where the capture device can be found (e.g.,
* "/dev/video0").
* frameDims: Space-delimited resolutions with each dimension delimited
* by a comma (e.g., "640,480 320,240").
* facingDir: Contains either "front" or "back".
*/
virtual status_t Initialize(const char *deviceName,
const char *frameDims,
const char *facingDir);
/**************************************************************************
* Camera Module API and Generic Hardware Device API Implementation
*************************************************************************/
virtual status_t connectCamera(hw_device_t **device);
virtual status_t closeCamera();
virtual status_t getCameraInfo(struct camera_info *info);
protected:
/**************************************************************************
* EmulatedCamera3 Abstract API Implementation
*************************************************************************/
virtual status_t configureStreams(camera3_stream_configuration *streamList);
virtual status_t registerStreamBuffers(
const camera3_stream_buffer_set *bufferSet);
virtual const camera_metadata_t* constructDefaultRequestSettings(int type);
virtual status_t processCaptureRequest(camera3_capture_request *request);
virtual status_t flush();
private:
/*
* Get the requested capability set (from boot properties) for this camera
* and populate "mCapabilities".
*/
status_t getCameraCapabilities();
/*
* Extracts supported resolutions into "mResolutions".
*
* Args:
* frameDims: A string of space-delimited resolutions with each
* dimension delimited by a comma (e.g., "640,480 320,240").
*/
void parseResolutions(const char *frameDims);
bool hasCapability(AvailableCapabilities cap);
/*
* Build the static info metadata buffer for this device.
*/
status_t constructStaticInfo();
status_t process3A(CameraMetadata &settings);
status_t doFakeAE(CameraMetadata &settings);
status_t doFakeAF(CameraMetadata &settings);
status_t doFakeAWB(CameraMetadata &settings);
void update3A(CameraMetadata &settings);
/*
* Signal from readout thread that it doesn't have anything to do.
*/
void signalReadoutIdle();
/*
* Handle interrupt events from the sensor.
*/
void onQemuSensorEvent(uint32_t frameNumber, Event e, nsecs_t timestamp);
private:
/**************************************************************************
* Static Configuration Information
*************************************************************************/
static const uint32_t kMaxRawStreamCount = 0;
static const uint32_t kMaxProcessedStreamCount = 3;
static const uint32_t kMaxJpegStreamCount = 1;
static const uint32_t kMaxReprocessStreamCount = 0;
static const uint32_t kMaxBufferCount = 3;
// We need a positive stream ID to distinguish external buffers from
// sensor-generated buffers which use a nonpositive ID. Otherwise, HAL3 has
// no concept of a stream id.
static const uint32_t kGenericStreamId = 1;
static const int32_t kAvailableFormats[];
static const int64_t kSyncWaitTimeout = 10000000; // 10 ms
static const int32_t kMaxSyncTimeoutCount = 1000; // 1000 kSyncWaitTimeouts
static const uint32_t kFenceTimeoutMs = 2000; // 2 s
static const nsecs_t kJpegTimeoutNs = 5000000000l; // 5 s
/**************************************************************************
* Data Members
*************************************************************************/
// HAL interface serialization lock.
Mutex mLock;
const char *mDeviceName;
bool mFacingBack;
uint32_t mSensorWidth;
uint32_t mSensorHeight;
std::vector<std::pair<int32_t,int32_t>> mResolutions;
SortedVector<AvailableCapabilities> mCapabilities;
/*
* Cache for default templates. Once one is requested, the pointer must be
* valid at least until close() is called on the device.
*/
camera_metadata_t *mDefaultTemplates[CAMERA3_TEMPLATE_COUNT];
// Private stream information, stored in camera3_stream_t->priv.
struct PrivateStreamInfo {
bool alive;
};
// Shortcut to the input stream.
camera3_stream_t* mInputStream;
typedef List<camera3_stream_t*> StreamList;
typedef List<camera3_stream_t*>::iterator StreamIterator;
typedef Vector<camera3_stream_buffer> HalBufferVector;
// All streams, including input stream.
StreamList mStreams;
// Cached settings from latest submitted request.
CameraMetadata mPrevSettings;
// Fake Hardware Interfaces
sp<QemuSensor> mSensor;
sp<JpegCompressor> mJpegCompressor;
friend class JpegCompressor;
/*
* Processing thread for sending out results.
*/
class ReadoutThread : public Thread, private JpegCompressor::JpegListener {
public:
ReadoutThread(EmulatedQemuCamera3 *parent);
~ReadoutThread();
struct Request {
uint32_t frameNumber;
CameraMetadata settings;
HalBufferVector *buffers;
Buffers *sensorBuffers;
};
/*
* Interface to Parent Class
*/
/*
* Place request in the in-flight queue to wait for sensor capture.
*/
void queueCaptureRequest(const Request &r);
/*
* Test if the readout thread is idle (no in-flight requests, not
* currently reading out anything).
*/
bool isIdle();
/*
* Wait until isIdle is true.
*/
status_t waitForReadout();
private:
static const nsecs_t kWaitPerLoop = 10000000L; // 10 ms
static const nsecs_t kMaxWaitLoops = 1000;
static const size_t kMaxQueueSize = 2;
EmulatedQemuCamera3 *mParent;
Mutex mLock;
List<Request> mInFlightQueue;
Condition mInFlightSignal;
bool mThreadActive;
virtual bool threadLoop();
// Only accessed by threadLoop.
Request mCurrentRequest;
Mutex mJpegLock;
bool mJpegWaiting;
camera3_stream_buffer mJpegHalBuffer;
uint32_t mJpegFrameNumber;
/*
* Jpeg Completion Callbacks
*/
virtual void onJpegDone(const StreamBuffer &jpegBuffer, bool success);
virtual void onJpegInputDone(const StreamBuffer &inputBuffer);
};
sp<ReadoutThread> mReadoutThread;
/** Fake 3A constants */
static const nsecs_t kNormalExposureTime;
static const nsecs_t kFacePriorityExposureTime;
static const int kNormalSensitivity;
static const int kFacePrioritySensitivity;
// Rate of converging AE to new target value, as fraction of difference between
// current and target value.
static const float kExposureTrackRate;
// Minimum duration for precapture state. May be longer if slow to converge
// to target exposure
static const int kPrecaptureMinFrames;
// How often to restart AE 'scanning'
static const int kStableAeMaxFrames;
// Maximum stop below 'normal' exposure time that we'll wander to while
// pretending to converge AE. In powers of 2. (-2 == 1/4 as bright)
static const float kExposureWanderMin;
// Maximum stop above 'normal' exposure time that we'll wander to while
// pretending to converge AE. In powers of 2. (2 == 4x as bright)
static const float kExposureWanderMax;
/** Fake 3A state */
uint8_t mControlMode;
bool mFacePriority;
uint8_t mAeState;
uint8_t mAfState;
uint8_t mAwbState;
uint8_t mAeMode;
uint8_t mAfMode;
uint8_t mAwbMode;
int mAeCounter;
nsecs_t mAeCurrentExposureTime;
nsecs_t mAeTargetExposureTime;
int mAeCurrentSensitivity;
};
}; // end of namespace android
#endif // HW_EMULATOR_CAMERA_EMULATED_QEMU_CAMERA3_H