From 42564d0d5e119307be2fac31faaf9aa9a2dd16d0 Mon Sep 17 00:00:00 2001 From: meh Date: Tue, 12 May 2015 03:44:45 +0200 Subject: [PATCH] codec/packet: add Packet and packet::SideData --- src/codec/mod.rs | 2 + src/codec/packet/mod.rs | 142 ++++++++++++++++++++++++++++++++++ src/codec/packet/side_data.rs | 95 +++++++++++++++++++++++ src/lib.rs | 1 + 4 files changed, 240 insertions(+) create mode 100644 src/codec/packet/mod.rs create mode 100644 src/codec/packet/side_data.rs diff --git a/src/codec/mod.rs b/src/codec/mod.rs index 5d1508b..c3befb2 100644 --- a/src/codec/mod.rs +++ b/src/codec/mod.rs @@ -1,6 +1,8 @@ pub mod id; pub use self::id::Id; +pub mod packet; + use std::ffi::CStr; use std::str::from_utf8_unchecked; diff --git a/src/codec/packet/mod.rs b/src/codec/packet/mod.rs new file mode 100644 index 0000000..b99b3a2 --- /dev/null +++ b/src/codec/packet/mod.rs @@ -0,0 +1,142 @@ +mod side_data; +pub use self::side_data::SideData; + +use std::marker::PhantomData; +use std::mem; +use libc::c_int; + +use ffi::*; + +bitflags! { + flags Flags: i32 { + const FLAG_KEY = AV_PKT_FLAG_KEY, + const FLAG_CORRUPT = AV_PKT_FLAG_CORRUPT, + } +} + +pub struct Packet { + pub val: AVPacket, +} + +impl Packet { + pub fn new() -> Self { + unsafe { + let mut pkt: AVPacket = mem::zeroed(); + + av_init_packet(&mut pkt); + + Packet { val: pkt } + } + } + + pub fn sized(size: usize) -> Self { + unsafe { + let mut pkt: AVPacket = mem::zeroed(); + + av_init_packet(&mut pkt); + av_new_packet(&mut pkt, size as c_int); + + Packet { val: pkt } + } + } + + pub fn shrink(&mut self, size: usize) { + unsafe { + av_shrink_packet(&mut self.val, size as c_int); + } + } + + pub fn grow(&mut self, size: usize) { + unsafe { + av_grow_packet(&mut self.val, size as c_int); + } + } + + pub fn flags(&self) -> Flags { + Flags::from_bits_truncate(self.val.flags) + } + + pub fn set_flags(&mut self, value: Flags) { + self.val.flags = value.bits(); + } + + pub fn pts(&self) -> isize { + self.val.pts as isize + } + + pub fn dts(&self) -> isize { + self.val.dts as isize + } + + pub fn size(&self) -> usize { + self.val.size as usize + } + + pub fn duration(&self) -> usize { + self.val.duration as usize + } + + pub fn position(&self) -> isize { + self.val.pos as isize + } + + pub fn convergence(&self) -> isize { + self.val.convergence_duration as isize + } + + pub fn side_data<'a>(&'a self) -> SideDataIter<'a> { + SideDataIter::new(&self.val) + } +} + +impl Clone for Packet { + fn clone(&self) -> Self { + let mut pkt = Packet::new(); + pkt.clone_from(self); + + pkt + } + + fn clone_from(&mut self, source: &Self) { + unsafe { + av_copy_packet(&mut self.val, &source.val); + } + } +} + +impl Drop for Packet { + fn drop(&mut self) { + unsafe { + av_free_packet(&mut self.val); + } + } +} + +pub struct SideDataIter<'a> { + ptr: *const AVPacket, + cur: c_int, + + _marker: PhantomData<&'a Packet>, +} + +impl<'a> SideDataIter<'a> { + pub fn new(ptr: *const AVPacket) -> Self { + SideDataIter { ptr: ptr, cur: 0, _marker: PhantomData } + } +} + +impl<'a> Iterator for SideDataIter<'a> { + type Item = SideData<'a>; + + fn next(&mut self) -> Option<::Item> { + unsafe { + if self.cur >= (*self.ptr).side_data_elems { + None + } + else { + self.cur += 1; + Some(SideData::wrap((*self.ptr).side_data.offset((self.cur - 1) as isize))) + } + } + } +} diff --git a/src/codec/packet/side_data.rs b/src/codec/packet/side_data.rs new file mode 100644 index 0000000..5884c4f --- /dev/null +++ b/src/codec/packet/side_data.rs @@ -0,0 +1,95 @@ +use std::marker::PhantomData; +use std::slice; + +use ffi::*; +use super::Packet; + +#[derive(Eq, PartialEq, Copy, Clone, Debug)] +pub enum Type { + Palette, + NewExtraData, + ParamChange, + H263MbInfo, + ReplayGain, + DisplayMatrix, + Stereo3d, + AudioServiceType, + SkipSamples, + JpDualMono, + StringsMetadata, + SubtitlePosition, + MatroskaBlockAdditional, + WebVTTIdentifier, + WebVTTSettings, + MetadataUpdate, +} + +impl From for Type { + fn from(value: AVPacketSideDataType) -> Self { + match value { + AV_PKT_DATA_PALETTE => Type::Palette, + AV_PKT_DATA_NEW_EXTRADATA => Type::NewExtraData, + AV_PKT_DATA_PARAM_CHANGE => Type::ParamChange, + AV_PKT_DATA_H263_MB_INFO => Type::H263MbInfo, + AV_PKT_DATA_REPLAYGAIN => Type::ReplayGain, + AV_PKT_DATA_DISPLAYMATRIX => Type::DisplayMatrix, + AV_PKT_DATA_STEREO3D => Type::Stereo3d, + AV_PKT_DATA_AUDIO_SERVICE_TYPE => Type::AudioServiceType, + AV_PKT_DATA_SKIP_SAMPLES => Type::SkipSamples, + AV_PKT_DATA_JP_DUALMONO => Type::JpDualMono, + AV_PKT_DATA_STRINGS_METADATA => Type::StringsMetadata, + AV_PKT_DATA_SUBTITLE_POSITION => Type::SubtitlePosition, + AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL => Type::MatroskaBlockAdditional, + AV_PKT_DATA_WEBVTT_IDENTIFIER => Type::WebVTTIdentifier, + AV_PKT_DATA_WEBVTT_SETTINGS => Type::WebVTTSettings, + AV_PKT_DATA_METADATA_UPDATE => Type::MetadataUpdate + } + } +} + +impl Into for Type { + fn into(self) -> AVPacketSideDataType { + match self { + Type::Palette => AV_PKT_DATA_PALETTE, + Type::NewExtraData => AV_PKT_DATA_NEW_EXTRADATA, + Type::ParamChange => AV_PKT_DATA_PARAM_CHANGE, + Type::H263MbInfo => AV_PKT_DATA_H263_MB_INFO, + Type::ReplayGain => AV_PKT_DATA_REPLAYGAIN, + Type::DisplayMatrix => AV_PKT_DATA_DISPLAYMATRIX, + Type::Stereo3d => AV_PKT_DATA_STEREO3D, + Type::AudioServiceType => AV_PKT_DATA_AUDIO_SERVICE_TYPE, + Type::SkipSamples => AV_PKT_DATA_SKIP_SAMPLES, + Type::JpDualMono => AV_PKT_DATA_JP_DUALMONO, + Type::StringsMetadata => AV_PKT_DATA_STRINGS_METADATA, + Type::SubtitlePosition => AV_PKT_DATA_SUBTITLE_POSITION, + Type::MatroskaBlockAdditional => AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, + Type::WebVTTIdentifier => AV_PKT_DATA_WEBVTT_IDENTIFIER, + Type::WebVTTSettings => AV_PKT_DATA_WEBVTT_SETTINGS, + Type::MetadataUpdate => AV_PKT_DATA_METADATA_UPDATE + } + } +} + +pub struct SideData<'a> { + ptr: *mut AVPacketSideData, + + _marker: PhantomData<&'a Packet> +} + +impl<'a> SideData<'a> { + pub fn wrap(ptr: *mut AVPacketSideData) -> Self { + SideData { ptr: ptr, _marker: PhantomData } + } + + pub fn kind(&self) -> Type { + unsafe { + Type::from((*self.ptr).kind) + } + } + + pub fn data(&'a self) -> &'a [u8] { + unsafe { + slice::from_raw_parts((*self.ptr).data, (*self.ptr).size as usize) + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 1ada8c7..89174a6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,3 +15,4 @@ pub use util::media; pub use util::frame::{self, Frame}; pub mod codec; +pub use codec::packet::{self, Packet};