cros_codecs/decoder/stateless/
vp9.rs1#[cfg(test)]
6mod dummy;
7#[cfg(feature = "vaapi")]
8mod vaapi;
9
10use std::os::fd::AsFd;
11use std::os::fd::BorrowedFd;
12
13use log::debug;
14
15use crate::codec::vp9::parser::BitDepth;
16use crate::codec::vp9::parser::Frame;
17use crate::codec::vp9::parser::Header;
18use crate::codec::vp9::parser::Parser;
19use crate::codec::vp9::parser::Profile;
20use crate::codec::vp9::parser::Segmentation;
21use crate::codec::vp9::parser::MAX_SEGMENTS;
22use crate::codec::vp9::parser::NUM_REF_FRAMES;
23use crate::decoder::stateless::DecodeError;
24use crate::decoder::stateless::DecodingState;
25use crate::decoder::stateless::NewPictureError;
26use crate::decoder::stateless::NewPictureResult;
27use crate::decoder::stateless::PoolLayer;
28use crate::decoder::stateless::StatelessBackendResult;
29use crate::decoder::stateless::StatelessCodec;
30use crate::decoder::stateless::StatelessDecoder;
31use crate::decoder::stateless::StatelessDecoderBackend;
32use crate::decoder::stateless::StatelessDecoderBackendPicture;
33use crate::decoder::stateless::StatelessVideoDecoder;
34use crate::decoder::stateless::TryFormat;
35use crate::decoder::BlockingMode;
36use crate::decoder::DecodedHandle;
37use crate::decoder::DecoderEvent;
38use crate::decoder::StreamInfo;
39use crate::Resolution;
40
41pub trait StatelessVp9DecoderBackend:
43 StatelessDecoderBackend + StatelessDecoderBackendPicture<Vp9>
44{
45 fn new_sequence(&mut self, header: &Header) -> StatelessBackendResult<()>;
47
48 fn new_picture(&mut self, timestamp: u64) -> NewPictureResult<Self::Picture>;
50
51 fn submit_picture(
57 &mut self,
58 picture: Self::Picture,
59 hdr: &Header,
60 reference_frames: &[Option<Self::Handle>; NUM_REF_FRAMES],
61 bitstream: &[u8],
62 segmentation: &[Segmentation; MAX_SEGMENTS],
63 ) -> StatelessBackendResult<Self::Handle>;
64}
65
66pub struct Vp9DecoderState<H: DecodedHandle> {
67 parser: Parser,
69
70 reference_frames: [Option<H>; NUM_REF_FRAMES],
72
73 segmentation: [Segmentation; MAX_SEGMENTS],
75
76 negotiation_info: NegotiationInfo,
78}
79
80impl<H> Default for Vp9DecoderState<H>
81where
82 H: DecodedHandle,
83{
84 fn default() -> Self {
85 Self {
86 parser: Default::default(),
87 reference_frames: Default::default(),
88 segmentation: Default::default(),
89 negotiation_info: Default::default(),
90 }
91 }
92}
93
94#[derive(Clone, Debug, Default, PartialEq, Eq)]
96struct NegotiationInfo {
97 coded_resolution: Resolution,
99 bit_depth: BitDepth,
101 profile: Profile,
103}
104
105impl From<&Header> for NegotiationInfo {
106 fn from(hdr: &Header) -> Self {
107 NegotiationInfo {
108 coded_resolution: Resolution {
109 width: hdr.width,
110 height: hdr.height,
111 },
112 bit_depth: hdr.bit_depth,
113 profile: hdr.profile,
114 }
115 }
116}
117
118pub struct Vp9;
126
127impl StatelessCodec for Vp9 {
128 type FormatInfo = Header;
129 type DecoderState<H: DecodedHandle, P> = Vp9DecoderState<H>;
130}
131
132impl<B> StatelessDecoder<Vp9, B>
133where
134 B: StatelessVp9DecoderBackend,
135 B::Handle: Clone,
136{
137 fn update_references(
138 reference_frames: &mut [Option<B::Handle>; NUM_REF_FRAMES],
139 picture: &B::Handle,
140 mut refresh_frame_flags: u8,
141 ) -> anyhow::Result<()> {
142 #[allow(clippy::needless_range_loop)]
143 for i in 0..NUM_REF_FRAMES {
144 if (refresh_frame_flags & 1) == 1 {
145 debug!("Replacing reference frame {}", i);
146 reference_frames[i] = Some(picture.clone());
147 }
148
149 refresh_frame_flags >>= 1;
150 }
151
152 Ok(())
153 }
154
155 fn handle_show_existing_frame(&mut self, frame_to_show_map_idx: u8) -> Result<(), DecodeError> {
157 let idx = usize::from(frame_to_show_map_idx);
160 let ref_frame = self
161 .codec
162 .reference_frames
163 .get(idx)
164 .ok_or_else(|| anyhow::anyhow!("invalid reference frame index in header"))?
165 .as_ref()
166 .ok_or_else(|| anyhow::anyhow!("empty reference frame referenced in frame header"))?;
167
168 let decoded_handle = ref_frame.clone();
170
171 self.ready_queue.push(decoded_handle);
172
173 Ok(())
174 }
175
176 fn handle_frame(&mut self, frame: &Frame, picture: B::Picture) -> Result<(), DecodeError> {
178 let refresh_frame_flags = frame.header.refresh_frame_flags;
179
180 Segmentation::update_segmentation(&mut self.codec.segmentation, &frame.header);
181
182 let decoded_handle = self.backend.submit_picture(
183 picture,
184 &frame.header,
185 &self.codec.reference_frames,
186 frame.as_ref(),
187 &self.codec.segmentation,
188 )?;
189
190 if self.blocking_mode == BlockingMode::Blocking {
191 decoded_handle.sync()?;
192 }
193
194 Self::update_references(
196 &mut self.codec.reference_frames,
197 &decoded_handle,
198 refresh_frame_flags,
199 )?;
200
201 if frame.header.show_frame {
202 self.ready_queue.push(decoded_handle);
203 }
204
205 Ok(())
206 }
207
208 fn negotiation_possible(&self, hdr: &Header, old_negotiation_info: &NegotiationInfo) -> bool {
209 let negotiation_info = NegotiationInfo::from(hdr);
210
211 if negotiation_info.coded_resolution.width == 0
212 || negotiation_info.coded_resolution.height == 0
213 {
214 false
215 } else {
216 *old_negotiation_info != negotiation_info
217 }
218 }
219}
220
221impl<B> StatelessVideoDecoder for StatelessDecoder<Vp9, B>
222where
223 B: StatelessVp9DecoderBackend + TryFormat<Vp9>,
224 B::Handle: Clone + 'static,
225{
226 type Handle = B::Handle;
227 type FramePool = B::FramePool;
228
229 fn decode(&mut self, timestamp: u64, bitstream: &[u8]) -> Result<usize, DecodeError> {
230 let frames = self.codec.parser.parse_chunk(bitstream)?;
231
232 let largest_in_superframe = frames.iter().max_by(|&a, &b| {
242 let a_res = Resolution::from((a.header.width, a.header.height));
243 let b_res = Resolution::from((b.header.width, b.header.height));
244 if a_res == b_res {
245 std::cmp::Ordering::Equal
246 } else if a_res.can_contain(b_res) {
247 std::cmp::Ordering::Greater
248 } else {
249 std::cmp::Ordering::Less
250 }
251 });
252
253 if let Some(frame) = largest_in_superframe {
254 if self.negotiation_possible(&frame.header, &self.codec.negotiation_info) {
255 self.backend.new_sequence(&frame.header)?;
256 self.await_format_change(frame.header.clone());
257 } else if matches!(self.decoding_state, DecodingState::Reset) {
258 self.decoding_state = DecodingState::Decoding;
260 }
261 }
262
263 match &mut self.decoding_state {
264 DecodingState::AwaitingStreamInfo | DecodingState::Reset => (),
266 DecodingState::AwaitingFormat(_) => return Err(DecodeError::CheckEvents),
268 DecodingState::Decoding => {
269 let num_required_pictures = frames
271 .iter()
272 .filter(|f| !f.header.show_existing_frame)
273 .count();
274 let frames_with_pictures = frames
275 .into_iter()
276 .enumerate()
277 .map(|(i, frame)| {
278 if frame.header.show_existing_frame {
279 Ok((frame, None))
280 } else {
281 self.backend
282 .new_picture(timestamp)
283 .map_err(|e| match e {
284 NewPictureError::OutOfOutputBuffers => {
285 DecodeError::NotEnoughOutputBuffers(
286 num_required_pictures - i,
287 )
288 }
289 e => DecodeError::from(e),
290 })
291 .map(|picture| (frame, Some(picture)))
292 }
293 })
294 .collect::<Result<Vec<_>, _>>()?;
295
296 for (frame, picture) in frames_with_pictures {
298 match picture {
299 None => {
300 self.handle_show_existing_frame(frame.header.frame_to_show_map_idx)?
301 }
302 Some(picture) => self.handle_frame(&frame, picture)?,
303 }
304 }
305 }
306 }
307
308 Ok(bitstream.len())
309 }
310
311 fn flush(&mut self) -> Result<(), DecodeError> {
312 self.codec.reference_frames = Default::default();
314 self.decoding_state = DecodingState::Reset;
315
316 Ok(())
317 }
318
319 fn next_event(&mut self) -> Option<DecoderEvent<B::Handle>> {
320 self.query_next_event(|decoder, hdr| {
321 decoder.codec.negotiation_info = hdr.into();
322 })
323 }
324
325 fn frame_pool(&mut self, layer: PoolLayer) -> Vec<&mut B::FramePool> {
326 self.backend.frame_pool(layer)
327 }
328
329 fn stream_info(&self) -> Option<&StreamInfo> {
330 self.backend.stream_info()
331 }
332
333 fn poll_fd(&self) -> BorrowedFd {
334 self.epoll_fd.0.as_fd()
335 }
336}
337
338#[cfg(test)]
339pub mod tests {
340 use crate::decoder::stateless::tests::test_decode_stream;
341 use crate::decoder::stateless::tests::TestStream;
342 use crate::decoder::stateless::vp9::Vp9;
343 use crate::decoder::stateless::StatelessDecoder;
344 use crate::decoder::BlockingMode;
345 use crate::utils::simple_playback_loop;
346 use crate::utils::simple_playback_loop_owned_frames;
347 use crate::utils::IvfIterator;
348 use crate::DecodedFormat;
349
350 fn test_decoder_dummy(test: &TestStream, blocking_mode: BlockingMode) {
352 let decoder = StatelessDecoder::<Vp9, _>::new_dummy(blocking_mode).unwrap();
353
354 test_decode_stream(
355 |d, s, c| {
356 simple_playback_loop(
357 d,
358 IvfIterator::new(s),
359 c,
360 &mut simple_playback_loop_owned_frames,
361 DecodedFormat::NV12,
362 blocking_mode,
363 )
364 },
365 decoder,
366 test,
367 false,
368 false,
369 );
370 }
371
372 pub const DECODE_TEST_25FPS: TestStream = TestStream {
374 stream: include_bytes!("../../codec/vp9/test_data/test-25fps.vp9"),
375 crcs: include_str!("../../codec/vp9/test_data/test-25fps.vp9.crc"),
376 };
377
378 #[test]
379 fn test_25fps_block() {
380 test_decoder_dummy(&DECODE_TEST_25FPS, BlockingMode::Blocking);
381 }
382
383 #[test]
384 fn test_25fps_nonblock() {
385 test_decoder_dummy(&DECODE_TEST_25FPS, BlockingMode::NonBlocking);
386 }
387
388 pub const DECODE_TEST_25FPS_SHOW_EXISTING_FRAME: TestStream = TestStream {
391 stream: include_bytes!("../../codec/vp9/test_data/vp90-2-10-show-existing-frame.vp9.ivf"),
392 crcs: include_str!("../../codec/vp9/test_data/vp90-2-10-show-existing-frame.vp9.ivf.crc"),
393 };
394
395 #[test]
396 fn show_existing_frame_block() {
397 test_decoder_dummy(
398 &DECODE_TEST_25FPS_SHOW_EXISTING_FRAME,
399 BlockingMode::Blocking,
400 );
401 }
402
403 #[test]
404 fn show_existing_frame_nonblock() {
405 test_decoder_dummy(
406 &DECODE_TEST_25FPS_SHOW_EXISTING_FRAME,
407 BlockingMode::NonBlocking,
408 );
409 }
410
411 pub const DECODE_TEST_25FPS_SHOW_EXISTING_FRAME2: TestStream = TestStream {
412 stream: include_bytes!("../../codec/vp9/test_data/vp90-2-10-show-existing-frame2.vp9.ivf"),
413 crcs: include_str!("../../codec/vp9/test_data/vp90-2-10-show-existing-frame2.vp9.ivf.crc"),
414 };
415
416 #[test]
417 fn show_existing_frame2_block() {
418 test_decoder_dummy(
419 &DECODE_TEST_25FPS_SHOW_EXISTING_FRAME2,
420 BlockingMode::Blocking,
421 );
422 }
423
424 #[test]
425 fn show_existing_frame2_nonblock() {
426 test_decoder_dummy(
427 &DECODE_TEST_25FPS_SHOW_EXISTING_FRAME2,
428 BlockingMode::NonBlocking,
429 );
430 }
431
432 pub const DECODE_RESOLUTION_CHANGE_500FRAMES: TestStream = TestStream {
438 stream: include_bytes!("../../codec/vp9/test_data/resolution_change_500frames-vp9.ivf"),
439 crcs: include_str!("../../codec/vp9/test_data/resolution_change_500frames-vp9.ivf.crc"),
440 };
441
442 #[test]
443 fn test_resolution_change_500frames_block() {
444 test_decoder_dummy(&DECODE_RESOLUTION_CHANGE_500FRAMES, BlockingMode::Blocking);
445 }
446
447 #[test]
448 fn test_resolution_change_500frames_nonblock() {
449 test_decoder_dummy(&DECODE_RESOLUTION_CHANGE_500FRAMES, BlockingMode::Blocking);
450 }
451}