use std::ptr::NonNull;
use ffmpeg_next::ffi;
pub(crate) struct AvBufferRef(NonNull<ffi::AVBufferRef>);
impl AvBufferRef {
pub(crate) unsafe fn from_raw(ptr: *mut ffi::AVBufferRef) -> Option<Self> {
NonNull::new(ptr).map(Self)
}
pub(crate) fn as_ptr(&self) -> *mut ffi::AVBufferRef {
self.0.as_ptr()
}
pub(crate) fn try_clone(&self) -> Option<Self> {
unsafe { Self::from_raw(ffi::av_buffer_ref(self.as_ptr())) }
}
pub(crate) fn into_raw(self) -> *mut ffi::AVBufferRef {
let ptr = self.as_ptr();
std::mem::forget(self);
ptr
}
}
unsafe impl Send for AvBufferRef {}
unsafe impl Sync for AvBufferRef {}
impl Drop for AvBufferRef {
fn drop(&mut self) {
let mut ptr = self.as_ptr();
unsafe { ffi::av_buffer_unref(&mut ptr) };
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn buffer_ref_clone_and_drop_balance_references() {
unsafe {
let owner = AvBufferRef::from_raw(ffi::av_buffer_alloc(1)).unwrap();
assert_eq!(ffi::av_buffer_get_ref_count(owner.as_ptr()), 1);
let clone = owner.try_clone().unwrap();
assert_eq!(ffi::av_buffer_get_ref_count(owner.as_ptr()), 2);
drop(clone);
assert_eq!(ffi::av_buffer_get_ref_count(owner.as_ptr()), 1);
}
}
#[test]
fn into_raw_transfers_the_owned_reference() {
unsafe {
let owner = AvBufferRef::from_raw(ffi::av_buffer_alloc(1)).unwrap();
let mut raw = owner.into_raw();
assert_eq!(ffi::av_buffer_get_ref_count(raw), 1);
ffi::av_buffer_unref(&mut raw);
assert!(raw.is_null());
}
}
}