Commit f8cebe8a authored by Mathieu Duponchelle's avatar Mathieu Duponchelle 🐸

Generate bindings for gstreamer-rtp

parent 51ea339a
Pipeline #55837 passed with stages
in 10 minutes and 55 seconds
......@@ -18,4 +18,5 @@ members = [
"gstreamer-gl-sys",
"gstreamer-editing-services-sys",
"gstreamer-check-sys",
"gstreamer-rtp-sys",
]
[options]
girs_dir = "gir-files"
library = "GstRtp"
version = "1.0"
min_cfg_version = "1.0"
target_path = "gstreamer-rtp-sys"
work_mode = "sys"
external_libraries = [
"GLib",
"GObject"
]
[external_libraries]
gstreamer="Gst"
gstreamer_base="GstBase"
This diff is collapsed.
[build-dependencies]
pkg-config = "0.3.7"
[dependencies]
libc = "0.2"
[dependencies.glib-sys]
git = "https://github.com/gtk-rs/sys"
[dependencies.gobject-sys]
git = "https://github.com/gtk-rs/sys"
[dependencies.gstreamer-base-sys]
path = "../gstreamer-base-sys"
[dependencies.gstreamer-sys]
path = "../gstreamer-sys"
[dev-dependencies]
shell-words = "0.1.0"
tempdir = "0.3"
[features]
v1_4 = ["v1_2"]
v1_8 = ["v1_4"]
v1_8_1 = ["v1_8"]
v1_12 = ["v1_10"]
v1_14 = ["v1_12"]
v1_2 = []
v1_6 = ["v1_2"]
v1_6_1 = ["v1_6"]
v1_10 = ["v1_6_1"]
v1_16 = ["v1_10"]
dox = []
[lib]
name = "gstreamer_rtp_sys"
[package]
authors = ["Mathieu Duponchelle <mathieu@centricular.com>", "Sebastian Dröge <sebastian@centricular.com>"]
build = "build.rs"
description = "FFI bindings to libgstrtp-1.0"
documentation = "https://slomo.pages.freedesktop.org/rustdocs/gstreamer-sys/gstreamer_rtp_sys/"
homepage = "https://gstreamer.freedesktop.org"
keywords = ["ffi", "gstreamer", "gnome", "multimedia"]
license = "MIT"
links = "gstrtp-1.0"
name = "gstreamer-rtp-sys"
readme = "README.md"
repository = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs-sys"
version = "0.9.0"
["package.metadata.docs.rs"]
features = ["dox", "v1_16"]
# NOTE: The canonical repository for gstreamer-sys has moved to [freedesktop.org GitLab](https://gitlab.freedesktop.org/gstreamer/gstreamer-rs-sys)!
# gstreamer-rtp-sys [![crates.io](https://img.shields.io/crates/v/gstreamer-rtp-sys.svg)](https://crates.io/crates/gstreamer-rtp-sys) [![pipeline status](https://gitlab.freedesktop.org/gstreamer/gstreamer-rs-sys/badges/master/pipeline.svg)](https://gitlab.freedesktop.org/gstreamer/gstreamer-rs-sys/commits/master)
[GStreamer](https://gstreamer.freedesktop.org/) (RTP library) FFI bindings for Rust.
These bindings are providing unsafe FFI API that can be used to interface with
GStreamer. Generally they are meant to be used as the building block for
higher-level abstractions like:
* Bindings for GStreamer applications and plugins: https://gitlab.freedesktop.org/gstreamer/gstreamer-rs
* Various GStreamer plugins written in Rust: https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs
The bindings 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.
## LICENSE
gstreamer-sys and all crates contained here are licensed under the MIT
license ([LICENSE](LICENSE) or http://opensource.org/licenses/MIT).
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 shall be licensed under the MIT license as above,
without any additional terms or conditions.
// This file was generated by gir (https://github.com/gtk-rs/gir @ 8f15e55)
// from gir-files (https://github.com/gtk-rs/gir-files @ ???)
// DO NOT EDIT
#[cfg(not(feature = "dox"))]
extern crate pkg_config;
#[cfg(not(feature = "dox"))]
use pkg_config::{Config, Error};
#[cfg(not(feature = "dox"))]
use std::env;
#[cfg(not(feature = "dox"))]
use std::io;
#[cfg(not(feature = "dox"))]
use std::io::prelude::*;
#[cfg(not(feature = "dox"))]
use std::process;
#[cfg(feature = "dox")]
fn main() {} // prevent linking libraries to avoid documentation failure
#[cfg(not(feature = "dox"))]
fn main() {
if let Err(s) = find() {
let _ = writeln!(io::stderr(), "{}", s);
process::exit(1);
}
}
#[cfg(not(feature = "dox"))]
fn find() -> Result<(), Error> {
let package_name = "gstreamer-rtp-1.0";
let shared_libs = ["gstrtp-1.0"];
let version = if cfg!(feature = "v1_16") {
"1.16"
} else if cfg!(feature = "v1_14") {
"1.14"
} else if cfg!(feature = "v1_12") {
"1.12"
} else if cfg!(feature = "v1_10") {
"1.10"
} else if cfg!(feature = "v1_8") {
"1.8"
} else if cfg!(feature = "v1_6_1") {
"1.6.1"
} else if cfg!(feature = "v1_6") {
"1.6"
} else if cfg!(feature = "v1_4") {
"1.4"
} else if cfg!(feature = "v1_2") {
"1.2"
} else {
"1.0"
};
if let Ok(inc_dir) = env::var("GTK_INCLUDE_DIR") {
println!("cargo:include={}", inc_dir);
}
if let Ok(lib_dir) = env::var("GTK_LIB_DIR") {
for lib_ in shared_libs.iter() {
println!("cargo:rustc-link-lib=dylib={}", lib_);
}
println!("cargo:rustc-link-search=native={}", lib_dir);
return Ok(());
}
let target = env::var("TARGET").expect("TARGET environment variable doesn't exist");
let hardcode_shared_libs = target.contains("windows");
let mut config = Config::new();
config.atleast_version(version);
config.print_system_libs(false);
if hardcode_shared_libs {
config.cargo_metadata(false);
}
match config.probe(package_name) {
Ok(library) => {
if let Ok(paths) = std::env::join_paths(library.include_paths) {
println!("cargo:include={}", paths.to_string_lossy());
}
if hardcode_shared_libs {
for lib_ in shared_libs.iter() {
println!("cargo:rustc-link-lib=dylib={}", lib_);
}
for path in library.link_paths.iter() {
println!(
"cargo:rustc-link-search=native={}",
path.to_str().expect("library path doesn't exist")
);
}
}
Ok(())
}
Err(Error::EnvNoPkgConfig(_)) | Err(Error::Command { .. }) => {
for lib_ in shared_libs.iter() {
println!("cargo:rustc-link-lib=dylib={}", lib_);
}
Ok(())
}
Err(err) => Err(err),
}
}
This diff is collapsed.
// This file was generated by gir (https://github.com/gtk-rs/gir @ 8f15e55)
// from gir-files (https://github.com/gtk-rs/gir-files @ ???)
// DO NOT EDIT
extern crate gstreamer_rtp_sys;
extern crate shell_words;
extern crate tempdir;
use gstreamer_rtp_sys::*;
use std::env;
use std::error::Error;
use std::mem::{align_of, size_of};
use std::path::Path;
use std::process::Command;
use std::str;
static PACKAGES: &[&str] = &["gstreamer-rtp-1.0"];
#[derive(Clone, Debug)]
struct Compiler {
pub args: Vec<String>,
}
impl Compiler {
pub fn new() -> Result<Compiler, Box<Error>> {
let mut args = get_var("CC", "cc")?;
args.push("-Wno-deprecated-declarations".to_owned());
// For %z support in printf when using MinGW.
args.push("-D__USE_MINGW_ANSI_STDIO".to_owned());
args.extend(get_var("CFLAGS", "")?);
args.extend(get_var("CPPFLAGS", "")?);
args.extend(pkg_config_cflags(PACKAGES)?);
Ok(Compiler { args })
}
pub fn define<'a, V: Into<Option<&'a str>>>(&mut self, var: &str, val: V) {
let arg = match val.into() {
None => format!("-D{}", var),
Some(val) => format!("-D{}={}", var, val),
};
self.args.push(arg);
}
pub fn compile(&self, src: &Path, out: &Path) -> Result<(), Box<Error>> {
let mut cmd = self.to_command();
cmd.arg(src);
cmd.arg("-o");
cmd.arg(out);
let status = cmd.spawn()?.wait()?;
if !status.success() {
return Err(format!("compilation command {:?} failed, {}", &cmd, status).into());
}
Ok(())
}
fn to_command(&self) -> Command {
let mut cmd = Command::new(&self.args[0]);
cmd.args(&self.args[1..]);
cmd
}
}
fn get_var(name: &str, default: &str) -> Result<Vec<String>, Box<Error>> {
match env::var(name) {
Ok(value) => Ok(shell_words::split(&value)?),
Err(env::VarError::NotPresent) => Ok(shell_words::split(default)?),
Err(err) => Err(format!("{} {}", name, err).into()),
}
}
fn pkg_config_cflags(packages: &[&str]) -> Result<Vec<String>, Box<Error>> {
if packages.is_empty() {
return Ok(Vec::new());
}
let mut cmd = Command::new("pkg-config");
cmd.arg("--cflags");
cmd.args(packages);
let out = cmd.output()?;
if !out.status.success() {
return Err(format!("command {:?} returned {}", &cmd, out.status).into());
}
let stdout = str::from_utf8(&out.stdout)?;
Ok(shell_words::split(stdout.trim())?)
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
struct Layout {
size: usize,
alignment: usize,
}
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
struct Results {
/// Number of successfully completed tests.
passed: usize,
/// Total number of failed tests (including those that failed to compile).
failed: usize,
/// Number of tests that failed to compile.
failed_to_compile: usize,
}
impl Results {
fn record_passed(&mut self) {
self.passed += 1;
}
fn record_failed(&mut self) {
self.failed += 1;
}
fn record_failed_to_compile(&mut self) {
self.failed += 1;
self.failed_to_compile += 1;
}
fn summary(&self) -> String {
format!(
"{} passed; {} failed (compilation errors: {})",
self.passed, self.failed, self.failed_to_compile
)
}
fn expect_total_success(&self) {
if self.failed == 0 {
println!("OK: {}", self.summary());
} else {
panic!("FAILED: {}", self.summary());
};
}
}
#[test]
fn cross_validate_constants_with_c() {
let tmpdir = tempdir::TempDir::new("abi").expect("temporary directory");
let cc = Compiler::new().expect("configured compiler");
assert_eq!(
"1",
get_c_value(tmpdir.path(), &cc, "1").expect("C constant"),
"failed to obtain correct constant value for 1"
);
let mut results: Results = Default::default();
for (i, &(name, rust_value)) in RUST_CONSTANTS.iter().enumerate() {
match get_c_value(tmpdir.path(), &cc, name) {
Err(e) => {
results.record_failed_to_compile();
eprintln!("{}", e);
}
Ok(ref c_value) => {
if rust_value == c_value {
results.record_passed();
} else {
results.record_failed();
eprintln!(
"Constant value mismatch for {}\nRust: {:?}\nC: {:?}",
name, rust_value, c_value
);
}
}
};
if (i + 1) % 25 == 0 {
println!("constants ... {}", results.summary());
}
}
results.expect_total_success();
}
#[test]
fn cross_validate_layout_with_c() {
let tmpdir = tempdir::TempDir::new("abi").expect("temporary directory");
let cc = Compiler::new().expect("configured compiler");
assert_eq!(
Layout {
size: 1,
alignment: 1
},
get_c_layout(tmpdir.path(), &cc, "char").expect("C layout"),
"failed to obtain correct layout for char type"
);
let mut results: Results = Default::default();
for (i, &(name, rust_layout)) in RUST_LAYOUTS.iter().enumerate() {
match get_c_layout(tmpdir.path(), &cc, name) {
Err(e) => {
results.record_failed_to_compile();
eprintln!("{}", e);
}
Ok(c_layout) => {
if rust_layout == c_layout {
results.record_passed();
} else {
results.record_failed();
eprintln!(
"Layout mismatch for {}\nRust: {:?}\nC: {:?}",
name, rust_layout, &c_layout
);
}
}
};
if (i + 1) % 25 == 0 {
println!("layout ... {}", results.summary());
}
}
results.expect_total_success();
}
fn get_c_layout(dir: &Path, cc: &Compiler, name: &str) -> Result<Layout, Box<Error>> {
let exe = dir.join("layout");
let mut cc = cc.clone();
cc.define("ABI_TYPE_NAME", name);
cc.compile(Path::new("tests/layout.c"), &exe)?;
let mut abi_cmd = Command::new(exe);
let output = abi_cmd.output()?;
if !output.status.success() {
return Err(format!("command {:?} failed, {:?}", &abi_cmd, &output).into());
}
let stdout = str::from_utf8(&output.stdout)?;
let mut words = stdout.trim().split_whitespace();
let size = words.next().unwrap().parse().unwrap();
let alignment = words.next().unwrap().parse().unwrap();
Ok(Layout { size, alignment })
}
fn get_c_value(dir: &Path, cc: &Compiler, name: &str) -> Result<String, Box<Error>> {
let exe = dir.join("constant");
let mut cc = cc.clone();
cc.define("ABI_CONSTANT_NAME", name);
cc.compile(Path::new("tests/constant.c"), &exe)?;
let mut abi_cmd = Command::new(exe);
let output = abi_cmd.output()?;
if !output.status.success() {
return Err(format!("command {:?} failed, {:?}", &abi_cmd, &output).into());
}
let output = str::from_utf8(&output.stdout)?.trim();
if !output.starts_with("###gir test###") || !output.ends_with("###gir test###") {
return Err(format!(
"command {:?} return invalid output, {:?}",
&abi_cmd, &output
)
.into());
}
Ok(String::from(&output[14..(output.len() - 14)]))
}
const RUST_LAYOUTS: &[(&str, Layout)] = &[
(
"GstRTCPBuffer",
Layout {
size: size_of::<GstRTCPBuffer>(),
alignment: align_of::<GstRTCPBuffer>(),
},
),
(
"GstRTCPFBType",
Layout {
size: size_of::<GstRTCPFBType>(),
alignment: align_of::<GstRTCPFBType>(),
},
),
(
"GstRTCPPacket",
Layout {
size: size_of::<GstRTCPPacket>(),
alignment: align_of::<GstRTCPPacket>(),
},
),
(
"GstRTCPSDESType",
Layout {
size: size_of::<GstRTCPSDESType>(),
alignment: align_of::<GstRTCPSDESType>(),
},
),
(
"GstRTCPType",
Layout {
size: size_of::<GstRTCPType>(),
alignment: align_of::<GstRTCPType>(),
},
),
(
"GstRTCPXRType",
Layout {
size: size_of::<GstRTCPXRType>(),
alignment: align_of::<GstRTCPXRType>(),
},
),
(
"GstRTPBaseAudioPayload",
Layout {
size: size_of::<GstRTPBaseAudioPayload>(),
alignment: align_of::<GstRTPBaseAudioPayload>(),
},
),
(
"GstRTPBaseAudioPayloadClass",
Layout {
size: size_of::<GstRTPBaseAudioPayloadClass>(),
alignment: align_of::<GstRTPBaseAudioPayloadClass>(),
},
),
(
"GstRTPBaseDepayload",
Layout {
size: size_of::<GstRTPBaseDepayload>(),
alignment: align_of::<GstRTPBaseDepayload>(),
},
),
(
"GstRTPBaseDepayloadClass",
Layout {
size: size_of::<GstRTPBaseDepayloadClass>(),
alignment: align_of::<GstRTPBaseDepayloadClass>(),
},
),
(
"GstRTPBasePayload",
Layout {
size: size_of::<GstRTPBasePayload>(),
alignment: align_of::<GstRTPBasePayload>(),
},
),
(
"GstRTPBasePayloadClass",
Layout {
size: size_of::<GstRTPBasePayloadClass>(),
alignment: align_of::<GstRTPBasePayloadClass>(),
},
),
(
"GstRTPBuffer",
Layout {
size: size_of::<GstRTPBuffer>(),
alignment: align_of::<GstRTPBuffer>(),
},
),
(
"GstRTPBufferFlags",
Layout {
size: size_of::<GstRTPBufferFlags>(),
alignment: align_of::<GstRTPBufferFlags>(),
},
),
(
"GstRTPBufferMapFlags",
Layout {
size: size_of::<GstRTPBufferMapFlags>(),
alignment: align_of::<GstRTPBufferMapFlags>(),
},
),
(
"GstRTPPayload",
Layout {
size: size_of::<GstRTPPayload>(),
alignment: align_of::<GstRTPPayload>(),
},
),
(
"GstRTPPayloadInfo",
Layout {
size: size_of::<GstRTPPayloadInfo>(),
alignment: align_of::<GstRTPPayloadInfo>(),
},
),
(
"GstRTPProfile",
Layout {
size: size_of::<GstRTPProfile>(),
alignment: align_of::<GstRTPProfile>(),
},
),
(
"GstRTPSourceMeta",
Layout {
size: size_of::<GstRTPSourceMeta>(),
alignment: align_of::<GstRTPSourceMeta>(),
},
),
];
const RUST_CONSTANTS: &[(&str, &str)] = &[
("(gint) GST_RTCP_FB_TYPE_INVALID", "0"),
("GST_RTCP_MAX_BYE_SSRC_COUNT", "31"),
("GST_RTCP_MAX_RB_COUNT", "31"),
("GST_RTCP_MAX_SDES", "255"),
("GST_RTCP_MAX_SDES_ITEM_COUNT", "31"),
("(gint) GST_RTCP_PSFB_TYPE_AFB", "15"),
("(gint) GST_RTCP_PSFB_TYPE_FIR", "4"),
("(gint) GST_RTCP_PSFB_TYPE_PLI", "1"),
("(gint) GST_RTCP_PSFB_TYPE_RPSI", "3"),
("(gint) GST_RTCP_PSFB_TYPE_SLI", "2"),
("(gint) GST_RTCP_PSFB_TYPE_TSTN", "6"),
("(gint) GST_RTCP_PSFB_TYPE_TSTR", "5"),
("(gint) GST_RTCP_PSFB_TYPE_VBCN", "7"),
("GST_RTCP_REDUCED_SIZE_VALID_MASK", "57592"),
("(gint) GST_RTCP_RTPFB_TYPE_NACK", "1"),
("(gint) GST_RTCP_RTPFB_TYPE_RTCP_SR_REQ", "5"),
("(gint) GST_RTCP_RTPFB_TYPE_TMMBN", "4"),
("(gint) GST_RTCP_RTPFB_TYPE_TMMBR", "3"),
("(gint) GST_RTCP_SDES_CNAME", "1"),
("(gint) GST_RTCP_SDES_EMAIL", "3"),
("(gint) GST_RTCP_SDES_END", "0"),
("(gint) GST_RTCP_SDES_INVALID", "-1"),
("(gint) GST_RTCP_SDES_LOC", "5"),
("(gint) GST_RTCP_SDES_NAME", "2"),
("(gint) GST_RTCP_SDES_NOTE", "7"),
("(gint) GST_RTCP_SDES_PHONE", "4"),
("(gint) GST_RTCP_SDES_PRIV", "8"),
("(gint) GST_RTCP_SDES_TOOL", "6"),
("(gint) GST_RTCP_TYPE_APP", "204"),