mirror of
https://github.com/encounter/rust-ffmpeg.git
synced 2026-07-10 21:18:39 -07:00
feat: add log integration
This commit is contained in:
@@ -101,6 +101,7 @@ ffmpeg_4_3 = ["ffmpeg_4_2"]
|
||||
libc = "0.2"
|
||||
bitflags = "1.0"
|
||||
thiserror = "1"
|
||||
vsprintf = "2"
|
||||
|
||||
[dependencies.serde]
|
||||
version = "1.0.0"
|
||||
@@ -114,3 +115,10 @@ optional = true
|
||||
[dependencies.ffmpeg-sys]
|
||||
version = "4.2"
|
||||
default-features = false
|
||||
|
||||
[dependencies.log]
|
||||
version = "0.4"
|
||||
optional = true
|
||||
|
||||
[dev-dependencies]
|
||||
env_logger = "0.8"
|
||||
|
||||
+4
-2
@@ -64,8 +64,10 @@ pub use crate::filter::Filter;
|
||||
|
||||
pub mod software;
|
||||
|
||||
fn init_error() {
|
||||
fn init_util() {
|
||||
util::error::register_all();
|
||||
#[cfg(feature = "log")]
|
||||
util::log::register();
|
||||
}
|
||||
|
||||
#[cfg(feature = "format")]
|
||||
@@ -93,7 +95,7 @@ fn init_filter() {
|
||||
fn init_filter() {}
|
||||
|
||||
pub fn init() -> Result<(), Error> {
|
||||
init_error();
|
||||
init_util();
|
||||
init_format();
|
||||
init_device();
|
||||
init_filter();
|
||||
|
||||
+45
-27
@@ -4,8 +4,8 @@ use libc::c_int;
|
||||
|
||||
use crate::ffi::*;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Error {
|
||||
Io(io::Error),
|
||||
Bug,
|
||||
Bug2,
|
||||
Unknown,
|
||||
@@ -68,15 +68,55 @@ impl From<c_int> for Error {
|
||||
AVERROR_HTTP_NOT_FOUND => Error::HttpNotFound,
|
||||
AVERROR_HTTP_OTHER_4XX => Error::HttpOther4xx,
|
||||
AVERROR_HTTP_SERVER_ERROR => Error::HttpServerError,
|
||||
|
||||
_ => Error::Unknown,
|
||||
err => Error::Io(io::Error::from_raw_os_error(-err)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<c_int> for Error {
|
||||
fn into(self) -> c_int {
|
||||
self.as_raw_error()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Error> for io::Error {
|
||||
fn from(value: Error) -> io::Error {
|
||||
match value {
|
||||
Error::Io(err) =>
|
||||
err,
|
||||
|
||||
value =>
|
||||
io::Error::new(io::ErrorKind::Other, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
match self {
|
||||
Error::Io(err) =>
|
||||
err.fmt(f),
|
||||
|
||||
err => f.write_str(unsafe {
|
||||
from_utf8_unchecked(CStr::from_ptr(STRINGS[index(err)].as_ptr()).to_bytes())
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
f.write_str("ffmpeg::Error(")?;
|
||||
f.write_str(&format!("{}: ", AVUNERROR(self.as_raw_error())))?;
|
||||
fmt::Display::fmt(self, f)?;
|
||||
f.write_str(")")
|
||||
}
|
||||
}
|
||||
|
||||
impl Error {
|
||||
pub fn as_raw_error(&self) -> c_int {
|
||||
match self {
|
||||
Error::Io(err) => err.raw_os_error().unwrap(),
|
||||
Error::BsfNotFound => AVERROR_BSF_NOT_FOUND,
|
||||
Error::Bug => AVERROR_BUG,
|
||||
Error::BufferTooSmall => AVERROR_BUFFER_TOO_SMALL,
|
||||
@@ -108,32 +148,10 @@ impl Into<c_int> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Error> for io::Error {
|
||||
fn from(value: Error) -> io::Error {
|
||||
io::Error::new(io::ErrorKind::Other, value)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
f.write_str(unsafe {
|
||||
from_utf8_unchecked(CStr::from_ptr(STRINGS[index(self)].as_ptr()).to_bytes())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
f.write_str("ffmpeg::Error(")?;
|
||||
f.write_str(&format!("{}: ", AVUNERROR((*self).into())))?;
|
||||
fmt::Display::fmt(self, f)?;
|
||||
f.write_str(")")
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn index(error: &Error) -> usize {
|
||||
match *error {
|
||||
match error {
|
||||
Error::Io(_) => unreachable!(),
|
||||
Error::BsfNotFound => 0,
|
||||
Error::Bug => 1,
|
||||
Error::BufferTooSmall => 2,
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
use libc::{c_void, c_int, c_char};
|
||||
use vsprintf::vsprintf;
|
||||
use log;
|
||||
use crate::ffi::*;
|
||||
|
||||
pub fn set_level(level: log::Level) {
|
||||
unsafe {
|
||||
av_log_set_level(match level {
|
||||
log::Level::Error => AV_LOG_ERROR,
|
||||
log::Level::Warn => AV_LOG_WARNING,
|
||||
log::Level::Info => AV_LOG_INFO,
|
||||
log::Level::Debug => AV_LOG_DEBUG,
|
||||
log::Level::Trace => AV_LOG_TRACE,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn callback(_ptr: *mut c_void, level: c_int, fmt: *const c_char, args: *mut __va_list_tag) {
|
||||
let string = vsprintf(fmt, args).unwrap();
|
||||
let level = match level {
|
||||
AV_LOG_PANIC | AV_LOG_FATAL | AV_LOG_ERROR =>
|
||||
log::LevelFilter::Error,
|
||||
|
||||
AV_LOG_WARNING =>
|
||||
log::LevelFilter::Warn,
|
||||
|
||||
AV_LOG_INFO =>
|
||||
log::LevelFilter::Info,
|
||||
|
||||
AV_LOG_VERBOSE | AV_LOG_DEBUG =>
|
||||
log::LevelFilter::Debug,
|
||||
|
||||
AV_LOG_TRACE =>
|
||||
log::LevelFilter::Trace,
|
||||
|
||||
_ =>
|
||||
log::LevelFilter::Off,
|
||||
};
|
||||
|
||||
if let Some(level) = level.to_level() {
|
||||
log::log!(target: "ffmpeg", level, "{}", string.trim());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register() {
|
||||
unsafe {
|
||||
av_log_set_callback(Some(callback));
|
||||
}
|
||||
|
||||
if let Some(level) = log::max_level().to_level() {
|
||||
set_level(level);
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,9 @@ pub mod range;
|
||||
pub mod rational;
|
||||
pub mod time;
|
||||
|
||||
#[cfg(feature = "log")]
|
||||
pub mod log;
|
||||
|
||||
use std::{ffi::CStr, str::from_utf8_unchecked};
|
||||
|
||||
use crate::ffi::*;
|
||||
|
||||
Reference in New Issue
Block a user