1mod audio;
5mod decode;
6mod encode;
7mod io;
8mod parse;
9mod remux;
10mod result;
11mod scaler;
12mod types;
13
14pub(crate) use audio::decoder_channel_layout;
15pub use audio::{transcode_audio_buffer, AudioSpec, AutoAudioBuffer, Resampler};
16pub use decode::{Decoder, Frame, FrameProcess};
17pub use encode::{EncodeParams, Encoder};
18pub use io::{
19 input_buffer, input_buffer_with_format, input_buffer_with_format_options, input_file,
20 input_reader, output_buffer, output_file, output_writer, read_attachment,
21};
22pub use parse::{parse_stream_info, parse_video_group};
23pub use remux::{remux, RemuxRequest, RemuxStream};
24pub use result::{FFmpegError, FFmpegResult};
25pub use scaler::{Scaler, ScalingAlgorithm};
26pub use types::{
27 AudioFrame, ChannelLayout, CodecId, FrameCalculation, FrameSize, Input, MediaType, Output,
28 Rational, Sample, SampleType, Stream, StreamDecoder, StreamEncoder, StreamFormat, StreamFrame,
29 VideoFrame, VideoGroups, VideoInfo, VideoPixel,
30};
31
32use ffmpeg_next::{
33 ffi::{AV_LOG_ERROR, AV_LOG_INFO, AV_LOG_TRACE, AV_LOG_WARNING},
34 sys::{av_log_set_level, AV_LOG_DEBUG},
35};
36use log::{debug, error};
37use std::{path::Path, time::Instant};
38
39pub fn initialize(level: log::Level) -> Result<(), ffmpeg_next::Error> {
40 let level = match level {
41 log::Level::Error => AV_LOG_ERROR,
42 log::Level::Warn => AV_LOG_WARNING,
43 log::Level::Info => AV_LOG_INFO,
44 log::Level::Debug => AV_LOG_DEBUG,
45 log::Level::Trace => AV_LOG_TRACE,
46 };
47 unsafe { av_log_set_level(level) }
48 ffmpeg_next::init()
49}
50
51#[cfg(test)]
52mod tests {
53 use super::*;
54 use ffmpeg_next::codec::Id;
55 use rav1e::prelude::{ChromaSampling, Config, Context, EncoderConfig, EncoderStatus};
56 use std::io::Cursor;
57
58 pub(crate) fn encoded_ogg() -> Vec<u8> {
59 let mut output = output_buffer("ogg").unwrap();
60 {
61 let mut encoder = Encoder::new(
62 output.as_mut(),
63 Id::OPUS,
64 EncodeParams::default()
65 .with_bitrate(64 * 1024)
66 .with_vbr(true),
67 )
68 .unwrap();
69 encoder.write_header().unwrap();
70 let (format, samples, layout, rate) = match encoder.get_encoder() {
71 StreamEncoder::Audio(encoder) => (
72 encoder.format(),
73 encoder.frame_size() as usize,
74 encoder.channel_layout(),
75 encoder.rate(),
76 ),
77 StreamEncoder::Video(_) => panic!("unexpected video encoder"),
78 };
79 for index in 0..4 {
80 let mut frame = AudioFrame::new(format, samples, layout);
81 frame.set_rate(rate);
82 frame.set_pts(Some((index * samples) as i64));
83 for plane in 0..frame.planes() {
84 frame.data_mut(plane).fill(0);
85 }
86 encoder.send_frame(&StreamFrame::Audio(frame)).unwrap();
87 encoder.encode_frame().unwrap();
88 }
89 encoder.send_frame(&StreamFrame::Eof).unwrap();
90 encoder.encode_frame().unwrap();
91 }
92 output.into_inner::<Cursor<Vec<u8>>>().unwrap().into_inner()
93 }
94
95 pub(crate) fn encoded_ivf(frame_count: usize) -> Vec<u8> {
96 let mut encoder = EncoderConfig::with_speed_preset(10);
97 encoder.width = 16;
98 encoder.height = 16;
99 encoder.chroma_sampling = ChromaSampling::Cs420;
100 encoder.low_latency = false;
101 encoder.min_key_frame_interval = 4;
102 encoder.max_key_frame_interval = 4;
103 let config = Config::new().with_encoder_config(encoder).with_threads(1);
104 let mut context: Context<u8> = config.new_context().unwrap();
105 for index in 0..frame_count {
106 let mut frame = context.new_frame();
107 frame.planes[0].data_origin_mut().fill((index * 16) as u8);
108 frame.planes[1].data_origin_mut().fill(128);
109 frame.planes[2].data_origin_mut().fill(128);
110 context.send_frame(frame).unwrap();
111 }
112 context.flush();
113 let mut packets = Vec::new();
114 loop {
115 match context.receive_packet() {
116 Ok(packet) => packets.push((packet.input_frameno, packet.data)),
117 Err(EncoderStatus::Encoded | EncoderStatus::NeedMoreData) => continue,
118 Err(EncoderStatus::LimitReached) => break,
119 Err(error) => panic!("rav1e fixture failed: {error}"),
120 }
121 }
122
123 let mut ivf = Vec::new();
124 ivf.extend_from_slice(b"DKIF");
125 ivf.extend_from_slice(&0_u16.to_le_bytes());
126 ivf.extend_from_slice(&32_u16.to_le_bytes());
127 ivf.extend_from_slice(b"AV01");
128 ivf.extend_from_slice(&16_u16.to_le_bytes());
129 ivf.extend_from_slice(&16_u16.to_le_bytes());
130 ivf.extend_from_slice(&30_u32.to_le_bytes());
131 ivf.extend_from_slice(&1_u32.to_le_bytes());
132 ivf.extend_from_slice(&(packets.len() as u32).to_le_bytes());
133 ivf.extend_from_slice(&0_u32.to_le_bytes());
134 for (timestamp, packet) in packets {
135 ivf.extend_from_slice(&(packet.len() as u32).to_le_bytes());
136 ivf.extend_from_slice(×tamp.to_le_bytes());
137 ivf.extend_from_slice(&packet);
138 }
139 ivf
140 }
141}