rav1e/
lib.rs

1// Copyright (c) 2017-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
10//! rav1e is an [AV1] video encoder. It is designed to eventually cover all use
11//! cases, though in its current form it is most suitable for cases where
12//! libaom (the reference encoder) is too slow.
13//!
14//! ## Features
15//!
16//! * Intra and inter frames
17//! * 64x64 superblocks
18//! * 4x4 to 64x64 RDO-selected square and 2:1/1:2 rectangular blocks
19//! * DC, H, V, Paeth, smooth, and a subset of directional prediction modes
20//! * DCT, (FLIP-)ADST and identity transforms (up to 64x64, 16x16 and 32x32
21//!   respectively)
22//! * 8-, 10- and 12-bit depth color
23//! * 4:2:0 (full support), 4:2:2 and 4:4:4 (limited) chroma sampling
24//! * Variable speed settings
25//! * Near real-time encoding at high speed levels
26//!
27//! ## Usage
28//!
29//! Encoding is done through the [`Context`] struct. Examples on
30//! [`Context::receive_packet`] show how to create a [`Context`], send frames
31//! into it and receive packets of encoded data.
32//!
33//! [AV1]: https://aomediacodec.github.io/av1-spec/av1-spec.pdf
34//! [`Context`]: struct.Context.html
35//! [`Context::receive_packet`]: struct.Context.html#method.receive_packet
36
37// Safety lints
38#![deny(bare_trait_objects)]
39#![deny(clippy::as_ptr_cast_mut)]
40#![deny(clippy::large_stack_arrays)]
41// Performance lints
42#![warn(clippy::inefficient_to_string)]
43#![warn(clippy::invalid_upcast_comparisons)]
44#![warn(clippy::iter_with_drain)]
45#![warn(clippy::linkedlist)]
46#![warn(clippy::mutex_integer)]
47#![warn(clippy::naive_bytecount)]
48#![warn(clippy::needless_bitwise_bool)]
49#![warn(clippy::needless_collect)]
50#![warn(clippy::or_fun_call)]
51#![warn(clippy::stable_sort_primitive)]
52#![warn(clippy::suboptimal_flops)]
53#![warn(clippy::trivial_regex)]
54#![warn(clippy::trivially_copy_pass_by_ref)]
55#![warn(clippy::unnecessary_join)]
56#![warn(clippy::unused_async)]
57#![warn(clippy::zero_sized_map_values)]
58// Correctness lints
59#![deny(clippy::case_sensitive_file_extension_comparisons)]
60#![deny(clippy::copy_iterator)]
61#![deny(clippy::expl_impl_clone_on_copy)]
62#![deny(clippy::float_cmp)]
63#![warn(clippy::imprecise_flops)]
64#![deny(clippy::manual_instant_elapsed)]
65#![deny(clippy::mem_forget)]
66#![deny(clippy::path_buf_push_overwrite)]
67#![deny(clippy::same_functions_in_if_condition)]
68#![deny(clippy::unchecked_duration_subtraction)]
69#![deny(clippy::unicode_not_nfc)]
70// Clarity/formatting lints
71#![warn(clippy::checked_conversions)]
72#![allow(clippy::comparison_chain)]
73#![warn(clippy::derive_partial_eq_without_eq)]
74#![allow(clippy::enum_variant_names)]
75#![warn(clippy::explicit_deref_methods)]
76#![warn(clippy::filter_map_next)]
77#![warn(clippy::flat_map_option)]
78#![warn(clippy::fn_params_excessive_bools)]
79#![warn(clippy::implicit_clone)]
80#![warn(clippy::iter_not_returning_iterator)]
81#![warn(clippy::iter_on_empty_collections)]
82#![warn(clippy::macro_use_imports)]
83#![warn(clippy::manual_clamp)]
84#![warn(clippy::manual_let_else)]
85#![warn(clippy::manual_ok_or)]
86#![warn(clippy::manual_string_new)]
87#![warn(clippy::map_flatten)]
88#![warn(clippy::match_bool)]
89#![warn(clippy::mut_mut)]
90#![warn(clippy::needless_borrow)]
91#![warn(clippy::needless_continue)]
92#![allow(clippy::needless_range_loop)]
93#![allow(clippy::too_many_arguments)]
94#![warn(clippy::range_minus_one)]
95#![warn(clippy::range_plus_one)]
96#![warn(clippy::ref_binding_to_reference)]
97#![warn(clippy::ref_option_ref)]
98#![warn(clippy::trait_duplication_in_bounds)]
99#![warn(clippy::unused_peekable)]
100#![warn(clippy::unused_rounding)]
101#![warn(clippy::unused_self)]
102#![allow(clippy::upper_case_acronyms)]
103#![warn(clippy::verbose_bit_mask)]
104#![warn(clippy::verbose_file_reads)]
105// Documentation lints
106#![warn(clippy::doc_link_with_quotes)]
107#![warn(clippy::doc_markdown)]
108#![warn(clippy::missing_errors_doc)]
109#![warn(clippy::missing_panics_doc)]
110// FIXME: We should fix instances of this lint and change it to `warn`
111#![allow(clippy::missing_safety_doc)]
112
113// Override assert! and assert_eq! in tests
114#[cfg(test)]
115#[macro_use]
116extern crate pretty_assertions;
117
118#[macro_use]
119extern crate log;
120
121pub(crate) mod built_info {
122  // The file has been placed there by the build script.
123  include!(concat!(env!("OUT_DIR"), "/built.rs"));
124}
125
126mod serialize {
127  cfg_if::cfg_if! {
128    if #[cfg(feature="serialize")] {
129      pub use serde::*;
130    } else {
131      pub use noop_proc_macro::{Deserialize, Serialize};
132    }
133  }
134}
135
136mod wasm_bindgen {
137  cfg_if::cfg_if! {
138    if #[cfg(feature="wasm")] {
139      pub use wasm_bindgen::prelude::*;
140    } else {
141      pub use noop_proc_macro::wasm_bindgen;
142    }
143  }
144}
145
146#[cfg(any(cargo_c, feature = "capi"))]
147pub mod capi;
148
149#[macro_use]
150mod transform;
151#[macro_use]
152mod cpu_features;
153
154mod activity;
155pub(crate) mod asm;
156mod dist;
157mod ec;
158mod partition;
159mod predict;
160mod quantize;
161mod rdo;
162mod rdo_tables;
163#[macro_use]
164mod util;
165mod cdef;
166#[doc(hidden)]
167pub mod context;
168mod deblock;
169mod encoder;
170mod entropymode;
171mod levels;
172mod lrf;
173mod mc;
174mod me;
175mod rate;
176mod recon_intra;
177mod sad_plane;
178mod scan_order;
179#[cfg(feature = "scenechange")]
180pub mod scenechange;
181#[cfg(not(feature = "scenechange"))]
182mod scenechange;
183mod segmentation;
184mod stats;
185#[doc(hidden)]
186pub mod tiling;
187mod token_cdfs;
188
189mod api;
190mod frame;
191mod header;
192
193use crate::encoder::*;
194
195pub use crate::api::{
196  Config, Context, EncoderConfig, EncoderStatus, InvalidConfig, Packet,
197};
198pub use crate::frame::Frame;
199pub use crate::util::{CastFromPrimitive, Pixel, PixelType};
200
201/// Commonly used types and traits.
202pub mod prelude {
203  pub use crate::api::*;
204  pub use crate::encoder::{Sequence, Tune};
205  pub use crate::frame::{
206    Frame, FrameParameters, FrameTypeOverride, Plane, PlaneConfig,
207  };
208  pub use crate::partition::BlockSize;
209  pub use crate::predict::PredictionMode;
210  pub use crate::transform::TxType;
211  pub use crate::util::{CastFromPrimitive, Pixel, PixelType};
212}
213
214/// Basic data structures
215pub mod data {
216  pub use crate::api::{
217    ChromaticityPoint, EncoderStatus, FrameType, Packet, Rational,
218  };
219  pub use crate::frame::{Frame, FrameParameters};
220  pub use crate::stats::EncoderStats;
221  pub use crate::util::{CastFromPrimitive, Pixel, PixelType};
222}
223
224pub use crate::api::color;
225
226/// Encoder configuration and settings
227pub mod config {
228  pub use crate::api::config::{
229    GrainTableSegment, NoiseGenArgs, TransferFunction, NUM_UV_COEFFS,
230    NUM_UV_POINTS, NUM_Y_COEFFS, NUM_Y_POINTS,
231  };
232  pub use crate::api::{
233    Config, EncoderConfig, InvalidConfig, PredictionModesSetting,
234    RateControlConfig, RateControlError, RateControlSummary, SpeedSettings,
235  };
236  pub use crate::cpu_features::CpuFeatureLevel;
237}
238
239/// Version information
240///
241/// The information is recovered from `Cargo.toml` and `git describe`, when available.
242///
243/// ```
244/// use rav1e::version;
245/// use semver::Version;
246///
247/// let major = version::major();
248/// let minor = version::minor();
249/// let patch = version::patch();
250///
251/// let short = version::short();
252///
253/// let v1 = Version::new(major, minor, patch);
254/// let v2 = Version::parse(&short).unwrap();
255///
256/// assert_eq!(v1.major, v2.major);
257/// ```
258pub mod version {
259  /// Major version component
260  ///
261  /// It is increased every time a release presents a incompatible API change.
262  ///
263  /// # Panics
264  ///
265  /// Will panic if package is not built with Cargo,
266  /// or if the package version is not a valid triplet of integers.
267  pub fn major() -> u64 {
268    env!("CARGO_PKG_VERSION_MAJOR").parse().unwrap()
269  }
270  /// Minor version component
271  ///
272  /// It is increased every time a release presents new functionalities are added
273  /// in a backwards-compatible manner.
274  ///
275  /// # Panics
276  ///
277  /// Will panic if package is not built with Cargo,
278  /// or if the package version is not a valid triplet of integers.
279  pub fn minor() -> u64 {
280    env!("CARGO_PKG_VERSION_MINOR").parse().unwrap()
281  }
282  /// Patch version component
283  ///
284  /// It is increased every time a release provides only backwards-compatible bugfixes.
285  ///
286  /// # Panics
287  ///
288  /// Will panic if package is not built with Cargo,
289  /// or if the package version is not a valid triplet of integers.
290  pub fn patch() -> u64 {
291    env!("CARGO_PKG_VERSION_PATCH").parse().unwrap()
292  }
293
294  /// Version information as presented in `[package]` `version`.
295  ///
296  /// e.g. `0.1.0`
297  ///
298  /// Can be parsed by [semver](https://crates.io/crates/semver).
299  pub fn short() -> String {
300    env!("CARGO_PKG_VERSION").to_string()
301  }
302
303  /// Version information as presented in `[package] version` followed by the
304  /// short commit hash if present.
305  ///
306  /// e.g. `0.1.0 - g743d464`
307  ///
308  pub fn long() -> String {
309    let s = short();
310    let hash = hash();
311
312    if hash.is_empty() {
313      s
314    } else {
315      format!("{s} - {hash}")
316    }
317  }
318
319  cfg_if::cfg_if! {
320    if #[cfg(feature="git_version")] {
321      fn git_version() -> &'static str {
322        crate::built_info::GIT_VERSION.unwrap_or_default()
323      }
324
325      fn git_hash() -> &'static str {
326        crate::built_info::GIT_COMMIT_HASH.unwrap_or_default()
327      }
328    } else {
329      fn git_version() -> &'static str {
330        "UNKNOWN"
331      }
332
333      fn git_hash() -> &'static str {
334        "UNKNOWN"
335      }
336    }
337  }
338  /// Commit hash (short)
339  ///
340  /// Short hash of the git commit used by this build
341  ///
342  /// e.g. `g743d464`
343  ///
344  pub fn hash() -> String {
345    git_hash().to_string()
346  }
347
348  /// Version information with the information
349  /// provided by `git describe --tags`.
350  ///
351  /// e.g. `0.1.0 (v0.1.0-1-g743d464)`
352  ///
353  pub fn full() -> String {
354    format!("{} ({})", short(), git_version(),)
355  }
356}
357#[cfg(all(
358  any(test, fuzzing),
359  any(feature = "decode_test", feature = "decode_test_dav1d")
360))]
361mod test_encode_decode;
362
363#[cfg(feature = "bench")]
364pub mod bench {
365  pub mod api {
366    pub use crate::api::*;
367  }
368  pub mod cdef {
369    pub use crate::cdef::*;
370  }
371  pub mod context {
372    pub use crate::context::*;
373  }
374  pub mod dist {
375    pub use crate::dist::*;
376  }
377  pub mod ec {
378    pub use crate::ec::*;
379  }
380  pub mod encoder {
381    pub use crate::encoder::*;
382  }
383  pub mod mc {
384    pub use crate::mc::*;
385  }
386  pub mod partition {
387    pub use crate::partition::*;
388  }
389  pub mod frame {
390    pub use crate::frame::*;
391  }
392  pub mod predict {
393    pub use crate::predict::*;
394  }
395  pub mod rdo {
396    pub use crate::rdo::*;
397  }
398  pub mod tiling {
399    pub use crate::tiling::*;
400  }
401  pub mod transform {
402    pub use crate::transform::*;
403  }
404  pub mod util {
405    pub use crate::util::*;
406  }
407  pub mod cpu_features {
408    pub use crate::cpu_features::*;
409  }
410}
411
412#[cfg(fuzzing)]
413pub mod fuzzing;