codec/subtitle: refactor Rect handling

This commit is contained in:
meh 2015-10-25 22:32:42 +01:00
parent 7ad3654976
commit 01b5f74fb0
3 changed files with 376 additions and 160 deletions

View File

@ -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::<AVSubtitleRect>() 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<usize>) {
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<<Self as Iterator>::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<usize>) {
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> { }

150
src/codec/subtitle/rect.rs Normal file
View File

@ -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())
}
}
}

View File

@ -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
}
}