util/frame: add Frame, frame::Video and frame::Audio
This commit is contained in:
parent
1a9ca7a4a0
commit
2ff14a2043
@ -12,5 +12,4 @@ pub use util::rational::Rational;
|
|||||||
pub use util::color_space::ColorSpace;
|
pub use util::color_space::ColorSpace;
|
||||||
pub use util::color_range::ColorRange;
|
pub use util::color_range::ColorRange;
|
||||||
pub use util::media;
|
pub use util::media;
|
||||||
pub use util::sample_format::SampleFormat;
|
pub use util::frame::{self, Frame};
|
||||||
pub use util::pixel_format::PixelFormat;
|
|
||||||
|
273
src/util/frame/mod.rs
Normal file
273
src/util/frame/mod.rs
Normal file
@ -0,0 +1,273 @@
|
|||||||
|
pub mod side_data;
|
||||||
|
pub use self::side_data::SideData;
|
||||||
|
|
||||||
|
use libc::c_int;
|
||||||
|
use std::ptr;
|
||||||
|
use std::mem;
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
use ffi::*;
|
||||||
|
use ::{Dictionary, ColorSpace, ColorRange};
|
||||||
|
use ::util::pixel_format::PixelFormat;
|
||||||
|
use ::util::sample_format::SampleFormat;
|
||||||
|
|
||||||
|
pub struct Packet {
|
||||||
|
pub duration: isize,
|
||||||
|
pub position: isize,
|
||||||
|
pub size: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Frame {
|
||||||
|
pub ptr: *mut AVFrame,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Frame {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
unsafe {
|
||||||
|
Frame { ptr: av_frame_alloc() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn make_unique(&mut self) -> &mut Self {
|
||||||
|
unsafe {
|
||||||
|
av_frame_make_writable(self.ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_unique(&self) -> bool {
|
||||||
|
unsafe {
|
||||||
|
av_frame_is_writable(self.ptr) == 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_key(&self) -> bool {
|
||||||
|
unsafe {
|
||||||
|
(*self.ptr).key_frame == 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn packet(&self) -> Packet {
|
||||||
|
unsafe {
|
||||||
|
Packet {
|
||||||
|
duration: av_frame_get_pkt_duration(self.ptr) as isize,
|
||||||
|
position: av_frame_get_pkt_pos(self.ptr) as isize,
|
||||||
|
size: av_frame_get_pkt_size(self.ptr) as usize,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn best_effort_timestamp(&self) -> isize {
|
||||||
|
unsafe {
|
||||||
|
av_frame_get_best_effort_timestamp(self.ptr) as isize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn metadata<'a>(&'a self) -> Dictionary<'a> {
|
||||||
|
unsafe {
|
||||||
|
Dictionary::wrap(av_frame_get_metadata(self.ptr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_metadata(&mut self, mut value: Dictionary) {
|
||||||
|
unsafe {
|
||||||
|
av_frame_set_metadata(self.ptr, value.take());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn side_data<'a>(&'a self, kind: side_data::Type) -> Option<SideData<'a>> {
|
||||||
|
unsafe {
|
||||||
|
let ptr = av_frame_get_side_data(self.ptr, kind.into());
|
||||||
|
|
||||||
|
if ptr == ptr::null_mut() {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Some(SideData::wrap(ptr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_side_data<'a>(&'a mut self, kind: side_data::Type, size: usize) -> Option<SideData<'a>> {
|
||||||
|
unsafe {
|
||||||
|
let ptr = av_frame_new_side_data(self.ptr, kind.into(), size as c_int);
|
||||||
|
|
||||||
|
if ptr == ptr::null_mut() {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Some(SideData::wrap(ptr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove_side_data(&mut self, kind: side_data::Type) {
|
||||||
|
unsafe {
|
||||||
|
av_frame_remove_side_data(self.ptr, kind.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for Frame {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
unsafe {
|
||||||
|
Frame { ptr: av_frame_clone(self.ptr) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clone_from(&mut self, source: &Self) {
|
||||||
|
unsafe {
|
||||||
|
av_frame_copy(self.ptr, source.ptr);
|
||||||
|
av_frame_copy_props(self.ptr, source.ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for Frame {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
av_frame_free(&mut self.ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Audio(Frame);
|
||||||
|
|
||||||
|
impl Audio {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Audio(Frame::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn format(&self) -> SampleFormat {
|
||||||
|
unsafe {
|
||||||
|
SampleFormat::from(mem::transmute::<_, AVSampleFormat>(((*self.ptr).format)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn channel_layout(&self) -> i64 {
|
||||||
|
unsafe {
|
||||||
|
av_frame_get_channel_layout(self.0.ptr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_channel_layout(&mut self, value: i64) {
|
||||||
|
unsafe {
|
||||||
|
av_frame_set_channel_layout(self.0.ptr, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn channels(&self) -> usize {
|
||||||
|
unsafe {
|
||||||
|
av_frame_get_channels(self.0.ptr) as usize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_channels(&mut self, value: usize) {
|
||||||
|
unsafe {
|
||||||
|
av_frame_set_channels(self.0.ptr, value as c_int);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sample_rate(&self) -> i32 {
|
||||||
|
unsafe {
|
||||||
|
av_frame_get_sample_rate(self.0.ptr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_sample_rate(&mut self, value: i32) {
|
||||||
|
unsafe {
|
||||||
|
av_frame_set_sample_rate(self.0.ptr, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for Audio {
|
||||||
|
type Target = Frame;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Frame {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<Frame> for Audio {
|
||||||
|
fn into(self) -> Frame {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<Audio> for Frame {
|
||||||
|
fn into(self) -> Audio {
|
||||||
|
Audio(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Video(Frame);
|
||||||
|
|
||||||
|
impl Deref for Video {
|
||||||
|
type Target = Frame;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Frame {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Video {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Video(Frame::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn format(&self) -> PixelFormat {
|
||||||
|
unsafe {
|
||||||
|
PixelFormat::from(mem::transmute::<_, AVPixelFormat>(((*self.ptr).format)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn width(&self) -> usize {
|
||||||
|
unsafe {
|
||||||
|
(*self.0.ptr).width as usize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn height(&self) -> usize {
|
||||||
|
unsafe {
|
||||||
|
(*self.0.ptr).height as usize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn color_space(&self) -> ColorSpace {
|
||||||
|
unsafe {
|
||||||
|
ColorSpace::from(av_frame_get_colorspace(self.0.ptr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_color_space(&mut self, value: ColorSpace) {
|
||||||
|
unsafe {
|
||||||
|
av_frame_set_colorspace(self.0.ptr, value.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn color_range(&self) -> ColorRange {
|
||||||
|
unsafe {
|
||||||
|
ColorRange::from(av_frame_get_color_range(self.0.ptr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_color_range(&mut self, value: ColorRange) {
|
||||||
|
unsafe {
|
||||||
|
av_frame_set_color_range(self.0.ptr, value.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<Video> for Frame {
|
||||||
|
fn into(self) -> Video {
|
||||||
|
Video(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<Frame> for Video {
|
||||||
|
fn into(self) -> Frame {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
97
src/util/frame/side_data.rs
Normal file
97
src/util/frame/side_data.rs
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
use std::marker::PhantomData;
|
||||||
|
use std::slice;
|
||||||
|
use std::ffi::CStr;
|
||||||
|
use std::str::from_utf8_unchecked;
|
||||||
|
|
||||||
|
use ffi::*;
|
||||||
|
use super::Frame;
|
||||||
|
use ::Dictionary;
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
|
||||||
|
pub enum Type {
|
||||||
|
PanScan,
|
||||||
|
A53CC,
|
||||||
|
Stereo3D,
|
||||||
|
MatrixEncoding,
|
||||||
|
DownMixInfo,
|
||||||
|
ReplayGain,
|
||||||
|
DisplayMatrix,
|
||||||
|
AFD,
|
||||||
|
MotionVectors,
|
||||||
|
SkipSamples,
|
||||||
|
AudioServiceType,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Type {
|
||||||
|
pub fn name(&self) -> &'static str {
|
||||||
|
unsafe {
|
||||||
|
from_utf8_unchecked(CStr::from_ptr(av_frame_side_data_name((*self).into())).to_bytes())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<AVFrameSideDataType> for Type {
|
||||||
|
fn from(value: AVFrameSideDataType) -> Self {
|
||||||
|
match value {
|
||||||
|
AV_FRAME_DATA_PANSCAN => Type::PanScan,
|
||||||
|
AV_FRAME_DATA_A53_CC => Type::A53CC,
|
||||||
|
AV_FRAME_DATA_STEREO3D => Type::Stereo3D,
|
||||||
|
AV_FRAME_DATA_MATRIXENCODING => Type::MatrixEncoding,
|
||||||
|
AV_FRAME_DATA_DOWNMIX_INFO => Type::DownMixInfo,
|
||||||
|
AV_FRAME_DATA_REPLAYGAIN => Type::ReplayGain,
|
||||||
|
AV_FRAME_DATA_DISPLAYMATRIX => Type::DisplayMatrix,
|
||||||
|
AV_FRAME_DATA_AFD => Type::AFD,
|
||||||
|
AV_FRAME_DATA_MOTION_VECTORS => Type::MotionVectors,
|
||||||
|
AV_FRAME_DATA_SKIP_SAMPLES => Type::SkipSamples,
|
||||||
|
AV_FRAME_DATA_AUDIO_SERVICE_TYPE => Type::AudioServiceType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<AVFrameSideDataType> for Type {
|
||||||
|
fn into(self) -> AVFrameSideDataType {
|
||||||
|
match self {
|
||||||
|
Type::PanScan => AV_FRAME_DATA_PANSCAN,
|
||||||
|
Type::A53CC => AV_FRAME_DATA_A53_CC,
|
||||||
|
Type::Stereo3D => AV_FRAME_DATA_STEREO3D,
|
||||||
|
Type::MatrixEncoding => AV_FRAME_DATA_MATRIXENCODING,
|
||||||
|
Type::DownMixInfo => AV_FRAME_DATA_DOWNMIX_INFO,
|
||||||
|
Type::ReplayGain => AV_FRAME_DATA_REPLAYGAIN,
|
||||||
|
Type::DisplayMatrix => AV_FRAME_DATA_DISPLAYMATRIX,
|
||||||
|
Type::AFD => AV_FRAME_DATA_AFD,
|
||||||
|
Type::MotionVectors => AV_FRAME_DATA_MOTION_VECTORS,
|
||||||
|
Type::SkipSamples => AV_FRAME_DATA_SKIP_SAMPLES,
|
||||||
|
Type::AudioServiceType => AV_FRAME_DATA_AUDIO_SERVICE_TYPE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SideData<'a> {
|
||||||
|
pub ptr: *mut AVFrameSideData,
|
||||||
|
|
||||||
|
_marker: PhantomData<&'a Frame>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> SideData<'a> {
|
||||||
|
pub fn wrap(ptr: *mut AVFrameSideData) -> 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn metadata(&'a self) -> Dictionary<'a> {
|
||||||
|
unsafe {
|
||||||
|
Dictionary::wrap((*self.ptr).metadata)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,7 @@ pub mod color_space;
|
|||||||
pub mod color_range;
|
pub mod color_range;
|
||||||
pub mod sample_format;
|
pub mod sample_format;
|
||||||
pub mod pixel_format;
|
pub mod pixel_format;
|
||||||
|
pub mod frame;
|
||||||
|
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::str::from_utf8_unchecked;
|
use std::str::from_utf8_unchecked;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user