playa_ffmpeg/codec/encoder/
encoder.rs

1use std::{
2    ops::{Deref, DerefMut},
3    ptr,
4};
5
6use crate::ffi::*;
7use libc::c_int;
8
9use super::{audio, subtitle, video};
10use crate::{Error, Frame, codec::Context, media, packet};
11
12/// An encoder for compressing raw media frames.
13///
14/// `Encoder` wraps an FFmpeg codec context configured for encoding. It provides methods
15/// to configure encoding parameters and convert it to type-specific encoders (video, audio,
16/// or subtitle).
17///
18/// # Lifecycle
19///
20/// 1. Create an `Encoder` from a codec
21/// 2. Configure encoding parameters (bitrate, quality, etc.)
22/// 3. Convert to type-specific encoder with [`video()`](Encoder::video), [`audio()`](Encoder::audio), or [`subtitle()`](Encoder::subtitle)
23/// 4. Send raw frames with [`send_frame()`](Encoder::send_frame) and receive encoded packets
24///
25/// # Example
26///
27/// ```ignore
28/// // Create encoder for H.264
29/// let codec = encoder::find(Id::H264).unwrap();
30/// let mut encoder = codec.encoder().unwrap();
31///
32/// // Configure as video encoder
33/// let mut video = encoder.video()?;
34/// video.set_width(1920);
35/// video.set_height(1080);
36/// video.set_format(Pixel::YUV420P);
37/// video.set_bit_rate(4_000_000);
38///
39/// // Encode frames
40/// video.send_frame(&frame)?;
41/// video.receive_packet(&mut packet)?;
42/// ```
43pub struct Encoder(pub Context);
44
45impl Encoder {
46    /// Converts this encoder to a video encoder.
47    ///
48    /// If the context media type is Unknown, it will be set to Video.
49    ///
50    /// # Errors
51    ///
52    /// Returns `Error::InvalidData` if the context is already configured for a
53    /// non-video media type.
54    pub fn video(mut self) -> Result<video::Video, Error> {
55        match self.medium() {
56            media::Type::Unknown => {
57                unsafe {
58                    // Set codec type to video
59                    (*self.as_mut_ptr()).codec_type = media::Type::Video.into();
60                }
61
62                Ok(video::Video(self))
63            }
64
65            media::Type::Video => Ok(video::Video(self)),
66
67            _ => Err(Error::InvalidData),
68        }
69    }
70
71    /// Converts this encoder to an audio encoder.
72    ///
73    /// If the context media type is Unknown, it will be set to Audio.
74    ///
75    /// # Errors
76    ///
77    /// Returns `Error::InvalidData` if the context is already configured for a
78    /// non-audio media type.
79    pub fn audio(mut self) -> Result<audio::Audio, Error> {
80        match self.medium() {
81            media::Type::Unknown => {
82                unsafe {
83                    // Set codec type to audio
84                    (*self.as_mut_ptr()).codec_type = media::Type::Audio.into();
85                }
86
87                Ok(audio::Audio(self))
88            }
89
90            media::Type::Audio => Ok(audio::Audio(self)),
91
92            _ => Err(Error::InvalidData),
93        }
94    }
95
96    /// Converts this encoder to a subtitle encoder.
97    ///
98    /// If the context media type is Unknown, it will be set to Subtitle.
99    ///
100    /// # Errors
101    ///
102    /// Returns `Error::InvalidData` if the context is already configured for a
103    /// non-subtitle media type.
104    pub fn subtitle(mut self) -> Result<subtitle::Subtitle, Error> {
105        match self.medium() {
106            media::Type::Unknown => {
107                unsafe {
108                    // Set codec type to subtitle
109                    (*self.as_mut_ptr()).codec_type = media::Type::Subtitle.into();
110                }
111
112                Ok(subtitle::Subtitle(self))
113            }
114
115            media::Type::Subtitle => Ok(subtitle::Subtitle(self)),
116
117            _ => Err(Error::InvalidData),
118        }
119    }
120
121    /// Sends a raw frame to the encoder.
122    ///
123    /// The encoder will buffer and encode the frame according to its configuration.
124    /// Call [`receive_packet()`](Encoder::receive_packet) to retrieve encoded packets.
125    ///
126    /// # Errors
127    ///
128    /// - `Error::Other(EAGAIN)` - The encoder needs more frames before producing output
129    /// - `Error::Eof` - The encoder has been flushed and won't accept more frames
130    /// - Other errors indicate encoding failure
131    pub fn send_frame(&mut self, frame: &Frame) -> Result<(), Error> {
132        unsafe {
133            match avcodec_send_frame(self.as_mut_ptr(), frame.as_ptr()) {
134                e if e < 0 => Err(Error::from(e)),
135                _ => Ok(()),
136            }
137        }
138    }
139
140    /// Signals end-of-stream and enters draining mode.
141    ///
142    /// After calling this, continue calling [`receive_packet()`](Encoder::receive_packet)
143    /// until it returns `Error::Eof` to retrieve all buffered encoded packets.
144    ///
145    /// # Errors
146    ///
147    /// Returns an error if the encoder is in an invalid state.
148    pub fn send_eof(&mut self) -> Result<(), Error> {
149        unsafe {
150            // Send null frame to signal EOF
151            self.send_frame(&Frame::wrap(ptr::null_mut()))
152        }
153    }
154
155    /// Receives an encoded packet from the encoder.
156    ///
157    /// Call this repeatedly after [`send_frame()`](Encoder::send_frame) to retrieve
158    /// all available encoded packets.
159    ///
160    /// # Errors
161    ///
162    /// - `Error::Other(EAGAIN)` - Need to send more frames before output is available
163    /// - `Error::Eof` - No more packets (encoder has been drained)
164    /// - Other errors indicate encoding failure
165    pub fn receive_packet<P: packet::Mut>(&mut self, packet: &mut P) -> Result<(), Error> {
166        unsafe {
167            match avcodec_receive_packet(self.as_mut_ptr(), packet.as_mut_ptr()) {
168                e if e < 0 => Err(Error::from(e)),
169                _ => Ok(()),
170            }
171        }
172    }
173
174    /// Sets the target bitrate in bits per second.
175    ///
176    /// This is the average bitrate the encoder will try to achieve. Used for
177    /// CBR (constant bitrate) or ABR (average bitrate) encoding.
178    pub fn set_bit_rate(&mut self, value: usize) {
179        unsafe {
180            (*self.as_mut_ptr()).bit_rate = value as i64;
181        }
182    }
183
184    /// Sets the maximum bitrate in bits per second for VBR encoding.
185    ///
186    /// Combined with bitrate, this defines the bitrate range for variable bitrate encoding.
187    /// The encoder will never exceed this bitrate.
188    pub fn set_max_bit_rate(&mut self, value: usize) {
189        unsafe {
190            (*self.as_mut_ptr()).rc_max_rate = value as i64;
191        }
192    }
193
194    /// Sets the bitrate tolerance for rate control.
195    ///
196    /// Defines how much the bitrate can deviate from the target. Higher values
197    /// allow more variation (better quality in complex scenes) but less consistent bitrate.
198    pub fn set_tolerance(&mut self, value: usize) {
199        unsafe {
200            (*self.as_mut_ptr()).bit_rate_tolerance = value as c_int;
201        }
202    }
203
204    /// Sets the global quality/quantizer for quality-based encoding.
205    ///
206    /// Interpretation is codec-specific. For example:
207    /// - MPEG-2/4: Use 1 (best) to 31 (worst)
208    /// - H.264: Use with CRF mode
209    ///
210    /// Lower values = higher quality = larger file size.
211    pub fn set_quality(&mut self, value: usize) {
212        unsafe {
213            (*self.as_mut_ptr()).global_quality = value as c_int;
214        }
215    }
216
217    /// Sets the compression level.
218    ///
219    /// Codec-specific parameter controlling the speed/compression tradeoff.
220    /// Higher values = slower encoding but better compression.
221    ///
222    /// Pass `None` to use the codec's default (-1).
223    pub fn set_compression(&mut self, value: Option<usize>) {
224        unsafe {
225            if let Some(value) = value {
226                (*self.as_mut_ptr()).compression_level = value as c_int;
227            } else {
228                // -1 means use codec default
229                (*self.as_mut_ptr()).compression_level = -1;
230            }
231        }
232    }
233}
234
235impl Deref for Encoder {
236    type Target = Context;
237
238    fn deref(&self) -> &<Self as Deref>::Target {
239        &self.0
240    }
241}
242
243impl DerefMut for Encoder {
244    fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {
245        &mut self.0
246    }
247}
248
249impl AsRef<Context> for Encoder {
250    fn as_ref(&self) -> &Context {
251        self
252    }
253}
254
255impl AsMut<Context> for Encoder {
256    fn as_mut(&mut self) -> &mut Context {
257        &mut *self
258    }
259}