diff --git a/src/ffi.rs b/src/ffi.rs index 0ccbff7..e5dc223 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -198,7 +198,7 @@ impl libvlc_media_track_t { pub unsafe fn audio(&mut self) -> *mut libvlc_audio_track_t { transmute(self._union0) } - pub unsafe fn video(&mut self) -> *mut libvlc_audio_track_t { + pub unsafe fn video(&mut self) -> *mut libvlc_video_track_t { transmute(self._union0) } pub unsafe fn subtitle(&mut self) -> *mut libvlc_subtitle_track_t { diff --git a/src/media.rs b/src/media.rs index 31de332..6bda0ef 100644 --- a/src/media.rs +++ b/src/media.rs @@ -119,6 +119,64 @@ impl Media { pub fn is_parsed(&self) -> bool { if unsafe{ ffi::libvlc_media_is_parsed(self.ptr) } == 0 { false }else{ true } } + + pub fn tracks(&self) -> Option> { + unsafe{ + let mut p_track: *mut *mut ffi::libvlc_media_track_t = ::std::ptr::null_mut(); + let n = ffi::libvlc_media_tracks_get(self.ptr, &mut p_track); + if n == 0 { + return None; + } + + let mut track = Vec::new(); + + for i in 0..n { + let p = p_track.offset(i as isize); + let type_specific_data = match (**p).i_type { + TrackType::Audio => { + let audio = (**p).audio(); + MediaTrackUnion::Audio(AudioTrack{ + channels: (*audio).i_channels, + rate: (*audio).i_rate, + }) + }, + TrackType::Video => { + let video = (**p).video(); + MediaTrackUnion::Video(VideoTrack{ + height: (*video).i_height, + width: (*video).i_width, + sar_num: (*video).i_sar_num, + sar_den: (*video).i_sar_den, + frame_rate_num: (*video).i_frame_rate_num, + frame_rate_den: (*video).i_frame_rate_den, + }) + }, + TrackType::Text => { + let subtitle = (**p).subtitle(); + MediaTrackUnion::Subtitle(SubtitleTrack{ + encoding: from_cstr((*subtitle).psz_encoding) + }) + }, + TrackType::Unknown => MediaTrackUnion::None, + }; + track.push(MediaTrack{ + codec: (**p).i_codec, + original_fourcc: (**p).i_original_fourcc, + id: (**p).i_id, + track_type: (**p).i_type, + profile: (**p).i_profile, + level: (**p).i_level, + bitrate: (**p).i_bitrate, + language: from_cstr((**p).psz_language), + description: from_cstr((**p).psz_description), + type_specific_data: type_specific_data, + }); + } + + ffi::libvlc_media_tracks_release(p_track, n); + Some(track) + } + } } impl Drop for Media { @@ -127,45 +185,43 @@ impl Drop for Media { } } -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] -pub struct MediaTrackInfo { +#[derive(Clone, PartialEq, Eq, Hash, Debug)] +pub struct MediaTrack { pub codec: u32, + pub original_fourcc: u32, pub id: i32, pub track_type: TrackType, - pub profile: i32, pub level: i32, + pub bitrate: u32, + pub language: Option, + pub description: Option, + pub type_specific_data: MediaTrackUnion, +} - audio: MediaTrackInfoAudio, - video: MediaTrackInfoVideo, +#[derive(Clone, PartialEq, Eq, Hash, Debug)] +pub enum MediaTrackUnion { + Audio(AudioTrack), Video(VideoTrack), Subtitle(SubtitleTrack), None, } #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] -pub struct MediaTrackInfoAudio { - pub channels: i32, - pub rate: i32, +pub struct AudioTrack { + pub channels: u32, + pub rate: u32, } #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] -pub struct MediaTrackInfoVideo { - pub height: i32, - pub width: i32, +pub struct VideoTrack { + pub height: u32, + pub width: u32, + pub sar_num: u32, + pub sar_den: u32, + pub frame_rate_num: u32, + pub frame_rate_den: u32, } -impl MediaTrackInfo { - pub fn audio(&self) -> Option { - if self.track_type == TrackType::Audio { - Some(self.audio) - }else{ - None - } - } - - pub fn video(&self) -> Option { - if self.track_type == TrackType::Video { - Some(self.video) - }else{ - None - } - } +#[derive(Clone, PartialEq, Eq, Hash, Debug)] +pub struct SubtitleTrack { + pub encoding: Option, } +