chromium/media/capture/video/chromeos/stream_buffer_manager.h

// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef MEDIA_CAPTURE_VIDEO_CHROMEOS_STREAM_BUFFER_MANAGER_H_
#define MEDIA_CAPTURE_VIDEO_CHROMEOS_STREAM_BUFFER_MANAGER_H_

#include <cstring>
#include <initializer_list>
#include <map>
#include <memory>
#include <optional>
#include <queue>
#include <set>
#include <unordered_map>
#include <vector>

#include "base/containers/flat_map.h"
#include "base/containers/queue.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/task/single_thread_task_runner.h"
#include "media/capture/video/chromeos/camera_device_context.h"
#include "media/capture/video/chromeos/camera_device_delegate.h"
#include "media/capture/video/chromeos/mojom/camera3.mojom.h"
#include "media/capture/video_capture_types.h"

namespace gfx {

class GpuMemoryBuffer;

}  // namespace gfx

namespace gpu {

class GpuMemoryBufferImpl;
class GpuMemoryBufferSupport;

}  // namespace gpu

namespace media {

class CameraBufferFactory;
class VideoCaptureBufferObserver;

struct BufferInfo;

// StreamBufferManager is responsible for managing the buffers of the
// stream.  StreamBufferManager allocates buffers according to the given
// stream configuration.
class CAPTURE_EXPORT StreamBufferManager final {
 public:
  using Buffer = VideoCaptureDevice::Client::Buffer;

  StreamBufferManager() = delete;

  StreamBufferManager(
      CameraDeviceContext* device_context,
      bool video_capture_use_gmb,
      std::unique_ptr<CameraBufferFactory> camera_buffer_factory,
      std::unique_ptr<VideoCaptureBufferObserver> buffer_observer);

  StreamBufferManager(const StreamBufferManager&) = delete;
  StreamBufferManager& operator=(const StreamBufferManager&) = delete;

  ~StreamBufferManager();

  void ReserveBuffer(StreamType stream_type);

  gfx::GpuMemoryBuffer* GetGpuMemoryBufferById(StreamType stream_type,
                                               uint64_t buffer_ipc_id);

  // Acquires the VCD client buffer specified by |stream_type| and
  // |buffer_ipc_id|, with optional rotation applied.  |rotation| is the
  // clockwise degrees that the source frame would be rotated to, and the valid
  // values are 0, 90, 180, and 270.  Returns the VideoCaptureFormat of the
  // returned buffer in |format|.
  //
  // TODO(crbug.com/990682): Remove the |rotation| arg when we disable the
  // camera frame rotation for good.
  std::optional<Buffer> AcquireBufferForClientById(StreamType stream_type,
                                                   uint64_t buffer_ipc_id,
                                                   VideoCaptureFormat* format);

  VideoCaptureFormat GetStreamCaptureFormat(StreamType stream_type);

  // Checks if all streams are available. For output stream, it is available if
  // it has free buffers. For input stream, it is always available.
  bool HasFreeBuffers(const std::set<StreamType>& stream_types);

  // Gets the number of free buffers for the stream specified by |stream_type|.
  size_t GetFreeBufferCount(StreamType stream_type);

  // Checks if the target stream types have been configured or not.
  bool HasStreamsConfigured(std::initializer_list<StreamType> stream_types);

  // Sets up the stream context and allocate buffers according to the
  // configuration specified in |stream|.
  void SetUpStreamsAndBuffers(
      base::flat_map<ClientType, VideoCaptureParams> capture_params,
      const cros::mojom::CameraMetadataPtr& static_metadata,
      std::vector<cros::mojom::Camera3StreamPtr> streams);

  cros::mojom::Camera3StreamPtr GetStreamConfiguration(StreamType stream_type);

  // Requests buffer for specific stream type.
  std::optional<BufferInfo> RequestBufferForCaptureRequest(
      StreamType stream_type);

  // Releases buffer by marking it as free buffer.
  void ReleaseBufferFromCaptureResult(StreamType stream_type,
                                      uint64_t buffer_ipc_id);

  gfx::Size GetBufferDimension(StreamType stream_type);

  bool IsPortraitModeSupported();

  bool IsRecordingSupported();

  std::unique_ptr<gpu::GpuMemoryBufferImpl> CreateGpuMemoryBuffer(
      gfx::GpuMemoryBufferHandle handle,
      const VideoCaptureFormat& format,
      gfx::BufferUsage buffer_usage);

 private:
  friend class RequestManagerTest;

  // BufferPair holding up to two types of handles of a stream buffer.
  struct BufferPair {
    BufferPair(std::unique_ptr<gfx::GpuMemoryBuffer> gmb,
               std::optional<Buffer> vcd_buffer);
    BufferPair(BufferPair&& other);
    ~BufferPair();
    // The GpuMemoryBuffer interface of the stream buffer.
    //   - When the VCD runs SharedMemory-based VideoCapture buffer, |gmb| is
    //     allocated by StreamBufferManager locally.
    //   - When the VCD runs GpuMemoryBuffer-based VideoCapture buffer, |gmb| is
    //     constructed from |vcd_buffer| below.
    std::unique_ptr<gfx::GpuMemoryBuffer> gmb;
    // The VCD buffer reserved from the VCD buffer pool.  This is only set when
    // the VCD runs GpuMemoryBuffer-based VideoCapture buffer.
    std::optional<Buffer> vcd_buffer;
  };

  struct StreamContext {
    StreamContext();
    ~StreamContext();
    // The actual pixel format used in the capture request.
    VideoCaptureFormat capture_format;
    // The camera HAL stream.
    cros::mojom::Camera3StreamPtr stream;
    // The dimension of the buffer layout.
    gfx::Size buffer_dimension;
    // The usage of the buffer.
    gfx::BufferUsage buffer_usage;
    // The allocated buffer pairs.
    std::map<int, BufferPair> buffers;
    // The free buffers of this stream.  The queue stores keys into the
    // |buffers| map.
    std::queue<int> free_buffers;
  };

  static uint64_t GetBufferIpcId(StreamType stream_type, int key);

  static int GetBufferKey(uint64_t buffer_ipc_id);

  bool CanReserveBufferFromPool(StreamType stream_type);
  void ReserveBufferFromFactory(StreamType stream_type);
  void ReserveBufferFromPool(StreamType stream_type);
  // Destroy current streams and unmap mapped buffers.
  void DestroyCurrentStreamsAndBuffers();

  // The context for the set of active streams.
  std::unordered_map<StreamType, std::unique_ptr<StreamContext>>
      stream_context_;

  raw_ptr<CameraDeviceContext> device_context_;

  // The interface to notify camera device a new buffer needs to be registered
  // or a buffer needs to be retired.
  std::unique_ptr<VideoCaptureBufferObserver> buffer_observer_;

  bool video_capture_use_gmb_;

  std::unique_ptr<gpu::GpuMemoryBufferSupport> gmb_support_;

  std::unique_ptr<CameraBufferFactory> camera_buffer_factory_;

  base::WeakPtrFactory<StreamBufferManager> weak_ptr_factory_{this};
};

}  // namespace media

#endif  // MEDIA_CAPTURE_VIDEO_CHROMEOS_STREAM_BUFFER_MANAGER_H_