forked from mirrors/gstreamer-rs
Add bindings for VideoMeta and VideoOverlayCompositionMeta
This commit is contained in:
parent
cb23d20270
commit
62074ba1ed
3 changed files with 239 additions and 3 deletions
|
@ -60,6 +60,8 @@ mod video_rectangle;
|
||||||
pub use video_rectangle::*;
|
pub use video_rectangle::*;
|
||||||
mod video_overlay_composition;
|
mod video_overlay_composition;
|
||||||
pub use video_overlay_composition::*;
|
pub use video_overlay_composition::*;
|
||||||
|
mod video_meta;
|
||||||
|
pub use video_meta::*;
|
||||||
|
|
||||||
// Re-export all the traits in a prelude module, so that applications
|
// Re-export all the traits in a prelude module, so that applications
|
||||||
// can always "use gst::prelude::*" without getting conflicts
|
// can always "use gst::prelude::*" without getting conflicts
|
||||||
|
|
235
gstreamer-video/src/video_meta.rs
Normal file
235
gstreamer-video/src/video_meta.rs
Normal file
|
@ -0,0 +1,235 @@
|
||||||
|
// Copyright (C) 2018 Sebastian Dröge <sebastian@centricular.com>
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
use ffi;
|
||||||
|
use glib;
|
||||||
|
use glib::translate::{from_glib, ToGlib};
|
||||||
|
use glib_ffi;
|
||||||
|
use gst;
|
||||||
|
use gst::prelude::*;
|
||||||
|
use gst_ffi;
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct VideoMeta<'a>(ffi::GstVideoMeta, PhantomData<&'a ()>);
|
||||||
|
|
||||||
|
impl<'a> VideoMeta<'a> {
|
||||||
|
pub fn add(
|
||||||
|
buffer: &'a mut gst::BufferRef,
|
||||||
|
flags: ::VideoFrameFlags,
|
||||||
|
format: ::VideoFormat,
|
||||||
|
width: u32,
|
||||||
|
height: u32,
|
||||||
|
) -> gst::MetaRefMut<'a, Self, gst::meta::Standalone> {
|
||||||
|
let info = ::VideoInfo::new(format, width, height).build().unwrap();
|
||||||
|
assert!(buffer.get_size() >= info.size());
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let meta = ffi::gst_buffer_add_video_meta(
|
||||||
|
buffer.as_mut_ptr(),
|
||||||
|
flags.to_glib(),
|
||||||
|
format.to_glib(),
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
);
|
||||||
|
|
||||||
|
Self::from_mut_ptr(buffer.as_mut_ptr(), meta)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_full(
|
||||||
|
buffer: &'a mut gst::BufferRef,
|
||||||
|
flags: ::VideoFrameFlags,
|
||||||
|
format: ::VideoFormat,
|
||||||
|
width: u32,
|
||||||
|
height: u32,
|
||||||
|
n_planes: u32,
|
||||||
|
offset: [usize; 4],
|
||||||
|
stride: [i32; 4],
|
||||||
|
) -> gst::MetaRefMut<'a, Self, gst::meta::Standalone> {
|
||||||
|
let info = ::VideoInfo::new(format, width, height)
|
||||||
|
.offset(&offset)
|
||||||
|
.stride(&stride)
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
assert!(buffer.get_size() >= info.size());
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let meta = ffi::gst_buffer_add_video_meta_full(
|
||||||
|
buffer.as_mut_ptr(),
|
||||||
|
flags.to_glib(),
|
||||||
|
format.to_glib(),
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
n_planes,
|
||||||
|
offset.as_ptr() as *mut _,
|
||||||
|
stride.as_ptr() as *mut _,
|
||||||
|
);
|
||||||
|
|
||||||
|
Self::from_mut_ptr(buffer.as_mut_ptr(), meta)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_flags(&self) -> ::VideoFrameFlags {
|
||||||
|
from_glib(self.0.flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_format(&self) -> ::VideoFormat {
|
||||||
|
from_glib(self.0.format)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_id(&self) -> i32 {
|
||||||
|
self.0.id
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_width(&self) -> u32 {
|
||||||
|
self.0.width
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_height(&self) -> u32 {
|
||||||
|
self.0.height
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_n_planes(&self) -> u32 {
|
||||||
|
self.0.n_planes
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_offset(&self) -> &[usize] {
|
||||||
|
&self.0.offset[0..(self.0.n_planes as usize)]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_stride(&self) -> &[i32] {
|
||||||
|
&self.0.stride[0..(self.0.n_planes as usize)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<'a> MetaAPI for VideoMeta<'a> {
|
||||||
|
type GstType = ffi::GstVideoMeta;
|
||||||
|
|
||||||
|
fn get_meta_api() -> glib::Type {
|
||||||
|
unsafe { from_glib(ffi::gst_video_meta_api_get_type()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> fmt::Debug for VideoMeta<'a> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
f.debug_struct("VideoMeta")
|
||||||
|
.field("id", &self.get_id())
|
||||||
|
.field("flags", &self.get_flags())
|
||||||
|
.field("format", &self.get_format())
|
||||||
|
.field("width", &self.get_width())
|
||||||
|
.field("height", &self.get_height())
|
||||||
|
.field("n_planes", &self.get_n_planes())
|
||||||
|
.field("offset", &self.get_offset())
|
||||||
|
.field("stride", &self.get_stride())
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct VideoOverlayCompositionMeta<'a>(
|
||||||
|
ffi::GstVideoOverlayCompositionMeta,
|
||||||
|
PhantomData<&'a ()>,
|
||||||
|
);
|
||||||
|
|
||||||
|
impl<'a> VideoOverlayCompositionMeta<'a> {
|
||||||
|
pub fn add(
|
||||||
|
buffer: &'a mut gst::BufferRef,
|
||||||
|
overlay: ::VideoOverlayComposition,
|
||||||
|
) -> gst::MetaRefMut<'a, Self, gst::meta::Standalone> {
|
||||||
|
unsafe {
|
||||||
|
let meta = ffi::gst_buffer_add_video_overlay_composition_meta(
|
||||||
|
buffer.as_mut_ptr(),
|
||||||
|
overlay.as_mut_ptr(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Self::from_mut_ptr(buffer.as_mut_ptr(), meta)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_overlay(&self) -> &::VideoOverlayCompositionRef {
|
||||||
|
unsafe { ::VideoOverlayCompositionRef::from_ptr(self.0.overlay) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_overlay_mut(&mut self) -> Option<&mut ::VideoOverlayCompositionRef> {
|
||||||
|
unsafe {
|
||||||
|
if gst_ffi::gst_mini_object_is_writable(self.0.overlay as *const _) == glib_ffi::GFALSE
|
||||||
|
{
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(::VideoOverlayCompositionRef::from_mut_ptr(self.0.overlay))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_overlay(&mut self, overlay: ::VideoOverlayComposition) {
|
||||||
|
unsafe {
|
||||||
|
gst_ffi::gst_mini_object_unref(self.0.overlay as *mut _);
|
||||||
|
self.0.overlay = gst_ffi::gst_mini_object_ref(overlay.as_mut_ptr() as *mut _) as *mut _;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<'a> MetaAPI for VideoOverlayCompositionMeta<'a> {
|
||||||
|
type GstType = ffi::GstVideoOverlayCompositionMeta;
|
||||||
|
|
||||||
|
fn get_meta_api() -> glib::Type {
|
||||||
|
unsafe { from_glib(ffi::gst_video_overlay_composition_meta_api_get_type()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> fmt::Debug for VideoOverlayCompositionMeta<'a> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
f.debug_struct("VideoOverlayCompositionMeta")
|
||||||
|
.field("overlay", &self.get_overlay())
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_add_get_meta() {
|
||||||
|
gst::init().unwrap();
|
||||||
|
|
||||||
|
let mut buffer = gst::Buffer::with_size(320 * 240 * 4).unwrap();
|
||||||
|
{
|
||||||
|
let meta = VideoMeta::add(
|
||||||
|
buffer.get_mut().unwrap(),
|
||||||
|
::VideoFrameFlags::NONE,
|
||||||
|
::VideoFormat::Argb,
|
||||||
|
320,
|
||||||
|
240,
|
||||||
|
);
|
||||||
|
assert_eq!(meta.get_id(), 0);
|
||||||
|
assert_eq!(meta.get_flags(), ::VideoFrameFlags::NONE);
|
||||||
|
assert_eq!(meta.get_format(), ::VideoFormat::Argb);
|
||||||
|
assert_eq!(meta.get_width(), 320);
|
||||||
|
assert_eq!(meta.get_height(), 240);
|
||||||
|
assert_eq!(meta.get_n_planes(), 1);
|
||||||
|
assert_eq!(meta.get_offset(), &[0]);
|
||||||
|
assert_eq!(meta.get_stride(), &[320 * 4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let meta = buffer.get_meta::<VideoMeta>().unwrap();
|
||||||
|
assert_eq!(meta.get_id(), 0);
|
||||||
|
assert_eq!(meta.get_flags(), ::VideoFrameFlags::NONE);
|
||||||
|
assert_eq!(meta.get_format(), ::VideoFormat::Argb);
|
||||||
|
assert_eq!(meta.get_width(), 320);
|
||||||
|
assert_eq!(meta.get_height(), 240);
|
||||||
|
assert_eq!(meta.get_n_planes(), 1);
|
||||||
|
assert_eq!(meta.get_offset(), &[0]);
|
||||||
|
assert_eq!(meta.get_stride(), &[320 * 4]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,9 +13,7 @@ use gst;
|
||||||
use gst::miniobject::*;
|
use gst::miniobject::*;
|
||||||
|
|
||||||
use glib;
|
use glib;
|
||||||
use glib::translate::{
|
use glib::translate::{from_glib, from_glib_full, from_glib_none, ToGlib, ToGlibPtr};
|
||||||
from_glib, from_glib_full, from_glib_none, ToGlib, ToGlibPtr,
|
|
||||||
};
|
|
||||||
use glib_ffi;
|
use glib_ffi;
|
||||||
|
|
||||||
gst_define_mini_object_wrapper!(
|
gst_define_mini_object_wrapper!(
|
||||||
|
@ -45,6 +43,7 @@ impl VideoOverlayRectangle {
|
||||||
render_height: u32,
|
render_height: u32,
|
||||||
flags: ::VideoOverlayFormatFlags,
|
flags: ::VideoOverlayFormatFlags,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
assert!(buffer.get_meta::<::VideoMeta>().is_some());
|
||||||
unsafe {
|
unsafe {
|
||||||
from_glib_full(ffi::gst_video_overlay_rectangle_new_raw(
|
from_glib_full(ffi::gst_video_overlay_rectangle_new_raw(
|
||||||
buffer.as_mut_ptr(),
|
buffer.as_mut_ptr(),
|
||||||
|
|
Loading…
Reference in a new issue