// Copyright (C) 2016-2017 Sebastian Dröge // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use std::os::raw::c_void; use std::ptr; use libc::c_char; use std::ffi::{CStr, CString}; use caps::Caps; use miniobject::*; use tags::TagList; pub struct Stream(*mut c_void); pub struct StreamCollection(*mut c_void); bitflags! { #[repr(C)] pub flags StreamType: u32 { const TYPE_UNKNOWN = 0b00000001, const TYPE_AUDIO = 0b00000010, const TYPE_VIDEO = 0b00000100, const TYPE_CONTAINER = 0b00001000, const TYPE_TEXT = 0b00010000, } } bitflags! { #[repr(C)] pub flags StreamFlags: u32 { const FLAG_SPARSE = 0b00000001, const FLAG_SELECT = 0b00000010, const FLAG_UNSELECT = 0b00000100, } } impl Stream { pub fn new(stream_id: &str, caps: Option>, t: StreamType, flags: StreamFlags) -> 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 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) }) } pub unsafe fn as_ptr(&self) -> *const c_void { self.0 } pub fn get_caps(&self) -> Option> { extern "C" { 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() { return None; } Some(unsafe { GstRc::new_from_owned_ptr(ptr) }) } pub fn get_stream_flags(&self) -> StreamFlags { extern "C" { 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 { extern "C" { 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 { extern "C" { 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() } pub fn get_tags(&self) -> Option { extern "C" { 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() { return None; } Some(unsafe { TagList::new_from_ptr(ptr) }) } pub fn set_caps(&self, caps: Option>) { 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()); unsafe { gst_stream_set_caps(self.0, ptr as *mut c_void) } } pub fn set_stream_flags(&self, flags: StreamFlags) { extern "C" { 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) { extern "C" { 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) { 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()); unsafe { gst_stream_set_tags(self.0, ptr as *mut c_void) } } } impl Clone for Stream { fn clone(&self) -> Self { extern "C" { fn gst_object_ref(object: *mut c_void) -> *mut c_void; } unsafe { Stream(gst_object_ref(self.0)) } } } impl Drop for Stream { fn drop(&mut self) { extern "C" { fn gst_object_unref(object: *mut c_void); } unsafe { gst_object_unref(self.0) } } } impl StreamCollection { 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 collection = StreamCollection(unsafe { gst_stream_collection_new(upstream_id_cstr.as_ptr()) }); for stream in streams { unsafe { gst_stream_collection_add_stream(collection.0, stream.clone().0) } } collection } pub fn streams(&self) -> StreamCollectionIterator { StreamCollectionIterator::new(self) } pub fn len(&self) -> u32 { extern "C" { fn gst_stream_collection_get_size(collection: *mut c_void) -> u32; } unsafe { gst_stream_collection_get_size(self.0) } } pub fn empty(&self) -> bool { self.len() == 0 } pub fn get_upstream_id(&self) -> &str { extern "C" { 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() } pub unsafe fn as_ptr(&self) -> *const c_void { self.0 } } pub struct StreamCollectionIterator<'a> { position: u32, length: u32, collection: &'a StreamCollection, } impl<'a> StreamCollectionIterator<'a> { fn new(collection: &'a StreamCollection) -> Self { StreamCollectionIterator { position: 0, length: collection.len(), collection: collection, } } } impl<'a> Iterator for StreamCollectionIterator<'a> { type Item = Stream; fn next(&mut self) -> Option { 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 { return None; } let stream = unsafe { gst_stream_collection_get_stream(self.collection.0, self.position) }; if stream.is_null() { self.position = self.length; return None; } self.position += 1; Some(unsafe { Stream(gst_object_ref(stream)) }) } } impl Clone for StreamCollection { fn clone(&self) -> Self { extern "C" { fn gst_object_ref(object: *mut c_void) -> *mut c_void; } unsafe { StreamCollection(gst_object_ref(self.0)) } } } impl Drop for StreamCollection { fn drop(&mut self) { extern "C" { fn gst_object_unref(object: *mut c_void); } unsafe { gst_object_unref(self.0) } } }