codec/context: make destructors safe
This commit is contained in:
parent
19548810dd
commit
9736980b02
@ -1,4 +1,5 @@
|
|||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
use libc::c_int;
|
use libc::c_int;
|
||||||
use ffi::*;
|
use ffi::*;
|
||||||
@ -9,16 +10,15 @@ use super::decoder::Decoder;
|
|||||||
use super::encoder::Encoder;
|
use super::encoder::Encoder;
|
||||||
|
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
ptr: *mut AVCodecContext,
|
ptr: *mut AVCodecContext,
|
||||||
|
owner: Option<Rc<Drop>>,
|
||||||
_own: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for Context { }
|
unsafe impl Send for Context { }
|
||||||
|
|
||||||
impl Context {
|
impl Context {
|
||||||
pub unsafe fn wrap(ptr: *mut AVCodecContext) -> Self {
|
pub unsafe fn wrap(ptr: *mut AVCodecContext, owner: Option<Rc<Drop>>) -> Self {
|
||||||
Context { ptr: ptr, _own: false }
|
Context { ptr: ptr, owner: owner }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn as_ptr(&self) -> *const AVCodecContext {
|
pub unsafe fn as_ptr(&self) -> *const AVCodecContext {
|
||||||
@ -33,7 +33,7 @@ impl Context {
|
|||||||
impl Context {
|
impl Context {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
unsafe {
|
unsafe {
|
||||||
Context { ptr: avcodec_alloc_context3(ptr::null()), _own: true }
|
Context { ptr: avcodec_alloc_context3(ptr::null()), owner: None }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,8 +107,8 @@ impl Context {
|
|||||||
|
|
||||||
impl Drop for Context {
|
impl Drop for Context {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if self._own {
|
unsafe {
|
||||||
unsafe {
|
if self.owner.is_none() {
|
||||||
avcodec_free_context(&mut self.as_mut_ptr());
|
avcodec_free_context(&mut self.as_mut_ptr());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
pub mod video;
|
pub mod video;
|
||||||
pub use self::video::Video;
|
pub use self::video::Encoder as Video;
|
||||||
|
|
||||||
pub mod audio;
|
pub mod audio;
|
||||||
pub use self::audio::Audio;
|
pub use self::audio::Encoder as Audio;
|
||||||
|
|
||||||
pub mod subtitle;
|
pub mod subtitle;
|
||||||
pub use self::subtitle::Subtitle;
|
pub use self::subtitle::Encoder as Subtitle;
|
||||||
|
|
||||||
pub mod motion_estimation;
|
pub mod motion_estimation;
|
||||||
pub use self::motion_estimation::MotionEstimation;
|
pub use self::motion_estimation::MotionEstimation;
|
||||||
@ -31,27 +31,27 @@ use ::media;
|
|||||||
pub struct Encoder(pub Context);
|
pub struct Encoder(pub Context);
|
||||||
|
|
||||||
impl Encoder {
|
impl Encoder {
|
||||||
pub fn video(self) -> Result<Video, Error> {
|
pub fn video(self) -> Result<video::Video, Error> {
|
||||||
if self.medium() == media::Type::Video {
|
if self.medium() == media::Type::Video {
|
||||||
Ok(Video(self))
|
Ok(video::Video(self))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Err(Error::InvalidData)
|
Err(Error::InvalidData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn audio(self) -> Result<Audio, Error> {
|
pub fn audio(self) -> Result<audio::Audio, Error> {
|
||||||
if self.medium() == media::Type::Audio {
|
if self.medium() == media::Type::Audio {
|
||||||
Ok(Audio(self))
|
Ok(audio::Audio(self))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Err(Error::InvalidData)
|
Err(Error::InvalidData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn subtitle(self) -> Result<Subtitle, Error> {
|
pub fn subtitle(self) -> Result<subtitle::Subtitle, Error> {
|
||||||
if self.medium() == media::Type::Subtitle {
|
if self.medium() == media::Type::Subtitle {
|
||||||
Ok(Subtitle(self))
|
Ok(subtitle::Subtitle(self))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Err(Error::InvalidData)
|
Err(Error::InvalidData)
|
||||||
|
@ -87,10 +87,6 @@ impl<'a> SideData<'a> {
|
|||||||
pub unsafe fn as_ptr(&self) -> *const AVPacketSideData {
|
pub unsafe fn as_ptr(&self) -> *const AVPacketSideData {
|
||||||
self.ptr as *const _
|
self.ptr as *const _
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn as_mut_ptr(&mut self) -> *mut AVPacketSideData {
|
|
||||||
self.ptr
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SideData<'a> {
|
impl<'a> SideData<'a> {
|
||||||
|
@ -1,19 +1,22 @@
|
|||||||
use std::marker::PhantomData;
|
use std::rc::Rc;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
use ffi::*;
|
use ffi::*;
|
||||||
use libc::{c_int, c_uint};
|
use libc::{c_int, c_uint};
|
||||||
use ::{media, Stream, StreamMut, DictionaryRef};
|
use ::{media, Stream, StreamMut, DictionaryRef};
|
||||||
|
use super::destructor::{self, Destructor};
|
||||||
|
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
ptr: *mut AVFormatContext,
|
ptr: *mut AVFormatContext,
|
||||||
|
dtor: Rc<Destructor>,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for Context { }
|
unsafe impl Send for Context { }
|
||||||
|
|
||||||
impl Context {
|
impl Context {
|
||||||
pub unsafe fn wrap(ptr: *mut AVFormatContext) -> Self {
|
pub unsafe fn wrap(ptr: *mut AVFormatContext, mode: destructor::Mode) -> Self {
|
||||||
Context { ptr: ptr }
|
Context { ptr: ptr, dtor: Rc::new(Destructor::new(ptr, mode)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn as_ptr(&self) -> *const AVFormatContext {
|
pub unsafe fn as_ptr(&self) -> *const AVFormatContext {
|
||||||
@ -23,6 +26,10 @@ impl Context {
|
|||||||
pub unsafe fn as_mut_ptr(&mut self) -> *mut AVFormatContext {
|
pub unsafe fn as_mut_ptr(&mut self) -> *mut AVFormatContext {
|
||||||
self.ptr
|
self.ptr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub unsafe fn destructor(&self) -> Rc<Destructor> {
|
||||||
|
self.dtor.clone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Context {
|
impl Context {
|
||||||
@ -32,7 +39,7 @@ impl Context {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Some(Stream::wrap(*(*self.as_ptr()).streams.offset(index as isize)))
|
Some(Stream::wrap(self, index))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -43,21 +50,17 @@ impl Context {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Some(StreamMut::wrap(*(*self.as_mut_ptr()).streams.offset(index as isize)))
|
Some(StreamMut::wrap(self, index))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn streams(&self) -> StreamIter {
|
pub fn streams(&self) -> StreamIter {
|
||||||
unsafe {
|
StreamIter::new(self)
|
||||||
StreamIter::new(self.as_ptr())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn streams_mut(&mut self) -> StreamIterMut {
|
pub fn streams_mut(&mut self) -> StreamIterMut {
|
||||||
unsafe {
|
StreamIterMut::new(self)
|
||||||
StreamIterMut::new(self.as_mut_ptr())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn metadata(&self) -> DictionaryRef {
|
pub fn metadata(&self) -> DictionaryRef {
|
||||||
@ -68,23 +71,19 @@ impl Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Best<'a> {
|
pub struct Best<'a> {
|
||||||
ptr: *const AVFormatContext,
|
context: &'a Context,
|
||||||
|
|
||||||
wanted: i32,
|
wanted: i32,
|
||||||
related: i32,
|
related: i32,
|
||||||
|
|
||||||
_marker: PhantomData<&'a ()>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Best<'a> {
|
impl<'a> Best<'a> {
|
||||||
pub unsafe fn new<'b>(ptr: *const AVFormatContext) -> Best<'b> {
|
pub unsafe fn new<'b, 'c: 'b>(context: &'c Context) -> Best<'b> {
|
||||||
Best {
|
Best {
|
||||||
ptr: ptr,
|
context: context,
|
||||||
|
|
||||||
wanted: -1,
|
wanted: -1,
|
||||||
related: -1,
|
related: -1,
|
||||||
|
|
||||||
_marker: PhantomData,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,12 +100,12 @@ impl<'a> Best<'a> {
|
|||||||
pub fn best<'b>(self, kind: media::Type) -> Option<Stream<'b>> where 'a: 'b {
|
pub fn best<'b>(self, kind: media::Type) -> Option<Stream<'b>> where 'a: 'b {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut decoder = ptr::null_mut();
|
let mut decoder = ptr::null_mut();
|
||||||
let index = av_find_best_stream(self.ptr,
|
let index = av_find_best_stream(self.context.as_ptr(),
|
||||||
kind.into(), self.wanted as c_int, self.related as c_int,
|
kind.into(), self.wanted as c_int, self.related as c_int,
|
||||||
&mut decoder, 0);
|
&mut decoder, 0);
|
||||||
|
|
||||||
if index >= 0 && !decoder.is_null() {
|
if index >= 0 && !decoder.is_null() {
|
||||||
Some(Stream::wrap(*(*self.ptr).streams.offset(index as isize)))
|
Some(Stream::wrap(self.context, index as usize))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
None
|
None
|
||||||
@ -116,34 +115,32 @@ impl<'a> Best<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct StreamIter<'a> {
|
pub struct StreamIter<'a> {
|
||||||
ptr: *const AVFormatContext,
|
context: &'a Context,
|
||||||
cur: c_uint,
|
current: c_uint,
|
||||||
|
|
||||||
_marker: PhantomData<&'a ()>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> StreamIter<'a> {
|
impl<'a> StreamIter<'a> {
|
||||||
pub fn new(ptr: *const AVFormatContext) -> Self {
|
pub fn new<'s, 'c: 's>(context: &'c Context) -> StreamIter<'s> {
|
||||||
StreamIter { ptr: ptr, cur: 0, _marker: PhantomData }
|
StreamIter { context: context, current: 0 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> StreamIter<'a> {
|
impl<'a> StreamIter<'a> {
|
||||||
pub fn wanted<'b: 'a, 'c: 'a>(&'a self, stream: &'b Stream) -> Best<'a> {
|
pub fn wanted<'b, 'c>(&self, stream: &'b Stream) -> Best<'c> where 'a: 'b, 'a: 'c {
|
||||||
unsafe {
|
unsafe {
|
||||||
Best::new(self.ptr).wanted(stream)
|
Best::new(self.context).wanted(stream)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn related<'b: 'a>(&'a self, stream: &'b Stream) -> Best<'a> {
|
pub fn related<'b, 'c>(&self, stream: &'b Stream) -> Best<'c> where 'a: 'b, 'a: 'c {
|
||||||
unsafe {
|
unsafe {
|
||||||
Best::new(self.ptr).related(stream)
|
Best::new(self.context).related(stream)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn best<'b: 'a>(&'a self, kind: media::Type) -> Option<Stream<'b>> {
|
pub fn best<'b>(&self, kind: media::Type) -> Option<Stream<'b>> where 'a: 'b {
|
||||||
unsafe {
|
unsafe {
|
||||||
Best::new(self.ptr).best(kind)
|
Best::new(self.context).best(kind)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -153,19 +150,21 @@ impl<'a> Iterator for StreamIter<'a> {
|
|||||||
|
|
||||||
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
|
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
|
||||||
unsafe {
|
unsafe {
|
||||||
if self.cur >= (*self.ptr).nb_streams {
|
if self.current >= (*self.context.as_ptr()).nb_streams {
|
||||||
None
|
return None;
|
||||||
}
|
|
||||||
else {
|
|
||||||
self.cur += 1;
|
|
||||||
Some(Stream::wrap(*(*self.ptr).streams.offset((self.cur - 1) as isize)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.current += 1;
|
||||||
|
|
||||||
|
Some(Stream::wrap(self.context, (self.current - 1) as usize))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
unsafe {
|
unsafe {
|
||||||
((*self.ptr).nb_streams as usize, Some((*self.ptr).nb_streams as usize))
|
let length = (*self.context.as_ptr()).nb_streams as usize;
|
||||||
|
|
||||||
|
(length - self.current as usize, Some(length - self.current as usize))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -173,15 +172,13 @@ impl<'a> Iterator for StreamIter<'a> {
|
|||||||
impl<'a> ExactSizeIterator for StreamIter<'a> { }
|
impl<'a> ExactSizeIterator for StreamIter<'a> { }
|
||||||
|
|
||||||
pub struct StreamIterMut<'a> {
|
pub struct StreamIterMut<'a> {
|
||||||
ptr: *const AVFormatContext,
|
context: &'a mut Context,
|
||||||
cur: c_uint,
|
current: c_uint,
|
||||||
|
|
||||||
_marker: PhantomData<&'a ()>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> StreamIterMut<'a> {
|
impl<'a> StreamIterMut<'a> {
|
||||||
pub fn new(ptr: *mut AVFormatContext) -> Self {
|
pub fn new<'s, 'c: 's>(context: &'c mut Context) -> StreamIterMut<'s> {
|
||||||
StreamIterMut { ptr: ptr, cur: 0, _marker: PhantomData }
|
StreamIterMut { context: context, current: 0 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,19 +187,21 @@ impl<'a> Iterator for StreamIterMut<'a> {
|
|||||||
|
|
||||||
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
|
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
|
||||||
unsafe {
|
unsafe {
|
||||||
if self.cur >= (*self.ptr).nb_streams {
|
if self.current >= (*self.context.as_ptr()).nb_streams {
|
||||||
None
|
return None
|
||||||
}
|
|
||||||
else {
|
|
||||||
self.cur += 1;
|
|
||||||
Some(StreamMut::wrap(*(*self.ptr).streams.offset((self.cur - 1) as isize)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.current += 1;
|
||||||
|
|
||||||
|
Some(StreamMut::wrap(mem::transmute_copy(&self.context), (self.current - 1) as usize))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
unsafe {
|
unsafe {
|
||||||
((*self.ptr).nb_streams as usize, Some((*self.ptr).nb_streams as usize))
|
let length = (*self.context.as_ptr()).nb_streams as usize;
|
||||||
|
|
||||||
|
(length - self.current as usize, Some(length - self.current as usize))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
35
src/format/context/destructor.rs
Normal file
35
src/format/context/destructor.rs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
use ffi::*;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub enum Mode {
|
||||||
|
Input,
|
||||||
|
Output,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Destructor {
|
||||||
|
ptr: *mut AVFormatContext,
|
||||||
|
mode: Mode,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Destructor {
|
||||||
|
pub unsafe fn new(ptr: *mut AVFormatContext, mode: Mode) -> Self {
|
||||||
|
Destructor {
|
||||||
|
ptr: ptr,
|
||||||
|
mode: mode,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for Destructor {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
match self.mode {
|
||||||
|
Mode::Input =>
|
||||||
|
avformat_close_input(&mut self.ptr),
|
||||||
|
|
||||||
|
Mode::Output =>
|
||||||
|
avformat_free_context(self.ptr),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,12 @@
|
|||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
use std::mem;
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
|
|
||||||
use ffi::*;
|
use ffi::*;
|
||||||
use ::{Error, Codec, Stream, Packet, format};
|
use ::{Error, Codec, Stream, Packet, format};
|
||||||
use super::common::Context;
|
use super::common::Context;
|
||||||
|
use super::destructor;
|
||||||
|
|
||||||
pub struct Input {
|
pub struct Input {
|
||||||
ptr: *mut AVFormatContext,
|
ptr: *mut AVFormatContext,
|
||||||
@ -15,7 +17,7 @@ unsafe impl Send for Input { }
|
|||||||
|
|
||||||
impl Input {
|
impl Input {
|
||||||
pub unsafe fn wrap(ptr: *mut AVFormatContext) -> Self {
|
pub unsafe fn wrap(ptr: *mut AVFormatContext) -> Self {
|
||||||
Input { ptr: ptr, ctx: Context::wrap(ptr) }
|
Input { ptr: ptr, ctx: Context::wrap(ptr, destructor::Mode::Input) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn as_ptr(&self) -> *const AVFormatContext {
|
pub unsafe fn as_ptr(&self) -> *const AVFormatContext {
|
||||||
@ -135,14 +137,6 @@ impl DerefMut for Input {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Input {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
unsafe {
|
|
||||||
avformat_close_input(&mut self.as_mut_ptr());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct PacketIter<'a> {
|
pub struct PacketIter<'a> {
|
||||||
context: &'a mut Input,
|
context: &'a mut Input,
|
||||||
}
|
}
|
||||||
@ -161,10 +155,11 @@ impl<'a> Iterator for PacketIter<'a> {
|
|||||||
|
|
||||||
loop {
|
loop {
|
||||||
match packet.read(self.context) {
|
match packet.read(self.context) {
|
||||||
Ok(..) =>
|
Ok(..) => unsafe {
|
||||||
return Some((unsafe {
|
return Some((
|
||||||
Stream::wrap(*(*self.context.as_ptr()).streams.offset(packet.stream() as isize))
|
Stream::wrap(mem::transmute_copy(&self.context), packet.stream()),
|
||||||
}, packet)),
|
packet));
|
||||||
|
},
|
||||||
|
|
||||||
Err(Error::Eof) =>
|
Err(Error::Eof) =>
|
||||||
return None,
|
return None,
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
pub mod destructor;
|
||||||
|
pub use self::destructor::Destructor;
|
||||||
|
|
||||||
pub mod input;
|
pub mod input;
|
||||||
pub use self::input::Input;
|
pub use self::input::Input;
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ use std::ffi::CString;
|
|||||||
use ffi::*;
|
use ffi::*;
|
||||||
use ::{Error, Codec, StreamMut, Dictionary, format};
|
use ::{Error, Codec, StreamMut, Dictionary, format};
|
||||||
use super::common::Context;
|
use super::common::Context;
|
||||||
|
use super::destructor;
|
||||||
|
|
||||||
pub struct Output {
|
pub struct Output {
|
||||||
ptr: *mut AVFormatContext,
|
ptr: *mut AVFormatContext,
|
||||||
@ -15,7 +16,7 @@ unsafe impl Send for Output { }
|
|||||||
|
|
||||||
impl Output {
|
impl Output {
|
||||||
pub unsafe fn wrap(ptr: *mut AVFormatContext) -> Self {
|
pub unsafe fn wrap(ptr: *mut AVFormatContext) -> Self {
|
||||||
Output { ptr: ptr, ctx: Context::wrap(ptr) }
|
Output { ptr: ptr, ctx: Context::wrap(ptr, destructor::Mode::Output) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn as_ptr(&self) -> *const AVFormatContext {
|
pub unsafe fn as_ptr(&self) -> *const AVFormatContext {
|
||||||
@ -74,7 +75,9 @@ impl Output {
|
|||||||
panic!("out of memory");
|
panic!("out of memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamMut::wrap(ptr)
|
let index = (*self.ctx.as_ptr()).nb_streams - 1;
|
||||||
|
|
||||||
|
StreamMut::wrap(&mut self.ctx, index as usize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,14 +102,6 @@ impl DerefMut for Output {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Output {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
unsafe {
|
|
||||||
avformat_free_context(self.as_mut_ptr());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn dump(ctx: &Output, index: i32, url: Option<&str>) {
|
pub fn dump(ctx: &Output, index: i32, url: Option<&str>) {
|
||||||
let url = url.map(|u| CString::new(u).unwrap());
|
let url = url.map(|u| CString::new(u).unwrap());
|
||||||
|
|
||||||
|
@ -1,33 +1,29 @@
|
|||||||
use std::marker::PhantomData;
|
|
||||||
|
|
||||||
use libc::c_int;
|
use libc::c_int;
|
||||||
use ffi::*;
|
use ffi::*;
|
||||||
use ::format;
|
|
||||||
use ::codec::{self, packet};
|
use ::codec::{self, packet};
|
||||||
use ::{Rational, Discard};
|
use ::{Rational, Discard};
|
||||||
use super::Disposition;
|
use super::Disposition;
|
||||||
|
use format::context::common::Context;
|
||||||
|
|
||||||
#[derive(Eq, PartialEq)]
|
|
||||||
pub struct Stream<'a> {
|
pub struct Stream<'a> {
|
||||||
ptr: *mut AVStream,
|
context: &'a Context,
|
||||||
|
index: usize,
|
||||||
_marker: PhantomData<&'a format::Context>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Stream<'a> {
|
impl<'a> Stream<'a> {
|
||||||
pub unsafe fn wrap(ptr: *mut AVStream) -> Self {
|
pub unsafe fn wrap(context: &Context, index: usize) -> Stream {
|
||||||
Stream { ptr: ptr, _marker: PhantomData }
|
Stream { context: context, index: index }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn as_ptr(&self) -> *const AVStream {
|
pub unsafe fn as_ptr(&self) -> *const AVStream {
|
||||||
self.ptr as *const _
|
*(*self.context.as_ptr()).streams.offset(self.index as isize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Stream<'a> {
|
impl<'a> Stream<'a> {
|
||||||
pub fn codec(&self) -> codec::Context {
|
pub fn codec(&self) -> codec::Context {
|
||||||
unsafe {
|
unsafe {
|
||||||
codec::Context::wrap((*self.as_ptr()).codec)
|
codec::Context::wrap((*self.as_ptr()).codec, Some(self.context.destructor()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,9 +70,7 @@ impl<'a> Stream<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn side_data(&self) -> SideDataIter {
|
pub fn side_data(&self) -> SideDataIter {
|
||||||
unsafe {
|
SideDataIter::new(self)
|
||||||
SideDataIter::new(self.as_ptr())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn frame_rate(&self) -> Rational {
|
pub fn frame_rate(&self) -> Rational {
|
||||||
@ -86,16 +80,24 @@ impl<'a> Stream<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SideDataIter<'a> {
|
impl<'a> PartialEq for Stream<'a> {
|
||||||
ptr: *const AVStream,
|
fn eq(&self, other: &Self) -> bool {
|
||||||
cur: c_int,
|
unsafe {
|
||||||
|
self.as_ptr() == other.as_ptr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_marker: PhantomData<&'a Stream<'a>>,
|
impl<'a> Eq for Stream<'a> { }
|
||||||
|
|
||||||
|
pub struct SideDataIter<'a> {
|
||||||
|
stream: &'a Stream<'a>,
|
||||||
|
current: c_int,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SideDataIter<'a> {
|
impl<'a> SideDataIter<'a> {
|
||||||
pub fn new(ptr: *const AVStream) -> Self {
|
pub fn new<'sd, 's: 'sd>(stream: &'s Stream) -> SideDataIter<'sd> {
|
||||||
SideDataIter { ptr: ptr, cur: 0, _marker: PhantomData }
|
SideDataIter { stream: stream, current: 0 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,19 +106,22 @@ impl<'a> Iterator for SideDataIter<'a> {
|
|||||||
|
|
||||||
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
|
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
|
||||||
unsafe {
|
unsafe {
|
||||||
if self.cur >= (*self.ptr).nb_side_data {
|
if self.current >= (*self.stream.as_ptr()).nb_side_data {
|
||||||
None
|
return None;
|
||||||
}
|
|
||||||
else {
|
|
||||||
self.cur += 1;
|
|
||||||
Some(packet::SideData::wrap((*self.ptr).side_data.offset((self.cur - 1) as isize)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.current += 1;
|
||||||
|
|
||||||
|
Some(packet::SideData::wrap(
|
||||||
|
(*self.stream.as_ptr()).side_data.offset((self.current - 1) as isize)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
unsafe {
|
unsafe {
|
||||||
((*self.ptr).nb_side_data as usize, Some((*self.ptr).nb_side_data as usize))
|
let length = (*self.stream.as_ptr()).nb_side_data as usize;
|
||||||
|
|
||||||
|
(length - self.current as usize, Some(length - self.current as usize))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,26 +1,30 @@
|
|||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
use ffi::*;
|
use ffi::*;
|
||||||
use ::Rational;
|
use ::Rational;
|
||||||
use super::Stream;
|
use super::Stream;
|
||||||
|
use format::context::common::Context;
|
||||||
|
|
||||||
#[derive(Eq, PartialEq)]
|
|
||||||
pub struct StreamMut<'a> {
|
pub struct StreamMut<'a> {
|
||||||
ptr: *mut AVStream,
|
context: &'a mut Context,
|
||||||
imm: Stream<'a>,
|
index: usize,
|
||||||
|
|
||||||
|
immutable: Stream<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> StreamMut<'a> {
|
impl<'a> StreamMut<'a> {
|
||||||
pub unsafe fn wrap(ptr: *mut AVStream) -> Self {
|
pub unsafe fn wrap(context: &mut Context, index: usize) -> StreamMut {
|
||||||
StreamMut { ptr: ptr, imm: Stream::wrap(ptr) }
|
StreamMut {
|
||||||
}
|
context: mem::transmute_copy(&context),
|
||||||
|
index: index,
|
||||||
|
|
||||||
pub unsafe fn as_ptr(&self) -> *const AVStream {
|
immutable: Stream::wrap(mem::transmute_copy(&context), index)
|
||||||
self.ptr as *const _
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn as_mut_ptr(&mut self) -> *mut AVStream {
|
pub unsafe fn as_mut_ptr(&mut self) -> *mut AVStream {
|
||||||
self.ptr
|
*(*self.context.as_mut_ptr()).streams.offset(self.index as isize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,6 +46,6 @@ impl<'a> Deref for StreamMut<'a> {
|
|||||||
type Target = Stream<'a>;
|
type Target = Stream<'a>;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.imm
|
&self.immutable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user