From 72e300f09efe89a2232daa12a6180615d50ca246 Mon Sep 17 00:00:00 2001 From: meh Date: Tue, 12 May 2015 18:21:02 +0200 Subject: [PATCH] codec/subtitle: improve Subtitle handling --- src/codec/subtitle.rs | 221 ++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 +- 2 files changed, 222 insertions(+), 1 deletion(-) diff --git a/src/codec/subtitle.rs b/src/codec/subtitle.rs index 15876b7..3b2c359 100644 --- a/src/codec/subtitle.rs +++ b/src/codec/subtitle.rs @@ -1,6 +1,49 @@ +use std::marker::PhantomData; use std::mem; +use std::ffi::CStr; +use std::str::from_utf8_unchecked; +use std::ops::Deref; +use libc::{c_uint, uint32_t, int64_t}; use ffi::*; +use ::format; +use ::Picture; + +bitflags! { + flags Flags: i32 { + const FLAG_FORCED = AV_SUBTITLE_FLAG_FORCED, + } +} + +#[derive(Eq, PartialEq, Clone, Copy, Debug)] +pub enum Type { + None, + Bitmap, + Text, + Ass, +} + +impl From for Type { + fn from(value: AVSubtitleType) -> Type { + match value { + SUBTITLE_NONE => Type::None, + SUBTITLE_BITMAP => Type::Bitmap, + SUBTITLE_TEXT => Type::Text, + SUBTITLE_ASS => Type::Ass + } + } +} + +impl Into for Type { + fn into(self) -> AVSubtitleType { + match self { + Type::None => SUBTITLE_NONE, + Type::Bitmap => SUBTITLE_BITMAP, + Type::Text => SUBTITLE_TEXT, + Type::Ass => SUBTITLE_ASS + } + } +} pub struct Subtitle { pub val: AVSubtitle, @@ -12,4 +55,182 @@ impl Subtitle { Subtitle { val: mem::zeroed() } } } + + pub fn pts(&self) -> isize { + self.val.pts as isize + } + + pub fn set_pts(&mut self, value: isize) { + self.val.pts = value as int64_t; + } + + pub fn start(&self) -> usize { + self.val.start_display_time as usize + } + + pub fn set_start(&mut self, value: usize) { + self.val.start_display_time = value as uint32_t; + } + + pub fn end(&self) -> usize { + self.val.end_display_time as usize + } + + pub fn set_end(&mut self, value: usize) { + self.val.end_display_time = value as uint32_t; + } + + pub fn rects<'a>(&'a self) -> RectIter<'a> { + RectIter::new(&self.val) + } +} + +pub struct RectIter<'a> { + ptr: *const AVSubtitle, + cur: c_uint, + + _marker: PhantomData<&'a Subtitle>, +} + +impl<'a> RectIter<'a> { + pub fn new(ptr: *const AVSubtitle) -> Self { + RectIter { ptr: ptr, cur: 0, _marker: PhantomData } + } +} + +impl<'a> Iterator for RectIter<'a> { + type Item = Rect<'a>; + + fn next(&mut self) -> Option<::Item> { + unsafe { + if self.cur >= (*self.ptr).num_rects { + None + } + else { + self.cur += 1; + Rect::wrap(*(*self.ptr).rects.offset((self.cur - 1) as isize)) + } + } + } +} + +pub enum Rect<'a> { + Bitmap(Bitmap<'a>), + Text(Text<'a>), + Ass(Ass<'a>), +} + +impl<'a> Rect<'a> { + pub fn wrap(ptr: *mut AVSubtitleRect) -> Option { + unsafe { + match Type::from((*ptr).kind) { + Type::None => None, + Type::Bitmap => Some(Rect::Bitmap(Bitmap::wrap(ptr))), + Type::Text => Some(Rect::Text(Text::wrap(ptr))), + Type::Ass => Some(Rect::Ass(Ass::wrap(ptr))) + } + } + } + + pub fn flags(&self) -> Flags { + unsafe { + Flags::from_bits_truncate(match self { + &Rect::Bitmap(ref b) => (*b.ptr).flags, + &Rect::Text(ref t) => (*t.ptr).flags, + &Rect::Ass(ref a) => (*a.ptr).flags + }) + } + } +} + +pub struct Bitmap<'a> { + pub ptr: *mut AVSubtitleRect, + + _marker: PhantomData<&'a ()>, +} + +impl<'a> Bitmap<'a> { + pub fn wrap(ptr: *mut AVSubtitleRect) -> Self { + Bitmap { ptr: ptr, _marker: PhantomData } + } + + pub fn x(&self) -> usize { + unsafe { + (*self.ptr).x as usize + } + } + + pub fn y(&self) -> usize { + unsafe { + (*self.ptr).y as usize + } + } + + pub fn width(&self) -> usize { + unsafe { + (*self.ptr).w as usize + } + } + + pub fn height(&self) -> usize { + unsafe { + (*self.ptr).h as usize + } + } + + pub fn colors(&self) -> usize { + unsafe { + (*self.ptr).nb_colors as usize + } + } + + pub fn picture(&self, format: format::Pixel) -> Picture<'a> { + unsafe { + Picture::wrap(&mut (*self.ptr).pict, format, (*self.ptr).w as usize, (*self.ptr).h as usize) + } + } +} + +pub struct Text<'a> { + pub ptr: *mut AVSubtitleRect, + + _marker: PhantomData<&'a ()>, +} + +impl<'a> Text<'a> { + pub fn wrap(ptr: *mut AVSubtitleRect) -> Self { + Text { ptr: ptr, _marker: PhantomData } + } +} + +impl<'a> Deref for Text<'a> { + type Target = str; + + fn deref<'b>(&'b self) -> &'b str { + unsafe { + from_utf8_unchecked(CStr::from_ptr((*self.ptr).text).to_bytes()) + } + } +} + +pub struct Ass<'a> { + pub ptr: *mut AVSubtitleRect, + + _marker: PhantomData<&'a ()>, +} + +impl<'a> Ass<'a> { + pub fn wrap(ptr: *mut AVSubtitleRect) -> Self { + Ass { ptr: ptr, _marker: PhantomData } + } +} + +impl<'a> Deref for Ass<'a> { + type Target = str; + + fn deref<'b>(&'b self) -> &'b str { + unsafe { + from_utf8_unchecked(CStr::from_ptr((*self.ptr).ass).to_bytes()) + } + } } diff --git a/src/lib.rs b/src/lib.rs index bedf191..1990978 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,7 +20,7 @@ pub use format::stream::Stream; pub mod codec; pub use codec::packet::{self, Packet}; -pub use codec::subtitle::Subtitle; +pub use codec::subtitle::{self, Subtitle}; pub use codec::picture::Picture; pub use codec::discard::Discard; pub use codec::codec::Codec;