symphonia/
lib.rs

1// Symphonia
2// Copyright (c) 2019-2022 The Project Symphonia Developers.
3//
4// This Source Code Form is subject to the terms of the Mozilla Public
5// License, v. 2.0. If a copy of the MPL was not distributed with this
6// file, You can obtain one at https://mozilla.org/MPL/2.0/.
7
8#![warn(rust_2018_idioms)]
9#![forbid(unsafe_code)]
10
11//! # Project Symphonia
12//!
13//! Symphonia is a 100% pure Rust audio decoding and multimedia format demuxing framework.
14//!
15//! # Support
16//!
17//! Supported formats, codecs, and metadata tags are listed below. By default Symphonia only enables
18//! royalty-free open standard media formats and codecs. Other formats and codecs must be enabled
19//! using feature flags.
20//!
21//! **Tip:** All formats and codecs can be enabled with the `all` feature flag.
22//!
23//! ## Formats
24//!
25//! The following container formats are supported.
26//!
27//! | Format   | Feature Flag | Gapless* | Default |
28//! |----------|--------------|----------|---------|
29//! | AIFF     | `aiff`       | Yes      | No      |
30//! | CAF      | `caf`        | No       | No      |
31//! | ISO/MP4  | `isomp4`     | No       | No      |
32//! | MKV/WebM | `mkv`        | No       | Yes     |
33//! | OGG      | `ogg`        | Yes      | Yes     |
34//! | Wave     | `wav`        | Yes      | Yes     |
35//!
36//! \* Gapless playback requires support from both the demuxer and decoder.
37//!
38//! **Tip:** All formats can be enabled with the `all-codecs` feature flag.
39//!
40//! ## Codecs
41//!
42//! The following codecs are supported.
43//!
44//! | Codec    | Feature Flag | Gapless | Default |
45//! |----------|--------------|---------|---------|
46//! | AAC-LC   | `aac`        | No      | No      |
47//! | ADPCM    | `adpcm`      | Yes     | Yes     |
48//! | ALAC     | `alac`       | Yes     | No      |
49//! | FLAC     | `flac`       | Yes     | Yes     |
50//! | MP1      | `mp1`, `mpa` | No      | No      |
51//! | MP2      | `mp2`, `mpa` | No      | No      |
52//! | MP3      | `mp3`, `mpa` | Yes     | No      |
53//! | PCM      | `pcm`        | Yes     | Yes     |
54//! | Vorbis   | `vorbis`     | Yes     | Yes     |
55//!
56//! **Tip:** All codecs can be enabled with the `all-codecs` feature flag. Similarly, all MPEG
57//! audio codecs can be enabled with the `mpa` feature flag.
58//!
59//! ## Metadata
60//!
61//! The following metadata tagging formats are supported. These are always enabled.
62//!
63//! * ID3v1
64//! * ID3v2
65//! * ISO/MP4
66//! * RIFF
67//! * Vorbis Comment (in OGG & FLAC)
68//!
69//! ## Optimizations
70//!
71//! SIMD optimizations are **not** enabled by default. They may be enabled on a per-instruction
72//! set basis using the following feature flags. Enabling any SIMD support feature flags will pull
73//! in the `rustfft` dependency.
74//!
75//! | Instruction Set | Feature Flag    | Default |
76//! |-----------------|-----------------|---------|
77//! | SSE             | `opt-simd-sse`  | No      |
78//! | AVX             | `opt-simd-avx`  | No      |
79//! | Neon            | `opt-simd-neon` | No      |
80//!
81//! **Tip:** All SIMD optimizations can be enabled with the `opt-simd` feature flag.
82//!
83//! # Usage
84//!
85//! The following steps describe a basic usage of Symphonia:
86//!
87//! 1.  Instantiate a [`CodecRegistry`][core::codecs::CodecRegistry] and register all the codecs
88//!     that are of interest. Alternatively, you may use [`default::get_codecs`] to get the default
89//!     registry with all the enabled codecs pre-registered. The registry will be used to
90//!     instantiate a [`Decoder`][core::codecs::Decoder] later.
91//! 2.  Instantiate a [`Probe`][core::probe::Probe] and register all the formats that are of
92//!     interest. Alternatively, you may use [`default::get_probe`] to get a default format probe
93//!     with all the enabled formats pre-registered. The probe will be used to automatically detect
94//!     the media format and instantiate a compatible [`FormatReader`][core::formats::FormatReader].
95//! 3.  Make sure the [`MediaSource`][core::io::MediaSource] trait is implemented for whatever
96//!     source you are using. This trait is already implemented for `std::fs::File` and
97//!     `std::io::Cursor`.
98//! 4.  Instantiate a [`MediaSourceStream`][core::io::MediaSourceStream] with the `MediaSource`
99//!     above.
100//! 5.  Using the `Probe`, call [`format`][core::probe::Probe::format] and pass it the
101//!    `MediaSourceStream`.
102//! 6.  If the probe successfully detects a compatible format, a `FormatReader` will be returned.
103//!     This is an instance of a demuxer that can read and demux the provided source into
104//!     [`Packet`][core::formats::Packet]s.
105//! 7.  At this point it is possible to interrogate the `FormatReader` for general information about
106//!     the media and metadata. Examine the [`Track`][core::formats::Track] listing using
107//!     [`tracks`][core::formats::FormatReader::tracks] and select one or more tracks of interest to
108//!     decode.
109//! 8.  To instantiate a `Decoder` for a selected `Track`, call the `CodecRegistry`'s
110//!     [`make`][core::codecs::CodecRegistry::make] function and pass it
111//!     the [`CodecParameters`][core::codecs::CodecParameters] for that track. This step is repeated
112//!     once per selected track.
113//! 9.  To decode a track, obtain a packet from the `FormatReader` by
114//!     calling [`next_packet`][`core::formats::FormatReader::next_packet`] and then pass the
115//!     `Packet` to the `Decoder` for that track. The [`decode`][core::codecs::Decoder::decode]
116//!     function will read a packet and return an [`AudioBufferRef`][core::audio::AudioBufferRef]
117//!     (an "any-type" [`AudioBuffer`][core::audio::AudioBuffer]).
118//! 10. The `AudioBufferRef` may be used to access the decoded audio samples directly, or it can be
119//!     copied into a [`SampleBuffer`][core::audio::SampleBuffer] or
120//!     [`RawSampleBuffer`][core::audio::RawSampleBuffer] to export the audio out of Symphonia.
121//! 11. Repeat step 9 and 10 until the end-of-stream error is returned.
122//!
123//! An example implementation of a simple audio player (symphonia-play) can be found in the
124//! Project Symphonia git repository.
125//!
126//! # Gapless Playback
127//!
128//! Gapless playback is disabled by default. To enable gapless playback, set
129//! [`FormatOptions::enable_gapless`][core::formats::FormatOptions::enable_gapless] to `true`.
130//!
131//! # Adding new formats and codecs
132//!
133//! Simply implement the [`Decoder`][core::codecs::Decoder] trait for a decoder or the
134//! [`FormatReader`][core::formats::FormatReader] trait for a demuxer trait and register with
135//! the appropriate registry or probe!
136
137pub mod default {
138    //! The `default` module provides convenience functions and registries to get an implementer
139    //! up-and-running as quickly as possible, and to reduce boiler-plate. Using the `default`
140    //! module is completely optional and incurs no overhead unless actually used.
141
142    pub mod codecs {
143        //! The `codecs` module re-exports all enabled Symphonia decoders.
144
145        #[cfg(feature = "flac")]
146        pub use symphonia_bundle_flac::FlacDecoder;
147        #[cfg(any(feature = "mp1", feature = "mp2", feature = "mp3"))]
148        pub use symphonia_bundle_mp3::MpaDecoder;
149        #[cfg(feature = "aac")]
150        pub use symphonia_codec_aac::AacDecoder;
151        #[cfg(feature = "adpcm")]
152        pub use symphonia_codec_adpcm::AdpcmDecoder;
153        #[cfg(feature = "alac")]
154        pub use symphonia_codec_alac::AlacDecoder;
155        #[cfg(feature = "pcm")]
156        pub use symphonia_codec_pcm::PcmDecoder;
157        #[cfg(feature = "vorbis")]
158        pub use symphonia_codec_vorbis::VorbisDecoder;
159
160        #[deprecated = "use `default::codecs::MpaDecoder` instead"]
161        #[cfg(any(feature = "mp1", feature = "mp2", feature = "mp3"))]
162        pub type Mp3Decoder = MpaDecoder;
163    }
164
165    pub mod formats {
166        //! The `formats` module re-exports all enabled Symphonia format readers.
167
168        #[cfg(feature = "flac")]
169        pub use symphonia_bundle_flac::FlacReader;
170        #[cfg(any(feature = "mp1", feature = "mp2", feature = "mp3"))]
171        pub use symphonia_bundle_mp3::MpaReader;
172        #[cfg(feature = "aac")]
173        pub use symphonia_codec_aac::AdtsReader;
174        #[cfg(feature = "caf")]
175        pub use symphonia_format_caf::CafReader;
176        #[cfg(feature = "isomp4")]
177        pub use symphonia_format_isomp4::IsoMp4Reader;
178        #[cfg(feature = "mkv")]
179        pub use symphonia_format_mkv::MkvReader;
180        #[cfg(feature = "ogg")]
181        pub use symphonia_format_ogg::OggReader;
182        #[cfg(feature = "aiff")]
183        pub use symphonia_format_riff::AiffReader;
184        #[cfg(feature = "wav")]
185        pub use symphonia_format_riff::WavReader;
186
187        #[deprecated = "use `default::formats::MpaReader` instead"]
188        #[cfg(any(feature = "mp1", feature = "mp2", feature = "mp3"))]
189        pub type Mp3Reader = MpaReader;
190    }
191
192    use lazy_static::lazy_static;
193
194    use symphonia_core::codecs::CodecRegistry;
195    use symphonia_core::probe::Probe;
196
197    lazy_static! {
198        static ref CODEC_REGISTRY: CodecRegistry = {
199            let mut registry = CodecRegistry::new();
200            register_enabled_codecs(&mut registry);
201            registry
202        };
203    }
204
205    lazy_static! {
206        static ref PROBE: Probe = {
207            let mut probe: Probe = Default::default();
208            register_enabled_formats(&mut probe);
209            probe
210        };
211    }
212
213    /// Gets the default `CodecRegistry`. This registry pre-registers all the codecs selected by the
214    /// `feature` flags in the includer's `Cargo.toml`. If `features` is not set, the default set of
215    /// Symphonia codecs is registered.
216    ///
217    /// This function is lazy and does not instantiate the `CodecRegistry` until the first call to
218    /// this function.
219    pub fn get_codecs() -> &'static CodecRegistry {
220        &CODEC_REGISTRY
221    }
222
223    /// Gets the default `Probe`. This registry pre-registers all the formats selected by the
224    /// `feature` flags in the includer's `Cargo.toml`. If `features` is not set, the default set of
225    /// Symphonia formats is registered.
226    ///
227    /// This function is lazy and does not instantiate the `Probe` until the first call to this
228    /// function.
229    pub fn get_probe() -> &'static Probe {
230        &PROBE
231    }
232
233    /// Registers all the codecs selected by the `feature` flags in the includer's `Cargo.toml` on
234    /// the provided `CodecRegistry`. If `features` is not set, the default set of Symphonia codecs
235    /// is registered.
236    ///
237    /// Use this function to easily populate a custom registry with all enabled codecs.
238    pub fn register_enabled_codecs(registry: &mut CodecRegistry) {
239        #[cfg(feature = "aac")]
240        registry.register_all::<codecs::AacDecoder>();
241
242        #[cfg(feature = "adpcm")]
243        registry.register_all::<codecs::AdpcmDecoder>();
244
245        #[cfg(feature = "alac")]
246        registry.register_all::<codecs::AlacDecoder>();
247
248        #[cfg(feature = "flac")]
249        registry.register_all::<codecs::FlacDecoder>();
250
251        #[cfg(any(feature = "mp1", feature = "mp2", feature = "mp3"))]
252        registry.register_all::<codecs::MpaDecoder>();
253
254        #[cfg(feature = "pcm")]
255        registry.register_all::<codecs::PcmDecoder>();
256
257        #[cfg(feature = "vorbis")]
258        registry.register_all::<codecs::VorbisDecoder>();
259    }
260
261    /// Registers all the formats selected by the `feature` flags in the includer's `Cargo.toml` on
262    /// the provided `Probe`. If `features` is not set, the default set of Symphonia formats is
263    /// registered.
264    ///
265    /// Use this function to easily populate a custom probe with all enabled formats.
266    pub fn register_enabled_formats(probe: &mut Probe) {
267        use symphonia_metadata::id3v2::Id3v2Reader;
268
269        // Formats
270        #[cfg(feature = "aac")]
271        probe.register_all::<formats::AdtsReader>();
272
273        #[cfg(feature = "caf")]
274        probe.register_all::<formats::CafReader>();
275
276        #[cfg(feature = "flac")]
277        probe.register_all::<formats::FlacReader>();
278
279        #[cfg(feature = "isomp4")]
280        probe.register_all::<formats::IsoMp4Reader>();
281
282        #[cfg(any(feature = "mp1", feature = "mp2", feature = "mp3"))]
283        probe.register_all::<formats::MpaReader>();
284
285        #[cfg(feature = "aiff")]
286        probe.register_all::<formats::AiffReader>();
287
288        #[cfg(feature = "wav")]
289        probe.register_all::<formats::WavReader>();
290
291        #[cfg(feature = "ogg")]
292        probe.register_all::<formats::OggReader>();
293
294        #[cfg(feature = "mkv")]
295        probe.register_all::<formats::MkvReader>();
296
297        // Metadata
298        probe.register_all::<Id3v2Reader>();
299    }
300}
301
302pub use symphonia_core as core;