mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2025-01-03 15:58:42 +00:00
sccenc: add output-padding property
When set to False, sccenc will only output non-padding byte pairs. I cannot find reference documentation for the format, but the closest thing I find to it is http://www.theneitherworld.com/mcpoodle/SCC_TOOLS/DOCS/SCC_FORMAT.HTML, which doesn't have padding in the examples. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/635>
This commit is contained in:
parent
16d35a789a
commit
0bc7697600
1 changed files with 86 additions and 1 deletions
|
@ -28,6 +28,8 @@ use once_cell::sync::Lazy;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
const DEFAULT_OUTPUT_PADDING: bool = true;
|
||||||
|
|
||||||
static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
|
static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
|
||||||
gst::DebugCategory::new(
|
gst::DebugCategory::new(
|
||||||
"sccenc",
|
"sccenc",
|
||||||
|
@ -36,12 +38,26 @@ static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
struct Settings {
|
||||||
|
output_padding: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Settings {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
output_padding: DEFAULT_OUTPUT_PADDING,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct State {
|
struct State {
|
||||||
need_headers: bool,
|
need_headers: bool,
|
||||||
expected_timecode: Option<ValidVideoTimeCode>,
|
expected_timecode: Option<ValidVideoTimeCode>,
|
||||||
internal_buffer: Vec<gst::Buffer>,
|
internal_buffer: Vec<gst::Buffer>,
|
||||||
framerate: Option<gst::Fraction>,
|
framerate: Option<gst::Fraction>,
|
||||||
|
settings: Settings,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for State {
|
impl Default for State {
|
||||||
|
@ -51,6 +67,7 @@ impl Default for State {
|
||||||
expected_timecode: None,
|
expected_timecode: None,
|
||||||
internal_buffer: Vec::with_capacity(64),
|
internal_buffer: Vec::with_capacity(64),
|
||||||
framerate: None,
|
framerate: None,
|
||||||
|
settings: Settings::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,6 +105,24 @@ impl State {
|
||||||
return Err(gst::FlowError::Error);
|
return Err(gst::FlowError::Error);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if !self.settings.output_padding {
|
||||||
|
let map = buffer.map_readable().map_err(|_| {
|
||||||
|
gst::element_error!(
|
||||||
|
element,
|
||||||
|
gst::StreamError::Format,
|
||||||
|
["Failed to map buffer readable"]
|
||||||
|
);
|
||||||
|
|
||||||
|
gst::FlowError::Error
|
||||||
|
})?;
|
||||||
|
|
||||||
|
if map[0] == 0x80 && map[1] == 0x80 {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
|
||||||
|
drop(map);
|
||||||
|
}
|
||||||
|
|
||||||
let mut timecode = buffer
|
let mut timecode = buffer
|
||||||
.meta::<gst_video::VideoTimeCodeMeta>()
|
.meta::<gst_video::VideoTimeCodeMeta>()
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
|
@ -219,6 +254,7 @@ pub struct SccEnc {
|
||||||
srcpad: gst::Pad,
|
srcpad: gst::Pad,
|
||||||
sinkpad: gst::Pad,
|
sinkpad: gst::Pad,
|
||||||
state: Mutex<State>,
|
state: Mutex<State>,
|
||||||
|
settings: Mutex<Settings>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SccEnc {
|
impl SccEnc {
|
||||||
|
@ -377,6 +413,7 @@ impl ObjectSubclass for SccEnc {
|
||||||
srcpad,
|
srcpad,
|
||||||
sinkpad,
|
sinkpad,
|
||||||
state: Mutex::new(State::default()),
|
state: Mutex::new(State::default()),
|
||||||
|
settings: Mutex::new(Settings::default()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -388,6 +425,48 @@ impl ObjectImpl for SccEnc {
|
||||||
obj.add_pad(&self.sinkpad).unwrap();
|
obj.add_pad(&self.sinkpad).unwrap();
|
||||||
obj.add_pad(&self.srcpad).unwrap();
|
obj.add_pad(&self.srcpad).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn properties() -> &'static [glib::ParamSpec] {
|
||||||
|
static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| {
|
||||||
|
vec![glib::ParamSpecBoolean::new(
|
||||||
|
"output-padding",
|
||||||
|
"Output padding",
|
||||||
|
"Whether the encoder should output padding captions. \
|
||||||
|
The element will never add padding, but will encode padding \
|
||||||
|
buffers it receives if this property is set to true.",
|
||||||
|
DEFAULT_OUTPUT_PADDING,
|
||||||
|
glib::ParamFlags::READWRITE | gst::PARAM_FLAG_MUTABLE_READY,
|
||||||
|
)]
|
||||||
|
});
|
||||||
|
|
||||||
|
PROPERTIES.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_property(
|
||||||
|
&self,
|
||||||
|
_obj: &Self::Type,
|
||||||
|
_id: usize,
|
||||||
|
value: &glib::Value,
|
||||||
|
pspec: &glib::ParamSpec,
|
||||||
|
) {
|
||||||
|
match pspec.name() {
|
||||||
|
"output-padding" => {
|
||||||
|
self.settings.lock().unwrap().output_padding =
|
||||||
|
value.get().expect("type checked upstream");
|
||||||
|
}
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
|
||||||
|
match pspec.name() {
|
||||||
|
"output-padding" => {
|
||||||
|
let settings = self.settings.lock().unwrap();
|
||||||
|
settings.output_padding.to_value()
|
||||||
|
}
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GstObjectImpl for SccEnc {}
|
impl GstObjectImpl for SccEnc {}
|
||||||
|
@ -445,7 +524,13 @@ impl ElementImpl for SccEnc {
|
||||||
gst_trace!(CAT, obj: element, "Changing state {:?}", transition);
|
gst_trace!(CAT, obj: element, "Changing state {:?}", transition);
|
||||||
|
|
||||||
match transition {
|
match transition {
|
||||||
gst::StateChange::ReadyToPaused | gst::StateChange::PausedToReady => {
|
gst::StateChange::ReadyToPaused => {
|
||||||
|
// Reset the whole state
|
||||||
|
let mut state = self.state.lock().unwrap();
|
||||||
|
*state = State::default();
|
||||||
|
state.settings = self.settings.lock().unwrap().clone();
|
||||||
|
}
|
||||||
|
gst::StateChange::PausedToReady => {
|
||||||
// Reset the whole state
|
// Reset the whole state
|
||||||
let mut state = self.state.lock().unwrap();
|
let mut state = self.state.lock().unwrap();
|
||||||
*state = State::default();
|
*state = State::default();
|
||||||
|
|
Loading…
Reference in a new issue