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