use std::ptr::null_mut;
use ffmpeg_sys_next::AVFormatContext;
use crate::core::context::{in_fmt_ctx_free, out_fmt_ctx_free};
pub(crate) enum Mode {
Input,
InputCustomIo,
Output,
OutputCustomIo,
}
pub(crate) struct FormatContext {
ptr: *mut AVFormatContext,
mode: Mode,
}
unsafe impl Send for FormatContext {}
impl FormatContext {
#[inline]
pub(crate) unsafe fn from_input(ptr: *mut AVFormatContext) -> Self {
Self {
ptr,
mode: Mode::Input,
}
}
#[inline]
pub(crate) unsafe fn from_input_custom_io(ptr: *mut AVFormatContext) -> Self {
Self {
ptr,
mode: Mode::InputCustomIo,
}
}
#[cfg_attr(docsrs, allow(dead_code))]
#[inline]
pub(crate) unsafe fn from_output(ptr: *mut AVFormatContext) -> Self {
Self {
ptr,
mode: Mode::Output,
}
}
#[cfg_attr(docsrs, allow(dead_code))]
#[inline]
pub(crate) unsafe fn from_output_custom_io(ptr: *mut AVFormatContext) -> Self {
Self {
ptr,
mode: Mode::OutputCustomIo,
}
}
#[inline]
pub(crate) unsafe fn as_ptr(&self) -> *mut AVFormatContext {
self.ptr
}
}
impl Drop for FormatContext {
fn drop(&mut self) {
if self.ptr.is_null() {
return;
}
match self.mode {
Mode::Input => in_fmt_ctx_free(self.ptr, false),
Mode::InputCustomIo => in_fmt_ctx_free(self.ptr, true),
Mode::Output => out_fmt_ctx_free(self.ptr, false),
Mode::OutputCustomIo => out_fmt_ctx_free(self.ptr, true),
}
self.ptr = null_mut();
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn drop_of_null_is_a_noop() {
for mode in [
Mode::Input,
Mode::InputCustomIo,
Mode::Output,
Mode::OutputCustomIo,
] {
let _ = FormatContext {
ptr: null_mut(),
mode,
};
}
}
}