audiofx: Use AtomicRefCell for protecting the element state

It's only accessed from the streaming thread and in PAUSED->READY after
the streaming thread was shut down, so it's already guaranteed that only
a single thread can access it at any time.
This commit is contained in:
Sebastian Dröge 2021-03-26 18:35:35 +02:00
parent 65d625a4eb
commit 81f9d334e8
4 changed files with 30 additions and 20 deletions

View file

@ -18,6 +18,7 @@ once_cell = "1.0"
ebur128 = "0.1"
nnnoiseless = { version = "0.3", default-features = false }
smallvec = "1"
atomic_refcell = "0.1"
[lib]
name = "gstrsaudiofx"

View file

@ -30,6 +30,9 @@ use std::{i32, u64};
use byte_slice_cast::*;
use once_cell::sync::Lazy;
use atomic_refcell::AtomicRefCell;
static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
gst::DebugCategory::new(
"rsaudioloudnorm",
@ -206,7 +209,7 @@ pub struct AudioLoudNorm {
srcpad: gst::Pad,
sinkpad: gst::Pad,
settings: Mutex<Settings>,
state: Mutex<Option<State>>,
state: AtomicRefCell<Option<State>>,
}
// Gain analysis parameters
@ -1547,7 +1550,7 @@ impl AudioLoudNorm {
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst_log!(CAT, obj: element, "Handling buffer {:?}", buffer);
let mut state_guard = self.state.lock().unwrap();
let mut state_guard = self.state.borrow_mut();
let state = match *state_guard {
None => {
gst_error!(CAT, obj: element, "Not negotiated yet");
@ -1606,7 +1609,7 @@ impl AudioLoudNorm {
}
};
let mut state = self.state.lock().unwrap();
let mut state = self.state.borrow_mut();
let mut outbuf = None;
if let Some(ref mut state) = &mut *state {
outbuf = match state.drain(&element) {
@ -1628,7 +1631,7 @@ impl AudioLoudNorm {
}
}
EventView::Eos(_) => {
let mut state = self.state.lock().unwrap();
let mut state = self.state.borrow_mut();
let mut outbuf = None;
if let Some(ref mut state) = &mut *state {
outbuf = match state.drain(&element) {
@ -1656,7 +1659,7 @@ impl AudioLoudNorm {
}
EventView::FlushStop(_) => {
// Resetting our whole state
let mut state = self.state.lock().unwrap();
let mut state = self.state.borrow_mut();
if let Some(info) = state.as_ref().map(|s| s.info.clone()) {
let settings = *self.settings.lock().unwrap();
@ -1742,7 +1745,7 @@ impl ObjectSubclass for AudioLoudNorm {
sinkpad,
srcpad,
settings: Mutex::new(Default::default()),
state: Mutex::new(None),
state: AtomicRefCell::new(None),
}
}
}
@ -1908,7 +1911,7 @@ impl ElementImpl for AudioLoudNorm {
match transition {
gst::StateChange::PausedToReady => {
// Drop state
*self.state.lock().unwrap() = None;
*self.state.borrow_mut() = None;
}
_ => (),
}

View file

@ -7,7 +7,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use byte_slice_cast::*;
use glib::subclass::prelude::*;
use gst::prelude::*;
use gst::subclass::prelude::*;
@ -15,10 +14,15 @@ use gst::{gst_debug, gst_error};
use gst_base::subclass::base_transform::BaseTransformImplExt;
use gst_base::subclass::base_transform::GenerateOutputSuccess;
use gst_base::subclass::prelude::*;
use nnnoiseless::DenoiseState;
use std::sync::Mutex;
use byte_slice_cast::*;
use once_cell::sync::Lazy;
use atomic_refcell::AtomicRefCell;
static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
gst::DebugCategory::new(
"audiornnoise",
@ -43,7 +47,7 @@ struct State {
#[derive(Default)]
pub struct AudioRNNoise {
state: Mutex<Option<State>>,
state: AtomicRefCell<Option<State>>,
}
impl State {
@ -114,7 +118,7 @@ impl State {
impl AudioRNNoise {
fn drain(&self, element: &super::AudioRNNoise) -> Result<gst::FlowSuccess, gst::FlowError> {
let mut state_lock = self.state.lock().unwrap();
let mut state_lock = self.state.borrow_mut();
let state = state_lock.as_mut().unwrap();
let available = state.adapter.available();
@ -259,7 +263,7 @@ impl BaseTransformImpl for AudioRNNoise {
outcaps: &gst::Caps,
) -> Result<(), gst::LoggableError> {
// Flush previous state
if self.state.lock().unwrap().is_some() {
if self.state.borrow_mut().is_some() {
self.drain(element).map_err(|e| {
gst::loggable_error!(CAT, "Error flusing previous state data {:?}", e)
})?;
@ -285,7 +289,7 @@ impl BaseTransformImpl for AudioRNNoise {
})
}
let mut state_lock = self.state.lock().unwrap();
let mut state_lock = self.state.borrow_mut();
*state_lock = Some(State {
in_info,
denoisers,
@ -307,7 +311,7 @@ impl BaseTransformImpl for AudioRNNoise {
self.drain(element)?;
}
let mut state_guard = self.state.lock().unwrap();
let mut state_guard = self.state.borrow_mut();
let state = state_guard.as_mut().ok_or_else(|| {
gst::element_error!(
element,
@ -370,7 +374,7 @@ impl BaseTransformImpl for AudioRNNoise {
fn stop(&self, _element: &Self::Type) -> Result<(), gst::ErrorMessage> {
// Drop state
let _ = self.state.lock().unwrap().take();
let _ = self.state.borrow_mut().take();
Ok(())
}

View file

@ -22,6 +22,8 @@ use byte_slice_cast::*;
use smallvec::SmallVec;
use atomic_refcell::AtomicRefCell;
static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
gst::DebugCategory::new(
"ebur128level",
@ -110,7 +112,7 @@ struct State {
#[derive(Default)]
pub struct EbuR128Level {
settings: Mutex<Settings>,
state: Mutex<Option<State>>,
state: AtomicRefCell<Option<State>>,
}
#[glib::object_subclass]
@ -397,7 +399,7 @@ impl BaseTransformImpl for EbuR128Level {
.mul_div_floor(info.rate() as u64, gst::SECOND_VAL)
.unwrap();
*self.state.lock().unwrap() = Some(State {
*self.state.borrow_mut() = Some(State {
info,
ebur128,
num_frames: 0,
@ -410,7 +412,7 @@ impl BaseTransformImpl for EbuR128Level {
fn stop(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> {
// Drop state
let _ = self.state.lock().unwrap().take();
let _ = self.state.borrow_mut().take();
gst_info!(CAT, obj: element, "Stopped");
@ -424,7 +426,7 @@ impl BaseTransformImpl for EbuR128Level {
) -> Result<gst::FlowSuccess, gst::FlowError> {
let settings = *self.settings.lock().unwrap();
let mut state_guard = self.state.lock().unwrap();
let mut state_guard = self.state.borrow_mut();
let mut state = state_guard.as_mut().ok_or_else(|| {
gst::element_error!(element, gst::CoreError::Negotiation, ["Have no state yet"]);
gst::FlowError::NotNegotiated
@ -586,7 +588,7 @@ impl BaseTransformImpl for EbuR128Level {
let _ = element.post_message(msg);
state_guard = self.state.lock().unwrap();
state_guard = self.state.borrow_mut();
state = state_guard.as_mut().ok_or_else(|| {
gst::element_error!(
element,