Fix filter::filter::PadIter to actually iterate

Bug caught by clippy:

  error: offset calculation on zero-sized value
    --> src/filter/filter.rs:98:33
     |
  98 |             let pad = Pad::wrap(self.ptr.offset(self.cur));
     |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^
     |
     = note: `#[deny(clippy::zst_offset)]` on by default
     = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#zst_offset

The problem is that `AVFilterPad` is zero-sized:

  #[repr(C)]
  #[derive(Debug, Copy, Clone)]
  pub struct AVFilterPad {
      _unused: [u8; 0],
  }

which is in turn due to `AVFilterPad` being an opaque type in
`libavfilter/avfilter.h`:

  typedef struct AVFilterContext AVFilterContext;
  typedef struct AVFilterLink    AVFilterLink;
  typedef struct AVFilterPad     AVFilterPad;
  typedef struct AVFilterFormats AVFilterFormats;

Doing pointer arithmetic on an opaque (incomplete) type doesn't work. We have
to use the proper FFI calls to obtain info on individual pads. The API has to
be tweaked a bit; hopefully it doesn't break user programs (if it does it
should only break bugged ones...).

Fixes #20.
This commit is contained in:
Zhiming Wang 2020-07-25 23:34:27 +08:00
parent ec7fed0333
commit 6639f02b80
No known key found for this signature in database
GPG Key ID: 5B58F95EC95965D8
3 changed files with 24 additions and 4 deletions

View File

@ -95,7 +95,7 @@ impl<'a> Iterator for PadIter<'a> {
return None;
}
let pad = Pad::wrap(self.ptr.offset(self.cur));
let pad = Pad::wrap(self.ptr, self.cur);
self.cur += 1;
Some(pad)

View File

@ -58,3 +58,21 @@ pub fn find(name: &str) -> Option<Filter> {
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_paditer() {
assert_eq!(
find("overlay")
.unwrap()
.inputs()
.unwrap()
.map(|input| input.name().unwrap().to_string())
.collect::<Vec<_>>(),
vec!("main", "overlay")
);
}
}

View File

@ -7,14 +7,16 @@ use media;
pub struct Pad<'a> {
ptr: *const AVFilterPad,
idx: isize,
_marker: PhantomData<&'a ()>,
}
impl<'a> Pad<'a> {
pub unsafe fn wrap(ptr: *const AVFilterPad) -> Self {
pub unsafe fn wrap(ptr: *const AVFilterPad, idx: isize) -> Self {
Pad {
ptr: ptr,
idx: idx,
_marker: PhantomData,
}
}
@ -31,7 +33,7 @@ impl<'a> Pad<'a> {
impl<'a> Pad<'a> {
pub fn name(&self) -> Option<&str> {
unsafe {
let ptr = avfilter_pad_get_name(self.ptr, 0);
let ptr = avfilter_pad_get_name(self.ptr, self.idx as i32);
if ptr.is_null() {
None
@ -42,6 +44,6 @@ impl<'a> Pad<'a> {
}
pub fn medium(&self) -> media::Type {
unsafe { media::Type::from(avfilter_pad_get_type(self.ptr, 0)) }
unsafe { media::Type::from(avfilter_pad_get_type(self.ptr, self.idx as i32)) }
}
}