forked from mirrors/gstreamer-rs
examples, audio, pbutils, video: Use AudioCapsBuilder and VideoCapsBuilder
Simplify caps creation code
This commit is contained in:
parent
734afa998b
commit
6d4ad712c7
18 changed files with 67 additions and 93 deletions
|
@ -16,7 +16,6 @@ use gst::prelude::*;
|
|||
use byte_slice_cast::*;
|
||||
|
||||
use std::i16;
|
||||
use std::i32;
|
||||
|
||||
use anyhow::Error;
|
||||
use derive_more::{Display, Error};
|
||||
|
@ -57,11 +56,9 @@ fn create_pipeline() -> Result<gst::Pipeline, Error> {
|
|||
// This can be set after linking the two objects, because format negotiation between
|
||||
// both elements will happen during pre-rolling of the pipeline.
|
||||
appsink.set_caps(Some(
|
||||
&gst::Caps::builder("audio/x-raw")
|
||||
.field("format", gst_audio::AUDIO_FORMAT_S16.to_str())
|
||||
.field("layout", "interleaved")
|
||||
.field("channels", 1i32)
|
||||
.field("rate", gst::IntRange::<i32>::new(1, i32::MAX))
|
||||
&gst_audio::AudioCapsBuilder::new_interleaved()
|
||||
.format(gst_audio::AUDIO_FORMAT_S16)
|
||||
.channels(1)
|
||||
.build(),
|
||||
));
|
||||
|
||||
|
|
|
@ -123,18 +123,9 @@ mod cairo_compositor {
|
|||
// GStreamer about all possible pads that could exist for this type.
|
||||
|
||||
// On all pads we can only handle BGRx.
|
||||
let caps = gst::Caps::builder("video/x-raw")
|
||||
.field("format", gst_video::VideoFormat::Bgrx.to_str())
|
||||
.field("width", gst::IntRange::<i32>::new(1, i32::MAX))
|
||||
.field("height", gst::IntRange::<i32>::new(1, i32::MAX))
|
||||
let caps = gst_video::VideoCapsBuilder::new()
|
||||
.format(gst_video::VideoFormat::Bgrx)
|
||||
.field("pixel-aspect-ratio", gst::Fraction::new(1, 1))
|
||||
.field(
|
||||
"framerate",
|
||||
gst::FractionRange::new(
|
||||
gst::Fraction::new(0, 1),
|
||||
gst::Fraction::new(i32::MAX, 1),
|
||||
),
|
||||
)
|
||||
.build();
|
||||
|
||||
vec![
|
||||
|
|
|
@ -459,8 +459,8 @@ mod video_filter {
|
|||
impl ElementImpl for FdMemoryFadeInVideoFilter {
|
||||
fn pad_templates() -> &'static [PadTemplate] {
|
||||
static PAD_TEMPLATES: Lazy<Vec<PadTemplate>> = Lazy::new(|| {
|
||||
let caps = gst::Caps::builder("video/x-raw")
|
||||
.field("format", "BGRA")
|
||||
let caps = gst_video::VideoCapsBuilder::new()
|
||||
.format(gst_video::VideoFormat::Bgra)
|
||||
.build();
|
||||
vec![
|
||||
PadTemplate::new("sink", PadDirection::Sink, PadPresence::Always, &caps)
|
||||
|
|
|
@ -75,10 +75,10 @@ fn create_pipeline() -> Result<gst::Pipeline, Error> {
|
|||
// Plug in a capsfilter element that will force the videotestsrc and the overlay to work
|
||||
// with images of the size 800x800, and framerate of 15 fps, since my laptop struggles
|
||||
// rendering it at the default 30 fps
|
||||
let caps = gst::Caps::builder("video/x-raw")
|
||||
.field("width", 800i32)
|
||||
.field("height", 800i32)
|
||||
.field("framerate", gst::Fraction::new(15, 1))
|
||||
let caps = gst_video::VideoCapsBuilder::new()
|
||||
.width(800)
|
||||
.height(800)
|
||||
.framerate(gst::Fraction::new(15, 1))
|
||||
.build();
|
||||
capsfilter.set_property("caps", &caps);
|
||||
|
||||
|
|
|
@ -77,9 +77,9 @@ fn create_pipeline() -> Result<gst::Pipeline, Error> {
|
|||
|
||||
// Plug in a capsfilter element that will force the videotestsrc and the cairooverlay to work
|
||||
// with images of the size 800x800.
|
||||
let caps = gst::Caps::builder("video/x-raw")
|
||||
.field("width", 800i32)
|
||||
.field("height", 800i32)
|
||||
let caps = gst_video::VideoCapsBuilder::new()
|
||||
.width(800)
|
||||
.height(800)
|
||||
.build();
|
||||
capsfilter.set_property("caps", &caps);
|
||||
|
||||
|
|
|
@ -222,9 +222,9 @@ fn example_main() -> Result<(), Error> {
|
|||
.field("clock-rate", 90000i32)
|
||||
.build();
|
||||
|
||||
let video_caps = gst::Caps::builder("video/x-raw")
|
||||
.field("width", 1920i32)
|
||||
.field("height", 1080i32)
|
||||
let video_caps = gst_video::VideoCapsBuilder::new()
|
||||
.width(1920)
|
||||
.height(1080)
|
||||
.build();
|
||||
|
||||
src.set_property("address", "127.0.0.1");
|
||||
|
|
|
@ -36,7 +36,6 @@ mod fir_filter {
|
|||
mod imp {
|
||||
use super::*;
|
||||
use std::collections::VecDeque;
|
||||
use std::i32;
|
||||
use std::sync::Mutex;
|
||||
|
||||
// This is the private data of our filter
|
||||
|
@ -86,11 +85,9 @@ mod fir_filter {
|
|||
// GStreamer about all possible pads that could exist for this type.
|
||||
|
||||
// On both of pads we can only handle F32 mono at any sample rate.
|
||||
let caps = gst::Caps::builder("audio/x-raw")
|
||||
.field("format", gst_audio::AUDIO_FORMAT_F32.to_str())
|
||||
.field("rate", gst::IntRange::<i32>::new(1, i32::MAX))
|
||||
.field("channels", 1i32)
|
||||
.field("layout", "interleaved")
|
||||
let caps = gst_audio::AudioCapsBuilder::new_interleaved()
|
||||
.format(gst_audio::AUDIO_FORMAT_F32)
|
||||
.channels(1)
|
||||
.build();
|
||||
|
||||
vec![
|
||||
|
|
|
@ -54,8 +54,8 @@ fn create_pipeline(uri: String, out_path: std::path::PathBuf) -> Result<gst::Pip
|
|||
// This can be set after linking the two objects, because format negotiation between
|
||||
// both elements will happen during pre-rolling of the pipeline.
|
||||
appsink.set_caps(Some(
|
||||
&gst::Caps::builder("video/x-raw")
|
||||
.field("format", gst_video::VideoFormat::Rgbx.to_str())
|
||||
&gst_video::VideoCapsBuilder::new()
|
||||
.format(gst_video::VideoFormat::Rgbx)
|
||||
.build(),
|
||||
));
|
||||
|
||||
|
|
|
@ -547,9 +547,9 @@ impl App {
|
|||
appsink.set_property("emit-signals", false);
|
||||
appsink.set_property("max-buffers", 1u32);
|
||||
|
||||
let caps = gst::Caps::builder("video/x-raw")
|
||||
let caps = gst_video::VideoCapsBuilder::new()
|
||||
.features(&[&gst_gl::CAPS_FEATURE_MEMORY_GL_MEMORY])
|
||||
.field("format", gst_video::VideoFormat::Rgba.to_str())
|
||||
.format(gst_video::VideoFormat::Rgba)
|
||||
.field("texture-target", "2D")
|
||||
.build();
|
||||
appsink.set_caps(Some(&caps));
|
||||
|
|
|
@ -315,7 +315,7 @@ pub trait AudioFormatIteratorExt {
|
|||
fn into_audio_caps(
|
||||
self,
|
||||
layout: crate::AudioLayout,
|
||||
) -> Option<gst::caps::Builder<gst::caps::NoFeature>>;
|
||||
) -> Option<crate::AudioCapsBuilder<gst::caps::NoFeature>>;
|
||||
}
|
||||
|
||||
impl<T> AudioFormatIteratorExt for T
|
||||
|
@ -325,7 +325,7 @@ where
|
|||
fn into_audio_caps(
|
||||
self,
|
||||
layout: crate::AudioLayout,
|
||||
) -> Option<gst::caps::Builder<gst::caps::NoFeature>> {
|
||||
) -> Option<crate::AudioCapsBuilder<gst::caps::NoFeature>> {
|
||||
let formats: Vec<crate::AudioFormat> = self.collect();
|
||||
if !formats.is_empty() {
|
||||
Some(crate::functions::audio_make_raw_caps(&formats, layout))
|
||||
|
@ -339,7 +339,7 @@ pub trait AudioFormatIteratorExtRef {
|
|||
fn into_audio_caps(
|
||||
self,
|
||||
layout: crate::AudioLayout,
|
||||
) -> Option<gst::caps::Builder<gst::caps::NoFeature>>;
|
||||
) -> Option<crate::AudioCapsBuilder<gst::caps::NoFeature>>;
|
||||
}
|
||||
|
||||
impl<'a, T> AudioFormatIteratorExtRef for T
|
||||
|
@ -349,7 +349,7 @@ where
|
|||
fn into_audio_caps(
|
||||
self,
|
||||
layout: crate::AudioLayout,
|
||||
) -> Option<gst::caps::Builder<gst::caps::NoFeature>> {
|
||||
) -> Option<crate::AudioCapsBuilder<gst::caps::NoFeature>> {
|
||||
let formats: Vec<crate::AudioFormat> = self.copied().collect();
|
||||
if !formats.is_empty() {
|
||||
Some(crate::functions::audio_make_raw_caps(&formats, layout))
|
||||
|
@ -416,7 +416,7 @@ mod tests {
|
|||
.into_audio_caps(crate::AudioLayout::Interleaved)
|
||||
.unwrap()
|
||||
.build();
|
||||
assert_eq!(caps.to_string(), "audio/x-raw, format=(string){ S16LE, S16BE }, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], layout=(string)interleaved");
|
||||
assert_eq!(caps.to_string(), "audio/x-raw, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], layout=(string)interleaved, format=(string){ S16LE, S16BE }");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -468,11 +468,10 @@ mod tests {
|
|||
fn test_from_to_caps() {
|
||||
gst::init().unwrap();
|
||||
|
||||
let caps = gst::Caps::builder("audio/x-raw")
|
||||
.field("format", "S16LE")
|
||||
.field("rate", 48000)
|
||||
.field("channels", 2)
|
||||
.field("layout", "interleaved")
|
||||
let caps = crate::AudioCapsBuilder::new_interleaved()
|
||||
.format(crate::AudioFormat::S16le)
|
||||
.rate(48000)
|
||||
.channels(2)
|
||||
.field("channel-mask", gst::Bitmask::new(0x3))
|
||||
.build();
|
||||
let info = AudioInfo::from_caps(&caps).unwrap();
|
||||
|
|
|
@ -119,6 +119,7 @@ impl<T> AudioCapsBuilder<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn build(self) -> gst::Caps {
|
||||
self.builder.build()
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// Take a look at the license at the top of the repository in the LICENSE file.
|
||||
|
||||
use glib::translate::{from_glib_full, IntoGlibPtr, ToGlibPtr};
|
||||
use glib::ToSendValue;
|
||||
|
||||
use std::i32;
|
||||
|
||||
|
@ -48,19 +47,16 @@ pub fn audio_buffer_truncate(
|
|||
pub fn audio_make_raw_caps(
|
||||
formats: &[crate::AudioFormat],
|
||||
layout: crate::AudioLayout,
|
||||
) -> gst::caps::Builder<gst::caps::NoFeature> {
|
||||
) -> crate::AudioCapsBuilder<gst::caps::NoFeature> {
|
||||
assert_initialized_main_thread!();
|
||||
|
||||
let formats = formats.iter().map(|f| match f {
|
||||
let formats = formats.iter().copied().map(|f| match f {
|
||||
crate::AudioFormat::Encoded => panic!("Invalid encoded format"),
|
||||
crate::AudioFormat::Unknown => panic!("Invalid unknown format"),
|
||||
_ => f.to_string().to_send_value(),
|
||||
_ => f,
|
||||
});
|
||||
|
||||
let builder = gst::caps::Caps::builder("audio/x-raw")
|
||||
.field("format", gst::List::from_values(formats))
|
||||
.field("rate", gst::IntRange::new(1, i32::MAX))
|
||||
.field("channels", gst::IntRange::new(1, i32::MAX));
|
||||
let builder = crate::AudioCapsBuilder::new().format_list(formats);
|
||||
|
||||
match layout {
|
||||
crate::AudioLayout::Interleaved => builder.field("layout", "interleaved"),
|
||||
|
@ -82,7 +78,7 @@ mod tests {
|
|||
crate::AudioLayout::Interleaved,
|
||||
)
|
||||
.build();
|
||||
assert_eq!(caps.to_string(), "audio/x-raw, format=(string){ S16BE, S16LE }, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], layout=(string)interleaved");
|
||||
assert_eq!(caps.to_string(), "audio/x-raw, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], layout=(string)interleaved, format=(string){ S16BE, S16LE }");
|
||||
|
||||
#[cfg(feature = "v1_18")]
|
||||
{
|
||||
|
@ -109,12 +105,12 @@ mod tests {
|
|||
&[crate::AudioFormat::S16be, crate::AudioFormat::S16le],
|
||||
crate::AudioLayout::NonInterleaved,
|
||||
)
|
||||
.field("rate", 16000)
|
||||
.field("channels", 2)
|
||||
.rate(16000)
|
||||
.channels(2)
|
||||
.build();
|
||||
assert_eq!(
|
||||
caps.to_string(),
|
||||
"audio/x-raw, format=(string){ S16BE, S16LE }, rate=(int)16000, channels=(int)2, layout=(string)non-interleaved"
|
||||
"audio/x-raw, rate=(int)16000, channels=(int)2, layout=(string)non-interleaved, format=(string){ S16BE, S16LE }",
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -637,8 +637,8 @@ mod tests {
|
|||
|
||||
let caps = gst::Caps::builder("audio/x-raw").build();
|
||||
|
||||
let restriction = gst::Caps::builder("audio/x-raw")
|
||||
.field("format", "S32LE")
|
||||
let restriction = gst_audio::AudioCapsBuilder::new()
|
||||
.format(gst_audio::AudioFormat::S32le)
|
||||
.build();
|
||||
|
||||
let audio_profile = EncodingAudioProfile::builder(&caps)
|
||||
|
@ -665,8 +665,8 @@ mod tests {
|
|||
assert_eq!(audio_profile.allows_dynamic_output(), ALLOW_DYNAMIC_OUTPUT);
|
||||
assert_eq!(audio_profile.is_enabled(), ENABLED);
|
||||
|
||||
let restriction = gst::Caps::builder("audio/x-raw")
|
||||
.field("format", "S32BE")
|
||||
let restriction = gst_audio::AudioCapsBuilder::new()
|
||||
.format(gst_audio::AudioFormat::S32be)
|
||||
.build();
|
||||
audio_profile.set_restriction(Some(&restriction));
|
||||
assert_eq!(audio_profile.restriction().unwrap(), restriction);
|
||||
|
@ -678,8 +678,8 @@ mod tests {
|
|||
|
||||
let caps = gst::Caps::builder("video/x-raw").build();
|
||||
|
||||
let restriction = gst::Caps::builder("video/x-raw")
|
||||
.field("format", "RGBA")
|
||||
let restriction = gst_video::VideoCapsBuilder::new()
|
||||
.format(gst_video::VideoFormat::Rgba)
|
||||
.build();
|
||||
|
||||
let video_profile = EncodingVideoProfile::builder(&caps)
|
||||
|
@ -713,8 +713,8 @@ mod tests {
|
|||
assert_eq!(video_profile.is_variableframerate(), VARIABLE_FRAMERATE);
|
||||
assert_eq!(video_profile.pass(), PASS);
|
||||
|
||||
let restriction = gst::Caps::builder("video/x-raw")
|
||||
.field("format", "NV12")
|
||||
let restriction = gst_video::VideoCapsBuilder::new()
|
||||
.format(gst_video::VideoFormat::Nv12)
|
||||
.build();
|
||||
video_profile.set_restriction(Some(&restriction));
|
||||
assert_eq!(video_profile.restriction().unwrap(), restriction);
|
||||
|
|
|
@ -182,6 +182,7 @@ impl<T> VideoCapsBuilder<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn build(self) -> gst::Caps {
|
||||
self.builder.build()
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// Take a look at the license at the top of the repository in the LICENSE file.
|
||||
|
||||
use glib::translate::{from_glib, from_glib_full, IntoGlib, ToGlibPtr};
|
||||
use glib::ToSendValue;
|
||||
|
||||
use std::i32;
|
||||
use std::mem;
|
||||
|
@ -214,23 +213,16 @@ pub fn is_common_aspect_ratio(width: u32, height: u32, par: gst::Fraction) -> bo
|
|||
|
||||
pub fn video_make_raw_caps(
|
||||
formats: &[crate::VideoFormat],
|
||||
) -> gst::caps::Builder<gst::caps::NoFeature> {
|
||||
) -> crate::VideoCapsBuilder<gst::caps::NoFeature> {
|
||||
assert_initialized_main_thread!();
|
||||
|
||||
let formats = formats.iter().map(|f| match f {
|
||||
let formats = formats.iter().copied().map(|f| match f {
|
||||
crate::VideoFormat::Encoded => panic!("Invalid encoded format"),
|
||||
crate::VideoFormat::Unknown => panic!("Invalid unknown format"),
|
||||
_ => f.to_string().to_send_value(),
|
||||
_ => f,
|
||||
});
|
||||
|
||||
gst::caps::Caps::builder("video/x-raw")
|
||||
.field("format", gst::List::from_values(formats))
|
||||
.field("width", gst::IntRange::new(1, i32::MAX))
|
||||
.field("height", gst::IntRange::new(1, i32::MAX))
|
||||
.field(
|
||||
"framerate",
|
||||
gst::FractionRange::new(gst::Fraction::new(0, 1), gst::Fraction::new(i32::MAX, 1)),
|
||||
)
|
||||
crate::VideoCapsBuilder::new().format_list(formats)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -321,9 +313,9 @@ mod tests {
|
|||
}
|
||||
|
||||
let caps = video_make_raw_caps(&[crate::VideoFormat::Nv12, crate::VideoFormat::Nv16])
|
||||
.field("width", 800)
|
||||
.field("height", 600)
|
||||
.field("framerate", gst::Fraction::new(30, 1))
|
||||
.width(800)
|
||||
.height(600)
|
||||
.framerate(gst::Fraction::new(30, 1))
|
||||
.build();
|
||||
assert_eq!(caps.to_string(), "video/x-raw, format=(string){ NV12, NV16 }, width=(int)800, height=(int)600, framerate=(fraction)30/1");
|
||||
}
|
||||
|
|
|
@ -407,14 +407,14 @@ impl DoubleEndedIterator for VideoFormatIterator {
|
|||
}
|
||||
}
|
||||
pub trait VideoFormatIteratorExt {
|
||||
fn into_video_caps(self) -> Option<gst::caps::Builder<gst::caps::NoFeature>>;
|
||||
fn into_video_caps(self) -> Option<crate::VideoCapsBuilder<gst::caps::NoFeature>>;
|
||||
}
|
||||
|
||||
impl<T> VideoFormatIteratorExt for T
|
||||
where
|
||||
T: Iterator<Item = crate::VideoFormat>,
|
||||
{
|
||||
fn into_video_caps(self) -> Option<gst::caps::Builder<gst::caps::NoFeature>> {
|
||||
fn into_video_caps(self) -> Option<crate::VideoCapsBuilder<gst::caps::NoFeature>> {
|
||||
let formats: Vec<crate::VideoFormat> = self.collect();
|
||||
if !formats.is_empty() {
|
||||
Some(crate::functions::video_make_raw_caps(&formats))
|
||||
|
@ -425,14 +425,14 @@ where
|
|||
}
|
||||
|
||||
pub trait VideoFormatIteratorExtRef {
|
||||
fn into_video_caps(self) -> Option<gst::caps::Builder<gst::caps::NoFeature>>;
|
||||
fn into_video_caps(self) -> Option<crate::VideoCapsBuilder<gst::caps::NoFeature>>;
|
||||
}
|
||||
|
||||
impl<'a, T> VideoFormatIteratorExtRef for T
|
||||
where
|
||||
T: Iterator<Item = &'a crate::VideoFormat>,
|
||||
{
|
||||
fn into_video_caps(self) -> Option<gst::caps::Builder<gst::caps::NoFeature>> {
|
||||
fn into_video_caps(self) -> Option<crate::VideoCapsBuilder<gst::caps::NoFeature>> {
|
||||
let formats: Vec<crate::VideoFormat> = self.copied().collect();
|
||||
if !formats.is_empty() {
|
||||
Some(crate::functions::video_make_raw_caps(&formats))
|
||||
|
|
|
@ -1038,11 +1038,11 @@ mod tests {
|
|||
fn test_from_to_caps() {
|
||||
gst::init().unwrap();
|
||||
|
||||
let caps = gst::Caps::builder("video/x-raw")
|
||||
.field("format", "I420")
|
||||
.field("width", 320)
|
||||
.field("height", 240)
|
||||
.field("framerate", gst::Fraction::new(30, 1))
|
||||
let caps = crate::VideoCapsBuilder::new()
|
||||
.format(crate::VideoFormat::I420)
|
||||
.width(320)
|
||||
.height(240)
|
||||
.framerate(gst::Fraction::new(30, 1))
|
||||
.field("pixel-aspect-ratio", gst::Fraction::new(1, 1))
|
||||
.field("interlace-mode", "progressive")
|
||||
.field("chroma-site", "mpeg2")
|
||||
|
|
Loading…
Reference in a new issue