rav1e/api/
context.rs

1// Copyright (c) 2018-2022, The rav1e contributors. All rights reserved
2//
3// This source code is subject to the terms of the BSD 2 Clause License and
4// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
5// was not distributed with this source code in the LICENSE file, you can
6// obtain it at www.aomedia.org/license/software. If the Alliance for Open
7// Media Patent License 1.0 was not distributed with this source code in the
8// PATENTS file, you can obtain it at www.aomedia.org/license/patent.
9#![deny(missing_docs)]
10
11use std::fmt;
12use std::io;
13use std::sync::Arc;
14
15use bitstream_io::{BigEndian, BitWrite, BitWriter};
16
17use crate::api::color::*;
18use crate::api::config::*;
19use crate::api::internal::*;
20use crate::api::util::*;
21use crate::encoder::*;
22use crate::frame::*;
23use crate::util::Pixel;
24
25/// The encoder context.
26///
27/// Contains the encoding state.
28pub struct Context<T: Pixel> {
29  pub(crate) inner: ContextInner<T>,
30  pub(crate) config: EncoderConfig,
31  pub(crate) pool: Option<Arc<rayon::ThreadPool>>,
32  pub(crate) is_flushing: bool,
33}
34
35impl<T: Pixel> Context<T> {
36  /// Allocates and returns a new frame.
37  ///
38  /// # Examples
39  ///
40  /// ```
41  /// use rav1e::prelude::*;
42  ///
43  /// # fn main() -> Result<(), InvalidConfig> {
44  /// let cfg = Config::default();
45  /// let ctx: Context<u8> = cfg.new_context()?;
46  /// let frame = ctx.new_frame();
47  /// # Ok(())
48  /// # }
49  /// ```
50  #[inline]
51  pub fn new_frame(&self) -> Frame<T> {
52    Frame::new(
53      self.config.width,
54      self.config.height,
55      self.config.chroma_sampling,
56    )
57  }
58
59  /// Sends the frame for encoding.
60  ///
61  /// This method adds the frame into the frame queue and runs the first passes
62  /// of the look-ahead computation.
63  ///
64  /// Passing `None` is equivalent to calling [`flush`].
65  ///
66  /// The caller is responsible for padding the invisible portion of the frame,
67  /// if multiple references to the frame are held.
68  /// Calling [`Plane::pad()`] after filling each plane or equivalent is required.
69  ///
70  /// # Errors
71  ///
72  /// If this method is called with a frame after the encoder has been flushed
73  /// or the encoder internal limit is hit (`std::i32::MAX` frames) the
74  /// [`EncoderStatus::EnoughData`] error is returned.
75  ///
76  /// # Examples
77  ///
78  /// ```
79  /// use rav1e::prelude::*;
80  ///
81  /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
82  /// # if false {
83  /// let cfg = Config::default();
84  /// let mut ctx: Context<u8> = cfg.new_context().unwrap();
85  /// let f1 = ctx.new_frame();
86  /// let f2 = f1.clone();
87  /// let info = FrameParameters {
88  ///   frame_type_override: FrameTypeOverride::Key,
89  ///   opaque: None,
90  ///   ..Default::default()
91  /// };
92  ///
93  /// // Send the plain frame data
94  /// ctx.send_frame(f1)?;
95  /// // Send the data and the per-frame parameters
96  /// // In this case the frame is forced to be a keyframe.
97  /// ctx.send_frame((f2, info))?;
98  /// // Flush the encoder, it is equivalent to a call to `flush()`
99  /// ctx.send_frame(None)?;
100  /// # }
101  /// # Ok(())
102  /// # }
103  /// ```
104  ///
105  /// [`flush`]: #method.flush
106  /// [`EncoderStatus::EnoughData`]: enum.EncoderStatus.html#variant.EnoughData
107  #[inline]
108  pub fn send_frame<F>(&mut self, frame: F) -> Result<(), EncoderStatus>
109  where
110    F: IntoFrame<T>,
111  {
112    let (frame, params) = frame.into();
113
114    if frame.is_none() {
115      if self.is_flushing {
116        return Ok(());
117      }
118      self.inner.limit = Some(self.inner.frame_count);
119      self.is_flushing = true;
120    } else if self.is_flushing
121      || (self.inner.config.still_picture && self.inner.frame_count > 0)
122    {
123      return Err(EncoderStatus::EnoughData);
124    // The rate control can process at most i32::MAX frames
125    } else if self.inner.frame_count == i32::MAX as u64 - 1 {
126      self.inner.limit = Some(self.inner.frame_count);
127      self.is_flushing = true;
128    }
129
130    let inner = &mut self.inner;
131    let run = move || inner.send_frame(frame, params);
132
133    match &self.pool {
134      Some(pool) => pool.install(run),
135      None => run(),
136    }
137  }
138
139  /// Returns the first-pass data of a two-pass encode for the frame that was
140  /// just encoded.
141  ///
142  /// This should be called BEFORE every call to [`receive_packet`] (including
143  /// the very first one), even if no packet was produced by the last call to
144  /// [`receive_packet`], if any (i.e., [`EncoderStatus::Encoded`] was
145  /// returned).  It needs to be called once more after
146  /// [`EncoderStatus::LimitReached`] is returned, to retrieve the header that
147  /// should be written to the front of the stats file (overwriting the
148  /// placeholder header that was emitted at the start of encoding).
149  ///
150  /// It is still safe to call this function when [`receive_packet`] returns
151  /// any other error. It will return `None` instead of returning a duplicate
152  /// copy of the previous frame's data.
153  ///
154  /// [`receive_packet`]: #method.receive_packet
155  /// [`EncoderStatus::Encoded`]: enum.EncoderStatus.html#variant.Encoded
156  /// [`EncoderStatus::LimitReached`]:
157  /// enum.EncoderStatus.html#variant.LimitReached
158  #[inline]
159  pub fn twopass_out(&mut self) -> Option<&[u8]> {
160    self.inner.rc_state.twopass_out(self.inner.done_processing())
161  }
162
163  /// Returns the number of bytes of the stats file needed before the next
164  /// frame of the second pass in a two-pass encode can be encoded.
165  ///
166  /// This is a lower bound (more might be required), but if `0` is returned,
167  /// then encoding can proceed. This is just a hint to the application, and
168  /// does not need to be called for encoding the second pass to work, so long
169  /// as the application continues to provide more data to [`twopass_in`] in a
170  /// loop until [`twopass_in`] returns `0`.
171  ///
172  /// [`twopass_in`]: #method.twopass_in
173  #[inline]
174  pub fn twopass_bytes_needed(&mut self) -> usize {
175    self.inner.rc_state.twopass_in(None).unwrap_or(0)
176  }
177
178  /// Provides the stats data produced in the first pass of a two-pass encode
179  /// to the second pass.
180  ///
181  /// On success this returns the number of bytes of the data which were
182  /// consumed. When encoding the second pass of a two-pass encode, this should
183  /// be called repeatedly in a loop before every call to [`receive_packet`]
184  /// (including the very first one) until no bytes are consumed, or until
185  /// [`twopass_bytes_needed`] returns `0`.
186  ///
187  /// [`receive_packet`]: #method.receive_packet
188  /// [`twopass_bytes_needed`]: #method.twopass_bytes_needed
189  ///
190  /// # Errors
191  ///
192  /// Returns `Err(EncoderStatus::Failure)` if the two-pass data is invalid.
193  #[inline]
194  pub fn twopass_in(&mut self, buf: &[u8]) -> Result<usize, EncoderStatus> {
195    self.inner.rc_state.twopass_in(Some(buf)).or(Err(EncoderStatus::Failure))
196  }
197
198  /// Encodes the next frame and returns the encoded data.
199  ///
200  /// This method is where the main encoding work is done.
201  ///
202  /// # Errors
203  ///
204  /// May return `Err(EncoderStatus)`, which should be handled by the caller.
205  ///
206  /// # Examples
207  ///
208  /// Encoding a single frame:
209  ///
210  /// ```
211  /// use rav1e::prelude::*;
212  ///
213  /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
214  /// # if false {
215  /// let cfg = Config::default();
216  /// let mut ctx: Context<u8> = cfg.new_context()?;
217  /// let frame = ctx.new_frame();
218  ///
219  /// ctx.send_frame(frame)?;
220  /// ctx.flush();
221  ///
222  /// loop {
223  ///     match ctx.receive_packet() {
224  ///         Ok(packet) => { /* Mux the packet. */ },
225  ///         Err(EncoderStatus::Encoded) => (),
226  ///         Err(EncoderStatus::LimitReached) => break,
227  ///         Err(err) => Err(err)?,
228  ///     }
229  /// }
230  /// # }
231  /// # Ok(())
232  /// # }
233  /// ```
234  ///
235  /// Encoding a sequence of frames:
236  ///
237  /// ```
238  /// use std::sync::Arc;
239  /// use rav1e::prelude::*;
240  ///
241  /// fn encode_frames(
242  ///     ctx: &mut Context<u8>,
243  ///     mut frames: impl Iterator<Item=Frame<u8>>
244  /// ) -> Result<(), EncoderStatus> {
245  ///     // This is a slightly contrived example, intended to showcase the
246  ///     // various statuses that can be returned from receive_packet().
247  ///     // Assume that, for example, there are a lot of frames in the
248  ///     // iterator, which are produced lazily, so you don't want to send
249  ///     // them all in at once as to not exhaust the memory.
250  ///     loop {
251  ///         match ctx.receive_packet() {
252  ///             Ok(packet) => { /* Mux the packet. */ },
253  ///             Err(EncoderStatus::Encoded) => {
254  ///                 // A frame was encoded without emitting a packet. This is
255  ///                 // normal, just proceed as usual.
256  ///             },
257  ///             Err(EncoderStatus::LimitReached) => {
258  ///                 // All frames have been encoded. Time to break out of the
259  ///                 // loop.
260  ///                 break;
261  ///             },
262  ///             Err(EncoderStatus::NeedMoreData) => {
263  ///                 // The encoder has requested additional frames. Push the
264  ///                 // next frame in, or flush the encoder if there are no
265  ///                 // frames left (on None).
266  ///                 ctx.send_frame(frames.next().map(Arc::new))?;
267  ///             },
268  ///             Err(EncoderStatus::EnoughData) => {
269  ///                 // Since we aren't trying to push frames after flushing,
270  ///                 // this should never happen in this example.
271  ///                 unreachable!();
272  ///             },
273  ///             Err(EncoderStatus::NotReady) => {
274  ///                 // We're not doing two-pass encoding, so this can never
275  ///                 // occur.
276  ///                 unreachable!();
277  ///             },
278  ///             Err(EncoderStatus::Failure) => {
279  ///                 return Err(EncoderStatus::Failure);
280  ///             },
281  ///         }
282  ///     }
283  ///
284  ///     Ok(())
285  /// }
286  /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
287  /// #   if false {
288  /// #     let mut enc = EncoderConfig::default();
289  /// #     // So it runs faster.
290  /// #     enc.width = 16;
291  /// #     enc.height = 16;
292  /// #     let cfg = Config::new().with_encoder_config(enc);
293  /// #     let mut ctx: Context<u8> = cfg.new_context()?;
294  /// #
295  /// #     let frames = vec![ctx.new_frame(); 4].into_iter();
296  /// #     encode_frames(&mut ctx, frames);
297  /// #   }
298  /// #   Ok(())
299  /// # }
300  /// ```
301  #[inline]
302  pub fn receive_packet(&mut self) -> Result<Packet<T>, EncoderStatus> {
303    let inner = &mut self.inner;
304    let mut run = move || inner.receive_packet();
305
306    match &self.pool {
307      Some(pool) => pool.install(run),
308      None => run(),
309    }
310  }
311
312  /// Flushes the encoder.
313  ///
314  /// Flushing signals the end of the video. After the encoder has been
315  /// flushed, no additional frames are accepted.
316  ///
317  /// # Panics
318  ///
319  /// Panics if `send_frame` returns an `Err`.
320  /// This should never happen when calling it with `None`
321  /// and indicates a development error.
322  #[inline]
323  pub fn flush(&mut self) {
324    self.send_frame(None).unwrap();
325  }
326
327  /// Produces a sequence header matching the current encoding context.
328  ///
329  /// Its format is compatible with the AV1 Matroska and ISOBMFF specification.
330  /// Note that the returned header does not include any config OBUs which are
331  /// required for some uses. See [the specification].
332  ///
333  /// [the specification]:
334  /// https://aomediacodec.github.io/av1-isobmff/#av1codecconfigurationbox-section
335  ///
336  /// # Panics
337  ///
338  /// Panics if the header cannot be written in memory. This is unrecoverable,
339  /// and usually indicates the system is out of memory.
340  #[inline]
341  pub fn container_sequence_header(&self) -> Vec<u8> {
342    fn sequence_header_inner(seq: &Sequence) -> io::Result<Vec<u8>> {
343      let mut buf = Vec::new();
344
345      {
346        let mut bw = BitWriter::endian(&mut buf, BigEndian);
347        bw.write_bit(true)?; // marker
348        bw.write::<7, u8>(1)?; // version
349        bw.write::<3, u8>(seq.profile)?;
350        bw.write::<5, u8>(31)?; // level
351        bw.write_bit(false)?; // tier
352        bw.write_bit(seq.bit_depth > 8)?; // high_bitdepth
353        bw.write_bit(seq.bit_depth == 12)?; // twelve_bit
354        bw.write_bit(seq.chroma_sampling == ChromaSampling::Cs400)?; // monochrome
355        bw.write_bit(seq.chroma_sampling != ChromaSampling::Cs444)?; // chroma_subsampling_x
356        bw.write_bit(seq.chroma_sampling == ChromaSampling::Cs420)?; // chroma_subsampling_y
357        bw.write::<2, u8>(0)?; // chroma_sample_position
358        bw.write::<3, u8>(0)?; // reserved
359        bw.write_bit(false)?; // initial_presentation_delay_present
360
361        bw.write::<4, u8>(0)?; // reserved
362      }
363
364      Ok(buf)
365    }
366
367    let seq = Sequence::new(&self.config);
368
369    sequence_header_inner(&seq).unwrap()
370  }
371}
372
373/// Rate Control Data
374pub enum RcData {
375  /// A Rate Control Summary Packet
376  ///
377  /// It is emitted once, after the encoder is flushed.
378  ///
379  /// It contains a summary of the rate control information for the
380  /// encoding process that just terminated.
381  Summary(Box<[u8]>),
382  /// A Rate Control Frame-specific Packet
383  ///
384  /// It is emitted every time a frame is processed.
385  ///
386  /// The information contained is required to encode its matching
387  /// frame in a second pass encoding.
388  Frame(Box<[u8]>),
389}
390
391impl<T: Pixel> Context<T> {
392  /// Return the Rate Control Summary Packet size
393  ///
394  /// It is useful mainly to preserve space when saving
395  /// both Rate Control Summary and Frame Packets in a single file.
396  pub fn rc_summary_size(&self) -> usize {
397    crate::rate::TWOPASS_HEADER_SZ
398  }
399
400  /// Return the first pass data
401  ///
402  /// Call it after `receive_packet`, it returns a packet or the encoder
403  /// lifecycle statuses [`EncoderStatus::Encoded`] and
404  /// [`EncoderStatus::LimitReached`].
405  ///
406  /// [`EncoderStatus::Encoded`]: enum.EncoderStatus.html#variant.Encoded
407  /// [`EncoderStatus::LimitReached`]:
408  /// enum.EncoderStatus.html#variant.LimitReached
409  ///
410  /// It will return a `RcData::Summary` once the encoder is flushed.
411  pub fn rc_receive_pass_data(&mut self) -> Option<RcData> {
412    if self.inner.done_processing() && self.inner.rc_state.pass1_data_retrieved
413    {
414      let data = self.inner.rc_state.emit_summary();
415      Some(RcData::Summary(data.to_vec().into_boxed_slice()))
416    } else if self.inner.rc_state.pass1_data_retrieved {
417      None
418    } else if let Some(data) = self.inner.rc_state.emit_frame_data() {
419      Some(RcData::Frame(data.to_vec().into_boxed_slice()))
420    } else {
421      unreachable!(
422        "The encoder received more frames than its internal limit allows"
423      )
424    }
425  }
426
427  /// Lower bound number of pass data packets required to progress the
428  /// encoding process.
429  ///
430  /// It should be called iteratively until it returns 0.
431  pub fn rc_second_pass_data_required(&self) -> usize {
432    if self.inner.done_processing() {
433      0
434    } else {
435      self.inner.rc_state.twopass_in_frames_needed() as usize
436    }
437  }
438
439  /// Feed the first pass Rate Control data to the encoder,
440  /// Frame-specific Packets only.
441  ///
442  /// Call it before `receive_packet()`
443  ///
444  /// # Errors
445  ///
446  /// Returns `EncoderStatus::Failure` if the data provided is incorrect
447  pub fn rc_send_pass_data(
448    &mut self, data: &[u8],
449  ) -> Result<(), EncoderStatus> {
450    self
451      .inner
452      .rc_state
453      .parse_frame_data_packet(data)
454      .map_err(|_| EncoderStatus::Failure)
455  }
456}
457
458impl<T: Pixel> fmt::Debug for Context<T> {
459  fn fmt(
460    &self, f: &mut fmt::Formatter<'_>,
461  ) -> std::result::Result<(), fmt::Error> {
462    write!(
463      f,
464      "{{ \
465        config: {:?}, \
466        is_flushing: {}, \
467      }}",
468      self.config, self.is_flushing,
469    )
470  }
471}