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
media / gpu / av1_decoder.h [blame]
// Copyright 2020 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_GPU_AV1_DECODER_H_
#define MEDIA_GPU_AV1_DECODER_H_
#include <array>
#include <memory>
#include "base/containers/span.h"
#include "base/memory/raw_ptr.h"
#include "base/sequence_checker.h"
#include "media/base/video_codecs.h"
#include "media/base/video_color_space.h"
#include "media/base/video_types.h"
#include "media/gpu/accelerated_video_decoder.h"
#include "media/gpu/av1_picture.h"
#include "media/gpu/media_gpu_export.h"
#include "third_party/libgav1/src/src/utils/constants.h"
// For libgav1::RefCountedBufferPtr.
#include "third_party/libgav1/src/src/buffer_pool.h"
// For libgav1::ObuSequenceHeader. std::optional demands ObuSequenceHeader to
// fulfill std::is_trivially_constructible if it is forward-declared. But
// ObuSequenceHeader doesn't.
#include "third_party/libgav1/src/src/obu_parser.h"
#include "ui/gfx/hdr_metadata.h"
namespace libgav1 {
struct DecoderState;
struct ObuFrameHeader;
template <typename T>
class Vector;
} // namespace libgav1
namespace media {
using AV1ReferenceFrameVector =
std::array<scoped_refptr<AV1Picture>, libgav1::kNumReferenceFrameTypes>;
// Clients of this class are expected to pass an AV1 OBU stream and are expected
// to provide an implementation of AV1Accelerator for offloading final steps
// of the decoding process.
//
// This class must be created, called and destroyed on a single thread, and
// does nothing internally on any other thread.
class MEDIA_GPU_EXPORT AV1Decoder : public AcceleratedVideoDecoder {
public:
class MEDIA_GPU_EXPORT AV1Accelerator {
public:
// Methods may return kTryAgain if they need additional data (provided
// independently) in order to proceed. Examples are things like not having
// an appropriate key to decode encrypted content. This is not considered an
// unrecoverable error, but rather a pause to allow an application to
// independently provide the required data. When AV1Decoder::Decode()
// is called again, it will attempt to resume processing of the stream
// by calling the same method again.
enum class Status {
// Operation completed successfully.
kOk,
// Operation failed.
kFail,
// Operation failed because some external data is missing. Retry the same
// operation later, once the data has been provided.
kTryAgain,
};
AV1Accelerator() = default;
virtual ~AV1Accelerator() = default;
AV1Accelerator(const AV1Accelerator&) = delete;
AV1Accelerator& operator=(const AV1Accelerator&) = delete;
// Creates an AV1Picture that the AV1Decoder can use to store some of the
// information needed to request accelerated decoding. This picture is later
// passed when calling SubmitDecode() so that the AV1Accelerator can submit
// the decode request to the driver. It may also be stored for use as
// reference to decode other pictures.
// When a picture is no longer needed by the decoder, it will just drop
// its reference to it, and it may do so at any time.
// Note that this may return nullptr if the accelerator is not able to
// provide any new pictures at the given time. The decoder must handle this
// case and treat it as normal, returning kRanOutOfSurfaces from Decode().
virtual scoped_refptr<AV1Picture> CreateAV1Picture(bool apply_grain) = 0;
// |secure_handle| is a reference to the corresponding secure memory when
// doing secure decoding on ARM. This is invoked instead of CreateAV1Picture
// when doing secure decoding on ARM. Default implementation returns
// nullptr.
// TODO(jkardatzke): Remove this once we move to the V4L2 flat stateless
// decoder and add a field to media::CodecPicture instead.
virtual scoped_refptr<AV1Picture> CreateAV1PictureSecure(
bool apply_grain,
uint64_t secure_handle);
// Submits |pic| to the driver for accelerated decoding. The following
// parameters are also passed:
// - |sequence_header|: the current OBU sequence header.
// - |ref_frames|: the pictures used as reference for decoding |pic|.
// - |tile_buffers|: tile information.
// - |data|: the entire data of the DecoderBuffer set by
// AV1Decoder::SetStream().
// Note that returning from this method does not mean that the decode
// process is finished, but the caller may drop its references to |pic|
// and |ref_frames| immediately, and |data| does not need to remain valid
// after this method returns.
virtual Status SubmitDecode(
const AV1Picture& pic,
const libgav1::ObuSequenceHeader& sequence_header,
const AV1ReferenceFrameVector& ref_frames,
const libgav1::Vector<libgav1::TileBuffer>& tile_buffers,
base::span<const uint8_t> data) = 0;
// Schedules output (display) of |pic|.
// Note that returning from this method does not mean that |pic| has already
// been outputted (displayed), but guarantees that all pictures will be
// outputted in the same order as this method was called for them, and that
// they are decoded before outputting (assuming SubmitDecode() has been
// called for them beforehand).
// Returns true when successful, false otherwise.
virtual bool OutputPicture(const AV1Picture& pic) = 0;
// Notifies the accelerater whenever there is a new stream to process.
// The lifetime of the stream is determined by the caller of
// AV1Decoder::SetStream(). `data` spans passed to SubmitDecode() will be
// contained in `stream` (in fact exactly the same span as `stream` in the
// current implementation).
virtual Status SetStream(base::span<const uint8_t> stream,
const DecryptConfig* decrypt_config);
};
AV1Decoder(std::unique_ptr<AV1Accelerator> accelerator,
VideoCodecProfile profile,
const VideoColorSpace& container_color_space = VideoColorSpace());
~AV1Decoder() override;
AV1Decoder(const AV1Decoder&) = delete;
AV1Decoder& operator=(const AV1Decoder&) = delete;
// AcceleratedVideoDecoder implementation.
void SetStream(int32_t id, const DecoderBuffer& decoder_buffer) override;
[[nodiscard]] bool Flush() override;
void Reset() override;
[[nodiscard]] DecodeResult Decode() override;
gfx::Size GetPicSize() const override;
gfx::Rect GetVisibleRect() const override;
VideoCodecProfile GetProfile() const override;
uint8_t GetBitDepth() const override;
VideoChromaSampling GetChromaSampling() const override;
VideoColorSpace GetVideoColorSpace() const override;
std::optional<gfx::HDRMetadata> GetHDRMetadata() const override;
size_t GetRequiredNumOfPictures() const override;
size_t GetNumReferenceFrames() const override;
private:
friend class AV1DecoderTest;
AV1Accelerator::Status DecodeAndOutputPicture(
scoped_refptr<AV1Picture> pic,
const libgav1::Vector<libgav1::TileBuffer>& tile_buffers);
void UpdateReferenceFrames(scoped_refptr<AV1Picture> pic);
void ClearReferenceFrames();
// Checks that |ref_frames_| is consistent with libgav1's reference frame
// state (returns false if not) and cleans old reference frames from
// |ref_frames_| as needed. Also asserts that all reference frames needed by
// |current_frame_header_| are in |ref_frames_|. This method should be called
// prior to using |ref_frames_| (which includes calling
// |accelerator_|->SubmitDecode());
bool CheckAndCleanUpReferenceFrames();
void ClearCurrentFrame();
DecodeResult DecodeInternal();
bool on_error_ = false;
std::unique_ptr<libgav1::BufferPool> buffer_pool_;
std::unique_ptr<libgav1::DecoderState> state_;
std::unique_ptr<libgav1::ObuParser> parser_;
const std::unique_ptr<AV1Accelerator> accelerator_;
AV1ReferenceFrameVector ref_frames_;
std::optional<libgav1::ObuSequenceHeader> current_sequence_header_;
std::optional<libgav1::ObuFrameHeader> current_frame_header_;
libgav1::RefCountedBufferPtr current_frame_;
gfx::Rect visible_rect_;
gfx::Size frame_size_;
VideoCodecProfile profile_;
VideoColorSpace container_color_space_;
VideoColorSpace picture_color_space_;
uint8_t bit_depth_ = 0;
VideoChromaSampling chroma_sampling_ = VideoChromaSampling::kUnknown;
std::optional<gfx::HDRMetadata> hdr_metadata_;
int32_t stream_id_ = 0;
raw_ptr<const uint8_t, DanglingUntriaged> stream_ = nullptr;
size_t stream_size_ = 0;
std::unique_ptr<DecryptConfig> decrypt_config_;
// Secure handle to pass through to the accelerator when doing secure playback
// on ARM.
uint64_t secure_handle_ = 0;
// Pending picture for decode when accelerator returns kTryAgain.
scoped_refptr<AV1Picture> pending_pic_;
SEQUENCE_CHECKER(sequence_checker_);
};
} // namespace media
#endif // MEDIA_GPU_AV1_DECODER_H_