Refactor format::{Input, Output} (#79)

* Refactor format::Input

* Refactor format::Output

* Remove av_register_* API

This was deprecated in 4.0 (2018) and without it,
we never need a mutable pointer to AVInputFormat/AVOutputFormat
This commit is contained in:
FreezyLemon 2024-10-28 10:42:24 +01:00 committed by GitHub
parent ef14631f71
commit 764ec831f9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 89 additions and 107 deletions

View File

@ -3,50 +3,60 @@ use std::ptr;
use crate::ffi::*; use crate::ffi::*;
use crate::format; use crate::format;
pub struct AudioIter(*mut AVInputFormat); pub struct AudioIter(*const AVInputFormat);
impl Iterator for AudioIter { impl Iterator for AudioIter {
type Item = format::Input; type Item = format::Input;
fn next(&mut self) -> Option<<Self as Iterator>::Item> { fn next(&mut self) -> Option<<Self as Iterator>::Item> {
unsafe { unsafe {
let ptr = av_input_audio_device_next(self.0) as *mut AVInputFormat; let inner = self.0;
if ptr.is_null() && !self.0.is_null() { // Pre-5.0 FFmpeg uses a non-const pointer here
None #[cfg(not(feature = "ffmpeg_5_0"))]
} else { let inner = inner as *mut _;
let ptr = av_input_audio_device_next(inner);
if let Some(input) = format::Input::from_raw(ptr) {
self.0 = ptr; self.0 = ptr;
Some(input)
Some(format::Input::wrap(ptr)) } else {
None
} }
} }
} }
} }
pub fn audio() -> AudioIter { pub fn audio() -> AudioIter {
AudioIter(ptr::null_mut()) AudioIter(ptr::null())
} }
pub struct VideoIter(*mut AVInputFormat); pub struct VideoIter(*const AVInputFormat);
impl Iterator for VideoIter { impl Iterator for VideoIter {
type Item = format::Input; type Item = format::Input;
fn next(&mut self) -> Option<<Self as Iterator>::Item> { fn next(&mut self) -> Option<<Self as Iterator>::Item> {
unsafe { unsafe {
let ptr = av_input_video_device_next(self.0) as *mut AVInputFormat; let inner = self.0;
if ptr.is_null() && !self.0.is_null() { // Pre-5.0 FFmpeg uses a non-const pointer here
None #[cfg(not(feature = "ffmpeg_5_0"))]
} else { let inner = inner as *mut _;
let ptr = av_input_video_device_next(inner);
if let Some(input) = format::Input::from_raw(ptr) {
self.0 = ptr; self.0 = ptr;
Some(input)
Some(format::Input::wrap(ptr)) } else {
None
} }
} }
} }
} }
pub fn video() -> VideoIter { pub fn video() -> VideoIter {
VideoIter(ptr::null_mut()) VideoIter(ptr::null())
} }

View File

@ -3,21 +3,26 @@ use std::ptr;
use crate::ffi::*; use crate::ffi::*;
use crate::format; use crate::format;
pub struct AudioIter(*mut AVOutputFormat); pub struct AudioIter(*const AVOutputFormat);
impl Iterator for AudioIter { impl Iterator for AudioIter {
type Item = format::Output; type Item = format::Output;
fn next(&mut self) -> Option<<Self as Iterator>::Item> { fn next(&mut self) -> Option<<Self as Iterator>::Item> {
unsafe { unsafe {
let ptr = av_output_audio_device_next(self.0) as *mut AVOutputFormat; let inner = self.0;
if ptr.is_null() && !self.0.is_null() { // Pre-5.0 FFmpeg uses a non-const pointer here
None #[cfg(not(feature = "ffmpeg_5_0"))]
let inner = inner as *mut _;
let ptr = av_output_audio_device_next(inner);
if let Some(output) = format::Output::from_raw(ptr) {
self.0 = ptr;
Some(output)
} else { } else {
self.0 = ptr as *mut AVOutputFormat; None
Some(format::Output::wrap(ptr))
} }
} }
} }
@ -27,21 +32,26 @@ pub fn audio() -> AudioIter {
AudioIter(ptr::null_mut()) AudioIter(ptr::null_mut())
} }
pub struct VideoIter(*mut AVOutputFormat); pub struct VideoIter(*const AVOutputFormat);
impl Iterator for VideoIter { impl Iterator for VideoIter {
type Item = format::Output; type Item = format::Output;
fn next(&mut self) -> Option<<Self as Iterator>::Item> { fn next(&mut self) -> Option<<Self as Iterator>::Item> {
unsafe { unsafe {
let ptr = av_output_video_device_next(self.0) as *mut AVOutputFormat; let inner = self.0;
if ptr.is_null() && !self.0.is_null() { // Pre-5.0 FFmpeg uses a non-const pointer here
None #[cfg(not(feature = "ffmpeg_5_0"))]
let inner = inner as *mut _;
let ptr = av_output_video_device_next(inner);
if let Some(output) = format::Output::from_raw(ptr) {
self.0 = ptr;
Some(output)
} else { } else {
self.0 = ptr as *mut AVOutputFormat; None
Some(format::Output::wrap(ptr))
} }
} }
} }

View File

@ -36,7 +36,7 @@ impl Input {
impl Input { impl Input {
pub fn format(&self) -> format::Input { pub fn format(&self) -> format::Input {
unsafe { format::Input::wrap((*self.as_ptr()).iformat as *mut AVInputFormat) } unsafe { format::Input::from_raw((*self.as_ptr()).iformat).expect("iformat is non-null") }
} }
#[cfg(not(feature = "ffmpeg_5_0"))] #[cfg(not(feature = "ffmpeg_5_0"))]

View File

@ -35,7 +35,7 @@ impl Output {
impl Output { impl Output {
pub fn format(&self) -> format::Output { pub fn format(&self) -> format::Output {
unsafe { format::Output::wrap((*self.as_ptr()).oformat as *mut AVOutputFormat) } unsafe { format::Output::from_raw((*self.as_ptr()).oformat).expect("oformat is non-null") }
} }
pub fn write_header(&mut self) -> Result<(), Error> { pub fn write_header(&mut self) -> Result<(), Error> {

View File

@ -1,34 +1,37 @@
use std::ptr::NonNull;
use crate::ffi::*; use crate::ffi::*;
use crate::utils; use crate::utils;
use super::Flags;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Input { pub struct Input {
ptr: *mut AVInputFormat, ptr: NonNull<AVInputFormat>,
} }
impl Input { impl Input {
pub unsafe fn wrap(ptr: *mut AVInputFormat) -> Self { pub unsafe fn from_raw(ptr: *const AVInputFormat) -> Option<Self> {
Input { ptr } NonNull::new(ptr as *mut _).map(|ptr| Self { ptr })
} }
pub unsafe fn as_ptr(&self) -> *const AVInputFormat { pub fn as_ptr(self) -> *const AVInputFormat {
self.ptr as *const _ self.ptr.as_ptr()
} }
pub unsafe fn as_mut_ptr(&mut self) -> *mut AVInputFormat { pub fn name(self) -> &'static str {
self.ptr
}
}
impl Input {
pub fn name(&self) -> &str {
unsafe { utils::str_from_c_ptr((*self.as_ptr()).name) } unsafe { utils::str_from_c_ptr((*self.as_ptr()).name) }
} }
pub fn description(&self) -> &str { pub fn description(self) -> &'static str {
unsafe { utils::optional_str_from_c_ptr((*self.as_ptr()).long_name).unwrap_or("") } unsafe { utils::optional_str_from_c_ptr((*self.as_ptr()).long_name).unwrap_or("") }
} }
pub fn extensions(&self) -> Vec<&str> { pub fn flags(self) -> Flags {
unsafe { Flags::from_bits_truncate((*self.as_ptr()).flags) }
}
pub fn extensions(self) -> Vec<&'static str> {
unsafe { unsafe {
let ptr = (*self.as_ptr()).extensions; let ptr = (*self.as_ptr()).extensions;
@ -40,7 +43,7 @@ impl Input {
} }
} }
pub fn mime_types(&self) -> Vec<&str> { pub fn mime_types(self) -> Vec<&'static str> {
unsafe { unsafe {
let ptr = (*self.as_ptr()).mime_type; let ptr = (*self.as_ptr()).mime_type;

View File

@ -26,11 +26,7 @@ impl Iterator for DemuxerIter {
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
unsafe { unsafe {
let next = av_demuxer_iterate(&mut self.ptr); let next = av_demuxer_iterate(&mut self.ptr);
if next.is_null() { Input::from_raw(next)
None
} else {
Some(Input::wrap(next as _))
}
} }
} }
} }
@ -57,11 +53,7 @@ impl Iterator for MuxerIter {
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
unsafe { unsafe {
let next = av_muxer_iterate(&mut self.ptr); let next = av_muxer_iterate(&mut self.ptr);
if next.is_null() { Output::from_raw(next)
None
} else {
Some(Output::wrap(next as _))
}
} }
} }
} }

View File

@ -1,40 +1,39 @@
use std::path::Path; use std::path::Path;
use std::ffi::CString; use std::ffi::CString;
use std::ptr; use std::ptr::{self, NonNull};
use super::Flags; use super::Flags;
use crate::ffi::*; use crate::ffi::*;
use crate::{codec, media, utils}; use crate::{codec, media, utils};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Output { pub struct Output {
ptr: *mut AVOutputFormat, ptr: NonNull<AVOutputFormat>,
} }
impl Output { impl Output {
pub unsafe fn wrap(ptr: *mut AVOutputFormat) -> Self { pub unsafe fn from_raw(ptr: *const AVOutputFormat) -> Option<Self> {
Output { ptr } NonNull::new(ptr as *mut _).map(|ptr| Self { ptr })
} }
pub unsafe fn as_ptr(&self) -> *const AVOutputFormat { pub fn as_ptr(self) -> *const AVOutputFormat {
self.ptr as *const _ self.ptr.as_ptr()
} }
pub unsafe fn as_mut_ptr(&mut self) -> *mut AVOutputFormat { pub fn name(self) -> &'static str {
self.ptr
}
}
impl Output {
pub fn name(&self) -> &str {
unsafe { utils::str_from_c_ptr((*self.as_ptr()).name) } unsafe { utils::str_from_c_ptr((*self.as_ptr()).name) }
} }
pub fn description(&self) -> &str { pub fn description(self) -> &'static str {
unsafe { utils::optional_str_from_c_ptr((*self.as_ptr()).long_name).unwrap_or("") } unsafe { utils::optional_str_from_c_ptr((*self.as_ptr()).long_name).unwrap_or("") }
} }
pub fn extensions(&self) -> Vec<&str> { pub fn flags(self) -> Flags {
unsafe { Flags::from_bits_truncate((*self.as_ptr()).flags) }
}
pub fn extensions(self) -> Vec<&'static str> {
unsafe { unsafe {
let ptr = (*self.as_ptr()).extensions; let ptr = (*self.as_ptr()).extensions;
@ -46,7 +45,7 @@ impl Output {
} }
} }
pub fn mime_types(&self) -> Vec<&str> { pub fn mime_types(self) -> Vec<&'static str> {
unsafe { unsafe {
let ptr = (*self.as_ptr()).mime_type; let ptr = (*self.as_ptr()).mime_type;
@ -58,9 +57,9 @@ impl Output {
} }
} }
pub fn codec<P: AsRef<Path>>(&self, path: &P, kind: media::Type) -> codec::Id { pub fn codec<P: AsRef<Path>>(self, path: &P, kind: media::Type) -> codec::Id {
// XXX: use to_cstring when stable // XXX: use to_cstring when stable
let path = CString::new(path.as_ref().as_os_str().to_str().unwrap()).unwrap(); let path = CString::new(path.as_ref().to_str().unwrap()).unwrap();
unsafe { unsafe {
codec::Id::from(av_guess_codec( codec::Id::from(av_guess_codec(
@ -72,8 +71,4 @@ impl Output {
)) ))
} }
} }
pub fn flags(&self) -> Flags {
unsafe { Flags::from_bits_truncate((*self.as_ptr()).flags) }
}
} }

View File

@ -23,27 +23,6 @@ use crate::ffi::*;
use crate::utils; use crate::utils;
use crate::{Dictionary, Error}; use crate::{Dictionary, Error};
#[cfg(not(feature = "ffmpeg_5_0"))]
pub fn register_all() {
unsafe {
av_register_all();
}
}
#[cfg(not(feature = "ffmpeg_5_0"))]
pub fn register_input(mut format: Input) {
unsafe {
av_register_input_format(format.as_mut_ptr());
}
}
#[cfg(not(feature = "ffmpeg_5_0"))]
pub fn register_output(mut format: Output) {
unsafe {
av_register_output_format(format.as_mut_ptr());
}
}
pub fn version() -> u32 { pub fn version() -> u32 {
unsafe { avformat_version() } unsafe { avformat_version() }
} }

View File

@ -83,11 +83,6 @@ fn init_error() {
util::error::register_all(); util::error::register_all();
} }
#[cfg(all(feature = "format", not(feature = "ffmpeg_5_0")))]
fn init_format() {
format::register_all();
}
#[cfg(not(feature = "format"))] #[cfg(not(feature = "format"))]
fn init_format() {} fn init_format() {}
@ -109,8 +104,6 @@ fn init_filter() {}
pub fn init() -> Result<(), Error> { pub fn init() -> Result<(), Error> {
init_error(); init_error();
#[cfg(not(feature = "ffmpeg_5_0"))]
init_format();
init_device(); init_device();
#[cfg(not(feature = "ffmpeg_5_0"))] #[cfg(not(feature = "ffmpeg_5_0"))]
init_filter(); init_filter();