-
Notifications
You must be signed in to change notification settings - Fork 6.6k
/
vaapi_video_decoder.h
263 lines (219 loc) · 10.4 KB
/
vaapi_video_decoder.h
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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_GPU_VAAPI_VAAPI_VIDEO_DECODER_H_
#define MEDIA_GPU_VAAPI_VAAPI_VIDEO_DECODER_H_
#include <stdint.h>
#include <va/va.h>
#include <map>
#include <memory>
#include <utility>
#include "base/containers/mru_cache.h"
#include "base/containers/queue.h"
#include "base/containers/small_map.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "build/chromeos_buildflags.h"
#include "media/base/callback_registry.h"
#include "media/base/cdm_context.h"
#include "media/base/status.h"
#include "media/base/supported_video_decoder_config.h"
#include "media/base/video_aspect_ratio.h"
#include "media/base/video_codecs.h"
#include "media/base/video_frame_layout.h"
#include "media/gpu/chromeos/video_decoder_pipeline.h"
#include "media/gpu/decode_surface_handler.h"
#include "media/gpu/vaapi/vaapi_utils.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/gpu_memory_buffer.h"
#include "ui/gfx/hdr_metadata.h"
namespace media {
class AcceleratedVideoDecoder;
class VaapiVideoDecoderDelegate;
class DmabufVideoFramePool;
class VaapiWrapper;
class VideoFrame;
class VASurface;
class VaapiVideoDecoder : public VideoDecoderMixin,
public DecodeSurfaceHandler<VASurface> {
public:
static std::unique_ptr<VideoDecoderMixin> Create(
scoped_refptr<base::SequencedTaskRunner> decoder_task_runner,
base::WeakPtr<VideoDecoderMixin::Client> client);
static SupportedVideoDecoderConfigs GetSupportedConfigs();
// VideoDecoderMixin implementation, VideoDecoder part.
void Initialize(const VideoDecoderConfig& config,
bool low_delay,
CdmContext* cdm_context,
InitCB init_cb,
const OutputCB& output_cb,
const WaitingCB& waiting_cb) override;
void Decode(scoped_refptr<DecoderBuffer> buffer, DecodeCB decode_cb) override;
void Reset(base::OnceClosure reset_cb) override;
bool NeedsBitstreamConversion() const override;
bool CanReadWithoutStalling() const override;
int GetMaxDecodeRequests() const override;
VideoDecoderType GetDecoderType() const override;
bool IsPlatformDecoder() const override;
// VideoDecoderMixin implementation, specific part.
void ApplyResolutionChange() override;
bool NeedsTranscryption() override;
// DecodeSurfaceHandler<VASurface> implementation.
scoped_refptr<VASurface> CreateSurface() override;
scoped_refptr<VASurface> CreateDecodeSurface() override;
bool IsScalingDecode() override;
const gfx::Rect GetOutputVisibleRect(
const gfx::Rect& decode_visible_rect,
const gfx::Size& output_picture_size) override;
void SurfaceReady(scoped_refptr<VASurface> va_surface,
int32_t buffer_id,
const gfx::Rect& visible_rect,
const VideoColorSpace& color_space) override;
private:
// Decode task holding single decode request.
struct DecodeTask {
DecodeTask(scoped_refptr<DecoderBuffer> buffer,
int32_t buffer_id,
DecodeCB decode_done_cb);
~DecodeTask();
DecodeTask(DecodeTask&&);
DecodeTask& operator=(DecodeTask&&) = default;
scoped_refptr<DecoderBuffer> buffer_;
int32_t buffer_id_ = -1;
DecodeCB decode_done_cb_;
DISALLOW_COPY_AND_ASSIGN(DecodeTask);
};
enum class State {
kUninitialized, // not initialized yet or initialization failed.
kWaitingForInput, // waiting for input buffers.
kWaitingForOutput, // waiting for output buffers.
kWaitingForProtected, // waiting on something related to protected content,
// either setup, full sample parsing or key loading.
kDecoding, // decoding buffers.
kChangingResolution, // need to change resolution, waiting for pipeline to
// be flushed.
kResetting, // resetting decoder.
kError, // decoder encountered an error.
};
VaapiVideoDecoder(
scoped_refptr<base::SequencedTaskRunner> decoder_task_runner,
base::WeakPtr<VideoDecoderMixin::Client> client);
~VaapiVideoDecoder() override;
// Schedule the next decode task in the queue to be executed.
void ScheduleNextDecodeTask();
// Try to decode a single input buffer.
void HandleDecodeTask();
// Clear the decode task queue. This is done when resetting or destroying the
// decoder, or encountering an error.
void ClearDecodeTaskQueue(DecodeStatus status);
// Releases the local reference to the VideoFrame associated with the
// specified |surface_id| on the decoder thread. This is called when
// |decoder_| has outputted the VideoFrame and stopped using it as a
// reference frame. Note that this doesn't mean the frame can be reused
// immediately, as it might still be used by the client.
void ReleaseVideoFrame(VASurfaceID surface_id);
// Callback for |frame_pool_| to notify of available resources.
void NotifyFrameAvailable();
// Callback from accelerator to indicate the protected state has been updated
// so we can proceed or fail.
void ProtectedSessionUpdate(bool success);
// Flushes |decoder_|, blocking until all pending decode tasks have been
// executed and all frames have been output.
void Flush();
// Called when resetting the decoder is finished, to execute |reset_cb|.
void ResetDone(base::OnceClosure reset_cb);
// Create codec-specific AcceleratedVideoDecoder and reset related variables.
Status CreateAcceleratedVideoDecoder();
// Change the current |state_| to the specified |state|.
void SetState(State state);
// Callback for the CDM to notify |this|.
void OnCdmContextEvent(CdmContext::Event event);
// This is a callback from ApplyResolutionChange() when we need to query the
// browser process for the screen sizes.
void ApplyResolutionChangeWithScreenSizes(
const std::vector<gfx::Size>& screen_resolution);
// Callback for when a VASurface in the decode pool is no longer used as a
// reference frame and should then be returned to the pool. We ignore the
// VASurfaceID in the normal callback because it is retained in the |surface|
// object.
void ReturnDecodeSurfaceToPool(std::unique_ptr<ScopedVASurface> surface,
VASurfaceID);
// The video decoder's state.
State state_ = State::kUninitialized;
// Callback used to notify the client when a frame is available for output.
OutputCB output_cb_;
// Callback used to notify the client when we have lost decode context and
// request a reset (Used in protected decoding).
WaitingCB waiting_cb_;
// Bitstream information, written during Initialize().
VideoCodecProfile profile_ = VIDEO_CODEC_PROFILE_UNKNOWN;
VideoColorSpace color_space_;
absl::optional<gfx::HDRMetadata> hdr_metadata_;
// Aspect ratio from the config.
VideoAspectRatio aspect_ratio_;
// Video frame pool used to allocate and recycle video frames.
DmabufVideoFramePool* frame_pool_ = nullptr;
// The time at which each buffer decode operation started. Not each decode
// operation leads to a frame being output and frames might be reordered, so
// we don't know when it's safe to drop a timestamp. This means we need to use
// a cache here, with a size large enough to account for frame reordering.
base::MRUCache<int32_t, base::TimeDelta> buffer_id_to_timestamp_;
// Queue containing all requested decode tasks.
base::queue<DecodeTask> decode_task_queue_;
// The decode task we're currently trying to execute.
absl::optional<DecodeTask> current_decode_task_;
// The next input buffer id.
int32_t next_buffer_id_ = 0;
// The list of frames currently used as output buffers or reference frames.
std::map<VASurfaceID, scoped_refptr<VideoFrame>> output_frames_;
// VASurfaces are created via importing |frame_pool_| resources into libva in
// CreateSurface(). The following map keeps those VASurfaces for reuse
// according to the expectations of libva vaDestroySurfaces(): "Surfaces can
// only be destroyed after all contexts using these surfaces have been
// destroyed."
// TODO(crbug.com/1040291): remove this keep-alive when using SharedImages.
base::small_map<std::map<gfx::GpuMemoryBufferId, scoped_refptr<VASurface>>>
allocated_va_surfaces_;
// We need to use a CdmContextRef so that we destruct
// |cdm_event_cb_registration_| before the CDM is destructed. The CDM has
// mechanisms to ensure destruction on the proper thread.
//
// For clarity, the MojoVideoDecoderService does hold a reference to both the
// decoder and the CDM to ensure the CDM doesn't get destructed before the
// decoder; however, in the VideoDecoderPipeline, which owns the
// VaapiVideoDecoder, it uses an asynchronous destructor to destroy the
// pipeline (and thus the VaapiVideoDecoder) on the decoder thread.
std::unique_ptr<CdmContextRef> cdm_context_ref_;
EncryptionScheme encryption_scheme_;
#if BUILDFLAG(IS_CHROMEOS_ASH)
// To keep the CdmContext event callback registered.
std::unique_ptr<CallbackRegistration> cdm_event_cb_registration_;
#endif
// Platform and codec specific video decoder.
std::unique_ptr<AcceleratedVideoDecoder> decoder_;
scoped_refptr<VaapiWrapper> vaapi_wrapper_;
// TODO(crbug.com/1022246): Instead of having the raw pointer here, getting
// the pointer from AcceleratedVideoDecoder.
VaapiVideoDecoderDelegate* decoder_delegate_ = nullptr;
// When we are doing scaled decoding, this is the pool of surfaces used by the
// decoder for reference frames.
base::queue<std::unique_ptr<ScopedVASurface>>
decode_surface_pool_for_scaling_;
// When we are doing scaled decoding, this is the scale factor we are using,
// and applies the same in both dimensions.
absl::optional<float> decode_to_output_scale_factor_;
// This is used on AMD protected content implementations to indicate that the
// DecoderBuffers we receive have been transcrypted and need special handling.
bool transcryption_ = false;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtr<VaapiVideoDecoder> weak_this_;
base::WeakPtrFactory<VaapiVideoDecoder> weak_this_factory_;
DISALLOW_COPY_AND_ASSIGN(VaapiVideoDecoder);
};
} // namespace media
#endif // MEDIA_GPU_VAAPI_VAAPI_VIDEO_DECODER_H_