1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
media / capture / video / video_capture_effects_processor.h [blame]
// Copyright 2024 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_VIDEO_CAPTURE_EFFECTS_PROCESSOR_H_
#define MEDIA_CAPTURE_VIDEO_VIDEO_CAPTURE_EFFECTS_PROCESSOR_H_
#include <optional>
#include "base/memory/read_only_shared_memory_region.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/trace_event/trace_id_helper.h"
#include "base/types/expected.h"
#include "gpu/command_buffer/client/shared_image_interface.h"
#include "media/capture/capture_export.h"
#include "media/capture/mojom/video_capture_buffer.mojom-forward.h"
#include "media/capture/video/video_capture_device.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/video_effects/public/cpp/buildflags.h"
#include "services/video_effects/public/mojom/video_effects_processor.mojom.h"
static_assert(BUILDFLAG(ENABLE_VIDEO_EFFECTS),
"enable_video_effects must be true.");
namespace media {
// Structure used to pass information about a post-processed video frame.
// Equivalent to `std::pair<VideoCaptureDevice::Client::Buffer,
// mojom::VideoFrameInfoPtr>`.
struct CAPTURE_EXPORT PostProcessDoneInfo {
// Note: style-guide allows us to use `explicit` keyword even for
// multi-parameter constructors.
explicit PostProcessDoneInfo(VideoCaptureDevice::Client::Buffer buffer,
mojom::VideoFrameInfoPtr info);
PostProcessDoneInfo(PostProcessDoneInfo& other) = delete;
PostProcessDoneInfo& operator=(const PostProcessDoneInfo& other) = delete;
PostProcessDoneInfo(PostProcessDoneInfo&& other);
PostProcessDoneInfo& operator=(PostProcessDoneInfo&& other);
~PostProcessDoneInfo();
VideoCaptureDevice::Client::Buffer buffer;
mojom::VideoFrameInfoPtr info;
};
// Companion class of `VideoCaptureDeviceClient`, used when video effects are
// enabled. Responsible for marshaling video frame data so that it's suitable
// for an IPC to Video Effects Processor, and for actually invoking the
// processor.
class CAPTURE_EXPORT VideoCaptureEffectsProcessor {
public:
// `video_effects_processor` remote will be used to apply the video effects.
explicit VideoCaptureEffectsProcessor(
mojo::PendingRemote<video_effects::mojom::VideoEffectsProcessor>
video_effects_processor);
VideoCaptureEffectsProcessor(const VideoCaptureEffectsProcessor& other) =
delete;
VideoCaptureEffectsProcessor& operator=(
const VideoCaptureEffectsProcessor& other) = delete;
VideoCaptureEffectsProcessor(VideoCaptureEffectsProcessor&& other) = delete;
VideoCaptureEffectsProcessor& operator=(
VideoCaptureEffectsProcessor&& other) = delete;
~VideoCaptureEffectsProcessor();
// Callback that will be called once the post-processor has completed
// processing a single frame. On success, the buffer will contain the
// processed frame (that was allocated by the client of the post-processor),
// and it is the same buffer that the client passed in to one of the
// PostProcess methods. The video frame info describes the video frame
// residing now in the buffer.
using PostProcessDoneCallback = base::OnceCallback<void(
base::expected<PostProcessDoneInfo,
video_effects::mojom::PostProcessError>)>;
// On-CPU variant. Prepares the shared images backed by `out_buffer` for
// receiving the processing results. Invokes the processor.
void PostProcessData(
base::ReadOnlySharedMemoryRegion data,
mojom::VideoFrameInfoPtr frame_info,
VideoCaptureDevice::Client::Buffer out_buffer,
const VideoCaptureFormat& out_buffer_format,
VideoCaptureBufferType out_buffer_type,
VideoCaptureEffectsProcessor::PostProcessDoneCallback post_process_cb);
// On-GPU variant. Creates shared images backed by `in_buffer` and
// `out_buffer`. Invokes the processor.
void PostProcessBuffer(
VideoCaptureDevice::Client::Buffer in_buffer,
mojom::VideoFrameInfoPtr frame_info,
VideoCaptureBufferType in_buffer_type,
VideoCaptureDevice::Client::Buffer out_buffer,
const VideoCaptureFormat& out_buffer_format,
VideoCaptureBufferType out_buffer_type,
VideoCaptureEffectsProcessor::PostProcessDoneCallback post_process_cb);
// On-GPU variant. Creates shared images backed by `in_buffer` and
// `out_buffer`. Invokes the processor. (Mainly used on MacOS)
void PostProcessExternalBuffer(
CapturedExternalVideoBuffer in_buffer,
mojom::VideoFrameInfoPtr frame_info,
VideoCaptureDevice::Client::Buffer out_buffer,
const VideoCaptureFormat& out_buffer_format,
VideoCaptureBufferType out_buffer_type,
VideoCaptureEffectsProcessor::PostProcessDoneCallback post_process_cb);
base::WeakPtr<VideoCaptureEffectsProcessor> GetWeakPtr();
private:
struct PostProcessContext {
// Creates the context. If `in_buffer` is set, then `in_shared_image` must
// also be set for buffers that had shared images created from them. Same
// requirement applies for `out_buffer` and `out_shared_image`. If we don't
// maintain the ownership of shared images backed by the buffers, the dtors
// of `gpu::ClientSharedImage` will be invoked and the shared images won't
// be visible on the other side of the IPC, despite being exported for IPC.
PostProcessContext(
std::optional<VideoCaptureDevice::Client::Buffer> in_buffer,
scoped_refptr<gpu::ClientSharedImage> in_shared_image,
VideoCaptureDevice::Client::Buffer out_buffer,
scoped_refptr<gpu::ClientSharedImage> out_shared_image,
VideoCaptureEffectsProcessor::PostProcessDoneCallback post_process_cb);
~PostProcessContext();
PostProcessContext(const PostProcessContext& other) = delete;
PostProcessContext& operator=(const PostProcessContext& other) = delete;
// Note: the class is move-constructible but not move-assignable!
// This is a consequence of `trace_id` being const.
PostProcessContext(PostProcessContext&& other);
PostProcessContext& operator=(PostProcessContext&& other) = delete;
const uint64_t trace_id = base::trace_event::GetNextGlobalTraceId();
// May be std::nullopt if the context was created for a post-process request
// that operates on on-CPU data - we won't have an `in_buffer` in this case.
std::optional<VideoCaptureDevice::Client::Buffer> in_buffer;
// May be null if `in_buffer` is not set.
scoped_refptr<gpu::ClientSharedImage> in_shared_image;
VideoCaptureDevice::Client::Buffer out_buffer;
scoped_refptr<gpu::ClientSharedImage> out_shared_image;
VideoCaptureEffectsProcessor::PostProcessDoneCallback post_process_cb;
};
void OnPostProcess(PostProcessContext context,
video_effects::mojom::PostProcessResultPtr result);
mojo::Remote<video_effects::mojom::VideoEffectsProcessor> effects_processor_
GUARDED_BY_CONTEXT(sequence_checker_);
SEQUENCE_CHECKER(sequence_checker_);
// Must be last:
base::WeakPtrFactory<VideoCaptureEffectsProcessor> weak_ptr_factory_{this};
};
} // namespace media
#endif // MEDIA_CAPTURE_VIDEO_VIDEO_CAPTURE_EFFECTS_PROCESSOR_H_