mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2024-12-20 09:06:32 +00:00
Port everything else over to glib/gobject/gstreamer-sys
This commit is contained in:
parent
e4ababa98f
commit
24a10bb614
19 changed files with 509 additions and 751 deletions
|
@ -14,9 +14,9 @@ slog = { version = "1.3", features = ["max_level_trace"] }
|
||||||
lazy_static = "0.2"
|
lazy_static = "0.2"
|
||||||
byteorder = "1.0"
|
byteorder = "1.0"
|
||||||
num-rational = { version = "0.1", default-features = false, features = [] }
|
num-rational = { version = "0.1", default-features = false, features = [] }
|
||||||
glib-sys = "0.3"
|
glib-sys = { git = "https://github.com/gtk-rs/sys.git" }
|
||||||
gobject-sys = "0.3"
|
gobject-sys = { git = "https://github.com/gtk-rs/sys.git" }
|
||||||
gstreamer-sys = { git = "https://github.com/sdroege/gstreamer-sys.git" }
|
gstreamer-sys = { git = "https://github.com/sdroege/gstreamer-sys.git", features = ["v1_10"] }
|
||||||
derivative = "1.0"
|
derivative = "1.0"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
|
|
|
@ -14,7 +14,7 @@ fn main() {
|
||||||
let gstbase = pkg_config::probe_library("gstreamer-base-1.0").unwrap();
|
let gstbase = pkg_config::probe_library("gstreamer-base-1.0").unwrap();
|
||||||
let includes = [gstreamer.include_paths, gstbase.include_paths];
|
let includes = [gstreamer.include_paths, gstbase.include_paths];
|
||||||
|
|
||||||
let files = ["src/error.c", "src/log.c", "src/source.c", "src/sink.c", "src/demuxer.c"];
|
let files = ["src/source.c", "src/sink.c", "src/demuxer.c"];
|
||||||
|
|
||||||
let mut config = gcc::Config::new();
|
let mut config = gcc::Config::new();
|
||||||
config.include("src");
|
config.include("src");
|
||||||
|
|
|
@ -179,7 +179,10 @@ impl Adapter {
|
||||||
trace!(LOGGER, "Get buffer of {} bytes, copy into new buffer", size);
|
trace!(LOGGER, "Get buffer of {} bytes, copy into new buffer", size);
|
||||||
let mut new = Buffer::new_with_size(size).unwrap();
|
let mut new = Buffer::new_with_size(size).unwrap();
|
||||||
{
|
{
|
||||||
let mut map = new.get_mut().unwrap().map_readwrite().unwrap();
|
let mut map = new.get_mut()
|
||||||
|
.unwrap()
|
||||||
|
.map_readwrite()
|
||||||
|
.unwrap();
|
||||||
let data = map.as_mut_slice();
|
let data = map.as_mut_slice();
|
||||||
Self::copy_data(&self.deque, self.skip, data, size);
|
Self::copy_data(&self.deque, self.skip, data, size);
|
||||||
}
|
}
|
||||||
|
@ -204,7 +207,10 @@ impl Adapter {
|
||||||
|
|
||||||
let mut left = size;
|
let mut left = size;
|
||||||
while left > 0 {
|
while left > 0 {
|
||||||
let front_size = self.deque.front().unwrap().get_size() - self.skip;
|
let front_size = self.deque
|
||||||
|
.front()
|
||||||
|
.unwrap()
|
||||||
|
.get_size() - self.skip;
|
||||||
|
|
||||||
if front_size <= left {
|
if front_size <= left {
|
||||||
trace!(LOGGER,
|
trace!(LOGGER,
|
||||||
|
@ -234,15 +240,11 @@ impl Adapter {
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::os::raw::c_void;
|
use gst;
|
||||||
|
|
||||||
fn init() {
|
fn init() {
|
||||||
extern "C" {
|
|
||||||
fn gst_init(argc: *mut c_void, argv: *mut c_void);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
gst_init(ptr::null_mut(), ptr::null_mut());
|
gst::gst_init(ptr::null_mut(), ptr::null_mut());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
|
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::os::raw::c_void;
|
|
||||||
use std::slice;
|
use std::slice;
|
||||||
use std::u64;
|
use std::u64;
|
||||||
use std::usize;
|
use std::usize;
|
||||||
|
@ -54,22 +53,24 @@ pub struct ReadWriteMappedBuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl MiniObject for Buffer {
|
unsafe impl MiniObject for Buffer {
|
||||||
unsafe fn as_ptr(&self) -> *mut c_void {
|
type PtrType = gst::GstBuffer;
|
||||||
self.0 as *mut c_void
|
|
||||||
|
unsafe fn as_ptr(&self) -> *mut gst::GstBuffer {
|
||||||
|
self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn replace_ptr(&mut self, ptr: *mut c_void) {
|
unsafe fn replace_ptr(&mut self, ptr: *mut gst::GstBuffer) {
|
||||||
self.0 = ptr as *mut gst::GstBuffer
|
self.0 = ptr
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn new_from_ptr(ptr: *mut c_void) -> Self {
|
unsafe fn new_from_ptr(ptr: *mut gst::GstBuffer) -> Self {
|
||||||
Buffer(ptr as *mut gst::GstBuffer)
|
Buffer(ptr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Buffer {
|
impl Buffer {
|
||||||
pub fn new() -> GstRc<Buffer> {
|
pub fn new() -> GstRc<Buffer> {
|
||||||
unsafe { GstRc::new_from_owned_ptr(gst::gst_buffer_new() as *mut c_void) }
|
unsafe { GstRc::new_from_owned_ptr(gst::gst_buffer_new()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_with_size(size: usize) -> Option<GstRc<Buffer>> {
|
pub fn new_with_size(size: usize) -> Option<GstRc<Buffer>> {
|
||||||
|
@ -77,7 +78,7 @@ impl Buffer {
|
||||||
if raw.is_null() {
|
if raw.is_null() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(unsafe { GstRc::new_from_owned_ptr(raw as *mut c_void) })
|
Some(unsafe { GstRc::new_from_owned_ptr(raw) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,17 +106,13 @@ impl Buffer {
|
||||||
if raw.is_null() {
|
if raw.is_null() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(unsafe { GstRc::new_from_owned_ptr(raw as *mut c_void) })
|
Some(unsafe { GstRc::new_from_owned_ptr(raw) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn map_read(&self) -> Option<ReadBufferMap> {
|
pub fn map_read(&self) -> Option<ReadBufferMap> {
|
||||||
let mut map_info: gst::GstMapInfo = unsafe { mem::zeroed() };
|
let mut map_info: gst::GstMapInfo = unsafe { mem::zeroed() };
|
||||||
let res = unsafe {
|
let res = unsafe { gst::gst_buffer_map(self.0, &mut map_info, gst::GST_MAP_READ) };
|
||||||
gst::gst_buffer_map(self.0,
|
|
||||||
&mut map_info as *mut gst::GstMapInfo,
|
|
||||||
gst::GST_MAP_READ)
|
|
||||||
};
|
|
||||||
if res == glib::GTRUE {
|
if res == glib::GTRUE {
|
||||||
Some(ReadBufferMap {
|
Some(ReadBufferMap {
|
||||||
buffer: self,
|
buffer: self,
|
||||||
|
@ -128,11 +125,7 @@ impl Buffer {
|
||||||
|
|
||||||
pub fn map_readwrite(&mut self) -> Option<ReadWriteBufferMap> {
|
pub fn map_readwrite(&mut self) -> Option<ReadWriteBufferMap> {
|
||||||
let mut map_info: gst::GstMapInfo = unsafe { mem::zeroed() };
|
let mut map_info: gst::GstMapInfo = unsafe { mem::zeroed() };
|
||||||
let res = unsafe {
|
let res = unsafe { gst::gst_buffer_map(self.0, &mut map_info, gst::GST_MAP_READWRITE) };
|
||||||
gst::gst_buffer_map(self.0,
|
|
||||||
&mut map_info as *mut gst::GstMapInfo,
|
|
||||||
gst::GST_MAP_READWRITE)
|
|
||||||
};
|
|
||||||
if res == glib::GTRUE {
|
if res == glib::GTRUE {
|
||||||
Some(ReadWriteBufferMap {
|
Some(ReadWriteBufferMap {
|
||||||
buffer: self,
|
buffer: self,
|
||||||
|
@ -145,11 +138,7 @@ impl Buffer {
|
||||||
|
|
||||||
pub fn into_read_mapped_buffer(buffer: GstRc<Buffer>) -> Option<ReadMappedBuffer> {
|
pub fn into_read_mapped_buffer(buffer: GstRc<Buffer>) -> Option<ReadMappedBuffer> {
|
||||||
let mut map_info: gst::GstMapInfo = unsafe { mem::zeroed() };
|
let mut map_info: gst::GstMapInfo = unsafe { mem::zeroed() };
|
||||||
let res = unsafe {
|
let res = unsafe { gst::gst_buffer_map(buffer.0, &mut map_info, gst::GST_MAP_READ) };
|
||||||
gst::gst_buffer_map(buffer.0,
|
|
||||||
&mut map_info as *mut gst::GstMapInfo,
|
|
||||||
gst::GST_MAP_READ)
|
|
||||||
};
|
|
||||||
if res == glib::GTRUE {
|
if res == glib::GTRUE {
|
||||||
Some(ReadMappedBuffer {
|
Some(ReadMappedBuffer {
|
||||||
buffer: buffer,
|
buffer: buffer,
|
||||||
|
@ -162,11 +151,7 @@ impl Buffer {
|
||||||
|
|
||||||
pub fn into_readwrite_mapped_buffer(buffer: GstRc<Buffer>) -> Option<ReadWriteMappedBuffer> {
|
pub fn into_readwrite_mapped_buffer(buffer: GstRc<Buffer>) -> Option<ReadWriteMappedBuffer> {
|
||||||
let mut map_info: gst::GstMapInfo = unsafe { mem::zeroed() };
|
let mut map_info: gst::GstMapInfo = unsafe { mem::zeroed() };
|
||||||
let res = unsafe {
|
let res = unsafe { gst::gst_buffer_map(buffer.0, &mut map_info, gst::GST_MAP_READWRITE) };
|
||||||
gst::gst_buffer_map(buffer.0,
|
|
||||||
&mut map_info as *mut gst::GstMapInfo,
|
|
||||||
gst::GST_MAP_READWRITE)
|
|
||||||
};
|
|
||||||
if res == glib::GTRUE {
|
if res == glib::GTRUE {
|
||||||
Some(ReadWriteMappedBuffer {
|
Some(ReadWriteMappedBuffer {
|
||||||
buffer: buffer,
|
buffer: buffer,
|
||||||
|
@ -182,8 +167,7 @@ impl Buffer {
|
||||||
GstRc::new_from_owned_ptr(gst::gst_buffer_append(buffer.into_ptr() as
|
GstRc::new_from_owned_ptr(gst::gst_buffer_append(buffer.into_ptr() as
|
||||||
*mut gst::GstBuffer,
|
*mut gst::GstBuffer,
|
||||||
other.into_ptr() as
|
other.into_ptr() as
|
||||||
*mut gst::GstBuffer) as
|
*mut gst::GstBuffer))
|
||||||
*mut c_void)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,7 +181,7 @@ impl Buffer {
|
||||||
if raw.is_null() {
|
if raw.is_null() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(unsafe { GstRc::new_from_owned_ptr(raw as *mut c_void) })
|
Some(unsafe { GstRc::new_from_owned_ptr(raw) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,7 +370,7 @@ impl<'a> ReadBufferMap<'a> {
|
||||||
impl<'a> Drop for ReadBufferMap<'a> {
|
impl<'a> Drop for ReadBufferMap<'a> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
gst::gst_buffer_unmap(self.buffer.0, &mut self.map_info as *mut gst::GstMapInfo);
|
gst::gst_buffer_unmap(self.buffer.0, &mut self.map_info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -412,7 +396,7 @@ impl<'a> ReadWriteBufferMap<'a> {
|
||||||
impl<'a> Drop for ReadWriteBufferMap<'a> {
|
impl<'a> Drop for ReadWriteBufferMap<'a> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
gst::gst_buffer_unmap(self.buffer.0, &mut self.map_info as *mut gst::GstMapInfo);
|
gst::gst_buffer_unmap(self.buffer.0, &mut self.map_info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -435,7 +419,7 @@ impl Drop for ReadMappedBuffer {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if !self.buffer.0.is_null() {
|
if !self.buffer.0.is_null() {
|
||||||
unsafe {
|
unsafe {
|
||||||
gst::gst_buffer_unmap(self.buffer.0, &mut self.map_info as *mut gst::GstMapInfo);
|
gst::gst_buffer_unmap(self.buffer.0, &mut self.map_info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -466,7 +450,7 @@ impl Drop for ReadWriteMappedBuffer {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if !self.buffer.0.is_null() {
|
if !self.buffer.0.is_null() {
|
||||||
unsafe {
|
unsafe {
|
||||||
gst::gst_buffer_unmap(self.buffer.0, &mut self.map_info as *mut gst::GstMapInfo);
|
gst::gst_buffer_unmap(self.buffer.0, &mut self.map_info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,62 +6,52 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use libc::c_char;
|
|
||||||
use std::os::raw::c_void;
|
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use value::*;
|
use value::*;
|
||||||
use utils::*;
|
|
||||||
use miniobject::*;
|
use miniobject::*;
|
||||||
|
|
||||||
|
use glib;
|
||||||
|
use gobject;
|
||||||
|
use gst;
|
||||||
|
|
||||||
#[derive(Eq)]
|
#[derive(Eq)]
|
||||||
pub struct Caps(*mut c_void);
|
pub struct Caps(*mut gst::GstCaps);
|
||||||
|
|
||||||
unsafe impl MiniObject for Caps {
|
unsafe impl MiniObject for Caps {
|
||||||
unsafe fn as_ptr(&self) -> *mut c_void {
|
type PtrType = gst::GstCaps;
|
||||||
|
|
||||||
|
unsafe fn as_ptr(&self) -> *mut gst::GstCaps {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn replace_ptr(&mut self, ptr: *mut c_void) {
|
unsafe fn replace_ptr(&mut self, ptr: *mut gst::GstCaps) {
|
||||||
self.0 = ptr
|
self.0 = ptr
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn new_from_ptr(ptr: *mut c_void) -> Self {
|
unsafe fn new_from_ptr(ptr: *mut gst::GstCaps) -> Self {
|
||||||
Caps(ptr)
|
Caps(ptr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Caps {
|
impl Caps {
|
||||||
pub fn new_empty() -> GstRc<Self> {
|
pub fn new_empty() -> GstRc<Self> {
|
||||||
extern "C" {
|
unsafe { GstRc::new_from_owned_ptr(gst::gst_caps_new_empty()) }
|
||||||
fn gst_caps_new_empty() -> *mut c_void;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe { GstRc::new_from_owned_ptr(gst_caps_new_empty()) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_any() -> GstRc<Self> {
|
pub fn new_any() -> GstRc<Self> {
|
||||||
extern "C" {
|
unsafe { GstRc::new_from_owned_ptr(gst::gst_caps_new_any()) }
|
||||||
fn gst_caps_new_any() -> *mut c_void;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe { GstRc::new_from_owned_ptr(gst_caps_new_any()) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_simple(name: &str, values: &[(&str, &Value)]) -> GstRc<Self> {
|
pub fn new_simple(name: &str, values: &[(&str, &Value)]) -> GstRc<Self> {
|
||||||
extern "C" {
|
|
||||||
fn gst_caps_append_structure(caps: *mut c_void, structure: *mut c_void);
|
|
||||||
fn gst_structure_new_empty(name: *const c_char) -> *mut c_void;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut caps = Caps::new_empty();
|
let mut caps = Caps::new_empty();
|
||||||
|
|
||||||
let name_cstr = CString::new(name).unwrap();
|
let name_cstr = CString::new(name).unwrap();
|
||||||
let structure = unsafe { gst_structure_new_empty(name_cstr.as_ptr()) };
|
let structure = unsafe { gst::gst_structure_new_empty(name_cstr.as_ptr()) };
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
gst_caps_append_structure(caps.as_ptr(), structure);
|
gst::gst_caps_append_structure((*caps).0, structure);
|
||||||
}
|
}
|
||||||
|
|
||||||
caps.get_mut().unwrap().set_simple(values);
|
caps.get_mut().unwrap().set_simple(values);
|
||||||
|
@ -70,14 +60,10 @@ impl Caps {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_string(value: &str) -> Option<GstRc<Self>> {
|
pub fn from_string(value: &str) -> Option<GstRc<Self>> {
|
||||||
extern "C" {
|
|
||||||
fn gst_caps_from_string(value: *const c_char) -> *mut c_void;
|
|
||||||
}
|
|
||||||
|
|
||||||
let value_cstr = CString::new(value).unwrap();
|
let value_cstr = CString::new(value).unwrap();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let caps_ptr = gst_caps_from_string(value_cstr.as_ptr());
|
let caps_ptr = gst::gst_caps_from_string(value_cstr.as_ptr());
|
||||||
|
|
||||||
if caps_ptr.is_null() {
|
if caps_ptr.is_null() {
|
||||||
None
|
None
|
||||||
|
@ -88,30 +74,21 @@ impl Caps {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_simple(&mut self, values: &[(&str, &Value)]) {
|
pub fn set_simple(&mut self, values: &[(&str, &Value)]) {
|
||||||
extern "C" {
|
|
||||||
fn gst_caps_set_value(caps: *mut c_void, name: *const c_char, value: *const GValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
for value in values {
|
for value in values {
|
||||||
let name_cstr = CString::new(value.0).unwrap();
|
let name_cstr = CString::new(value.0).unwrap();
|
||||||
let mut gvalue = value.1.to_gvalue();
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
gst_caps_set_value(self.0, name_cstr.as_ptr(), &mut gvalue as *mut GValue);
|
let mut gvalue = value.1.to_gvalue();
|
||||||
|
gst::gst_caps_set_value(self.0, name_cstr.as_ptr(), &mut gvalue);
|
||||||
|
gobject::g_value_unset(&mut gvalue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_string(&self) -> String {
|
pub fn to_string(&self) -> String {
|
||||||
extern "C" {
|
|
||||||
fn gst_caps_to_string(caps: *mut c_void) -> *mut c_char;
|
|
||||||
fn g_free(ptr: *mut c_char);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = gst_caps_to_string(self.0);
|
let ptr = gst::gst_caps_to_string(self.0);
|
||||||
let s = CStr::from_ptr(ptr).to_str().unwrap().into();
|
let s = CStr::from_ptr(ptr).to_str().unwrap().into();
|
||||||
g_free(ptr);
|
glib::g_free(ptr as glib::gpointer);
|
||||||
|
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
@ -126,11 +103,7 @@ impl fmt::Debug for Caps {
|
||||||
|
|
||||||
impl PartialEq for Caps {
|
impl PartialEq for Caps {
|
||||||
fn eq(&self, other: &Caps) -> bool {
|
fn eq(&self, other: &Caps) -> bool {
|
||||||
extern "C" {
|
(unsafe { gst::gst_caps_is_equal(self.0, other.0) } == glib::GTRUE)
|
||||||
fn gst_caps_is_equal(a: *const c_void, b: *const c_void) -> GBoolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe { gst_caps_is_equal(self.0, other.0).to_bool() }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,15 +114,10 @@ unsafe impl Send for Caps {}
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::os::raw::c_void;
|
|
||||||
|
|
||||||
fn init() {
|
fn init() {
|
||||||
extern "C" {
|
|
||||||
fn gst_init(argc: *mut c_void, argv: *mut c_void);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
gst_init(ptr::null_mut(), ptr::null_mut());
|
gst::gst_init(ptr::null_mut(), ptr::null_mut());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,9 @@ use log::*;
|
||||||
use caps::Caps;
|
use caps::Caps;
|
||||||
use plugin::Plugin;
|
use plugin::Plugin;
|
||||||
|
|
||||||
|
use glib;
|
||||||
|
use gst;
|
||||||
|
|
||||||
pub type StreamIndex = u32;
|
pub type StreamIndex = u32;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -89,14 +92,14 @@ impl Stream {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DemuxerWrapper {
|
pub struct DemuxerWrapper {
|
||||||
raw: *mut c_void,
|
raw: *mut gst::GstElement,
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
demuxer: Mutex<Box<Demuxer>>,
|
demuxer: Mutex<Box<Demuxer>>,
|
||||||
panicked: AtomicBool,
|
panicked: AtomicBool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DemuxerWrapper {
|
impl DemuxerWrapper {
|
||||||
fn new(raw: *mut c_void, demuxer: Box<Demuxer>) -> DemuxerWrapper {
|
fn new(raw: *mut gst::GstElement, demuxer: Box<Demuxer>) -> DemuxerWrapper {
|
||||||
DemuxerWrapper {
|
DemuxerWrapper {
|
||||||
raw: raw,
|
raw: raw,
|
||||||
logger: Logger::root(GstDebugDrain::new(Some(unsafe { &Element::new(raw) }),
|
logger: Logger::root(GstDebugDrain::new(Some(unsafe { &Element::new(raw) }),
|
||||||
|
@ -164,44 +167,44 @@ impl DemuxerWrapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn get_position(&self, position: &mut u64) -> GBoolean {
|
fn get_position(&self, position: &mut u64) -> glib::gboolean {
|
||||||
let demuxer = &self.demuxer.lock().unwrap();
|
let demuxer = &self.demuxer.lock().unwrap();
|
||||||
|
|
||||||
match demuxer.get_position() {
|
match demuxer.get_position() {
|
||||||
None => {
|
None => {
|
||||||
trace!(self.logger, "Got no position");
|
trace!(self.logger, "Got no position");
|
||||||
*position = u64::MAX;
|
*position = u64::MAX;
|
||||||
GBoolean::False
|
glib::GFALSE
|
||||||
}
|
}
|
||||||
Some(pos) => {
|
Some(pos) => {
|
||||||
trace!(self.logger, "Returning position {}", pos);
|
trace!(self.logger, "Returning position {}", pos);
|
||||||
*position = pos;
|
*position = pos;
|
||||||
GBoolean::True
|
glib::GTRUE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_duration(&self, duration: &mut u64) -> GBoolean {
|
fn get_duration(&self, duration: &mut u64) -> glib::gboolean {
|
||||||
let demuxer = &self.demuxer.lock().unwrap();
|
let demuxer = &self.demuxer.lock().unwrap();
|
||||||
|
|
||||||
match demuxer.get_duration() {
|
match demuxer.get_duration() {
|
||||||
None => {
|
None => {
|
||||||
trace!(self.logger, "Got no duration");
|
trace!(self.logger, "Got no duration");
|
||||||
*duration = u64::MAX;
|
*duration = u64::MAX;
|
||||||
GBoolean::False
|
glib::GFALSE
|
||||||
}
|
}
|
||||||
Some(dur) => {
|
Some(dur) => {
|
||||||
trace!(self.logger, "Returning duration {}", dur);
|
trace!(self.logger, "Returning duration {}", dur);
|
||||||
*duration = dur;
|
*duration = dur;
|
||||||
GBoolean::True
|
glib::GTRUE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn seek(&self, start: u64, stop: u64, offset: &mut u64) -> bool {
|
fn seek(&self, start: u64, stop: u64, offset: &mut u64) -> bool {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn gst_rs_demuxer_stream_eos(raw: *mut c_void, index: u32);
|
fn gst_rs_demuxer_stream_eos(raw: *mut gst::GstElement, index: u32);
|
||||||
};
|
};
|
||||||
|
|
||||||
let stop = if stop == u64::MAX { None } else { Some(stop) };
|
let stop = if stop == u64::MAX { None } else { Some(stop) };
|
||||||
|
@ -246,19 +249,19 @@ impl DemuxerWrapper {
|
||||||
|
|
||||||
fn handle_buffer(&self, buffer: GstRc<Buffer>) -> GstFlowReturn {
|
fn handle_buffer(&self, buffer: GstRc<Buffer>) -> GstFlowReturn {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn gst_rs_demuxer_stream_eos(raw: *mut c_void, index: u32);
|
fn gst_rs_demuxer_stream_eos(raw: *mut gst::GstElement, index: u32);
|
||||||
fn gst_rs_demuxer_add_stream(raw: *mut c_void,
|
fn gst_rs_demuxer_add_stream(raw: *mut gst::GstElement,
|
||||||
index: u32,
|
index: u32,
|
||||||
caps: *const c_void,
|
caps: *const gst::GstCaps,
|
||||||
stream_id: *const c_char);
|
stream_id: *const c_char);
|
||||||
fn gst_rs_demuxer_added_all_streams(raw: *mut c_void);
|
fn gst_rs_demuxer_added_all_streams(raw: *mut gst::GstElement);
|
||||||
// fn gst_rs_demuxer_remove_all_streams(raw: *mut c_void);
|
// fn gst_rs_demuxer_remove_all_streams(raw: *mut gst::GstElement);
|
||||||
fn gst_rs_demuxer_stream_format_changed(raw: *mut c_void,
|
fn gst_rs_demuxer_stream_format_changed(raw: *mut gst::GstElement,
|
||||||
index: u32,
|
index: u32,
|
||||||
caps: *const c_void);
|
caps: *const gst::GstCaps);
|
||||||
fn gst_rs_demuxer_stream_push_buffer(raw: *mut c_void,
|
fn gst_rs_demuxer_stream_push_buffer(raw: *mut gst::GstElement,
|
||||||
index: u32,
|
index: u32,
|
||||||
buffer: *mut c_void)
|
buffer: *mut gst::GstBuffer)
|
||||||
-> GstFlowReturn;
|
-> GstFlowReturn;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -379,7 +382,7 @@ impl DemuxerWrapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn demuxer_new(demuxer: *mut c_void,
|
pub unsafe extern "C" fn demuxer_new(demuxer: *mut gst::GstElement,
|
||||||
create_instance: fn(Element) -> Box<Demuxer>)
|
create_instance: fn(Element) -> Box<Demuxer>)
|
||||||
-> *mut DemuxerWrapper {
|
-> *mut DemuxerWrapper {
|
||||||
let instance = create_instance(Element::new(demuxer));
|
let instance = create_instance(Element::new(demuxer));
|
||||||
|
@ -394,40 +397,52 @@ pub unsafe extern "C" fn demuxer_drop(ptr: *mut DemuxerWrapper) {
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn demuxer_start(ptr: *const DemuxerWrapper,
|
pub unsafe extern "C" fn demuxer_start(ptr: *const DemuxerWrapper,
|
||||||
upstream_size: u64,
|
upstream_size: u64,
|
||||||
random_access: GBoolean)
|
random_access: glib::gboolean)
|
||||||
-> GBoolean {
|
-> glib::gboolean {
|
||||||
let wrap: &DemuxerWrapper = &*ptr;
|
let wrap: &DemuxerWrapper = &*ptr;
|
||||||
|
|
||||||
panic_to_error!(wrap, GBoolean::False, {
|
panic_to_error!(wrap, glib::GFALSE, {
|
||||||
GBoolean::from_bool(wrap.start(upstream_size, random_access.to_bool()))
|
if wrap.start(upstream_size, random_access != glib::GFALSE) {
|
||||||
|
glib::GTRUE
|
||||||
|
} else {
|
||||||
|
glib::GFALSE
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn demuxer_stop(ptr: *const DemuxerWrapper) -> GBoolean {
|
pub unsafe extern "C" fn demuxer_stop(ptr: *const DemuxerWrapper) -> glib::gboolean {
|
||||||
let wrap: &DemuxerWrapper = &*ptr;
|
let wrap: &DemuxerWrapper = &*ptr;
|
||||||
|
|
||||||
panic_to_error!(wrap, GBoolean::True, {
|
panic_to_error!(wrap, glib::GTRUE, {
|
||||||
GBoolean::from_bool(wrap.stop())
|
if wrap.stop() {
|
||||||
|
glib::GTRUE
|
||||||
|
} else {
|
||||||
|
glib::GFALSE
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn demuxer_is_seekable(ptr: *const DemuxerWrapper) -> GBoolean {
|
pub unsafe extern "C" fn demuxer_is_seekable(ptr: *const DemuxerWrapper) -> glib::gboolean {
|
||||||
let wrap: &DemuxerWrapper = &*ptr;
|
let wrap: &DemuxerWrapper = &*ptr;
|
||||||
|
|
||||||
panic_to_error!(wrap, GBoolean::False, {
|
panic_to_error!(wrap, glib::GFALSE, {
|
||||||
GBoolean::from_bool(wrap.is_seekable())
|
if wrap.is_seekable() {
|
||||||
|
glib::GTRUE
|
||||||
|
} else {
|
||||||
|
glib::GFALSE
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn demuxer_get_position(ptr: *const DemuxerWrapper,
|
pub unsafe extern "C" fn demuxer_get_position(ptr: *const DemuxerWrapper,
|
||||||
position: *mut u64)
|
position: *mut u64)
|
||||||
-> GBoolean {
|
-> glib::gboolean {
|
||||||
let wrap: &DemuxerWrapper = &*ptr;
|
let wrap: &DemuxerWrapper = &*ptr;
|
||||||
|
|
||||||
panic_to_error!(wrap, GBoolean::False, {
|
panic_to_error!(wrap, glib::GFALSE, {
|
||||||
let position = &mut *position;
|
let position = &mut *position;
|
||||||
wrap.get_position(position)
|
wrap.get_position(position)
|
||||||
})
|
})
|
||||||
|
@ -436,10 +451,10 @@ pub unsafe extern "C" fn demuxer_get_position(ptr: *const DemuxerWrapper,
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn demuxer_get_duration(ptr: *const DemuxerWrapper,
|
pub unsafe extern "C" fn demuxer_get_duration(ptr: *const DemuxerWrapper,
|
||||||
duration: *mut u64)
|
duration: *mut u64)
|
||||||
-> GBoolean {
|
-> glib::gboolean {
|
||||||
let wrap: &DemuxerWrapper = &*ptr;
|
let wrap: &DemuxerWrapper = &*ptr;
|
||||||
|
|
||||||
panic_to_error!(wrap, GBoolean::False, {
|
panic_to_error!(wrap, glib::GFALSE, {
|
||||||
let duration = &mut *duration;
|
let duration = &mut *duration;
|
||||||
wrap.get_duration(duration)
|
wrap.get_duration(duration)
|
||||||
})
|
})
|
||||||
|
@ -450,20 +465,24 @@ pub unsafe extern "C" fn demuxer_seek(ptr: *mut DemuxerWrapper,
|
||||||
start: u64,
|
start: u64,
|
||||||
stop: u64,
|
stop: u64,
|
||||||
offset: *mut u64)
|
offset: *mut u64)
|
||||||
-> GBoolean {
|
-> glib::gboolean {
|
||||||
|
|
||||||
let wrap: &mut DemuxerWrapper = &mut *ptr;
|
let wrap: &mut DemuxerWrapper = &mut *ptr;
|
||||||
|
|
||||||
panic_to_error!(wrap, GBoolean::False, {
|
panic_to_error!(wrap, glib::GFALSE, {
|
||||||
let offset = &mut *offset;
|
let offset = &mut *offset;
|
||||||
|
|
||||||
GBoolean::from_bool(wrap.seek(start, stop, offset))
|
if wrap.seek(start, stop, offset) {
|
||||||
|
glib::GTRUE
|
||||||
|
} else {
|
||||||
|
glib::GFALSE
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn demuxer_handle_buffer(ptr: *mut DemuxerWrapper,
|
pub unsafe extern "C" fn demuxer_handle_buffer(ptr: *mut DemuxerWrapper,
|
||||||
buffer: *mut c_void)
|
buffer: *mut gst::GstBuffer)
|
||||||
-> GstFlowReturn {
|
-> GstFlowReturn {
|
||||||
let wrap: &mut DemuxerWrapper = &mut *ptr;
|
let wrap: &mut DemuxerWrapper = &mut *ptr;
|
||||||
|
|
||||||
|
@ -496,7 +515,7 @@ pub struct DemuxerInfo<'a> {
|
||||||
|
|
||||||
pub fn demuxer_register(plugin: &Plugin, demuxer_info: &DemuxerInfo) {
|
pub fn demuxer_register(plugin: &Plugin, demuxer_info: &DemuxerInfo) {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn gst_rs_demuxer_register(plugin: *const c_void,
|
fn gst_rs_demuxer_register(plugin: *const gst::GstPlugin,
|
||||||
name: *const c_char,
|
name: *const c_char,
|
||||||
long_name: *const c_char,
|
long_name: *const c_char,
|
||||||
description: *const c_char,
|
description: *const c_char,
|
||||||
|
@ -504,9 +523,9 @@ pub fn demuxer_register(plugin: &Plugin, demuxer_info: &DemuxerInfo) {
|
||||||
author: *const c_char,
|
author: *const c_char,
|
||||||
rank: i32,
|
rank: i32,
|
||||||
create_instance: *const c_void,
|
create_instance: *const c_void,
|
||||||
input_caps: *const c_void,
|
input_caps: *const gst::GstCaps,
|
||||||
output_caps: *const c_void)
|
output_caps: *const gst::GstCaps)
|
||||||
-> GBoolean;
|
-> glib::gboolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
let cname = CString::new(demuxer_info.name).unwrap();
|
let cname = CString::new(demuxer_info.name).unwrap();
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
/* Copyright (C) 2016-2017 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <gst/gst.h>
|
|
||||||
|
|
||||||
void
|
|
||||||
gst_rs_element_error (GstElement * element, GQuark error_domain,
|
|
||||||
gint error_code, const gchar * message, const gchar * debug,
|
|
||||||
const gchar * file, const gchar * function, guint line)
|
|
||||||
{
|
|
||||||
gst_element_message_full (element, GST_MESSAGE_ERROR, error_domain,
|
|
||||||
error_code, g_strdup (message), g_strdup (debug), file, function, line);
|
|
||||||
}
|
|
|
@ -6,8 +6,6 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use libc::c_char;
|
|
||||||
use std::os::raw::c_void;
|
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
@ -19,6 +17,9 @@ use url::Url;
|
||||||
|
|
||||||
use utils::*;
|
use utils::*;
|
||||||
|
|
||||||
|
use glib;
|
||||||
|
use gst;
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! error_msg(
|
macro_rules! error_msg(
|
||||||
// Plain strings
|
// Plain strings
|
||||||
|
@ -61,20 +62,12 @@ pub trait ToGError {
|
||||||
fn to_gerror(&self) -> (u32, i32);
|
fn to_gerror(&self) -> (u32, i32);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gst_library_error_domain() -> u32 {
|
pub fn gst_library_error_domain() -> glib::GQuark {
|
||||||
extern "C" {
|
unsafe { gst::gst_library_error_quark() }
|
||||||
fn gst_library_error_quark() -> u32;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe { gst_library_error_quark() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gst_resource_error_domain() -> u32 {
|
pub fn gst_resource_error_domain() -> glib::GQuark {
|
||||||
extern "C" {
|
unsafe { gst::gst_resource_error_quark() }
|
||||||
fn gst_resource_error_quark() -> u32;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe { gst_resource_error_quark() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -110,18 +103,7 @@ impl ErrorMessage {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub unsafe fn post(&self, element: *mut c_void) {
|
pub unsafe fn post(&self, element: *mut gst::GstElement) {
|
||||||
extern "C" {
|
|
||||||
fn gst_rs_element_error(sink: *mut c_void,
|
|
||||||
error_domain: u32,
|
|
||||||
error_code: i32,
|
|
||||||
message: *const c_char,
|
|
||||||
debug: *const c_char,
|
|
||||||
filename: *const c_char,
|
|
||||||
function: *const c_char,
|
|
||||||
line: u32);
|
|
||||||
}
|
|
||||||
|
|
||||||
let ErrorMessage { error_domain,
|
let ErrorMessage { error_domain,
|
||||||
error_code,
|
error_code,
|
||||||
ref message,
|
ref message,
|
||||||
|
@ -142,14 +124,15 @@ impl ErrorMessage {
|
||||||
let function_cstr = CString::new(function.as_bytes()).unwrap();
|
let function_cstr = CString::new(function.as_bytes()).unwrap();
|
||||||
let function_ptr = function_cstr.as_ptr();
|
let function_ptr = function_cstr.as_ptr();
|
||||||
|
|
||||||
gst_rs_element_error(element,
|
gst::gst_element_message_full(element,
|
||||||
error_domain,
|
gst::GST_MESSAGE_ERROR,
|
||||||
error_code,
|
error_domain,
|
||||||
message_ptr,
|
error_code,
|
||||||
debug_ptr,
|
glib::g_strdup(message_ptr),
|
||||||
file_ptr,
|
glib::g_strdup(debug_ptr),
|
||||||
function_ptr,
|
file_ptr,
|
||||||
line);
|
function_ptr,
|
||||||
|
line as i32);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,27 +216,18 @@ impl UriError {
|
||||||
&self.error_kind
|
&self.error_kind
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn into_gerror(self, err: *mut c_void) {
|
pub unsafe fn into_gerror(self, err: *mut *mut glib::GError) {
|
||||||
extern "C" {
|
|
||||||
fn g_set_error_literal(err: *mut c_void,
|
|
||||||
domain: u32,
|
|
||||||
code: i32,
|
|
||||||
message: *const c_char);
|
|
||||||
fn gst_uri_error_quark() -> u32;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if let Some(msg) = self.message {
|
if let Some(msg) = self.message {
|
||||||
let cmsg = CString::new(msg.as_str()).unwrap();
|
let cmsg = CString::new(msg.as_str()).unwrap();
|
||||||
g_set_error_literal(err,
|
glib::g_set_error_literal(err,
|
||||||
gst_uri_error_quark(),
|
gst::gst_uri_error_quark(),
|
||||||
self.error_kind as i32,
|
self.error_kind as i32,
|
||||||
cmsg.as_ptr());
|
cmsg.as_ptr());
|
||||||
} else {
|
} else {
|
||||||
g_set_error_literal(err,
|
glib::g_set_error_literal(err,
|
||||||
gst_uri_error_quark(),
|
gst::gst_uri_error_quark(),
|
||||||
self.error_kind as i32,
|
self.error_kind as i32,
|
||||||
ptr::null());
|
ptr::null());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,9 +19,9 @@ extern crate byteorder;
|
||||||
extern crate num_rational;
|
extern crate num_rational;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate derivative;
|
extern crate derivative;
|
||||||
extern crate gobject_sys as gobject;
|
pub extern crate gobject_sys as gobject;
|
||||||
extern crate glib_sys as glib;
|
pub extern crate glib_sys as glib;
|
||||||
extern crate gstreamer_sys as gst;
|
pub extern crate gstreamer_sys as gst;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
@ -41,3 +41,9 @@ pub mod bytes;
|
||||||
pub mod tags;
|
pub mod tags;
|
||||||
pub mod streams;
|
pub mod streams;
|
||||||
pub mod miniobject;
|
pub mod miniobject;
|
||||||
|
|
||||||
|
pub mod ffi {
|
||||||
|
pub use glib;
|
||||||
|
pub use gobject;
|
||||||
|
pub use gst;
|
||||||
|
}
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
/* Copyright (C) 2016-2017 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <gst/gst.h>
|
|
||||||
|
|
||||||
void
|
|
||||||
gst_rs_debug_log (GstDebugCategory * category,
|
|
||||||
GstDebugLevel level,
|
|
||||||
const gchar * file,
|
|
||||||
const gchar * function, gint line, GObject * object, const gchar * message)
|
|
||||||
{
|
|
||||||
gst_debug_log (category, level, file, function, line, object, "%s", message);
|
|
||||||
}
|
|
|
@ -6,19 +6,21 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use std::os::raw::c_void;
|
|
||||||
use libc::c_char;
|
use libc::c_char;
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use slog::{Drain, Record, OwnedKeyValueList, Never, Level};
|
use slog::{Drain, Record, OwnedKeyValueList, Never, Level};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
use utils::Element;
|
use utils::Element;
|
||||||
|
|
||||||
#[derive(Debug)]
|
use gobject;
|
||||||
|
use gst;
|
||||||
|
|
||||||
pub struct GstDebugDrain {
|
pub struct GstDebugDrain {
|
||||||
category: *const c_void,
|
category: *mut gst::GstDebugCategory,
|
||||||
element: *const c_void,
|
element: gobject::GWeakRef,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GstDebugDrain {
|
impl GstDebugDrain {
|
||||||
|
@ -31,7 +33,7 @@ impl GstDebugDrain {
|
||||||
fn _gst_debug_category_new(name: *const c_char,
|
fn _gst_debug_category_new(name: *const c_char,
|
||||||
color: u32,
|
color: u32,
|
||||||
description: *const c_char)
|
description: *const c_char)
|
||||||
-> *const c_void;
|
-> *mut gst::GstDebugCategory;
|
||||||
}
|
}
|
||||||
|
|
||||||
let name_cstr = CString::new(name.as_bytes()).unwrap();
|
let name_cstr = CString::new(name.as_bytes()).unwrap();
|
||||||
|
@ -47,18 +49,14 @@ impl GstDebugDrain {
|
||||||
None => ptr::null(),
|
None => ptr::null(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let drain = GstDebugDrain {
|
let mut drain = GstDebugDrain {
|
||||||
category: category,
|
category: category,
|
||||||
element: ptr::null(),
|
element: unsafe { mem::zeroed() },
|
||||||
};
|
};
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
fn g_weak_ref_set(weak_ref: &*const c_void, obj: *const c_void);
|
|
||||||
}
|
|
||||||
|
|
||||||
if !element.is_null() {
|
if !element.is_null() {
|
||||||
unsafe {
|
unsafe {
|
||||||
g_weak_ref_set(&drain.element, element);
|
gobject::g_weak_ref_set(&mut drain.element, element as *mut gobject::GObject);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,14 +66,8 @@ impl GstDebugDrain {
|
||||||
|
|
||||||
impl Drop for GstDebugDrain {
|
impl Drop for GstDebugDrain {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
extern "C" {
|
unsafe {
|
||||||
fn g_weak_ref_clear(weak_ref: &*const c_void);
|
gobject::g_weak_ref_clear(&mut self.element);
|
||||||
}
|
|
||||||
|
|
||||||
if !self.element.is_null() {
|
|
||||||
unsafe {
|
|
||||||
g_weak_ref_clear(&self.element);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,30 +76,17 @@ impl Drain for GstDebugDrain {
|
||||||
type Error = Never;
|
type Error = Never;
|
||||||
|
|
||||||
fn log(&self, record: &Record, _: &OwnedKeyValueList) -> Result<(), Never> {
|
fn log(&self, record: &Record, _: &OwnedKeyValueList) -> Result<(), Never> {
|
||||||
extern "C" {
|
|
||||||
fn gst_rs_debug_log(category: *const c_void,
|
|
||||||
level: u32,
|
|
||||||
file: *const c_char,
|
|
||||||
function: *const c_char,
|
|
||||||
line: u32,
|
|
||||||
object: *const c_void,
|
|
||||||
message: *const c_char);
|
|
||||||
fn gst_debug_category_get_threshold(category: *const c_void) -> u32;
|
|
||||||
fn g_weak_ref_get(weak_ref: &*const c_void) -> *const c_void;
|
|
||||||
fn gst_object_unref(obj: *const c_void);
|
|
||||||
}
|
|
||||||
|
|
||||||
let level = match record.level() {
|
let level = match record.level() {
|
||||||
Level::Critical | Level::Error => 1,
|
Level::Critical | Level::Error => gst::GST_LEVEL_ERROR,
|
||||||
Level::Warning => 2,
|
Level::Warning => gst::GST_LEVEL_WARNING,
|
||||||
Level::Info => 4,
|
Level::Info => gst::GST_LEVEL_INFO,
|
||||||
Level::Debug => 5,
|
Level::Debug => gst::GST_LEVEL_DEBUG,
|
||||||
Level::Trace => 7,
|
Level::Trace => gst::GST_LEVEL_TRACE,
|
||||||
};
|
};
|
||||||
|
|
||||||
let threshold = unsafe { gst_debug_category_get_threshold(self.category) };
|
let threshold = unsafe { gst::gst_debug_category_get_threshold(self.category) };
|
||||||
|
|
||||||
if level > threshold {
|
if level as u32 > threshold as u32 {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,22 +98,19 @@ impl Drain for GstDebugDrain {
|
||||||
let message_cstr = CString::new(fmt::format(record.msg()).as_bytes()).unwrap();
|
let message_cstr = CString::new(fmt::format(record.msg()).as_bytes()).unwrap();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let element = if self.element.is_null() {
|
let element = gobject::g_weak_ref_get(&self.element as *const gobject::GWeakRef as
|
||||||
ptr::null()
|
*mut gobject::GWeakRef);
|
||||||
} else {
|
|
||||||
g_weak_ref_get(&self.element)
|
|
||||||
};
|
|
||||||
|
|
||||||
gst_rs_debug_log(self.category,
|
gst::gst_debug_log(self.category,
|
||||||
level,
|
level,
|
||||||
file_cstr.as_ptr(),
|
file_cstr.as_ptr(),
|
||||||
function_cstr.as_ptr(),
|
function_cstr.as_ptr(),
|
||||||
record.line(),
|
record.line() as i32,
|
||||||
element,
|
element as *mut gobject::GObject,
|
||||||
message_cstr.as_ptr());
|
message_cstr.as_ptr());
|
||||||
|
|
||||||
if !element.is_null() {
|
if !element.is_null() {
|
||||||
gst_object_unref(element);
|
gst::gst_object_unref(element as *mut gst::GstObject);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,10 +6,11 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use std::os::raw::c_void;
|
|
||||||
use std::{fmt, ops, borrow, ptr};
|
use std::{fmt, ops, borrow, ptr};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use utils::*;
|
|
||||||
|
use glib;
|
||||||
|
use gst;
|
||||||
|
|
||||||
#[derive(Hash, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Hash, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub struct GstRc<T: MiniObject> {
|
pub struct GstRc<T: MiniObject> {
|
||||||
|
@ -18,31 +19,24 @@ pub struct GstRc<T: MiniObject> {
|
||||||
|
|
||||||
impl<T: MiniObject> GstRc<T> {
|
impl<T: MiniObject> GstRc<T> {
|
||||||
unsafe fn new(obj: T, owned: bool) -> Self {
|
unsafe fn new(obj: T, owned: bool) -> Self {
|
||||||
extern "C" {
|
|
||||||
fn gst_mini_object_ref(obj: *mut c_void) -> *mut c_void;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert!(!obj.as_ptr().is_null());
|
assert!(!obj.as_ptr().is_null());
|
||||||
|
|
||||||
if !owned {
|
if !owned {
|
||||||
gst_mini_object_ref(obj.as_ptr());
|
gst::gst_mini_object_ref(obj.as_ptr() as *mut gst::GstMiniObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
GstRc { obj: obj }
|
GstRc { obj: obj }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn new_from_owned_ptr(ptr: *mut c_void) -> Self {
|
pub unsafe fn new_from_owned_ptr(ptr: *mut T::PtrType) -> Self {
|
||||||
Self::new(T::new_from_ptr(ptr), true)
|
Self::new(T::new_from_ptr(ptr), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn new_from_unowned_ptr(ptr: *mut c_void) -> Self {
|
pub unsafe fn new_from_unowned_ptr(ptr: *mut T::PtrType) -> Self {
|
||||||
Self::new(T::new_from_ptr(ptr), false)
|
Self::new(T::new_from_ptr(ptr), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_mut(&mut self) -> &mut T {
|
pub fn make_mut(&mut self) -> &mut T {
|
||||||
extern "C" {
|
|
||||||
fn gst_mini_object_make_writable(obj: *mut c_void) -> *mut c_void;
|
|
||||||
}
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = self.obj.as_ptr();
|
let ptr = self.obj.as_ptr();
|
||||||
|
|
||||||
|
@ -50,7 +44,9 @@ impl<T: MiniObject> GstRc<T> {
|
||||||
return &mut self.obj;
|
return &mut self.obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.obj.replace_ptr(gst_mini_object_make_writable(ptr));
|
self.obj.replace_ptr(gst::gst_mini_object_make_writable(ptr as
|
||||||
|
*mut gst::GstMiniObject) as
|
||||||
|
*mut T::PtrType);
|
||||||
assert!(self.is_writable());
|
assert!(self.is_writable());
|
||||||
|
|
||||||
&mut self.obj
|
&mut self.obj
|
||||||
|
@ -66,20 +62,20 @@ impl<T: MiniObject> GstRc<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn copy(&self) -> Self {
|
pub fn copy(&self) -> Self {
|
||||||
extern "C" {
|
unsafe {
|
||||||
fn gst_mini_object_copy(obj: *const c_void) -> *mut c_void;
|
GstRc::new_from_owned_ptr(gst::gst_mini_object_copy(self.obj.as_ptr() as
|
||||||
|
*const gst::GstMiniObject) as
|
||||||
|
*mut T::PtrType)
|
||||||
}
|
}
|
||||||
unsafe { GstRc::new_from_owned_ptr(gst_mini_object_copy(self.obj.as_ptr())) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_writable(&self) -> bool {
|
fn is_writable(&self) -> bool {
|
||||||
extern "C" {
|
(unsafe {
|
||||||
fn gst_mini_object_is_writable(obj: *mut c_void) -> GBoolean;
|
gst::gst_mini_object_is_writable(self.as_ptr() as *const gst::GstMiniObject)
|
||||||
}
|
} == glib::GTRUE)
|
||||||
unsafe { gst_mini_object_is_writable(self.as_ptr()).to_bool() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn into_ptr(mut self) -> *mut c_void {
|
pub unsafe fn into_ptr(mut self) -> *mut T::PtrType {
|
||||||
self.obj.swap_ptr(ptr::null_mut())
|
self.obj.swap_ptr(ptr::null_mut())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -111,13 +107,9 @@ impl<T: MiniObject> Clone for GstRc<T> {
|
||||||
|
|
||||||
impl<T: MiniObject> Drop for GstRc<T> {
|
impl<T: MiniObject> Drop for GstRc<T> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
extern "C" {
|
|
||||||
fn gst_mini_object_unref(obj: *mut c_void) -> *mut c_void;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
if !self.obj.as_ptr().is_null() {
|
if !self.obj.as_ptr().is_null() {
|
||||||
gst_mini_object_unref(self.obj.as_ptr());
|
gst::gst_mini_object_unref(self.obj.as_ptr() as *mut gst::GstMiniObject);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,16 +126,18 @@ impl<T: MiniObject + fmt::Display> fmt::Display for GstRc<T> {
|
||||||
|
|
||||||
// NOTE: Reference counting must not happen in here
|
// NOTE: Reference counting must not happen in here
|
||||||
pub unsafe trait MiniObject {
|
pub unsafe trait MiniObject {
|
||||||
unsafe fn as_ptr(&self) -> *mut c_void;
|
type PtrType;
|
||||||
unsafe fn replace_ptr(&mut self, ptr: *mut c_void);
|
|
||||||
unsafe fn swap_ptr(&mut self, new_ptr: *mut c_void) -> *mut c_void {
|
unsafe fn as_ptr(&self) -> *mut Self::PtrType;
|
||||||
|
unsafe fn replace_ptr(&mut self, ptr: *mut Self::PtrType);
|
||||||
|
unsafe fn swap_ptr(&mut self, new_ptr: *mut Self::PtrType) -> *mut Self::PtrType {
|
||||||
let ptr = self.as_ptr();
|
let ptr = self.as_ptr();
|
||||||
self.replace_ptr(new_ptr);
|
self.replace_ptr(new_ptr);
|
||||||
|
|
||||||
ptr
|
ptr
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn new_from_ptr(ptr: *mut c_void) -> Self;
|
unsafe fn new_from_ptr(ptr: *mut Self::PtrType) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: MiniObject> From<&'a T> for GstRc<T> {
|
impl<'a, T: MiniObject> From<&'a T> for GstRc<T> {
|
||||||
|
@ -159,19 +153,19 @@ impl<'a, T: MiniObject> From<&'a mut T> for GstRc<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct GstRefPtr(*mut c_void);
|
pub struct GstRefPtr<T: MiniObject>(*mut T::PtrType);
|
||||||
|
|
||||||
#[derive(Hash, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Hash, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub struct GstRef<'a, T: MiniObject> {
|
pub struct GstRef<'a, T: 'a + MiniObject> {
|
||||||
obj: T,
|
obj: T,
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
phantom: PhantomData<&'a GstRefPtr>,
|
phantom: PhantomData<&'a GstRefPtr<T>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: MiniObject> GstRef<'a, T> {
|
impl<'a, T: MiniObject> GstRef<'a, T> {
|
||||||
pub unsafe fn new(ptr: &'a GstRefPtr) -> GstRef<'a, T> {
|
pub unsafe fn new(ptr: &'a GstRefPtr<T>) -> GstRef<'a, T> {
|
||||||
GstRef {
|
GstRef {
|
||||||
obj: T::new_from_ptr(ptr.0),
|
obj: T::new_from_ptr(ptr.0 as *mut T::PtrType),
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -185,20 +179,20 @@ impl<'a, T: MiniObject> GstRef<'a, T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn copy(&self) -> GstRc<T> {
|
pub fn copy(&self) -> GstRc<T> {
|
||||||
extern "C" {
|
unsafe {
|
||||||
fn gst_mini_object_copy(obj: *const c_void) -> *mut c_void;
|
GstRc::new_from_owned_ptr(gst::gst_mini_object_copy(self.obj.as_ptr() as
|
||||||
|
*const gst::GstMiniObject) as
|
||||||
|
*mut T::PtrType)
|
||||||
}
|
}
|
||||||
unsafe { GstRc::new_from_owned_ptr(gst_mini_object_copy(self.obj.as_ptr())) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_writable(&self) -> bool {
|
fn is_writable(&self) -> bool {
|
||||||
extern "C" {
|
(unsafe {
|
||||||
fn gst_mini_object_is_writable(obj: *mut c_void) -> GBoolean;
|
gst::gst_mini_object_is_writable(self.as_ptr() as *const gst::GstMiniObject)
|
||||||
}
|
} == glib::GTRUE)
|
||||||
unsafe { gst_mini_object_is_writable(self.as_ptr()).to_bool() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn into_ptr(mut self) -> *mut c_void {
|
pub unsafe fn into_ptr(mut self) -> *mut T::PtrType {
|
||||||
self.obj.swap_ptr(ptr::null_mut())
|
self.obj.swap_ptr(ptr::null_mut())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,16 +6,16 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use std::os::raw::c_void;
|
use gst;
|
||||||
|
|
||||||
pub struct Plugin(*const c_void);
|
pub struct Plugin(*mut gst::GstPlugin);
|
||||||
|
|
||||||
impl Plugin {
|
impl Plugin {
|
||||||
pub unsafe fn new(plugin: *const c_void) -> Plugin {
|
pub unsafe fn new(plugin: *mut gst::GstPlugin) -> Plugin {
|
||||||
Plugin(plugin)
|
Plugin(plugin)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn as_ptr(&self) -> *const c_void {
|
pub unsafe fn as_ptr(&self) -> *mut gst::GstPlugin {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,47 +26,41 @@ macro_rules! plugin_define(
|
||||||
$version:expr, $license:expr, $source:expr,
|
$version:expr, $license:expr, $source:expr,
|
||||||
$package:expr, $origin:expr, $release_datetime:expr) => {
|
$package:expr, $origin:expr, $release_datetime:expr) => {
|
||||||
pub mod plugin_desc {
|
pub mod plugin_desc {
|
||||||
use std::os::raw::c_void;
|
|
||||||
use $crate::utils::GBoolean;
|
|
||||||
use $crate::plugin::Plugin;
|
use $crate::plugin::Plugin;
|
||||||
|
use $crate::ffi::gst;
|
||||||
|
use $crate::ffi::glib;
|
||||||
|
|
||||||
|
// Not using c_char here because it requires the libc crate
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
type c_char = i8;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct GstPluginDesc {
|
pub struct GstPluginDesc(gst::GstPluginDesc);
|
||||||
major_version: i32,
|
|
||||||
minor_version: i32,
|
|
||||||
name: *const u8,
|
|
||||||
description: *const u8,
|
|
||||||
plugin_init: unsafe extern "C" fn(plugin: *const c_void) -> GBoolean,
|
|
||||||
version: *const u8,
|
|
||||||
license: *const u8,
|
|
||||||
source: *const u8,
|
|
||||||
package: *const u8,
|
|
||||||
origin: *const u8,
|
|
||||||
release_datetime: *const u8,
|
|
||||||
_gst_reserved: [usize; 4],
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe impl Sync for GstPluginDesc {}
|
unsafe impl Sync for GstPluginDesc {}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals)]
|
||||||
pub static gst_plugin_desc: GstPluginDesc = GstPluginDesc {
|
pub static gst_plugin_desc: GstPluginDesc = GstPluginDesc(gst::GstPluginDesc {
|
||||||
major_version: 1,
|
major_version: 1,
|
||||||
minor_version: 10,
|
minor_version: 10,
|
||||||
name: $name as *const u8,
|
name: $name as *const u8 as *const c_char,
|
||||||
description: $description as *const u8,
|
description: $description as *const u8 as *const c_char,
|
||||||
plugin_init: plugin_init_trampoline,
|
plugin_init: Some(plugin_init_trampoline),
|
||||||
version: $version as *const u8,
|
version: $version as *const u8 as *const c_char,
|
||||||
license: $license as *const u8,
|
license: $license as *const u8 as *const c_char,
|
||||||
source: $source as *const u8,
|
source: $source as *const u8 as *const c_char,
|
||||||
package: $package as *const u8,
|
package: $package as *const u8 as *const c_char,
|
||||||
origin: $origin as *const u8,
|
origin: $origin as *const u8 as *const c_char,
|
||||||
release_datetime: $release_datetime as *const u8,
|
release_datetime: $release_datetime as *const u8 as *const c_char,
|
||||||
_gst_reserved: [0, 0, 0, 0],
|
_gst_reserved: [0 as glib::gpointer; 4],
|
||||||
};
|
});
|
||||||
|
|
||||||
unsafe extern "C" fn plugin_init_trampoline(plugin: *const c_void) -> GBoolean {
|
unsafe extern "C" fn plugin_init_trampoline(plugin: *mut gst::GstPlugin) -> glib::gboolean {
|
||||||
GBoolean::from_bool(super::$plugin_init(&Plugin::new(plugin)))
|
if super::$plugin_init(&Plugin::new(plugin)) {
|
||||||
|
glib::GTRUE
|
||||||
|
} else {
|
||||||
|
glib::GFALSE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -28,6 +28,9 @@ use miniobject::*;
|
||||||
use log::*;
|
use log::*;
|
||||||
use plugin::Plugin;
|
use plugin::Plugin;
|
||||||
|
|
||||||
|
use glib;
|
||||||
|
use gst;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum SinkError {
|
pub enum SinkError {
|
||||||
Failure,
|
Failure,
|
||||||
|
@ -50,7 +53,7 @@ impl ToGError for SinkError {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SinkWrapper {
|
pub struct SinkWrapper {
|
||||||
raw: *mut c_void,
|
raw: *mut gst::GstElement,
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
uri: Mutex<(Option<Url>, bool)>,
|
uri: Mutex<(Option<Url>, bool)>,
|
||||||
uri_validator: Box<UriValidator>,
|
uri_validator: Box<UriValidator>,
|
||||||
|
@ -68,7 +71,7 @@ pub trait Sink {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SinkWrapper {
|
impl SinkWrapper {
|
||||||
fn new(raw: *mut c_void, sink: Box<Sink>) -> SinkWrapper {
|
fn new(raw: *mut gst::GstElement, sink: Box<Sink>) -> SinkWrapper {
|
||||||
SinkWrapper {
|
SinkWrapper {
|
||||||
raw: raw,
|
raw: raw,
|
||||||
logger: Logger::root(GstDebugDrain::new(Some(unsafe { &Element::new(raw) }),
|
logger: Logger::root(GstDebugDrain::new(Some(unsafe { &Element::new(raw) }),
|
||||||
|
@ -141,7 +144,10 @@ impl SinkWrapper {
|
||||||
Err(ref msg) => {
|
Err(ref msg) => {
|
||||||
error!(self.logger, "Failed to start: {:?}", msg);
|
error!(self.logger, "Failed to start: {:?}", msg);
|
||||||
|
|
||||||
self.uri.lock().unwrap().1 = false;
|
self.uri
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.1 = false;
|
||||||
self.post_message(msg);
|
self.post_message(msg);
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
@ -156,7 +162,10 @@ impl SinkWrapper {
|
||||||
match sink.stop() {
|
match sink.stop() {
|
||||||
Ok(..) => {
|
Ok(..) => {
|
||||||
trace!(self.logger, "Stopped successfully");
|
trace!(self.logger, "Stopped successfully");
|
||||||
self.uri.lock().unwrap().1 = false;
|
self.uri
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.1 = false;
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
Err(ref msg) => {
|
Err(ref msg) => {
|
||||||
|
@ -195,7 +204,7 @@ impl SinkWrapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn sink_new(sink: *mut c_void,
|
pub unsafe extern "C" fn sink_new(sink: *mut gst::GstElement,
|
||||||
create_instance: fn(Element) -> Box<Sink>)
|
create_instance: fn(Element) -> Box<Sink>)
|
||||||
-> *mut SinkWrapper {
|
-> *mut SinkWrapper {
|
||||||
let instance = create_instance(Element::new(sink));
|
let instance = create_instance(Element::new(sink));
|
||||||
|
@ -210,11 +219,11 @@ pub unsafe extern "C" fn sink_drop(ptr: *mut SinkWrapper) {
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn sink_set_uri(ptr: *const SinkWrapper,
|
pub unsafe extern "C" fn sink_set_uri(ptr: *const SinkWrapper,
|
||||||
uri_ptr: *const c_char,
|
uri_ptr: *const c_char,
|
||||||
cerr: *mut c_void)
|
cerr: *mut *mut glib::GError)
|
||||||
-> GBoolean {
|
-> glib::gboolean {
|
||||||
let wrap: &SinkWrapper = &*ptr;
|
let wrap: &SinkWrapper = &*ptr;
|
||||||
|
|
||||||
panic_to_error!(wrap, GBoolean::False, {
|
panic_to_error!(wrap, glib::GFALSE, {
|
||||||
let uri_str = if uri_ptr.is_null() {
|
let uri_str = if uri_ptr.is_null() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
|
@ -225,9 +234,9 @@ pub unsafe extern "C" fn sink_set_uri(ptr: *const SinkWrapper,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!(wrap.logger, "Failed to set URI {:?}", err);
|
error!(wrap.logger, "Failed to set URI {:?}", err);
|
||||||
err.into_gerror(cerr);
|
err.into_gerror(cerr);
|
||||||
GBoolean::False
|
glib::GFALSE
|
||||||
}
|
}
|
||||||
Ok(_) => GBoolean::True,
|
Ok(_) => glib::GTRUE,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -245,24 +254,34 @@ pub unsafe extern "C" fn sink_get_uri(ptr: *const SinkWrapper) -> *mut c_char {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn sink_start(ptr: *const SinkWrapper) -> GBoolean {
|
pub unsafe extern "C" fn sink_start(ptr: *const SinkWrapper) -> glib::gboolean {
|
||||||
let wrap: &SinkWrapper = &*ptr;
|
let wrap: &SinkWrapper = &*ptr;
|
||||||
|
|
||||||
panic_to_error!(wrap, GBoolean::False, {
|
panic_to_error!(wrap, glib::GFALSE, {
|
||||||
GBoolean::from_bool(wrap.start())
|
if wrap.start() {
|
||||||
|
glib::GTRUE
|
||||||
|
} else {
|
||||||
|
glib::GFALSE
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn sink_stop(ptr: *const SinkWrapper) -> GBoolean {
|
pub unsafe extern "C" fn sink_stop(ptr: *const SinkWrapper) -> glib::gboolean {
|
||||||
let wrap: &SinkWrapper = &*ptr;
|
let wrap: &SinkWrapper = &*ptr;
|
||||||
panic_to_error!(wrap, GBoolean::True, {
|
panic_to_error!(wrap, glib::GTRUE, {
|
||||||
GBoolean::from_bool(wrap.stop())
|
if wrap.stop() {
|
||||||
|
glib::GTRUE
|
||||||
|
} else {
|
||||||
|
glib::GFALSE
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn sink_render(ptr: *const SinkWrapper, buffer: GstRefPtr) -> GstFlowReturn {
|
pub unsafe extern "C" fn sink_render(ptr: *const SinkWrapper,
|
||||||
|
buffer: GstRefPtr<Buffer>)
|
||||||
|
-> GstFlowReturn {
|
||||||
let wrap: &SinkWrapper = &*ptr;
|
let wrap: &SinkWrapper = &*ptr;
|
||||||
panic_to_error!(wrap, GstFlowReturn::Error, {
|
panic_to_error!(wrap, GstFlowReturn::Error, {
|
||||||
let buffer: GstRef<Buffer> = GstRef::new(&buffer);
|
let buffer: GstRef<Buffer> = GstRef::new(&buffer);
|
||||||
|
@ -283,7 +302,7 @@ pub struct SinkInfo<'a> {
|
||||||
|
|
||||||
pub fn sink_register(plugin: &Plugin, sink_info: &SinkInfo) {
|
pub fn sink_register(plugin: &Plugin, sink_info: &SinkInfo) {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn gst_rs_sink_register(plugin: *const c_void,
|
fn gst_rs_sink_register(plugin: *const gst::GstPlugin,
|
||||||
name: *const c_char,
|
name: *const c_char,
|
||||||
long_name: *const c_char,
|
long_name: *const c_char,
|
||||||
description: *const c_char,
|
description: *const c_char,
|
||||||
|
@ -292,7 +311,7 @@ pub fn sink_register(plugin: &Plugin, sink_info: &SinkInfo) {
|
||||||
rank: i32,
|
rank: i32,
|
||||||
create_instance: *const c_void,
|
create_instance: *const c_void,
|
||||||
protocols: *const c_char)
|
protocols: *const c_char)
|
||||||
-> GBoolean;
|
-> glib::gboolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
let cname = CString::new(sink_info.name).unwrap();
|
let cname = CString::new(sink_info.name).unwrap();
|
||||||
|
|
|
@ -28,6 +28,9 @@ use buffer::*;
|
||||||
use miniobject::*;
|
use miniobject::*;
|
||||||
use log::*;
|
use log::*;
|
||||||
|
|
||||||
|
use glib;
|
||||||
|
use gst;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum SourceError {
|
pub enum SourceError {
|
||||||
Failure,
|
Failure,
|
||||||
|
@ -50,7 +53,7 @@ impl ToGError for SourceError {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SourceWrapper {
|
pub struct SourceWrapper {
|
||||||
raw: *mut c_void,
|
raw: *mut gst::GstElement,
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
uri: Mutex<(Option<Url>, bool)>,
|
uri: Mutex<(Option<Url>, bool)>,
|
||||||
uri_validator: Box<UriValidator>,
|
uri_validator: Box<UriValidator>,
|
||||||
|
@ -71,7 +74,7 @@ pub trait Source {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SourceWrapper {
|
impl SourceWrapper {
|
||||||
fn new(raw: *mut c_void, source: Box<Source>) -> SourceWrapper {
|
fn new(raw: *mut gst::GstElement, source: Box<Source>) -> SourceWrapper {
|
||||||
SourceWrapper {
|
SourceWrapper {
|
||||||
raw: raw,
|
raw: raw,
|
||||||
logger: Logger::root(GstDebugDrain::new(Some(unsafe { &Element::new(raw) }),
|
logger: Logger::root(GstDebugDrain::new(Some(unsafe { &Element::new(raw) }),
|
||||||
|
@ -154,7 +157,10 @@ impl SourceWrapper {
|
||||||
Err(ref msg) => {
|
Err(ref msg) => {
|
||||||
error!(self.logger, "Failed to start: {:?}", msg);
|
error!(self.logger, "Failed to start: {:?}", msg);
|
||||||
|
|
||||||
self.uri.lock().unwrap().1 = false;
|
self.uri
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.1 = false;
|
||||||
self.post_message(msg);
|
self.post_message(msg);
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
@ -169,7 +175,10 @@ impl SourceWrapper {
|
||||||
match source.stop() {
|
match source.stop() {
|
||||||
Ok(..) => {
|
Ok(..) => {
|
||||||
trace!(self.logger, "Stopped successfully");
|
trace!(self.logger, "Stopped successfully");
|
||||||
self.uri.lock().unwrap().1 = false;
|
self.uri
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.1 = false;
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
Err(ref msg) => {
|
Err(ref msg) => {
|
||||||
|
@ -227,7 +236,7 @@ impl SourceWrapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn source_new(source: *mut c_void,
|
pub unsafe extern "C" fn source_new(source: *mut gst::GstElement,
|
||||||
create_instance: fn(Element) -> Box<Source>)
|
create_instance: fn(Element) -> Box<Source>)
|
||||||
-> *mut SourceWrapper {
|
-> *mut SourceWrapper {
|
||||||
let instance = create_instance(Element::new(source));
|
let instance = create_instance(Element::new(source));
|
||||||
|
@ -243,11 +252,11 @@ pub unsafe extern "C" fn source_drop(ptr: *mut SourceWrapper) {
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn source_set_uri(ptr: *const SourceWrapper,
|
pub unsafe extern "C" fn source_set_uri(ptr: *const SourceWrapper,
|
||||||
uri_ptr: *const c_char,
|
uri_ptr: *const c_char,
|
||||||
cerr: *mut c_void)
|
cerr: *mut *mut glib::GError)
|
||||||
-> GBoolean {
|
-> glib::gboolean {
|
||||||
let wrap: &SourceWrapper = &*ptr;
|
let wrap: &SourceWrapper = &*ptr;
|
||||||
|
|
||||||
panic_to_error!(wrap, GBoolean::False, {
|
panic_to_error!(wrap, glib::GFALSE, {
|
||||||
let uri_str = if uri_ptr.is_null() {
|
let uri_str = if uri_ptr.is_null() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
|
@ -258,9 +267,9 @@ pub unsafe extern "C" fn source_set_uri(ptr: *const SourceWrapper,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!(wrap.logger, "Failed to set URI {:?}", err);
|
error!(wrap.logger, "Failed to set URI {:?}", err);
|
||||||
err.into_gerror(cerr);
|
err.into_gerror(cerr);
|
||||||
GBoolean::False
|
glib::GFALSE
|
||||||
}
|
}
|
||||||
Ok(_) => GBoolean::True,
|
Ok(_) => glib::GTRUE,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -277,11 +286,15 @@ pub unsafe extern "C" fn source_get_uri(ptr: *const SourceWrapper) -> *mut c_cha
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn source_is_seekable(ptr: *const SourceWrapper) -> GBoolean {
|
pub unsafe extern "C" fn source_is_seekable(ptr: *const SourceWrapper) -> glib::gboolean {
|
||||||
let wrap: &SourceWrapper = &*ptr;
|
let wrap: &SourceWrapper = &*ptr;
|
||||||
|
|
||||||
panic_to_error!(wrap, GBoolean::False, {
|
panic_to_error!(wrap, glib::GFALSE, {
|
||||||
GBoolean::from_bool(wrap.is_seekable())
|
if wrap.is_seekable() {
|
||||||
|
glib::GTRUE
|
||||||
|
} else {
|
||||||
|
glib::GFALSE
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,20 +307,28 @@ pub unsafe extern "C" fn source_get_size(ptr: *const SourceWrapper) -> u64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn source_start(ptr: *const SourceWrapper) -> GBoolean {
|
pub unsafe extern "C" fn source_start(ptr: *const SourceWrapper) -> glib::gboolean {
|
||||||
let wrap: &SourceWrapper = &*ptr;
|
let wrap: &SourceWrapper = &*ptr;
|
||||||
|
|
||||||
panic_to_error!(wrap, GBoolean::False, {
|
panic_to_error!(wrap, glib::GFALSE, {
|
||||||
GBoolean::from_bool(wrap.start())
|
if wrap.start() {
|
||||||
|
glib::GTRUE
|
||||||
|
} else {
|
||||||
|
glib::GFALSE
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn source_stop(ptr: *const SourceWrapper) -> GBoolean {
|
pub unsafe extern "C" fn source_stop(ptr: *const SourceWrapper) -> glib::gboolean {
|
||||||
let wrap: &SourceWrapper = &*ptr;
|
let wrap: &SourceWrapper = &*ptr;
|
||||||
|
|
||||||
panic_to_error!(wrap, GBoolean::True, {
|
panic_to_error!(wrap, glib::GTRUE, {
|
||||||
GBoolean::from_bool(wrap.stop())
|
if wrap.stop() {
|
||||||
|
glib::GTRUE
|
||||||
|
} else {
|
||||||
|
glib::GFALSE
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,7 +336,7 @@ pub unsafe extern "C" fn source_stop(ptr: *const SourceWrapper) -> GBoolean {
|
||||||
pub unsafe extern "C" fn source_fill(ptr: *const SourceWrapper,
|
pub unsafe extern "C" fn source_fill(ptr: *const SourceWrapper,
|
||||||
offset: u64,
|
offset: u64,
|
||||||
length: u32,
|
length: u32,
|
||||||
buffer: GstRefPtr)
|
buffer: GstRefPtr<Buffer>)
|
||||||
-> GstFlowReturn {
|
-> GstFlowReturn {
|
||||||
let wrap: &SourceWrapper = &*ptr;
|
let wrap: &SourceWrapper = &*ptr;
|
||||||
|
|
||||||
|
@ -326,11 +347,18 @@ pub unsafe extern "C" fn source_fill(ptr: *const SourceWrapper,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn source_seek(ptr: *const SourceWrapper, start: u64, stop: u64) -> GBoolean {
|
pub unsafe extern "C" fn source_seek(ptr: *const SourceWrapper,
|
||||||
|
start: u64,
|
||||||
|
stop: u64)
|
||||||
|
-> glib::gboolean {
|
||||||
let wrap: &SourceWrapper = &*ptr;
|
let wrap: &SourceWrapper = &*ptr;
|
||||||
|
|
||||||
panic_to_error!(wrap, GBoolean::False, {
|
panic_to_error!(wrap, glib::GFALSE, {
|
||||||
GBoolean::from_bool(wrap.seek(start, if stop == u64::MAX { None } else { Some(stop) }))
|
if wrap.seek(start, if stop == u64::MAX { None } else { Some(stop) }) {
|
||||||
|
glib::GTRUE
|
||||||
|
} else {
|
||||||
|
glib::GFALSE
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,7 +377,7 @@ pub struct SourceInfo<'a> {
|
||||||
pub fn source_register(plugin: &Plugin, source_info: &SourceInfo) {
|
pub fn source_register(plugin: &Plugin, source_info: &SourceInfo) {
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn gst_rs_source_register(plugin: *const c_void,
|
fn gst_rs_source_register(plugin: *const gst::GstPlugin,
|
||||||
name: *const c_char,
|
name: *const c_char,
|
||||||
long_name: *const c_char,
|
long_name: *const c_char,
|
||||||
description: *const c_char,
|
description: *const c_char,
|
||||||
|
@ -358,8 +386,8 @@ pub fn source_register(plugin: &Plugin, source_info: &SourceInfo) {
|
||||||
rank: i32,
|
rank: i32,
|
||||||
create_instance: *const c_void,
|
create_instance: *const c_void,
|
||||||
protocols: *const c_char,
|
protocols: *const c_char,
|
||||||
push_only: GBoolean)
|
push_only: glib::gboolean)
|
||||||
-> GBoolean;
|
-> glib::gboolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
let cname = CString::new(source_info.name).unwrap();
|
let cname = CString::new(source_info.name).unwrap();
|
||||||
|
@ -379,6 +407,10 @@ pub fn source_register(plugin: &Plugin, source_info: &SourceInfo) {
|
||||||
source_info.rank,
|
source_info.rank,
|
||||||
source_info.create_instance as *const c_void,
|
source_info.create_instance as *const c_void,
|
||||||
cprotocols.as_ptr(),
|
cprotocols.as_ptr(),
|
||||||
GBoolean::from_bool(source_info.push_only));
|
if source_info.push_only {
|
||||||
|
glib::GTRUE
|
||||||
|
} else {
|
||||||
|
glib::GFALSE
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,16 +6,17 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use std::os::raw::c_void;
|
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use libc::c_char;
|
use std::mem;
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr, CString};
|
||||||
use caps::Caps;
|
use caps::Caps;
|
||||||
use miniobject::*;
|
use miniobject::*;
|
||||||
use tags::TagList;
|
use tags::TagList;
|
||||||
|
|
||||||
pub struct Stream(*mut c_void);
|
use gst;
|
||||||
pub struct StreamCollection(*mut c_void);
|
|
||||||
|
pub struct Stream(*mut gst::GstStream);
|
||||||
|
pub struct StreamCollection(*mut gst::GstStreamCollection);
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
@ -43,30 +44,23 @@ impl Stream {
|
||||||
t: StreamType,
|
t: StreamType,
|
||||||
flags: StreamFlags)
|
flags: StreamFlags)
|
||||||
-> Self {
|
-> Self {
|
||||||
extern "C" {
|
|
||||||
fn gst_stream_new(stream_id: *const c_char,
|
|
||||||
caps: *const c_void,
|
|
||||||
t: StreamType,
|
|
||||||
flags: StreamFlags)
|
|
||||||
-> *mut c_void;
|
|
||||||
}
|
|
||||||
|
|
||||||
let stream_id_cstr = CString::new(stream_id).unwrap();
|
let stream_id_cstr = CString::new(stream_id).unwrap();
|
||||||
let caps = caps.map(|caps| unsafe { caps.as_ptr() }).unwrap_or(ptr::null_mut());
|
let caps = caps.map(|caps| unsafe { caps.as_ptr() }).unwrap_or(ptr::null_mut());
|
||||||
|
|
||||||
Stream(unsafe { gst_stream_new(stream_id_cstr.as_ptr(), caps, t, flags) })
|
Stream(unsafe {
|
||||||
|
gst::gst_stream_new(stream_id_cstr.as_ptr(),
|
||||||
|
caps,
|
||||||
|
mem::transmute(t.bits()),
|
||||||
|
mem::transmute(flags.bits()))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn as_ptr(&self) -> *const c_void {
|
pub unsafe fn as_ptr(&self) -> *const gst::GstStream {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_caps(&self) -> Option<GstRc<Caps>> {
|
pub fn get_caps(&self) -> Option<GstRc<Caps>> {
|
||||||
extern "C" {
|
let ptr = unsafe { gst::gst_stream_get_caps(self.0) };
|
||||||
fn gst_stream_get_caps(stream: *mut c_void) -> *mut c_void;
|
|
||||||
}
|
|
||||||
|
|
||||||
let ptr = unsafe { gst_stream_get_caps(self.0) };
|
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
return None;
|
return None;
|
||||||
|
@ -76,36 +70,20 @@ impl Stream {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_stream_flags(&self) -> StreamFlags {
|
pub fn get_stream_flags(&self) -> StreamFlags {
|
||||||
extern "C" {
|
StreamFlags::from_bits_truncate(unsafe { gst::gst_stream_get_stream_flags(self.0).bits() })
|
||||||
fn gst_stream_get_stream_flags(stream: *mut c_void) -> u32;
|
|
||||||
}
|
|
||||||
|
|
||||||
StreamFlags::from_bits_truncate(unsafe { gst_stream_get_stream_flags(self.0) })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_stream_type(&self) -> StreamType {
|
pub fn get_stream_type(&self) -> StreamType {
|
||||||
extern "C" {
|
StreamType::from_bits_truncate(unsafe { gst::gst_stream_get_stream_type(self.0).bits() })
|
||||||
fn gst_stream_get_stream_type(stream: *mut c_void) -> u32;
|
|
||||||
}
|
|
||||||
|
|
||||||
StreamType::from_bits_truncate(unsafe { gst_stream_get_stream_type(self.0) })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_stream_id(&self) -> &str {
|
pub fn get_stream_id(&self) -> &str {
|
||||||
extern "C" {
|
let cstr = unsafe { CStr::from_ptr(gst::gst_stream_get_stream_id(self.0)) };
|
||||||
fn gst_stream_get_stream_id(collection: *mut c_void) -> *mut c_char;
|
|
||||||
}
|
|
||||||
|
|
||||||
let cstr = unsafe { CStr::from_ptr(gst_stream_get_stream_id(self.0)) };
|
|
||||||
cstr.to_str().unwrap()
|
cstr.to_str().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_tags(&self) -> Option<TagList> {
|
pub fn get_tags(&self) -> Option<TagList> {
|
||||||
extern "C" {
|
let ptr = unsafe { gst::gst_stream_get_tags(self.0) };
|
||||||
fn gst_stream_get_tags(stream: *mut c_void) -> *mut c_void;
|
|
||||||
}
|
|
||||||
|
|
||||||
let ptr = unsafe { gst_stream_get_tags(self.0) };
|
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
return None;
|
return None;
|
||||||
|
@ -115,75 +93,46 @@ impl Stream {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_caps(&self, caps: Option<GstRc<Caps>>) {
|
pub fn set_caps(&self, caps: Option<GstRc<Caps>>) {
|
||||||
extern "C" {
|
|
||||||
fn gst_stream_set_caps(stream: *mut c_void, caps: *mut c_void);
|
|
||||||
}
|
|
||||||
|
|
||||||
let ptr = caps.map(|caps| unsafe { caps.as_ptr() }).unwrap_or(ptr::null_mut());
|
let ptr = caps.map(|caps| unsafe { caps.as_ptr() }).unwrap_or(ptr::null_mut());
|
||||||
|
|
||||||
unsafe { gst_stream_set_caps(self.0, ptr as *mut c_void) }
|
unsafe { gst::gst_stream_set_caps(self.0, ptr) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_stream_flags(&self, flags: StreamFlags) {
|
pub fn set_stream_flags(&self, flags: StreamFlags) {
|
||||||
extern "C" {
|
unsafe { gst::gst_stream_set_stream_flags(self.0, mem::transmute(flags.bits())) }
|
||||||
fn gst_stream_set_stream_flags(stream: *mut c_void, flags: u32);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe { gst_stream_set_stream_flags(self.0, flags.bits()) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_stream_type(&self, t: StreamType) {
|
pub fn set_stream_type(&self, t: StreamType) {
|
||||||
extern "C" {
|
unsafe { gst::gst_stream_set_stream_type(self.0, mem::transmute(t.bits())) }
|
||||||
fn gst_stream_set_stream_type(stream: *mut c_void, t: u32);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe { gst_stream_set_stream_type(self.0, t.bits()) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_tags(&self, tags: Option<TagList>) {
|
pub fn set_tags(&self, tags: Option<TagList>) {
|
||||||
extern "C" {
|
|
||||||
fn gst_stream_set_tags(stream: *mut c_void, tags: *mut c_void);
|
|
||||||
}
|
|
||||||
|
|
||||||
let ptr = tags.map(|tags| unsafe { tags.as_ptr() }).unwrap_or(ptr::null_mut());
|
let ptr = tags.map(|tags| unsafe { tags.as_ptr() }).unwrap_or(ptr::null_mut());
|
||||||
|
|
||||||
unsafe { gst_stream_set_tags(self.0, ptr as *mut c_void) }
|
unsafe { gst::gst_stream_set_tags(self.0, ptr) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for Stream {
|
impl Clone for Stream {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
extern "C" {
|
unsafe { Stream(gst::gst_object_ref(self.0 as *mut gst::GstObject) as *mut gst::GstStream) }
|
||||||
fn gst_object_ref(object: *mut c_void) -> *mut c_void;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe { Stream(gst_object_ref(self.0)) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Stream {
|
impl Drop for Stream {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
extern "C" {
|
unsafe { gst::gst_object_unref(self.0 as *mut gst::GstObject) }
|
||||||
fn gst_object_unref(object: *mut c_void);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe { gst_object_unref(self.0) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StreamCollection {
|
impl StreamCollection {
|
||||||
pub fn new(upstream_id: &str, streams: &[Stream]) -> Self {
|
pub fn new(upstream_id: &str, streams: &[Stream]) -> Self {
|
||||||
extern "C" {
|
|
||||||
fn gst_stream_collection_new(upstream_id: *const c_char) -> *mut c_void;
|
|
||||||
fn gst_stream_collection_add_stream(collection: *mut c_void, stream: *mut c_void);
|
|
||||||
}
|
|
||||||
|
|
||||||
let upstream_id_cstr = CString::new(upstream_id).unwrap();
|
let upstream_id_cstr = CString::new(upstream_id).unwrap();
|
||||||
let collection =
|
let collection =
|
||||||
StreamCollection(unsafe { gst_stream_collection_new(upstream_id_cstr.as_ptr()) });
|
StreamCollection(unsafe { gst::gst_stream_collection_new(upstream_id_cstr.as_ptr()) });
|
||||||
|
|
||||||
for stream in streams {
|
for stream in streams {
|
||||||
unsafe { gst_stream_collection_add_stream(collection.0, stream.clone().0) }
|
unsafe { gst::gst_stream_collection_add_stream(collection.0, stream.clone().0) };
|
||||||
}
|
}
|
||||||
|
|
||||||
collection
|
collection
|
||||||
|
@ -194,11 +143,7 @@ impl StreamCollection {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn len(&self) -> u32 {
|
pub fn len(&self) -> u32 {
|
||||||
extern "C" {
|
unsafe { gst::gst_stream_collection_get_size(self.0) }
|
||||||
fn gst_stream_collection_get_size(collection: *mut c_void) -> u32;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe { gst_stream_collection_get_size(self.0) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn empty(&self) -> bool {
|
pub fn empty(&self) -> bool {
|
||||||
|
@ -206,15 +151,11 @@ impl StreamCollection {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_upstream_id(&self) -> &str {
|
pub fn get_upstream_id(&self) -> &str {
|
||||||
extern "C" {
|
let cstr = unsafe { CStr::from_ptr(gst::gst_stream_collection_get_upstream_id(self.0)) };
|
||||||
fn gst_stream_collection_get_upstream_id(collection: *mut c_void) -> *mut c_char;
|
|
||||||
}
|
|
||||||
|
|
||||||
let cstr = unsafe { CStr::from_ptr(gst_stream_collection_get_upstream_id(self.0)) };
|
|
||||||
cstr.to_str().unwrap()
|
cstr.to_str().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn as_ptr(&self) -> *const c_void {
|
pub unsafe fn as_ptr(&self) -> *const gst::GstStreamCollection {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -239,44 +180,35 @@ impl<'a> Iterator for StreamCollectionIterator<'a> {
|
||||||
type Item = Stream;
|
type Item = Stream;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Stream> {
|
fn next(&mut self) -> Option<Stream> {
|
||||||
extern "C" {
|
|
||||||
fn gst_stream_collection_get_stream(collection: *mut c_void,
|
|
||||||
index: u32)
|
|
||||||
-> *mut c_void;
|
|
||||||
fn gst_object_ref(object: *mut c_void) -> *mut c_void;
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.position == self.length {
|
if self.position == self.length {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let stream = unsafe { gst_stream_collection_get_stream(self.collection.0, self.position) };
|
let stream =
|
||||||
|
unsafe { gst::gst_stream_collection_get_stream(self.collection.0, self.position) };
|
||||||
if stream.is_null() {
|
if stream.is_null() {
|
||||||
self.position = self.length;
|
self.position = self.length;
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
self.position += 1;
|
self.position += 1;
|
||||||
|
|
||||||
Some(unsafe { Stream(gst_object_ref(stream)) })
|
Some(unsafe {
|
||||||
|
Stream(gst::gst_object_ref(stream as *mut gst::GstObject) as *mut gst::GstStream)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for StreamCollection {
|
impl Clone for StreamCollection {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
extern "C" {
|
unsafe {
|
||||||
fn gst_object_ref(object: *mut c_void) -> *mut c_void;
|
StreamCollection(gst::gst_object_ref(self.0 as *mut gst::GstObject) as
|
||||||
|
*mut gst::GstStreamCollection)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe { StreamCollection(gst_object_ref(self.0)) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for StreamCollection {
|
impl Drop for StreamCollection {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
extern "C" {
|
unsafe { gst::gst_object_unref(self.0 as *mut gst::GstObject) }
|
||||||
fn gst_object_unref(object: *mut c_void);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe { gst_object_unref(self.0) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,14 +6,16 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use std::os::raw::c_void;
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use libc::c_char;
|
use std::mem;
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr, CString};
|
||||||
use utils::*;
|
|
||||||
use value::*;
|
use value::*;
|
||||||
use miniobject::*;
|
use miniobject::*;
|
||||||
|
|
||||||
|
use glib;
|
||||||
|
use gobject;
|
||||||
|
use gst;
|
||||||
|
|
||||||
pub trait Tag {
|
pub trait Tag {
|
||||||
type TagType: ValueType;
|
type TagType: ValueType;
|
||||||
fn tag_name() -> &'static str;
|
fn tag_name() -> &'static str;
|
||||||
|
@ -44,9 +46,8 @@ impl_tag!(LanguageCode, String, "language-code");
|
||||||
impl_tag!(Duration, u64, "duration");
|
impl_tag!(Duration, u64, "duration");
|
||||||
impl_tag!(NominalBitrate, u32, "nominal-bitrate");
|
impl_tag!(NominalBitrate, u32, "nominal-bitrate");
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
pub enum MergeMode {
|
pub enum MergeMode {
|
||||||
ReplaceAll = 1,
|
ReplaceAll,
|
||||||
Replace,
|
Replace,
|
||||||
Append,
|
Append,
|
||||||
Prepend,
|
Prepend,
|
||||||
|
@ -54,91 +55,86 @@ pub enum MergeMode {
|
||||||
KeepAll,
|
KeepAll,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl MergeMode {
|
||||||
|
fn to_ffi(&self) -> gst::GstTagMergeMode {
|
||||||
|
match *self {
|
||||||
|
MergeMode::ReplaceAll => gst::GST_TAG_MERGE_REPLACE_ALL,
|
||||||
|
MergeMode::Replace => gst::GST_TAG_MERGE_REPLACE,
|
||||||
|
MergeMode::Append => gst::GST_TAG_MERGE_APPEND,
|
||||||
|
MergeMode::Prepend => gst::GST_TAG_MERGE_PREPEND,
|
||||||
|
MergeMode::Keep => gst::GST_TAG_MERGE_KEEP,
|
||||||
|
MergeMode::KeepAll => gst::GST_TAG_MERGE_KEEP_ALL,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Eq)]
|
#[derive(Eq)]
|
||||||
pub struct TagList(*mut c_void);
|
pub struct TagList(*mut gst::GstTagList);
|
||||||
|
|
||||||
unsafe impl MiniObject for TagList {
|
unsafe impl MiniObject for TagList {
|
||||||
unsafe fn as_ptr(&self) -> *mut c_void {
|
type PtrType = gst::GstTagList;
|
||||||
|
|
||||||
|
unsafe fn as_ptr(&self) -> *mut gst::GstTagList {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn replace_ptr(&mut self, ptr: *mut c_void) {
|
unsafe fn replace_ptr(&mut self, ptr: *mut gst::GstTagList) {
|
||||||
self.0 = ptr
|
self.0 = ptr
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn new_from_ptr(ptr: *mut c_void) -> Self {
|
unsafe fn new_from_ptr(ptr: *mut gst::GstTagList) -> Self {
|
||||||
TagList(ptr)
|
TagList(ptr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TagList {
|
impl TagList {
|
||||||
pub fn new() -> GstRc<Self> {
|
pub fn new() -> GstRc<Self> {
|
||||||
extern "C" {
|
unsafe { GstRc::new_from_owned_ptr(gst::gst_tag_list_new_empty()) }
|
||||||
fn gst_tag_list_new_empty() -> *mut c_void;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe { GstRc::new_from_owned_ptr(gst_tag_list_new_empty()) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add<T: Tag>(&mut self, value: T::TagType, mode: MergeMode)
|
pub fn add<T: Tag>(&mut self, value: T::TagType, mode: MergeMode)
|
||||||
where Value: From<<T as Tag>::TagType>
|
where Value: From<<T as Tag>::TagType>
|
||||||
{
|
{
|
||||||
extern "C" {
|
|
||||||
fn gst_tag_list_add_value(list: *mut c_void,
|
|
||||||
mode: u32,
|
|
||||||
tag: *const c_char,
|
|
||||||
value: *const GValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
let v = Value::from(value);
|
|
||||||
let gvalue = v.to_gvalue();
|
|
||||||
let tag_name = CString::new(T::tag_name()).unwrap();
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
gst_tag_list_add_value(self.0,
|
let v = Value::from(value);
|
||||||
mode as u32,
|
let mut gvalue = v.to_gvalue();
|
||||||
tag_name.as_ptr(),
|
let tag_name = CString::new(T::tag_name()).unwrap();
|
||||||
&gvalue as *const GValue);
|
|
||||||
|
gst::gst_tag_list_add_value(self.0, mode.to_ffi(), tag_name.as_ptr(), &gvalue);
|
||||||
|
|
||||||
|
gobject::g_value_unset(&mut gvalue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get<T: Tag>(&self) -> Option<TypedValue<T::TagType>>
|
pub fn get<T: Tag>(&self) -> Option<TypedValue<T::TagType>>
|
||||||
where Value: From<<T as Tag>::TagType>
|
where Value: From<<T as Tag>::TagType>
|
||||||
{
|
{
|
||||||
extern "C" {
|
unsafe {
|
||||||
fn gst_tag_list_copy_value(value: *mut GValue,
|
let mut gvalue = mem::zeroed();
|
||||||
list: *mut c_void,
|
let tag_name = CString::new(T::tag_name()).unwrap();
|
||||||
tag: *const c_char)
|
|
||||||
-> GBoolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut gvalue = GValue::new();
|
let found = gst::gst_tag_list_copy_value(&mut gvalue, self.0, tag_name.as_ptr());
|
||||||
let tag_name = CString::new(T::tag_name()).unwrap();
|
|
||||||
|
|
||||||
let found = unsafe {
|
if found == glib::GFALSE {
|
||||||
gst_tag_list_copy_value(&mut gvalue as *mut GValue, self.0, tag_name.as_ptr())
|
return None;
|
||||||
};
|
}
|
||||||
|
|
||||||
if !found.to_bool() {
|
let res = match Value::from_gvalue(&gvalue) {
|
||||||
return None;
|
Some(value) => Some(TypedValue::new(value)),
|
||||||
}
|
None => None,
|
||||||
|
};
|
||||||
|
|
||||||
match Value::from_gvalue(&gvalue) {
|
gobject::g_value_unset(&mut gvalue);
|
||||||
Some(value) => Some(TypedValue::new(value)),
|
|
||||||
None => None,
|
res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_string(&self) -> String {
|
pub fn to_string(&self) -> String {
|
||||||
extern "C" {
|
|
||||||
fn gst_tag_list_to_string(tag_list: *mut c_void) -> *mut c_char;
|
|
||||||
fn g_free(ptr: *mut c_char);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = gst_tag_list_to_string(self.0);
|
let ptr = gst::gst_tag_list_to_string(self.0);
|
||||||
let s = CStr::from_ptr(ptr).to_str().unwrap().into();
|
let s = CStr::from_ptr(ptr).to_str().unwrap().into();
|
||||||
g_free(ptr);
|
glib::g_free(ptr as glib::gpointer);
|
||||||
|
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
@ -153,11 +149,7 @@ impl fmt::Debug for TagList {
|
||||||
|
|
||||||
impl PartialEq for TagList {
|
impl PartialEq for TagList {
|
||||||
fn eq(&self, other: &TagList) -> bool {
|
fn eq(&self, other: &TagList) -> bool {
|
||||||
extern "C" {
|
(unsafe { gst::gst_tag_list_is_equal(self.0, other.0) } == glib::GTRUE)
|
||||||
fn gst_tag_list_is_equal(a: *const c_void, b: *const c_void) -> GBoolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe { gst_tag_list_is_equal(self.0, other.0).to_bool() }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,15 +160,10 @@ unsafe impl Send for TagList {}
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::os::raw::c_void;
|
|
||||||
|
|
||||||
fn init() {
|
fn init() {
|
||||||
extern "C" {
|
|
||||||
fn gst_init(argc: *mut c_void, argv: *mut c_void);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
gst_init(ptr::null_mut(), ptr::null_mut());
|
gst::gst_init(ptr::null_mut(), ptr::null_mut());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,11 +7,12 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use libc::c_char;
|
use libc::c_char;
|
||||||
use std::os::raw::c_void;
|
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::i32;
|
use std::i32;
|
||||||
use num_rational::Rational32;
|
use num_rational::Rational32;
|
||||||
|
|
||||||
|
use gst;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
pub enum GstFlowReturn {
|
pub enum GstFlowReturn {
|
||||||
|
@ -23,53 +24,28 @@ pub enum GstFlowReturn {
|
||||||
Error = -5,
|
Error = -5,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
pub struct Element(*mut gst::GstElement);
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
|
||||||
pub enum GBoolean {
|
|
||||||
False = 0,
|
|
||||||
True = 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GBoolean {
|
|
||||||
pub fn from_bool(v: bool) -> GBoolean {
|
|
||||||
if v { GBoolean::True } else { GBoolean::False }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_bool(&self) -> bool {
|
|
||||||
!(*self == GBoolean::False)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Element(*const c_void);
|
|
||||||
|
|
||||||
impl Element {
|
impl Element {
|
||||||
pub unsafe fn new(element: *const c_void) -> Element {
|
pub unsafe fn new(element: *mut gst::GstElement) -> Element {
|
||||||
extern "C" {
|
|
||||||
fn gst_object_ref(object: *const c_void) -> *const c_void;
|
|
||||||
}
|
|
||||||
|
|
||||||
if element.is_null() {
|
if element.is_null() {
|
||||||
panic!("NULL not allowed");
|
panic!("NULL not allowed");
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_object_ref(element);
|
gst::gst_object_ref(element as *mut gst::GstObject);
|
||||||
|
|
||||||
Element(element)
|
Element(element)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn as_ptr(&self) -> *const c_void {
|
pub unsafe fn as_ptr(&self) -> *mut gst::GstElement {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Element {
|
impl Drop for Element {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
extern "C" {
|
|
||||||
fn gst_object_unref(object: *const c_void);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
gst_object_unref(self.0);
|
gst::gst_object_unref(self.0 as *mut gst::GstObject);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,6 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use libc::c_char;
|
|
||||||
use std::os::raw::c_void;
|
|
||||||
use std::ffi::{CString, CStr};
|
use std::ffi::{CString, CStr};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
@ -18,6 +16,10 @@ pub use num_rational::Rational32;
|
||||||
use buffer::*;
|
use buffer::*;
|
||||||
use miniobject::*;
|
use miniobject::*;
|
||||||
|
|
||||||
|
use glib;
|
||||||
|
use gobject;
|
||||||
|
use gst;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
Bool(bool),
|
Bool(bool),
|
||||||
|
@ -58,145 +60,76 @@ impl_value_type!(Rational32, Fraction);
|
||||||
impl_value_type!(GstRc<Buffer>, Buffer);
|
impl_value_type!(GstRc<Buffer>, Buffer);
|
||||||
impl_value_type!(Vec<Value>, Array);
|
impl_value_type!(Vec<Value>, Array);
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct GValue {
|
|
||||||
typ: usize,
|
|
||||||
data: [u64; 2],
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GValue {
|
|
||||||
pub fn new() -> GValue {
|
|
||||||
unsafe { mem::zeroed() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for GValue {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
extern "C" {
|
|
||||||
fn g_value_unset(value: *mut GValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.typ != 0 {
|
|
||||||
unsafe { g_value_unset(self as *mut GValue) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// See gtype.h
|
|
||||||
const TYPE_BOOLEAN: usize = (5 << 2);
|
|
||||||
const TYPE_INT: usize = (6 << 2);
|
|
||||||
const TYPE_UINT: usize = (7 << 2);
|
|
||||||
const TYPE_INT64: usize = (10 << 2);
|
|
||||||
const TYPE_UINT64: usize = (11 << 2);
|
|
||||||
const TYPE_STRING: usize = (16 << 2);
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
fn gst_buffer_get_type() -> usize;
|
|
||||||
fn gst_fraction_get_type() -> usize;
|
|
||||||
fn gst_value_array_get_type() -> usize;
|
|
||||||
}
|
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref TYPE_BUFFER: usize = unsafe { gst_buffer_get_type() };
|
static ref TYPE_BUFFER: glib::GType = unsafe { gst::gst_buffer_get_type() };
|
||||||
static ref TYPE_FRACTION: usize = unsafe { gst_fraction_get_type() };
|
static ref TYPE_FRACTION: glib::GType = unsafe { gst::gst_fraction_get_type() };
|
||||||
static ref TYPE_GST_VALUE_ARRAY: usize = unsafe { gst_value_array_get_type() };
|
static ref TYPE_GST_VALUE_ARRAY: glib::GType = unsafe { gst::gst_value_array_get_type() };
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Value {
|
impl Value {
|
||||||
pub fn to_gvalue(&self) -> GValue {
|
pub unsafe fn to_gvalue(&self) -> gobject::GValue {
|
||||||
extern "C" {
|
let mut gvalue = mem::zeroed();
|
||||||
fn g_value_init(value: *mut GValue, gtype: usize);
|
|
||||||
fn g_value_set_boolean(value: *mut GValue, value: i32);
|
|
||||||
fn g_value_set_int(value: *mut GValue, value: i32);
|
|
||||||
fn g_value_set_uint(value: *mut GValue, value: u32);
|
|
||||||
fn g_value_set_int64(value: *mut GValue, value: i64);
|
|
||||||
fn g_value_set_uint64(value: *mut GValue, value: u64);
|
|
||||||
fn g_value_set_string(value: *mut GValue, value: *const c_char);
|
|
||||||
fn gst_value_set_fraction(value: *mut GValue, value_n: i32, value_d: i32);
|
|
||||||
fn g_value_set_boxed(value: *mut GValue, boxed: *const c_void);
|
|
||||||
fn gst_value_array_append_and_take_value(value: *mut GValue, element: *mut GValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut gvalue = GValue::new();
|
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
Value::Bool(v) => unsafe {
|
Value::Bool(v) => {
|
||||||
g_value_init(&mut gvalue as *mut GValue, TYPE_BOOLEAN);
|
gobject::g_value_init(&mut gvalue, gobject::G_TYPE_BOOLEAN);
|
||||||
g_value_set_boolean(&mut gvalue as *mut GValue, if v { 1 } else { 0 });
|
gobject::g_value_set_boolean(&mut gvalue,
|
||||||
},
|
if v { glib::GTRUE } else { glib::GFALSE });
|
||||||
Value::Int(v) => unsafe {
|
}
|
||||||
g_value_init(&mut gvalue as *mut GValue, TYPE_INT);
|
Value::Int(v) => {
|
||||||
g_value_set_int(&mut gvalue as *mut GValue, v);
|
gobject::g_value_init(&mut gvalue, gobject::G_TYPE_INT);
|
||||||
},
|
gobject::g_value_set_int(&mut gvalue, v);
|
||||||
Value::UInt(v) => unsafe {
|
}
|
||||||
g_value_init(&mut gvalue as *mut GValue, TYPE_UINT);
|
Value::UInt(v) => {
|
||||||
g_value_set_uint(&mut gvalue as *mut GValue, v);
|
gobject::g_value_init(&mut gvalue, gobject::G_TYPE_UINT);
|
||||||
},
|
gobject::g_value_set_uint(&mut gvalue, v);
|
||||||
Value::Int64(v) => unsafe {
|
}
|
||||||
g_value_init(&mut gvalue as *mut GValue, TYPE_INT64);
|
Value::Int64(v) => {
|
||||||
g_value_set_int64(&mut gvalue as *mut GValue, v);
|
gobject::g_value_init(&mut gvalue, gobject::G_TYPE_INT64);
|
||||||
},
|
gobject::g_value_set_int64(&mut gvalue, v);
|
||||||
Value::UInt64(v) => unsafe {
|
}
|
||||||
g_value_init(&mut gvalue as *mut GValue, TYPE_UINT64);
|
Value::UInt64(v) => {
|
||||||
g_value_set_uint64(&mut gvalue as *mut GValue, v);
|
gobject::g_value_init(&mut gvalue, gobject::G_TYPE_UINT64);
|
||||||
},
|
gobject::g_value_set_uint64(&mut gvalue, v);
|
||||||
Value::String(ref v) => unsafe {
|
}
|
||||||
|
Value::String(ref v) => {
|
||||||
let v_cstr = CString::new(String::from(v.clone())).unwrap();
|
let v_cstr = CString::new(String::from(v.clone())).unwrap();
|
||||||
|
|
||||||
g_value_init(&mut gvalue as *mut GValue, TYPE_STRING);
|
gobject::g_value_init(&mut gvalue, gobject::G_TYPE_STRING);
|
||||||
g_value_set_string(&mut gvalue as *mut GValue, v_cstr.as_ptr());
|
gobject::g_value_set_string(&mut gvalue, v_cstr.as_ptr());
|
||||||
},
|
}
|
||||||
Value::Fraction(ref v) => unsafe {
|
Value::Fraction(ref v) => {
|
||||||
g_value_init(&mut gvalue as *mut GValue, *TYPE_FRACTION);
|
gobject::g_value_init(&mut gvalue, *TYPE_FRACTION);
|
||||||
gst_value_set_fraction(&mut gvalue as *mut GValue, *v.numer(), *v.denom());
|
gst::gst_value_set_fraction(&mut gvalue, *v.numer(), *v.denom());
|
||||||
},
|
}
|
||||||
Value::Buffer(ref buffer) => unsafe {
|
Value::Buffer(ref buffer) => {
|
||||||
g_value_init(&mut gvalue as *mut GValue, *TYPE_BUFFER);
|
gobject::g_value_init(&mut gvalue, *TYPE_BUFFER);
|
||||||
g_value_set_boxed(&mut gvalue as *mut GValue, buffer.as_ptr());
|
gobject::g_value_set_boxed(&mut gvalue, buffer.as_ptr() as glib::gconstpointer);
|
||||||
},
|
}
|
||||||
Value::Array(ref array) => unsafe {
|
Value::Array(ref array) => {
|
||||||
g_value_init(&mut gvalue as *mut GValue, *TYPE_GST_VALUE_ARRAY);
|
gobject::g_value_init(&mut gvalue, *TYPE_GST_VALUE_ARRAY);
|
||||||
|
|
||||||
for e in array {
|
for e in array {
|
||||||
let mut e_value = e.to_gvalue();
|
let mut e_value = e.to_gvalue();
|
||||||
gst_value_array_append_and_take_value(&mut gvalue as *mut GValue,
|
gst::gst_value_array_append_and_take_value(&mut gvalue, &mut e_value);
|
||||||
&mut e_value as *mut GValue);
|
|
||||||
// Takes ownership, invalidate GValue
|
|
||||||
e_value.typ = 0;
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gvalue
|
gvalue
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_gvalue(gvalue: &GValue) -> Option<Self> {
|
pub unsafe fn from_gvalue(gvalue: &gobject::GValue) -> Option<Self> {
|
||||||
extern "C" {
|
match gvalue.g_type {
|
||||||
fn g_value_get_boolean(value: *const GValue) -> i32;
|
gobject::G_TYPE_BOOLEAN => {
|
||||||
fn g_value_get_int(value: *const GValue) -> i32;
|
Some(Value::Bool(!(gobject::g_value_get_boolean(gvalue) == 0)))
|
||||||
fn g_value_get_uint(value: *const GValue) -> u32;
|
}
|
||||||
fn g_value_get_int64(value: *const GValue) -> i64;
|
gobject::G_TYPE_INT => Some(Value::Int(gobject::g_value_get_int(gvalue))),
|
||||||
fn g_value_get_uint64(value: *const GValue) -> u64;
|
gobject::G_TYPE_UINT => Some(Value::UInt(gobject::g_value_get_uint(gvalue))),
|
||||||
fn g_value_get_string(value: *const GValue) -> *const c_char;
|
gobject::G_TYPE_INT64 => Some(Value::Int64(gobject::g_value_get_int64(gvalue))),
|
||||||
fn gst_value_get_fraction_numerator(value: *const GValue) -> i32;
|
gobject::G_TYPE_UINT64 => Some(Value::UInt64(gobject::g_value_get_uint64(gvalue))),
|
||||||
fn gst_value_get_fraction_denominator(value: *const GValue) -> i32;
|
gobject::G_TYPE_STRING => {
|
||||||
fn g_value_get_boxed(value: *const GValue) -> *mut c_void;
|
let s = gobject::g_value_get_string(gvalue);
|
||||||
fn gst_value_array_get_size(value: *const GValue) -> u32;
|
|
||||||
fn gst_value_array_get_value(value: *const GValue, index: u32) -> *const GValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
match gvalue.typ {
|
|
||||||
TYPE_BOOLEAN => unsafe {
|
|
||||||
Some(Value::Bool(!(g_value_get_boolean(gvalue as *const GValue) == 0)))
|
|
||||||
},
|
|
||||||
TYPE_INT => unsafe { Some(Value::Int(g_value_get_int(gvalue as *const GValue))) },
|
|
||||||
TYPE_UINT => unsafe { Some(Value::UInt(g_value_get_uint(gvalue as *const GValue))) },
|
|
||||||
TYPE_INT64 => unsafe { Some(Value::Int64(g_value_get_int64(gvalue as *const GValue))) },
|
|
||||||
TYPE_UINT64 => unsafe {
|
|
||||||
Some(Value::UInt64(g_value_get_uint64(gvalue as *const GValue)))
|
|
||||||
},
|
|
||||||
TYPE_STRING => unsafe {
|
|
||||||
let s = g_value_get_string(gvalue as *const GValue);
|
|
||||||
if s.is_null() {
|
if s.is_null() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
@ -206,29 +139,29 @@ impl Value {
|
||||||
Err(_) => None,
|
Err(_) => None,
|
||||||
Ok(s) => Some(Value::String(s.into())),
|
Ok(s) => Some(Value::String(s.into())),
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
typ if typ == *TYPE_FRACTION => unsafe {
|
typ if typ == *TYPE_FRACTION => {
|
||||||
let n = gst_value_get_fraction_numerator(gvalue as *const GValue);
|
let n = gst::gst_value_get_fraction_numerator(gvalue);
|
||||||
let d = gst_value_get_fraction_denominator(gvalue as *const GValue);
|
let d = gst::gst_value_get_fraction_denominator(gvalue);
|
||||||
|
|
||||||
Some(Value::Fraction(Rational32::new(n, d)))
|
Some(Value::Fraction(Rational32::new(n, d)))
|
||||||
},
|
}
|
||||||
typ if typ == *TYPE_BUFFER => unsafe {
|
typ if typ == *TYPE_BUFFER => {
|
||||||
let b = g_value_get_boxed(gvalue as *const GValue);
|
let b = gobject::g_value_get_boxed(gvalue);
|
||||||
|
|
||||||
if b.is_null() {
|
if b.is_null() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(Value::Buffer(GstRc::new_from_unowned_ptr(b)))
|
Some(Value::Buffer(GstRc::new_from_unowned_ptr(b as *mut gst::GstBuffer)))
|
||||||
},
|
}
|
||||||
typ if typ == *TYPE_GST_VALUE_ARRAY => unsafe {
|
typ if typ == *TYPE_GST_VALUE_ARRAY => {
|
||||||
let n = gst_value_array_get_size(gvalue as *const GValue);
|
let n = gst::gst_value_array_get_size(gvalue);
|
||||||
|
|
||||||
let mut vec = Vec::with_capacity(n as usize);
|
let mut vec = Vec::with_capacity(n as usize);
|
||||||
|
|
||||||
for i in 0..n {
|
for i in 0..n {
|
||||||
let val = gst_value_array_get_value(gvalue as *const GValue, i);
|
let val = gst::gst_value_array_get_value(gvalue, i);
|
||||||
|
|
||||||
if val.is_null() {
|
if val.is_null() {
|
||||||
return None;
|
return None;
|
||||||
|
@ -242,7 +175,7 @@ impl Value {
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(Value::Array(vec))
|
Some(Value::Array(vec))
|
||||||
},
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue