encoding_profile: add builders for all types

This commit is contained in:
Thiago Santos 2018-05-06 10:14:00 -07:00 committed by Sebastian Dröge
parent 67bdfee1f6
commit 861f052c3d
5 changed files with 339 additions and 7 deletions

View file

@ -2,6 +2,8 @@
extern crate gstreamer as gst;
use gst::prelude::*;
extern crate gstreamer_pbutils as pbutils;
extern crate glib;
use std::env;
@ -32,7 +34,36 @@ struct ErrorMessage {
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> {
@ -58,18 +89,18 @@ fn example_main() -> Result<(), Error> {
src.set_property("uri", &uri)?;
sink.set_property("location", &output_file)?;
configure_encodebin(&encodebin);
configure_encodebin(&encodebin)?;
pipeline.add_many(&[&src, &encodebin, &sink])?;
gst::Element::link_many(&[&encodebin, &sink])?;
// Need to move a new reference into the closure
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 (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| {
let name = s.get_name();
(name.starts_with("audio/"), name.starts_with("video/"))
@ -81,7 +112,7 @@ fn example_main() -> Result<(), Error> {
gst_element_warning!(
dbin,
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;
@ -112,7 +143,7 @@ fn example_main() -> Result<(), Error> {
}
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 {
let 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");
src_pad.link(&sink_pad).into_result()?;
dbin_src_pad.link(&sink_pad).into_result()?;
}
Ok(())

View 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
}
}
}

View 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
}
}

View 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
}
}
}

View file

@ -55,6 +55,15 @@ pub mod discoverer_stream_info;
mod 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
// can always "use gst::prelude::*" without getting conflicts
pub mod prelude {
@ -65,5 +74,9 @@ pub mod prelude {
pub use discoverer_stream_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::*;
}