1use rff_codec::{Codec, CodecParams, CodecRegistry, Decoder};
18use rff_core::{CodecId, Error, Frame, MediaType, Packet, PixelFormat, Result, VideoFrame};
19use rusty_av2d::{PixelLayout, PlanarImageComponent, Rav1dError};
20
21pub use rusty_av2d;
23
24pub fn register(registry: &mut CodecRegistry) {
26 registry.register(Codec {
27 id: CodecId::Av2,
28 name: "av2",
29 long_name: "AOMedia Video 2",
30 media_type: MediaType::Video,
31 decoder: Some(|| Box::new(Av2Decoder::new())),
32 encoder: None,
33 });
34}
35
36fn map_err(e: Rav1dError) -> Error {
40 match e {
41 Rav1dError::TryAgain => Error::Again,
42 Rav1dError::InvalidArgument => Error::InvalidData("av2: invalid bitstream".into()),
43 Rav1dError::UnsupportedBitstream => {
44 Error::Unsupported("av2: unsupported bitstream feature".into())
45 }
46 other => Error::InvalidData(format!("av2: {other:?}")),
47 }
48}
49
50struct Av2Decoder {
55 inner: Option<rusty_av2d::Decoder>,
58 pending: bool,
62 draining: bool,
65}
66
67impl Av2Decoder {
68 fn new() -> Self {
69 Self {
70 inner: None,
71 pending: false,
72 draining: false,
73 }
74 }
75
76 fn engine(&mut self) -> Result<&mut rusty_av2d::Decoder> {
77 if self.inner.is_none() {
78 self.inner = Some(rusty_av2d::Decoder::new().map_err(map_err)?);
79 }
80 Ok(self.inner.as_mut().expect("just initialized"))
81 }
82}
83
84impl Decoder for Av2Decoder {
85 fn configure(&mut self, _params: &CodecParams) -> Result<()> {
86 Ok(())
89 }
90
91 fn send_packet(&mut self, packet: &Packet) -> Result<()> {
92 let pts = packet.pts;
93
94 if packet.data.is_empty() || packet.data.len() > usize::MAX / 2 {
100 return Err(Error::InvalidData("av2: empty or oversized packet".into()));
101 }
102 let data = packet.data.clone().into_boxed_slice();
103
104 if self.pending {
107 let r = self.engine()?.send_pending_data();
108 match r {
109 Ok(()) => self.pending = false,
110 Err(Rav1dError::TryAgain) => return Err(Error::Again),
111 Err(e) => {
112 self.pending = false;
113 return Err(map_err(e));
114 }
115 }
116 }
117
118 let r = self.engine()?.send_data(data, None, pts, None);
119 match r {
120 Ok(()) => Ok(()),
121 Err(Rav1dError::TryAgain) => {
122 self.pending = true;
125 Err(Error::Again)
126 }
127 Err(e) => Err(map_err(e)),
128 }
129 }
130
131 fn receive_frame(&mut self) -> Result<Frame> {
132 let draining = self.draining;
133 let Some(engine) = self.inner.as_mut() else {
134 return Err(if draining { Error::Eof } else { Error::Again });
136 };
137 match engine.get_picture() {
138 Ok(pic) => picture_to_frame(&pic),
139 Err(Rav1dError::TryAgain) if draining => Err(Error::Eof),
142 Err(e) => Err(map_err(e)),
143 }
144 }
145
146 fn flush(&mut self) {
147 self.draining = true;
148 }
149}
150
151fn picture_to_frame(pic: &rusty_av2d::Picture) -> Result<Frame> {
157 let layout = pic.pixel_layout();
158 let format = match (layout, pic.bit_depth()) {
159 (PixelLayout::I420, 8) => PixelFormat::Yuv420p,
160 (PixelLayout::I422, 8) => PixelFormat::Yuv422p,
161 (PixelLayout::I444, 8) => PixelFormat::Yuv444p,
162 (PixelLayout::I420, 10) => PixelFormat::Yuv420p10,
163 (PixelLayout::I422, 10) => PixelFormat::Yuv422p10,
164 (PixelLayout::I444, 10) => PixelFormat::Yuv444p10,
165 (PixelLayout::I420, 12) => PixelFormat::Yuv420p12,
166 (PixelLayout::I422, 12) => PixelFormat::Yuv422p12,
167 (PixelLayout::I444, 12) => PixelFormat::Yuv444p12,
168 (PixelLayout::I400, _) => {
171 return Err(Error::Unsupported("av2: monochrome (4:0:0) output".into()))
172 }
173 (_, depth) => {
174 return Err(Error::Unsupported(format!(
175 "av2: {depth}-bit output is not mapped to a pixel format"
176 )))
177 }
178 };
179
180 let mut planes = Vec::with_capacity(3);
181 let mut strides = Vec::with_capacity(3);
182 for c in [
183 PlanarImageComponent::Y,
184 PlanarImageComponent::U,
185 PlanarImageComponent::V,
186 ] {
187 planes.push(pic.plane(c).to_vec());
188 strides.push(pic.stride(c) as usize);
189 }
190
191 Ok(Frame::Video(VideoFrame {
192 width: pic.width(),
193 height: pic.height(),
194 format,
195 planes,
196 strides,
197 pts: pic.timestamp(),
198 }))
199}
200
201#[cfg(test)]
202mod tests {
203 use super::*;
204
205 #[test]
206 fn registers_a_decode_only_av2_codec() {
207 let mut reg = CodecRegistry::new();
208 register(&mut reg);
209 let codec = reg.by_id(CodecId::Av2).expect("av2 registered");
210 assert_eq!(codec.name, "av2");
211 assert_eq!(codec.media_type, MediaType::Video);
212 assert!(codec.decoder.is_some());
213 assert!(
214 codec.encoder.is_none(),
215 "there is no AV2 encoder; the registry must not advertise one"
216 );
217 }
218
219 #[test]
220 fn try_again_maps_to_the_control_flow_error() {
221 assert!(matches!(map_err(Rav1dError::TryAgain), Error::Again));
224 }
225
226 #[test]
227 fn garbage_input_errors_rather_than_panicking() {
228 let mut dec = Av2Decoder::new();
229 let packet = Packet {
230 data: vec![0xde, 0xad, 0xbe, 0xef, 0x00, 0x11, 0x22, 0x33],
231 ..Default::default()
232 };
233 let _ = dec.send_packet(&packet);
235 let _ = dec.receive_frame();
236 }
237}
238
239#[cfg(test)]
240mod fuzz_smoke {
241 use super::*;
242 use rff_codec::Decoder as _;
243
244 struct Rng(u64);
245 impl Rng {
246 fn next(&mut self) -> u64 {
247 self.0 ^= self.0 << 13;
248 self.0 ^= self.0 >> 7;
249 self.0 ^= self.0 << 17;
250 self.0
251 }
252 fn byte(&mut self) -> u8 {
253 (self.next() >> 33) as u8
254 }
255 fn range(&mut self, n: usize) -> usize {
256 (self.next() >> 33) as usize % n.max(1)
257 }
258 }
259
260 #[test]
266 fn random_bytes_never_panic() {
267 let mut rng = Rng(0xFACE_B00C_1234_5678);
268 for i in 0..1500 {
269 let len = if i % 10 == 0 {
270 rng.range(65536)
271 } else {
272 rng.range(4096)
273 } + 1;
274 let data: Vec<u8> = (0..len).map(|_| rng.byte()).collect();
275 let mut dec = Av2Decoder::new();
276 let pkt = Packet {
277 data,
278 ..Default::default()
279 };
280 let _ = dec.send_packet(&pkt);
281 for _ in 0..8 {
282 if dec.receive_frame().is_err() {
283 break;
284 }
285 }
286 dec.flush();
287 let _ = dec.receive_frame();
288 }
289 }
290
291 #[test]
296 fn empty_packet_is_an_error_not_an_abort() {
297 let mut dec = Av2Decoder::new();
298 let pkt = Packet {
299 data: Vec::new(),
300 ..Default::default()
301 };
302 assert!(matches!(dec.send_packet(&pkt), Err(Error::InvalidData(_))));
303 assert!(dec.receive_frame().is_err());
305 }
306}