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