hylarana_codec/
lib.rs

1mod audio;
2mod codec;
3mod video;
4
5use std::ffi::{c_char, c_int, c_void};
6
7use common::strings::PSTR;
8use ffmpeg::*;
9use log::Level;
10
11pub use self::{
12    audio::{
13        create_opus_identification_header, AudioDecoder, AudioDecoderError, AudioEncoder,
14        AudioEncoderError, AudioEncoderSettings,
15    },
16    codec::{CodecError, CodecType, CreateVideoContextError, CreateVideoFrameError},
17    video::{
18        VideoDecoder, VideoDecoderError, VideoDecoderSettings, VideoEncoder, VideoEncoderError,
19        VideoEncoderSettings,
20    },
21};
22
23#[repr(C)]
24#[derive(Debug)]
25#[allow(dead_code)]
26enum LoggerLevel {
27    Panic = 0,
28    Fatal = 8,
29    Error = 16,
30    Warn = 24,
31    Info = 32,
32    Verbose = 40,
33    Debug = 48,
34    Trace = 56,
35}
36
37impl Into<Level> for LoggerLevel {
38    fn into(self) -> Level {
39        match self {
40            Self::Panic | Self::Fatal | Self::Error => Level::Error,
41            Self::Info | Self::Verbose => Level::Info,
42            Self::Warn => Level::Warn,
43            Self::Debug => Level::Debug,
44            Self::Trace => Level::Trace,
45        }
46    }
47}
48
49#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
50#[allow(non_camel_case_types)]
51type va_list = *mut __va_list_tag;
52
53#[cfg(all(target_os = "linux", not(target_arch = "x86_64")))]
54#[allow(non_camel_case_types)]
55type va_list = [u64; 4];
56
57extern "C" {
58    // Write formatted data from variable argument list to sized buffer
59    // Composes a string with the same text that would be printed if format was used
60    // on printf, but using the elements in the variable argument list identified by
61    // arg instead of additional function arguments and storing the resulting
62    // content as a C string in the buffer pointed by s (taking n as the maximum
63    // buffer capacity to fill).
64    //
65    // If the resulting string would be longer than n-1 characters, the remaining
66    // characters are discarded and not stored, but counted for the value returned
67    // by the function.
68    //
69    // Internally, the function retrieves arguments from the list identified by arg
70    // as if va_arg was used on it, and thus the state of arg is likely to be
71    // altered by the call.
72    //
73    // In any case, arg should have been initialized by va_start at some point
74    // before the call, and it is expected to be released by va_end at some point
75    // after the call.
76    #[allow(improper_ctypes)]
77    fn vsnprintf(s: *mut c_char, n: usize, format: *const c_char, args: va_list) -> c_int;
78}
79
80#[allow(improper_ctypes_definitions)]
81unsafe extern "C" fn logger_proc(
82    _: *mut c_void,
83    level: c_int,
84    message: *const c_char,
85    args: va_list,
86) {
87    let mut chars: [c_char; 1024] = [0; 1024];
88    vsnprintf(chars.as_mut_ptr(), 2048, message, args);
89
90    let level: LoggerLevel = std::mem::transmute(level);
91    if let Ok(message) = PSTR::from(chars.as_ptr()).to_string() {
92        log::log!(
93            target: "ffmpeg",
94            level.into(),
95            "{}",
96            message.as_str().strip_suffix("\n").unwrap_or(&message)
97        );
98    }
99}
100
101pub fn startup() {
102    unsafe {
103        av_log_set_callback(Some(logger_proc));
104    }
105}
106
107pub fn shutdown() {
108    unsafe {
109        av_log_set_callback(None);
110    }
111}