diff --git a/Cargo.toml b/Cargo.toml index 41b7d59..f47da71 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ crate-type = ["dylib"] [dependencies] libc = "0.2.0" nom = "1.2.3" +vlc_module = { git = "https://github.com/Geal/vlc_module.rs.git" } va_list-rs = { git = "https://github.com/GuillaumeGomez/va_list-rs" } [dependencies.flavors] diff --git a/src/ffi.rs b/src/ffi.rs deleted file mode 100644 index ea73d1d..0000000 --- a/src/ffi.rs +++ /dev/null @@ -1,328 +0,0 @@ -use libc::{uint8_t, uint16_t, uint32_t, uint64_t, int64_t, size_t, ssize_t, c_void, c_int, c_uint, c_char, - c_float}; - -#[macro_export] -macro_rules! vlc_fourcc ( - ($a: expr, $b: expr, $c: expr, $d: expr) => { - $a as uint32_t | (($b as uint32_t) << 8) | - (($c as uint32_t) << 16) | (($d as uint32_t) << 24) - } -); - -#[repr(i32)] -pub enum VLCModuleProperties { - VLC_MODULE_CREATE = 0, - VLC_CONFIG_CREATE, - - VLC_MODULE_CPU_REQUIREMENT=0x100, - VLC_MODULE_SHORTCUT, - VLC_MODULE_CAPABILITY, - VLC_MODULE_SCORE, - VLC_MODULE_CB_OPEN, - VLC_MODULE_CB_CLOSE, - VLC_MODULE_NO_UNLOAD, - VLC_MODULE_NAME, - VLC_MODULE_SHORTNAME, - VLC_MODULE_DESCRIPTION, - VLC_MODULE_HELP, - VLC_MODULE_TEXTDOMAIN, - - VLC_CONFIG_NAME=0x1000, - VLC_CONFIG_VALUE, - VLC_CONFIG_RANGE, - VLC_CONFIG_ADVANCED, - VLC_CONFIG_VOLATILE, - VLC_CONFIG_PERSISTENT_OBSOLETE, - VLC_CONFIG_PRIVATE, - VLC_CONFIG_REMOVED, - VLC_CONFIG_CAPABILITY, - VLC_CONFIG_SHORTCUT, - VLC_CONFIG_OLDNAME_OBSOLETE, - VLC_CONFIG_SAFE, - VLC_CONFIG_DESC, - VLC_CONFIG_LIST_OBSOLETE, - VLC_CONFIG_ADD_ACTION_OBSOLETE, - VLC_CONFIG_LIST, - VLC_CONFIG_LIST_CB, -} - -pub type stream_t = c_void; -pub type libvlc_int_t = c_void; -pub type module_t = c_void; -//FIXME: correct va_list implementation in Rust? -pub type va_list = c_void; -pub type input_thread_t = c_void; -pub type es_out_id_t = c_void; -pub type mtime_t = int64_t; -pub type vlc_fourcc_t = uint32_t; - -pub type extra_languages_t = c_void; -pub type text_style_t = c_void; -pub type es_out_sys_t = c_void; - -#[repr(C)] -pub struct vlc_object_t { - pub psz_object_type: *const c_char, - pub psz_header: *mut c_char, - pub i_flags: c_int, - // no c_bool in Rust FFI yet? - pub b_force: bool, - pub p_libvlc: *mut libvlc_int_t, - pub p_parent: *mut vlc_object_t, -} - -#[repr(C)] -pub struct demux_t { - //VLC_COMMON_MEMBERS - pub psz_object_type: *const c_char, - pub psz_header: *mut c_char, - pub i_flags: c_int, - pub b_force: bool, - pub p_libvlc: *mut libvlc_int_t, - pub p_parent: *mut vlc_object_t, - - pub p_module: *mut module_t, - - pub psz_access: *mut c_char, - pub psz_demux: *mut c_char, - pub psz_location: *mut c_char, - pub psz_file: *mut c_char, - - pub s: *mut stream_t, - pub out: *mut es_out_t, - pub pf_demux: Option) -> c_int>, - pub pf_control: Option, c_int, *const va_list) -> c_int>, - - // 'info' nested struct. Can we do that with Rust FFI? - pub i_update: c_uint, - pub i_title: c_int, - pub i_seekpoint: c_int, - - //FIXME: p_sys contains a pointer to a module specific structure, make it generic? - pub p_sys: *mut T, - - pub p_input: *mut input_thread_t, -} - -#[repr(C)] -pub struct es_out_t { - pub pf_add: Option *mut es_out_id_t>, - pub pf_send: Option c_int>, - pub pf_del: Option, - pub pf_control: Option c_int>, - pub pf_destroy: Option, - pub p_sys: *mut es_out_sys_t, -} - -#[repr(C)] -pub struct block_t { - pub p_next: *mut block_t, - pub p_buffer: *mut uint8_t, - pub i_buffer: size_t, - pub p_start: *mut uint8_t, - pub i_size: size_t, - pub i_flags: uint32_t, - pub i_nb_samples: c_uint, - pub i_pts: mtime_t, - pub i_dts: mtime_t, - pub i_length: mtime_t, - pub pf_release: Option, -} - -#[repr(C)] -pub struct audio_format_t { - pub i_format: vlc_fourcc_t, - pub i_rate: c_uint, - pub i_physical_channels: uint16_t, - pub i_original_channels: uint32_t, - pub i_bytes_per_frame: c_uint, - pub i_frame_length: c_uint, - pub i_bitspersample: c_uint, - pub i_blockalign: c_uint, - pub i_channels: uint8_t, -} - -#[repr(C)] -pub struct audio_replay_gain_t { - pub pb_peak: [bool; 2], - pub pf_peak: [c_float; 2], - pub pb_gain: [bool; 2], - pub pf_gain: [c_float; 2], -} - -#[repr(C)] -pub struct video_palette_t { - pub i_entries: c_int, - pub palette: [[uint8_t; 256];4], -} - -#[repr(i32)] -pub enum es_format_category_e { - UNKNOWN_ES = 0, - VIDEO_ES, - AUDIO_ES, - SPU_ES, - NAV_ES, -} - -#[repr(i32)] -pub enum video_orientation_t { - /**< Top line represents top, left column left. */ - ORIENT_TOP_LEFT = 0, - /**< Flipped horizontally */ - ORIENT_TOP_RIGHT, - /**< Flipped vertically */ - ORIENT_BOTTOM_LEFT, - /**< Rotated 180 degrees */ - ORIENT_BOTTOM_RIGHT, - /**< Transposed */ - ORIENT_LEFT_TOP, - /**< Rotated 90 degrees clockwise */ - ORIENT_LEFT_BOTTOM, - /**< Rotated 90 degrees anti-clockwise */ - ORIENT_RIGHT_TOP, - /**< Anti-transposed */ - ORIENT_RIGHT_BOTTOM, -} -/* - ORIENT_NORMAL = ORIENT_TOP_LEFT, - ORIENT_TRANSPOSED = ORIENT_LEFT_TOP, - ORIENT_ANTI_TRANSPOSED = ORIENT_RIGHT_BOTTOM, - ORIENT_HFLIPPED = ORIENT_TOP_RIGHT, - ORIENT_VFLIPPED = ORIENT_BOTTOM_LEFT, - ORIENT_ROTATED_180 = ORIENT_BOTTOM_RIGHT, - ORIENT_ROTATED_270 = ORIENT_LEFT_BOTTOM, - ORIENT_ROTATED_90 = ORIENT_RIGHT_TOP, -*/ - -#[repr(i32)] -pub enum video_color_primaries_t { - COLOR_PRIMARIES_UNDEF, - COLOR_PRIMARIES_BT601_525, - COLOR_PRIMARIES_BT601_625, - COLOR_PRIMARIES_BT709, - COLOR_PRIMARIES_BT2020, - COLOR_PRIMARIES_DCI_P3, -} - -#[repr(i32)] -pub enum video_transfer_func_t { - TRANSFER_FUNC_UNDEF, - TRANSFER_FUNC_LINEAR, - TRANSFER_FUNC_SRGB /*< Gamma 2.2 */, - TRANSFER_FUNC_BT709, -} - -#[repr(i32)] -pub enum video_color_space_t { - COLOR_SPACE_UNDEF, - COLOR_SPACE_BT601, - COLOR_SPACE_BT709, - COLOR_SPACE_BT2020, -} - -#[repr(i32)] -pub enum video_chroma_location_t { - CHROMA_LOCATION_UNDEF, - CHROMA_LOCATION_LEFT, /*< Most common in MPEG-2 Video, H.264/265 */ - CHROMA_LOCATION_CENTER, /*< Most common in MPEG-1 Video, JPEG */ - CHROMA_LOCATION_TOP_LEFT, - CHROMA_LOCATION_TOP_CENTER, - CHROMA_LOCATION_BOTTOM_LEFT, - CHROMA_LOCATION_BOTTOM_CENTER, -} - -#[repr(C)] -pub struct video_format_t { - pub i_chroma: vlc_fourcc_t, - pub i_width: c_uint, - pub i_height: c_uint, - pub i_x_offset: c_uint, - pub i_y_offset: c_uint, - pub i_visible_width: c_uint, - pub i_visible_height: c_uint, - pub i_bits_per_pixel: c_uint, - pub i_sar_num: c_uint, - pub i_sar_den: c_uint, - pub i_frame_rate: c_uint, - pub i_frame_rate_base: c_uint, - pub i_rmask: uint32_t, - pub i_gmask: uint32_t, - pub i_bmask: uint32_t, - pub i_rrshift: c_int, - pub i_lrshift: c_int, - pub i_rgshift: c_int, - pub i_lgshift: c_int, - pub i_rbshift: c_int, - pub i_lbshift: c_int, - pub p_palette: *mut video_palette_t, - pub orientation: video_orientation_t, - pub primaries: video_color_primaries_t, - pub transfer: video_transfer_func_t, - pub space: video_color_space_t, - pub b_color_range_full: bool, - pub chroma_location: video_chroma_location_t, -} - -#[repr(C)] -pub struct subs_format_t { - pub psz_encoding: *mut c_char, - pub i_x_origin: c_int, - pub i_y_origin: c_int, - - // spu struct - pub palette: [uint32_t; 17], - pub i_original_frame_width: c_int, - pub i_original_frame_height: c_int, - - // dvb struct - pub i_id: c_int, - - // teletext struct - pub i_magazine: c_int, - pub i_page: c_int, - - pub p_style: *mut text_style_t, -} - -#[repr(C)] -pub struct es_format_t { - pub i_cat: c_int, - pub i_codec: vlc_fourcc_t, - pub i_original_fourcc: vlc_fourcc_t, - pub i_id: c_int, - pub i_group: c_int, - pub i_priority: c_int, - pub psz_language: *mut c_char, - pub psz_description: *mut c_char, - pub i_extra_languages: c_uint, - pub p_extra_languages: *mut extra_languages_t, - pub audio: audio_format_t, - pub audio_replay_gain: audio_replay_gain_t, - pub video: video_format_t, - pub subs: subs_format_t, - pub i_bitrate: c_int, - pub i_profile: c_int, - pub i_level: c_int, - pub b_packetized: bool, - pub i_extra: c_int, - pub p_extra: *mut c_void, -} - -#[link(name = "vlccore")] -extern { - pub fn stream_Peek(stream: *mut stream_t, buf: *mut *const uint8_t, size: size_t) -> ssize_t; - - // https://www.videolan.org/developers/vlc/doc/doxygen/html/group__stream.html - pub fn stream_Read(stream: *mut stream_t, buf: *const c_void, size: size_t) -> ssize_t; - // https://www.videolan.org/developers/vlc/doc/doxygen/html/group__stream.html - pub fn stream_Tell(stream: *mut stream_t) -> uint64_t; - - pub fn stream_Block(stream: *mut stream_t, size: size_t) -> *mut block_t; - - pub fn demux_vaControlHelper(stream: *mut stream_t, i_start: int64_t, i_end: int64_t, - i_bitrate: int64_t, i_align: c_int, i_query: c_int, args: *const va_list) -> c_int; - - pub fn es_format_Init(format: *mut es_format_t, i_cat: c_int, i_codec: vlc_fourcc_t); - pub fn vlc_Log(obj: *mut vlc_object_t, priority: c_int, module: *const uint8_t, format: *const uint8_t, ...); -} diff --git a/src/lib.rs b/src/lib.rs index 84bca83..4360fd1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,32 +1,24 @@ #![allow(non_camel_case_types, dead_code)] +extern crate libc; +extern crate core; extern crate nom; extern crate flavors; -extern crate core; #[macro_use] extern crate va_list as rs_va_list; #[macro_use] -mod vlc; - -#[macro_use] -mod ffi; - -mod traits; -mod types; +extern crate vlc_module; -extern crate libc; use libc::{size_t, c_int, c_void, c_uint, uint32_t, uint64_t, int64_t}; use std::boxed::Box; use std::fmt; use std::mem::{transmute,zeroed}; -use vlc::{VLCModuleProperties, LogType, demux_t, va_list, block_t, mtime_t, es_format_t, +use vlc_module::vlc::{VLCModuleProperties, LogType, demux_t, va_list, block_t, mtime_t, es_format_t, vlc_fourcc_t, es_out_id_t}; -use vlc::{stream_Peek, stream_Seek, stream_Read, stream_Block, +use vlc_module::vlc::{stream_Peek, stream_Seek, stream_Read, stream_Block, demux_vaControlHelper, es_format_Init, es_out_Send, es_out_Add}; - -pub use traits::*; -pub use types::*; +use vlc_module::ffi::es_format_category_e; const PLUGIN_NAME: &'static [u8; 14] = b"inrustwetrust\0"; @@ -180,7 +172,7 @@ extern "C" fn demux(p_demux: *mut demux_t) -> c_int { if ! p_sys.audio_initialized { es_format_Init(&mut p_sys.audio_es_format, - ffi::es_format_category_e::AUDIO_ES, + es_format_category_e::AUDIO_ES, audio_codec_id_to_fourcc(audio_header.sound_format)); p_sys.audio_es_format.audio.i_channels = match audio_header.sound_type { flavors::parser::SoundType::SndMono => 1, @@ -254,7 +246,7 @@ extern "C" fn demux(p_demux: *mut demux_t) -> c_int { if ! p_sys.video_initialized { es_format_Init(&mut p_sys.video_es_format, - ffi::es_format_category_e::VIDEO_ES, + es_format_category_e::VIDEO_ES, video_codec_id_to_fourcc(vheader.codec_id)); p_sys.video_es_id = es_out_Add(p_demux.out, &mut p_sys.video_es_format); diff --git a/src/traits.rs b/src/traits.rs deleted file mode 100644 index e53df38..0000000 --- a/src/traits.rs +++ /dev/null @@ -1,40 +0,0 @@ -use libc::{c_char, c_int}; -use CString; -use vlc::LogType; - -pub trait ToC<'a, P: Copy> { - type Storage; - - fn to_c(&self) -> P; -} - -impl<'a> ToC<'a, *const c_char> for str { - type Storage = CString; - - fn to_c(&self) -> *const c_char { - let c_str = CString::new(self).unwrap(); - c_str.as_ptr() - } -} - -impl<'a> ToC<'a, c_int> for LogType { - type Storage = c_int; - - fn to_c(&self) -> c_int { - match *self { - LogType::Info => 0, - LogType::Error => 1, - LogType::Warning => 2, - LogType::Debug => 3, - } - } -} - -/*impl<'a> ToC<'a, *mut c_char> for str { - type Storage = CString; - - fn to_c(&self) -> *mut c_char { - let c_str = CString::new(self).unwrap(); - c_str.as_mut_ptr() - } -}*/ diff --git a/src/types.rs b/src/types.rs deleted file mode 100644 index f81e73b..0000000 --- a/src/types.rs +++ /dev/null @@ -1,101 +0,0 @@ -use libc::{c_char, c_void, free, malloc}; -use core; - -pub struct CString { - inner: *mut c_char, -} - -impl CString { - pub fn new(s: &str) -> Result { - unsafe { - let ptr: *mut c_char = malloc(s.len() + 1) as *mut c_char; - if ptr.is_null() { - Err(()) - } else { - let s_ptr = s.as_ptr(); - let mut pos: isize = 0; - while pos < s.len() as isize { - *ptr.offset(pos) = *s_ptr.offset(pos) as c_char; - pos += 1; - } - *ptr.offset(s.len() as isize) = 0; - Ok(CString { inner: ptr }) - } - } - } - - pub fn as_ptr(&self) -> *const c_char { - self.inner as *const c_char - } - - pub fn as_mut_ptr(&self) -> *mut c_char { - self.inner - } -} - -impl Drop for CString { - fn drop(&mut self) { - unsafe { free(self.inner as *mut c_void) } - } -} - -pub struct VlcBox { - inner: *mut T, - counter: *mut u32, -} - -impl VlcBox { - pub fn new(mut t: T) -> VlcBox { - unsafe { - let size = core::mem::size_of::(); - let tx = malloc(size) as *mut u8; - let counter = malloc(4) as *mut u32; - *counter = 1; - let x = &mut t; - let c_x = x as *mut _ as *mut u8; - for pos in 0..size { - *tx.offset(pos as isize) = *c_x.offset(pos as isize); - } - VlcBox { - inner: tx as *mut T, - counter: counter, - } - } - } -} - -impl core::ops::Deref for VlcBox { - type Target = T; - - fn deref(&self) -> &T { - unsafe { &*self.inner } - } -} - -impl core::ops::DerefMut for VlcBox { - fn deref_mut(&mut self) -> &mut T { - unsafe { &mut *self.inner } - } -} - -impl Clone for VlcBox { - fn clone(&self) -> VlcBox { - unsafe {*self.counter += 1; } - VlcBox { - inner: self.inner, - counter: self.counter, - } - } -} - -impl Drop for VlcBox { - fn drop(&mut self) { - unsafe { - *self.counter -= 1; - if *self.counter < 1 { - free(self.inner as *mut c_void); - free(self.counter as *mut c_void); - } - } - } -} diff --git a/src/vlc.rs b/src/vlc.rs deleted file mode 100644 index 0a34f9c..0000000 --- a/src/vlc.rs +++ /dev/null @@ -1,146 +0,0 @@ -#![allow(non_snake_case)] - -use libc::{uint8_t, uint64_t, int64_t, size_t, ssize_t, c_void, c_int}; -use std::slice::from_raw_parts; - -pub use ffi::{VLCModuleProperties,vlc_Log,demux_t,vlc_object_t, va_list, block_t, mtime_t, es_format_t, - vlc_fourcc_t, es_out_t, es_out_id_t}; - -use ffi::{self, stream_t, es_format_category_e}; - -macro_rules! vlc_module { - ($fn_name:ident, set_name($name:expr) set_description($desc:expr) set_capability($cap:expr, $score:expr) set_callbacks($open:expr, $close:expr)) => ( - #[allow(non_snake_case)] - #[no_mangle] - pub unsafe extern fn $fn_name(vlc_set: unsafe extern fn(*mut c_void, *mut c_void, c_int, ...) - -> c_int, - opaque: *mut c_void) -> c_int { - let module: *mut c_void = 0 as *mut c_void; - - if vlc_set(opaque, 0 as *mut c_void, VLCModuleProperties::VLC_MODULE_CREATE as i32, - &module) != 0 { - return -1; - } - - if vlc_set(opaque, module, VLCModuleProperties::VLC_MODULE_NAME as i32, - concat!($name, "\0").as_ptr()) != 0 { - return -1; - } - - if vlc_set(opaque, module, VLCModuleProperties::VLC_MODULE_DESCRIPTION as i32, - concat!($desc, "\0").as_ptr()) != 0 { - return -1; - } - - if vlc_set(opaque, module, VLCModuleProperties::VLC_MODULE_CAPABILITY as i32, - concat!($cap, "\0").as_ptr()) != 0 { - return -1; - } - - if vlc_set(opaque, module, VLCModuleProperties::VLC_MODULE_SCORE as i32, $score) != 0 { - return -1; - } - - let p_open: extern "C" fn(*mut demux_t) -> c_int = - transmute($open as extern "C" fn(_) -> c_int); - if vlc_set(opaque, module, VLCModuleProperties::VLC_MODULE_CB_OPEN as i32, p_open) != 0 { - return -1; - } - - let p_close: extern "C" fn(*mut demux_t) = transmute($close as extern "C" fn(_)); - if vlc_set(opaque, module, VLCModuleProperties::VLC_MODULE_CB_CLOSE as i32, p_close) != 0 { - return -1; - } - 0 - } - ); -} - -pub fn stream_Peek<'a>(stream: *mut stream_t, size: size_t) -> &'a[u8] { - let mut buf = 0 as *const uint8_t; - unsafe { - let sz = ffi::stream_Peek(stream, &mut buf, size); - // FIXME: what if returned sz is negative? (error) - if sz > 0 { - from_raw_parts(buf, sz as usize) - } else { - &[] - } - } -} - -pub fn stream_Read(stream: *mut stream_t, buf: &mut [u8]) -> ssize_t { - unsafe { - ffi::stream_Read(stream, buf.as_mut_ptr() as *const c_void, buf.len()) - } -} - -// FIXME: _stream_Tell and _stream_Seek are not exported by libvlccore, why? -pub fn stream_Tell(stream: *mut stream_t) -> uint64_t { - unsafe { - ffi::stream_Tell(stream) - } -} - -pub fn stream_Seek(stream: *mut stream_t, index: uint64_t) -> bool { - unsafe { - ffi::stream_Read(stream, 0 as *const c_void, index as size_t) == index as ssize_t - } -} - -pub fn stream_Block(stream: *mut stream_t, size: size_t) -> *mut block_t { - unsafe { - ffi::stream_Block(stream, size) - } -} - -pub fn es_format_Init(format: *mut es_format_t, i_cat: es_format_category_e, - i_codec: vlc_fourcc_t) { - unsafe { ffi::es_format_Init(format, i_cat as i32, i_codec) } -} - -pub fn es_out_Send(out: *mut es_out_t, id: *mut es_out_id_t, p_block: *mut block_t) -> c_int { - // FIXME: should not unwrap without checks - unsafe { ((*out).pf_send.as_ref().unwrap())( out, id, p_block ) } -} - -pub fn es_out_Add(out: *mut es_out_t, fmt: *mut es_format_t) -> *mut es_out_id_t { - unsafe { ((*out).pf_add.as_ref().unwrap())( out, fmt ) } -} - -pub fn demux_vaControlHelper(stream: *mut stream_t, i_start: int64_t, i_end: int64_t, - i_bitrate: int64_t, i_align: c_int, i_query: c_int, - args: *const va_list) -> c_int { - unsafe { - ffi::demux_vaControlHelper(stream, i_start, i_end, i_bitrate, i_align, i_query, args) - } -} - -pub trait VLCObject {} -impl VLCObject for demux_t {} - -use traits::ToC; - -pub enum LogType { - Info, - Error, - Warning, - Debug, -} - -pub fn Log(object: &mut T, priority: LogType, module: &[u8], format: &str) { - unsafe { - let ptr = object as *mut T; - vlc_Log(ptr as *mut vlc_object_t, priority.to_c(), module.as_ptr(), format.to_c() as *const uint8_t) - } -} - -macro_rules! vlc_Log { - ($demux:expr, $priority:expr, $module:expr, $format:expr) => {{ - vlc::Log($demux, $priority, $module, concat!($format, "\0")) - }}; - ($demux:expr, $priority:expr, $module:expr, $format:expr, $($args:expr),*) => {{ - let formatted = fmt::format(format_args!(concat!($format, "\0"),$($args),*)); - vlc::Log($demux, $priority, $module, &formatted) - }}; -}