1use 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
28pub struct BitstreamFilterBuilder {
30 ptr: *mut c_void,
31
32 input_time_base: TimeBase,
33 output_time_base: TimeBase,
34}
35
36impl BitstreamFilterBuilder {
37 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 #[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 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 #[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 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 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
139pub struct BitstreamFilter {
148 ptr: *mut c_void,
149 output_time_base: TimeBase,
150}
151
152impl BitstreamFilter {
153 pub fn builder(name: &str) -> Result<BitstreamFilterBuilder, Error> {
166 BitstreamFilterBuilder::new(name)
167 }
168
169 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 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 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 {}