• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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