-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#include <stddef.h>
#include <stdint.h>
-#include <list>
#include <memory>
#include <string>
-#include "base/callback.h"
#include "base/files/file.h"
-#include "base/logging.h"
-#include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
+#include "base/functional/callback.h"
+#include "base/memory/unsafe_shared_memory_region.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/time/time.h"
+#include "base/token.h"
#include "build/build_config.h"
#include "media/base/video_frame.h"
#include "media/capture/capture_export.h"
#include "media/capture/mojom/image_capture.mojom.h"
+#include "media/capture/mojom/video_capture_types.mojom.h"
#include "media/capture/video/video_capture_buffer_handle.h"
#include "media/capture/video/video_capture_device_descriptor.h"
+#include "media/capture/video/video_capture_feedback.h"
#include "media/capture/video_capture_types.h"
#include "ui/gfx/gpu_memory_buffer.h"
+#if BUILDFLAG(IS_WIN)
+#include <mfobjects.h>
+#include <wrl/client.h>
+#endif
+
namespace base {
class Location;
} // namespace base
// is available for encoding and/or sufficient bandwidth is available for
// transmission over the network. The maximum of the two utilization
// measurements would be used as feedback.
- //
- // The parameter |frame_feedback_id| must match a |frame_feedback_id|
- // previously sent out by the VideoCaptureDevice we are giving feedback about.
- // It is used to indicate which particular frame the reported utilization
- // corresponds to.
- virtual void OnUtilizationReport(int frame_feedback_id, double utilization) {}
+ virtual void OnUtilizationReport(media::VideoCaptureFeedback feedback) {}
+};
- static constexpr double kNoUtilizationRecorded = -1.0;
+struct CAPTURE_EXPORT CapturedExternalVideoBuffer {
+ CapturedExternalVideoBuffer(gfx::GpuMemoryBufferHandle handle,
+ VideoCaptureFormat format,
+ gfx::ColorSpace color_space);
+
+#if BUILDFLAG(IS_WIN)
+ CapturedExternalVideoBuffer(Microsoft::WRL::ComPtr<IMFMediaBuffer> imf_buffer,
+ gfx::GpuMemoryBufferHandle handle,
+ VideoCaptureFormat format,
+ gfx::ColorSpace color_space);
+#endif
+
+ CapturedExternalVideoBuffer(CapturedExternalVideoBuffer&& other);
+ CapturedExternalVideoBuffer& operator=(CapturedExternalVideoBuffer&& other);
+
+ CapturedExternalVideoBuffer(const CapturedExternalVideoBuffer&) = delete;
+ CapturedExternalVideoBuffer& operator=(const CapturedExternalVideoBuffer&) =
+ delete;
+
+ ~CapturedExternalVideoBuffer();
+
+#if BUILDFLAG(IS_WIN)
+ Microsoft::WRL::ComPtr<IMFMediaBuffer> imf_buffer;
+#endif
+ gfx::GpuMemoryBufferHandle handle;
+ VideoCaptureFormat format;
+ gfx::ColorSpace color_space;
};
class CAPTURE_EXPORT VideoCaptureDevice
class CAPTURE_EXPORT HandleProvider {
public:
virtual ~HandleProvider() {}
- virtual mojo::ScopedSharedBufferHandle GetHandleForInterProcessTransit(
- bool read_only) = 0;
- virtual base::SharedMemoryHandle
- GetNonOwnedSharedMemoryHandleForLegacyIPC() = 0;
+
+ // Duplicate as an writable (unsafe) shared memory region.
+ virtual base::UnsafeSharedMemoryRegion DuplicateAsUnsafeRegion() = 0;
+
+ // Access a |VideoCaptureBufferHandle| for local, writable memory.
virtual std::unique_ptr<VideoCaptureBufferHandle>
GetHandleForInProcessAccess() = 0;
+
+ // Clone a |GpuMemoryBufferHandle| for IPC.
+ virtual gfx::GpuMemoryBufferHandle GetGpuMemoryBufferHandle() = 0;
};
Buffer();
Buffer(Buffer&& other);
Buffer& operator=(Buffer&& other);
- bool is_valid() const { return handle_provider != nullptr; }
-
int id;
int frame_feedback_id;
std::unique_ptr<HandleProvider> handle_provider;
std::unique_ptr<ScopedAccessPermission> access_permission;
+
+ // Some buffer types may be preemptively mapped in the capturer if
+ // requested by the consumer.
+ // This is used to notify the client that a shared memory region
+ // associated with the buffer is valid.
+ bool is_premapped = false;
+ };
+
+ // Result code for calls to ReserveOutputBuffer()
+ enum class ReserveResult {
+ kSucceeded,
+ kMaxBufferCountExceeded,
+ kAllocationFailed
};
virtual ~Client() {}
+ // The configuration of the VideoCaptureDevice has changed.
+ virtual void OnCaptureConfigurationChanged() = 0;
+
// Captured a new video frame, data for which is pointed to by |data|.
//
// The format of the frame is described by |frame_format|, and is assumed to
virtual void OnIncomingCapturedData(const uint8_t* data,
int length,
const VideoCaptureFormat& frame_format,
+ const gfx::ColorSpace& color_space,
int clockwise_rotation,
+ bool flip_y,
base::TimeTicks reference_time,
base::TimeDelta timestamp,
- int frame_feedback_id = 0) = 0;
+ int frame_feedback_id) = 0;
+ // Convenience wrapper that passes in 0 as |frame_feedback_id|.
+ void OnIncomingCapturedData(const uint8_t* data,
+ int length,
+ const VideoCaptureFormat& frame_format,
+ const gfx::ColorSpace& color_space,
+ int clockwise_rotation,
+ bool flip_y,
+ base::TimeTicks reference_time,
+ base::TimeDelta timestamp);
+
+ // Captured a new video frame, data for which is stored in the
+ // GpuMemoryBuffer pointed to by |buffer|. The format of the frame is
+ // described by |frame_format|. Since the memory buffer pointed to by
+ // |buffer| may be allocated with some size/address alignment requirement,
+ // this method takes into consideration the size and offset of each plane in
+ // |buffer| when creating the content of the output buffer.
+ // |clockwise_rotation|, |reference_time|, |timestamp|, and
+ // |frame_feedback_id| serve the same purposes as in OnIncomingCapturedData.
+ virtual void OnIncomingCapturedGfxBuffer(
+ gfx::GpuMemoryBuffer* buffer,
+ const VideoCaptureFormat& frame_format,
+ int clockwise_rotation,
+ base::TimeTicks reference_time,
+ base::TimeDelta timestamp,
+ int frame_feedback_id) = 0;
+ // Convenience wrapper that passes in 0 as |frame_feedback_id|.
+ void OnIncomingCapturedGfxBuffer(gfx::GpuMemoryBuffer* buffer,
+ const VideoCaptureFormat& frame_format,
+ int clockwise_rotation,
+ base::TimeTicks reference_time,
+ base::TimeDelta timestamp);
+
+ // Captured a new video frame. The data for this frame is in
+ // |buffer.handle|, which is owned by the platform-specific capture device.
+ // It is the responsibility of the implementation to prevent the buffer in
+ // |buffer.handle| from being reused by the external capturer. In practice,
+ // this is used only on macOS, the external capturer maintains a
+ // CVPixelBufferPool, and gfx::ScopedInUseIOSurface is used to prevent reuse
+ // of buffers until all consumers have consumed them. |visible_rect|
+ // specifies the region in the memory pointed to by |buffer.handle| that
+ // contains the captured content.
+ virtual void OnIncomingCapturedExternalBuffer(
+ CapturedExternalVideoBuffer buffer,
+ base::TimeTicks reference_time,
+ base::TimeDelta timestamp,
+ const gfx::Rect& visible_rect) = 0;
// Reserve an output buffer into which contents can be captured directly.
- // The returned Buffer will always be allocated with a memory size suitable
- // for holding a packed video frame with pixels of |format| format, of
- // |dimensions| frame dimensions. It is permissible for |dimensions| to be
- // zero; in which case the returned Buffer does not guarantee memory
+ // The returned |buffer| will always be allocated with a memory size
+ // suitable for holding a packed video frame with pixels of |format| format,
+ // of |dimensions| frame dimensions. It is permissible for |dimensions| to
+ // be zero; in which case the returned Buffer does not guarantee memory
// backing, but functions as a reservation for external input for the
// purposes of buffer throttling.
//
// The buffer stays reserved for use by the caller as long as it
// holds on to the contained |buffer_read_write_permission|.
- virtual Buffer ReserveOutputBuffer(const gfx::Size& dimensions,
- VideoPixelFormat format,
- VideoPixelStorage storage,
- int frame_feedback_id) = 0;
+ [[nodiscard]] virtual ReserveResult ReserveOutputBuffer(
+ const gfx::Size& dimensions,
+ VideoPixelFormat format,
+ int frame_feedback_id,
+ Buffer* buffer) = 0;
// Provides VCD::Client with a populated Buffer containing the content of
// the next video frame. The |buffer| must originate from an earlier call to
virtual void OnIncomingCapturedBufferExt(
Buffer buffer,
const VideoCaptureFormat& format,
+ const gfx::ColorSpace& color_space,
base::TimeTicks reference_time,
base::TimeDelta timestamp,
gfx::Rect visible_rect,
- const VideoFrameMetadata& additional_metadata) = 0;
-
- // Attempts to reserve the same Buffer provided in the last call to one of
- // the OnIncomingCapturedBufferXXX() methods. This will fail if the content
- // of the Buffer has not been preserved, or if the |dimensions|, |format|,
- // or |storage| disagree with how it was reserved via ReserveOutputBuffer().
- // When this operation fails, nullptr will be returned.
- virtual Buffer ResurrectLastOutputBuffer(const gfx::Size& dimensions,
- VideoPixelFormat format,
- VideoPixelStorage storage,
- int new_frame_feedback_id) = 0;
+ const VideoFrameMetadata& additional_metadata,
+ unsigned int encoded_data_size = 0) = 0;
// An error has occurred that cannot be handled and VideoCaptureDevice must
// be StopAndDeAllocate()-ed. |reason| is a text description of the error.
- virtual void OnError(const base::Location& from_here,
+ virtual void OnError(VideoCaptureError error,
+ const base::Location& from_here,
const std::string& reason) = 0;
+ virtual void OnFrameDropped(VideoCaptureFrameDropReason reason) = 0;
+
// VideoCaptureDevice requests the |message| to be logged.
virtual void OnLog(const std::string& message) {}
// StopAndDeAllocate(). Otherwise, its behavior is undefined.
virtual void Resume() {}
+ // Start/stop cropping.
+ //
+ // Non-empty |crop_id| sets (or changes) the crop-target.
+ // Empty |crop_id| reverts the capture to its original, uncropped state.
+ //
+ // |sub_capture_target_version| must be incremented by at least one for each
+ // call. By including it in frame's metadata, Viz informs Blink what was the
+ // latest invocation of cropTo() before a given frame was produced.
+ //
+ // The callback reports success/failure. It is called on an unspecified
+ // thread, it's the caller's responsibility to wrap it (i.e. via BindPostTask)
+ // as needed.
+ virtual void Crop(
+ const base::Token& crop_id,
+ uint32_t sub_capture_target_version,
+ base::OnceCallback<void(media::mojom::ApplySubCaptureTargetResult)>
+ callback);
+
// Deallocates the video capturer, possibly asynchronously.
//
// This call requires the device to do the following things, eventually: put
// Gets the power line frequency, either from the params if specified by the
// user or from the current system time zone.
- PowerLineFrequency GetPowerLineFrequency(
- const VideoCaptureParams& params) const;
+ static PowerLineFrequency GetPowerLineFrequency(
+ const VideoCaptureParams& params);
private:
// Gets the power line frequency from the current system time zone if this is
// defined, otherwise returns 0.
- PowerLineFrequency GetPowerLineFrequencyForLocation() const;
+ static PowerLineFrequency GetPowerLineFrequencyForLocation();
};
+VideoCaptureFrameDropReason ConvertReservationFailureToFrameDropReason(
+ VideoCaptureDevice::Client::ReserveResult reserve_result);
+
} // namespace media
#endif // MEDIA_CAPTURE_VIDEO_VIDEO_CAPTURE_DEVICE_H_