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}