1 // Copyright 2022 The ChromiumOS Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #[cfg(test)] 6 mod dummy; 7 #[cfg(feature = "v4l2")] 8 mod v4l2; 9 #[cfg(feature = "vaapi")] 10 mod vaapi; 11 12 use std::os::fd::AsFd; 13 use std::os::fd::BorrowedFd; 14 15 use log::debug; 16 17 use crate::codec::vp9::parser::BitDepth; 18 use crate::codec::vp9::parser::Frame; 19 use crate::codec::vp9::parser::Header; 20 use crate::codec::vp9::parser::Parser; 21 use crate::codec::vp9::parser::Profile; 22 use crate::codec::vp9::parser::Segmentation; 23 use crate::codec::vp9::parser::MAX_SEGMENTS; 24 use crate::codec::vp9::parser::NUM_REF_FRAMES; 25 use crate::decoder::stateless::DecodeError; 26 use crate::decoder::stateless::DecodingState; 27 use crate::decoder::stateless::NewPictureError; 28 use crate::decoder::stateless::NewPictureResult; 29 use crate::decoder::stateless::StatelessBackendResult; 30 use crate::decoder::stateless::StatelessCodec; 31 use crate::decoder::stateless::StatelessDecoder; 32 use crate::decoder::stateless::StatelessDecoderBackend; 33 use crate::decoder::stateless::StatelessDecoderBackendPicture; 34 use crate::decoder::stateless::StatelessVideoDecoder; 35 use crate::decoder::BlockingMode; 36 use crate::decoder::DecodedHandle; 37 use crate::decoder::DecoderEvent; 38 use crate::decoder::StreamInfo; 39 use crate::Resolution; 40 41 /// Stateless backend methods specific to VP9. 42 pub trait StatelessVp9DecoderBackend: 43 StatelessDecoderBackend + StatelessDecoderBackendPicture<Vp9> 44 { 45 /// Called when new stream parameters are found. new_sequence(&mut self, header: &Header) -> StatelessBackendResult<()>46 fn new_sequence(&mut self, header: &Header) -> StatelessBackendResult<()>; 47 48 /// Allocate all resources required to process a new picture. new_picture( &mut self, timestamp: u64, alloc_cb: &mut dyn FnMut() -> Option< <<Self as StatelessDecoderBackend>::Handle as DecodedHandle>::Frame, >, ) -> NewPictureResult<Self::Picture>49 fn new_picture( 50 &mut self, 51 timestamp: u64, 52 alloc_cb: &mut dyn FnMut() -> Option< 53 <<Self as StatelessDecoderBackend>::Handle as DecodedHandle>::Frame, 54 >, 55 ) -> NewPictureResult<Self::Picture>; 56 57 /// Called when the decoder wants the backend to finish the decoding 58 /// operations for `picture`. 59 /// 60 /// This call will assign the ownership of the BackendHandle to the Picture 61 /// and then assign the ownership of the Picture to the Handle. submit_picture( &mut self, picture: Self::Picture, hdr: &Header, reference_frames: &[Option<Self::Handle>; NUM_REF_FRAMES], bitstream: &[u8], segmentation: &[Segmentation; MAX_SEGMENTS], ) -> StatelessBackendResult<Self::Handle>62 fn submit_picture( 63 &mut self, 64 picture: Self::Picture, 65 hdr: &Header, 66 reference_frames: &[Option<Self::Handle>; NUM_REF_FRAMES], 67 bitstream: &[u8], 68 segmentation: &[Segmentation; MAX_SEGMENTS], 69 ) -> StatelessBackendResult<Self::Handle>; 70 } 71 72 pub struct Vp9DecoderState<H: DecodedHandle> { 73 /// VP9 bitstream parser. 74 parser: Parser, 75 76 /// The reference frames in use. 77 reference_frames: [Option<H>; NUM_REF_FRAMES], 78 79 /// Per-segment data. 80 segmentation: [Segmentation; MAX_SEGMENTS], 81 82 /// Keeps track of the last values seen for negotiation purposes. 83 negotiation_info: NegotiationInfo, 84 } 85 86 impl<H> Default for Vp9DecoderState<H> 87 where 88 H: DecodedHandle, 89 { default() -> Self90 fn default() -> Self { 91 Self { 92 parser: Default::default(), 93 reference_frames: Default::default(), 94 segmentation: Default::default(), 95 negotiation_info: Default::default(), 96 } 97 } 98 } 99 100 /// Keeps track of the last values seen for negotiation purposes. 101 #[derive(Clone, Debug, Default, PartialEq, Eq)] 102 struct NegotiationInfo { 103 /// The current coded resolution 104 coded_resolution: Resolution, 105 /// Cached value for bit depth 106 bit_depth: BitDepth, 107 /// Cached value for profile 108 profile: Profile, 109 } 110 111 impl From<&Header> for NegotiationInfo { from(hdr: &Header) -> Self112 fn from(hdr: &Header) -> Self { 113 NegotiationInfo { 114 coded_resolution: Resolution { width: hdr.width, height: hdr.height }, 115 bit_depth: hdr.bit_depth, 116 profile: hdr.profile, 117 } 118 } 119 } 120 121 /// [`StatelessCodec`] structure to use in order to create a VP9 stateless decoder. 122 /// 123 /// # Accepted input 124 /// 125 /// the VP9 specification requires the last byte of the chunk to contain the superframe marker. 126 /// Thus, a decoder using this codec processes exactly one encoded chunk per call to 127 /// [`StatelessDecoder::decode`], and always returns the size of the passed input if successful. 128 pub struct Vp9; 129 130 impl StatelessCodec for Vp9 { 131 type FormatInfo = Header; 132 type DecoderState<H: DecodedHandle, P> = Vp9DecoderState<H>; 133 } 134 135 impl<B> StatelessDecoder<Vp9, B> 136 where 137 B: StatelessVp9DecoderBackend, 138 B::Handle: Clone, 139 { update_references( reference_frames: &mut [Option<B::Handle>; NUM_REF_FRAMES], picture: &B::Handle, mut refresh_frame_flags: u8, ) -> anyhow::Result<()>140 fn update_references( 141 reference_frames: &mut [Option<B::Handle>; NUM_REF_FRAMES], 142 picture: &B::Handle, 143 mut refresh_frame_flags: u8, 144 ) -> anyhow::Result<()> { 145 #[allow(clippy::needless_range_loop)] 146 for i in 0..NUM_REF_FRAMES { 147 if (refresh_frame_flags & 1) == 1 { 148 debug!("Replacing reference frame {}", i); 149 reference_frames[i] = Some(picture.clone()); 150 } 151 152 refresh_frame_flags >>= 1; 153 } 154 155 Ok(()) 156 } 157 158 /// Handle a frame which `show_existing_frame` flag is `true`. handle_show_existing_frame(&mut self, frame_to_show_map_idx: u8) -> Result<(), DecodeError>159 fn handle_show_existing_frame(&mut self, frame_to_show_map_idx: u8) -> Result<(), DecodeError> { 160 // Frame to be shown. Because the spec mandates that frame_to_show_map_idx references a 161 // valid entry in the DPB, an non-existing index means that the stream is invalid. 162 let idx = usize::from(frame_to_show_map_idx); 163 let ref_frame = self 164 .codec 165 .reference_frames 166 .get(idx) 167 .ok_or_else(|| anyhow::anyhow!("invalid reference frame index in header"))? 168 .as_ref() 169 .ok_or_else(|| anyhow::anyhow!("empty reference frame referenced in frame header"))?; 170 171 // We are done, no further processing needed. 172 let decoded_handle = ref_frame.clone(); 173 174 self.ready_queue.push(decoded_handle); 175 176 Ok(()) 177 } 178 179 /// Decode a single frame. handle_frame(&mut self, frame: &Frame, picture: B::Picture) -> Result<(), DecodeError>180 fn handle_frame(&mut self, frame: &Frame, picture: B::Picture) -> Result<(), DecodeError> { 181 let refresh_frame_flags = frame.header.refresh_frame_flags; 182 183 Segmentation::update_segmentation(&mut self.codec.segmentation, &frame.header); 184 185 let decoded_handle = self.backend.submit_picture( 186 picture, 187 &frame.header, 188 &self.codec.reference_frames, 189 frame.as_ref(), 190 &self.codec.segmentation, 191 )?; 192 193 if self.blocking_mode == BlockingMode::Blocking { 194 decoded_handle.sync()?; 195 } 196 197 // Do DPB management 198 Self::update_references( 199 &mut self.codec.reference_frames, 200 &decoded_handle, 201 refresh_frame_flags, 202 )?; 203 204 if frame.header.show_frame { 205 self.ready_queue.push(decoded_handle); 206 } 207 208 Ok(()) 209 } 210 negotiation_possible(&self, hdr: &Header, old_negotiation_info: &NegotiationInfo) -> bool211 fn negotiation_possible(&self, hdr: &Header, old_negotiation_info: &NegotiationInfo) -> bool { 212 let negotiation_info = NegotiationInfo::from(hdr); 213 214 if negotiation_info.coded_resolution.width == 0 215 || negotiation_info.coded_resolution.height == 0 216 { 217 false 218 } else { 219 *old_negotiation_info != negotiation_info 220 } 221 } 222 } 223 224 impl<B> StatelessVideoDecoder for StatelessDecoder<Vp9, B> 225 where 226 B: StatelessVp9DecoderBackend, 227 B::Handle: Clone + 'static, 228 { 229 type Handle = B::Handle; 230 decode( &mut self, timestamp: u64, bitstream: &[u8], alloc_cb: &mut dyn FnMut() -> Option< <<B as StatelessDecoderBackend>::Handle as DecodedHandle>::Frame, >, ) -> Result<usize, DecodeError>231 fn decode( 232 &mut self, 233 timestamp: u64, 234 bitstream: &[u8], 235 alloc_cb: &mut dyn FnMut() -> Option< 236 <<B as StatelessDecoderBackend>::Handle as DecodedHandle>::Frame, 237 >, 238 ) -> Result<usize, DecodeError> { 239 let frames = self 240 .codec 241 .parser 242 .parse_chunk(bitstream) 243 .map_err(|err| DecodeError::ParseFrameError(err))?; 244 245 self.wait_for_drc_flush()?; 246 247 // With SVC, the first frame will usually be a key-frame, with 248 // inter-frames carrying the other layers. 249 // 250 // We do not want each of those to be considered as a separate DRC 251 // event. Not only that, allowing them to be will cause an infinite 252 // loop. 253 // 254 // Instead, negotiate based on the largest spatial layer. That will be 255 // enough to house the other layers in between. 256 let largest_in_superframe = frames.iter().max_by(|&a, &b| { 257 let a_res = Resolution::from((a.header.width, a.header.height)); 258 let b_res = Resolution::from((b.header.width, b.header.height)); 259 if a_res == b_res { 260 std::cmp::Ordering::Equal 261 } else if a_res.can_contain(b_res) { 262 std::cmp::Ordering::Greater 263 } else { 264 std::cmp::Ordering::Less 265 } 266 }); 267 268 if let Some(frame) = largest_in_superframe { 269 if self.negotiation_possible(&frame.header, &self.codec.negotiation_info) { 270 if matches!(self.decoding_state, DecodingState::Decoding) { 271 // DRC occurs when a key frame is seen, the format is different, 272 // and the decoder is already decoding frames. 273 self.flush()?; 274 self.decoding_state = DecodingState::FlushingForDRC; 275 // Start signaling the awaiting format event to process a format change. 276 self.awaiting_format_event.write(1).unwrap(); 277 return Err(DecodeError::CheckEvents); 278 } 279 self.backend.new_sequence(&frame.header)?; 280 self.await_format_change(frame.header.clone()); 281 } else if matches!(self.decoding_state, DecodingState::Reset) { 282 // We can resume decoding since the decoding parameters have not changed. 283 self.decoding_state = DecodingState::Decoding; 284 } 285 } 286 287 match &mut self.decoding_state { 288 // Skip input until we get information from the stream. 289 DecodingState::AwaitingStreamInfo | DecodingState::Reset => (), 290 // Ask the client to confirm the format before we can process this. 291 DecodingState::FlushingForDRC | DecodingState::AwaitingFormat(_) => { 292 // Start signaling the awaiting format event to process a format change. 293 self.awaiting_format_event.write(1).unwrap(); 294 return Err(DecodeError::CheckEvents); 295 } 296 DecodingState::Decoding => { 297 // First allocate all the pictures we need for this superframe. 298 let num_required_pictures = 299 frames.iter().filter(|f| !f.header.show_existing_frame).count(); 300 let frames_with_pictures = frames 301 .into_iter() 302 .enumerate() 303 .map(|(i, frame)| { 304 if frame.header.show_existing_frame { 305 Ok((frame, None)) 306 } else { 307 self.backend 308 .new_picture(timestamp, alloc_cb) 309 .map_err(|e| match e { 310 NewPictureError::OutOfOutputBuffers => { 311 DecodeError::NotEnoughOutputBuffers( 312 num_required_pictures - i, 313 ) 314 } 315 e => DecodeError::from(e), 316 }) 317 .map(|picture| (frame, Some(picture))) 318 } 319 }) 320 .collect::<Result<Vec<_>, _>>()?; 321 322 // Then process each frame. 323 for (frame, picture) in frames_with_pictures { 324 match picture { 325 None => { 326 self.handle_show_existing_frame(frame.header.frame_to_show_map_idx)? 327 } 328 Some(picture) => self.handle_frame(&frame, picture)?, 329 } 330 } 331 } 332 } 333 334 Ok(bitstream.len()) 335 } 336 flush(&mut self) -> Result<(), DecodeError>337 fn flush(&mut self) -> Result<(), DecodeError> { 338 // Note: all the submitted frames are already in the ready queue. 339 self.codec.reference_frames = Default::default(); 340 self.decoding_state = DecodingState::Reset; 341 342 Ok(()) 343 } 344 next_event(&mut self) -> Option<DecoderEvent<B::Handle>>345 fn next_event(&mut self) -> Option<DecoderEvent<B::Handle>> { 346 self.query_next_event(|decoder, hdr| { 347 decoder.codec.negotiation_info = hdr.into(); 348 }) 349 } 350 stream_info(&self) -> Option<&StreamInfo>351 fn stream_info(&self) -> Option<&StreamInfo> { 352 self.backend.stream_info() 353 } 354 poll_fd(&self) -> BorrowedFd355 fn poll_fd(&self) -> BorrowedFd { 356 self.epoll_fd.0.as_fd() 357 } 358 } 359 360 #[cfg(test)] 361 pub mod tests { 362 use crate::bitstream_utils::IvfIterator; 363 use crate::decoder::stateless::tests::test_decode_stream; 364 use crate::decoder::stateless::tests::TestStream; 365 use crate::decoder::stateless::vp9::Vp9; 366 use crate::decoder::stateless::StatelessDecoder; 367 use crate::decoder::BlockingMode; 368 use crate::utils::simple_playback_loop; 369 use crate::utils::simple_playback_loop_owned_frames; 370 use crate::DecodedFormat; 371 372 /// Run `test` using the dummy decoder, in both blocking and non-blocking modes. test_decoder_dummy(test: &TestStream, blocking_mode: BlockingMode)373 fn test_decoder_dummy(test: &TestStream, blocking_mode: BlockingMode) { 374 let decoder = StatelessDecoder::<Vp9, _>::new_dummy(blocking_mode).unwrap(); 375 376 test_decode_stream( 377 |d, s, c| { 378 simple_playback_loop( 379 d, 380 IvfIterator::new(s), 381 c, 382 &mut simple_playback_loop_owned_frames, 383 DecodedFormat::NV12, 384 blocking_mode, 385 ) 386 }, 387 decoder, 388 test, 389 false, 390 false, 391 ); 392 } 393 394 /// Same as Chromium's test-25fps.vp8 395 pub const DECODE_TEST_25FPS: TestStream = TestStream { 396 stream: include_bytes!("../../codec/vp9/test_data/test-25fps.vp9"), 397 crcs: include_str!("../../codec/vp9/test_data/test-25fps.vp9.crc"), 398 }; 399 400 #[test] test_25fps_block()401 fn test_25fps_block() { 402 test_decoder_dummy(&DECODE_TEST_25FPS, BlockingMode::Blocking); 403 } 404 405 #[test] test_25fps_nonblock()406 fn test_25fps_nonblock() { 407 test_decoder_dummy(&DECODE_TEST_25FPS, BlockingMode::NonBlocking); 408 } 409 410 // Remuxed from the original matroska source in libvpx using ffmpeg: 411 // ffmpeg -i vp90-2-10-show-existing-frame.webm/vp90-2-10-show-existing-frame.webm -c:v copy /tmp/vp90-2-10-show-existing-frame.vp9.ivf 412 pub const DECODE_TEST_25FPS_SHOW_EXISTING_FRAME: TestStream = TestStream { 413 stream: include_bytes!("../../codec/vp9/test_data/vp90-2-10-show-existing-frame.vp9.ivf"), 414 crcs: include_str!("../../codec/vp9/test_data/vp90-2-10-show-existing-frame.vp9.ivf.crc"), 415 }; 416 417 #[test] show_existing_frame_block()418 fn show_existing_frame_block() { 419 test_decoder_dummy(&DECODE_TEST_25FPS_SHOW_EXISTING_FRAME, BlockingMode::Blocking); 420 } 421 422 #[test] show_existing_frame_nonblock()423 fn show_existing_frame_nonblock() { 424 test_decoder_dummy(&DECODE_TEST_25FPS_SHOW_EXISTING_FRAME, BlockingMode::NonBlocking); 425 } 426 427 pub const DECODE_TEST_25FPS_SHOW_EXISTING_FRAME2: TestStream = TestStream { 428 stream: include_bytes!("../../codec/vp9/test_data/vp90-2-10-show-existing-frame2.vp9.ivf"), 429 crcs: include_str!("../../codec/vp9/test_data/vp90-2-10-show-existing-frame2.vp9.ivf.crc"), 430 }; 431 432 #[test] show_existing_frame2_block()433 fn show_existing_frame2_block() { 434 test_decoder_dummy(&DECODE_TEST_25FPS_SHOW_EXISTING_FRAME2, BlockingMode::Blocking); 435 } 436 437 #[test] show_existing_frame2_nonblock()438 fn show_existing_frame2_nonblock() { 439 test_decoder_dummy(&DECODE_TEST_25FPS_SHOW_EXISTING_FRAME2, BlockingMode::NonBlocking); 440 } 441 442 // Remuxed from the original matroska source in libvpx using ffmpeg: 443 // ffmpeg -i vp90-2-10-show-existing-frame.webm/vp90-2-10-show-existing-frame.webm -c:v copy /tmp/vp90-2-10-show-existing-frame.vp9.ivf 444 // There are some weird padding issues introduced by GStreamer for 445 // resolutions that are not multiple of 4, so we're ignoring CRCs for 446 // this one. 447 pub const DECODE_RESOLUTION_CHANGE_500FRAMES: TestStream = TestStream { 448 stream: include_bytes!("../../codec/vp9/test_data/resolution_change_500frames-vp9.ivf"), 449 crcs: include_str!("../../codec/vp9/test_data/resolution_change_500frames-vp9.ivf.crc"), 450 }; 451 452 #[test] test_resolution_change_500frames_block()453 fn test_resolution_change_500frames_block() { 454 test_decoder_dummy(&DECODE_RESOLUTION_CHANGE_500FRAMES, BlockingMode::Blocking); 455 } 456 457 #[test] test_resolution_change_500frames_nonblock()458 fn test_resolution_change_500frames_nonblock() { 459 test_decoder_dummy(&DECODE_RESOLUTION_CHANGE_500FRAMES, BlockingMode::Blocking); 460 } 461 } 462