ac_ffmpeg/codec/
bsf.rs

1//! Bitstream filter.
2
3use std::{
4    ffi::CString,
5    os::raw::{c_char, c_int, c_void},
6    ptr,
7};
8
9use crate::{codec::CodecParameters, packet::Packet, time::TimeBase, Error};
10
11extern "C" {
12    fn ffw_bsf_new(name: *const c_char, context: *mut *mut c_void) -> c_int;
13    fn ffw_bsf_set_input_codec_parameters(context: *mut c_void, params: *const c_void) -> c_int;
14    fn ffw_bsf_set_output_codec_parameters(context: *mut c_void, params: *const c_void) -> c_int;
15    fn ffw_bsf_init(
16        context: *mut c_void,
17        itb_num: c_int,
18        itb_den: c_int,
19        otb_num: c_int,
20        otb_den: c_int,
21    ) -> c_int;
22    fn ffw_bsf_push(context: *mut c_void, packet: *mut c_void) -> c_int;
23    fn ffw_bsf_flush(context: *mut c_void) -> c_int;
24    fn ffw_bsf_take(context: *mut c_void, packet: *mut *mut c_void) -> c_int;
25    fn ffw_bsf_free(context: *mut c_void);
26}
27
28/// A builder for bitstream filters.
29pub struct BitstreamFilterBuilder {
30    ptr: *mut c_void,
31
32    input_time_base: TimeBase,
33    output_time_base: TimeBase,
34}
35
36impl BitstreamFilterBuilder {
37    /// Create a new bitstream filter builder for a given filter.
38    fn new(name: &str) -> Result<Self, Error> {
39        let name = CString::new(name).expect("invalid bitstream filter name");
40
41        let mut ptr = ptr::null_mut();
42
43        let ret = unsafe { ffw_bsf_new(name.as_ptr() as _, &mut ptr) };
44
45        if ret < 0 {
46            return Err(Error::from_raw_error_code(ret));
47        } else if ptr.is_null() {
48            panic!("unable to allocate a bitstream filter");
49        }
50
51        let res = BitstreamFilterBuilder {
52            ptr,
53
54            input_time_base: TimeBase::MICROSECONDS,
55            output_time_base: TimeBase::MICROSECONDS,
56        };
57
58        Ok(res)
59    }
60
61    /// Set input time base. By default it's in microseconds. All input packets
62    /// will be rescaled to this time base before passing them to the filter.
63    #[inline]
64    pub fn input_time_base(mut self, time_base: TimeBase) -> Self {
65        self.input_time_base = time_base;
66        self
67    }
68
69    /// Set input codec parameters.
70    pub fn input_codec_parameters(self, codec_parameters: &CodecParameters) -> Self {
71        let ret =
72            unsafe { ffw_bsf_set_input_codec_parameters(self.ptr, codec_parameters.as_ptr()) };
73
74        if ret < 0 {
75            panic!("unable to set input codec parameters");
76        }
77
78        self
79    }
80
81    /// Set output time base. By default it's in microseconds. All output
82    /// packets will use this time base.
83    #[inline]
84    pub fn output_time_base(mut self, time_base: TimeBase) -> Self {
85        self.output_time_base = time_base;
86        self
87    }
88
89    /// Set output codec parameters.
90    pub fn output_codec_parameters(self, codec_parameters: &CodecParameters) -> Self {
91        let ret =
92            unsafe { ffw_bsf_set_output_codec_parameters(self.ptr, codec_parameters.as_ptr()) };
93
94        if ret < 0 {
95            panic!("unable to set output codec parameters");
96        }
97
98        self
99    }
100
101    /// Build the bitstream filter.
102    pub fn build(mut self) -> Result<BitstreamFilter, Error> {
103        let ret = unsafe {
104            ffw_bsf_init(
105                self.ptr,
106                self.input_time_base.num() as _,
107                self.input_time_base.den() as _,
108                self.output_time_base.num() as _,
109                self.output_time_base.den() as _,
110            )
111        };
112
113        if ret < 0 {
114            return Err(Error::from_raw_error_code(ret));
115        }
116
117        let ptr = self.ptr;
118
119        self.ptr = ptr::null_mut();
120
121        let res = BitstreamFilter {
122            ptr,
123            output_time_base: self.output_time_base,
124        };
125
126        Ok(res)
127    }
128}
129
130impl Drop for BitstreamFilterBuilder {
131    fn drop(&mut self) {
132        unsafe { ffw_bsf_free(self.ptr) }
133    }
134}
135
136unsafe impl Send for BitstreamFilterBuilder {}
137unsafe impl Sync for BitstreamFilterBuilder {}
138
139/// A bitstream filter.
140///
141/// # Filter operation
142/// 1. Push a packet to the filter.
143/// 2. Take all packets from the filter until you get None.
144/// 3. If there are more packets to be processed, continue with 1.
145/// 4. Flush the filter.
146/// 5. Take all packets from the filter until you get None.
147pub struct BitstreamFilter {
148    ptr: *mut c_void,
149    output_time_base: TimeBase,
150}
151
152impl BitstreamFilter {
153    /// Get a builder for a given bitstream filter.
154    ///
155    /// # Example
156    /// ```text
157    /// ...
158    ///
159    /// let filter = BitstreamFilter::builder("aac_adtstoasc")?
160    ///     .input_codec_parameters(&params)
161    ///     .build()?;
162    ///
163    /// ...
164    /// ```
165    pub fn builder(name: &str) -> Result<BitstreamFilterBuilder, Error> {
166        BitstreamFilterBuilder::new(name)
167    }
168
169    /// Push a given packet to the filter.
170    pub fn push(&mut self, mut packet: Packet) -> Result<(), Error> {
171        let ret = unsafe { ffw_bsf_push(self.ptr, packet.as_mut_ptr()) };
172
173        if ret < 0 {
174            return Err(Error::from_raw_error_code(ret));
175        }
176
177        Ok(())
178    }
179
180    /// Flush the filter.
181    pub fn flush(&mut self) -> Result<(), Error> {
182        let ret = unsafe { ffw_bsf_flush(self.ptr) };
183
184        if ret < 0 {
185            return Err(Error::from_raw_error_code(ret));
186        }
187
188        Ok(())
189    }
190
191    /// Take the next packet from the bitstream filter.
192    pub fn take(&mut self) -> Result<Option<Packet>, Error> {
193        let mut pptr = ptr::null_mut();
194
195        unsafe {
196            let ret = ffw_bsf_take(self.ptr, &mut pptr);
197
198            if ret == crate::ffw_error_again || ret == crate::ffw_error_eof {
199                Ok(None)
200            } else if ret < 0 {
201                Err(Error::from_raw_error_code(ret))
202            } else if pptr.is_null() {
203                panic!("unable to allocate a packet");
204            } else {
205                Ok(Some(Packet::from_raw_ptr(pptr, self.output_time_base)))
206            }
207        }
208    }
209}
210
211impl Drop for BitstreamFilter {
212    fn drop(&mut self) {
213        unsafe { ffw_bsf_free(self.ptr) }
214    }
215}
216
217unsafe impl Send for BitstreamFilter {}
218unsafe impl Sync for BitstreamFilter {}