Commit 160fd103 authored by Sebastian Dröge's avatar Sebastian Dröge 🍵

Add initial bindings for GStreamer base library

https://github.com/sdroege/gstreamer-rs/issues/7
parent 3b0e6843
......@@ -4,6 +4,7 @@ members = [
"gstreamer",
"gstreamer-app",
"gstreamer-audio",
"gstreamer-base",
"gstreamer-player",
"gstreamer-video",
"examples",
......
[options]
girs_dir = "gir-files"
library = "GstBase"
version = "1.0"
min_cfg_version = "1.8"
target_path = "gstreamer-base"
work_mode = "normal"
concurrency = "send+sync"
generate_safety_asserts = true
external_libraries = [
"GLib",
"GObject",
"Gst",
]
generate = [
"GstBase.BaseSrc",
"GstBase.BaseSink",
"GstBase.BaseTransform",
"GstBase.PushSrc",
]
manual = [
"GObject.Object",
"GLib.Bytes",
"Gst.Object",
"Gst.Element",
"Gst.ClockTime",
"Gst.ClockTimeDiff",
"Gst.ClockReturn",
"Gst.FlowReturn",
"Gst.Format",
"Gst.Pad",
]
[[object]]
name = "GstBase.Adapter"
status = "generate"
trait = false
concurrency = "none"
[[object.function]]
name = "map"
# Unsafe
ignore = true
[[object.function]]
name = "unmap"
# Unsafe
ignore = true
[[object.function]]
name = "copy"
# Unsafe
ignore = true
[[object.function]]
name = "push"
# Move Buffer
ignore = true
[[object.function]]
name = "take"
# Useless copying of data
ignore = true
[[object]]
name = "GstBase.FlowCombiner"
status = "generate"
trait = false
concurrency = "none"
[[object]]
name = "Gst.Structure"
status = "manual"
ref_mode = "ref-mut"
[[object]]
name = "Gst.Caps"
status = "manual"
ref_mode = "ref"
[[object]]
name = "Gst.Buffer"
status = "manual"
ref_mode = "ref"
[[object]]
name = "Gst.BufferList"
status = "manual"
ref_mode = "ref"
[[object]]
name = "Gst.Sample"
status = "manual"
ref_mode = "ref"
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html),
specifically the [variant used by Rust](http://doc.crates.io/manifest.html#the-version-field).
## [0.8.0] - 2017-08-31
- Initial release of the autogenerated GStreamer bindings. Older versions
(< 0.8.0) of the bindings can be found [here](https://github.com/arturoc/gstreamer1.0-rs).
The API of the two is incompatible.
[Unreleased]: https://github.com/sdroege/gstreamer-rs/compare/0.8.0...HEAD
[package]
name = "gstreamer-base"
version = "0.9.0"
authors = ["Sebastian Dröge <sebastian@centricular.com>"]
categories = ["api-bindings", "multimedia"]
description = "Rust bindings for GStreamer Base library"
repository = "https://github.com/sdroege/gstreamer-rs"
license = "MIT/Apache-2.0"
readme = "README.md"
homepage = "https://gstreamer.freedesktop.org"
documentation = "https://sdroege.github.io/rustdoc/gstreamer/gstreamer-base"
keywords = ["gstreamer", "multimedia", "audio", "video", "gnome"]
build = "build.rs"
[dependencies]
bitflags = "0.9"
libc = "0.2"
glib-sys = { git = "https://github.com/gtk-rs/sys" }
gobject-sys = { git = "https://github.com/gtk-rs/sys" }
gstreamer-sys = { git = "https://github.com/sdroege/gstreamer-sys", features = ["v1_8"] }
gstreamer-base-sys = { git = "https://github.com/sdroege/gstreamer-sys", features = ["v1_8"] }
glib = { git = "https://github.com/gtk-rs/glib" }
gstreamer = { path = "../gstreamer" }
[build-dependencies.rustdoc-stripper]
version = "0.1"
optional = true
[features]
v1_10 = ["gstreamer-sys/v1_10", "gstreamer-base-sys/v1_10"]
v1_12 = ["gstreamer-sys/v1_12", "gstreamer-base-sys/v1_12", "v1_10"]
embed-lgpl-docs = ["rustdoc-stripper"]
purge-lgpl-docs = ["rustdoc-stripper"]
default-features = []
[badges]
travis-ci = { repository = "sdroege/gstreamer-rs", branch = "master" }
This diff is collapsed.
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
# gstreamer-rs [![crates.io](https://img.shields.io/crates/v/gstreamer-app.svg)](https://crates.io/crates/gstreamer-app) [![Build Status](https://travis-ci.org/sdroege/gstreamer-rs.svg?branch=master)](https://travis-ci.org/sdroege/gstreamer-rs)
[GStreamer](https://gstreamer.freedesktop.org/) (Base library) bindings for Rust.
Documentation can be found [here](https://sdroege.github.io/rustdoc/gstreamer/gstreamer/).
These bindings are providing a safe API that can be used to interface with
GStreamer, e.g. for writing GStreamer-based applications.
For background and motivation, see the [announcement blogpost](https://coaxion.net/blog/2017/07/writing-gstreamer-applications-in-rust/).
The bindings (since 0.8.0) are autogenerated with [gir](https://github.com/gtk-rs/gir/)
based on the [GObject-Introspection](https://wiki.gnome.org/Projects/GObjectIntrospection/)
API metadata provided by the GStreamer project. Older versions before 0.8.0 were manually
written and the repository can be found [here](https://github.com/arturoc/gstreamer1.0-rs).
The API of the two is incompatible.
A crate for writing GStreamer plugins in Rust can be found here: https://github.com/sdroege/gst-plugin-rs
## LICENSE
gstreamer-rs and all crates contained in here are licensed under either of
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or
http://opensource.org/licenses/MIT)
at your option.
GStreamer itself is licensed under the Lesser General Public License version
2.1 or (at your option) any later version:
https://www.gnu.org/licenses/lgpl-2.1.html
## Contribution
Any kinds of contributions are welcome as a pull request.
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in gstreamer-rs by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.
fn main() {
manage_docs();
}
#[cfg(any(feature = "embed-lgpl-docs", feature = "purge-lgpl-docs"))]
fn manage_docs() {
extern crate stripper_lib;
use std::io;
let path = "src";
let ignores: &[&str] = &[];
stripper_lib::loop_over_files(
path.as_ref(),
&mut |w, s| stripper_lib::strip_comments(w, s, &mut io::sink(), true),
&ignores,
false,
);
#[cfg(feature = "embed-lgpl-docs")]
{
let docs = include_str!("../docs/gstreamer-base/docs.md");
let mut infos = stripper_lib::parse_cmts(docs.lines(), true);
stripper_lib::loop_over_files(
path.as_ref(),
&mut |w, s| stripper_lib::regenerate_comments(w, s, &mut infos, true, true),
&ignores,
false,
);
}
}
#[cfg(not(any(feature = "embed-lgpl-docs", feature = "purge-lgpl-docs")))]
fn manage_docs() {}
// Copyright (C) 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.
use ffi;
use glib::translate::*;
use gst;
use Adapter;
impl Adapter {
pub fn copy(&self, offset: usize, dest: &mut [u8]) {
unsafe {
let size = dest.len();
ffi::gst_adapter_copy(
self.to_glib_none().0,
dest.as_mut_ptr() as *mut _,
offset,
size,
);
}
}
pub fn push(&self, buf: gst::Buffer) {
unsafe {
ffi::gst_adapter_push(self.to_glib_none().0, buf.into_ptr());
}
}
}
// This file was generated by gir (6a48033) from gir-files (???)
// DO NOT EDIT
use ffi;
use glib;
use glib::translate::*;
use glib_ffi;
use gobject_ffi;
use gst;
use std::mem;
use std::ptr;
glib_wrapper! {
pub struct Adapter(Object<ffi::GstAdapter>);
match fn {
get_type => || ffi::gst_adapter_get_type(),
}
}
impl Adapter {
pub fn new() -> Adapter {
assert_initialized_main_thread!();
unsafe {
from_glib_full(ffi::gst_adapter_new())
}
}
pub fn available(&self) -> usize {
unsafe {
ffi::gst_adapter_available(self.to_glib_none().0)
}
}
pub fn available_fast(&self) -> usize {
unsafe {
ffi::gst_adapter_available_fast(self.to_glib_none().0)
}
}
pub fn clear(&self) {
unsafe {
ffi::gst_adapter_clear(self.to_glib_none().0);
}
}
pub fn copy_bytes(&self, offset: usize, size: usize) -> Option<glib::Bytes> {
unsafe {
from_glib_full(ffi::gst_adapter_copy_bytes(self.to_glib_none().0, offset, size))
}
}
pub fn distance_from_discont(&self) -> u64 {
unsafe {
ffi::gst_adapter_distance_from_discont(self.to_glib_none().0)
}
}
#[cfg(feature = "v1_10")]
pub fn dts_at_discont(&self) -> gst::ClockTime {
unsafe {
ffi::gst_adapter_dts_at_discont(self.to_glib_none().0)
}
}
pub fn flush(&self, flush: usize) {
unsafe {
ffi::gst_adapter_flush(self.to_glib_none().0, flush);
}
}
pub fn get_buffer(&self, nbytes: usize) -> Option<gst::Buffer> {
unsafe {
from_glib_full(ffi::gst_adapter_get_buffer(self.to_glib_none().0, nbytes))
}
}
pub fn get_buffer_fast(&self, nbytes: usize) -> Option<gst::Buffer> {
unsafe {
from_glib_full(ffi::gst_adapter_get_buffer_fast(self.to_glib_none().0, nbytes))
}
}
pub fn get_buffer_list(&self, nbytes: usize) -> Option<gst::BufferList> {
unsafe {
from_glib_full(ffi::gst_adapter_get_buffer_list(self.to_glib_none().0, nbytes))
}
}
pub fn get_list(&self, nbytes: usize) -> Vec<gst::Buffer> {
unsafe {
FromGlibPtrContainer::from_glib_full(ffi::gst_adapter_get_list(self.to_glib_none().0, nbytes))
}
}
pub fn masked_scan_uint32(&self, mask: u32, pattern: u32, offset: usize, size: usize) -> isize {
unsafe {
ffi::gst_adapter_masked_scan_uint32(self.to_glib_none().0, mask, pattern, offset, size)
}
}
pub fn masked_scan_uint32_peek(&self, mask: u32, pattern: u32, offset: usize, size: usize) -> (isize, u32) {
unsafe {
let mut value = mem::uninitialized();
let ret = ffi::gst_adapter_masked_scan_uint32_peek(self.to_glib_none().0, mask, pattern, offset, size, &mut value);
(ret, value)
}
}
#[cfg(feature = "v1_10")]
pub fn offset_at_discont(&self) -> u64 {
unsafe {
ffi::gst_adapter_offset_at_discont(self.to_glib_none().0)
}
}
pub fn prev_dts(&self) -> (gst::ClockTime, u64) {
unsafe {
let mut distance = mem::uninitialized();
let ret = ffi::gst_adapter_prev_dts(self.to_glib_none().0, &mut distance);
(ret, distance)
}
}
pub fn prev_dts_at_offset(&self, offset: usize) -> (gst::ClockTime, u64) {
unsafe {
let mut distance = mem::uninitialized();
let ret = ffi::gst_adapter_prev_dts_at_offset(self.to_glib_none().0, offset, &mut distance);
(ret, distance)
}
}
#[cfg(feature = "v1_10")]
pub fn prev_offset(&self) -> (u64, u64) {
unsafe {
let mut distance = mem::uninitialized();
let ret = ffi::gst_adapter_prev_offset(self.to_glib_none().0, &mut distance);
(ret, distance)
}
}
pub fn prev_pts(&self) -> (gst::ClockTime, u64) {
unsafe {
let mut distance = mem::uninitialized();
let ret = ffi::gst_adapter_prev_pts(self.to_glib_none().0, &mut distance);
(ret, distance)
}
}
pub fn prev_pts_at_offset(&self, offset: usize) -> (gst::ClockTime, u64) {
unsafe {
let mut distance = mem::uninitialized();
let ret = ffi::gst_adapter_prev_pts_at_offset(self.to_glib_none().0, offset, &mut distance);
(ret, distance)
}
}
#[cfg(feature = "v1_10")]
pub fn pts_at_discont(&self) -> gst::ClockTime {
unsafe {
ffi::gst_adapter_pts_at_discont(self.to_glib_none().0)
}
}
pub fn take_buffer(&self, nbytes: usize) -> Option<gst::Buffer> {
unsafe {
from_glib_full(ffi::gst_adapter_take_buffer(self.to_glib_none().0, nbytes))
}
}
pub fn take_buffer_fast(&self, nbytes: usize) -> Option<gst::Buffer> {
unsafe {
from_glib_full(ffi::gst_adapter_take_buffer_fast(self.to_glib_none().0, nbytes))
}
}
pub fn take_buffer_list(&self, nbytes: usize) -> Option<gst::BufferList> {
unsafe {
from_glib_full(ffi::gst_adapter_take_buffer_list(self.to_glib_none().0, nbytes))
}
}
pub fn take_list(&self, nbytes: usize) -> Vec<gst::Buffer> {
unsafe {
FromGlibPtrContainer::from_glib_full(ffi::gst_adapter_take_list(self.to_glib_none().0, nbytes))
}
}
}
impl Default for Adapter {
fn default() -> Self {
Self::new()
}
}
This diff is collapsed.
// This file was generated by gir (6a48033) from gir-files (???)
// DO NOT EDIT
use ffi;
use glib;
use glib::Value;
use glib::object::Downcast;
use glib::object::IsA;
use glib::signal::SignalHandlerId;
use glib::signal::connect;
use glib::translate::*;
use glib_ffi;
use gobject_ffi;
use gst;
use gst_ffi;
use std::boxed::Box as Box_;
use std::mem;
use std::mem::transmute;
use std::ptr;
glib_wrapper! {
pub struct BaseSrc(Object<ffi::GstBaseSrc>): [
gst::Element => gst_ffi::GstElement,
gst::Object => gst_ffi::GstObject,
];
match fn {
get_type => || ffi::gst_base_src_get_type(),
}
}
unsafe impl Send for BaseSrc {}
unsafe impl Sync for BaseSrc {}
pub trait BaseSrcExt {
//fn get_allocator(&self, allocator: /*Ignored*/gst::Allocator, params: /*Ignored*/gst::AllocationParams);
fn get_blocksize(&self) -> u32;
//fn get_buffer_pool(&self) -> /*Ignored*/Option<gst::BufferPool>;
fn get_do_timestamp(&self) -> bool;
fn is_async(&self) -> bool;
fn is_live(&self) -> bool;
fn new_seamless_segment(&self, start: i64, stop: i64, time: i64) -> bool;
fn query_latency(&self) -> Option<(bool, gst::ClockTime, gst::ClockTime)>;
fn set_async(&self, async: bool);
fn set_automatic_eos(&self, automatic_eos: bool);
fn set_blocksize(&self, blocksize: u32);
fn set_caps(&self, caps: &gst::Caps) -> bool;
fn set_do_timestamp(&self, timestamp: bool);
fn set_dynamic_size(&self, dynamic: bool);
fn set_format(&self, format: gst::Format);
fn set_live(&self, live: bool);
fn start_complete(&self, ret: gst::FlowReturn);
fn start_wait(&self) -> gst::FlowReturn;
fn wait_playing(&self) -> gst::FlowReturn;
fn get_property_num_buffers(&self) -> i32;
fn set_property_num_buffers(&self, num_buffers: i32);
fn get_property_typefind(&self) -> bool;
fn set_property_typefind(&self, typefind: bool);
fn connect_property_blocksize_notify<F: Fn(&Self) + Send + Sync + 'static>(&self, f: F) -> SignalHandlerId;
fn connect_property_do_timestamp_notify<F: Fn(&Self) + Send + Sync + 'static>(&self, f: F) -> SignalHandlerId;
fn connect_property_num_buffers_notify<F: Fn(&Self) + Send + Sync + 'static>(&self, f: F) -> SignalHandlerId;
fn connect_property_typefind_notify<F: Fn(&Self) + Send + Sync + 'static>(&self, f: F) -> SignalHandlerId;
}
impl<O: IsA<BaseSrc> + IsA<glib::object::Object>> BaseSrcExt for O {
//fn get_allocator(&self, allocator: /*Ignored*/gst::Allocator, params: /*Ignored*/gst::AllocationParams) {
// unsafe { TODO: call ffi::gst_base_src_get_allocator() }
//}
fn get_blocksize(&self) -> u32 {
unsafe {
ffi::gst_base_src_get_blocksize(self.to_glib_none().0)
}
}
//fn get_buffer_pool(&self) -> /*Ignored*/Option<gst::BufferPool> {
// unsafe { TODO: call ffi::gst_base_src_get_buffer_pool() }
//}
fn get_do_timestamp(&self) -> bool {
unsafe {
from_glib(ffi::gst_base_src_get_do_timestamp(self.to_glib_none().0))
}
}
fn is_async(&self) -> bool {
unsafe {
from_glib(ffi::gst_base_src_is_async(self.to_glib_none().0))
}
}
fn is_live(&self) -> bool {
unsafe {
from_glib(ffi::gst_base_src_is_live(self.to_glib_none().0))
}
}
fn new_seamless_segment(&self, start: i64, stop: i64, time: i64) -> bool {
unsafe {
from_glib(ffi::gst_base_src_new_seamless_segment(self.to_glib_none().0, start, stop, time))
}
}
fn query_latency(&self) -> Option<(bool, gst::ClockTime, gst::ClockTime)> {
unsafe {
let mut live = mem::uninitialized();
let mut min_latency = mem::uninitialized();
let mut max_latency = mem::uninitialized();
let ret = from_glib(ffi::gst_base_src_query_latency(self.to_glib_none().0, &mut live, &mut min_latency, &mut max_latency));
if ret { Some((from_glib(live), min_latency, max_latency)) } else { None }
}
}
fn set_async(&self, async: bool) {
unsafe {
ffi::gst_base_src_set_async(self.to_glib_none().0, async.to_glib());
}
}
fn set_automatic_eos(&self, automatic_eos: bool) {
unsafe {
ffi::gst_base_src_set_automatic_eos(self.to_glib_none().0, automatic_eos.to_glib());
}
}
fn set_blocksize(&self, blocksize: u32) {
unsafe {
ffi::gst_base_src_set_blocksize(self.to_glib_none().0, blocksize);
}
}
fn set_caps(&self, caps: &gst::Caps) -> bool {
unsafe {
from_glib(ffi::gst_base_src_set_caps(self.to_glib_none().0, caps.to_glib_none().0))
}
}
fn set_do_timestamp(&self, timestamp: bool) {
unsafe {
ffi::gst_base_src_set_do_timestamp(self.to_glib_none().0, timestamp.to_glib());
}
}
fn set_dynamic_size(&self, dynamic: bool) {
unsafe {
ffi::gst_base_src_set_dynamic_size(self.to_glib_none().0, dynamic.to_glib());
}
}
fn set_format(&self, format: gst::Format) {
unsafe {
ffi::gst_base_src_set_format(self.to_glib_none().0, format.to_glib());
}
}
fn set_live(&self, live: bool) {
unsafe {
ffi::gst_base_src_set_live(self.to_glib_none().0, live.to_glib());
}
}
fn start_complete(&self, ret: gst::FlowReturn) {
unsafe {
ffi::gst_base_src_start_complete(self.to_glib_none().0, ret.to_glib());
}
}
fn start_wait(&self) -> gst::FlowReturn {
unsafe {
from_glib(ffi::gst_base_src_start_wait(self.to_glib_none().0))
}
}
fn wait_playing(&self) -> gst::FlowReturn {
unsafe {
from_glib(ffi::gst_base_src_wait_playing(self.to_glib_none().0))
}
}
fn get_property_num_buffers(&self) -> i32 {
let mut value = Value::from(&0);
unsafe {
gobject_ffi::g_object_get_property(self.to_glib_none().0, "num-buffers".to_glib_none().0, value.to_glib_none_mut().0);
}
value.get().unwrap()
}
fn set_property_num_buffers(&self, num_buffers: i32) {
unsafe {
gobject_ffi::g_object_set_property(self.to_glib_none().0, "num-buffers".to_glib_none().0, Value::from(&num_buffers).to_glib_none().0);
}
}
fn get_property_typefind(&self) -> bool {
let mut value = Value::from(&false);
unsafe {
gobject_ffi::g_object_get_property(self.to_glib_none().0, "typefind".to_glib_none().0, value.to_glib_none_mut().0);
}
value.get().unwrap()
}
fn set_property_typefind(&self, typefind: bool) {
unsafe {
gobject_ffi::g_object_set_property(self.to_glib_none().0, "typefind".to_glib_none().0, Value::from(&typefind).to_glib_none().0);