C++程序  |  422行  |  13.14 KB

/*
 * Copyright (C) 2012 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_FAKE_CAMERA2_H
#define HW_EMULATOR_CAMERA_EMULATED_FAKE_CAMERA2_H

/*
 * Contains declaration of a class EmulatedFakeCamera2 that encapsulates
 * functionality of a fake camera that implements version 2 of the camera device
 * interface.
 */

#include <vector>

#include <utils/Condition.h>
#include <utils/KeyedVector.h>
#include <utils/String16.h>
#include <utils/String8.h>
#include "EmulatedCamera2.h"
#include "fake-pipeline2/Base.h"
#include "fake-pipeline2/JpegCompressor.h"
#include "fake-pipeline2/Sensor.h"

namespace android {

/* Encapsulates functionality of an advanced fake camera.  This camera contains
 * a simple simulation of a scene, sensor, and image processing pipeline.
 */
class EmulatedFakeCamera2 : public EmulatedCamera2 {
 public:
  /* Constructs EmulatedFakeCamera instance. */
  EmulatedFakeCamera2(int cameraId, bool facingBack,
                      struct hw_module_t *module);

  /* Destructs EmulatedFakeCamera instance. */
  ~EmulatedFakeCamera2();

  /****************************************************************************
   * EmulatedCamera2 virtual overrides.
   ***************************************************************************/

 public:
  /* Initializes EmulatedFakeCamera2 instance. */
  status_t Initialize(const cvd::CameraDefinition &props);

  /****************************************************************************
   * Camera Module API and generic hardware device API implementation
   ***************************************************************************/
 public:
  virtual status_t connectCamera(hw_device_t **device);

  virtual status_t plugCamera();
  virtual status_t unplugCamera();
  virtual camera_device_status_t getHotplugStatus();

  virtual status_t closeCamera();

  virtual status_t getCameraInfo(struct camera_info *info);

  /****************************************************************************
   * EmulatedCamera2 abstract API implementation.
   ***************************************************************************/
 protected:
  /** Request input queue */

  virtual int requestQueueNotify();

  /** Count of requests in flight */
  virtual int getInProgressCount();

  /** Cancel all captures in flight */
  // virtual int flushCapturesInProgress();

  /** Construct default request */
  virtual int constructDefaultRequest(int request_template,
                                      camera_metadata_t **request);

  virtual int allocateStream(uint32_t width, uint32_t height, int format,
                             const camera2_stream_ops_t *stream_ops,
                             uint32_t *stream_id, uint32_t *format_actual,
                             uint32_t *usage, uint32_t *max_buffers);

  virtual int registerStreamBuffers(uint32_t stream_id, int num_buffers,
                                    buffer_handle_t *buffers);

  virtual int releaseStream(uint32_t stream_id);

  // virtual int allocateReprocessStream(
  //         uint32_t width,
  //         uint32_t height,
  //         uint32_t format,
  //         const camera2_stream_ops_t *stream_ops,
  //         uint32_t *stream_id,
  //         uint32_t *format_actual,
  //         uint32_t *usage,
  //         uint32_t *max_buffers);

  virtual int allocateReprocessStreamFromStream(
      uint32_t output_stream_id, const camera2_stream_in_ops_t *stream_ops,
      uint32_t *stream_id);

  virtual int releaseReprocessStream(uint32_t stream_id);

  virtual int triggerAction(uint32_t trigger_id, int32_t ext1, int32_t ext2);

  /** Debug methods */

  virtual int dump(int fd);

 public:
  /****************************************************************************
   * Utility methods called by configure/readout threads and pipeline
   ***************************************************************************/

  // Get information about a given stream. Will lock mMutex
  const Stream &getStreamInfo(uint32_t streamId);
  const ReprocessStream &getReprocessStreamInfo(uint32_t streamId);

  // Notifies rest of camera subsystem of serious error
  void signalError();

 private:
  /****************************************************************************
   * Utility methods
   ***************************************************************************/
  /** Construct static camera metadata, two-pass */
  status_t constructStaticInfo(camera_metadata_t **info,
                               bool sizeRequest) const;

  /** Two-pass implementation of constructDefaultRequest */
  status_t constructDefaultRequest(int request_template,
                                   camera_metadata_t **request,
                                   bool sizeRequest) const;
  /** Helper function for constructDefaultRequest */
  static status_t addOrSize(camera_metadata_t *request, bool sizeRequest,
                            size_t *entryCount, size_t *dataCount, uint32_t tag,
                            const void *entry_data, size_t entry_count);

  /** Determine if the stream id is listed in any currently-in-flight
   * requests. Assumes mMutex is locked */
  bool isStreamInUse(uint32_t streamId);

  /** Determine if the reprocess stream id is listed in any
   * currently-in-flight requests. Assumes mMutex is locked */
  bool isReprocessStreamInUse(uint32_t streamId);

  /****************************************************************************
   * Pipeline controller threads
   ***************************************************************************/

  class ConfigureThread : public Thread {
   public:
    ConfigureThread(EmulatedFakeCamera2 *parent);
    ~ConfigureThread();

    status_t waitUntilRunning();
    status_t newRequestAvailable();
    status_t readyToRun();

    bool isStreamInUse(uint32_t id);
    int getInProgressCount();

   private:
    EmulatedFakeCamera2 *mParent;
    static const nsecs_t kWaitPerLoop = 10000000L;  // 10 ms

    bool mRunning;
    bool threadLoop();

    bool setupCapture();
    bool setupReprocess();

    bool configureNextCapture();
    bool configureNextReprocess();

    bool getBuffers();

    Mutex mInputMutex;  // Protects mActive, mRequestCount
    Condition mInputSignal;
    bool mActive;  // Whether we're waiting for input requests or actively
                   // working on them
    size_t mRequestCount;

    camera_metadata_t *mRequest;

    Mutex mInternalsMutex;  // Lock before accessing below members.
    bool mWaitingForReadout;
    bool mNextNeedsJpeg;
    bool mNextIsCapture;
    int32_t mNextFrameNumber;
    int64_t mNextExposureTime;
    int64_t mNextFrameDuration;
    int32_t mNextSensitivity;
    Buffers *mNextBuffers;
  };

  class ReadoutThread : public Thread, private JpegCompressor::JpegListener {
   public:
    ReadoutThread(EmulatedFakeCamera2 *parent);
    ~ReadoutThread();

    status_t readyToRun();

    // Input
    status_t waitUntilRunning();
    bool waitForReady(nsecs_t timeout);
    void setNextOperation(bool isCapture, camera_metadata_t *request,
                          Buffers *buffers);
    bool isStreamInUse(uint32_t id);
    int getInProgressCount();

   private:
    EmulatedFakeCamera2 *mParent;

    bool mRunning;
    bool threadLoop();

    bool readyForNextCapture();
    status_t collectStatisticsMetadata(camera_metadata_t *frame);

    // Inputs
    Mutex mInputMutex;  // Protects mActive, mInFlightQueue, mRequestCount
    Condition mInputSignal;
    Condition mReadySignal;

    bool mActive;

    static const int kInFlightQueueSize = 4;
    struct InFlightQueue {
      bool isCapture;
      camera_metadata_t *request;
      Buffers *buffers;
    } * mInFlightQueue;

    size_t mInFlightHead;
    size_t mInFlightTail;

    size_t mRequestCount;

    // Internals
    Mutex mInternalsMutex;

    bool mIsCapture;
    camera_metadata_t *mRequest;
    Buffers *mBuffers;

    // Jpeg completion listeners
    void onJpegDone(const StreamBuffer &jpegBuffer, bool success);
    void onJpegInputDone(const StreamBuffer &inputBuffer);
    nsecs_t mJpegTimestamp;
  };

  // 3A management thread (auto-exposure, focus, white balance)
  class ControlThread : public Thread {
   public:
    ControlThread(EmulatedFakeCamera2 *parent);
    ~ControlThread();

    status_t readyToRun();

    status_t waitUntilRunning();

    // Interpret request's control parameters and override
    // capture settings as needed
    status_t processRequest(camera_metadata_t *request);

    status_t triggerAction(uint32_t msgType, int32_t ext1, int32_t ext2);

   private:
    ControlThread(const ControlThread &t);
    ControlThread &operator=(const ControlThread &t);

    // Constants controlling fake 3A behavior
    static const nsecs_t kControlCycleDelay;
    static const nsecs_t kMinAfDuration;
    static const nsecs_t kMaxAfDuration;
    static const float kAfSuccessRate;
    static const float kContinuousAfStartRate;

    static const float kAeScanStartRate;
    static const nsecs_t kMinAeDuration;
    static const nsecs_t kMaxAeDuration;
    static const nsecs_t kMinPrecaptureAeDuration;
    static const nsecs_t kMaxPrecaptureAeDuration;

    static const nsecs_t kNormalExposureTime;
    static const nsecs_t kExposureJump;
    static const nsecs_t kMinExposureTime;

    EmulatedFakeCamera2 *mParent;

    bool mRunning;
    bool threadLoop();

    Mutex mInputMutex;  // Protects input methods
    Condition mInputSignal;

    // Trigger notifications
    bool mStartAf;
    bool mCancelAf;
    bool mStartPrecapture;

    // Latest state for 3A request fields
    uint8_t mControlMode;

    uint8_t mEffectMode;
    uint8_t mSceneMode;

    uint8_t mAfMode;
    bool mAfModeChange;

    uint8_t mAwbMode;
    uint8_t mAeMode;

    // Latest trigger IDs
    int32_t mAfTriggerId;
    int32_t mPrecaptureTriggerId;

    // Current state for 3A algorithms
    uint8_t mAfState;
    uint8_t mAeState;
    uint8_t mAwbState;
    bool mAeLock;

    // Current control parameters
    nsecs_t mExposureTime;

    // Private to threadLoop and its utility methods

    nsecs_t mAfScanDuration;
    nsecs_t mAeScanDuration;
    bool mLockAfterPassiveScan;

    // Utility methods for AF
    int processAfTrigger(uint8_t afMode, uint8_t afState);
    int maybeStartAfScan(uint8_t afMode, uint8_t afState);
    int updateAfScan(uint8_t afMode, uint8_t afState, nsecs_t *maxSleep);
    void updateAfState(uint8_t newState, int32_t triggerId);

    // Utility methods for precapture trigger
    int processPrecaptureTrigger(uint8_t aeMode, uint8_t aeState);
    int maybeStartAeScan(uint8_t aeMode, bool aeLock, uint8_t aeState);
    int updateAeScan(uint8_t aeMode, bool aeLock, uint8_t aeState,
                     nsecs_t *maxSleep);
    void updateAeState(uint8_t newState, int32_t triggerId);
  };

  /****************************************************************************
   * Static configuration information
   ***************************************************************************/
 private:
  static const uint32_t kMaxRawStreamCount = 1;
  static const uint32_t kMaxProcessedStreamCount = 3;
  static const uint32_t kMaxJpegStreamCount = 1;
  static const uint32_t kMaxReprocessStreamCount = 2;
  static const uint32_t kMaxBufferCount = 4;
  static const uint32_t kAvailableFormats[];
  static const uint32_t kAvailableRawSizes[];
  static const uint64_t kAvailableRawMinDurations[];
  static const uint32_t kAvailableProcessedSizesBack[];
  static const uint32_t kAvailableProcessedSizesFront[];
  static const uint64_t kAvailableProcessedMinDurations[];
  static const uint32_t kAvailableJpegSizesBack[];
  static const uint32_t kAvailableJpegSizesFront[];
  static const uint64_t kAvailableJpegMinDurations[];

  /****************************************************************************
   * Data members.
   ***************************************************************************/

 protected:
  /* Facing back (true) or front (false) switch. */
  bool mFacingBack;

 private:
  bool mIsConnected;

  int32_t mSensorWidth, mSensorHeight;

  /** Stream manipulation */
  uint32_t mNextStreamId;
  uint32_t mRawStreamCount;
  uint32_t mProcessedStreamCount;
  uint32_t mJpegStreamCount;

  std::vector<uint32_t> mAvailableRawSizes;
  std::vector<uint32_t> mAvailableProcessedSizes;
  std::vector<uint32_t> mAvailableJpegSizes;

  uint32_t mNextReprocessStreamId;
  uint32_t mReprocessStreamCount;

  KeyedVector<uint32_t, Stream> mStreams;
  KeyedVector<uint32_t, ReprocessStream> mReprocessStreams;

  /** Simulated hardware interfaces */
  sp<Sensor> mSensor;
  sp<JpegCompressor> mJpegCompressor;

  /** Pipeline control threads */
  sp<ConfigureThread> mConfigureThread;
  sp<ReadoutThread> mReadoutThread;
  sp<ControlThread> mControlThread;
};

}; /* namespace android */

#endif /* HW_EMULATOR_CAMERA_EMULATED_FAKE_CAMERA2_H */