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}