C++程序  |  200行  |  5.46 KB

/*
 * 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.
 */

/*
 * This class is an abstraction to treat a capture device (e.g., a webcam)
 * connected to the host computer as an image sensor.  The capture device must
 * support both 360x240 and 640x480 resolutions.
 *
 * The characteristics of this sensor don't correspond to any actual sensor,
 * but are not far off typical sensors.
 */

#ifndef HW_EMULATOR_CAMERA2_QEMU_SENSOR_H
#define HW_EMULATOR_CAMERA2_QEMU_SENSOR_H

#include "fake-pipeline2/Base.h"
#include "QemuClient.h"

#include <utils/Mutex.h>
#include <utils/Thread.h>
#include <utils/Timers.h>

namespace android {

class EmulatedFakeCamera2;

class QemuSensor: private Thread, public virtual RefBase {
  public:
   /*
    * Args:
    *     deviceName: File path where the capture device can be found (e.g.,
    *                 "/dev/video0").
    *     width: Width of pixel array.
    *     height: Height of pixel array.
    */
    QemuSensor(const char *deviceName, uint32_t width, uint32_t height);
    ~QemuSensor();

    /*
     * Power Control
     */

    status_t startUp();
    status_t shutDown();

    /*
     * Controls that can be updated every frame.
     */

    void setFrameDuration(uint64_t ns);

    /*
     * Each Buffer in "buffers" must be at least stride*height*2 bytes in size.
     */
    void setDestinationBuffers(Buffers *buffers);
    /*
     * To simplify tracking the sensor's current frame.
     */
    void setFrameNumber(uint32_t frameNumber);

    /*
     * Synchronizing with sensor operation (vertical sync).
     */

    /*
     * Wait until the sensor outputs its next vertical sync signal, meaning it
     * is starting readout of its latest frame of data.
     *
     * Returns:
     *     true if vertical sync is signaled; false if the wait timed out.
     */
    bool waitForVSync(nsecs_t reltime);

    /*
     * Wait until a new frame has been read out, and then return the time
     * capture started. May return immediately if a new frame has been pushed
     * since the last wait for a new frame.
     *
     * Returns:
     *     true if new frame is returned; false if timed out.
     */
    bool waitForNewFrame(nsecs_t reltime, nsecs_t *captureTime);

    /*
     * Interrupt event servicing from the sensor. Only triggers for sensor
     * cycles that have valid buffers to write to.
     */
    struct QemuSensorListener {
        enum Event {
            EXPOSURE_START,
        };

        virtual void onQemuSensorEvent(uint32_t frameNumber, Event e,
                nsecs_t timestamp) = 0;
        virtual ~QemuSensorListener();
    };

    void setQemuSensorListener(QemuSensorListener *listener);

    /*
     * Static Sensor Characteristics
     */
    const uint32_t mWidth, mHeight;
    const uint32_t mActiveArray[4];

    static const nsecs_t kExposureTimeRange[2];
    static const nsecs_t kFrameDurationRange[2];
    static const nsecs_t kMinVerticalBlank;

    static const int32_t kSensitivityRange[2];
    static const uint32_t kDefaultSensitivity;

  private:
    int32_t mLastRequestWidth, mLastRequestHeight;

    /*
     * 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;

    CameraQemuClient mCameraQemuClient;
    const char *mDeviceName;

    // Always lock before accessing control parameters.
    Mutex mControlMutex;
    /*
     * Control Parameters
     */
    Condition mVSync;
    bool mGotVSync;
    uint64_t mFrameDuration;
    Buffers *mNextBuffers;
    uint32_t mFrameNumber;

    // Always lock before accessing readout variables.
    Mutex mReadoutMutex;
    /*
     * Readout Variables
     */
    Condition mReadoutAvailable;
    Condition mReadoutComplete;
    Buffers *mCapturedBuffers;
    nsecs_t mCaptureTime;
    QemuSensorListener *mListener;

    // Time of sensor startup (used for simulation zero-time point).
    nsecs_t mStartupTime;

  private:
    /*
     * Inherited Thread Virtual Overrides
     */
    virtual status_t readyToRun();
    /*
     * QemuSensor capture operation main loop.
     */
    virtual bool threadLoop();

    /*
     * Members only used by the processing thread.
     */
    nsecs_t mNextCaptureTime;
    Buffers *mNextCapturedBuffers;

    void captureRGBA(uint8_t *img, uint32_t width, uint32_t height,
            uint32_t stride, int64_t *timestamp);
    void captureRGB(uint8_t *img, uint32_t width, uint32_t height,
            uint32_t stride, int64_t *timestamp);
    void captureNV21(uint8_t *img, uint32_t width, uint32_t height,
            uint32_t stride, int64_t *timestamp);
};

}; // end of namespace android

#endif // HW_EMULATOR_CAMERA2_QEMU_SENSOR_H