Move debug categories from an instance member to lazy_static

Simplifies the code a bit and less state to carry around.
This commit is contained in:
Sebastian Dröge 2019-10-31 23:34:21 +01:00
parent 93756c392f
commit 1ae57967ae
41 changed files with 632 additions and 675 deletions

View file

@ -54,8 +54,6 @@ struct State {
} }
struct AudioEcho { struct AudioEcho {
#[allow(dead_code)]
cat: gst::DebugCategory,
settings: Mutex<Settings>, settings: Mutex<Settings>,
state: Mutex<Option<State>>, state: Mutex<Option<State>>,
} }
@ -135,11 +133,6 @@ impl ObjectSubclass for AudioEcho {
fn new() -> Self { fn new() -> Self {
Self { Self {
cat: gst::DebugCategory::new(
"rsaudioecho",
gst::DebugColorFlags::empty(),
Some("Rust audioecho effect"),
),
settings: Mutex::new(Default::default()), settings: Mutex::new(Default::default()),
state: Mutex::new(None), state: Mutex::new(None),
} }

View file

@ -17,6 +17,7 @@ cdg = "0.1"
cdg_renderer = "0.3" cdg_renderer = "0.3"
image = "0.22" image = "0.22"
muldiv = "0.2" muldiv = "0.2"
lazy_static = "1.0"
[lib] [lib]
name = "gstcdg" name = "gstcdg"

View file

@ -23,11 +23,15 @@ use std::sync::Mutex;
use crate::constants::{CDG_HEIGHT, CDG_WIDTH}; use crate::constants::{CDG_HEIGHT, CDG_WIDTH};
struct CdgDec { struct CdgDec {
cat: gst::DebugCategory,
cdg_inter: Mutex<cdg_renderer::CdgInterpreter>, cdg_inter: Mutex<cdg_renderer::CdgInterpreter>,
output_info: Mutex<Option<gst_video::VideoInfo>>, output_info: Mutex<Option<gst_video::VideoInfo>>,
} }
lazy_static! {
static ref CAT: gst::DebugCategory =
gst::DebugCategory::new("cdgdec", gst::DebugColorFlags::empty(), Some("CDG decoder"),);
}
impl ObjectSubclass for CdgDec { impl ObjectSubclass for CdgDec {
const NAME: &'static str = "CdgDec"; const NAME: &'static str = "CdgDec";
type ParentType = gst_video::VideoDecoder; type ParentType = gst_video::VideoDecoder;
@ -38,11 +42,6 @@ impl ObjectSubclass for CdgDec {
fn new() -> Self { fn new() -> Self {
Self { Self {
cat: gst::DebugCategory::new(
"cdgdec",
gst::DebugColorFlags::empty(),
Some("CDG decoder"),
),
cdg_inter: Mutex::new(cdg_renderer::CdgInterpreter::new()), cdg_inter: Mutex::new(cdg_renderer::CdgInterpreter::new()),
output_info: Mutex::new(None), output_info: Mutex::new(None),
} }
@ -185,12 +184,7 @@ impl VideoDecoderImpl for CdgDec {
} }
} }
gst_debug!( gst_debug!(CAT, obj: element, "Finish frame pts={}", frame.get_pts());
self.cat,
obj: element,
"Finish frame pts={}",
frame.get_pts()
);
element.finish_frame(frame) element.finish_frame(frame)
} }

View file

@ -24,8 +24,14 @@ use crate::constants::{
const CDG_CMD_MEMORY_PRESET: u8 = 1; const CDG_CMD_MEMORY_PRESET: u8 = 1;
struct CdgParse { struct CdgParse;
cat: gst::DebugCategory,
lazy_static! {
static ref CAT: gst::DebugCategory = gst::DebugCategory::new(
"cdgparse",
gst::DebugColorFlags::empty(),
Some("CDG parser"),
);
} }
impl ObjectSubclass for CdgParse { impl ObjectSubclass for CdgParse {
@ -37,13 +43,7 @@ impl ObjectSubclass for CdgParse {
glib_object_subclass!(); glib_object_subclass!();
fn new() -> Self { fn new() -> Self {
Self { Self
cat: gst::DebugCategory::new(
"cdgparse",
gst::DebugColorFlags::empty(),
Some("CDG parser"),
),
}
} }
fn class_init(klass: &mut subclass::simple::ClassStruct<Self>) { fn class_init(klass: &mut subclass::simple::ClassStruct<Self>) {
@ -196,7 +196,7 @@ impl BaseParseImpl for CdgParse {
buffer.set_flags(gst::BufferFlags::DELTA_UNIT); buffer.set_flags(gst::BufferFlags::DELTA_UNIT);
} }
gst_debug!(self.cat, obj: element, "Found frame pts={}", pts); gst_debug!(CAT, obj: element, "Found frame pts={}", pts);
element.finish_frame(frame, CDG_PACKET_SIZE as u32)?; element.finish_frame(frame, CDG_PACKET_SIZE as u32)?;

View file

@ -12,6 +12,8 @@
extern crate glib; extern crate glib;
#[macro_use] #[macro_use]
extern crate gstreamer as gst; extern crate gstreamer as gst;
#[macro_use]
extern crate lazy_static;
mod cdgdec; mod cdgdec;
mod cdgparse; mod cdgparse;

View file

@ -93,13 +93,20 @@ static PROPERTIES: [subclass::Property; 2] = [
]; ];
struct MccEnc { struct MccEnc {
cat: gst::DebugCategory,
srcpad: gst::Pad, srcpad: gst::Pad,
sinkpad: gst::Pad, sinkpad: gst::Pad,
state: Mutex<State>, state: Mutex<State>,
settings: Mutex<Settings>, settings: Mutex<Settings>,
} }
lazy_static! {
static ref CAT: gst::DebugCategory = gst::DebugCategory::new(
"mccenc",
gst::DebugColorFlags::empty(),
Some("Mcc Encoder Element"),
);
}
impl MccEnc { impl MccEnc {
fn set_pad_functions(sinkpad: &gst::Pad, srcpad: &gst::Pad) { fn set_pad_functions(sinkpad: &gst::Pad, srcpad: &gst::Pad) {
sinkpad.set_chain_function(|pad, parent, buffer| { sinkpad.set_chain_function(|pad, parent, buffer| {
@ -390,7 +397,7 @@ impl MccEnc {
element: &gst::Element, element: &gst::Element,
buffer: gst::Buffer, buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> { ) -> Result<gst::FlowSuccess, gst::FlowError> {
gst_log!(self.cat, obj: pad, "Handling buffer {:?}", buffer); gst_log!(CAT, obj: pad, "Handling buffer {:?}", buffer);
let mut state = self.state.lock().unwrap(); let mut state = self.state.lock().unwrap();
@ -414,7 +421,7 @@ impl MccEnc {
fn sink_event(&self, pad: &gst::Pad, element: &gst::Element, event: gst::Event) -> bool { fn sink_event(&self, pad: &gst::Pad, element: &gst::Element, event: gst::Event) -> bool {
use gst::EventView; use gst::EventView;
gst_log!(self.cat, obj: pad, "Handling event {:?}", event); gst_log!(CAT, obj: pad, "Handling event {:?}", event);
match event.view() { match event.view() {
EventView::Caps(ev) => { EventView::Caps(ev) => {
@ -423,7 +430,7 @@ impl MccEnc {
let framerate = match s.get_some::<gst::Fraction>("framerate") { let framerate = match s.get_some::<gst::Fraction>("framerate") {
Ok(framerate) => framerate, Ok(framerate) => framerate,
Err(structure::GetError::FieldNotFound { .. }) => { Err(structure::GetError::FieldNotFound { .. }) => {
gst_error!(self.cat, obj: pad, "Caps without framerate"); gst_error!(CAT, obj: pad, "Caps without framerate");
return false; return false;
} }
err => panic!("MccEnc::sink_event caps: {:?}", err), err => panic!("MccEnc::sink_event caps: {:?}", err),
@ -457,10 +464,10 @@ impl MccEnc {
fn src_event(&self, pad: &gst::Pad, element: &gst::Element, event: gst::Event) -> bool { fn src_event(&self, pad: &gst::Pad, element: &gst::Element, event: gst::Event) -> bool {
use gst::EventView; use gst::EventView;
gst_log!(self.cat, obj: pad, "Handling event {:?}", event); gst_log!(CAT, obj: pad, "Handling event {:?}", event);
match event.view() { match event.view() {
EventView::Seek(_) => { EventView::Seek(_) => {
gst_log!(self.cat, obj: pad, "Dropping seek event"); gst_log!(CAT, obj: pad, "Dropping seek event");
false false
} }
_ => pad.event_default(Some(element), event), _ => pad.event_default(Some(element), event),
@ -470,7 +477,7 @@ impl MccEnc {
fn src_query(&self, pad: &gst::Pad, element: &gst::Element, query: &mut gst::QueryRef) -> bool { fn src_query(&self, pad: &gst::Pad, element: &gst::Element, query: &mut gst::QueryRef) -> bool {
use gst::QueryView; use gst::QueryView;
gst_log!(self.cat, obj: pad, "Handling query {:?}", query); gst_log!(CAT, obj: pad, "Handling query {:?}", query);
match query.view_mut() { match query.view_mut() {
QueryView::Seeking(mut q) => { QueryView::Seeking(mut q) => {
@ -505,11 +512,6 @@ impl ObjectSubclass for MccEnc {
MccEnc::set_pad_functions(&sinkpad, &srcpad); MccEnc::set_pad_functions(&sinkpad, &srcpad);
Self { Self {
cat: gst::DebugCategory::new(
"mccenc",
gst::DebugColorFlags::empty(),
Some("Mcc Encoder Element"),
),
srcpad, srcpad,
sinkpad, sinkpad,
state: Mutex::new(State::default()), state: Mutex::new(State::default()),
@ -624,7 +626,7 @@ impl ElementImpl for MccEnc {
element: &gst::Element, element: &gst::Element,
transition: gst::StateChange, transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> { ) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst_trace!(self.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 | gst::StateChange::PausedToReady => {

View file

@ -19,6 +19,7 @@ gstreamer-audio = { git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs
gstreamer-video = { git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs", features = ["v1_14"] } gstreamer-video = { git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs", features = ["v1_14"] }
gtk = { git = "https://github.com/gtk-rs/gtk", optional = true } gtk = { git = "https://github.com/gtk-rs/gtk", optional = true }
gio = { git = "https://github.com/gtk-rs/gio", optional = true } gio = { git = "https://github.com/gtk-rs/gio", optional = true }
lazy_static = "1.0"
[dev-dependencies] [dev-dependencies]
gstreamer-check = { git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs", features = ["v1_14"]} gstreamer-check = { git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs", features = ["v1_14"]}

View file

@ -34,7 +34,6 @@ use gst_video;
use std::sync::{Mutex, RwLock}; use std::sync::{Mutex, RwLock};
struct FallbackSwitch { struct FallbackSwitch {
cat: gst::DebugCategory,
sinkpad: gst_base::AggregatorPad, sinkpad: gst_base::AggregatorPad,
fallback_sinkpad: RwLock<Option<gst_base::AggregatorPad>>, fallback_sinkpad: RwLock<Option<gst_base::AggregatorPad>>,
active_sinkpad: Mutex<gst::Pad>, active_sinkpad: Mutex<gst::Pad>,
@ -43,6 +42,14 @@ struct FallbackSwitch {
settings: Mutex<Settings>, settings: Mutex<Settings>,
} }
lazy_static! {
static ref CAT: gst::DebugCategory = gst::DebugCategory::new(
"fallbackswitch",
gst::DebugColorFlags::empty(),
Some("Fallback switch Element"),
);
}
#[derive(Debug)] #[derive(Debug)]
struct OutputState { struct OutputState {
last_sinkpad_time: gst::ClockTime, last_sinkpad_time: gst::ClockTime,
@ -116,10 +123,10 @@ impl FallbackSwitch {
fallback_sinkpad: Option<&gst_base::AggregatorPad>, fallback_sinkpad: Option<&gst_base::AggregatorPad>,
) -> Result<Option<(gst::Buffer, gst::Caps, bool)>, gst::FlowError> { ) -> Result<Option<(gst::Buffer, gst::Caps, bool)>, gst::FlowError> {
// If we got a buffer on the sinkpad just handle it // If we got a buffer on the sinkpad just handle it
gst_debug!(self.cat, obj: agg, "Got buffer on sinkpad {:?}", buffer); gst_debug!(CAT, obj: agg, "Got buffer on sinkpad {:?}", buffer);
if buffer.get_pts().is_none() { if buffer.get_pts().is_none() {
gst_error!(self.cat, obj: agg, "Only buffers with PTS supported"); gst_error!(CAT, obj: agg, "Only buffers with PTS supported");
return Err(gst::FlowError::Error); return Err(gst::FlowError::Error);
} }
@ -128,7 +135,7 @@ impl FallbackSwitch {
.get_segment() .get_segment()
.downcast::<gst::ClockTime>() .downcast::<gst::ClockTime>()
.map_err(|_| { .map_err(|_| {
gst_error!(self.cat, obj: agg, "Only TIME segments supported"); gst_error!(CAT, obj: agg, "Only TIME segments supported");
gst::FlowError::Error gst::FlowError::Error
})?; })?;
@ -144,7 +151,7 @@ impl FallbackSwitch {
if pad_change { if pad_change {
if buffer.get_flags().contains(gst::BufferFlags::DELTA_UNIT) { if buffer.get_flags().contains(gst::BufferFlags::DELTA_UNIT) {
gst_info!( gst_info!(
self.cat, CAT,
obj: agg, obj: agg,
"Can't change back to sinkpad, waiting for keyframe" "Can't change back to sinkpad, waiting for keyframe"
); );
@ -156,7 +163,7 @@ impl FallbackSwitch {
return Ok(None); return Ok(None);
} }
gst_info!(self.cat, obj: agg, "Active pad changed to sinkpad"); gst_info!(CAT, obj: agg, "Active pad changed to sinkpad");
*active_sinkpad = self.sinkpad.clone().upcast(); *active_sinkpad = self.sinkpad.clone().upcast();
} }
drop(active_sinkpad); drop(active_sinkpad);
@ -170,7 +177,7 @@ impl FallbackSwitch {
.get_segment() .get_segment()
.downcast::<gst::ClockTime>() .downcast::<gst::ClockTime>()
.map_err(|_| { .map_err(|_| {
gst_error!(self.cat, obj: agg, "Only TIME segments supported"); gst_error!(CAT, obj: agg, "Only TIME segments supported");
gst::FlowError::Error gst::FlowError::Error
})?; })?;
@ -180,7 +187,7 @@ impl FallbackSwitch {
|| fallback_segment.to_running_time(fallback_pts) <= state.last_sinkpad_time || fallback_segment.to_running_time(fallback_pts) <= state.last_sinkpad_time
{ {
gst_debug!( gst_debug!(
self.cat, CAT,
obj: agg, obj: agg,
"Dropping fallback buffer {:?}", "Dropping fallback buffer {:?}",
fallback_buffer fallback_buffer
@ -213,15 +220,10 @@ impl FallbackSwitch {
.pop_buffer() .pop_buffer()
.ok_or(gst_base::AGGREGATOR_FLOW_NEED_DATA)?; .ok_or(gst_base::AGGREGATOR_FLOW_NEED_DATA)?;
gst_debug!( gst_debug!(CAT, obj: agg, "Got buffer on fallback sinkpad {:?}", buffer);
self.cat,
obj: agg,
"Got buffer on fallback sinkpad {:?}",
buffer
);
if buffer.get_pts().is_none() { if buffer.get_pts().is_none() {
gst_error!(self.cat, obj: agg, "Only buffers with PTS supported"); gst_error!(CAT, obj: agg, "Only buffers with PTS supported");
return Err(gst::FlowError::Error); return Err(gst::FlowError::Error);
} }
@ -229,7 +231,7 @@ impl FallbackSwitch {
.get_segment() .get_segment()
.downcast::<gst::ClockTime>() .downcast::<gst::ClockTime>()
.map_err(|_| { .map_err(|_| {
gst_error!(self.cat, obj: agg, "Only TIME segments supported"); gst_error!(CAT, obj: agg, "Only TIME segments supported");
gst::FlowError::Error gst::FlowError::Error
})?; })?;
let running_time = fallback_segment.to_running_time(buffer.get_dts_or_pts()); let running_time = fallback_segment.to_running_time(buffer.get_dts_or_pts());
@ -250,7 +252,7 @@ impl FallbackSwitch {
// Get the next one if this one is before the timeout // Get the next one if this one is before the timeout
if state.last_sinkpad_time + settings.timeout > running_time { if state.last_sinkpad_time + settings.timeout > running_time {
gst_debug!( gst_debug!(
self.cat, CAT,
obj: agg, obj: agg,
"Timeout not reached yet: {} + {} > {}", "Timeout not reached yet: {} + {} > {}",
state.last_sinkpad_time, state.last_sinkpad_time,
@ -262,7 +264,7 @@ impl FallbackSwitch {
} }
gst_debug!( gst_debug!(
self.cat, CAT,
obj: agg, obj: agg,
"Timeout reached: {} + {} <= {}", "Timeout reached: {} + {} <= {}",
state.last_sinkpad_time, state.last_sinkpad_time,
@ -275,7 +277,7 @@ impl FallbackSwitch {
if pad_change { if pad_change {
if buffer.get_flags().contains(gst::BufferFlags::DELTA_UNIT) { if buffer.get_flags().contains(gst::BufferFlags::DELTA_UNIT) {
gst_info!( gst_info!(
self.cat, CAT,
obj: agg, obj: agg,
"Can't change to fallback sinkpad yet, waiting for keyframe" "Can't change to fallback sinkpad yet, waiting for keyframe"
); );
@ -287,7 +289,7 @@ impl FallbackSwitch {
continue; continue;
} }
gst_info!(self.cat, obj: agg, "Active pad changed to fallback sinkpad"); gst_info!(CAT, obj: agg, "Active pad changed to fallback sinkpad");
*active_sinkpad = fallback_sinkpad.clone().upcast(); *active_sinkpad = fallback_sinkpad.clone().upcast();
} }
drop(active_sinkpad); drop(active_sinkpad);
@ -316,7 +318,7 @@ impl FallbackSwitch {
let mut state = self.output_state.lock().unwrap(); let mut state = self.output_state.lock().unwrap();
let fallback_sinkpad = self.fallback_sinkpad.read().unwrap(); let fallback_sinkpad = self.fallback_sinkpad.read().unwrap();
gst_debug!(self.cat, obj: agg, "Aggregate called: timeout {}", timeout); gst_debug!(CAT, obj: agg, "Aggregate called: timeout {}", timeout);
if let Some(buffer) = self.sinkpad.pop_buffer() { if let Some(buffer) = self.sinkpad.pop_buffer() {
if let Some(res) = if let Some(res) =
@ -325,16 +327,12 @@ impl FallbackSwitch {
return Ok(res); return Ok(res);
} }
} else if self.sinkpad.is_eos() { } else if self.sinkpad.is_eos() {
gst_log!(self.cat, obj: agg, "Sinkpad is EOS"); gst_log!(CAT, obj: agg, "Sinkpad is EOS");
return Err(gst::FlowError::Eos); return Err(gst::FlowError::Eos);
} }
if let (false, Some(_)) = (timeout, &*fallback_sinkpad) { if let (false, Some(_)) = (timeout, &*fallback_sinkpad) {
gst_debug!( gst_debug!(CAT, obj: agg, "Have fallback sinkpad but no timeout yet");
self.cat,
obj: agg,
"Have fallback sinkpad but no timeout yet"
);
Err(gst_base::AGGREGATOR_FLOW_NEED_DATA) Err(gst_base::AGGREGATOR_FLOW_NEED_DATA)
} else if let (true, Some(fallback_sinkpad)) = (timeout, &*fallback_sinkpad) { } else if let (true, Some(fallback_sinkpad)) = (timeout, &*fallback_sinkpad) {
@ -342,7 +340,7 @@ impl FallbackSwitch {
} else { } else {
// Otherwise there's not much we can do at this point // Otherwise there's not much we can do at this point
gst_debug!( gst_debug!(
self.cat, CAT,
obj: agg, obj: agg,
"Got no buffer on sinkpad and have no fallback sinkpad" "Got no buffer on sinkpad and have no fallback sinkpad"
); );
@ -374,11 +372,6 @@ impl ObjectSubclass for FallbackSwitch {
.unwrap(); .unwrap();
Self { Self {
cat: gst::DebugCategory::new(
"fallbackswitch",
gst::DebugColorFlags::empty(),
Some("Fallback switch Element"),
),
sinkpad: sinkpad.clone(), sinkpad: sinkpad.clone(),
fallback_sinkpad: RwLock::new(None), fallback_sinkpad: RwLock::new(None),
active_sinkpad: Mutex::new(sinkpad.upcast()), active_sinkpad: Mutex::new(sinkpad.upcast()),
@ -450,7 +443,7 @@ impl ObjectImpl for FallbackSwitch {
let mut settings = self.settings.lock().unwrap(); let mut settings = self.settings.lock().unwrap();
let timeout = value.get_some().expect("type checked upstream"); let timeout = value.get_some().expect("type checked upstream");
gst_info!( gst_info!(
self.cat, CAT,
obj: agg, obj: agg,
"Changing timeout from {} to {}", "Changing timeout from {} to {}",
settings.timeout, settings.timeout,
@ -493,13 +486,13 @@ impl ElementImpl for FallbackSwitch {
if templ != &fallback_sink_templ if templ != &fallback_sink_templ
|| (name.is_some() && name.as_ref().map(String::as_str) != Some("fallback_sink")) || (name.is_some() && name.as_ref().map(String::as_str) != Some("fallback_sink"))
{ {
gst_error!(self.cat, obj: agg, "Wrong pad template or name"); gst_error!(CAT, obj: agg, "Wrong pad template or name");
return None; return None;
} }
let mut fallback_sinkpad = self.fallback_sinkpad.write().unwrap(); let mut fallback_sinkpad = self.fallback_sinkpad.write().unwrap();
if fallback_sinkpad.is_some() { if fallback_sinkpad.is_some() {
gst_error!(self.cat, obj: agg, "Already have a fallback sinkpad"); gst_error!(CAT, obj: agg, "Already have a fallback sinkpad");
return None; return None;
} }
@ -533,7 +526,7 @@ impl ElementImpl for FallbackSwitch {
drop(pad_states); drop(pad_states);
drop(fallback_sinkpad); drop(fallback_sinkpad);
agg.remove_pad(pad).unwrap(); agg.remove_pad(pad).unwrap();
gst_debug!(self.cat, obj: agg, "Removed fallback sinkpad {:?}", pad); gst_debug!(CAT, obj: agg, "Removed fallback sinkpad {:?}", pad);
} }
} }
} }
@ -557,7 +550,7 @@ impl AggregatorImpl for FallbackSwitch {
match event.view() { match event.view() {
EventView::Gap(_) => { EventView::Gap(_) => {
gst_debug!(self.cat, obj: agg_pad, "Dropping gap event"); gst_debug!(CAT, obj: agg_pad, "Dropping gap event");
true true
} }
_ => self.parent_sink_event_pre_queue(agg, agg_pad, event), _ => self.parent_sink_event_pre_queue(agg, agg_pad, event),
@ -575,7 +568,7 @@ impl AggregatorImpl for FallbackSwitch {
match event.view() { match event.view() {
EventView::Caps(caps) => { EventView::Caps(caps) => {
let caps = caps.get_caps_owned(); let caps = caps.get_caps_owned();
gst_debug!(self.cat, obj: agg_pad, "Received caps {}", caps); gst_debug!(CAT, obj: agg_pad, "Received caps {}", caps);
let audio_info; let audio_info;
let video_info; let video_info;
@ -618,14 +611,10 @@ impl AggregatorImpl for FallbackSwitch {
// to be its running time. We will then either output the buffer or drop it, depending on // to be its running time. We will then either output the buffer or drop it, depending on
// its distance from the last sinkpad time // its distance from the last sinkpad time
if let Some(_) = self.sinkpad.peek_buffer() { if let Some(_) = self.sinkpad.peek_buffer() {
gst_debug!( gst_debug!(CAT, obj: agg, "Have buffer on sinkpad, immediate timeout");
self.cat,
obj: agg,
"Have buffer on sinkpad, immediate timeout"
);
0.into() 0.into()
} else if self.sinkpad.is_eos() { } else if self.sinkpad.is_eos() {
gst_debug!(self.cat, obj: agg, "Sinkpad is EOS, immediate timeout"); gst_debug!(CAT, obj: agg, "Sinkpad is EOS, immediate timeout");
0.into() 0.into()
} else if let Some((buffer, fallback_sinkpad)) = self } else if let Some((buffer, fallback_sinkpad)) = self
.fallback_sinkpad .fallback_sinkpad
@ -635,7 +624,7 @@ impl AggregatorImpl for FallbackSwitch {
.and_then(|p| p.peek_buffer().map(|buffer| (buffer, p))) .and_then(|p| p.peek_buffer().map(|buffer| (buffer, p)))
{ {
if buffer.get_pts().is_none() { if buffer.get_pts().is_none() {
gst_error!(self.cat, obj: agg, "Only buffers with PTS supported"); gst_error!(CAT, obj: agg, "Only buffers with PTS supported");
// Trigger aggregate immediately to error out immediately // Trigger aggregate immediately to error out immediately
return 0.into(); return 0.into();
} }
@ -643,7 +632,7 @@ impl AggregatorImpl for FallbackSwitch {
let segment = match fallback_sinkpad.get_segment().downcast::<gst::ClockTime>() { let segment = match fallback_sinkpad.get_segment().downcast::<gst::ClockTime>() {
Ok(segment) => segment, Ok(segment) => segment,
Err(_) => { Err(_) => {
gst_error!(self.cat, obj: agg, "Only TIME segments supported"); gst_error!(CAT, obj: agg, "Only TIME segments supported");
// Trigger aggregate immediately to error out immediately // Trigger aggregate immediately to error out immediately
return 0.into(); return 0.into();
} }
@ -651,14 +640,14 @@ impl AggregatorImpl for FallbackSwitch {
let running_time = segment.to_running_time(buffer.get_dts_or_pts()); let running_time = segment.to_running_time(buffer.get_dts_or_pts());
gst_debug!( gst_debug!(
self.cat, CAT,
obj: agg, obj: agg,
"Have buffer on fallback sinkpad, timeout at {}", "Have buffer on fallback sinkpad, timeout at {}",
running_time running_time
); );
running_time running_time
} else { } else {
gst_debug!(self.cat, obj: agg, "Have no buffer at all yet"); gst_debug!(CAT, obj: agg, "Have no buffer at all yet");
gst::CLOCK_TIME_NONE gst::CLOCK_TIME_NONE
} }
} }
@ -674,14 +663,14 @@ impl AggregatorImpl for FallbackSwitch {
let segment = match agg_pad.get_segment().downcast::<gst::ClockTime>() { let segment = match agg_pad.get_segment().downcast::<gst::ClockTime>() {
Ok(segment) => segment, Ok(segment) => segment,
Err(_) => { Err(_) => {
gst_error!(self.cat, obj: agg, "Only TIME segments supported"); gst_error!(CAT, obj: agg, "Only TIME segments supported");
return Some(buffer); return Some(buffer);
} }
}; };
let pts = buffer.get_pts(); let pts = buffer.get_pts();
if pts.is_none() { if pts.is_none() {
gst_error!(self.cat, obj: agg, "Only buffers with PTS supported"); gst_error!(CAT, obj: agg, "Only buffers with PTS supported");
return Some(buffer); return Some(buffer);
} }
@ -728,7 +717,7 @@ impl AggregatorImpl for FallbackSwitch {
}; };
gst_debug!( gst_debug!(
self.cat, CAT,
obj: agg_pad, obj: agg_pad,
"Clipping buffer {:?} with PTS {} and duration {}", "Clipping buffer {:?} with PTS {} and duration {}",
buffer, buffer,
@ -765,14 +754,14 @@ impl AggregatorImpl for FallbackSwitch {
agg: &gst_base::Aggregator, agg: &gst_base::Aggregator,
timeout: bool, timeout: bool,
) -> Result<gst::FlowSuccess, gst::FlowError> { ) -> Result<gst::FlowSuccess, gst::FlowError> {
gst_debug!(self.cat, obj: agg, "Aggregate called: timeout {}", timeout); gst_debug!(CAT, obj: agg, "Aggregate called: timeout {}", timeout);
let (mut buffer, active_caps, pad_change) = self.get_next_buffer(agg, timeout)?; let (mut buffer, active_caps, pad_change) = self.get_next_buffer(agg, timeout)?;
let current_src_caps = agg.get_static_pad("src").unwrap().get_current_caps(); let current_src_caps = agg.get_static_pad("src").unwrap().get_current_caps();
if Some(&active_caps) != current_src_caps.as_ref() { if Some(&active_caps) != current_src_caps.as_ref() {
gst_info!( gst_info!(
self.cat, CAT,
obj: agg, obj: agg,
"Caps change from {:?} to {:?}", "Caps change from {:?} to {:?}",
current_src_caps, current_src_caps,
@ -786,7 +775,7 @@ impl AggregatorImpl for FallbackSwitch {
buffer.make_mut().set_flags(gst::BufferFlags::DISCONT); buffer.make_mut().set_flags(gst::BufferFlags::DISCONT);
} }
gst_debug!(self.cat, obj: agg, "Finishing buffer {:?}", buffer); gst_debug!(CAT, obj: agg, "Finishing buffer {:?}", buffer);
agg.finish_buffer(buffer) agg.finish_buffer(buffer)
} }

View file

@ -39,6 +39,9 @@ mod gst_base {
pub use super::base::*; pub use super::base::*;
} }
#[macro_use]
extern crate lazy_static;
mod fallbackswitch; mod fallbackswitch;
fn plugin_init(plugin: &gst::Plugin) -> Result<(), glib::BoolError> { fn plugin_init(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {

View file

@ -11,6 +11,7 @@ url = "2"
glib = { git = "https://github.com/gtk-rs/glib" } glib = { git = "https://github.com/gtk-rs/glib" }
gstreamer = { git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs" } gstreamer = { git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs" }
gstreamer-base = { git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs" } gstreamer-base = { git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs" }
lazy_static = "1.0"
[lib] [lib]
name = "gstrsfile" name = "gstrsfile"

View file

@ -62,11 +62,18 @@ impl Default for State {
} }
pub struct FileSink { pub struct FileSink {
cat: gst::DebugCategory,
settings: Mutex<Settings>, settings: Mutex<Settings>,
state: Mutex<State>, state: Mutex<State>,
} }
lazy_static! {
static ref CAT: gst::DebugCategory = gst::DebugCategory::new(
"rsfilesink",
gst::DebugColorFlags::empty(),
Some("File Sink"),
);
}
impl FileSink { impl FileSink {
fn set_location( fn set_location(
&self, &self,
@ -87,7 +94,7 @@ impl FileSink {
match settings.location { match settings.location {
Some(ref location_cur) => { Some(ref location_cur) => {
gst_info!( gst_info!(
self.cat, CAT,
obj: element, obj: element,
"Changing `location` from {:?} to {}", "Changing `location` from {:?} to {}",
location_cur, location_cur,
@ -95,13 +102,13 @@ impl FileSink {
); );
} }
None => { None => {
gst_info!(self.cat, obj: element, "Setting `location` to {}", location,); gst_info!(CAT, obj: element, "Setting `location` to {}", location,);
} }
} }
Some(location) Some(location)
} }
None => { None => {
gst_info!(self.cat, obj: element, "Resetting `location` to None",); gst_info!(CAT, obj: element, "Resetting `location` to None",);
None None
} }
}; };
@ -120,11 +127,6 @@ impl ObjectSubclass for FileSink {
fn new() -> Self { fn new() -> Self {
Self { Self {
cat: gst::DebugCategory::new(
"rsfilesink",
gst::DebugColorFlags::empty(),
Some("File Sink"),
),
settings: Mutex::new(Default::default()), settings: Mutex::new(Default::default()),
state: Mutex::new(Default::default()), state: Mutex::new(Default::default()),
} }
@ -174,7 +176,7 @@ impl ObjectImpl for FileSink {
if let Err(err) = res { if let Err(err) = res {
gst_error!( gst_error!(
self.cat, CAT,
obj: element, obj: element,
"Failed to set property `location`: {}", "Failed to set property `location`: {}",
err err
@ -229,10 +231,10 @@ impl BaseSinkImpl for FileSink {
] ]
) )
})?; })?;
gst_debug!(self.cat, obj: element, "Opened file {:?}", file); gst_debug!(CAT, obj: element, "Opened file {:?}", file);
*state = State::Started { file, position: 0 }; *state = State::Started { file, position: 0 };
gst_info!(self.cat, obj: element, "Started"); gst_info!(CAT, obj: element, "Started");
Ok(()) Ok(())
} }
@ -247,7 +249,7 @@ impl BaseSinkImpl for FileSink {
} }
*state = State::Stopped; *state = State::Stopped;
gst_info!(self.cat, obj: element, "Stopped"); gst_info!(CAT, obj: element, "Stopped");
Ok(()) Ok(())
} }
@ -271,7 +273,7 @@ impl BaseSinkImpl for FileSink {
} }
}; };
gst_trace!(self.cat, obj: element, "Rendering {:?}", buffer); gst_trace!(CAT, obj: element, "Rendering {:?}", buffer);
let map = buffer.map_readable().ok_or_else(|| { let map = buffer.map_readable().ok_or_else(|| {
gst_element_error!(element, gst::CoreError::Failed, ["Failed to map buffer"]); gst_element_error!(element, gst::CoreError::Failed, ["Failed to map buffer"]);
gst::FlowError::Error gst::FlowError::Error

View file

@ -62,11 +62,18 @@ impl Default for State {
} }
pub struct FileSrc { pub struct FileSrc {
cat: gst::DebugCategory,
settings: Mutex<Settings>, settings: Mutex<Settings>,
state: Mutex<State>, state: Mutex<State>,
} }
lazy_static! {
static ref CAT: gst::DebugCategory = gst::DebugCategory::new(
"rsfilesrc",
gst::DebugColorFlags::empty(),
Some("File Source"),
);
}
impl FileSrc { impl FileSrc {
fn set_location( fn set_location(
&self, &self,
@ -101,7 +108,7 @@ impl FileSrc {
match settings.location { match settings.location {
Some(ref location_cur) => { Some(ref location_cur) => {
gst_info!( gst_info!(
self.cat, CAT,
obj: element, obj: element,
"Changing `location` from {:?} to {}", "Changing `location` from {:?} to {}",
location_cur, location_cur,
@ -109,13 +116,13 @@ impl FileSrc {
); );
} }
None => { None => {
gst_info!(self.cat, obj: element, "Setting `location to {}", location,); gst_info!(CAT, obj: element, "Setting `location to {}", location,);
} }
} }
Some(location) Some(location)
} }
None => { None => {
gst_info!(self.cat, obj: element, "Resetting `location` to None",); gst_info!(CAT, obj: element, "Resetting `location` to None",);
None None
} }
}; };
@ -134,11 +141,6 @@ impl ObjectSubclass for FileSrc {
fn new() -> Self { fn new() -> Self {
Self { Self {
cat: gst::DebugCategory::new(
"rsfilesrc",
gst::DebugColorFlags::empty(),
Some("File Source"),
),
settings: Mutex::new(Default::default()), settings: Mutex::new(Default::default()),
state: Mutex::new(Default::default()), state: Mutex::new(Default::default()),
} }
@ -188,7 +190,7 @@ impl ObjectImpl for FileSrc {
if let Err(err) = res { if let Err(err) = res {
gst_error!( gst_error!(
self.cat, CAT,
obj: element, obj: element,
"Failed to set property `location`: {}", "Failed to set property `location`: {}",
err err
@ -264,11 +266,11 @@ impl BaseSrcImpl for FileSrc {
) )
})?; })?;
gst_debug!(self.cat, obj: element, "Opened file {:?}", file); gst_debug!(CAT, obj: element, "Opened file {:?}", file);
*state = State::Started { file, position: 0 }; *state = State::Started { file, position: 0 };
gst_info!(self.cat, obj: element, "Started"); gst_info!(CAT, obj: element, "Started");
Ok(()) Ok(())
} }
@ -284,7 +286,7 @@ impl BaseSrcImpl for FileSrc {
*state = State::Stopped; *state = State::Stopped;
gst_info!(self.cat, obj: element, "Stopped"); gst_info!(CAT, obj: element, "Stopped");
Ok(()) Ok(())
} }

View file

@ -14,6 +14,8 @@ extern crate glib;
extern crate gstreamer as gst; extern crate gstreamer as gst;
extern crate gstreamer_base as gst_base; extern crate gstreamer_base as gst_base;
extern crate url; extern crate url;
#[macro_use]
extern crate lazy_static;
mod file_location; mod file_location;
mod filesink; mod filesink;

View file

@ -15,6 +15,7 @@ gstreamer-check = { git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs
lewton = { version = "0.9", default-features = false } lewton = { version = "0.9", default-features = false }
byte-slice-cast = "0.3" byte-slice-cast = "0.3"
atomic_refcell = "0.1" atomic_refcell = "0.1"
lazy_static = "1.0"
[lib] [lib]
name = "gstlewton" name = "gstlewton"

View file

@ -32,10 +32,17 @@ struct State {
} }
struct LewtonDec { struct LewtonDec {
cat: gst::DebugCategory,
state: AtomicRefCell<Option<State>>, state: AtomicRefCell<Option<State>>,
} }
lazy_static! {
static ref CAT: gst::DebugCategory = gst::DebugCategory::new(
"lewtondec",
gst::DebugColorFlags::empty(),
Some("lewton Vorbis decoder"),
);
}
impl ObjectSubclass for LewtonDec { impl ObjectSubclass for LewtonDec {
const NAME: &'static str = "LewtonDec"; const NAME: &'static str = "LewtonDec";
type ParentType = gst_audio::AudioDecoder; type ParentType = gst_audio::AudioDecoder;
@ -46,11 +53,6 @@ impl ObjectSubclass for LewtonDec {
fn new() -> Self { fn new() -> Self {
Self { Self {
cat: gst::DebugCategory::new(
"lewtondec",
gst::DebugColorFlags::empty(),
Some("lewton Vorbis decoder"),
),
state: AtomicRefCell::new(None), state: AtomicRefCell::new(None),
} }
} }
@ -123,7 +125,7 @@ impl AudioDecoderImpl for LewtonDec {
element: &gst_audio::AudioDecoder, element: &gst_audio::AudioDecoder,
caps: &gst::Caps, caps: &gst::Caps,
) -> Result<(), gst::LoggableError> { ) -> Result<(), gst::LoggableError> {
gst_debug!(self.cat, obj: element, "Setting format {:?}", caps); gst_debug!(CAT, obj: element, "Setting format {:?}", caps);
// When the caps are changing we require new headers // When the caps are changing we require new headers
let mut state_guard = self.state.borrow_mut(); let mut state_guard = self.state.borrow_mut();
@ -142,7 +144,7 @@ impl AudioDecoderImpl for LewtonDec {
let streamheaders = streamheaders.as_slice(); let streamheaders = streamheaders.as_slice();
if streamheaders.len() < 3 { if streamheaders.len() < 3 {
gst_debug!( gst_debug!(
self.cat, CAT,
obj: element, obj: element,
"Not enough streamheaders, trying in-band" "Not enough streamheaders, trying in-band"
); );
@ -155,7 +157,7 @@ impl AudioDecoderImpl for LewtonDec {
if let (Ok(Some(ident_buf)), Ok(Some(comment_buf)), Ok(Some(setup_buf))) = if let (Ok(Some(ident_buf)), Ok(Some(comment_buf)), Ok(Some(setup_buf))) =
(ident_buf, comment_buf, setup_buf) (ident_buf, comment_buf, setup_buf)
{ {
gst_debug!(self.cat, obj: element, "Got streamheader buffers"); gst_debug!(CAT, obj: element, "Got streamheader buffers");
state.header_bufs = (Some(ident_buf), Some(comment_buf), Some(setup_buf)); state.header_bufs = (Some(ident_buf), Some(comment_buf), Some(setup_buf));
} }
} }
@ -164,7 +166,7 @@ impl AudioDecoderImpl for LewtonDec {
} }
fn flush(&self, element: &gst_audio::AudioDecoder, _hard: bool) { fn flush(&self, element: &gst_audio::AudioDecoder, _hard: bool) {
gst_debug!(self.cat, obj: element, "Flushing"); gst_debug!(CAT, obj: element, "Flushing");
let mut state_guard = self.state.borrow_mut(); let mut state_guard = self.state.borrow_mut();
if let Some(ref mut state) = *state_guard { if let Some(ref mut state) = *state_guard {
@ -177,7 +179,7 @@ impl AudioDecoderImpl for LewtonDec {
element: &gst_audio::AudioDecoder, element: &gst_audio::AudioDecoder,
inbuf: Option<&gst::Buffer>, inbuf: Option<&gst::Buffer>,
) -> Result<gst::FlowSuccess, gst::FlowError> { ) -> Result<gst::FlowSuccess, gst::FlowError> {
gst_debug!(self.cat, obj: element, "Handling buffer {:?}", inbuf); gst_debug!(CAT, obj: element, "Handling buffer {:?}", inbuf);
let inbuf = match inbuf { let inbuf = match inbuf {
None => return Ok(gst::FlowSuccess::Ok), None => return Ok(gst::FlowSuccess::Ok),
@ -185,7 +187,7 @@ impl AudioDecoderImpl for LewtonDec {
}; };
let inmap = inbuf.map_readable().ok_or_else(|| { let inmap = inbuf.map_readable().ok_or_else(|| {
gst_error!(self.cat, obj: element, "Failed to buffer readable"); gst_error!(CAT, obj: element, "Failed to buffer readable");
gst::FlowError::Error gst::FlowError::Error
})?; })?;
@ -199,11 +201,7 @@ impl AudioDecoderImpl for LewtonDec {
if state.headerset.is_some() { if state.headerset.is_some() {
return Ok(gst::FlowSuccess::Ok); return Ok(gst::FlowSuccess::Ok);
} else { } else {
gst_error!( gst_error!(CAT, obj: element, "Got empty packet before all headers");
self.cat,
obj: element,
"Got empty packet before all headers"
);
return Err(gst::FlowError::Error); return Err(gst::FlowError::Error);
} }
} }
@ -232,30 +230,26 @@ impl LewtonDec {
) -> Result<gst::FlowSuccess, gst::FlowError> { ) -> Result<gst::FlowSuccess, gst::FlowError> {
// ident header // ident header
if indata[0] == 0x01 { if indata[0] == 0x01 {
gst_debug!(self.cat, obj: element, "Got ident header buffer"); gst_debug!(CAT, obj: element, "Got ident header buffer");
state.header_bufs = (Some(inbuf.clone()), None, None); state.header_bufs = (Some(inbuf.clone()), None, None);
} else if indata[0] == 0x03 { } else if indata[0] == 0x03 {
// comment header // comment header
if state.header_bufs.0.is_none() { if state.header_bufs.0.is_none() {
gst_warning!( gst_warning!(CAT, obj: element, "Got comment header before ident header");
self.cat,
obj: element,
"Got comment header before ident header"
);
} else { } else {
gst_debug!(self.cat, obj: element, "Got comment header buffer"); gst_debug!(CAT, obj: element, "Got comment header buffer");
state.header_bufs.1 = Some(inbuf.clone()); state.header_bufs.1 = Some(inbuf.clone());
} }
} else if indata[0] == 0x05 { } else if indata[0] == 0x05 {
// setup header // setup header
if state.header_bufs.0.is_none() || state.header_bufs.1.is_none() { if state.header_bufs.0.is_none() || state.header_bufs.1.is_none() {
gst_warning!( gst_warning!(
self.cat, CAT,
obj: element, obj: element,
"Got setup header before ident/comment header" "Got setup header before ident/comment header"
); );
} else { } else {
gst_debug!(self.cat, obj: element, "Got setup header buffer"); gst_debug!(CAT, obj: element, "Got setup header buffer");
state.header_bufs.2 = Some(inbuf.clone()); state.header_bufs.2 = Some(inbuf.clone());
} }
} }
@ -284,11 +278,7 @@ impl LewtonDec {
// First try to parse the headers // First try to parse the headers
let ident_map = ident_buf.map_readable().ok_or_else(|| { let ident_map = ident_buf.map_readable().ok_or_else(|| {
gst_error!( gst_error!(CAT, obj: element, "Failed to map ident buffer readable");
self.cat,
obj: element,
"Failed to map ident buffer readable"
);
gst::FlowError::Error gst::FlowError::Error
})?; })?;
let ident = lewton::header::read_header_ident(ident_map.as_ref()).map_err(|err| { let ident = lewton::header::read_header_ident(ident_map.as_ref()).map_err(|err| {
@ -301,11 +291,7 @@ impl LewtonDec {
})?; })?;
let comment_map = comment_buf.map_readable().ok_or_else(|| { let comment_map = comment_buf.map_readable().ok_or_else(|| {
gst_error!( gst_error!(CAT, obj: element, "Failed to map comment buffer readable");
self.cat,
obj: element,
"Failed to map comment buffer readable"
);
gst::FlowError::Error gst::FlowError::Error
})?; })?;
let comment = lewton::header::read_header_comment(comment_map.as_ref()).map_err(|err| { let comment = lewton::header::read_header_comment(comment_map.as_ref()).map_err(|err| {
@ -318,11 +304,7 @@ impl LewtonDec {
})?; })?;
let setup_map = setup_buf.map_readable().ok_or_else(|| { let setup_map = setup_buf.map_readable().ok_or_else(|| {
gst_error!( gst_error!(CAT, obj: element, "Failed to map setup buffer readable");
self.cat,
obj: element,
"Failed to map setup buffer readable"
);
gst::FlowError::Error gst::FlowError::Error
})?; })?;
let setup = lewton::header::read_header_setup( let setup = lewton::header::read_header_setup(
@ -359,7 +341,7 @@ impl LewtonDec {
let mut map = [0; 8]; let mut map = [0; 8];
if let Err(_) = gst_audio::get_channel_reorder_map(from, to, &mut map[..channels]) { if let Err(_) = gst_audio::get_channel_reorder_map(from, to, &mut map[..channels]) {
gst_error!( gst_error!(
self.cat, CAT,
obj: element, obj: element,
"Failed to generate channel reorder map from {:?} to {:?}", "Failed to generate channel reorder map from {:?} to {:?}",
from, from,
@ -375,7 +357,7 @@ impl LewtonDec {
let audio_info = audio_info.build().unwrap(); let audio_info = audio_info.build().unwrap();
gst_debug!( gst_debug!(
self.cat, CAT,
obj: element, obj: element,
"Successfully parsed headers: {:?}", "Successfully parsed headers: {:?}",
audio_info audio_info
@ -430,12 +412,7 @@ impl LewtonDec {
} }
let sample_count = decoded.samples.len() / audio_info.channels() as usize; let sample_count = decoded.samples.len() / audio_info.channels() as usize;
gst_debug!( gst_debug!(CAT, obj: element, "Got {} decoded samples", sample_count);
self.cat,
obj: element,
"Got {} decoded samples",
sample_count
);
if sample_count == 0 { if sample_count == 0 {
return element.finish_frame(None, 1); return element.finish_frame(None, 1);

View file

@ -14,6 +14,8 @@ extern crate glib;
extern crate gstreamer as gst; extern crate gstreamer as gst;
#[macro_use] #[macro_use]
extern crate gstreamer_audio as gst_audio; extern crate gstreamer_audio as gst_audio;
#[macro_use]
extern crate lazy_static;
mod lewtondec; mod lewtondec;

View file

@ -14,6 +14,7 @@ gstreamer-video = { git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs
gstreamer-check = { git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs" } gstreamer-check = { git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs" }
rav1e = { git = "https://github.com/xiph/rav1e.git", default-features=false } rav1e = { git = "https://github.com/xiph/rav1e.git", default-features=false }
atomic_refcell = "0.1" atomic_refcell = "0.1"
lazy_static = "1.0"
[lib] [lib]
name = "gstrav1e" name = "gstrav1e"

View file

@ -12,6 +12,8 @@
extern crate glib; extern crate glib;
#[macro_use] #[macro_use]
extern crate gstreamer as gst; extern crate gstreamer as gst;
#[macro_use]
extern crate lazy_static;
mod rav1enc; mod rav1enc;

View file

@ -285,11 +285,18 @@ struct State {
} }
struct Rav1Enc { struct Rav1Enc {
cat: gst::DebugCategory,
state: AtomicRefCell<Option<State>>, state: AtomicRefCell<Option<State>>,
settings: Mutex<Settings>, settings: Mutex<Settings>,
} }
lazy_static! {
static ref CAT: gst::DebugCategory = gst::DebugCategory::new(
"rav1enc",
gst::DebugColorFlags::empty(),
Some("rav1e AV1 encoder"),
);
}
impl ObjectSubclass for Rav1Enc { impl ObjectSubclass for Rav1Enc {
const NAME: &'static str = "Rav1Enc"; const NAME: &'static str = "Rav1Enc";
type ParentType = gst_video::VideoEncoder; type ParentType = gst_video::VideoEncoder;
@ -300,11 +307,6 @@ impl ObjectSubclass for Rav1Enc {
fn new() -> Self { fn new() -> Self {
Self { Self {
cat: gst::DebugCategory::new(
"rav1enc",
gst::DebugColorFlags::empty(),
Some("rav1e AV1 encoder"),
),
state: AtomicRefCell::new(None), state: AtomicRefCell::new(None),
settings: Mutex::new(Default::default()), settings: Mutex::new(Default::default()),
} }
@ -488,10 +490,10 @@ impl VideoEncoderImpl for Rav1Enc {
state: &gst_video::VideoCodecState<gst_video::video_codec_state::Readable>, state: &gst_video::VideoCodecState<gst_video::video_codec_state::Readable>,
) -> Result<(), gst::LoggableError> { ) -> Result<(), gst::LoggableError> {
self.finish(element) self.finish(element)
.map_err(|_| gst_loggable_error!(self.cat, "Failed to drain"))?; .map_err(|_| gst_loggable_error!(CAT, "Failed to drain"))?;
let video_info = state.get_info(); let video_info = state.get_info();
gst_debug!(self.cat, obj: element, "Setting format {:?}", video_info); gst_debug!(CAT, obj: element, "Setting format {:?}", video_info);
let settings = self.settings.lock().unwrap(); let settings = self.settings.lock().unwrap();
@ -610,11 +612,11 @@ impl VideoEncoderImpl for Rav1Enc {
*self.state.borrow_mut() = Some(State { *self.state.borrow_mut() = Some(State {
context: if video_info.format_info().depth()[0] > 8 { context: if video_info.format_info().depth()[0] > 8 {
Context::Sixteen(cfg.new_context().map_err(|err| { Context::Sixteen(cfg.new_context().map_err(|err| {
gst_loggable_error!(self.cat, "Failed to create context: {:?}", err) gst_loggable_error!(CAT, "Failed to create context: {:?}", err)
})?) })?)
} else { } else {
Context::Eight(cfg.new_context().map_err(|err| { Context::Eight(cfg.new_context().map_err(|err| {
gst_loggable_error!(self.cat, "Failed to create context: {:?}", err) gst_loggable_error!(CAT, "Failed to create context: {:?}", err)
})?) })?)
}, },
video_info: video_info.clone(), video_info: video_info.clone(),
@ -622,16 +624,16 @@ impl VideoEncoderImpl for Rav1Enc {
let output_state = element let output_state = element
.set_output_state(gst::Caps::new_simple("video/x-av1", &[]), Some(state)) .set_output_state(gst::Caps::new_simple("video/x-av1", &[]), Some(state))
.map_err(|_| gst_loggable_error!(self.cat, "Failed to set output state"))?; .map_err(|_| gst_loggable_error!(CAT, "Failed to set output state"))?;
element element
.negotiate(output_state) .negotiate(output_state)
.map_err(|_| gst_loggable_error!(self.cat, "Failed to negotiate"))?; .map_err(|_| gst_loggable_error!(CAT, "Failed to negotiate"))?;
self.parent_set_format(element, state) self.parent_set_format(element, state)
} }
fn flush(&self, element: &gst_video::VideoEncoder) -> bool { fn flush(&self, element: &gst_video::VideoEncoder) -> bool {
gst_debug!(self.cat, obj: element, "Flushing"); gst_debug!(CAT, obj: element, "Flushing");
let mut state_guard = self.state.borrow_mut(); let mut state_guard = self.state.borrow_mut();
if let Some(ref mut state) = *state_guard { if let Some(ref mut state) = *state_guard {
@ -639,7 +641,7 @@ impl VideoEncoderImpl for Rav1Enc {
loop { loop {
match state.context.receive_packet() { match state.context.receive_packet() {
Ok(_) | Err(data::EncoderStatus::Encoded) => { Ok(_) | Err(data::EncoderStatus::Encoded) => {
gst_debug!(self.cat, obj: element, "Dropping packet on flush",); gst_debug!(CAT, obj: element, "Dropping packet on flush",);
} }
_ => break, _ => break,
} }
@ -653,7 +655,7 @@ impl VideoEncoderImpl for Rav1Enc {
&self, &self,
element: &gst_video::VideoEncoder, element: &gst_video::VideoEncoder,
) -> Result<gst::FlowSuccess, gst::FlowError> { ) -> Result<gst::FlowSuccess, gst::FlowError> {
gst_debug!(self.cat, obj: element, "Finishing"); gst_debug!(CAT, obj: element, "Finishing");
let mut state_guard = self.state.borrow_mut(); let mut state_guard = self.state.borrow_mut();
if let Some(ref mut state) = *state_guard { if let Some(ref mut state) = *state_guard {
@ -678,7 +680,7 @@ impl VideoEncoderImpl for Rav1Enc {
self.output_frames(element, state)?; self.output_frames(element, state)?;
gst_debug!( gst_debug!(
self.cat, CAT,
obj: element, obj: element,
"Sending frame {}", "Sending frame {}",
frame.get_system_frame_number() frame.get_system_frame_number()
@ -707,7 +709,7 @@ impl VideoEncoderImpl for Rav1Enc {
) { ) {
Ok(_) => { Ok(_) => {
gst_debug!( gst_debug!(
self.cat, CAT,
obj: element, obj: element,
"Sent frame {}", "Sent frame {}",
frame.get_system_frame_number() frame.get_system_frame_number()
@ -734,7 +736,7 @@ impl Rav1Enc {
match state.context.receive_packet() { match state.context.receive_packet() {
Ok((packet_type, packet_number, packet_data)) => { Ok((packet_type, packet_number, packet_data)) => {
gst_debug!( gst_debug!(
self.cat, CAT,
obj: element, obj: element,
"Received packet {} of size {}, frame type {:?}", "Received packet {} of size {}, frame type {:?}",
packet_number, packet_number,
@ -751,7 +753,7 @@ impl Rav1Enc {
element.finish_frame(Some(frame))?; element.finish_frame(Some(frame))?;
} }
Err(data::EncoderStatus::Encoded) => { Err(data::EncoderStatus::Encoded) => {
gst_debug!(self.cat, obj: element, "Encoded but not output frame yet",); gst_debug!(CAT, obj: element, "Encoded but not output frame yet",);
} }
Err(data::EncoderStatus::Failure) => { Err(data::EncoderStatus::Failure) => {
gst_element_error!( gst_element_error!(
@ -763,7 +765,7 @@ impl Rav1Enc {
} }
Err(err) => { Err(err) => {
gst_debug!( gst_debug!(
self.cat, CAT,
obj: element, obj: element,
"Soft error when receiving frame: {:?}", "Soft error when receiving frame: {:?}",
err err

View file

@ -17,6 +17,7 @@ gstreamer = { git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs", fea
gstreamer-base = { git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs" } gstreamer-base = { git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs" }
tokio = "0.1" tokio = "0.1"
bytes = "0.4" bytes = "0.4"
lazy_static = "1.0"
[dev-dependencies] [dev-dependencies]
hyper = "0.12" hyper = "0.12"

View file

@ -19,6 +19,8 @@ extern crate hyperx;
extern crate reqwest; extern crate reqwest;
extern crate tokio; extern crate tokio;
extern crate url; extern crate url;
#[macro_use]
extern crate lazy_static;
mod reqwesthttpsrc; mod reqwesthttpsrc;

View file

@ -220,7 +220,6 @@ impl Default for State {
#[derive(Debug)] #[derive(Debug)]
pub struct ReqwestHttpSrc { pub struct ReqwestHttpSrc {
cat: gst::DebugCategory,
client: Mutex<Option<ClientContext>>, client: Mutex<Option<ClientContext>>,
external_client: Mutex<Option<ClientContext>>, external_client: Mutex<Option<ClientContext>>,
settings: Mutex<Settings>, settings: Mutex<Settings>,
@ -229,6 +228,14 @@ pub struct ReqwestHttpSrc {
canceller: Mutex<Option<oneshot::Sender<Bytes>>>, canceller: Mutex<Option<oneshot::Sender<Bytes>>>,
} }
lazy_static! {
static ref CAT: gst::DebugCategory = gst::DebugCategory::new(
"reqwesthttpsrc",
gst::DebugColorFlags::empty(),
Some("Rust HTTP source"),
);
}
impl ReqwestHttpSrc { impl ReqwestHttpSrc {
fn set_location( fn set_location(
&self, &self,
@ -273,7 +280,7 @@ impl ReqwestHttpSrc {
fn ensure_client(&self, src: &gst_base::BaseSrc) -> Result<ClientContext, gst::ErrorMessage> { fn ensure_client(&self, src: &gst_base::BaseSrc) -> Result<ClientContext, gst::ErrorMessage> {
let mut client_guard = self.client.lock().unwrap(); let mut client_guard = self.client.lock().unwrap();
if let Some(ref client) = *client_guard { if let Some(ref client) = *client_guard {
gst_debug!(self.cat, obj: src, "Using already configured client"); gst_debug!(CAT, obj: src, "Using already configured client");
return Ok(client.clone()); return Ok(client.clone());
} }
@ -299,13 +306,13 @@ impl ReqwestHttpSrc {
drop(external_client); drop(external_client);
client client
} { } {
gst_debug!(self.cat, obj: src, "Using shared client"); gst_debug!(CAT, obj: src, "Using shared client");
*client_guard = Some(client.clone()); *client_guard = Some(client.clone());
return Ok(client); return Ok(client);
} }
gst_debug!(self.cat, obj: src, "Creating new client"); gst_debug!(CAT, obj: src, "Creating new client");
let client = ClientContext(Arc::new(ClientContextInner { let client = ClientContext(Arc::new(ClientContextInner {
client: Client::builder() client: Client::builder()
.cookie_store(true) .cookie_store(true)
@ -319,7 +326,7 @@ impl ReqwestHttpSrc {
})?, })?,
})); }));
gst_debug!(self.cat, obj: src, "Sharing new client with other elements"); gst_debug!(CAT, obj: src, "Sharing new client with other elements");
let mut context = gst::Context::new(REQWEST_CLIENT_CONTEXT, true); let mut context = gst::Context::new(REQWEST_CLIENT_CONTEXT, true);
{ {
let context = context.get_mut().unwrap(); let context = context.get_mut().unwrap();
@ -351,7 +358,7 @@ impl ReqwestHttpSrc {
RangeUnit, RawLike, UserAgent, RangeUnit, RawLike, UserAgent,
}; };
gst_debug!(self.cat, obj: src, "Creating new request for {}", uri); gst_debug!(CAT, obj: src, "Creating new request for {}", uri);
let req = { let req = {
let client = self.ensure_client(src)?; let client = self.ensure_client(src)?;
@ -391,7 +398,7 @@ impl ReqwestHttpSrc {
if let Some(value) = value.transform::<String>() { if let Some(value) = value.transform::<String>() {
let value = value.get::<&str>().unwrap().unwrap_or(""); let value = value.get::<&str>().unwrap().unwrap_or("");
gst_debug!( gst_debug!(
self.cat, CAT,
obj: src, obj: src,
"Appending extra-header: {}: {}", "Appending extra-header: {}: {}",
field, field,
@ -400,7 +407,7 @@ impl ReqwestHttpSrc {
headers.append_raw(String::from(field), value); headers.append_raw(String::from(field), value);
} else { } else {
gst_warning!( gst_warning!(
self.cat, CAT,
obj: src, obj: src,
"Failed to transform extra-header '{}' to string", "Failed to transform extra-header '{}' to string",
field field
@ -412,7 +419,7 @@ impl ReqwestHttpSrc {
if let Some(value) = value.transform::<String>() { if let Some(value) = value.transform::<String>() {
let value = value.get::<&str>().unwrap().unwrap_or(""); let value = value.get::<&str>().unwrap().unwrap_or("");
gst_debug!( gst_debug!(
self.cat, CAT,
obj: src, obj: src,
"Appending extra-header: {}: {}", "Appending extra-header: {}: {}",
field, field,
@ -421,7 +428,7 @@ impl ReqwestHttpSrc {
headers.append_raw(String::from(field), value); headers.append_raw(String::from(field), value);
} else { } else {
gst_warning!( gst_warning!(
self.cat, CAT,
obj: src, obj: src,
"Failed to transform extra-header '{}' to string", "Failed to transform extra-header '{}' to string",
field field
@ -431,7 +438,7 @@ impl ReqwestHttpSrc {
} else if let Some(value) = value.transform::<String>() { } else if let Some(value) = value.transform::<String>() {
let value = value.get::<&str>().unwrap().unwrap_or(""); let value = value.get::<&str>().unwrap().unwrap_or("");
gst_debug!( gst_debug!(
self.cat, CAT,
obj: src, obj: src,
"Appending extra-header: {}: {}", "Appending extra-header: {}: {}",
field, field,
@ -440,7 +447,7 @@ impl ReqwestHttpSrc {
headers.append_raw(String::from(field), value); headers.append_raw(String::from(field), value);
} else { } else {
gst_warning!( gst_warning!(
self.cat, CAT,
obj: src, obj: src,
"Failed to transform extra-header '{}' to string", "Failed to transform extra-header '{}' to string",
field field
@ -476,7 +483,7 @@ impl ReqwestHttpSrc {
req req
}; };
gst_debug!(self.cat, obj: src, "Sending new request: {:?}", req); gst_debug!(CAT, obj: src, "Sending new request: {:?}", req);
let uri_clone = uri.clone(); let uri_clone = uri.clone();
let res = self.wait(req.send().map_err(move |err| { let res = self.wait(req.send().map_err(move |err| {
@ -489,21 +496,21 @@ impl ReqwestHttpSrc {
let mut res = match res { let mut res = match res {
Ok(res) => res, Ok(res) => res,
Err(Some(err)) => { Err(Some(err)) => {
gst_debug!(self.cat, obj: src, "Error {:?}", err); gst_debug!(CAT, obj: src, "Error {:?}", err);
return Err(Some(err)); return Err(Some(err));
} }
Err(None) => { Err(None) => {
gst_debug!(self.cat, obj: src, "Flushing"); gst_debug!(CAT, obj: src, "Flushing");
return Err(None); return Err(None);
} }
}; };
gst_debug!(self.cat, obj: src, "Received response: {:?}", res); gst_debug!(CAT, obj: src, "Received response: {:?}", res);
if !res.status().is_success() { if !res.status().is_success() {
match res.status() { match res.status() {
StatusCode::NOT_FOUND => { StatusCode::NOT_FOUND => {
gst_error!(self.cat, obj: src, "Resource not found"); gst_error!(CAT, obj: src, "Resource not found");
return Err(Some(gst_error_msg!( return Err(Some(gst_error_msg!(
gst::ResourceError::NotFound, gst::ResourceError::NotFound,
["Resource '{}' not found", uri] ["Resource '{}' not found", uri]
@ -513,14 +520,14 @@ impl ReqwestHttpSrc {
| StatusCode::PAYMENT_REQUIRED | StatusCode::PAYMENT_REQUIRED
| StatusCode::FORBIDDEN | StatusCode::FORBIDDEN
| StatusCode::PROXY_AUTHENTICATION_REQUIRED => { | StatusCode::PROXY_AUTHENTICATION_REQUIRED => {
gst_error!(self.cat, obj: src, "Not authorized: {}", res.status()); gst_error!(CAT, obj: src, "Not authorized: {}", res.status());
return Err(Some(gst_error_msg!( return Err(Some(gst_error_msg!(
gst::ResourceError::NotAuthorized, gst::ResourceError::NotAuthorized,
["Not Authorized for resource '{}': {}", uri, res.status()] ["Not Authorized for resource '{}': {}", uri, res.status()]
))); )));
} }
_ => { _ => {
gst_error!(self.cat, obj: src, "Request failed: {}", res.status()); gst_error!(CAT, obj: src, "Request failed: {}", res.status());
return Err(Some(gst_error_msg!( return Err(Some(gst_error_msg!(
gst::ResourceError::OpenRead, gst::ResourceError::OpenRead,
["Request for '{}' failed: {}", uri, res.status()] ["Request for '{}' failed: {}", uri, res.status()]
@ -569,7 +576,7 @@ impl ReqwestHttpSrc {
}); });
if let Some(ContentType(ref content_type)) = headers.get() { if let Some(ContentType(ref content_type)) = headers.get() {
gst_debug!(self.cat, obj: src, "Got content type {}", content_type); gst_debug!(CAT, obj: src, "Got content type {}", content_type);
if let Some(ref mut caps) = caps { if let Some(ref mut caps) = caps {
let caps = caps.get_mut().unwrap(); let caps = caps.get_mut().unwrap();
let s = caps.get_mut_structure(0).unwrap(); let s = caps.get_mut_structure(0).unwrap();
@ -624,7 +631,7 @@ impl ReqwestHttpSrc {
} }
} }
gst_debug!(self.cat, obj: src, "Request successful"); gst_debug!(CAT, obj: src, "Request successful");
let body = mem::replace(res.body_mut(), Decoder::empty()); let body = mem::replace(res.body_mut(), Decoder::empty());
@ -706,7 +713,7 @@ impl ObjectImpl for ReqwestHttpSrc {
let location = value.get::<&str>().expect("type checked upstream"); let location = value.get::<&str>().expect("type checked upstream");
if let Err(err) = self.set_location(element, location) { if let Err(err) = self.set_location(element, location) {
gst_error!( gst_error!(
self.cat, CAT,
obj: element, obj: element,
"Failed to set property `location`: {:?}", "Failed to set property `location`: {:?}",
err err
@ -892,7 +899,7 @@ impl BaseSrcImpl for ReqwestHttpSrc {
}) })
.map(|uri| uri.clone())?; .map(|uri| uri.clone())?;
gst_debug!(self.cat, obj: src, "Starting for URI {}", uri); gst_debug!(CAT, obj: src, "Starting for URI {}", uri);
*state = self.do_request(src, uri, 0, None).map_err(|err| { *state = self.do_request(src, uri, 0, None).map_err(|err| {
err.unwrap_or_else(|| { err.unwrap_or_else(|| {
@ -904,7 +911,7 @@ impl BaseSrcImpl for ReqwestHttpSrc {
} }
fn stop(&self, src: &gst_base::BaseSrc) -> Result<(), gst::ErrorMessage> { fn stop(&self, src: &gst_base::BaseSrc) -> Result<(), gst::ErrorMessage> {
gst_debug!(self.cat, obj: src, "Stopping"); gst_debug!(CAT, obj: src, "Stopping");
*self.state.lock().unwrap() = State::Stopped; *self.state.lock().unwrap() = State::Stopped;
Ok(()) Ok(())
@ -950,10 +957,10 @@ impl BaseSrcImpl for ReqwestHttpSrc {
let start = segment.get_start().expect("No start position given"); let start = segment.get_start().expect("No start position given");
let stop = segment.get_stop(); let stop = segment.get_stop();
gst_debug!(self.cat, obj: src, "Seeking to {}-{:?}", start, stop); gst_debug!(CAT, obj: src, "Seeking to {}-{:?}", start, stop);
if position == start && old_stop == stop.0 { if position == start && old_stop == stop.0 {
gst_debug!(self.cat, obj: src, "No change to current request"); gst_debug!(CAT, obj: src, "No change to current request");
return true; return true;
} }
@ -1007,7 +1014,7 @@ impl BaseSrcImpl for ReqwestHttpSrc {
let current_body = match body.take() { let current_body = match body.take() {
Some(body) => body, Some(body) => body,
None => { None => {
gst_error!(self.cat, obj: src, "Don't have a response body"); gst_error!(CAT, obj: src, "Don't have a response body");
gst_element_error!( gst_element_error!(
src, src,
gst::ResourceError::Read, gst::ResourceError::Read,
@ -1023,13 +1030,13 @@ impl BaseSrcImpl for ReqwestHttpSrc {
drop(state); drop(state);
if let Some(caps) = caps { if let Some(caps) = caps {
gst_debug!(self.cat, obj: src, "Setting caps {:?}", caps); gst_debug!(CAT, obj: src, "Setting caps {:?}", caps);
src.set_caps(&caps) src.set_caps(&caps)
.map_err(|_| gst::FlowError::NotNegotiated)?; .map_err(|_| gst::FlowError::NotNegotiated)?;
} }
if let Some(tags) = tags { if let Some(tags) = tags {
gst_debug!(self.cat, obj: src, "Sending iradio tags {:?}", tags); gst_debug!(CAT, obj: src, "Sending iradio tags {:?}", tags);
let pad = src.get_static_pad("src").unwrap(); let pad = src.get_static_pad("src").unwrap();
pad.push_event(gst::Event::new_tag(tags).build()); pad.push_event(gst::Event::new_tag(tags).build());
} }
@ -1044,12 +1051,12 @@ impl BaseSrcImpl for ReqwestHttpSrc {
let res = match res { let res = match res {
Ok(res) => res, Ok(res) => res,
Err(Some(err)) => { Err(Some(err)) => {
gst_debug!(self.cat, obj: src, "Error {:?}", err); gst_debug!(CAT, obj: src, "Error {:?}", err);
src.post_error_message(&err); src.post_error_message(&err);
return Err(gst::FlowError::Error); return Err(gst::FlowError::Error);
} }
Err(None) => { Err(None) => {
gst_debug!(self.cat, obj: src, "Flushing"); gst_debug!(CAT, obj: src, "Flushing");
return Err(gst::FlowError::Flushing); return Err(gst::FlowError::Flushing);
} }
}; };
@ -1073,7 +1080,7 @@ impl BaseSrcImpl for ReqwestHttpSrc {
/* do something with the chunk and store the body again in the state */ /* do something with the chunk and store the body again in the state */
gst_trace!( gst_trace!(
self.cat, CAT,
obj: src, obj: src,
"Chunk of {} bytes received at offset {}", "Chunk of {} bytes received at offset {}",
chunk.len(), chunk.len(),
@ -1098,7 +1105,7 @@ impl BaseSrcImpl for ReqwestHttpSrc {
} }
(None, current_body) => { (None, current_body) => {
/* No further data, end of stream */ /* No further data, end of stream */
gst_debug!(self.cat, obj: src, "End of stream"); gst_debug!(CAT, obj: src, "End of stream");
*body = Some(current_body); *body = Some(current_body);
Err(gst::FlowError::Eos) Err(gst::FlowError::Eos)
} }
@ -1138,11 +1145,6 @@ impl ObjectSubclass for ReqwestHttpSrc {
fn new() -> Self { fn new() -> Self {
Self { Self {
cat: gst::DebugCategory::new(
"reqwesthttpsrc",
gst::DebugColorFlags::empty(),
Some("Rust HTTP source"),
),
client: Mutex::new(None), client: Mutex::new(None),
external_client: Mutex::new(None), external_client: Mutex::new(None),
settings: Mutex::new(Default::default()), settings: Mutex::new(Default::default()),

View file

@ -18,6 +18,7 @@ rusoto_s3 = "0.41"
url = "2" url = "2"
percent-encoding = "2" percent-encoding = "2"
tokio = "0.1" tokio = "0.1"
lazy_static = "1.0"
[lib] [lib]
name = "gstrusoto" name = "gstrusoto"

View file

@ -13,6 +13,8 @@ extern crate glib;
#[macro_use] #[macro_use]
extern crate gstreamer as gst; extern crate gstreamer as gst;
extern crate gstreamer_base as gst_base; extern crate gstreamer_base as gst_base;
#[macro_use]
extern crate lazy_static;
mod s3sink; mod s3sink;
mod s3src; mod s3src;

View file

@ -95,12 +95,19 @@ struct Settings {
pub struct S3Sink { pub struct S3Sink {
settings: Mutex<Settings>, settings: Mutex<Settings>,
state: Mutex<State>, state: Mutex<State>,
cat: gst::DebugCategory,
runtime: runtime::Runtime, runtime: runtime::Runtime,
canceller: Mutex<Option<oneshot::Sender<()>>>, canceller: Mutex<Option<oneshot::Sender<()>>>,
client: Mutex<S3Client>, client: Mutex<S3Client>,
} }
lazy_static! {
static ref CAT: gst::DebugCategory = gst::DebugCategory::new(
"rusotos3sink",
gst::DebugColorFlags::empty(),
Some("Amazon S3 Sink"),
);
}
impl Default for Settings { impl Default for Settings {
fn default() -> Self { fn default() -> Self {
Settings { Settings {
@ -187,7 +194,7 @@ impl S3Sink {
e_tag: output.e_tag.clone(), e_tag: output.e_tag.clone(),
part_number: Some(part_number), part_number: Some(part_number),
}); });
gst_info!(self.cat, obj: element, "Uploaded part {}", part_number); gst_info!(CAT, obj: element, "Uploaded part {}", part_number);
Ok(()) Ok(())
} }
@ -386,11 +393,6 @@ impl ObjectSubclass for S3Sink {
Self { Self {
settings: Mutex::new(Default::default()), settings: Mutex::new(Default::default()),
state: Mutex::new(Default::default()), state: Mutex::new(Default::default()),
cat: gst::DebugCategory::new(
"rusotos3sink",
gst::DebugColorFlags::empty(),
Some("Amazon S3 Sink"),
),
canceller: Mutex::new(None), canceller: Mutex::new(None),
runtime: runtime::Builder::new() runtime: runtime::Builder::new()
.core_threads(1) .core_threads(1)
@ -489,7 +491,7 @@ impl BaseSinkImpl for S3Sink {
fn stop(&self, element: &gst_base::BaseSink) -> Result<(), gst::ErrorMessage> { fn stop(&self, element: &gst_base::BaseSink) -> Result<(), gst::ErrorMessage> {
let mut state = self.state.lock().unwrap(); let mut state = self.state.lock().unwrap();
*state = State::Stopped; *state = State::Stopped;
gst_info!(self.cat, obj: element, "Stopped"); gst_info!(CAT, obj: element, "Stopped");
Ok(()) Ok(())
} }
@ -504,7 +506,7 @@ impl BaseSinkImpl for S3Sink {
return Err(gst::FlowError::Error); return Err(gst::FlowError::Error);
} }
gst_trace!(self.cat, obj: element, "Rendering {:?}", buffer); gst_trace!(CAT, obj: element, "Rendering {:?}", buffer);
let map = buffer.map_readable().ok_or_else(|| { let map = buffer.map_readable().ok_or_else(|| {
gst_element_error!(element, gst::CoreError::Failed, ["Failed to map buffer"]); gst_element_error!(element, gst::CoreError::Failed, ["Failed to map buffer"]);
gst::FlowError::Error gst::FlowError::Error
@ -515,7 +517,7 @@ impl BaseSinkImpl for S3Sink {
Err(err) => match err { Err(err) => match err {
Some(error_message) => { Some(error_message) => {
gst_error!( gst_error!(
self.cat, CAT,
obj: element, obj: element,
"Multipart upload failed: {}", "Multipart upload failed: {}",
error_message error_message
@ -524,7 +526,7 @@ impl BaseSinkImpl for S3Sink {
Err(gst::FlowError::Error) Err(gst::FlowError::Error)
} }
_ => { _ => {
gst_info!(self.cat, obj: element, "Upload interrupted. Flushing..."); gst_info!(CAT, obj: element, "Upload interrupted. Flushing...");
Err(gst::FlowError::Flushing) Err(gst::FlowError::Flushing)
} }
}, },
@ -542,7 +544,7 @@ impl BaseSinkImpl for S3Sink {
gst::EventView::Eos(_) => { gst::EventView::Eos(_) => {
if let Err(error_message) = self.finalize_upload(element) { if let Err(error_message) = self.finalize_upload(element) {
gst_error!( gst_error!(
self.cat, CAT,
obj: element, obj: element,
"Failed to finalize the upload: {}", "Failed to finalize the upload: {}",
error_message error_message

View file

@ -41,11 +41,18 @@ enum StreamingState {
pub struct S3Src { pub struct S3Src {
url: Mutex<Option<GstS3Url>>, url: Mutex<Option<GstS3Url>>,
state: Mutex<StreamingState>, state: Mutex<StreamingState>,
cat: gst::DebugCategory,
runtime: runtime::Runtime, runtime: runtime::Runtime,
canceller: Mutex<Option<oneshot::Sender<Bytes>>>, canceller: Mutex<Option<oneshot::Sender<Bytes>>>,
} }
lazy_static! {
static ref CAT: gst::DebugCategory = gst::DebugCategory::new(
"rusotos3src",
gst::DebugColorFlags::empty(),
Some("Amazon S3 Source"),
);
}
static PROPERTIES: [subclass::Property; 1] = [subclass::Property("uri", |name| { static PROPERTIES: [subclass::Property; 1] = [subclass::Property("uri", |name| {
glib::ParamSpec::string( glib::ParamSpec::string(
name, name,
@ -136,12 +143,7 @@ impl S3Src {
})?; })?;
if let Some(size) = output.content_length { if let Some(size) = output.content_length {
gst_info!( gst_info!(CAT, obj: src, "HEAD success, content length = {}", size);
self.cat,
obj: src,
"HEAD success, content length = {}",
size
);
Ok(size as u64) Ok(size as u64)
} else { } else {
Err(gst_error_msg!( Err(gst_error_msg!(
@ -183,7 +185,7 @@ impl S3Src {
}; };
gst_debug!( gst_debug!(
self.cat, CAT,
obj: src, obj: src,
"Requesting range: {}-{}", "Requesting range: {}-{}",
offset, offset,
@ -205,7 +207,7 @@ impl S3Src {
)?; )?;
gst_debug!( gst_debug!(
self.cat, CAT,
obj: src, obj: src,
"Read {} bytes", "Read {} bytes",
output.content_length.unwrap() output.content_length.unwrap()
@ -233,11 +235,6 @@ impl ObjectSubclass for S3Src {
Self { Self {
url: Mutex::new(None), url: Mutex::new(None),
state: Mutex::new(StreamingState::Stopped), state: Mutex::new(StreamingState::Stopped),
cat: gst::DebugCategory::new(
"rusotos3src",
gst::DebugColorFlags::empty(),
Some("Amazon S3 Source"),
),
runtime: runtime::Builder::new() runtime: runtime::Builder::new()
.core_threads(1) .core_threads(1)
.name_prefix("rusotos3src-runtime") .name_prefix("rusotos3src-runtime")
@ -430,7 +427,7 @@ impl BaseSrcImpl for S3Src {
Err(None) => Err(gst::FlowError::Flushing), Err(None) => Err(gst::FlowError::Flushing),
/* Actual Error */ /* Actual Error */
Err(Some(err)) => { Err(Some(err)) => {
gst_error!(self.cat, obj: src, "Could not GET: {}", err); gst_error!(CAT, obj: src, "Could not GET: {}", err);
Err(gst::FlowError::Error) Err(gst::FlowError::Error)
} }
} }

View file

@ -138,12 +138,19 @@ impl Default for State {
} }
struct AppSrc { struct AppSrc {
cat: gst::DebugCategory,
src_pad: gst::Pad, src_pad: gst::Pad,
state: Mutex<State>, state: Mutex<State>,
settings: Mutex<Settings>, settings: Mutex<Settings>,
} }
lazy_static! {
static ref CAT: gst::DebugCategory = gst::DebugCategory::new(
"ts-appsrc",
gst::DebugColorFlags::empty(),
Some("Thread-sharing app source"),
);
}
impl AppSrc { impl AppSrc {
fn create_io_context_event(state: &State) -> Option<gst::Event> { fn create_io_context_event(state: &State) -> Option<gst::Event> {
if let (&Some(ref pending_future_id), &Some(ref io_context)) = if let (&Some(ref pending_future_id), &Some(ref io_context)) =
@ -165,7 +172,7 @@ impl AppSrc {
fn src_event(&self, pad: &gst::Pad, element: &gst::Element, event: gst::Event) -> bool { fn src_event(&self, pad: &gst::Pad, element: &gst::Element, event: gst::Event) -> bool {
use gst::EventView; use gst::EventView;
gst_log!(self.cat, obj: pad, "Handling event {:?}", event); gst_log!(CAT, obj: pad, "Handling event {:?}", event);
let ret = match event.view() { let ret = match event.view() {
EventView::FlushStart(..) => { EventView::FlushStart(..) => {
@ -187,9 +194,9 @@ impl AppSrc {
}; };
if ret { if ret {
gst_log!(self.cat, obj: pad, "Handled event {:?}", event); gst_log!(CAT, obj: pad, "Handled event {:?}", event);
} else { } else {
gst_log!(self.cat, obj: pad, "Didn't handle event {:?}", event); gst_log!(CAT, obj: pad, "Didn't handle event {:?}", event);
} }
ret ret
@ -203,7 +210,7 @@ impl AppSrc {
) -> bool { ) -> bool {
use gst::QueryView; use gst::QueryView;
gst_log!(self.cat, obj: pad, "Handling query {:?}", query); gst_log!(CAT, obj: pad, "Handling query {:?}", query);
let ret = match query.view_mut() { let ret = match query.view_mut() {
QueryView::Latency(ref mut q) => { QueryView::Latency(ref mut q) => {
q.set(true, 0.into(), 0.into()); q.set(true, 0.into(), 0.into());
@ -234,9 +241,9 @@ impl AppSrc {
}; };
if ret { if ret {
gst_log!(self.cat, obj: pad, "Handled query {:?}", query); gst_log!(CAT, obj: pad, "Handled query {:?}", query);
} else { } else {
gst_log!(self.cat, obj: pad, "Didn't handle query {:?}", query); gst_log!(CAT, obj: pad, "Didn't handle query {:?}", query);
} }
ret ret
} }
@ -253,7 +260,7 @@ impl AppSrc {
buffer.set_dts(now - base_time); buffer.set_dts(now - base_time);
buffer.set_pts(gst::CLOCK_TIME_NONE); buffer.set_pts(gst::CLOCK_TIME_NONE);
} else { } else {
gst_error!(self.cat, obj: element, "Don't have a clock yet"); gst_error!(CAT, obj: element, "Don't have a clock yet");
return false; return false;
} }
} }
@ -263,7 +270,7 @@ impl AppSrc {
match channel.try_send(Either::Left(buffer)) { match channel.try_send(Either::Left(buffer)) {
Ok(_) => true, Ok(_) => true,
Err(err) => { Err(err) => {
gst_error!(self.cat, obj: element, "Failed to queue buffer: {}", err); gst_error!(CAT, obj: element, "Failed to queue buffer: {}", err);
false false
} }
} }
@ -278,7 +285,7 @@ impl AppSrc {
match channel.try_send(Either::Right(gst::Event::new_eos().build())) { match channel.try_send(Either::Right(gst::Event::new_eos().build())) {
Ok(_) => true, Ok(_) => true,
Err(err) => { Err(err) => {
gst_error!(self.cat, obj: element, "Failed to queue EOS: {}", err); gst_error!(CAT, obj: element, "Failed to queue EOS: {}", err);
false false
} }
} }
@ -298,7 +305,7 @@ impl AppSrc {
let mut events = Vec::new(); let mut events = Vec::new();
let mut state = self.state.lock().unwrap(); let mut state = self.state.lock().unwrap();
if state.need_initial_events { if state.need_initial_events {
gst_debug!(self.cat, obj: element, "Pushing initial events"); gst_debug!(CAT, obj: element, "Pushing initial events");
let stream_id = format!("{:08x}{:08x}", rand::random::<u32>(), rand::random::<u32>()); let stream_id = format!("{:08x}{:08x}", rand::random::<u32>(), rand::random::<u32>());
events.push(gst::Event::new_stream_start(&stream_id).build()); events.push(gst::Event::new_stream_start(&stream_id).build());
@ -330,11 +337,11 @@ impl AppSrc {
let res = match item { let res = match item {
Either::Left(buffer) => { Either::Left(buffer) => {
gst_log!(self.cat, obj: element, "Forwarding buffer {:?}", buffer); gst_log!(CAT, obj: element, "Forwarding buffer {:?}", buffer);
self.src_pad.push(buffer).map(|_| ()) self.src_pad.push(buffer).map(|_| ())
} }
Either::Right(event) => { Either::Right(event) => {
gst_log!(self.cat, obj: element, "Forwarding event {:?}", event); gst_log!(CAT, obj: element, "Forwarding event {:?}", event);
self.src_pad.push_event(event); self.src_pad.push_event(event);
Ok(()) Ok(())
} }
@ -342,15 +349,15 @@ impl AppSrc {
let res = match res { let res = match res {
Ok(_) => { Ok(_) => {
gst_log!(self.cat, obj: element, "Successfully pushed item"); gst_log!(CAT, obj: element, "Successfully pushed item");
Ok(()) Ok(())
} }
Err(gst::FlowError::Flushing) | Err(gst::FlowError::Eos) => { Err(gst::FlowError::Flushing) | Err(gst::FlowError::Eos) => {
gst_debug!(self.cat, obj: element, "EOS"); gst_debug!(CAT, obj: element, "EOS");
Err(()) Err(())
} }
Err(err) => { Err(err) => {
gst_error!(self.cat, obj: element, "Got error {}", err); gst_error!(CAT, obj: element, "Got error {}", err);
gst_element_error!( gst_element_error!(
element, element,
gst::StreamError::Failed, gst::StreamError::Failed,
@ -385,7 +392,7 @@ impl AppSrc {
} }
fn prepare(&self, element: &gst::Element) -> Result<(), gst::ErrorMessage> { fn prepare(&self, element: &gst::Element) -> Result<(), gst::ErrorMessage> {
gst_debug!(self.cat, obj: element, "Preparing"); gst_debug!(CAT, obj: element, "Preparing");
let settings = self.settings.lock().unwrap().clone(); let settings = self.settings.lock().unwrap().clone();
@ -401,7 +408,7 @@ impl AppSrc {
let pending_future_id = io_context.acquire_pending_future_id(); let pending_future_id = io_context.acquire_pending_future_id();
gst_debug!( gst_debug!(
self.cat, CAT,
obj: element, obj: element,
"Got pending future id {:?}", "Got pending future id {:?}",
pending_future_id pending_future_id
@ -410,13 +417,13 @@ impl AppSrc {
state.io_context = Some(io_context); state.io_context = Some(io_context);
state.pending_future_id = Some(pending_future_id); state.pending_future_id = Some(pending_future_id);
gst_debug!(self.cat, obj: element, "Prepared"); gst_debug!(CAT, obj: element, "Prepared");
Ok(()) Ok(())
} }
fn unprepare(&self, element: &gst::Element) -> Result<(), ()> { fn unprepare(&self, element: &gst::Element) -> Result<(), ()> {
gst_debug!(self.cat, obj: element, "Unpreparing"); gst_debug!(CAT, obj: element, "Unpreparing");
// FIXME: The IO Context has to be alive longer than the other parts // FIXME: The IO Context has to be alive longer than the other parts
// of the state. Otherwise a deadlock can happen between shutting down // of the state. Otherwise a deadlock can happen between shutting down
@ -438,13 +445,13 @@ impl AppSrc {
drop(io_context); drop(io_context);
gst_debug!(self.cat, obj: element, "Unprepared"); gst_debug!(CAT, obj: element, "Unprepared");
Ok(()) Ok(())
} }
fn start(&self, element: &gst::Element) -> Result<(), ()> { fn start(&self, element: &gst::Element) -> Result<(), ()> {
gst_debug!(self.cat, obj: element, "Starting"); gst_debug!(CAT, obj: element, "Starting");
let settings = self.settings.lock().unwrap().clone(); let settings = self.settings.lock().unwrap().clone();
let mut state = self.state.lock().unwrap(); let mut state = self.state.lock().unwrap();
@ -466,19 +473,19 @@ impl AppSrc {
io_context.spawn(future); io_context.spawn(future);
*channel = Some(channel_sender); *channel = Some(channel_sender);
gst_debug!(self.cat, obj: element, "Started"); gst_debug!(CAT, obj: element, "Started");
Ok(()) Ok(())
} }
fn stop(&self, element: &gst::Element) -> Result<(), ()> { fn stop(&self, element: &gst::Element) -> Result<(), ()> {
gst_debug!(self.cat, obj: element, "Stopping"); gst_debug!(CAT, obj: element, "Stopping");
let mut state = self.state.lock().unwrap(); let mut state = self.state.lock().unwrap();
let _ = state.channel.take(); let _ = state.channel.take();
let _ = state.pending_future_cancel.take(); let _ = state.pending_future_cancel.take();
gst_debug!(self.cat, obj: element, "Stopped"); gst_debug!(CAT, obj: element, "Stopped");
Ok(()) Ok(())
} }
@ -569,11 +576,6 @@ impl ObjectSubclass for AppSrc {
}); });
Self { Self {
cat: gst::DebugCategory::new(
"ts-appsrc",
gst::DebugColorFlags::empty(),
Some("Thread-sharing app source"),
),
src_pad, src_pad,
state: Mutex::new(State::default()), state: Mutex::new(State::default()),
settings: Mutex::new(Settings::default()), settings: Mutex::new(Settings::default()),
@ -659,7 +661,7 @@ impl ElementImpl for AppSrc {
element: &gst::Element, element: &gst::Element,
transition: gst::StateChange, transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> { ) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst_trace!(self.cat, obj: element, "Changing state {:?}", transition); gst_trace!(CAT, obj: element, "Changing state {:?}", transition);
match transition { match transition {
gst::StateChange::NullToReady => { gst::StateChange::NullToReady => {

View file

@ -241,13 +241,20 @@ impl Default for State {
} }
struct JitterBuffer { struct JitterBuffer {
cat: gst::DebugCategory,
sink_pad: gst::Pad, sink_pad: gst::Pad,
src_pad: gst::Pad, src_pad: gst::Pad,
state: Mutex<State>, state: Mutex<State>,
settings: Mutex<Settings>, settings: Mutex<Settings>,
} }
lazy_static! {
static ref CAT: gst::DebugCategory = gst::DebugCategory::new(
"ts-jitterbuffer",
gst::DebugColorFlags::empty(),
Some("Thread-sharing jitterbuffer"),
);
}
impl JitterBuffer { impl JitterBuffer {
fn get_current_running_time(&self, element: &gst::Element) -> gst::ClockTime { fn get_current_running_time(&self, element: &gst::Element) -> gst::ClockTime {
if let Some(clock) = element.get_clock() { if let Some(clock) = element.get_clock() {
@ -270,7 +277,7 @@ impl JitterBuffer {
) -> Result<gst::FlowSuccess, gst::FlowError> { ) -> Result<gst::FlowSuccess, gst::FlowError> {
let s = caps.get_structure(0).ok_or(gst::FlowError::Error)?; let s = caps.get_structure(0).ok_or(gst::FlowError::Error)?;
gst_info!(self.cat, obj: element, "Parsing caps: {:?}", caps); gst_info!(CAT, obj: element, "Parsing caps: {:?}", caps);
let payload = s let payload = s
.get_some::<i32>("payload") .get_some::<i32>("payload")
@ -317,7 +324,7 @@ impl JitterBuffer {
} }
gst_debug!( gst_debug!(
self.cat, CAT,
"new packet spacing {}, old packet spacing {} combined to {}", "new packet spacing {}, old packet spacing {} combined to {}",
new_packet_spacing, new_packet_spacing,
old_packet_spacing, old_packet_spacing,
@ -342,7 +349,7 @@ impl JitterBuffer {
let mut reset = false; let mut reset = false;
gst_debug!( gst_debug!(
self.cat, CAT,
obj: element, obj: element,
"Handling big gap, gap packets length: {}", "Handling big gap, gap packets length: {}",
gap_packets_length gap_packets_length
@ -361,7 +368,7 @@ impl JitterBuffer {
let gap_seq = rtp_buffer.get_seq(); let gap_seq = rtp_buffer.get_seq();
gst_log!( gst_log!(
self.cat, CAT,
obj: element, obj: element,
"Looking at gap packet with seq {}", "Looking at gap packet with seq {}",
gap_seq gap_seq
@ -384,12 +391,7 @@ impl JitterBuffer {
} }
} }
gst_debug!( gst_debug!(CAT, obj: element, "all consecutive: {}", all_consecutive);
self.cat,
obj: element,
"all consecutive: {}",
all_consecutive
);
if all_consecutive && gap_packets_length > 3 { if all_consecutive && gap_packets_length > 3 {
reset = true; reset = true;
@ -407,7 +409,7 @@ impl JitterBuffer {
pad: &gst::Pad, pad: &gst::Pad,
element: &gst::Element, element: &gst::Element,
) -> Result<gst::FlowSuccess, gst::FlowError> { ) -> Result<gst::FlowSuccess, gst::FlowError> {
gst_info!(self.cat, obj: element, "Resetting"); gst_info!(CAT, obj: element, "Resetting");
state.jbuf.borrow().flush(); state.jbuf.borrow().flush();
state.jbuf.borrow().reset_skew(); state.jbuf.borrow().reset_skew();
@ -456,7 +458,7 @@ impl JitterBuffer {
drop(rtp_buffer); drop(rtp_buffer);
gst_log!( gst_log!(
self.cat, CAT,
obj: element, obj: element,
"Storing buffer, seq: {}, rtptime: {}, pt: {}", "Storing buffer, seq: {}, rtptime: {}, pt: {}",
seq, seq,
@ -488,7 +490,7 @@ impl JitterBuffer {
state.last_pt = pt as u32; state.last_pt = pt as u32;
state.clock_rate = -1; state.clock_rate = -1;
gst_debug!(self.cat, obj: pad, "New payload type: {}", pt); gst_debug!(CAT, obj: pad, "New payload type: {}", pt);
if let Some(caps) = pad.get_current_caps() { if let Some(caps) = pad.get_current_caps() {
self.parse_caps(state, element, &caps, pt)?; self.parse_caps(state, element, &caps, pt)?;
@ -526,7 +528,7 @@ impl JitterBuffer {
if pts.is_none() { if pts.is_none() {
gst_debug!( gst_debug!(
self.cat, CAT,
obj: element, obj: element,
"cannot calculate a valid pts for #{}, discard", "cannot calculate a valid pts for #{}, discard",
seq seq
@ -559,7 +561,7 @@ impl JitterBuffer {
if gap <= 0 { if gap <= 0 {
state.num_late += 1; state.num_late += 1;
gst_debug!(self.cat, obj: element, "Dropping late {}", seq); gst_debug!(CAT, obj: element, "Dropping late {}", seq);
return Ok(gst::FlowSuccess::Ok); return Ok(gst::FlowSuccess::Ok);
} }
} }
@ -598,7 +600,7 @@ impl JitterBuffer {
state.earliest_seqnum = seq; state.earliest_seqnum = seq;
} }
gst_log!(self.cat, obj: pad, "Stored buffer"); gst_log!(CAT, obj: pad, "Stored buffer");
Ok(gst::FlowSuccess::Ok) Ok(gst::FlowSuccess::Ok)
} }
@ -619,7 +621,7 @@ impl JitterBuffer {
let mut ret = true; let mut ret = true;
gst_debug!( gst_debug!(
self.cat, CAT,
obj: element, obj: element,
"Pushing lost events seq: {}, last popped seq: {}", "Pushing lost events seq: {}, last popped seq: {}",
seqnum, seqnum,
@ -773,7 +775,7 @@ impl JitterBuffer {
state.num_pushed += 1; state.num_pushed += 1;
gst_debug!(self.cat, obj: &self.src_pad, "Pushing buffer {:?} with seq {}", buffer, seq); gst_debug!(CAT, obj: &self.src_pad, "Pushing buffer {:?} with seq {}", buffer, seq);
self.send_io_context_event(&state)?; self.send_io_context_event(&state)?;
@ -789,7 +791,7 @@ impl JitterBuffer {
let now = self.get_current_running_time(element); let now = self.get_current_running_time(element);
gst_debug!( gst_debug!(
self.cat, CAT,
obj: element, obj: element,
"now is {}, earliest pts is {}, packet_spacing {} and latency {}", "now is {}, earliest pts is {}, packet_spacing {} and latency {}",
now, now,
@ -817,7 +819,7 @@ impl JitterBuffer {
let element_clone = element.clone(); let element_clone = element.clone();
gst_debug!(self.cat, obj: element, "Scheduling wakeup in {}", timeout); gst_debug!(CAT, obj: element, "Scheduling wakeup in {}", timeout);
let timer = Timeout::new( let timer = Timeout::new(
state.io_context.as_ref().unwrap(), state.io_context.as_ref().unwrap(),
@ -835,7 +837,7 @@ impl JitterBuffer {
let now = jb.get_current_running_time(&element_clone); let now = jb.get_current_running_time(&element_clone);
gst_debug!( gst_debug!(
jb.cat, CAT,
obj: &element_clone, obj: &element_clone,
"Woke back up, earliest_pts {}", "Woke back up, earliest_pts {}",
state.earliest_pts state.earliest_pts
@ -937,7 +939,7 @@ impl JitterBuffer {
fn flush(&self, element: &gst::Element) { fn flush(&self, element: &gst::Element) {
let mut state = self.state.lock().unwrap(); let mut state = self.state.lock().unwrap();
gst_info!(self.cat, obj: element, "Flushing"); gst_info!(CAT, obj: element, "Flushing");
let io_context = state.io_context.take(); let io_context = state.io_context.take();
@ -952,7 +954,7 @@ impl JitterBuffer {
element: &gst::Element, element: &gst::Element,
buffer: gst::Buffer, buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> { ) -> Result<gst::FlowSuccess, gst::FlowError> {
gst_debug!(self.cat, obj: pad, "Handling buffer {:?}", buffer); gst_debug!(CAT, obj: pad, "Handling buffer {:?}", buffer);
let mut state = self.state.lock().unwrap(); let mut state = self.state.lock().unwrap();
self.enqueue_item(&mut state, pad, element, Some(buffer)) self.enqueue_item(&mut state, pad, element, Some(buffer))
} }
@ -961,7 +963,7 @@ impl JitterBuffer {
let mut forward = true; let mut forward = true;
use gst::EventView; use gst::EventView;
gst_log!(self.cat, obj: pad, "Handling event {:?}", event); gst_log!(CAT, obj: pad, "Handling event {:?}", event);
match event.view() { match event.view() {
EventView::FlushStop(..) => { EventView::FlushStop(..) => {
@ -989,7 +991,7 @@ impl JitterBuffer {
}; };
if forward { if forward {
gst_log!(self.cat, obj: pad, "Forwarding event {:?}", event); gst_log!(CAT, obj: pad, "Forwarding event {:?}", event);
self.src_pad.push_event(event) self.src_pad.push_event(event)
} else { } else {
true true
@ -1003,12 +1005,12 @@ impl JitterBuffer {
query: &mut gst::QueryRef, query: &mut gst::QueryRef,
) -> bool { ) -> bool {
use gst::QueryView; use gst::QueryView;
gst_log!(self.cat, obj: pad, "Forwarding query {:?}", query); gst_log!(CAT, obj: pad, "Forwarding query {:?}", query);
match query.view_mut() { match query.view_mut() {
QueryView::Drain(..) => { QueryView::Drain(..) => {
let mut state = self.state.lock().unwrap(); let mut state = self.state.lock().unwrap();
gst_info!(self.cat, obj: pad, "Draining"); gst_info!(CAT, obj: pad, "Draining");
self.enqueue_item(&mut state, pad, element, None).is_ok() self.enqueue_item(&mut state, pad, element, None).is_ok()
} }
_ => self.src_pad.peer_query(query), _ => self.src_pad.peer_query(query),
@ -1023,7 +1025,7 @@ impl JitterBuffer {
) -> bool { ) -> bool {
use gst::QueryView; use gst::QueryView;
gst_log!(self.cat, obj: pad, "Forwarding query {:?}", query); gst_log!(CAT, obj: pad, "Forwarding query {:?}", query);
match query.view_mut() { match query.view_mut() {
QueryView::Latency(ref mut q) => { QueryView::Latency(ref mut q) => {
@ -1059,7 +1061,7 @@ impl JitterBuffer {
} }
fn clear_pt_map(&self, element: &gst::Element) { fn clear_pt_map(&self, element: &gst::Element) {
gst_info!(self.cat, obj: element, "Clearing PT map"); gst_info!(CAT, obj: element, "Clearing PT map");
let mut state = self.state.lock().unwrap(); let mut state = self.state.lock().unwrap();
state.clock_rate = -1; state.clock_rate = -1;
@ -1164,11 +1166,6 @@ impl ObjectSubclass for JitterBuffer {
}); });
Self { Self {
cat: gst::DebugCategory::new(
"ts-jitterbuffer",
gst::DebugColorFlags::empty(),
Some("Thread-sharing jitterbuffer"),
),
sink_pad, sink_pad,
src_pad, src_pad,
state: Mutex::new(State::default()), state: Mutex::new(State::default()),
@ -1282,7 +1279,7 @@ impl ElementImpl for JitterBuffer {
element: &gst::Element, element: &gst::Element,
transition: gst::StateChange, transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> { ) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst_trace!(self.cat, obj: element, "Changing state {:?}", transition); gst_trace!(CAT, obj: element, "Changing state {:?}", transition);
match transition { match transition {
gst::StateChange::NullToReady => { gst::StateChange::NullToReady => {

View file

@ -283,13 +283,20 @@ impl Default for StateSink {
} }
struct ProxySink { struct ProxySink {
cat: gst::DebugCategory,
#[allow(unused)] #[allow(unused)]
sink_pad: gst::Pad, sink_pad: gst::Pad,
state: Mutex<StateSink>, state: Mutex<StateSink>,
settings: Mutex<SettingsSink>, settings: Mutex<SettingsSink>,
} }
lazy_static! {
static ref SINK_CAT: gst::DebugCategory = gst::DebugCategory::new(
"ts-proxysink",
gst::DebugColorFlags::empty(),
Some("Thread-sharing proxy sink"),
);
}
impl ProxySink { impl ProxySink {
fn enqueue_item( fn enqueue_item(
&self, &self,
@ -359,13 +366,13 @@ impl ProxySink {
queue.pending_queue.as_mut().unwrap().2.push_back(item); queue.pending_queue.as_mut().unwrap().2.push_back(item);
gst_log!( gst_log!(
self.cat, SINK_CAT,
obj: element, obj: element,
"Proxy is full - Pushing first item on pending queue" "Proxy is full - Pushing first item on pending queue"
); );
if schedule_now { if schedule_now {
gst_log!(self.cat, obj: element, "Scheduling pending queue now"); gst_log!(SINK_CAT, obj: element, "Scheduling pending queue now");
queue.pending_queue.as_mut().unwrap().1 = true; queue.pending_queue.as_mut().unwrap().1 = true;
@ -375,7 +382,7 @@ impl ProxySink {
let state = sink.state.lock().unwrap(); let state = sink.state.lock().unwrap();
gst_log!( gst_log!(
sink.cat, SINK_CAT,
obj: &element_clone, obj: &element_clone,
"Trying to empty pending queue" "Trying to empty pending queue"
); );
@ -407,14 +414,14 @@ impl ProxySink {
items.push_front(failed_item); items.push_front(failed_item);
*task = Some(task::current()); *task = Some(task::current());
gst_log!( gst_log!(
sink.cat, SINK_CAT,
obj: &element_clone, obj: &element_clone,
"Waiting for more queue space" "Waiting for more queue space"
); );
Ok(Async::NotReady) Ok(Async::NotReady)
} else { } else {
gst_log!( gst_log!(
sink.cat, SINK_CAT,
obj: &element_clone, obj: &element_clone,
"Pending queue is empty now" "Pending queue is empty now"
); );
@ -422,7 +429,7 @@ impl ProxySink {
} }
} else { } else {
gst_log!( gst_log!(
sink.cat, SINK_CAT,
obj: &element_clone, obj: &element_clone,
"Waiting for queue to be allocated" "Waiting for queue to be allocated"
); );
@ -430,7 +437,7 @@ impl ProxySink {
} }
} else { } else {
gst_log!( gst_log!(
sink.cat, SINK_CAT,
obj: &element_clone, obj: &element_clone,
"Flushing, dropping pending queue" "Flushing, dropping pending queue"
); );
@ -453,7 +460,7 @@ impl ProxySink {
Some(future) Some(future)
} }
} else { } else {
gst_log!(self.cat, obj: element, "Scheduling pending queue later"); gst_log!(SINK_CAT, obj: element, "Scheduling pending queue later");
None None
} }
@ -468,7 +475,7 @@ impl ProxySink {
}; };
if let Some(wait_future) = wait_future { if let Some(wait_future) = wait_future {
gst_log!(self.cat, obj: element, "Blocking until queue becomes empty"); gst_log!(SINK_CAT, obj: element, "Blocking until queue becomes empty");
executor::current_thread::block_on_all(wait_future).map_err(|_| { executor::current_thread::block_on_all(wait_future).map_err(|_| {
gst_element_error!( gst_element_error!(
element, element,
@ -490,7 +497,7 @@ impl ProxySink {
element: &gst::Element, element: &gst::Element,
buffer: gst::Buffer, buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> { ) -> Result<gst::FlowSuccess, gst::FlowError> {
gst_log!(self.cat, obj: pad, "Handling buffer {:?}", buffer); gst_log!(SINK_CAT, obj: pad, "Handling buffer {:?}", buffer);
self.enqueue_item(pad, element, DataQueueItem::Buffer(buffer)) self.enqueue_item(pad, element, DataQueueItem::Buffer(buffer))
} }
@ -500,14 +507,14 @@ impl ProxySink {
element: &gst::Element, element: &gst::Element,
list: gst::BufferList, list: gst::BufferList,
) -> Result<gst::FlowSuccess, gst::FlowError> { ) -> Result<gst::FlowSuccess, gst::FlowError> {
gst_log!(self.cat, obj: pad, "Handling buffer list {:?}", list); gst_log!(SINK_CAT, obj: pad, "Handling buffer list {:?}", list);
self.enqueue_item(pad, element, DataQueueItem::BufferList(list)) self.enqueue_item(pad, element, DataQueueItem::BufferList(list))
} }
fn sink_event(&self, pad: &gst::Pad, element: &gst::Element, event: gst::Event) -> bool { fn sink_event(&self, pad: &gst::Pad, element: &gst::Element, event: gst::Event) -> bool {
use gst::EventView; use gst::EventView;
gst_log!(self.cat, obj: pad, "Handling event {:?}", event); gst_log!(SINK_CAT, obj: pad, "Handling event {:?}", event);
match event.view() { match event.view() {
EventView::Eos(..) => { EventView::Eos(..) => {
@ -538,7 +545,7 @@ impl ProxySink {
.expect("missing signal arg"); .expect("missing signal arg");
gst_debug!( gst_debug!(
self.cat, SINK_CAT,
obj: element, obj: element,
"Got upstream pending future id {:?}", "Got upstream pending future id {:?}",
pending_future_id pending_future_id
@ -551,7 +558,7 @@ impl ProxySink {
_ => (), _ => (),
}; };
gst_log!(self.cat, obj: pad, "Queuing event {:?}", event); gst_log!(SINK_CAT, obj: pad, "Queuing event {:?}", event);
let _ = self.enqueue_item(pad, element, DataQueueItem::Event(event)); let _ = self.enqueue_item(pad, element, DataQueueItem::Event(event));
true true
} }
@ -562,13 +569,13 @@ impl ProxySink {
element: &gst::Element, element: &gst::Element,
query: &mut gst::QueryRef, query: &mut gst::QueryRef,
) -> bool { ) -> bool {
gst_log!(self.cat, obj: pad, "Handling query {:?}", query); gst_log!(SINK_CAT, obj: pad, "Handling query {:?}", query);
pad.query_default(Some(element), query) pad.query_default(Some(element), query)
} }
fn prepare(&self, element: &gst::Element) -> Result<(), gst::ErrorMessage> { fn prepare(&self, element: &gst::Element) -> Result<(), gst::ErrorMessage> {
gst_debug!(self.cat, obj: element, "Preparing"); gst_debug!(SINK_CAT, obj: element, "Preparing");
let settings = self.settings.lock().unwrap().clone(); let settings = self.settings.lock().unwrap().clone();
@ -584,35 +591,35 @@ impl ProxySink {
} }
}; };
gst_debug!(self.cat, obj: element, "Prepared"); gst_debug!(SINK_CAT, obj: element, "Prepared");
Ok(()) Ok(())
} }
fn unprepare(&self, element: &gst::Element) -> Result<(), ()> { fn unprepare(&self, element: &gst::Element) -> Result<(), ()> {
gst_debug!(self.cat, obj: element, "Unpreparing"); gst_debug!(SINK_CAT, obj: element, "Unpreparing");
let mut state = self.state.lock().unwrap(); let mut state = self.state.lock().unwrap();
*state = StateSink::default(); *state = StateSink::default();
gst_debug!(self.cat, obj: element, "Unprepared"); gst_debug!(SINK_CAT, obj: element, "Unprepared");
Ok(()) Ok(())
} }
fn start(&self, element: &gst::Element) -> Result<(), ()> { fn start(&self, element: &gst::Element) -> Result<(), ()> {
gst_debug!(self.cat, obj: element, "Starting"); gst_debug!(SINK_CAT, obj: element, "Starting");
let state = self.state.lock().unwrap(); let state = self.state.lock().unwrap();
let mut queue = state.queue.as_ref().unwrap().0.lock().unwrap(); let mut queue = state.queue.as_ref().unwrap().0.lock().unwrap();
queue.last_res = Ok(gst::FlowSuccess::Ok); queue.last_res = Ok(gst::FlowSuccess::Ok);
gst_debug!(self.cat, obj: element, "Started"); gst_debug!(SINK_CAT, obj: element, "Started");
Ok(()) Ok(())
} }
fn stop(&self, element: &gst::Element) -> Result<(), ()> { fn stop(&self, element: &gst::Element) -> Result<(), ()> {
gst_debug!(self.cat, obj: element, "Stopping"); gst_debug!(SINK_CAT, obj: element, "Stopping");
let mut state = self.state.lock().unwrap(); let mut state = self.state.lock().unwrap();
state.io_context = None; state.io_context = None;
@ -625,7 +632,7 @@ impl ProxySink {
} }
queue.last_res = Err(gst::FlowError::Flushing); queue.last_res = Err(gst::FlowError::Flushing);
gst_debug!(self.cat, obj: element, "Stopped"); gst_debug!(SINK_CAT, obj: element, "Stopped");
Ok(()) Ok(())
} }
@ -695,11 +702,6 @@ impl ObjectSubclass for ProxySink {
}); });
Self { Self {
cat: gst::DebugCategory::new(
"ts-proxysink",
gst::DebugColorFlags::empty(),
Some("Thread-sharing proxy sink"),
),
sink_pad, sink_pad,
state: Mutex::new(StateSink::default()), state: Mutex::new(StateSink::default()),
settings: Mutex::new(SettingsSink::default()), settings: Mutex::new(SettingsSink::default()),
@ -753,7 +755,7 @@ impl ElementImpl for ProxySink {
element: &gst::Element, element: &gst::Element,
transition: gst::StateChange, transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> { ) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst_trace!(self.cat, obj: element, "Changing state {:?}", transition); gst_trace!(SINK_CAT, obj: element, "Changing state {:?}", transition);
match transition { match transition {
gst::StateChange::NullToReady => { gst::StateChange::NullToReady => {
@ -782,12 +784,19 @@ impl ElementImpl for ProxySink {
} }
struct ProxySrc { struct ProxySrc {
cat: gst::DebugCategory,
src_pad: gst::Pad, src_pad: gst::Pad,
state: Mutex<StateSrc>, state: Mutex<StateSrc>,
settings: Mutex<SettingsSrc>, settings: Mutex<SettingsSrc>,
} }
lazy_static! {
static ref SRC_CAT: gst::DebugCategory = gst::DebugCategory::new(
"ts-proxysrc",
gst::DebugColorFlags::empty(),
Some("Thread-sharing proxy source"),
);
}
impl ProxySrc { impl ProxySrc {
fn create_io_context_event(state: &StateSrc) -> Option<gst::Event> { fn create_io_context_event(state: &StateSrc) -> Option<gst::Event> {
if let (&Some(ref pending_future_id), &Some(ref io_context)) = if let (&Some(ref pending_future_id), &Some(ref io_context)) =
@ -809,7 +818,7 @@ impl ProxySrc {
fn src_event(&self, pad: &gst::Pad, element: &gst::Element, event: gst::Event) -> bool { fn src_event(&self, pad: &gst::Pad, element: &gst::Element, event: gst::Event) -> bool {
use gst::EventView; use gst::EventView;
gst_log!(self.cat, obj: pad, "Handling event {:?}", event); gst_log!(SRC_CAT, obj: pad, "Handling event {:?}", event);
let ret = match event.view() { let ret = match event.view() {
EventView::FlushStart(..) => { EventView::FlushStart(..) => {
@ -831,9 +840,9 @@ impl ProxySrc {
}; };
if ret { if ret {
gst_log!(self.cat, obj: pad, "Handled event {:?}", event); gst_log!(SRC_CAT, obj: pad, "Handled event {:?}", event);
} else { } else {
gst_log!(self.cat, obj: pad, "Didn't handle event {:?}", event); gst_log!(SRC_CAT, obj: pad, "Didn't handle event {:?}", event);
} }
ret ret
@ -847,7 +856,7 @@ impl ProxySrc {
) -> bool { ) -> bool {
use gst::QueryView; use gst::QueryView;
gst_log!(self.cat, obj: pad, "Handling query {:?}", query); gst_log!(SRC_CAT, obj: pad, "Handling query {:?}", query);
let ret = match query.view_mut() { let ret = match query.view_mut() {
QueryView::Latency(ref mut q) => { QueryView::Latency(ref mut q) => {
q.set(true, 0.into(), 0.into()); q.set(true, 0.into(), 0.into());
@ -877,9 +886,9 @@ impl ProxySrc {
}; };
if ret { if ret {
gst_log!(self.cat, obj: pad, "Handled query {:?}", query); gst_log!(SRC_CAT, obj: pad, "Handled query {:?}", query);
} else { } else {
gst_log!(self.cat, obj: pad, "Didn't handle query {:?}", query); gst_log!(SRC_CAT, obj: pad, "Didn't handle query {:?}", query);
} }
ret ret
} }
@ -912,11 +921,11 @@ impl ProxySrc {
let res = match item { let res = match item {
DataQueueItem::Buffer(buffer) => { DataQueueItem::Buffer(buffer) => {
gst_log!(self.cat, obj: element, "Forwarding buffer {:?}", buffer); gst_log!(SRC_CAT, obj: element, "Forwarding buffer {:?}", buffer);
self.src_pad.push(buffer).map(|_| ()) self.src_pad.push(buffer).map(|_| ())
} }
DataQueueItem::BufferList(list) => { DataQueueItem::BufferList(list) => {
gst_log!(self.cat, obj: element, "Forwarding buffer list {:?}", list); gst_log!(SRC_CAT, obj: element, "Forwarding buffer list {:?}", list);
self.src_pad.push_list(list).map(|_| ()) self.src_pad.push_list(list).map(|_| ())
} }
DataQueueItem::Event(event) => { DataQueueItem::Event(event) => {
@ -936,11 +945,11 @@ impl ProxySrc {
match new_event { match new_event {
Some(event) => { Some(event) => {
gst_log!(self.cat, obj: element, "Forwarding new event {:?}", event); gst_log!(SRC_CAT, obj: element, "Forwarding new event {:?}", event);
self.src_pad.push_event(event); self.src_pad.push_event(event);
} }
None => { None => {
gst_log!(self.cat, obj: element, "Forwarding event {:?}", event); gst_log!(SRC_CAT, obj: element, "Forwarding event {:?}", event);
self.src_pad.push_event(event); self.src_pad.push_event(event);
} }
} }
@ -950,14 +959,14 @@ impl ProxySrc {
let res = match res { let res = match res {
Ok(_) => { Ok(_) => {
gst_log!(self.cat, obj: element, "Successfully pushed item"); gst_log!(SRC_CAT, obj: element, "Successfully pushed item");
let state = self.state.lock().unwrap(); let state = self.state.lock().unwrap();
let mut queue = state.queue.as_ref().unwrap().0.lock().unwrap(); let mut queue = state.queue.as_ref().unwrap().0.lock().unwrap();
queue.last_res = Ok(gst::FlowSuccess::Ok); queue.last_res = Ok(gst::FlowSuccess::Ok);
Ok(()) Ok(())
} }
Err(gst::FlowError::Flushing) => { Err(gst::FlowError::Flushing) => {
gst_debug!(self.cat, obj: element, "Flushing"); gst_debug!(SRC_CAT, obj: element, "Flushing");
let state = self.state.lock().unwrap(); let state = self.state.lock().unwrap();
let mut queue = state.queue.as_ref().unwrap().0.lock().unwrap(); let mut queue = state.queue.as_ref().unwrap().0.lock().unwrap();
if let Some(ref queue) = queue.queue { if let Some(ref queue) = queue.queue {
@ -967,7 +976,7 @@ impl ProxySrc {
Ok(()) Ok(())
} }
Err(gst::FlowError::Eos) => { Err(gst::FlowError::Eos) => {
gst_debug!(self.cat, obj: element, "EOS"); gst_debug!(SRC_CAT, obj: element, "EOS");
let state = self.state.lock().unwrap(); let state = self.state.lock().unwrap();
let mut queue = state.queue.as_ref().unwrap().0.lock().unwrap(); let mut queue = state.queue.as_ref().unwrap().0.lock().unwrap();
if let Some(ref queue) = queue.queue { if let Some(ref queue) = queue.queue {
@ -977,7 +986,7 @@ impl ProxySrc {
Ok(()) Ok(())
} }
Err(err) => { Err(err) => {
gst_error!(self.cat, obj: element, "Got error {}", err); gst_error!(SRC_CAT, obj: element, "Got error {}", err);
gst_element_error!( gst_element_error!(
element, element,
gst::StreamError::Failed, gst::StreamError::Failed,
@ -1015,7 +1024,7 @@ impl ProxySrc {
} }
fn prepare(&self, element: &gst::Element) -> Result<(), gst::ErrorMessage> { fn prepare(&self, element: &gst::Element) -> Result<(), gst::ErrorMessage> {
gst_debug!(self.cat, obj: element, "Preparing"); gst_debug!(SRC_CAT, obj: element, "Preparing");
let settings = self.settings.lock().unwrap().clone(); let settings = self.settings.lock().unwrap().clone();
@ -1062,8 +1071,7 @@ impl ProxySrc {
src.push_item(&element_clone, item) src.push_item(&element_clone, item)
}, },
move |err| { move |err| {
let src = Self::from_instance(&element_clone2); gst_error!(SRC_CAT, obj: &element_clone2, "Got error {}", err);
gst_error!(src.cat, obj: &element_clone2, "Got error {}", err);
match err { match err {
gst::FlowError::CustomError => (), gst::FlowError::CustomError => (),
err => { err => {
@ -1086,7 +1094,7 @@ impl ProxySrc {
let pending_future_id = io_context.acquire_pending_future_id(); let pending_future_id = io_context.acquire_pending_future_id();
gst_debug!( gst_debug!(
self.cat, SRC_CAT,
obj: element, obj: element,
"Got pending future id {:?}", "Got pending future id {:?}",
pending_future_id pending_future_id
@ -1098,13 +1106,13 @@ impl ProxySrc {
state.pending_future_id = Some(pending_future_id); state.pending_future_id = Some(pending_future_id);
state.queue = Some(queue); state.queue = Some(queue);
gst_debug!(self.cat, obj: element, "Prepared"); gst_debug!(SRC_CAT, obj: element, "Prepared");
Ok(()) Ok(())
} }
fn unprepare(&self, element: &gst::Element) -> Result<(), ()> { fn unprepare(&self, element: &gst::Element) -> Result<(), ()> {
gst_debug!(self.cat, obj: element, "Unpreparing"); gst_debug!(SRC_CAT, obj: element, "Unpreparing");
// FIXME: The IO Context has to be alive longer than the queue, // FIXME: The IO Context has to be alive longer than the queue,
// otherwise the queue can't finish any remaining work // otherwise the queue can't finish any remaining work
@ -1136,13 +1144,13 @@ impl ProxySrc {
} }
drop(io_context); drop(io_context);
gst_debug!(self.cat, obj: element, "Unprepared"); gst_debug!(SRC_CAT, obj: element, "Unprepared");
Ok(()) Ok(())
} }
fn start(&self, element: &gst::Element) -> Result<(), ()> { fn start(&self, element: &gst::Element) -> Result<(), ()> {
gst_debug!(self.cat, obj: element, "Starting"); gst_debug!(SRC_CAT, obj: element, "Starting");
let state = self.state.lock().unwrap(); let state = self.state.lock().unwrap();
let queue = state.queue.as_ref().unwrap().0.lock().unwrap(); let queue = state.queue.as_ref().unwrap().0.lock().unwrap();
@ -1150,13 +1158,13 @@ impl ProxySrc {
queue.unpause(); queue.unpause();
} }
gst_debug!(self.cat, obj: element, "Started"); gst_debug!(SRC_CAT, obj: element, "Started");
Ok(()) Ok(())
} }
fn stop(&self, element: &gst::Element) -> Result<(), ()> { fn stop(&self, element: &gst::Element) -> Result<(), ()> {
gst_debug!(self.cat, obj: element, "Stopping"); gst_debug!(SRC_CAT, obj: element, "Stopping");
let state = self.state.lock().unwrap(); let state = self.state.lock().unwrap();
let mut queue = state.queue.as_ref().unwrap().0.lock().unwrap(); let mut queue = state.queue.as_ref().unwrap().0.lock().unwrap();
@ -1166,7 +1174,7 @@ impl ProxySrc {
} }
let _ = queue.pending_future_cancel.take(); let _ = queue.pending_future_cancel.take();
gst_debug!(self.cat, obj: element, "Stopped"); gst_debug!(SRC_CAT, obj: element, "Stopped");
Ok(()) Ok(())
} }
@ -1226,11 +1234,6 @@ impl ObjectSubclass for ProxySrc {
}); });
Self { Self {
cat: gst::DebugCategory::new(
"ts-proxysrc",
gst::DebugColorFlags::empty(),
Some("Thread-sharing proxy source"),
),
src_pad, src_pad,
state: Mutex::new(StateSrc::default()), state: Mutex::new(StateSrc::default()),
settings: Mutex::new(SettingsSrc::default()), settings: Mutex::new(SettingsSrc::default()),
@ -1327,7 +1330,7 @@ impl ElementImpl for ProxySrc {
element: &gst::Element, element: &gst::Element,
transition: gst::StateChange, transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> { ) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst_trace!(self.cat, obj: element, "Changing state {:?}", transition); gst_trace!(SRC_CAT, obj: element, "Changing state {:?}", transition);
match transition { match transition {
gst::StateChange::NullToReady => { gst::StateChange::NullToReady => {

View file

@ -153,13 +153,20 @@ impl Default for State {
} }
struct Queue { struct Queue {
cat: gst::DebugCategory,
sink_pad: gst::Pad, sink_pad: gst::Pad,
src_pad: gst::Pad, src_pad: gst::Pad,
state: Mutex<State>, state: Mutex<State>,
settings: Mutex<Settings>, settings: Mutex<Settings>,
} }
lazy_static! {
static ref CAT: gst::DebugCategory = gst::DebugCategory::new(
"ts-queue",
gst::DebugColorFlags::empty(),
Some("Thread-sharing queue"),
);
}
impl Queue { impl Queue {
fn create_io_context_event(state: &State) -> Option<gst::Event> { fn create_io_context_event(state: &State) -> Option<gst::Event> {
if let (&Some(ref pending_future_id), &Some(ref io_context)) = if let (&Some(ref pending_future_id), &Some(ref io_context)) =
@ -222,7 +229,7 @@ impl Queue {
element: &gst::Element, element: &gst::Element,
state: &mut State, state: &mut State,
) -> Option<impl Future<Item = (), Error = ()>> { ) -> Option<impl Future<Item = (), Error = ()>> {
gst_log!(self.cat, obj: element, "Scheduling pending queue now"); gst_log!(CAT, obj: element, "Scheduling pending queue now");
let State { let State {
ref mut pending_queue, ref mut pending_queue,
@ -248,11 +255,7 @@ impl Queue {
return Ok(Async::Ready(())); return Ok(Async::Ready(()));
} }
gst_log!( gst_log!(CAT, obj: &element_clone, "Trying to empty pending queue");
queue.cat,
obj: &element_clone,
"Trying to empty pending queue"
);
let res = if let Some(PendingQueue { let res = if let Some(PendingQueue {
ref mut task, ref mut task,
@ -270,22 +273,14 @@ impl Queue {
if let Some(failed_item) = failed_item { if let Some(failed_item) = failed_item {
items.push_front(failed_item); items.push_front(failed_item);
*task = Some(task::current()); *task = Some(task::current());
gst_log!( gst_log!(CAT, obj: &element_clone, "Waiting for more queue space");
queue.cat,
obj: &element_clone,
"Waiting for more queue space"
);
Ok(Async::NotReady) Ok(Async::NotReady)
} else { } else {
gst_log!(queue.cat, obj: &element_clone, "Pending queue is empty now"); gst_log!(CAT, obj: &element_clone, "Pending queue is empty now");
Ok(Async::Ready(())) Ok(Async::Ready(()))
} }
} else { } else {
gst_log!( gst_log!(CAT, obj: &element_clone, "Flushing, dropping pending queue");
queue.cat,
obj: &element_clone,
"Flushing, dropping pending queue"
);
Ok(Async::Ready(())) Ok(Async::Ready(()))
}; };
@ -347,7 +342,7 @@ impl Queue {
pending_queue.as_mut().unwrap().items.push_back(item); pending_queue.as_mut().unwrap().items.push_back(item);
gst_log!( gst_log!(
self.cat, CAT,
obj: element, obj: element,
"Queue is full - Pushing first item on pending queue" "Queue is full - Pushing first item on pending queue"
); );
@ -355,7 +350,7 @@ impl Queue {
if schedule_now { if schedule_now {
self.schedule_pending_queue(element, &mut state) self.schedule_pending_queue(element, &mut state)
} else { } else {
gst_log!(self.cat, obj: element, "Scheduling pending queue later"); gst_log!(CAT, obj: element, "Scheduling pending queue later");
None None
} }
@ -371,11 +366,7 @@ impl Queue {
}; };
if let Some(wait_future) = wait_future { if let Some(wait_future) = wait_future {
gst_log!( gst_log!(CAT, obj: element, "Blocking until queue has space again");
self.cat,
obj: element,
"Blocking until queue has space again"
);
executor::current_thread::block_on_all(wait_future).map_err(|_| { executor::current_thread::block_on_all(wait_future).map_err(|_| {
gst_element_error!( gst_element_error!(
element, element,
@ -395,7 +386,7 @@ impl Queue {
element: &gst::Element, element: &gst::Element,
buffer: gst::Buffer, buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> { ) -> Result<gst::FlowSuccess, gst::FlowError> {
gst_log!(self.cat, obj: pad, "Handling buffer {:?}", buffer); gst_log!(CAT, obj: pad, "Handling buffer {:?}", buffer);
self.enqueue_item(pad, element, DataQueueItem::Buffer(buffer)) self.enqueue_item(pad, element, DataQueueItem::Buffer(buffer))
} }
@ -405,14 +396,14 @@ impl Queue {
element: &gst::Element, element: &gst::Element,
list: gst::BufferList, list: gst::BufferList,
) -> Result<gst::FlowSuccess, gst::FlowError> { ) -> Result<gst::FlowSuccess, gst::FlowError> {
gst_log!(self.cat, obj: pad, "Handling buffer list {:?}", list); gst_log!(CAT, obj: pad, "Handling buffer list {:?}", list);
self.enqueue_item(pad, element, DataQueueItem::BufferList(list)) self.enqueue_item(pad, element, DataQueueItem::BufferList(list))
} }
fn sink_event(&self, pad: &gst::Pad, element: &gst::Element, mut event: gst::Event) -> bool { fn sink_event(&self, pad: &gst::Pad, element: &gst::Element, mut event: gst::Event) -> bool {
use gst::EventView; use gst::EventView;
gst_log!(self.cat, obj: pad, "Handling event {:?}", event); gst_log!(CAT, obj: pad, "Handling event {:?}", event);
let mut new_event = None; let mut new_event = None;
match event.view() { match event.view() {
@ -441,7 +432,7 @@ impl Queue {
.expect("missing signal arg"); .expect("missing signal arg");
gst_debug!( gst_debug!(
self.cat, CAT,
obj: element, obj: element,
"Got upstream pending future id {:?}", "Got upstream pending future id {:?}",
pending_future_id pending_future_id
@ -464,11 +455,11 @@ impl Queue {
} }
if event.is_serialized() { if event.is_serialized() {
gst_log!(self.cat, obj: pad, "Queuing event {:?}", event); gst_log!(CAT, obj: pad, "Queuing event {:?}", event);
let _ = self.enqueue_item(pad, element, DataQueueItem::Event(event)); let _ = self.enqueue_item(pad, element, DataQueueItem::Event(event));
true true
} else { } else {
gst_log!(self.cat, obj: pad, "Forwarding event {:?}", event); gst_log!(CAT, obj: pad, "Forwarding event {:?}", event);
self.src_pad.push_event(event) self.src_pad.push_event(event)
} }
} }
@ -479,14 +470,14 @@ impl Queue {
_element: &gst::Element, _element: &gst::Element,
query: &mut gst::QueryRef, query: &mut gst::QueryRef,
) -> bool { ) -> bool {
gst_log!(self.cat, obj: pad, "Handling query {:?}", query); gst_log!(CAT, obj: pad, "Handling query {:?}", query);
if query.is_serialized() { if query.is_serialized() {
// FIXME: How can we do this? // FIXME: How can we do this?
gst_log!(self.cat, obj: pad, "Dropping serialized query {:?}", query); gst_log!(CAT, obj: pad, "Dropping serialized query {:?}", query);
false false
} else { } else {
gst_log!(self.cat, obj: pad, "Forwarding query {:?}", query); gst_log!(CAT, obj: pad, "Forwarding query {:?}", query);
self.src_pad.peer_query(query) self.src_pad.peer_query(query)
} }
} }
@ -494,7 +485,7 @@ impl Queue {
fn src_event(&self, pad: &gst::Pad, element: &gst::Element, event: gst::Event) -> bool { fn src_event(&self, pad: &gst::Pad, element: &gst::Element, event: gst::Event) -> bool {
use gst::EventView; use gst::EventView;
gst_log!(self.cat, obj: pad, "Handling event {:?}", event); gst_log!(CAT, obj: pad, "Handling event {:?}", event);
match event.view() { match event.view() {
EventView::FlushStart(..) => { EventView::FlushStart(..) => {
@ -511,7 +502,7 @@ impl Queue {
_ => (), _ => (),
}; };
gst_log!(self.cat, obj: pad, "Forwarding event {:?}", event); gst_log!(CAT, obj: pad, "Forwarding event {:?}", event);
self.sink_pad.push_event(event) self.sink_pad.push_event(event)
} }
@ -523,7 +514,7 @@ impl Queue {
) -> bool { ) -> bool {
use gst::QueryView; use gst::QueryView;
gst_log!(self.cat, obj: pad, "Handling query {:?}", query); gst_log!(CAT, obj: pad, "Handling query {:?}", query);
match query.view_mut() { match query.view_mut() {
QueryView::Scheduling(ref mut q) => { QueryView::Scheduling(ref mut q) => {
let mut new_query = gst::Query::new_scheduling(); let mut new_query = gst::Query::new_scheduling();
@ -532,7 +523,7 @@ impl Queue {
return res; return res;
} }
gst_log!(self.cat, obj: pad, "Upstream returned {:?}", new_query); gst_log!(CAT, obj: pad, "Upstream returned {:?}", new_query);
let (flags, min, max, align) = new_query.get_result(); let (flags, min, max, align) = new_query.get_result();
q.set(flags, min, max, align); q.set(flags, min, max, align);
@ -544,13 +535,13 @@ impl Queue {
.filter(|m| m != &gst::PadMode::Pull) .filter(|m| m != &gst::PadMode::Pull)
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
); );
gst_log!(self.cat, obj: pad, "Returning {:?}", q.get_mut_query()); gst_log!(CAT, obj: pad, "Returning {:?}", q.get_mut_query());
return true; return true;
} }
_ => (), _ => (),
}; };
gst_log!(self.cat, obj: pad, "Forwarding query {:?}", query); gst_log!(CAT, obj: pad, "Forwarding query {:?}", query);
self.sink_pad.peer_query(query) self.sink_pad.peer_query(query)
} }
@ -585,15 +576,15 @@ impl Queue {
let res = match item { let res = match item {
DataQueueItem::Buffer(buffer) => { DataQueueItem::Buffer(buffer) => {
gst_log!(self.cat, obj: element, "Forwarding buffer {:?}", buffer); gst_log!(CAT, obj: element, "Forwarding buffer {:?}", buffer);
self.src_pad.push(buffer).map(|_| ()) self.src_pad.push(buffer).map(|_| ())
} }
DataQueueItem::BufferList(list) => { DataQueueItem::BufferList(list) => {
gst_log!(self.cat, obj: element, "Forwarding buffer list {:?}", list); gst_log!(CAT, obj: element, "Forwarding buffer list {:?}", list);
self.src_pad.push_list(list).map(|_| ()) self.src_pad.push_list(list).map(|_| ())
} }
DataQueueItem::Event(event) => { DataQueueItem::Event(event) => {
gst_log!(self.cat, obj: element, "Forwarding event {:?}", event); gst_log!(CAT, obj: element, "Forwarding event {:?}", event);
self.src_pad.push_event(event); self.src_pad.push_event(event);
Ok(()) Ok(())
} }
@ -601,13 +592,13 @@ impl Queue {
let res = match res { let res = match res {
Ok(_) => { Ok(_) => {
gst_log!(self.cat, obj: element, "Successfully pushed item"); gst_log!(CAT, obj: element, "Successfully pushed item");
let mut state = self.state.lock().unwrap(); let mut state = self.state.lock().unwrap();
state.last_res = Ok(gst::FlowSuccess::Ok); state.last_res = Ok(gst::FlowSuccess::Ok);
Ok(()) Ok(())
} }
Err(gst::FlowError::Flushing) => { Err(gst::FlowError::Flushing) => {
gst_debug!(self.cat, obj: element, "Flushing"); gst_debug!(CAT, obj: element, "Flushing");
let mut state = self.state.lock().unwrap(); let mut state = self.state.lock().unwrap();
if let Some(ref queue) = state.queue { if let Some(ref queue) = state.queue {
queue.pause(); queue.pause();
@ -616,7 +607,7 @@ impl Queue {
Ok(()) Ok(())
} }
Err(gst::FlowError::Eos) => { Err(gst::FlowError::Eos) => {
gst_debug!(self.cat, obj: element, "EOS"); gst_debug!(CAT, obj: element, "EOS");
let mut state = self.state.lock().unwrap(); let mut state = self.state.lock().unwrap();
if let Some(ref queue) = state.queue { if let Some(ref queue) = state.queue {
queue.pause(); queue.pause();
@ -625,7 +616,7 @@ impl Queue {
Ok(()) Ok(())
} }
Err(err) => { Err(err) => {
gst_error!(self.cat, obj: element, "Got error {}", err); gst_error!(CAT, obj: element, "Got error {}", err);
gst_element_error!( gst_element_error!(
element, element,
gst::StreamError::Failed, gst::StreamError::Failed,
@ -662,7 +653,7 @@ impl Queue {
} }
fn prepare(&self, element: &gst::Element) -> Result<(), gst::ErrorMessage> { fn prepare(&self, element: &gst::Element) -> Result<(), gst::ErrorMessage> {
gst_debug!(self.cat, obj: element, "Preparing"); gst_debug!(CAT, obj: element, "Preparing");
let settings = self.settings.lock().unwrap().clone(); let settings = self.settings.lock().unwrap().clone();
@ -705,8 +696,7 @@ impl Queue {
queue.push_item(&element_clone, item) queue.push_item(&element_clone, item)
}, },
move |err| { move |err| {
let queue = Self::from_instance(&element_clone2); gst_error!(CAT, obj: &element_clone2, "Got error {}", err);
gst_error!(queue.cat, obj: &element_clone2, "Got error {}", err);
match err { match err {
gst::FlowError::CustomError => (), gst::FlowError::CustomError => (),
err => { err => {
@ -729,7 +719,7 @@ impl Queue {
let pending_future_id = io_context.acquire_pending_future_id(); let pending_future_id = io_context.acquire_pending_future_id();
gst_debug!( gst_debug!(
self.cat, CAT,
obj: element, obj: element,
"Got pending future id {:?}", "Got pending future id {:?}",
pending_future_id pending_future_id
@ -739,13 +729,13 @@ impl Queue {
state.queue = Some(dataqueue); state.queue = Some(dataqueue);
state.pending_future_id = Some(pending_future_id); state.pending_future_id = Some(pending_future_id);
gst_debug!(self.cat, obj: element, "Prepared"); gst_debug!(CAT, obj: element, "Prepared");
Ok(()) Ok(())
} }
fn unprepare(&self, element: &gst::Element) -> Result<(), ()> { fn unprepare(&self, element: &gst::Element) -> Result<(), ()> {
gst_debug!(self.cat, obj: element, "Unpreparing"); gst_debug!(CAT, obj: element, "Unpreparing");
// FIXME: The IO Context has to be alive longer than the queue, // FIXME: The IO Context has to be alive longer than the queue,
// otherwise the queue can't finish any remaining work // otherwise the queue can't finish any remaining work
@ -770,12 +760,12 @@ impl Queue {
} }
drop(io_context); drop(io_context);
gst_debug!(self.cat, obj: element, "Unprepared"); gst_debug!(CAT, obj: element, "Unprepared");
Ok(()) Ok(())
} }
fn start(&self, element: &gst::Element) -> Result<(), ()> { fn start(&self, element: &gst::Element) -> Result<(), ()> {
gst_debug!(self.cat, obj: element, "Starting"); gst_debug!(CAT, obj: element, "Starting");
let mut state = self.state.lock().unwrap(); let mut state = self.state.lock().unwrap();
if let Some(ref queue) = state.queue { if let Some(ref queue) = state.queue {
@ -783,13 +773,13 @@ impl Queue {
} }
state.last_res = Ok(gst::FlowSuccess::Ok); state.last_res = Ok(gst::FlowSuccess::Ok);
gst_debug!(self.cat, obj: element, "Started"); gst_debug!(CAT, obj: element, "Started");
Ok(()) Ok(())
} }
fn stop(&self, element: &gst::Element) -> Result<(), ()> { fn stop(&self, element: &gst::Element) -> Result<(), ()> {
gst_debug!(self.cat, obj: element, "Stopping"); gst_debug!(CAT, obj: element, "Stopping");
let mut state = self.state.lock().unwrap(); let mut state = self.state.lock().unwrap();
if let Some(ref queue) = state.queue { if let Some(ref queue) = state.queue {
@ -805,7 +795,7 @@ impl Queue {
let _ = state.pending_future_cancel.take(); let _ = state.pending_future_cancel.take();
state.last_res = Err(gst::FlowError::Flushing); state.last_res = Err(gst::FlowError::Flushing);
gst_debug!(self.cat, obj: element, "Stopped"); gst_debug!(CAT, obj: element, "Stopped");
Ok(()) Ok(())
} }
@ -901,11 +891,6 @@ impl ObjectSubclass for Queue {
}); });
Self { Self {
cat: gst::DebugCategory::new(
"ts-queue",
gst::DebugColorFlags::empty(),
Some("Thread-sharing queue"),
),
sink_pad, sink_pad,
src_pad, src_pad,
state: Mutex::new(State::default()), state: Mutex::new(State::default()),
@ -991,7 +976,7 @@ impl ElementImpl for Queue {
element: &gst::Element, element: &gst::Element,
transition: gst::StateChange, transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> { ) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst_trace!(self.cat, obj: element, "Changing state {:?}", transition); gst_trace!(CAT, obj: element, "Changing state {:?}", transition);
match transition { match transition {
gst::StateChange::NullToReady => { gst::StateChange::NullToReady => {

View file

@ -199,17 +199,24 @@ impl Default for State {
} }
struct TcpClientSrc { struct TcpClientSrc {
cat: gst::DebugCategory,
src_pad: gst::Pad, src_pad: gst::Pad,
state: Mutex<State>, state: Mutex<State>,
settings: Mutex<Settings>, settings: Mutex<Settings>,
} }
lazy_static! {
static ref CAT: gst::DebugCategory = gst::DebugCategory::new(
"ts-tcpclientsrc",
gst::DebugColorFlags::empty(),
Some("Thread-sharing TCP Client source"),
);
}
impl TcpClientSrc { impl TcpClientSrc {
fn src_event(&self, pad: &gst::Pad, element: &gst::Element, event: gst::Event) -> bool { fn src_event(&self, pad: &gst::Pad, element: &gst::Element, event: gst::Event) -> bool {
use gst::EventView; use gst::EventView;
gst_log!(self.cat, obj: pad, "Handling event {:?}", event); gst_log!(CAT, obj: pad, "Handling event {:?}", event);
let ret = match event.view() { let ret = match event.view() {
EventView::FlushStart(..) => { EventView::FlushStart(..) => {
@ -231,9 +238,9 @@ impl TcpClientSrc {
}; };
if ret { if ret {
gst_log!(self.cat, obj: pad, "Handled event {:?}", event); gst_log!(CAT, obj: pad, "Handled event {:?}", event);
} else { } else {
gst_log!(self.cat, obj: pad, "Didn't handle event {:?}", event); gst_log!(CAT, obj: pad, "Didn't handle event {:?}", event);
} }
ret ret
} }
@ -246,7 +253,7 @@ impl TcpClientSrc {
) -> bool { ) -> bool {
use gst::QueryView; use gst::QueryView;
gst_log!(self.cat, obj: pad, "Handling query {:?}", query); gst_log!(CAT, obj: pad, "Handling query {:?}", query);
let ret = match query.view_mut() { let ret = match query.view_mut() {
QueryView::Latency(ref mut q) => { QueryView::Latency(ref mut q) => {
q.set(false, 0.into(), 0.into()); q.set(false, 0.into(), 0.into());
@ -277,9 +284,9 @@ impl TcpClientSrc {
}; };
if ret { if ret {
gst_log!(self.cat, obj: pad, "Handled query {:?}", query); gst_log!(CAT, obj: pad, "Handled query {:?}", query);
} else { } else {
gst_log!(self.cat, obj: pad, "Didn't handle query {:?}", query); gst_log!(CAT, obj: pad, "Didn't handle query {:?}", query);
} }
ret ret
} }
@ -312,7 +319,7 @@ impl TcpClientSrc {
let mut events = Vec::new(); let mut events = Vec::new();
let mut state = self.state.lock().unwrap(); let mut state = self.state.lock().unwrap();
if state.need_initial_events { if state.need_initial_events {
gst_debug!(self.cat, obj: element, "Pushing initial events"); gst_debug!(CAT, obj: element, "Pushing initial events");
let stream_id = format!("{:08x}{:08x}", rand::random::<u32>(), rand::random::<u32>()); let stream_id = format!("{:08x}{:08x}", rand::random::<u32>(), rand::random::<u32>());
events.push(gst::Event::new_stream_start(&stream_id).build()); events.push(gst::Event::new_stream_start(&stream_id).build());
@ -349,11 +356,11 @@ impl TcpClientSrc {
let res = match self.src_pad.push(buffer) { let res = match self.src_pad.push(buffer) {
Ok(_) => { Ok(_) => {
gst_log!(self.cat, obj: element, "Successfully pushed buffer"); gst_log!(CAT, obj: element, "Successfully pushed buffer");
Ok(()) Ok(())
} }
Err(gst::FlowError::Flushing) => { Err(gst::FlowError::Flushing) => {
gst_debug!(self.cat, obj: element, "Flushing"); gst_debug!(CAT, obj: element, "Flushing");
let state = self.state.lock().unwrap(); let state = self.state.lock().unwrap();
if let Some(ref socket) = state.socket { if let Some(ref socket) = state.socket {
socket.pause(); socket.pause();
@ -361,7 +368,7 @@ impl TcpClientSrc {
Ok(()) Ok(())
} }
Err(gst::FlowError::Eos) => { Err(gst::FlowError::Eos) => {
gst_debug!(self.cat, obj: element, "EOS"); gst_debug!(CAT, obj: element, "EOS");
let state = self.state.lock().unwrap(); let state = self.state.lock().unwrap();
if let Some(ref socket) = state.socket { if let Some(ref socket) = state.socket {
socket.pause(); socket.pause();
@ -369,7 +376,7 @@ impl TcpClientSrc {
Ok(()) Ok(())
} }
Err(err) => { Err(err) => {
gst_error!(self.cat, obj: element, "Got error {}", err); gst_error!(CAT, obj: element, "Got error {}", err);
gst_element_error!( gst_element_error!(
element, element,
gst::StreamError::Failed, gst::StreamError::Failed,
@ -406,7 +413,7 @@ impl TcpClientSrc {
fn prepare(&self, element: &gst::Element) -> Result<(), gst::ErrorMessage> { fn prepare(&self, element: &gst::Element) -> Result<(), gst::ErrorMessage> {
use std::net::{IpAddr, SocketAddr}; use std::net::{IpAddr, SocketAddr};
gst_debug!(self.cat, obj: element, "Preparing"); gst_debug!(CAT, obj: element, "Preparing");
let settings = self.settings.lock().unwrap().clone(); let settings = self.settings.lock().unwrap().clone();
@ -440,7 +447,7 @@ impl TcpClientSrc {
let port = settings.port; let port = settings.port;
let saddr = SocketAddr::new(addr, port as u16); let saddr = SocketAddr::new(addr, port as u16);
gst_debug!(self.cat, obj: element, "Connecting to {:?}", saddr); gst_debug!(CAT, obj: element, "Connecting to {:?}", saddr);
let socket = net::TcpStream::connect(&saddr); let socket = net::TcpStream::connect(&saddr);
let buffer_pool = gst::BufferPool::new(); let buffer_pool = gst::BufferPool::new();
@ -469,8 +476,7 @@ impl TcpClientSrc {
tcpclientsrc.push_buffer(&element_clone, buffer) tcpclientsrc.push_buffer(&element_clone, buffer)
}, },
move |err| { move |err| {
let tcpclientsrc = Self::from_instance(&element_clone2); gst_error!(CAT, obj: &element_clone2, "Got error {}", err);
gst_error!(tcpclientsrc.cat, obj: &element_clone2, "Got error {}", err);
match err { match err {
Either::Left(gst::FlowError::CustomError) => (), Either::Left(gst::FlowError::CustomError) => (),
Either::Left(err) => { Either::Left(err) => {
@ -498,7 +504,7 @@ impl TcpClientSrc {
let pending_future_id = io_context.acquire_pending_future_id(); let pending_future_id = io_context.acquire_pending_future_id();
gst_debug!( gst_debug!(
self.cat, CAT,
obj: element, obj: element,
"Got pending future id {:?}", "Got pending future id {:?}",
pending_future_id pending_future_id
@ -508,13 +514,13 @@ impl TcpClientSrc {
state.io_context = Some(io_context); state.io_context = Some(io_context);
state.pending_future_id = Some(pending_future_id); state.pending_future_id = Some(pending_future_id);
gst_debug!(self.cat, obj: element, "Prepared"); gst_debug!(CAT, obj: element, "Prepared");
Ok(()) Ok(())
} }
fn unprepare(&self, element: &gst::Element) -> Result<(), ()> { fn unprepare(&self, element: &gst::Element) -> Result<(), ()> {
gst_debug!(self.cat, obj: element, "Unpreparing"); gst_debug!(CAT, obj: element, "Unpreparing");
// FIXME: The IO Context has to be alive longer than the queue, // FIXME: The IO Context has to be alive longer than the queue,
// otherwise the queue can't finish any remaining work // otherwise the queue can't finish any remaining work
@ -538,25 +544,25 @@ impl TcpClientSrc {
} }
drop(io_context); drop(io_context);
gst_debug!(self.cat, obj: element, "Unprepared"); gst_debug!(CAT, obj: element, "Unprepared");
Ok(()) Ok(())
} }
fn start(&self, element: &gst::Element) -> Result<(), ()> { fn start(&self, element: &gst::Element) -> Result<(), ()> {
gst_debug!(self.cat, obj: element, "Starting"); gst_debug!(CAT, obj: element, "Starting");
let state = self.state.lock().unwrap(); let state = self.state.lock().unwrap();
if let Some(ref socket) = state.socket { if let Some(ref socket) = state.socket {
socket.unpause(None, None); socket.unpause(None, None);
} }
gst_debug!(self.cat, obj: element, "Started"); gst_debug!(CAT, obj: element, "Started");
Ok(()) Ok(())
} }
fn stop(&self, element: &gst::Element) -> Result<(), ()> { fn stop(&self, element: &gst::Element) -> Result<(), ()> {
gst_debug!(self.cat, obj: element, "Stopping"); gst_debug!(CAT, obj: element, "Stopping");
let mut state = self.state.lock().unwrap(); let mut state = self.state.lock().unwrap();
if let Some(ref socket) = state.socket { if let Some(ref socket) = state.socket {
@ -564,7 +570,7 @@ impl TcpClientSrc {
} }
let _ = state.pending_future_cancel.take(); let _ = state.pending_future_cancel.take();
gst_debug!(self.cat, obj: element, "Stopped"); gst_debug!(CAT, obj: element, "Stopped");
Ok(()) Ok(())
} }
@ -619,11 +625,6 @@ impl ObjectSubclass for TcpClientSrc {
}); });
Self { Self {
cat: gst::DebugCategory::new(
"ts-tcpclientsrc",
gst::DebugColorFlags::empty(),
Some("Thread-sharing TCP Client source"),
),
src_pad, src_pad,
state: Mutex::new(State::default()), state: Mutex::new(State::default()),
settings: Mutex::new(Settings::default()), settings: Mutex::new(Settings::default()),
@ -717,7 +718,7 @@ impl ElementImpl for TcpClientSrc {
element: &gst::Element, element: &gst::Element,
transition: gst::StateChange, transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> { ) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst_trace!(self.cat, obj: element, "Changing state {:?}", transition); gst_trace!(CAT, obj: element, "Changing state {:?}", transition);
match transition { match transition {
gst::StateChange::NullToReady => { gst::StateChange::NullToReady => {

View file

@ -334,17 +334,24 @@ impl Default for State {
} }
struct UdpSrc { struct UdpSrc {
cat: gst::DebugCategory,
src_pad: gst::Pad, src_pad: gst::Pad,
state: Mutex<State>, state: Mutex<State>,
settings: Mutex<Settings>, settings: Mutex<Settings>,
} }
lazy_static! {
static ref CAT: gst::DebugCategory = gst::DebugCategory::new(
"ts-udpsrc",
gst::DebugColorFlags::empty(),
Some("Thread-sharing UDP source"),
);
}
impl UdpSrc { impl UdpSrc {
fn src_event(&self, pad: &gst::Pad, element: &gst::Element, event: gst::Event) -> bool { fn src_event(&self, pad: &gst::Pad, element: &gst::Element, event: gst::Event) -> bool {
use gst::EventView; use gst::EventView;
gst_log!(self.cat, obj: pad, "Handling event {:?}", event); gst_log!(CAT, obj: pad, "Handling event {:?}", event);
let ret = match event.view() { let ret = match event.view() {
EventView::FlushStart(..) => { EventView::FlushStart(..) => {
@ -366,9 +373,9 @@ impl UdpSrc {
}; };
if ret { if ret {
gst_log!(self.cat, obj: pad, "Handled event {:?}", event); gst_log!(CAT, obj: pad, "Handled event {:?}", event);
} else { } else {
gst_log!(self.cat, obj: pad, "Didn't handle event {:?}", event); gst_log!(CAT, obj: pad, "Didn't handle event {:?}", event);
} }
ret ret
} }
@ -381,7 +388,7 @@ impl UdpSrc {
) -> bool { ) -> bool {
use gst::QueryView; use gst::QueryView;
gst_log!(self.cat, obj: pad, "Handling query {:?}", query); gst_log!(CAT, obj: pad, "Handling query {:?}", query);
let ret = match query.view_mut() { let ret = match query.view_mut() {
QueryView::Latency(ref mut q) => { QueryView::Latency(ref mut q) => {
q.set(true, 0.into(), 0.into()); q.set(true, 0.into(), 0.into());
@ -412,9 +419,9 @@ impl UdpSrc {
}; };
if ret { if ret {
gst_log!(self.cat, obj: pad, "Handled query {:?}", query); gst_log!(CAT, obj: pad, "Handled query {:?}", query);
} else { } else {
gst_log!(self.cat, obj: pad, "Didn't handle query {:?}", query); gst_log!(CAT, obj: pad, "Didn't handle query {:?}", query);
} }
ret ret
} }
@ -447,7 +454,7 @@ impl UdpSrc {
let mut events = Vec::new(); let mut events = Vec::new();
let mut state = self.state.lock().unwrap(); let mut state = self.state.lock().unwrap();
if state.need_initial_events { if state.need_initial_events {
gst_debug!(self.cat, obj: element, "Pushing initial events"); gst_debug!(CAT, obj: element, "Pushing initial events");
let stream_id = format!("{:08x}{:08x}", rand::random::<u32>(), rand::random::<u32>()); let stream_id = format!("{:08x}{:08x}", rand::random::<u32>(), rand::random::<u32>());
events.push(gst::Event::new_stream_start(&stream_id).build()); events.push(gst::Event::new_stream_start(&stream_id).build());
@ -479,11 +486,11 @@ impl UdpSrc {
let res = match self.src_pad.push(buffer) { let res = match self.src_pad.push(buffer) {
Ok(_) => { Ok(_) => {
gst_log!(self.cat, obj: element, "Successfully pushed buffer"); gst_log!(CAT, obj: element, "Successfully pushed buffer");
Ok(()) Ok(())
} }
Err(gst::FlowError::Flushing) => { Err(gst::FlowError::Flushing) => {
gst_debug!(self.cat, obj: element, "Flushing"); gst_debug!(CAT, obj: element, "Flushing");
let state = self.state.lock().unwrap(); let state = self.state.lock().unwrap();
if let Some(ref socket) = state.socket { if let Some(ref socket) = state.socket {
socket.pause(); socket.pause();
@ -491,7 +498,7 @@ impl UdpSrc {
Ok(()) Ok(())
} }
Err(gst::FlowError::Eos) => { Err(gst::FlowError::Eos) => {
gst_debug!(self.cat, obj: element, "EOS"); gst_debug!(CAT, obj: element, "EOS");
let state = self.state.lock().unwrap(); let state = self.state.lock().unwrap();
if let Some(ref socket) = state.socket { if let Some(ref socket) = state.socket {
socket.pause(); socket.pause();
@ -499,7 +506,7 @@ impl UdpSrc {
Ok(()) Ok(())
} }
Err(err) => { Err(err) => {
gst_error!(self.cat, obj: element, "Got error {}", err); gst_error!(CAT, obj: element, "Got error {}", err);
gst_element_error!( gst_element_error!(
element, element,
gst::StreamError::Failed, gst::StreamError::Failed,
@ -536,7 +543,7 @@ impl UdpSrc {
fn prepare(&self, element: &gst::Element) -> Result<(), gst::ErrorMessage> { fn prepare(&self, element: &gst::Element) -> Result<(), gst::ErrorMessage> {
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
gst_debug!(self.cat, obj: element, "Preparing"); gst_debug!(CAT, obj: element, "Preparing");
let settings = self.settings.lock().unwrap().clone(); let settings = self.settings.lock().unwrap().clone();
@ -606,7 +613,7 @@ impl UdpSrc {
let saddr = SocketAddr::new(bind_addr, port as u16); let saddr = SocketAddr::new(bind_addr, port as u16);
gst_debug!( gst_debug!(
self.cat, CAT,
obj: element, obj: element,
"Binding to {:?} for multicast group {:?}", "Binding to {:?} for multicast group {:?}",
saddr, saddr,
@ -616,7 +623,7 @@ impl UdpSrc {
saddr saddr
} else { } else {
let saddr = SocketAddr::new(addr, port as u16); let saddr = SocketAddr::new(addr, port as u16);
gst_debug!(self.cat, obj: element, "Binding to {:?}", saddr); gst_debug!(CAT, obj: element, "Binding to {:?}", saddr);
saddr saddr
}; };
@ -787,8 +794,7 @@ impl UdpSrc {
udpsrc.push_buffer(&element_clone, buffer) udpsrc.push_buffer(&element_clone, buffer)
}, },
move |err| { move |err| {
let udpsrc = Self::from_instance(&element_clone2); gst_error!(CAT, obj: &element_clone2, "Got error {}", err);
gst_error!(udpsrc.cat, obj: &element_clone2, "Got error {}", err);
match err { match err {
Either::Left(gst::FlowError::CustomError) => (), Either::Left(gst::FlowError::CustomError) => (),
Either::Left(err) => { Either::Left(err) => {
@ -816,7 +822,7 @@ impl UdpSrc {
let pending_future_id = io_context.acquire_pending_future_id(); let pending_future_id = io_context.acquire_pending_future_id();
gst_debug!( gst_debug!(
self.cat, CAT,
obj: element, obj: element,
"Got pending future id {:?}", "Got pending future id {:?}",
pending_future_id pending_future_id
@ -826,7 +832,7 @@ impl UdpSrc {
state.io_context = Some(io_context); state.io_context = Some(io_context);
state.pending_future_id = Some(pending_future_id); state.pending_future_id = Some(pending_future_id);
gst_debug!(self.cat, obj: element, "Prepared"); gst_debug!(CAT, obj: element, "Prepared");
drop(state); drop(state);
element.notify("used-socket"); element.notify("used-socket");
@ -835,7 +841,7 @@ impl UdpSrc {
} }
fn unprepare(&self, element: &gst::Element) -> Result<(), ()> { fn unprepare(&self, element: &gst::Element) -> Result<(), ()> {
gst_debug!(self.cat, obj: element, "Unpreparing"); gst_debug!(CAT, obj: element, "Unpreparing");
self.settings.lock().unwrap().used_socket = None; self.settings.lock().unwrap().used_socket = None;
@ -861,25 +867,25 @@ impl UdpSrc {
} }
drop(io_context); drop(io_context);
gst_debug!(self.cat, obj: element, "Unprepared"); gst_debug!(CAT, obj: element, "Unprepared");
Ok(()) Ok(())
} }
fn start(&self, element: &gst::Element) -> Result<(), ()> { fn start(&self, element: &gst::Element) -> Result<(), ()> {
gst_debug!(self.cat, obj: element, "Starting"); gst_debug!(CAT, obj: element, "Starting");
let state = self.state.lock().unwrap(); let state = self.state.lock().unwrap();
if let Some(ref socket) = state.socket { if let Some(ref socket) = state.socket {
socket.unpause(element.get_clock(), Some(element.get_base_time())); socket.unpause(element.get_clock(), Some(element.get_base_time()));
} }
gst_debug!(self.cat, obj: element, "Started"); gst_debug!(CAT, obj: element, "Started");
Ok(()) Ok(())
} }
fn stop(&self, element: &gst::Element) -> Result<(), ()> { fn stop(&self, element: &gst::Element) -> Result<(), ()> {
gst_debug!(self.cat, obj: element, "Stopping"); gst_debug!(CAT, obj: element, "Stopping");
let mut state = self.state.lock().unwrap(); let mut state = self.state.lock().unwrap();
if let Some(ref socket) = state.socket { if let Some(ref socket) = state.socket {
@ -887,7 +893,7 @@ impl UdpSrc {
} }
let _ = state.pending_future_cancel.take(); let _ = state.pending_future_cancel.take();
gst_debug!(self.cat, obj: element, "Stopped"); gst_debug!(CAT, obj: element, "Stopped");
Ok(()) Ok(())
} }
@ -958,11 +964,6 @@ impl ObjectSubclass for UdpSrc {
}); });
Self { Self {
cat: gst::DebugCategory::new(
"ts-udpsrc",
gst::DebugColorFlags::empty(),
Some("Thread-sharing UDP source"),
),
src_pad, src_pad,
state: Mutex::new(State::default()), state: Mutex::new(State::default()),
settings: Mutex::new(Settings::default()), settings: Mutex::new(Settings::default()),
@ -1097,7 +1098,7 @@ impl ElementImpl for UdpSrc {
element: &gst::Element, element: &gst::Element,
transition: gst::StateChange, transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> { ) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst_trace!(self.cat, obj: element, "Changing state {:?}", transition); gst_trace!(CAT, obj: element, "Changing state {:?}", transition);
match transition { match transition {
gst::StateChange::NullToReady => { gst::StateChange::NullToReady => {

View file

@ -15,6 +15,7 @@ gstreamer-video = { git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs
gtk = { git = "https://github.com/gtk-rs/gtk", optional = true } gtk = { git = "https://github.com/gtk-rs/gtk", optional = true }
gio = { git = "https://github.com/gtk-rs/gio", optional = true } gio = { git = "https://github.com/gtk-rs/gio", optional = true }
parking_lot = "0.9" parking_lot = "0.9"
lazy_static = "1.0"
[dev-dependencies] [dev-dependencies]
either = "1.0" either = "1.0"

View file

@ -24,6 +24,9 @@ extern crate gstreamer as gst;
extern crate gstreamer_audio as gst_audio; extern crate gstreamer_audio as gst_audio;
extern crate gstreamer_video as gst_video; extern crate gstreamer_video as gst_video;
#[macro_use]
extern crate lazy_static;
extern crate parking_lot; extern crate parking_lot;
mod togglerecord; mod togglerecord;

View file

@ -344,7 +344,6 @@ impl HandleData for gst::Buffer {
} }
struct ToggleRecord { struct ToggleRecord {
cat: gst::DebugCategory,
settings: Mutex<Settings>, settings: Mutex<Settings>,
state: Mutex<State>, state: Mutex<State>,
main_stream: Stream, main_stream: Stream,
@ -356,6 +355,14 @@ struct ToggleRecord {
pads: Mutex<HashMap<gst::Pad, Stream>>, pads: Mutex<HashMap<gst::Pad, Stream>>,
} }
lazy_static! {
static ref CAT: gst::DebugCategory = gst::DebugCategory::new(
"togglerecord",
gst::DebugColorFlags::empty(),
Some("Toggle Record Element"),
);
}
impl ToggleRecord { impl ToggleRecord {
fn set_pad_functions(sinkpad: &gst::Pad, srcpad: &gst::Pad) { fn set_pad_functions(sinkpad: &gst::Pad, srcpad: &gst::Pad) {
sinkpad.set_chain_function(|pad, parent, buffer| { sinkpad.set_chain_function(|pad, parent, buffer| {
@ -439,7 +446,7 @@ impl ToggleRecord {
let data = match data.clip(&state, &state.in_segment) { let data = match data.clip(&state, &state.in_segment) {
None => { None => {
gst_log!(self.cat, obj: pad, "Dropping raw data outside segment"); gst_log!(CAT, obj: pad, "Dropping raw data outside segment");
return Ok(HandleResult::Drop); return Ok(HandleResult::Drop);
} }
Some(data) => data, Some(data) => data,
@ -464,7 +471,7 @@ impl ToggleRecord {
self.main_stream_cond.notify_all(); self.main_stream_cond.notify_all();
gst_log!( gst_log!(
self.cat, CAT,
obj: pad, obj: pad,
"Main stream current running time {}-{} (position: {}-{})", "Main stream current running time {}-{} (position: {}-{})",
current_running_time, current_running_time,
@ -479,12 +486,12 @@ impl ToggleRecord {
let mut rec_state = self.state.lock(); let mut rec_state = self.state.lock();
let settings_changed = match rec_state.recording_state { let settings_changed = match rec_state.recording_state {
RecordingState::Recording if !settings.record => { RecordingState::Recording if !settings.record => {
gst_debug!(self.cat, obj: pad, "Stopping recording"); gst_debug!(CAT, obj: pad, "Stopping recording");
rec_state.recording_state = RecordingState::Stopping; rec_state.recording_state = RecordingState::Stopping;
true true
} }
RecordingState::Stopped if settings.record => { RecordingState::Stopped if settings.record => {
gst_debug!(self.cat, obj: pad, "Starting recording"); gst_debug!(CAT, obj: pad, "Starting recording");
rec_state.recording_state = RecordingState::Starting; rec_state.recording_state = RecordingState::Starting;
true true
} }
@ -495,19 +502,19 @@ impl ToggleRecord {
RecordingState::Recording => { RecordingState::Recording => {
// Remember where we stopped last, in case of EOS // Remember where we stopped last, in case of EOS
rec_state.last_recording_stop = current_running_time_end; rec_state.last_recording_stop = current_running_time_end;
gst_log!(self.cat, obj: pad, "Passing buffer (recording)"); gst_log!(CAT, obj: pad, "Passing buffer (recording)");
Ok(HandleResult::Pass(data)) Ok(HandleResult::Pass(data))
} }
RecordingState::Stopping => { RecordingState::Stopping => {
if !data.is_keyframe() { if !data.is_keyframe() {
// Remember where we stopped last, in case of EOS // Remember where we stopped last, in case of EOS
rec_state.last_recording_stop = current_running_time_end; rec_state.last_recording_stop = current_running_time_end;
gst_log!(self.cat, obj: pad, "Passing non-keyframe buffer (stopping)"); gst_log!(CAT, obj: pad, "Passing non-keyframe buffer (stopping)");
drop(rec_state); drop(rec_state);
drop(state); drop(state);
if settings_changed { if settings_changed {
gst_debug!(self.cat, obj: pad, "Requesting a new keyframe"); gst_debug!(CAT, obj: pad, "Requesting a new keyframe");
stream stream
.sinkpad .sinkpad
.push_event(gst_video::new_upstream_force_key_unit_event().build()); .push_event(gst_video::new_upstream_force_key_unit_event().build());
@ -518,7 +525,7 @@ impl ToggleRecord {
// Remember the time when we stopped: now, i.e. right before the current buffer! // Remember the time when we stopped: now, i.e. right before the current buffer!
rec_state.last_recording_stop = current_running_time; rec_state.last_recording_stop = current_running_time;
gst_debug!(self.cat, obj: pad, "Stopping at {}", current_running_time); gst_debug!(CAT, obj: pad, "Stopping at {}", current_running_time);
// Then unlock and wait for all other streams to reach it or go EOS instead. // Then unlock and wait for all other streams to reach it or go EOS instead.
drop(rec_state); drop(rec_state);
@ -529,12 +536,12 @@ impl ToggleRecord {
|| (s.current_running_time.is_some() || (s.current_running_time.is_some()
&& s.current_running_time >= current_running_time_end) && s.current_running_time >= current_running_time_end)
}) { }) {
gst_log!(self.cat, obj: pad, "Waiting for other streams to stop"); gst_log!(CAT, obj: pad, "Waiting for other streams to stop");
self.main_stream_cond.wait(&mut state); self.main_stream_cond.wait(&mut state);
} }
if state.flushing { if state.flushing {
gst_debug!(self.cat, obj: pad, "Flushing"); gst_debug!(CAT, obj: pad, "Flushing");
return Ok(HandleResult::Flushing); return Ok(HandleResult::Flushing);
} }
@ -546,7 +553,7 @@ impl ToggleRecord {
rec_state.last_recording_stop = gst::CLOCK_TIME_NONE; rec_state.last_recording_stop = gst::CLOCK_TIME_NONE;
gst_debug!( gst_debug!(
self.cat, CAT,
obj: pad, obj: pad,
"Stopped at {}, recording duration {}", "Stopped at {}, recording duration {}",
current_running_time, current_running_time,
@ -555,7 +562,7 @@ impl ToggleRecord {
// Then become Stopped and drop this buffer. We always stop right before // Then become Stopped and drop this buffer. We always stop right before
// a keyframe // a keyframe
gst_log!(self.cat, obj: pad, "Dropping buffer (stopped)"); gst_log!(CAT, obj: pad, "Dropping buffer (stopped)");
drop(rec_state); drop(rec_state);
drop(state); drop(state);
@ -564,22 +571,18 @@ impl ToggleRecord {
Ok(HandleResult::Drop) Ok(HandleResult::Drop)
} }
RecordingState::Stopped => { RecordingState::Stopped => {
gst_log!(self.cat, obj: pad, "Dropping buffer (stopped)"); gst_log!(CAT, obj: pad, "Dropping buffer (stopped)");
Ok(HandleResult::Drop) Ok(HandleResult::Drop)
} }
RecordingState::Starting => { RecordingState::Starting => {
// If this is no keyframe, we can directly go out again here and drop the frame // If this is no keyframe, we can directly go out again here and drop the frame
if !data.is_keyframe() { if !data.is_keyframe() {
gst_log!( gst_log!(CAT, obj: pad, "Dropping non-keyframe buffer (starting)");
self.cat,
obj: pad,
"Dropping non-keyframe buffer (starting)"
);
drop(rec_state); drop(rec_state);
drop(state); drop(state);
if settings_changed { if settings_changed {
gst_debug!(self.cat, obj: pad, "Requesting a new keyframe"); gst_debug!(CAT, obj: pad, "Requesting a new keyframe");
stream stream
.sinkpad .sinkpad
.push_event(gst_video::new_upstream_force_key_unit_event().build()); .push_event(gst_video::new_upstream_force_key_unit_event().build());
@ -591,7 +594,7 @@ impl ToggleRecord {
// Remember the time when we started: now! // Remember the time when we started: now!
rec_state.last_recording_start = current_running_time; rec_state.last_recording_start = current_running_time;
rec_state.running_time_offset = current_running_time - rec_state.recording_duration; rec_state.running_time_offset = current_running_time - rec_state.recording_duration;
gst_debug!(self.cat, obj: pad, "Starting at {}", current_running_time); gst_debug!(CAT, obj: pad, "Starting at {}", current_running_time);
state.segment_pending = true; state.segment_pending = true;
for other_stream in &self.other_streams.lock().0 { for other_stream in &self.other_streams.lock().0 {
@ -608,26 +611,26 @@ impl ToggleRecord {
|| (s.current_running_time.is_some() || (s.current_running_time.is_some()
&& s.current_running_time >= current_running_time_end) && s.current_running_time >= current_running_time_end)
}) { }) {
gst_log!(self.cat, obj: pad, "Waiting for other streams to start"); gst_log!(CAT, obj: pad, "Waiting for other streams to start");
self.main_stream_cond.wait(&mut state); self.main_stream_cond.wait(&mut state);
} }
if state.flushing { if state.flushing {
gst_debug!(self.cat, obj: pad, "Flushing"); gst_debug!(CAT, obj: pad, "Flushing");
return Ok(HandleResult::Flushing); return Ok(HandleResult::Flushing);
} }
let mut rec_state = self.state.lock(); let mut rec_state = self.state.lock();
rec_state.recording_state = RecordingState::Recording; rec_state.recording_state = RecordingState::Recording;
gst_debug!( gst_debug!(
self.cat, CAT,
obj: pad, obj: pad,
"Started at {}, recording duration {}", "Started at {}, recording duration {}",
current_running_time, current_running_time,
rec_state.recording_duration rec_state.recording_duration
); );
gst_log!(self.cat, obj: pad, "Passing buffer (recording)"); gst_log!(CAT, obj: pad, "Passing buffer (recording)");
drop(rec_state); drop(rec_state);
drop(state); drop(state);
@ -683,7 +686,7 @@ impl ToggleRecord {
let data = match data.clip(&state, &state.in_segment) { let data = match data.clip(&state, &state.in_segment) {
None => { None => {
gst_log!(self.cat, obj: pad, "Dropping raw data outside segment"); gst_log!(CAT, obj: pad, "Dropping raw data outside segment");
return Ok(HandleResult::Drop); return Ok(HandleResult::Drop);
} }
Some(data) => data, Some(data) => data,
@ -702,7 +705,7 @@ impl ToggleRecord {
state.current_running_time = cmp::max(current_running_time_end, state.current_running_time); state.current_running_time = cmp::max(current_running_time_end, state.current_running_time);
gst_log!( gst_log!(
self.cat, CAT,
obj: pad, obj: pad,
"Secondary stream current running time {}-{} (position: {}-{}", "Secondary stream current running time {}-{} (position: {}-{}",
current_running_time, current_running_time,
@ -725,7 +728,7 @@ impl ToggleRecord {
&& !stream.state.lock().flushing && !stream.state.lock().flushing
{ {
gst_log!( gst_log!(
self.cat, CAT,
obj: pad, obj: pad,
"Waiting for reaching {} / EOS / flushing, main stream at {}", "Waiting for reaching {} / EOS / flushing, main stream at {}",
current_running_time, current_running_time,
@ -738,7 +741,7 @@ impl ToggleRecord {
state = stream.state.lock(); state = stream.state.lock();
if state.flushing { if state.flushing {
gst_debug!(self.cat, obj: pad, "Flushing"); gst_debug!(CAT, obj: pad, "Flushing");
return Ok(HandleResult::Flushing); return Ok(HandleResult::Flushing);
} }
@ -749,11 +752,7 @@ impl ToggleRecord {
if main_state.eos { if main_state.eos {
// If we have no start or stop position (we never recorded) then we're EOS too now // If we have no start or stop position (we never recorded) then we're EOS too now
if rec_state.last_recording_stop.is_none() || rec_state.last_recording_start.is_none() { if rec_state.last_recording_stop.is_none() || rec_state.last_recording_start.is_none() {
gst_debug!( gst_debug!(CAT, obj: pad, "Main stream EOS and recording never started",);
self.cat,
obj: pad,
"Main stream EOS and recording never started",
);
return Ok(HandleResult::Eos); return Ok(HandleResult::Eos);
} else if data.can_clip(&*state) } else if data.can_clip(&*state)
&& current_running_time < rec_state.last_recording_start && current_running_time < rec_state.last_recording_start
@ -762,7 +761,7 @@ impl ToggleRecord {
// Otherwise if we're before the recording start but the end of the buffer is after // Otherwise if we're before the recording start but the end of the buffer is after
// the start and we can clip, clip the buffer and pass it onwards. // the start and we can clip, clip the buffer and pass it onwards.
gst_debug!( gst_debug!(
self.cat, CAT,
obj: pad, obj: pad,
"Main stream EOS and we're not EOS yet (overlapping recording start, {} < {} < {})", "Main stream EOS and we're not EOS yet (overlapping recording start, {} < {} < {})",
current_running_time, current_running_time,
@ -786,12 +785,12 @@ impl ToggleRecord {
segment.set_start(clip_start); segment.set_start(clip_start);
segment.set_stop(clip_stop); segment.set_stop(clip_stop);
gst_log!(self.cat, obj: pad, "Clipping to segment {:?}", segment,); gst_log!(CAT, obj: pad, "Clipping to segment {:?}", segment,);
if let Some(data) = data.clip(&*state, &segment) { if let Some(data) = data.clip(&*state, &segment) {
return Ok(HandleResult::Pass(data)); return Ok(HandleResult::Pass(data));
} else { } else {
gst_warning!(self.cat, obj: pad, "Complete buffer clipped!"); gst_warning!(CAT, obj: pad, "Complete buffer clipped!");
return Ok(HandleResult::Drop); return Ok(HandleResult::Drop);
} }
} else if current_running_time < rec_state.last_recording_start { } else if current_running_time < rec_state.last_recording_start {
@ -799,7 +798,7 @@ impl ToggleRecord {
// means that we either can't clip, or that the end is also before the // means that we either can't clip, or that the end is also before the
// recording start // recording start
gst_debug!( gst_debug!(
self.cat, CAT,
obj: pad, obj: pad,
"Main stream EOS and we're not EOS yet (before recording start, {} < {})", "Main stream EOS and we're not EOS yet (before recording start, {} < {})",
current_running_time, current_running_time,
@ -813,7 +812,7 @@ impl ToggleRecord {
// Similarly if the end is after the recording stop but the start is before and we // Similarly if the end is after the recording stop but the start is before and we
// can clip, clip the buffer and pass it through. // can clip, clip the buffer and pass it through.
gst_debug!( gst_debug!(
self.cat, CAT,
obj: pad, obj: pad,
"Main stream EOS and we're not EOS yet (overlapping recording end, {} < {} < {})", "Main stream EOS and we're not EOS yet (overlapping recording end, {} < {} < {})",
current_running_time, current_running_time,
@ -837,12 +836,12 @@ impl ToggleRecord {
segment.set_start(clip_start); segment.set_start(clip_start);
segment.set_stop(clip_stop); segment.set_stop(clip_stop);
gst_log!(self.cat, obj: pad, "Clipping to segment {:?}", segment,); gst_log!(CAT, obj: pad, "Clipping to segment {:?}", segment,);
if let Some(data) = data.clip(&*state, &segment) { if let Some(data) = data.clip(&*state, &segment) {
return Ok(HandleResult::Pass(data)); return Ok(HandleResult::Pass(data));
} else { } else {
gst_warning!(self.cat, obj: pad, "Complete buffer clipped!"); gst_warning!(CAT, obj: pad, "Complete buffer clipped!");
return Ok(HandleResult::Eos); return Ok(HandleResult::Eos);
} }
} else if current_running_time_end > rec_state.last_recording_stop { } else if current_running_time_end > rec_state.last_recording_stop {
@ -850,7 +849,7 @@ impl ToggleRecord {
// now. This means that we either couldn't clip or that the start is also after // now. This means that we either couldn't clip or that the start is also after
// the recording stop // the recording stop
gst_debug!( gst_debug!(
self.cat, CAT,
obj: pad, obj: pad,
"Main stream EOS and we're EOS too (after recording end, {} > {})", "Main stream EOS and we're EOS too (after recording end, {} > {})",
current_running_time_end, current_running_time_end,
@ -864,7 +863,7 @@ impl ToggleRecord {
assert!(current_running_time_end <= rec_state.last_recording_stop); assert!(current_running_time_end <= rec_state.last_recording_stop);
gst_debug!( gst_debug!(
self.cat, CAT,
obj: pad, obj: pad,
"Main stream EOS and we're not EOS yet (before recording end, {} <= {} <= {})", "Main stream EOS and we're not EOS yet (before recording end, {} <= {} <= {})",
rec_state.last_recording_start, rec_state.last_recording_start,
@ -884,21 +883,21 @@ impl ToggleRecord {
// be actually after that start position // be actually after that start position
assert!(rec_state.last_recording_start.is_some()); assert!(rec_state.last_recording_start.is_some());
assert!(current_running_time >= rec_state.last_recording_start); assert!(current_running_time >= rec_state.last_recording_start);
gst_log!(self.cat, obj: pad, "Passing buffer (recording)"); gst_log!(CAT, obj: pad, "Passing buffer (recording)");
Ok(HandleResult::Pass(data)) Ok(HandleResult::Pass(data))
} }
RecordingState::Stopping => { RecordingState::Stopping => {
// If we have no start position yet, the main stream is waiting for a key-frame // If we have no start position yet, the main stream is waiting for a key-frame
if rec_state.last_recording_stop.is_none() { if rec_state.last_recording_stop.is_none() {
gst_log!( gst_log!(
self.cat, CAT,
obj: pad, obj: pad,
"Passing buffer (stopping: waiting for keyframe)", "Passing buffer (stopping: waiting for keyframe)",
); );
Ok(HandleResult::Pass(data)) Ok(HandleResult::Pass(data))
} else if current_running_time_end <= rec_state.last_recording_stop { } else if current_running_time_end <= rec_state.last_recording_stop {
gst_log!( gst_log!(
self.cat, CAT,
obj: pad, obj: pad,
"Passing buffer (stopping: {} <= {})", "Passing buffer (stopping: {} <= {})",
current_running_time_end, current_running_time_end,
@ -910,7 +909,7 @@ impl ToggleRecord {
&& current_running_time_end > rec_state.last_recording_stop && current_running_time_end > rec_state.last_recording_stop
{ {
gst_log!( gst_log!(
self.cat, CAT,
obj: pad, obj: pad,
"Passing buffer (stopping: {} < {} < {})", "Passing buffer (stopping: {} < {} < {})",
current_running_time, current_running_time,
@ -927,17 +926,17 @@ impl ToggleRecord {
let mut segment = state.in_segment.clone(); let mut segment = state.in_segment.clone();
segment.set_stop(clip_stop); segment.set_stop(clip_stop);
gst_log!(self.cat, obj: pad, "Clipping to segment {:?}", segment,); gst_log!(CAT, obj: pad, "Clipping to segment {:?}", segment,);
if let Some(data) = data.clip(&*state, &segment) { if let Some(data) = data.clip(&*state, &segment) {
Ok(HandleResult::Pass(data)) Ok(HandleResult::Pass(data))
} else { } else {
gst_warning!(self.cat, obj: pad, "Complete buffer clipped!"); gst_warning!(CAT, obj: pad, "Complete buffer clipped!");
Ok(HandleResult::Drop) Ok(HandleResult::Drop)
} }
} else { } else {
gst_log!( gst_log!(
self.cat, CAT,
obj: pad, obj: pad,
"Dropping buffer (stopping: {} > {})", "Dropping buffer (stopping: {} > {})",
current_running_time_end, current_running_time_end,
@ -948,21 +947,21 @@ impl ToggleRecord {
} }
RecordingState::Stopped => { RecordingState::Stopped => {
// We're properly stopped // We're properly stopped
gst_log!(self.cat, obj: pad, "Dropping buffer (stopped)"); gst_log!(CAT, obj: pad, "Dropping buffer (stopped)");
Ok(HandleResult::Drop) Ok(HandleResult::Drop)
} }
RecordingState::Starting => { RecordingState::Starting => {
// If we have no start position yet, the main stream is waiting for a key-frame // If we have no start position yet, the main stream is waiting for a key-frame
if rec_state.last_recording_start.is_none() { if rec_state.last_recording_start.is_none() {
gst_log!( gst_log!(
self.cat, CAT,
obj: pad, obj: pad,
"Dropping buffer (starting: waiting for keyframe)", "Dropping buffer (starting: waiting for keyframe)",
); );
Ok(HandleResult::Drop) Ok(HandleResult::Drop)
} else if current_running_time >= rec_state.last_recording_start { } else if current_running_time >= rec_state.last_recording_start {
gst_log!( gst_log!(
self.cat, CAT,
obj: pad, obj: pad,
"Passing buffer (starting: {} >= {})", "Passing buffer (starting: {} >= {})",
current_running_time, current_running_time,
@ -974,7 +973,7 @@ impl ToggleRecord {
&& current_running_time_end > rec_state.last_recording_start && current_running_time_end > rec_state.last_recording_start
{ {
gst_log!( gst_log!(
self.cat, CAT,
obj: pad, obj: pad,
"Passing buffer (starting: {} < {} < {})", "Passing buffer (starting: {} < {} < {})",
current_running_time, current_running_time,
@ -991,17 +990,17 @@ impl ToggleRecord {
let mut segment = state.in_segment.clone(); let mut segment = state.in_segment.clone();
segment.set_start(clip_start); segment.set_start(clip_start);
gst_log!(self.cat, obj: pad, "Clipping to segment {:?}", segment,); gst_log!(CAT, obj: pad, "Clipping to segment {:?}", segment,);
if let Some(data) = data.clip(&*state, &segment) { if let Some(data) = data.clip(&*state, &segment) {
Ok(HandleResult::Pass(data)) Ok(HandleResult::Pass(data))
} else { } else {
gst_warning!(self.cat, obj: pad, "Complete buffer clipped!"); gst_warning!(CAT, obj: pad, "Complete buffer clipped!");
Ok(HandleResult::Drop) Ok(HandleResult::Drop)
} }
} else { } else {
gst_log!( gst_log!(
self.cat, CAT,
obj: pad, obj: pad,
"Dropping buffer (starting: {} < {})", "Dropping buffer (starting: {} < {})",
current_running_time, current_running_time,
@ -1028,7 +1027,7 @@ impl ToggleRecord {
gst::FlowError::Error gst::FlowError::Error
})?; })?;
gst_log!(self.cat, obj: pad, "Handling buffer {:?}", buffer); gst_log!(CAT, obj: pad, "Handling buffer {:?}", buffer);
{ {
let state = stream.state.lock(); let state = stream.state.lock();
@ -1086,16 +1085,11 @@ impl ToggleRecord {
.build(), .build(),
); );
state.segment_pending = false; state.segment_pending = false;
gst_debug!( gst_debug!(CAT, obj: pad, "Pending Segment {:?}", &state.out_segment);
self.cat,
obj: pad,
"Pending Segment {:?}",
&state.out_segment
);
} }
if !state.pending_events.is_empty() { if !state.pending_events.is_empty() {
gst_debug!(self.cat, obj: pad, "Pushing pending events"); gst_debug!(CAT, obj: pad, "Pushing pending events");
} }
events.append(&mut state.pending_events); events.append(&mut state.pending_events);
@ -1113,7 +1107,7 @@ impl ToggleRecord {
}; };
gst_log!( gst_log!(
self.cat, CAT,
obj: pad, obj: pad,
"Pushing buffer with running time {}: {:?}", "Pushing buffer with running time {}: {:?}",
out_running_time, out_running_time,
@ -1137,7 +1131,7 @@ impl ToggleRecord {
Some(stream) => stream.clone(), Some(stream) => stream.clone(),
}; };
gst_log!(self.cat, obj: pad, "Handling event {:?}", event); gst_log!(CAT, obj: pad, "Handling event {:?}", event);
let mut forward = true; let mut forward = true;
let mut send_pending = false; let mut send_pending = false;
@ -1168,12 +1162,12 @@ impl ToggleRecord {
let s = caps.get_structure(0).unwrap(); let s = caps.get_structure(0).unwrap();
if s.get_name().starts_with("audio/") { if s.get_name().starts_with("audio/") {
state.audio_info = gst_audio::AudioInfo::from_caps(caps); state.audio_info = gst_audio::AudioInfo::from_caps(caps);
gst_log!(self.cat, obj: pad, "Got audio caps {:?}", state.audio_info); gst_log!(CAT, obj: pad, "Got audio caps {:?}", state.audio_info);
state.video_info = None; state.video_info = None;
} else if s.get_name().starts_with("video/") { } else if s.get_name().starts_with("video/") {
state.audio_info = None; state.audio_info = None;
state.video_info = gst_video::VideoInfo::from_caps(caps); state.video_info = gst_video::VideoInfo::from_caps(caps);
gst_log!(self.cat, obj: pad, "Got video caps {:?}", state.video_info); gst_log!(CAT, obj: pad, "Got video caps {:?}", state.video_info);
} else { } else {
state.audio_info = None; state.audio_info = None;
state.video_info = None; state.video_info = None;
@ -1214,12 +1208,12 @@ impl ToggleRecord {
state.segment_pending = true; state.segment_pending = true;
state.current_running_time = gst::CLOCK_TIME_NONE; state.current_running_time = gst::CLOCK_TIME_NONE;
gst_debug!(self.cat, obj: pad, "Got new Segment {:?}", state.in_segment); gst_debug!(CAT, obj: pad, "Got new Segment {:?}", state.in_segment);
forward = false; forward = false;
} }
EventView::Gap(e) => { EventView::Gap(e) => {
gst_debug!(self.cat, obj: pad, "Handling Gap event {:?}", event); gst_debug!(CAT, obj: pad, "Handling Gap event {:?}", event);
let (pts, duration) = e.get(); let (pts, duration) = e.get();
let handle_result = if stream == self.main_stream { let handle_result = if stream == self.main_stream {
self.handle_main_stream(element, pad, &stream, (pts, duration)) self.handle_main_stream(element, pad, &stream, (pts, duration))
@ -1249,7 +1243,7 @@ impl ToggleRecord {
state.eos = true; state.eos = true;
self.main_stream_cond.notify_all(); self.main_stream_cond.notify_all();
gst_debug!( gst_debug!(
self.cat, CAT,
obj: pad, obj: pad,
"Stream is EOS now, sending any pending events" "Stream is EOS now, sending any pending events"
); );
@ -1269,7 +1263,7 @@ impl ToggleRecord {
{ {
let mut state = stream.state.lock(); let mut state = stream.state.lock();
if state.segment_pending { if state.segment_pending {
gst_log!(self.cat, obj: pad, "Storing event for later pushing"); gst_log!(CAT, obj: pad, "Storing event for later pushing");
state.pending_events.push(event); state.pending_events.push(event);
return true; return true;
} }
@ -1297,10 +1291,10 @@ impl ToggleRecord {
} }
if forward { if forward {
gst_log!(self.cat, obj: pad, "Forwarding event {:?}", event); gst_log!(CAT, obj: pad, "Forwarding event {:?}", event);
stream.srcpad.push_event(event) stream.srcpad.push_event(event)
} else { } else {
gst_log!(self.cat, obj: pad, "Dropping event {:?}", event); gst_log!(CAT, obj: pad, "Dropping event {:?}", event);
true true
} }
} }
@ -1323,7 +1317,7 @@ impl ToggleRecord {
Some(stream) => stream.clone(), Some(stream) => stream.clone(),
}; };
gst_log!(self.cat, obj: pad, "Handling query {:?}", query); gst_log!(CAT, obj: pad, "Handling query {:?}", query);
stream.srcpad.peer_query(query) stream.srcpad.peer_query(query)
} }
@ -1343,7 +1337,7 @@ impl ToggleRecord {
Some(stream) => stream.clone(), Some(stream) => stream.clone(),
}; };
gst_log!(self.cat, obj: pad, "Handling event {:?}", event); gst_log!(CAT, obj: pad, "Handling event {:?}", event);
let forward = match event.view() { let forward = match event.view() {
EventView::Seek(..) => false, EventView::Seek(..) => false,
@ -1359,10 +1353,10 @@ impl ToggleRecord {
drop(rec_state); drop(rec_state);
if forward { if forward {
gst_log!(self.cat, obj: pad, "Forwarding event {:?}", event); gst_log!(CAT, obj: pad, "Forwarding event {:?}", event);
stream.sinkpad.push_event(event) stream.sinkpad.push_event(event)
} else { } else {
gst_log!(self.cat, obj: pad, "Dropping event {:?}", event); gst_log!(CAT, obj: pad, "Dropping event {:?}", event);
false false
} }
} }
@ -1382,7 +1376,7 @@ impl ToggleRecord {
Some(stream) => stream.clone(), Some(stream) => stream.clone(),
}; };
gst_log!(self.cat, obj: pad, "Handling query {:?}", query); gst_log!(CAT, obj: pad, "Handling query {:?}", query);
match query.view_mut() { match query.view_mut() {
QueryView::Scheduling(ref mut q) => { QueryView::Scheduling(ref mut q) => {
let mut new_query = gst::Query::new_scheduling(); let mut new_query = gst::Query::new_scheduling();
@ -1391,7 +1385,7 @@ impl ToggleRecord {
return res; return res;
} }
gst_log!(self.cat, obj: pad, "Downstream returned {:?}", new_query); gst_log!(CAT, obj: pad, "Downstream returned {:?}", new_query);
let (flags, min, max, align) = new_query.get_result(); let (flags, min, max, align) = new_query.get_result();
q.set(flags, min, max, align); q.set(flags, min, max, align);
@ -1403,7 +1397,7 @@ impl ToggleRecord {
.filter(|m| m != &gst::PadMode::Pull) .filter(|m| m != &gst::PadMode::Pull)
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
); );
gst_log!(self.cat, obj: pad, "Returning {:?}", q.get_mut_query()); gst_log!(CAT, obj: pad, "Returning {:?}", q.get_mut_query());
true true
} }
QueryView::Seeking(ref mut q) => { QueryView::Seeking(ref mut q) => {
@ -1415,7 +1409,7 @@ impl ToggleRecord {
gst::GenericFormattedValue::new(format, -1), gst::GenericFormattedValue::new(format, -1),
); );
gst_log!(self.cat, obj: pad, "Returning {:?}", q.get_mut_query()); gst_log!(CAT, obj: pad, "Returning {:?}", q.get_mut_query());
true true
} }
// Position and duration is always the current recording position // Position and duration is always the current recording position
@ -1454,7 +1448,7 @@ impl ToggleRecord {
} }
} }
_ => { _ => {
gst_log!(self.cat, obj: pad, "Forwarding query {:?}", query); gst_log!(CAT, obj: pad, "Forwarding query {:?}", query);
stream.sinkpad.peer_query(query) stream.sinkpad.peer_query(query)
} }
} }
@ -1508,11 +1502,6 @@ impl ObjectSubclass for ToggleRecord {
pads.insert(main_stream.srcpad.clone(), main_stream.clone()); pads.insert(main_stream.srcpad.clone(), main_stream.clone());
Self { Self {
cat: gst::DebugCategory::new(
"togglerecord",
gst::DebugColorFlags::empty(),
Some("Toggle Record Element"),
),
settings: Mutex::new(Settings::default()), settings: Mutex::new(Settings::default()),
state: Mutex::new(State::default()), state: Mutex::new(State::default()),
main_stream, main_stream,
@ -1583,7 +1572,7 @@ impl ObjectImpl for ToggleRecord {
let mut settings = self.settings.lock(); let mut settings = self.settings.lock();
let record = value.get_some().expect("type checked upstream"); let record = value.get_some().expect("type checked upstream");
gst_debug!( gst_debug!(
self.cat, CAT,
obj: element, obj: element,
"Setting record from {:?} to {:?}", "Setting record from {:?} to {:?}",
settings.record, settings.record,
@ -1626,7 +1615,7 @@ impl ElementImpl for ToggleRecord {
element: &gst::Element, element: &gst::Element,
transition: gst::StateChange, transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> { ) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst_trace!(self.cat, obj: element, "Changing state {:?}", transition); gst_trace!(CAT, obj: element, "Changing state {:?}", transition);
match transition { match transition {
gst::StateChange::ReadyToPaused => { gst::StateChange::ReadyToPaused => {

View file

@ -15,6 +15,7 @@ gstreamer-video = { git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs
gstreamer-audio = { git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs" } gstreamer-audio = { git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs" }
byte-slice-cast = "0.3" byte-slice-cast = "0.3"
num-traits = "0.2" num-traits = "0.2"
lazy_static = "1.0"
[lib] [lib]
name = "gstrstutorial" name = "gstrstutorial"

View file

@ -16,11 +16,18 @@ use gst::subclass::prelude::*;
// Struct containing all the element data // Struct containing all the element data
struct Identity { struct Identity {
cat: gst::DebugCategory,
srcpad: gst::Pad, srcpad: gst::Pad,
sinkpad: gst::Pad, sinkpad: gst::Pad,
} }
lazy_static! {
static ref CAT: gst::DebugCategory = gst::DebugCategory::new(
"rsidentity",
gst::DebugColorFlags::empty(),
Some("Identity Element"),
);
}
impl Identity { impl Identity {
// After creating of our two pads set all the functions on them // After creating of our two pads set all the functions on them
// //
@ -82,7 +89,7 @@ impl Identity {
_element: &gst::Element, _element: &gst::Element,
buffer: gst::Buffer, buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> { ) -> Result<gst::FlowSuccess, gst::FlowError> {
gst_log!(self.cat, obj: pad, "Handling buffer {:?}", buffer); gst_log!(CAT, obj: pad, "Handling buffer {:?}", buffer);
self.srcpad.push(buffer) self.srcpad.push(buffer)
} }
@ -94,7 +101,7 @@ impl Identity {
// See the documentation of gst::Event and gst::EventRef to see what can be done with // See the documentation of gst::Event and gst::EventRef to see what can be done with
// events, and especially the gst::EventView type for inspecting events. // events, and especially the gst::EventView type for inspecting events.
fn sink_event(&self, pad: &gst::Pad, _element: &gst::Element, event: gst::Event) -> bool { fn sink_event(&self, pad: &gst::Pad, _element: &gst::Element, event: gst::Event) -> bool {
gst_log!(self.cat, obj: pad, "Handling event {:?}", event); gst_log!(CAT, obj: pad, "Handling event {:?}", event);
self.srcpad.push_event(event) self.srcpad.push_event(event)
} }
@ -113,7 +120,7 @@ impl Identity {
_element: &gst::Element, _element: &gst::Element,
query: &mut gst::QueryRef, query: &mut gst::QueryRef,
) -> bool { ) -> bool {
gst_log!(self.cat, obj: pad, "Handling query {:?}", query); gst_log!(CAT, obj: pad, "Handling query {:?}", query);
self.srcpad.peer_query(query) self.srcpad.peer_query(query)
} }
@ -126,7 +133,7 @@ impl Identity {
// See the documentation of gst::Event and gst::EventRef to see what can be done with // See the documentation of gst::Event and gst::EventRef to see what can be done with
// events, and especially the gst::EventView type for inspecting events. // events, and especially the gst::EventView type for inspecting events.
fn src_event(&self, pad: &gst::Pad, _element: &gst::Element, event: gst::Event) -> bool { fn src_event(&self, pad: &gst::Pad, _element: &gst::Element, event: gst::Event) -> bool {
gst_log!(self.cat, obj: pad, "Handling event {:?}", event); gst_log!(CAT, obj: pad, "Handling event {:?}", event);
self.sinkpad.push_event(event) self.sinkpad.push_event(event)
} }
@ -145,7 +152,7 @@ impl Identity {
_element: &gst::Element, _element: &gst::Element,
query: &mut gst::QueryRef, query: &mut gst::QueryRef,
) -> bool { ) -> bool {
gst_log!(self.cat, obj: pad, "Handling query {:?}", query); gst_log!(CAT, obj: pad, "Handling query {:?}", query);
self.sinkpad.peer_query(query) self.sinkpad.peer_query(query)
} }
} }
@ -179,15 +186,7 @@ impl ObjectSubclass for Identity {
// Return an instance of our struct and also include our debug category here. // Return an instance of our struct and also include our debug category here.
// The debug category will be used later whenever we need to put something // The debug category will be used later whenever we need to put something
// into the debug logs // into the debug logs
Self { Self { srcpad, sinkpad }
cat: gst::DebugCategory::new(
"rsidentity",
gst::DebugColorFlags::empty(),
Some("Identity Element"),
),
srcpad,
sinkpad,
}
} }
// Called exactly once when registering the type. Used for // Called exactly once when registering the type. Used for
@ -263,7 +262,7 @@ impl ElementImpl for Identity {
element: &gst::Element, element: &gst::Element,
transition: gst::StateChange, transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> { ) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst_trace!(self.cat, obj: element, "Changing state {:?}", transition); gst_trace!(CAT, obj: element, "Changing state {:?}", transition);
// Call the parent class' implementation of ::change_state() // Call the parent class' implementation of ::change_state()
self.parent_change_state(element, transition) self.parent_change_state(element, transition)

View file

@ -16,6 +16,8 @@ extern crate gstreamer_video as gst_video;
extern crate byte_slice_cast; extern crate byte_slice_cast;
extern crate num_traits; extern crate num_traits;
#[macro_use]
extern crate lazy_static;
mod identity; mod identity;
mod progressbin; mod progressbin;

View file

@ -16,8 +16,6 @@ use gst::subclass::prelude::*;
// Struct containing all the element data // Struct containing all the element data
struct ProgressBin { struct ProgressBin {
#[allow(dead_code)]
cat: gst::DebugCategory,
progress: gst::Element, progress: gst::Element,
srcpad: gst::GhostPad, srcpad: gst::GhostPad,
sinkpad: gst::GhostPad, sinkpad: gst::GhostPad,
@ -53,15 +51,8 @@ impl ObjectSubclass for ProgressBin {
// Don't let progressreport print to stdout itself // Don't let progressreport print to stdout itself
progress.set_property("silent", &true).unwrap(); progress.set_property("silent", &true).unwrap();
// Return an instance of our struct and also include our debug category here. // Return an instance of our struct
// The debug category will be used later whenever we need to put something
// into the debug logs
Self { Self {
cat: gst::DebugCategory::new(
"rsprogressbin",
gst::DebugColorFlags::empty(),
Some("Progress printing Bin"),
),
progress, progress,
srcpad, srcpad,
sinkpad, sinkpad,

View file

@ -71,11 +71,18 @@ struct State {
// Struct containing all the element data // Struct containing all the element data
struct Rgb2Gray { struct Rgb2Gray {
cat: gst::DebugCategory,
settings: Mutex<Settings>, settings: Mutex<Settings>,
state: Mutex<Option<State>>, state: Mutex<Option<State>>,
} }
lazy_static! {
static ref CAT: gst::DebugCategory = gst::DebugCategory::new(
"rsrgb2gray",
gst::DebugColorFlags::empty(),
Some("Rust RGB-GRAY converter"),
);
}
impl Rgb2Gray { impl Rgb2Gray {
// Converts one pixel of BGRx to a grayscale value, shifting and/or // Converts one pixel of BGRx to a grayscale value, shifting and/or
// inverting it as configured // inverting it as configured
@ -119,11 +126,6 @@ impl ObjectSubclass for Rgb2Gray {
// of our struct here. // of our struct here.
fn new() -> Self { fn new() -> Self {
Self { Self {
cat: gst::DebugCategory::new(
"rsrgb2gray",
gst::DebugColorFlags::empty(),
Some("Rust RGB-GRAY converter"),
),
settings: Mutex::new(Default::default()), settings: Mutex::new(Default::default()),
state: Mutex::new(None), state: Mutex::new(None),
} }
@ -251,7 +253,7 @@ impl ObjectImpl for Rgb2Gray {
let mut settings = self.settings.lock().unwrap(); let mut settings = self.settings.lock().unwrap();
let invert = value.get_some().expect("type checked upstream"); let invert = value.get_some().expect("type checked upstream");
gst_info!( gst_info!(
self.cat, CAT,
obj: element, obj: element,
"Changing invert from {} to {}", "Changing invert from {} to {}",
settings.invert, settings.invert,
@ -263,7 +265,7 @@ impl ObjectImpl for Rgb2Gray {
let mut settings = self.settings.lock().unwrap(); let mut settings = self.settings.lock().unwrap();
let shift = value.get_some().expect("type checked upstream"); let shift = value.get_some().expect("type checked upstream");
gst_info!( gst_info!(
self.cat, CAT,
obj: element, obj: element,
"Changing shift from {} to {}", "Changing shift from {} to {}",
settings.shift, settings.shift,
@ -343,7 +345,7 @@ impl BaseTransformImpl for Rgb2Gray {
}; };
gst_debug!( gst_debug!(
self.cat, CAT,
obj: element, obj: element,
"Transformed caps from {} to {} in direction {:?}", "Transformed caps from {} to {} in direction {:?}",
caps, caps,
@ -389,7 +391,7 @@ impl BaseTransformImpl for Rgb2Gray {
}; };
gst_debug!( gst_debug!(
self.cat, CAT,
obj: element, obj: element,
"Configured for caps {} to {}", "Configured for caps {} to {}",
incaps, incaps,
@ -407,7 +409,7 @@ impl BaseTransformImpl for Rgb2Gray {
// Drop state // Drop state
let _ = self.state.lock().unwrap().take(); let _ = self.state.lock().unwrap().take();
gst_info!(self.cat, obj: element, "Stopped"); gst_info!(CAT, obj: element, "Stopped");
Ok(()) Ok(())
} }

View file

@ -137,12 +137,19 @@ struct ClockWait {
// Struct containing all the element data // Struct containing all the element data
struct SineSrc { struct SineSrc {
cat: gst::DebugCategory,
settings: Mutex<Settings>, settings: Mutex<Settings>,
state: Mutex<State>, state: Mutex<State>,
clock_wait: Mutex<ClockWait>, clock_wait: Mutex<ClockWait>,
} }
lazy_static! {
static ref CAT: gst::DebugCategory = gst::DebugCategory::new(
"rssinesrc",
gst::DebugColorFlags::empty(),
Some("Rust Sine Wave Source"),
);
}
impl SineSrc { impl SineSrc {
fn process<F: Float + FromByteSlice>( fn process<F: Float + FromByteSlice>(
data: &mut [u8], data: &mut [u8],
@ -204,11 +211,6 @@ impl ObjectSubclass for SineSrc {
// of our struct here. // of our struct here.
fn new() -> Self { fn new() -> Self {
Self { Self {
cat: gst::DebugCategory::new(
"rssinesrc",
gst::DebugColorFlags::empty(),
Some("Rust Sine Wave Source"),
),
settings: Mutex::new(Default::default()), settings: Mutex::new(Default::default()),
state: Mutex::new(Default::default()), state: Mutex::new(Default::default()),
clock_wait: Mutex::new(ClockWait { clock_wait: Mutex::new(ClockWait {
@ -306,7 +308,7 @@ impl ObjectImpl for SineSrc {
let mut settings = self.settings.lock().unwrap(); let mut settings = self.settings.lock().unwrap();
let samples_per_buffer = value.get_some().expect("type checked upstream"); let samples_per_buffer = value.get_some().expect("type checked upstream");
gst_info!( gst_info!(
self.cat, CAT,
obj: basesrc, obj: basesrc,
"Changing samples-per-buffer from {} to {}", "Changing samples-per-buffer from {} to {}",
settings.samples_per_buffer, settings.samples_per_buffer,
@ -322,7 +324,7 @@ impl ObjectImpl for SineSrc {
let mut settings = self.settings.lock().unwrap(); let mut settings = self.settings.lock().unwrap();
let freq = value.get_some().expect("type checked upstream"); let freq = value.get_some().expect("type checked upstream");
gst_info!( gst_info!(
self.cat, CAT,
obj: basesrc, obj: basesrc,
"Changing freq from {} to {}", "Changing freq from {} to {}",
settings.freq, settings.freq,
@ -334,7 +336,7 @@ impl ObjectImpl for SineSrc {
let mut settings = self.settings.lock().unwrap(); let mut settings = self.settings.lock().unwrap();
let volume = value.get_some().expect("type checked upstream"); let volume = value.get_some().expect("type checked upstream");
gst_info!( gst_info!(
self.cat, CAT,
obj: basesrc, obj: basesrc,
"Changing volume from {} to {}", "Changing volume from {} to {}",
settings.volume, settings.volume,
@ -346,7 +348,7 @@ impl ObjectImpl for SineSrc {
let mut settings = self.settings.lock().unwrap(); let mut settings = self.settings.lock().unwrap();
let mute = value.get_some().expect("type checked upstream"); let mute = value.get_some().expect("type checked upstream");
gst_info!( gst_info!(
self.cat, CAT,
obj: basesrc, obj: basesrc,
"Changing mute from {} to {}", "Changing mute from {} to {}",
settings.mute, settings.mute,
@ -358,7 +360,7 @@ impl ObjectImpl for SineSrc {
let mut settings = self.settings.lock().unwrap(); let mut settings = self.settings.lock().unwrap();
let is_live = value.get_some().expect("type checked upstream"); let is_live = value.get_some().expect("type checked upstream");
gst_info!( gst_info!(
self.cat, CAT,
obj: basesrc, obj: basesrc,
"Changing is-live from {} to {}", "Changing is-live from {} to {}",
settings.is_live, settings.is_live,
@ -442,10 +444,10 @@ impl BaseSrcImpl for SineSrc {
use std::f64::consts::PI; use std::f64::consts::PI;
let info = gst_audio::AudioInfo::from_caps(caps).ok_or_else(|| { let info = gst_audio::AudioInfo::from_caps(caps).ok_or_else(|| {
gst_loggable_error!(self.cat, "Failed to build `AudioInfo` from caps {}", caps) gst_loggable_error!(CAT, "Failed to build `AudioInfo` from caps {}", caps)
})?; })?;
gst_debug!(self.cat, obj: element, "Configuring for caps {}", caps); gst_debug!(CAT, obj: element, "Configuring for caps {}", caps);
element.set_blocksize(info.bpf() * (*self.settings.lock().unwrap()).samples_per_buffer); element.set_blocksize(info.bpf() * (*self.settings.lock().unwrap()).samples_per_buffer);
@ -493,7 +495,7 @@ impl BaseSrcImpl for SineSrc {
*self.state.lock().unwrap() = Default::default(); *self.state.lock().unwrap() = Default::default();
self.unlock_stop(element)?; self.unlock_stop(element)?;
gst_info!(self.cat, obj: element, "Started"); gst_info!(CAT, obj: element, "Started");
Ok(()) Ok(())
} }
@ -504,7 +506,7 @@ impl BaseSrcImpl for SineSrc {
*self.state.lock().unwrap() = Default::default(); *self.state.lock().unwrap() = Default::default();
self.unlock(element)?; self.unlock(element)?;
gst_info!(self.cat, obj: element, "Stopped"); gst_info!(CAT, obj: element, "Stopped");
Ok(()) Ok(())
} }
@ -531,7 +533,7 @@ impl BaseSrcImpl for SineSrc {
let latency = gst::SECOND let latency = gst::SECOND
.mul_div_floor(settings.samples_per_buffer as u64, info.rate() as u64) .mul_div_floor(settings.samples_per_buffer as u64, info.rate() as u64)
.unwrap(); .unwrap();
gst_debug!(self.cat, obj: element, "Returning latency {}", latency); gst_debug!(CAT, obj: element, "Returning latency {}", latency);
q.set(settings.is_live, latency, gst::CLOCK_TIME_NONE); q.set(settings.is_live, latency, gst::CLOCK_TIME_NONE);
true true
} else { } else {
@ -568,7 +570,7 @@ impl BaseSrcImpl for SineSrc {
// point but at most samples_per_buffer samples per buffer // point but at most samples_per_buffer samples per buffer
let n_samples = if let Some(sample_stop) = state.sample_stop { let n_samples = if let Some(sample_stop) = state.sample_stop {
if sample_stop <= state.sample_offset { if sample_stop <= state.sample_offset {
gst_log!(self.cat, obj: element, "At EOS"); gst_log!(CAT, obj: element, "At EOS");
return Err(gst::FlowError::Eos); return Err(gst::FlowError::Eos);
} }
@ -661,7 +663,7 @@ impl BaseSrcImpl for SineSrc {
// so that we immediately stop waiting on e.g. shutdown. // so that we immediately stop waiting on e.g. shutdown.
let mut clock_wait = self.clock_wait.lock().unwrap(); let mut clock_wait = self.clock_wait.lock().unwrap();
if clock_wait.flushing { if clock_wait.flushing {
gst_debug!(self.cat, obj: element, "Flushing"); gst_debug!(CAT, obj: element, "Flushing");
return Err(gst::FlowError::Flushing); return Err(gst::FlowError::Flushing);
} }
@ -670,31 +672,25 @@ impl BaseSrcImpl for SineSrc {
drop(clock_wait); drop(clock_wait);
gst_log!( gst_log!(
self.cat, CAT,
obj: element, obj: element,
"Waiting until {}, now {}", "Waiting until {}, now {}",
wait_until, wait_until,
clock.get_time() clock.get_time()
); );
let (res, jitter) = id.wait(); let (res, jitter) = id.wait();
gst_log!( gst_log!(CAT, obj: element, "Waited res {:?} jitter {}", res, jitter);
self.cat,
obj: element,
"Waited res {:?} jitter {}",
res,
jitter
);
self.clock_wait.lock().unwrap().clock_id.take(); self.clock_wait.lock().unwrap().clock_id.take();
// If the clock ID was unscheduled, unlock() was called // If the clock ID was unscheduled, unlock() was called
// and we should return Flushing immediately. // and we should return Flushing immediately.
if res == Err(gst::ClockError::Unscheduled) { if res == Err(gst::ClockError::Unscheduled) {
gst_debug!(self.cat, obj: element, "Flushing"); gst_debug!(CAT, obj: element, "Flushing");
return Err(gst::FlowError::Flushing); return Err(gst::FlowError::Flushing);
} }
} }
gst_debug!(self.cat, obj: element, "Produced buffer {:?}", buffer); gst_debug!(CAT, obj: element, "Produced buffer {:?}", buffer);
Ok(buffer) Ok(buffer)
} }
@ -733,7 +729,7 @@ impl BaseSrcImpl for SineSrc {
// and for calculating the timestamps, etc. // and for calculating the timestamps, etc.
if segment.get_rate() < 0.0 { if segment.get_rate() < 0.0 {
gst_error!(self.cat, obj: element, "Reverse playback not supported"); gst_error!(CAT, obj: element, "Reverse playback not supported");
return false; return false;
} }
@ -765,7 +761,7 @@ impl BaseSrcImpl for SineSrc {
(sample_offset as f64).rem(2.0 * PI * (settings.freq as f64) / (rate as f64)); (sample_offset as f64).rem(2.0 * PI * (settings.freq as f64) / (rate as f64));
gst_debug!( gst_debug!(
self.cat, CAT,
obj: element, obj: element,
"Seeked to {}-{:?} (accum: {}) for segment {:?}", "Seeked to {}-{:?} (accum: {}) for segment {:?}",
sample_offset, sample_offset,
@ -787,7 +783,7 @@ impl BaseSrcImpl for SineSrc {
if state.info.is_none() { if state.info.is_none() {
gst_error!( gst_error!(
self.cat, CAT,
obj: element, obj: element,
"Can only seek in Default format if sample rate is known" "Can only seek in Default format if sample rate is known"
); );
@ -801,7 +797,7 @@ impl BaseSrcImpl for SineSrc {
(sample_offset as f64).rem(2.0 * PI * (settings.freq as f64) / (rate as f64)); (sample_offset as f64).rem(2.0 * PI * (settings.freq as f64) / (rate as f64));
gst_debug!( gst_debug!(
self.cat, CAT,
obj: element, obj: element,
"Seeked to {}-{:?} (accum: {}) for segment {:?}", "Seeked to {}-{:?} (accum: {}) for segment {:?}",
sample_offset, sample_offset,
@ -820,7 +816,7 @@ impl BaseSrcImpl for SineSrc {
true true
} else { } else {
gst_error!( gst_error!(
self.cat, CAT,
obj: element, obj: element,
"Can't seek in format {:?}", "Can't seek in format {:?}",
segment.get_format() segment.get_format()
@ -833,7 +829,7 @@ impl BaseSrcImpl for SineSrc {
fn unlock(&self, element: &gst_base::BaseSrc) -> Result<(), gst::ErrorMessage> { fn unlock(&self, element: &gst_base::BaseSrc) -> Result<(), gst::ErrorMessage> {
// This should unblock the create() function ASAP, so we // This should unblock the create() function ASAP, so we
// just unschedule the clock it here, if any. // just unschedule the clock it here, if any.
gst_debug!(self.cat, obj: element, "Unlocking"); gst_debug!(CAT, obj: element, "Unlocking");
let mut clock_wait = self.clock_wait.lock().unwrap(); let mut clock_wait = self.clock_wait.lock().unwrap();
if let Some(clock_id) = clock_wait.clock_id.take() { if let Some(clock_id) = clock_wait.clock_id.take() {
clock_id.unschedule(); clock_id.unschedule();
@ -846,7 +842,7 @@ impl BaseSrcImpl for SineSrc {
fn unlock_stop(&self, element: &gst_base::BaseSrc) -> Result<(), gst::ErrorMessage> { fn unlock_stop(&self, element: &gst_base::BaseSrc) -> Result<(), gst::ErrorMessage> {
// This signals that unlocking is done, so we can reset // This signals that unlocking is done, so we can reset
// all values again. // all values again.
gst_debug!(self.cat, obj: element, "Unlock stop"); gst_debug!(CAT, obj: element, "Unlock stop");
let mut clock_wait = self.clock_wait.lock().unwrap(); let mut clock_wait = self.clock_wait.lock().unwrap();
clock_wait.flushing = false; clock_wait.flushing = false;