1#![warn(missing_docs)]
48#![warn(clippy::all)]
49#![warn(clippy::pedantic)]
50
51pub mod channel;
53pub mod codec;
54pub mod color;
55pub mod error;
56pub mod frame;
57pub mod media;
58pub mod pixel;
59pub mod sample;
60pub mod stream;
61pub mod time;
62
63pub use channel::ChannelLayout;
64pub use codec::{AudioCodec, VideoCodec};
65pub use color::{ColorPrimaries, ColorRange, ColorSpace};
66pub use error::{FormatError, FrameError};
67pub use ff_common::PooledBuffer;
68pub use frame::{AudioFrame, VideoFrame};
69pub use media::{MediaInfo, MediaInfoBuilder};
70pub use pixel::PixelFormat;
71pub use sample::SampleFormat;
72pub use stream::{
73 AudioStreamInfo, AudioStreamInfoBuilder, VideoStreamInfo, VideoStreamInfoBuilder,
74};
75pub use time::{Rational, Timestamp};
76
77pub mod prelude {
85 pub use crate::{
86 AudioCodec, AudioFrame, AudioStreamInfo, ChannelLayout, ColorPrimaries, ColorRange,
87 ColorSpace, FormatError, FrameError, MediaInfo, PixelFormat, PooledBuffer, Rational,
88 SampleFormat, Timestamp, VideoCodec, VideoFrame, VideoStreamInfo,
89 };
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95
96 #[test]
97 fn test_prelude_exports() {
98 let _pixel: PixelFormat = PixelFormat::default();
100 let _sample: SampleFormat = SampleFormat::default();
101 let _rational: Rational = Rational::default();
102 let _timestamp: Timestamp = Timestamp::default();
103 let _video_frame: VideoFrame = VideoFrame::default();
104 let _audio_frame: AudioFrame = AudioFrame::default();
105
106 let _color_space: ColorSpace = ColorSpace::default();
108 let _color_range: ColorRange = ColorRange::default();
109 let _color_primaries: ColorPrimaries = ColorPrimaries::default();
110 let _video_codec: VideoCodec = VideoCodec::default();
111 let _audio_codec: AudioCodec = AudioCodec::default();
112 let _channel_layout: ChannelLayout = ChannelLayout::default();
113 let _video_stream: VideoStreamInfo = VideoStreamInfo::default();
114 let _audio_stream: AudioStreamInfo = AudioStreamInfo::default();
115 let _media_info: MediaInfo = MediaInfo::default();
116 }
117
118 #[test]
119 fn test_stream_info_builder() {
120 let video = VideoStreamInfo::builder()
122 .index(0)
123 .codec(VideoCodec::H264)
124 .width(1920)
125 .height(1080)
126 .frame_rate(Rational::new(30, 1))
127 .pixel_format(PixelFormat::Yuv420p)
128 .color_space(ColorSpace::Bt709)
129 .build();
130
131 assert_eq!(video.width(), 1920);
132 assert_eq!(video.height(), 1080);
133 assert_eq!(video.codec(), VideoCodec::H264);
134 assert_eq!(video.color_space(), ColorSpace::Bt709);
135
136 let audio = AudioStreamInfo::builder()
138 .index(1)
139 .codec(AudioCodec::Aac)
140 .sample_rate(48000)
141 .channels(2)
142 .sample_format(SampleFormat::F32)
143 .build();
144
145 assert_eq!(audio.sample_rate(), 48000);
146 assert_eq!(audio.channels(), 2);
147 assert_eq!(audio.codec(), AudioCodec::Aac);
148 assert_eq!(audio.channel_layout(), ChannelLayout::Stereo);
149 }
150
151 #[test]
152 fn test_media_info_builder() {
153 use std::time::Duration;
154
155 let video = VideoStreamInfo::builder()
157 .index(0)
158 .codec(VideoCodec::H264)
159 .width(1920)
160 .height(1080)
161 .frame_rate(Rational::new(30, 1))
162 .build();
163
164 let audio = AudioStreamInfo::builder()
165 .index(1)
166 .codec(AudioCodec::Aac)
167 .sample_rate(48000)
168 .channels(2)
169 .build();
170
171 let media = MediaInfo::builder()
173 .path("/path/to/video.mp4")
174 .format("mp4")
175 .format_long_name("QuickTime / MOV")
176 .duration(Duration::from_secs(120))
177 .file_size(100_000_000)
178 .bitrate(8_000_000)
179 .video_stream(video)
180 .audio_stream(audio)
181 .metadata("title", "Test Video")
182 .build();
183
184 assert!(media.has_video());
185 assert!(media.has_audio());
186 assert_eq!(media.resolution(), Some((1920, 1080)));
187 assert!((media.frame_rate().unwrap() - 30.0).abs() < 0.001);
188 assert_eq!(media.sample_rate(), Some(48000));
189 assert_eq!(media.channels(), Some(2));
190 assert_eq!(media.format(), "mp4");
191 assert_eq!(media.format_long_name(), Some("QuickTime / MOV"));
192 assert_eq!(media.metadata_value("title"), Some("Test Video"));
193 }
194}