forked from mirrors/gstreamer-rs
encoding_profile: add builders for all types
This commit is contained in:
parent
67bdfee1f6
commit
861f052c3d
5 changed files with 339 additions and 7 deletions
|
@ -2,6 +2,8 @@
|
||||||
extern crate gstreamer as gst;
|
extern crate gstreamer as gst;
|
||||||
use gst::prelude::*;
|
use gst::prelude::*;
|
||||||
|
|
||||||
|
extern crate gstreamer_pbutils as pbutils;
|
||||||
|
|
||||||
extern crate glib;
|
extern crate glib;
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
|
@ -32,7 +34,36 @@ struct ErrorMessage {
|
||||||
cause: glib::Error,
|
cause: glib::Error,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn configure_encodebin(encodebin: &gst::Element) {
|
fn configure_encodebin(encodebin: &gst::Element) -> Result<(), Error> {
|
||||||
|
let audio_profile = pbutils::EncodingAudioProfileBuilder::new()
|
||||||
|
.format(&gst::Caps::new_simple(
|
||||||
|
"audio/x-vorbis",
|
||||||
|
&[],
|
||||||
|
))
|
||||||
|
.presence(0)
|
||||||
|
.build()?;
|
||||||
|
|
||||||
|
let video_profile = pbutils::EncodingVideoProfileBuilder::new()
|
||||||
|
.format(&gst::Caps::new_simple(
|
||||||
|
"video/x-theora",
|
||||||
|
&[],
|
||||||
|
))
|
||||||
|
.presence(0)
|
||||||
|
.build()?;
|
||||||
|
|
||||||
|
let container_profile = pbutils::EncodingContainerProfileBuilder::new()
|
||||||
|
.name("container")
|
||||||
|
.format(&gst::Caps::new_simple(
|
||||||
|
"video/x-matroska",
|
||||||
|
&[],
|
||||||
|
))
|
||||||
|
.add_profile(&(video_profile.upcast()))
|
||||||
|
.add_profile(&(audio_profile.upcast()))
|
||||||
|
.build()?;
|
||||||
|
|
||||||
|
encodebin.set_property("profile", &container_profile)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn example_main() -> Result<(), Error> {
|
fn example_main() -> Result<(), Error> {
|
||||||
|
@ -58,18 +89,18 @@ fn example_main() -> Result<(), Error> {
|
||||||
src.set_property("uri", &uri)?;
|
src.set_property("uri", &uri)?;
|
||||||
sink.set_property("location", &output_file)?;
|
sink.set_property("location", &output_file)?;
|
||||||
|
|
||||||
configure_encodebin(&encodebin);
|
configure_encodebin(&encodebin)?;
|
||||||
|
|
||||||
pipeline.add_many(&[&src, &encodebin, &sink])?;
|
pipeline.add_many(&[&src, &encodebin, &sink])?;
|
||||||
gst::Element::link_many(&[&encodebin, &sink])?;
|
gst::Element::link_many(&[&encodebin, &sink])?;
|
||||||
|
|
||||||
// Need to move a new reference into the closure
|
// Need to move a new reference into the closure
|
||||||
let pipeline_clone = pipeline.clone();
|
let pipeline_clone = pipeline.clone();
|
||||||
src.connect_pad_added(move |dbin, src_pad| {
|
src.connect_pad_added(move |dbin, dbin_src_pad| {
|
||||||
let pipeline = &pipeline_clone;
|
let pipeline = &pipeline_clone;
|
||||||
|
|
||||||
let (is_audio, is_video) = {
|
let (is_audio, is_video) = {
|
||||||
let media_type = src_pad.get_current_caps().and_then(|caps| {
|
let media_type = dbin_src_pad.get_current_caps().and_then(|caps| {
|
||||||
caps.get_structure(0).map(|s| {
|
caps.get_structure(0).map(|s| {
|
||||||
let name = s.get_name();
|
let name = s.get_name();
|
||||||
(name.starts_with("audio/"), name.starts_with("video/"))
|
(name.starts_with("audio/"), name.starts_with("video/"))
|
||||||
|
@ -81,7 +112,7 @@ fn example_main() -> Result<(), Error> {
|
||||||
gst_element_warning!(
|
gst_element_warning!(
|
||||||
dbin,
|
dbin,
|
||||||
gst::CoreError::Negotiation,
|
gst::CoreError::Negotiation,
|
||||||
("Failed to get media type from pad {}", src_pad.get_name())
|
("Failed to get media type from pad {}", dbin_src_pad.get_name())
|
||||||
);
|
);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -112,7 +143,7 @@ fn example_main() -> Result<(), Error> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let sink_pad = queue.get_static_pad("sink").expect("queue has no sinkpad");
|
let sink_pad = queue.get_static_pad("sink").expect("queue has no sinkpad");
|
||||||
src_pad.link(&sink_pad).into_result()?;
|
dbin_src_pad.link(&sink_pad).into_result()?;
|
||||||
} else if is_video {
|
} else if is_video {
|
||||||
let queue =
|
let queue =
|
||||||
gst::ElementFactory::make("queue", None).ok_or(MissingElement("queue"))?;
|
gst::ElementFactory::make("queue", None).ok_or(MissingElement("queue"))?;
|
||||||
|
@ -134,7 +165,7 @@ fn example_main() -> Result<(), Error> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let sink_pad = queue.get_static_pad("sink").expect("queue has no sinkpad");
|
let sink_pad = queue.get_static_pad("sink").expect("queue has no sinkpad");
|
||||||
src_pad.link(&sink_pad).into_result()?;
|
dbin_src_pad.link(&sink_pad).into_result()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
84
gstreamer-pbutils/src/encoding_audio_profile.rs
Normal file
84
gstreamer-pbutils/src/encoding_audio_profile.rs
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
|
||||||
|
use gst;
|
||||||
|
|
||||||
|
use std::error;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
use auto::EncodingAudioProfile;
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct EncodingAudioProfileBuilderError;
|
||||||
|
|
||||||
|
impl fmt::Display for EncodingAudioProfileBuilderError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "failed to build encoding audio profile")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl error::Error for EncodingAudioProfileBuilderError {
|
||||||
|
fn description(&self) -> &str {
|
||||||
|
"invalid parameters to build encoding audio profile"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cause(&self) -> Option<&error::Error> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct EncodingAudioProfileBuilder<'a> {
|
||||||
|
format: Option<& 'a gst::Caps>,
|
||||||
|
preset: Option<& 'a str>,
|
||||||
|
restriction: Option<& 'a gst::Caps>,
|
||||||
|
presence: u32
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> EncodingAudioProfileBuilder<'a> {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
EncodingAudioProfileBuilder {
|
||||||
|
format: None,
|
||||||
|
preset: None,
|
||||||
|
restriction: None,
|
||||||
|
presence: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(self) -> Result<EncodingAudioProfile, EncodingAudioProfileBuilderError> {
|
||||||
|
if self.format.is_none() {
|
||||||
|
return Err(EncodingAudioProfileBuilderError);
|
||||||
|
}
|
||||||
|
|
||||||
|
let profile = EncodingAudioProfile::new(
|
||||||
|
self.format.unwrap(), self.preset, self.restriction, self.presence);
|
||||||
|
|
||||||
|
Ok(profile)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn format(self, format: & 'a gst::Caps) -> Self {
|
||||||
|
Self {
|
||||||
|
format: Some(format),
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn restriction(self, restriction: & 'a gst::Caps) -> Self {
|
||||||
|
Self {
|
||||||
|
restriction: Some(restriction),
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn preset(self, preset: & 'a str) -> Self {
|
||||||
|
Self {
|
||||||
|
preset: Some(preset),
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn presence(self, presence: u32) -> Self {
|
||||||
|
Self {
|
||||||
|
presence: presence,
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
99
gstreamer-pbutils/src/encoding_container_profile.rs
Normal file
99
gstreamer-pbutils/src/encoding_container_profile.rs
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
|
||||||
|
use gst;
|
||||||
|
|
||||||
|
use std::error;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
use auto::EncodingProfile;
|
||||||
|
use auto::EncodingContainerProfile;
|
||||||
|
use auto::EncodingContainerProfileExt;
|
||||||
|
|
||||||
|
use std::collections::LinkedList;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct EncodingContainerProfileBuilderError;
|
||||||
|
|
||||||
|
impl fmt::Display for EncodingContainerProfileBuilderError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "failed to build encoding video profile")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl error::Error for EncodingContainerProfileBuilderError {
|
||||||
|
fn description(&self) -> &str {
|
||||||
|
"invalid parameters to build encoding container profile"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cause(&self) -> Option<&error::Error> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct EncodingContainerProfileBuilder<'a> {
|
||||||
|
name: Option<& 'a str>,
|
||||||
|
description: Option<& 'a str>,
|
||||||
|
format: Option<& 'a gst::Caps>,
|
||||||
|
preset: Option<& 'a str>,
|
||||||
|
profiles: LinkedList<& 'a EncodingProfile>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> EncodingContainerProfileBuilder<'a> {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
EncodingContainerProfileBuilder {
|
||||||
|
name: None,
|
||||||
|
description: None,
|
||||||
|
format: None,
|
||||||
|
preset: None,
|
||||||
|
profiles: LinkedList::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(self) -> Result<EncodingContainerProfile, EncodingContainerProfileBuilderError> {
|
||||||
|
if self.format.is_none() {
|
||||||
|
return Err(EncodingContainerProfileBuilderError);
|
||||||
|
}
|
||||||
|
|
||||||
|
let container_profile = EncodingContainerProfile::new(
|
||||||
|
self.name, self.description, self.format.unwrap(), self.preset);
|
||||||
|
|
||||||
|
for profile in self.profiles {
|
||||||
|
container_profile.add_profile(profile).or_else(|_error| Err(EncodingContainerProfileBuilderError))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(container_profile)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn name(self, name: & 'a str) -> Self {
|
||||||
|
Self {
|
||||||
|
name: Some(name),
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn description(self, description: & 'a str) -> Self {
|
||||||
|
Self {
|
||||||
|
description: Some(description),
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn format(self, format: & 'a gst::Caps) -> Self {
|
||||||
|
Self {
|
||||||
|
format: Some(format),
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn preset(self, preset: & 'a str) -> Self {
|
||||||
|
Self {
|
||||||
|
preset: Some(preset),
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_profile(mut self, profile: & 'a EncodingProfile) -> Self {
|
||||||
|
self.profiles.push_back(profile);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
105
gstreamer-pbutils/src/encoding_video_profile.rs
Normal file
105
gstreamer-pbutils/src/encoding_video_profile.rs
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
|
||||||
|
use gst;
|
||||||
|
|
||||||
|
use std::error;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
use auto::EncodingVideoProfile;
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct EncodingVideoProfileBuilderError;
|
||||||
|
|
||||||
|
impl fmt::Display for EncodingVideoProfileBuilderError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "failed to build encoding video profile")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl error::Error for EncodingVideoProfileBuilderError {
|
||||||
|
fn description(&self) -> &str {
|
||||||
|
"invalid parameters to build encoding video profile"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cause(&self) -> Option<&error::Error> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct EncodingVideoProfileBuilder<'a> {
|
||||||
|
format: Option<& 'a gst::Caps>,
|
||||||
|
preset: Option<& 'a str>,
|
||||||
|
restriction: Option<& 'a gst::Caps>,
|
||||||
|
presence: u32,
|
||||||
|
pass: u32,
|
||||||
|
variable_framerate: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> EncodingVideoProfileBuilder<'a> {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
EncodingVideoProfileBuilder {
|
||||||
|
format: None,
|
||||||
|
preset: None,
|
||||||
|
restriction: None,
|
||||||
|
presence: 0,
|
||||||
|
pass: 0,
|
||||||
|
variable_framerate: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(self) -> Result<EncodingVideoProfile, EncodingVideoProfileBuilderError> {
|
||||||
|
if self.format.is_none() {
|
||||||
|
return Err(EncodingVideoProfileBuilderError);
|
||||||
|
}
|
||||||
|
|
||||||
|
let profile = EncodingVideoProfile::new(
|
||||||
|
self.format.unwrap(), self.preset, self.restriction, self.presence);
|
||||||
|
|
||||||
|
profile.set_pass(self.pass);
|
||||||
|
profile.set_variableframerate(self.variable_framerate);
|
||||||
|
|
||||||
|
Ok(profile)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn format(self, format: & 'a gst::Caps) -> Self {
|
||||||
|
Self {
|
||||||
|
format: Some(format),
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn restriction(self, restriction: & 'a gst::Caps) -> Self {
|
||||||
|
Self {
|
||||||
|
restriction: Some(restriction),
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn preset(self, preset: & 'a str) -> Self {
|
||||||
|
Self {
|
||||||
|
preset: Some(preset),
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn presence(self, presence: u32) -> Self {
|
||||||
|
Self {
|
||||||
|
presence: presence,
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pass(self, pass: u32) -> Self {
|
||||||
|
Self {
|
||||||
|
pass: pass,
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn variable_framerate(self, variable_framerate: bool) -> Self {
|
||||||
|
Self {
|
||||||
|
variable_framerate: variable_framerate,
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -55,6 +55,15 @@ pub mod discoverer_stream_info;
|
||||||
mod discoverer_video_info;
|
mod discoverer_video_info;
|
||||||
pub use discoverer_video_info::*;
|
pub use discoverer_video_info::*;
|
||||||
|
|
||||||
|
mod encoding_container_profile;
|
||||||
|
pub use encoding_container_profile::*;
|
||||||
|
|
||||||
|
mod encoding_audio_profile;
|
||||||
|
pub use encoding_audio_profile::*;
|
||||||
|
|
||||||
|
mod encoding_video_profile;
|
||||||
|
pub use encoding_video_profile::*;
|
||||||
|
|
||||||
// Re-export all the traits in a prelude module, so that applications
|
// Re-export all the traits in a prelude module, so that applications
|
||||||
// can always "use gst::prelude::*" without getting conflicts
|
// can always "use gst::prelude::*" without getting conflicts
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
|
@ -65,5 +74,9 @@ pub mod prelude {
|
||||||
pub use discoverer_stream_info::*;
|
pub use discoverer_stream_info::*;
|
||||||
pub use discoverer_video_info::*;
|
pub use discoverer_video_info::*;
|
||||||
|
|
||||||
|
pub use encoding_container_profile::*;
|
||||||
|
pub use encoding_video_profile::*;
|
||||||
|
pub use encoding_audio_profile::*;
|
||||||
|
|
||||||
pub use auto::traits::*;
|
pub use auto::traits::*;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue