From 01b5f74fb08be156a1634719a88312697351b374 Mon Sep 17 00:00:00 2001 From: meh Date: Sun, 25 Oct 2015 22:32:42 +0100 Subject: [PATCH] codec/subtitle: refactor Rect handling --- src/codec/subtitle/mod.rs | 213 ++++++++------------------------- src/codec/subtitle/rect.rs | 150 +++++++++++++++++++++++ src/codec/subtitle/rect_mut.rs | 173 ++++++++++++++++++++++++++ 3 files changed, 376 insertions(+), 160 deletions(-) create mode 100644 src/codec/subtitle/rect.rs create mode 100644 src/codec/subtitle/rect_mut.rs diff --git a/src/codec/subtitle/mod.rs b/src/codec/subtitle/mod.rs index b26c87b..612aa19 100644 --- a/src/codec/subtitle/mod.rs +++ b/src/codec/subtitle/mod.rs @@ -1,17 +1,17 @@ pub mod flag; pub use self::flag::Flags; +mod rect; +pub use self::rect::{Rect, Bitmap, Text, Ass}; + +mod rect_mut; +pub use self::rect_mut::{RectMut, BitmapMut, TextMut, AssMut}; + use std::marker::PhantomData; use std::mem; -use std::ptr; -use std::ffi::CStr; -use std::str::from_utf8_unchecked; -use std::ops::Deref; -use libc::{c_uint, uint32_t}; +use libc::{c_uint, uint32_t, size_t}; use ffi::*; -use ::format; -use ::Picture; #[derive(Eq, PartialEq, Clone, Copy, Debug)] pub enum Type { @@ -92,6 +92,26 @@ impl Subtitle { pub fn rects(&self) -> RectIter { RectIter::new(&self.0) } + + pub fn rects_mut(&mut self) -> RectMutIter { + RectMutIter::new(&mut self.0) + } + + pub fn add_rect(&mut self, kind: Type) -> RectMut { + unsafe { + self.0.num_rects += 1; + self.0.rects = av_realloc(self.0.rects as *mut _, + (mem::size_of::<*const AVSubtitleRect>() * self.0.num_rects as usize) as size_t) + as *mut _; + + let mut rect = av_mallocz(mem::size_of::() as size_t) as *mut AVSubtitleRect; + (*rect).kind = kind.into(); + + *self.0.rects.offset((self.0.num_rects - 1) as isize) = rect; + + RectMut::wrap(rect) + } + } } pub struct RectIter<'a> { @@ -124,177 +144,50 @@ impl<'a> Iterator for RectIter<'a> { fn size_hint(&self) -> (usize, Option) { unsafe { - ((*self.ptr).num_rects as usize, Some((*self.ptr).num_rects as usize)) + let length = (*self.ptr).num_rects as usize; + + (length - self.cur as usize, Some(length - self.cur as usize)) } } } impl<'a> ExactSizeIterator for RectIter<'a> { } -pub enum Rect<'a> { - None, - Bitmap(Bitmap<'a>), - Text(Text<'a>), - Ass(Ass<'a>), +pub struct RectMutIter<'a> { + ptr: *mut AVSubtitle, + cur: c_uint, + + _marker: PhantomData<&'a Subtitle>, } -impl<'a> Rect<'a> { - pub unsafe fn wrap(ptr: *mut AVSubtitleRect) -> Self { - match Type::from((*ptr).kind) { - Type::None => Rect::None, - Type::Bitmap => Rect::Bitmap(Bitmap::wrap(ptr)), - Type::Text => Rect::Text(Text::wrap(ptr)), - Type::Ass => Rect::Ass(Ass::wrap(ptr)) - } - } - - pub unsafe fn as_ptr(&self) -> *const AVSubtitleRect { - match self { - &Rect::None => ptr::null(), - &Rect::Bitmap(ref b) => b.as_ptr(), - &Rect::Text(ref t) => t.as_ptr(), - &Rect::Ass(ref a) => a.as_ptr() - } - } - - pub unsafe fn as_mut_ptr(&mut self) -> *mut AVSubtitleRect { - match self { - &mut Rect::None => ptr::null_mut(), - &mut Rect::Bitmap(ref mut b) => b.as_mut_ptr(), - &mut Rect::Text(ref mut t) => t.as_mut_ptr(), - &mut Rect::Ass(ref mut a) => a.as_mut_ptr() - } +impl<'a> RectMutIter<'a> { + pub fn new(ptr: *mut AVSubtitle) -> Self { + RectMutIter { ptr: ptr, cur: 0, _marker: PhantomData } } } -impl<'a> Rect<'a> { - pub fn flags(&self) -> Flags { +impl<'a> Iterator for RectMutIter<'a> { + type Item = RectMut<'a>; + + fn next(&mut self) -> Option<::Item> { unsafe { - Flags::from_bits_truncate(match self { - &Rect::None => 0, - &Rect::Bitmap(ref b) => (*b.as_ptr()).flags, - &Rect::Text(ref t) => (*t.as_ptr()).flags, - &Rect::Ass(ref a) => (*a.as_ptr()).flags - }) + if self.cur >= (*self.ptr).num_rects { + None + } + else { + self.cur += 1; + Some(RectMut::wrap(*(*self.ptr).rects.offset((self.cur - 1) as isize))) + } } } -} -pub struct Bitmap<'a> { - ptr: *mut AVSubtitleRect, - - _marker: PhantomData<&'a ()>, -} - -impl<'a> Bitmap<'a> { - pub unsafe fn wrap(ptr: *mut AVSubtitleRect) -> Self { - Bitmap { ptr: ptr, _marker: PhantomData } - } - - pub unsafe fn as_ptr(&self) -> *const AVSubtitleRect { - self.ptr as *const _ - } - - pub unsafe fn as_mut_ptr(&mut self) -> *mut AVSubtitleRect { - self.ptr - } -} - -impl<'a> Bitmap<'a> { - pub fn x(&self) -> usize { + fn size_hint(&self) -> (usize, Option) { unsafe { - (*self.as_ptr()).x as usize - } - } + let length = (*self.ptr).num_rects as usize; - pub fn y(&self) -> usize { - unsafe { - (*self.as_ptr()).y as usize - } - } - - pub fn width(&self) -> u32 { - unsafe { - (*self.as_ptr()).w as u32 - } - } - - pub fn height(&self) -> u32 { - unsafe { - (*self.as_ptr()).h as u32 - } - } - - pub fn colors(&self) -> usize { - unsafe { - (*self.as_ptr()).nb_colors as usize - } - } - - // XXX: verify safety - pub fn picture(&self, format: format::Pixel) -> Picture<'a> { - unsafe { - Picture::wrap(&(*self.as_ptr()).pict as *const _ as *mut _, format, (*self.as_ptr()).w as u32, (*self.as_ptr()).h as u32) + (length - self.cur as usize, Some(length - self.cur as usize)) } } } -pub struct Text<'a> { - ptr: *mut AVSubtitleRect, - - _marker: PhantomData<&'a ()>, -} - -impl<'a> Text<'a> { - pub unsafe fn wrap(ptr: *mut AVSubtitleRect) -> Self { - Text { ptr: ptr, _marker: PhantomData } - } - - pub unsafe fn as_ptr(&self) -> *const AVSubtitleRect { - self.ptr as *const _ - } - - pub unsafe fn as_mut_ptr(&mut self) -> *mut AVSubtitleRect { - self.ptr - } -} - -impl<'a> Deref for Text<'a> { - type Target = str; - - fn deref<'b>(&'b self) -> &'b str { - unsafe { - from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).text).to_bytes()) - } - } -} - -pub struct Ass<'a> { - ptr: *mut AVSubtitleRect, - - _marker: PhantomData<&'a ()>, -} - -impl<'a> Ass<'a> { - pub unsafe fn wrap(ptr: *mut AVSubtitleRect) -> Self { - Ass { ptr: ptr, _marker: PhantomData } - } - - pub unsafe fn as_ptr(&self) -> *const AVSubtitleRect { - self.ptr as *const _ - } - - pub unsafe fn as_mut_ptr(&mut self) -> *mut AVSubtitleRect { - self.ptr - } -} - -impl<'a> Deref for Ass<'a> { - type Target = str; - - fn deref<'b>(&'b self) -> &'b str { - unsafe { - from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).ass).to_bytes()) - } - } -} +impl<'a> ExactSizeIterator for RectMutIter<'a> { } diff --git a/src/codec/subtitle/rect.rs b/src/codec/subtitle/rect.rs new file mode 100644 index 0000000..c645dc6 --- /dev/null +++ b/src/codec/subtitle/rect.rs @@ -0,0 +1,150 @@ +use std::marker::PhantomData; +use std::ffi::CStr; +use std::str::from_utf8_unchecked; + +use ffi::*; +use super::{Type, Flags}; +use ::{format, Picture}; + +pub enum Rect<'a> { + None(*const AVSubtitleRect), + Bitmap(Bitmap<'a>), + Text(Text<'a>), + Ass(Ass<'a>), +} + +impl<'a> Rect<'a> { + pub unsafe fn wrap(ptr: *const AVSubtitleRect) -> Self { + match Type::from((*ptr).kind) { + Type::None => Rect::None(ptr), + Type::Bitmap => Rect::Bitmap(Bitmap::wrap(ptr)), + Type::Text => Rect::Text(Text::wrap(ptr)), + Type::Ass => Rect::Ass(Ass::wrap(ptr)) + } + } + + pub unsafe fn as_ptr(&self) -> *const AVSubtitleRect { + match self { + &Rect::None(ptr) => ptr, + &Rect::Bitmap(ref b) => b.as_ptr(), + &Rect::Text(ref t) => t.as_ptr(), + &Rect::Ass(ref a) => a.as_ptr() + } + } +} + +impl<'a> Rect<'a> { + pub fn flags(&self) -> Flags { + unsafe { + Flags::from_bits_truncate(match self { + &Rect::None(ptr) => (*ptr).flags, + &Rect::Bitmap(ref b) => (*b.as_ptr()).flags, + &Rect::Text(ref t) => (*t.as_ptr()).flags, + &Rect::Ass(ref a) => (*a.as_ptr()).flags + }) + } + } +} + +pub struct Bitmap<'a> { + ptr: *const AVSubtitleRect, + + _marker: PhantomData<&'a ()>, +} + +impl<'a> Bitmap<'a> { + pub unsafe fn wrap(ptr: *const AVSubtitleRect) -> Self { + Bitmap { ptr: ptr, _marker: PhantomData } + } + + pub unsafe fn as_ptr(&self) -> *const AVSubtitleRect { + self.ptr + } +} + +impl<'a> Bitmap<'a> { + pub fn x(&self) -> usize { + unsafe { + (*self.as_ptr()).x as usize + } + } + + pub fn y(&self) -> usize { + unsafe { + (*self.as_ptr()).y as usize + } + } + + pub fn width(&self) -> u32 { + unsafe { + (*self.as_ptr()).w as u32 + } + } + + pub fn height(&self) -> u32 { + unsafe { + (*self.as_ptr()).h as u32 + } + } + + pub fn colors(&self) -> usize { + unsafe { + (*self.as_ptr()).nb_colors as usize + } + } + + // XXX: must split Picture and PictureMut + pub fn picture(&self, format: format::Pixel) -> Picture<'a> { + unsafe { + Picture::wrap(&(*self.as_ptr()).pict as *const _ as *mut _, format, (*self.as_ptr()).w as u32, (*self.as_ptr()).h as u32) + } + } +} + +pub struct Text<'a> { + ptr: *const AVSubtitleRect, + + _marker: PhantomData<&'a ()>, +} + +impl<'a> Text<'a> { + pub unsafe fn wrap(ptr: *const AVSubtitleRect) -> Self { + Text { ptr: ptr, _marker: PhantomData } + } + + pub unsafe fn as_ptr(&self) -> *const AVSubtitleRect { + self.ptr + } +} + +impl<'a> Text<'a> { + pub fn get(&self) -> &str { + unsafe { + from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).text).to_bytes()) + } + } +} + +pub struct Ass<'a> { + ptr: *const AVSubtitleRect, + + _marker: PhantomData<&'a ()>, +} + +impl<'a> Ass<'a> { + pub unsafe fn wrap(ptr: *const AVSubtitleRect) -> Self { + Ass { ptr: ptr, _marker: PhantomData } + } + + pub unsafe fn as_ptr(&self) -> *const AVSubtitleRect { + self.ptr + } +} + +impl<'a> Ass<'a> { + pub fn get(&self) -> &str { + unsafe { + from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).ass).to_bytes()) + } + } +} diff --git a/src/codec/subtitle/rect_mut.rs b/src/codec/subtitle/rect_mut.rs new file mode 100644 index 0000000..934ad8e --- /dev/null +++ b/src/codec/subtitle/rect_mut.rs @@ -0,0 +1,173 @@ +use std::ops::Deref; +use std::ffi::CString; + +use libc::c_int; +use ffi::*; +use super::{Type, Flags, Bitmap, Text, Ass}; + +pub enum RectMut<'a> { + None(*mut AVSubtitleRect), + Bitmap(BitmapMut<'a>), + Text(TextMut<'a>), + Ass(AssMut<'a>), +} + +impl<'a> RectMut<'a> { + pub unsafe fn wrap(ptr: *mut AVSubtitleRect) -> Self { + match Type::from((*ptr).kind) { + Type::None => RectMut::None(ptr), + Type::Bitmap => RectMut::Bitmap(BitmapMut::wrap(ptr)), + Type::Text => RectMut::Text(TextMut::wrap(ptr)), + Type::Ass => RectMut::Ass(AssMut::wrap(ptr)) + } + } + + pub unsafe fn as_ptr(&self) -> *const AVSubtitleRect { + match self { + &RectMut::None(ptr) => ptr as *const _, + &RectMut::Bitmap(ref b) => b.as_ptr(), + &RectMut::Text(ref t) => t.as_ptr(), + &RectMut::Ass(ref a) => a.as_ptr() + } + } + + pub unsafe fn as_mut_ptr(&mut self) -> *mut AVSubtitleRect { + match self { + &mut RectMut::None(ptr) => ptr, + &mut RectMut::Bitmap(ref mut b) => b.as_mut_ptr(), + &mut RectMut::Text(ref mut t) => t.as_mut_ptr(), + &mut RectMut::Ass(ref mut a) => a.as_mut_ptr() + } + } +} + +impl<'a> RectMut<'a> { + pub fn flags(&self) -> Flags { + unsafe { + Flags::from_bits_truncate(match self { + &RectMut::None(ptr) => (*ptr).flags, + &RectMut::Bitmap(ref b) => (*b.as_ptr()).flags, + &RectMut::Text(ref t) => (*t.as_ptr()).flags, + &RectMut::Ass(ref a) => (*a.as_ptr()).flags + }) + } + } +} + +pub struct BitmapMut<'a> { + immutable: Bitmap<'a>, +} + +impl<'a> BitmapMut<'a> { + pub unsafe fn wrap(ptr: *mut AVSubtitleRect) -> Self { + BitmapMut { immutable: Bitmap::wrap(ptr as *const _) } + } + + pub unsafe fn as_mut_ptr(&mut self) -> *mut AVSubtitleRect { + self.as_ptr() as *mut _ + } +} + +impl<'a> BitmapMut<'a> { + pub fn set_x(&mut self, value: usize) { + unsafe { + (*self.as_mut_ptr()).x = value as c_int; + } + } + + pub fn set_y(&mut self, value: usize) { + unsafe { + (*self.as_mut_ptr()).y = value as c_int; + } + } + + pub fn set_width(&mut self, value: u32) { + unsafe { + (*self.as_mut_ptr()).w = value as c_int; + } + } + + pub fn set_height(&mut self, value: u32) { + unsafe { + (*self.as_mut_ptr()).h = value as c_int; + } + } + + pub fn set_colors(&mut self, value: usize) { + unsafe { + (*self.as_mut_ptr()).nb_colors = value as c_int; + } + } +} + +impl<'a> Deref for BitmapMut<'a> { + type Target = Bitmap<'a>; + + fn deref(&self) -> &Self::Target { + &self.immutable + } +} + +pub struct TextMut<'a> { + immutable: Text<'a>, +} + +impl<'a> TextMut<'a> { + pub unsafe fn wrap(ptr: *mut AVSubtitleRect) -> Self { + TextMut { immutable: Text::wrap(ptr as *const _) } + } + + pub unsafe fn as_mut_ptr(&mut self) -> *mut AVSubtitleRect { + self.as_ptr() as *mut _ + } +} + +impl<'a> TextMut<'a> { + pub fn set(&mut self, value: &str) { + let value = CString::new(value).unwrap(); + + unsafe { + (*self.as_mut_ptr()).text = av_strdup(value.as_ptr()); + } + } +} + +impl<'a> Deref for TextMut<'a> { + type Target = Text<'a>; + + fn deref(&self) -> &Self::Target { + &self.immutable + } +} + +pub struct AssMut<'a> { + immutable: Ass<'a>, +} + +impl<'a> AssMut<'a> { + pub unsafe fn wrap(ptr: *mut AVSubtitleRect) -> Self { + AssMut { immutable: Ass::wrap(ptr) } + } + + pub unsafe fn as_mut_ptr(&mut self) -> *mut AVSubtitleRect { + self.as_ptr() as *mut _ + } +} + +impl<'a> AssMut<'a> { + pub fn set(&mut self, value: &str) { + let value = CString::new(value).unwrap(); + + unsafe { + (*self.as_mut_ptr()).ass = av_strdup(value.as_ptr()); + } + } +} + +impl<'a> Deref for AssMut<'a> { + type Target = Ass<'a>; + + fn deref(&self) -> &Self::Target { + &self.immutable + } +}