#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include "media/capture/video/video_capture_device_client.h"
#include <memory>
#include <utility>
#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/containers/span.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/location.h"
#include "base/ranges/algorithm.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "base/types/expected.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "media/base/video_frame.h"
#include "media/base/video_frame_metadata.h"
#include "media/base/video_types.h"
#include "media/capture/mojom/video_capture_buffer.mojom-forward.h"
#include "media/capture/mojom/video_capture_buffer.mojom.h"
#include "media/capture/mojom/video_capture_types.mojom-forward.h"
#include "media/capture/video/scoped_buffer_pool_reservation.h"
#include "media/capture/video/video_capture_buffer_handle.h"
#include "media/capture/video/video_capture_buffer_pool.h"
#include "media/capture/video/video_frame_receiver.h"
#include "media/capture/video_capture_types.h"
#include "services/video_effects/public/mojom/video_effects_processor.mojom.h"
#include "third_party/abseil-cpp/absl/cleanup/cleanup.h"
#include "third_party/libyuv/include/libyuv.h"
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "media/capture/video/chromeos/video_capture_jpeg_decoder.h"
#endif
#if BUILDFLAG(ENABLE_VIDEO_EFFECTS)
#include "media/base/media_switches.h"
#include "media/capture/video/video_capture_effects_processor.h"
#endif
namespace {
bool IsFormatSupported(media::VideoPixelFormat pixel_format) { … }
libyuv::RotationMode TranslateRotation(int rotation_degrees) { … }
void GetI420BufferAccess(
const media::VideoCaptureDevice::Client::Buffer& buffer,
const gfx::Size& dimensions,
uint8_t** y_plane_data,
uint8_t** u_plane_data,
uint8_t** v_plane_data,
int* y_plane_stride,
int* uv_plane_stride) { … }
gfx::ColorSpace OverrideColorSpaceForLibYuvConversion(
const gfx::ColorSpace& color_space,
const media::VideoPixelFormat pixel_format) { … }
struct FourccAndFlip { … };
FourccAndFlip GetFourccAndFlipFromPixelFormat(
const media::VideoCaptureFormat& format,
bool flip_y) { … }
}
namespace media {
#if BUILDFLAG(IS_MAC)
BASE_FEATURE(kFallbackToSharedMemoryIfNotNv12OnMac,
"FallbackToSharedMemoryIfNotNv12OnMac",
base::FEATURE_DISABLED_BY_DEFAULT);
#endif
namespace {
class ScopedAccessPermissionEndWithCallback
: public VideoCaptureDevice::Client::Buffer::ScopedAccessPermission { … };
}
class BufferPoolBufferHandleProvider
: public VideoCaptureDevice::Client::Buffer::HandleProvider { … };
VideoEffectsContext::VideoEffectsContext(
mojo::PendingRemote<video_effects::mojom::VideoEffectsProcessor> remote)
: … { … }
VideoEffectsContext::VideoEffectsContext(VideoEffectsContext&& other) = default;
VideoEffectsContext& VideoEffectsContext::operator=(
VideoEffectsContext&& other) = default;
VideoEffectsContext::~VideoEffectsContext() = default;
mojo::PendingRemote<video_effects::mojom::VideoEffectsProcessor>&&
VideoEffectsContext::TakeVideoEffectsProcessor() { … }
#if BUILDFLAG(IS_CHROMEOS_ASH)
VideoCaptureDeviceClient::VideoCaptureDeviceClient(
std::unique_ptr<VideoFrameReceiver> receiver,
scoped_refptr<VideoCaptureBufferPool> buffer_pool,
VideoCaptureJpegDecoderFactoryCB optional_jpeg_decoder_factory_callback)
: receiver_(std::move(receiver)),
optional_jpeg_decoder_factory_callback_(
std::move(optional_jpeg_decoder_factory_callback)),
buffer_pool_(std::move(buffer_pool)),
last_captured_pixel_format_(PIXEL_FORMAT_UNKNOWN) {
on_started_using_gpu_cb_ =
base::BindOnce(&VideoFrameReceiver::OnStartedUsingGpuDecode,
base::Unretained(receiver_.get()));
}
#else
VideoCaptureDeviceClient::VideoCaptureDeviceClient(
std::unique_ptr<VideoFrameReceiver> receiver,
scoped_refptr<VideoCaptureBufferPool> buffer_pool,
VideoEffectsContext video_effects_context)
: … { … }
#endif
VideoCaptureDeviceClient::~VideoCaptureDeviceClient() { … }
VideoCaptureDevice::Client::Buffer VideoCaptureDeviceClient::MakeBufferStruct(
scoped_refptr<VideoCaptureBufferPool> buffer_pool,
int buffer_id,
int frame_feedback_id) { … }
void VideoCaptureDeviceClient::OnCaptureConfigurationChanged() { … }
#if BUILDFLAG(ENABLE_VIDEO_EFFECTS)
void VideoCaptureDeviceClient::OnPostProcessDone(
base::expected<PostProcessDoneInfo, video_effects::mojom::PostProcessError>
post_process_info_or_error) { … }
#endif
void VideoCaptureDeviceClient::OnIncomingCapturedData(
const uint8_t* data,
int length,
const VideoCaptureFormat& format,
const gfx::ColorSpace& data_color_space,
int rotation,
bool flip_y,
base::TimeTicks reference_time,
base::TimeDelta timestamp,
std::optional<base::TimeTicks> capture_begin_timestamp,
int frame_feedback_id) { … }
void VideoCaptureDeviceClient::OnIncomingCapturedGfxBuffer(
gfx::GpuMemoryBuffer* buffer,
const VideoCaptureFormat& frame_format,
int clockwise_rotation,
base::TimeTicks reference_time,
base::TimeDelta timestamp,
std::optional<base::TimeTicks> capture_begin_timestamp,
int frame_feedback_id) { … }
void VideoCaptureDeviceClient::OnIncomingCapturedExternalBuffer(
CapturedExternalVideoBuffer buffer,
base::TimeTicks reference_time,
base::TimeDelta timestamp,
std::optional<base::TimeTicks> capture_begin_timestamp,
const gfx::Rect& visible_rect) { … }
VideoCaptureDevice::Client::ReserveResult
VideoCaptureDeviceClient::CreateReadyFrameFromExternalBuffer(
CapturedExternalVideoBuffer buffer,
base::TimeTicks reference_time,
base::TimeDelta timestamp,
std::optional<base::TimeTicks> capture_begin_timestamp,
const gfx::Rect& visible_rect,
ReadyFrameInBuffer* ready_buffer) { … }
VideoCaptureDevice::Client::ReserveResult
VideoCaptureDeviceClient::ReserveOutputBuffer(const gfx::Size& frame_size,
VideoPixelFormat pixel_format,
int frame_feedback_id,
Buffer* buffer,
int* require_new_buffer_id,
int* retire_old_buffer_id) { … }
void VideoCaptureDeviceClient::OnIncomingCapturedBuffer(
Buffer buffer,
const VideoCaptureFormat& format,
base::TimeTicks reference_time,
base::TimeDelta timestamp,
std::optional<base::TimeTicks> capture_begin_timestamp) { … }
void VideoCaptureDeviceClient::OnIncomingCapturedBufferExt(
Buffer buffer,
const VideoCaptureFormat& format,
const gfx::ColorSpace& color_space,
base::TimeTicks reference_time,
base::TimeDelta timestamp,
std::optional<base::TimeTicks> capture_begin_timestamp,
gfx::Rect visible_rect,
const VideoFrameMetadata& additional_metadata) { … }
void VideoCaptureDeviceClient::OnError(VideoCaptureError error,
const base::Location& from_here,
const std::string& reason) { … }
void VideoCaptureDeviceClient::OnFrameDropped(
VideoCaptureFrameDropReason reason) { … }
void VideoCaptureDeviceClient::OnLog(const std::string& message) { … }
void VideoCaptureDeviceClient::OnStarted() { … }
double VideoCaptureDeviceClient::GetBufferPoolUtilization() const { … }
void VideoCaptureDeviceClient::OnIncomingCapturedY16Data(
const uint8_t* data,
int length,
const VideoCaptureFormat& format,
base::TimeTicks reference_time,
base::TimeDelta timestamp,
std::optional<base::TimeTicks> capture_begin_timestamp,
int frame_feedback_id) { … }
}