Skip to main content

wedeo_codec/
encoder.rs

1use bitflags::bitflags;
2
3use wedeo_core::channel_layout::ChannelLayout;
4use wedeo_core::codec_id::CodecId;
5use wedeo_core::error::Result;
6use wedeo_core::frame::Frame;
7use wedeo_core::media_type::MediaType;
8use wedeo_core::packet::Packet;
9use wedeo_core::pixel_format::PixelFormat;
10use wedeo_core::rational::Rational;
11use wedeo_core::sample_format::SampleFormat;
12
13use crate::descriptor::{CodecCapabilities, CodecProperties};
14use crate::options::CodecOptions;
15
16bitflags! {
17    /// Codec flags, matching FFmpeg's AV_CODEC_FLAG_*.
18    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
19    pub struct CodecFlags: u32 {
20        const UNALIGNED       = 1 << 0;
21        const QSCALE          = 1 << 1;
22        const OUTPUT_CORRUPT  = 1 << 3;
23        const QPEL            = 1 << 4;
24        const DROPCHANGED     = 1 << 5;
25        const RECON_FRAME     = 1 << 6;
26        const COPY_OPAQUE     = 1 << 7;
27        const FRAME_DURATION  = 1 << 8;
28        const PASS1           = 1 << 9;
29        const PASS2           = 1 << 10;
30        const LOOP_FILTER     = 1 << 11;
31        const GRAY            = 1 << 13;
32        const PSNR            = 1 << 15;
33        const INTERLACED_DCT  = 1 << 18;
34        const LOW_DELAY       = 1 << 19;
35        const GLOBAL_HEADER   = 1 << 22;
36        const BITEXACT        = 1 << 23;
37        const AC_PRED         = 1 << 24;
38        const INTERLACED_ME   = 1 << 29;
39        const CLOSED_GOP      = 1 << 31;
40    }
41}
42
43/// Encoder trait — the main abstraction for all encoders.
44///
45/// Follows FFmpeg's send/receive model:
46/// 1. `send_frame()` — feed raw data
47/// 2. `receive_packet()` — pull compressed data
48/// 3. `flush()` — signal end-of-stream
49pub trait Encoder: Send {
50    /// Send a raw frame to the encoder.
51    /// Pass `None` to signal end-of-stream (drain mode).
52    fn send_frame(&mut self, frame: Option<&Frame>) -> Result<()>;
53
54    /// Receive an encoded packet from the encoder.
55    /// Returns `Error::Again` when more input is needed.
56    /// Returns `Error::Eof` when all data has been drained.
57    fn receive_packet(&mut self) -> Result<Packet>;
58
59    /// Flush the encoder (reset internal state).
60    fn flush(&mut self);
61}
62
63/// Builder for creating encoders.
64pub struct EncoderBuilder {
65    pub codec_id: CodecId,
66    pub media_type: MediaType,
67    pub bit_rate: i64,
68    pub flags: CodecFlags,
69    pub time_base: Rational,
70
71    // Audio
72    pub sample_rate: u32,
73    pub sample_format: SampleFormat,
74    pub channel_layout: ChannelLayout,
75
76    // Video
77    pub width: u32,
78    pub height: u32,
79    pub pixel_format: PixelFormat,
80
81    /// Codec-private options (string key-value pairs).
82    pub options: CodecOptions,
83}
84
85impl EncoderBuilder {
86    pub fn new(codec_id: CodecId, media_type: MediaType) -> Self {
87        Self {
88            codec_id,
89            media_type,
90            bit_rate: 0,
91            flags: CodecFlags::empty(),
92            time_base: Rational::new(1, 1),
93            sample_rate: 0,
94            sample_format: SampleFormat::None,
95            channel_layout: ChannelLayout::unspec(0),
96            width: 0,
97            height: 0,
98            pixel_format: PixelFormat::None,
99            options: CodecOptions::new(),
100        }
101    }
102
103    /// Set a codec-private option (string key-value pair).
104    pub fn option(mut self, key: &str, value: &str) -> Self {
105        self.options.set(key, value);
106        self
107    }
108
109    pub fn open(self) -> Result<Box<dyn Encoder>> {
110        crate::registry::find_encoder(self.codec_id)
111            .ok_or(wedeo_core::Error::EncoderNotFound)?
112            .create(self)
113    }
114}
115
116/// Descriptor for an encoder implementation, used in the registry.
117#[derive(Debug, Clone)]
118pub struct EncoderDescriptor {
119    pub codec_id: CodecId,
120    pub name: &'static str,
121    pub long_name: &'static str,
122    pub media_type: MediaType,
123    pub capabilities: CodecCapabilities,
124    pub properties: CodecProperties,
125    pub supported_sample_formats: &'static [SampleFormat],
126    pub supported_pixel_formats: &'static [PixelFormat],
127    /// Priority for registry selection. Higher priority wins when multiple
128    /// encoders support the same codec_id. Native implementations use 100,
129    /// wrapper/adapter implementations use 50.
130    pub priority: i32,
131}