audio: Update for subclassing API changes

This commit is contained in:
Sebastian Dröge 2020-11-14 18:52:56 +02:00
parent f43436056e
commit f54f9f977e
14 changed files with 366 additions and 218 deletions

View file

@ -13,7 +13,7 @@ use gst::subclass::prelude::*;
use gst_base::subclass::prelude::*;
use std::sync::Mutex;
use std::{cmp, i32, iter, u64};
use std::{cmp, i32, u64};
use byte_slice_cast::*;
@ -28,6 +28,8 @@ lazy_static! {
);
}
use super::ring_buffer::RingBuffer;
const DEFAULT_MAX_DELAY: u64 = gst::SECOND_VAL;
const DEFAULT_DELAY: u64 = 500 * gst::MSECOND_VAL;
const DEFAULT_INTENSITY: f64 = 0.5;
@ -57,7 +59,7 @@ struct State {
buffer: RingBuffer,
}
struct AudioEcho {
pub struct AudioEcho {
settings: Mutex<Settings>,
state: Mutex<Option<State>>,
}
@ -129,6 +131,7 @@ impl AudioEcho {
impl ObjectSubclass for AudioEcho {
const NAME: &'static str = "RsAudioEcho";
type Type = super::AudioEcho;
type ParentType = gst_base::BaseTransform;
type Instance = gst::subclass::ElementInstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
@ -142,7 +145,7 @@ impl ObjectSubclass for AudioEcho {
}
}
fn class_init(klass: &mut subclass::simple::ClassStruct<Self>) {
fn class_init(klass: &mut Self::Class) {
klass.set_metadata(
"Audio echo",
"Filter/Effect/Audio",
@ -194,7 +197,7 @@ impl ObjectSubclass for AudioEcho {
}
impl ObjectImpl for AudioEcho {
fn set_property(&self, _obj: &glib::Object, id: usize, value: &glib::Value) {
fn set_property(&self, _obj: &Self::Type, id: usize, value: &glib::Value) {
let prop = &PROPERTIES[id];
match *prop {
@ -220,7 +223,7 @@ impl ObjectImpl for AudioEcho {
}
}
fn get_property(&self, _obj: &glib::Object, id: usize) -> Result<glib::Value, ()> {
fn get_property(&self, _obj: &Self::Type, id: usize) -> Result<glib::Value, ()> {
let prop = &PROPERTIES[id];
match *prop {
@ -250,7 +253,7 @@ impl ElementImpl for AudioEcho {}
impl BaseTransformImpl for AudioEcho {
fn transform_ip(
&self,
_element: &gst_base::BaseTransform,
_element: &Self::Type,
buf: &mut gst::BufferRef,
) -> Result<gst::FlowSuccess, gst::FlowError> {
let mut settings = *self.settings.lock().unwrap();
@ -278,7 +281,7 @@ impl BaseTransformImpl for AudioEcho {
fn set_caps(
&self,
_element: &gst_base::BaseTransform,
_element: &Self::Type,
incaps: &gst::Caps,
outcaps: &gst::Caps,
) -> Result<(), gst::LoggableError> {
@ -303,94 +306,10 @@ impl BaseTransformImpl for AudioEcho {
Ok(())
}
fn stop(&self, _element: &gst_base::BaseTransform) -> Result<(), gst::ErrorMessage> {
fn stop(&self, _element: &Self::Type) -> Result<(), gst::ErrorMessage> {
// Drop state
let _ = self.state.lock().unwrap().take();
Ok(())
}
}
pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
gst::Element::register(
Some(plugin),
"rsaudioecho",
gst::Rank::None,
AudioEcho::get_type(),
)
}
struct RingBuffer {
buffer: Box<[f64]>,
pos: usize,
}
impl RingBuffer {
fn new(size: usize) -> Self {
let mut buffer = Vec::with_capacity(size as usize);
buffer.extend(iter::repeat(0.0).take(size as usize));
Self {
buffer: buffer.into_boxed_slice(),
pos: 0,
}
}
fn iter(&mut self, delay: usize) -> RingBufferIter {
RingBufferIter::new(self, delay)
}
}
struct RingBufferIter<'a> {
buffer: &'a mut [f64],
buffer_pos: &'a mut usize,
read_pos: usize,
write_pos: usize,
}
impl<'a> RingBufferIter<'a> {
fn new(buffer: &'a mut RingBuffer, delay: usize) -> RingBufferIter<'a> {
let size = buffer.buffer.len();
assert!(size >= delay);
assert_ne!(size, 0);
let read_pos = (size - delay + buffer.pos) % size;
let write_pos = buffer.pos % size;
let buffer_pos = &mut buffer.pos;
let buffer = &mut buffer.buffer;
RingBufferIter {
buffer,
buffer_pos,
read_pos,
write_pos,
}
}
}
impl<'a> Iterator for RingBufferIter<'a> {
type Item = (&'a mut f64, f64);
fn next(&mut self) -> Option<Self::Item> {
let res = unsafe {
let r = *self.buffer.get_unchecked(self.read_pos);
let w = self.buffer.get_unchecked_mut(self.write_pos);
// Cast needed to get from &mut f64 to &'a mut f64
(&mut *(w as *mut f64), r)
};
let size = self.buffer.len();
self.write_pos = (self.write_pos + 1) % size;
self.read_pos = (self.read_pos + 1) % size;
Some(res)
}
}
impl<'a> Drop for RingBufferIter<'a> {
fn drop(&mut self) {
*self.buffer_pos = self.write_pos;
}
}

View file

@ -0,0 +1,28 @@
// Copyright (C) 2017,2018 Sebastian Dröge <sebastian@centricular.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use glib::prelude::*;
mod imp;
mod ring_buffer;
glib_wrapper! {
pub struct AudioEcho(ObjectSubclass<imp::AudioEcho>) @extends gst_base::BaseTransform, gst::Element, gst::Object;
}
unsafe impl Send for AudioEcho {}
unsafe impl Sync for AudioEcho {}
pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
gst::Element::register(
Some(plugin),
"rsaudioecho",
gst::Rank::None,
AudioEcho::static_type(),
)
}

View file

@ -0,0 +1,84 @@
// Copyright (C) 2017,2018 Sebastian Dröge <sebastian@centricular.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::iter;
pub struct RingBuffer {
buffer: Box<[f64]>,
pos: usize,
}
impl RingBuffer {
pub fn new(size: usize) -> Self {
let mut buffer = Vec::with_capacity(size as usize);
buffer.extend(iter::repeat(0.0).take(size as usize));
Self {
buffer: buffer.into_boxed_slice(),
pos: 0,
}
}
pub fn iter(&mut self, delay: usize) -> RingBufferIter {
RingBufferIter::new(self, delay)
}
}
pub struct RingBufferIter<'a> {
buffer: &'a mut [f64],
buffer_pos: &'a mut usize,
read_pos: usize,
write_pos: usize,
}
impl<'a> RingBufferIter<'a> {
fn new(buffer: &'a mut RingBuffer, delay: usize) -> RingBufferIter<'a> {
let size = buffer.buffer.len();
assert!(size >= delay);
assert_ne!(size, 0);
let read_pos = (size - delay + buffer.pos) % size;
let write_pos = buffer.pos % size;
let buffer_pos = &mut buffer.pos;
let buffer = &mut buffer.buffer;
RingBufferIter {
buffer,
buffer_pos,
read_pos,
write_pos,
}
}
}
impl<'a> Iterator for RingBufferIter<'a> {
type Item = (&'a mut f64, f64);
fn next(&mut self) -> Option<Self::Item> {
let res = unsafe {
let r = *self.buffer.get_unchecked(self.read_pos);
let w = self.buffer.get_unchecked_mut(self.write_pos);
// Cast needed to get from &mut f64 to &'a mut f64
(&mut *(w as *mut f64), r)
};
let size = self.buffer.len();
self.write_pos = (self.write_pos + 1) % size;
self.read_pos = (self.read_pos + 1) % size;
Some(res)
}
}
impl<'a> Drop for RingBufferIter<'a> {
fn drop(&mut self) {
*self.buffer_pos = self.write_pos;
}
}

View file

@ -201,7 +201,7 @@ impl State {
}
}
struct AudioLoudNorm {
pub struct AudioLoudNorm {
srcpad: gst::Pad,
sinkpad: gst::Pad,
settings: Mutex<Settings>,
@ -268,7 +268,7 @@ impl State {
// Drains all full frames that are currently in the adapter
fn drain_full_frames(
&mut self,
element: &gst::Element,
element: &super::AudioLoudNorm,
) -> Result<Vec<gst::Buffer>, gst::FlowError> {
let mut outbufs = vec![];
while self.adapter.available() >= self.info.bpf() as usize * self.current_samples_per_frame
@ -308,7 +308,7 @@ impl State {
}
// Drains everything
fn drain(&mut self, element: &gst::Element) -> Result<gst::Buffer, gst::FlowError> {
fn drain(&mut self, element: &super::AudioLoudNorm) -> Result<gst::Buffer, gst::FlowError> {
gst_debug!(CAT, obj: element, "Draining");
let (pts, distance) = self.adapter.prev_pts();
@ -363,7 +363,7 @@ impl State {
fn process_first_frame_is_last(
&mut self,
element: &gst::Element,
element: &super::AudioLoudNorm,
) -> Result<(), gst::FlowError> {
// Calculated loudness in LUFS
let global = self
@ -411,7 +411,7 @@ impl State {
fn process_first_frame(
&mut self,
element: &gst::Element,
element: &super::AudioLoudNorm,
src: &[f64],
pts: gst::ClockTime,
) -> Result<(gst::Buffer, gst::ClockTime), gst::FlowError> {
@ -485,7 +485,7 @@ impl State {
Ok((outbuf, pts))
}
fn process_fill_inner_frame(&mut self, element: &gst::Element, src: &[f64]) {
fn process_fill_inner_frame(&mut self, element: &super::AudioLoudNorm, src: &[f64]) {
// Get gain for this and the next 100ms frame based the delta array
// and smoothened with a gaussian filter.
let gain = self.gaussian_filter(if self.index + 10 < 30 {
@ -557,7 +557,7 @@ impl State {
fn process_update_gain_inner_frame(
&mut self,
element: &gst::Element,
element: &super::AudioLoudNorm,
) -> Result<(), gst::FlowError> {
// Calculate global, shortterm loudness and relative threshold in LUFS.
let global = self
@ -641,7 +641,7 @@ impl State {
fn process_inner_frame(
&mut self,
element: &gst::Element,
element: &super::AudioLoudNorm,
src: &[f64],
pts: gst::ClockTime,
) -> Result<(gst::Buffer, gst::ClockTime), gst::FlowError> {
@ -681,7 +681,7 @@ impl State {
fn process_fill_final_frame(
&mut self,
_element: &gst::Element,
_element: &super::AudioLoudNorm,
idx: usize,
num_samples: usize,
) {
@ -734,7 +734,7 @@ impl State {
fn process_final_frame(
&mut self,
element: &gst::Element,
element: &super::AudioLoudNorm,
src: &[f64],
pts: gst::ClockTime,
) -> Result<(gst::Buffer, gst::ClockTime), gst::FlowError> {
@ -818,7 +818,7 @@ impl State {
fn process_linear_frame(
&mut self,
element: &gst::Element,
element: &super::AudioLoudNorm,
src: &[f64],
pts: gst::ClockTime,
) -> Result<(gst::Buffer, gst::ClockTime), gst::FlowError> {
@ -855,7 +855,7 @@ impl State {
fn process(
&mut self,
element: &gst::Element,
element: &super::AudioLoudNorm,
src: &[f64],
pts: gst::ClockTime,
) -> Result<(gst::Buffer, gst::ClockTime), gst::FlowError> {
@ -882,7 +882,7 @@ impl State {
fn true_peak_limiter_out(
&mut self,
element: &gst::Element,
element: &super::AudioLoudNorm,
mut smp_cnt: usize,
nb_samples: usize,
) -> usize {
@ -923,7 +923,7 @@ impl State {
fn true_peak_limiter_attack(
&mut self,
element: &gst::Element,
element: &super::AudioLoudNorm,
mut smp_cnt: usize,
nb_samples: usize,
) -> usize {
@ -1136,7 +1136,7 @@ impl State {
fn true_peak_limiter_sustain(
&mut self,
element: &gst::Element,
element: &super::AudioLoudNorm,
mut smp_cnt: usize,
nb_samples: usize,
) -> usize {
@ -1252,7 +1252,7 @@ impl State {
fn true_peak_limiter_release(
&mut self,
element: &gst::Element,
element: &super::AudioLoudNorm,
mut smp_cnt: usize,
nb_samples: usize,
) -> usize {
@ -1371,7 +1371,7 @@ impl State {
smp_cnt
}
fn true_peak_limiter_first_frame(&mut self, element: &gst::Element) {
fn true_peak_limiter_first_frame(&mut self, element: &super::AudioLoudNorm) {
let channels = self.info.channels() as usize;
assert_eq!(self.limiter_buf_index, 0);
@ -1412,7 +1412,7 @@ impl State {
}
}
fn true_peak_limiter(&mut self, element: &gst::Element, dst: &mut [f64]) {
fn true_peak_limiter(&mut self, element: &super::AudioLoudNorm, dst: &mut [f64]) {
let channels = self.info.channels() as usize;
let nb_samples = dst.len() / channels;
@ -1588,7 +1588,7 @@ impl AudioLoudNorm {
fn sink_chain(
&self,
_pad: &gst::Pad,
element: &gst::Element,
element: &super::AudioLoudNorm,
buffer: gst::Buffer,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst_log!(CAT, obj: element, "Handling buffer {:?}", buffer);
@ -1629,7 +1629,12 @@ impl AudioLoudNorm {
Ok(gst::FlowSuccess::Ok)
}
fn sink_event(&self, pad: &gst::Pad, element: &gst::Element, event: gst::Event) -> bool {
fn sink_event(
&self,
pad: &gst::Pad,
element: &super::AudioLoudNorm,
event: gst::Event,
) -> bool {
use gst::EventView;
gst_log!(CAT, obj: pad, "Handling event {:?}", event);
@ -1712,7 +1717,12 @@ impl AudioLoudNorm {
pad.event_default(Some(element), event)
}
fn src_query(&self, pad: &gst::Pad, element: &gst::Element, query: &mut gst::QueryRef) -> bool {
fn src_query(
&self,
pad: &gst::Pad,
element: &super::AudioLoudNorm,
query: &mut gst::QueryRef,
) -> bool {
use gst::QueryView;
gst_log!(CAT, obj: pad, "Handling query {:?}", query);
@ -1738,13 +1748,14 @@ impl AudioLoudNorm {
impl ObjectSubclass for AudioLoudNorm {
const NAME: &'static str = "RsAudioLoudNorm";
type Type = super::AudioLoudNorm;
type ParentType = gst::Element;
type Instance = gst::subclass::ElementInstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
glib_object_subclass!();
fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self {
fn with_class(klass: &Self::Class) -> Self {
let templ = klass.get_pad_template("sink").unwrap();
let sinkpad = gst::Pad::builder_with_template(&templ, Some("sink"))
.chain_function(|pad, parent, buffer| {
@ -1784,7 +1795,7 @@ impl ObjectSubclass for AudioLoudNorm {
}
}
fn class_init(klass: &mut subclass::simple::ClassStruct<Self>) {
fn class_init(klass: &mut Self::Class) {
klass.set_metadata(
"Audio loudness normalizer",
"Filter/Effect/Audio",
@ -1824,15 +1835,14 @@ impl ObjectSubclass for AudioLoudNorm {
}
impl ObjectImpl for AudioLoudNorm {
fn constructed(&self, obj: &glib::Object) {
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
let element = obj.downcast_ref::<gst::Element>().unwrap();
element.add_pad(&self.sinkpad).unwrap();
element.add_pad(&self.srcpad).unwrap();
obj.add_pad(&self.sinkpad).unwrap();
obj.add_pad(&self.srcpad).unwrap();
}
fn set_property(&self, _obj: &glib::Object, id: usize, value: &glib::Value) {
fn set_property(&self, _obj: &Self::Type, id: usize, value: &glib::Value) {
let prop = &PROPERTIES[id];
match *prop {
@ -1856,7 +1866,7 @@ impl ObjectImpl for AudioLoudNorm {
}
}
fn get_property(&self, _obj: &glib::Object, id: usize) -> Result<glib::Value, ()> {
fn get_property(&self, _obj: &Self::Type, id: usize) -> Result<glib::Value, ()> {
let prop = &PROPERTIES[id];
match *prop {
@ -1884,7 +1894,7 @@ impl ObjectImpl for AudioLoudNorm {
impl ElementImpl for AudioLoudNorm {
fn change_state(
&self,
element: &gst::Element,
element: &Self::Type,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
let res = self.parent_change_state(element, transition);
@ -1901,15 +1911,6 @@ impl ElementImpl for AudioLoudNorm {
}
}
pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
gst::Element::register(
Some(plugin),
"rsaudioloudnorm",
gst::Rank::None,
AudioLoudNorm::get_type(),
)
}
fn init_gaussian_filter() -> [f64; 21] {
let mut weights = [0.0f64; 21];
let mut total_weight = 0.0f64;

View file

@ -0,0 +1,39 @@
// Copyright (C) 2019-2020 Sebastian Dröge <sebastian@centricular.com>
//
// Audio processing part of this file ported from ffmpeg/libavfilter/af_loudnorm.c
//
// Copyright (c) 2016 Kyle Swanson <k@ylo.ph>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// FFmpeg is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with FFmpeg; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
use glib::prelude::*;
mod imp;
glib_wrapper! {
pub struct AudioLoudNorm(ObjectSubclass<imp::AudioLoudNorm>) @extends gst::Element, gst::Object;
}
unsafe impl Send for AudioLoudNorm {}
unsafe impl Sync for AudioLoudNorm {}
pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
gst::Element::register(
Some(plugin),
"rsaudioloudnorm",
gst::Rank::None,
AudioLoudNorm::static_type(),
)
}

View file

@ -40,7 +40,7 @@ struct State {
adapter: gst_base::UniqueAdapter,
}
struct AudioRNNoise {
pub struct AudioRNNoise {
state: Mutex<Option<State>>,
}
@ -111,7 +111,7 @@ impl State {
}
impl AudioRNNoise {
fn drain(&self, element: &gst_base::BaseTransform) -> Result<gst::FlowSuccess, gst::FlowError> {
fn drain(&self, element: &super::AudioRNNoise) -> Result<gst::FlowSuccess, gst::FlowError> {
let mut state_lock = self.state.lock().unwrap();
let state = state_lock.as_mut().unwrap();
@ -154,7 +154,7 @@ impl AudioRNNoise {
fn generate_output(
&self,
_element: &gst_base::BaseTransform,
_element: &super::AudioRNNoise,
state: &mut State,
) -> Result<GenerateOutputSuccess, gst::FlowError> {
let available = state.adapter.available();
@ -189,6 +189,7 @@ impl AudioRNNoise {
impl ObjectSubclass for AudioRNNoise {
const NAME: &'static str = "AudioRNNoise";
type Type = super::AudioRNNoise;
type ParentType = gst_base::BaseTransform;
type Instance = gst::subclass::ElementInstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
@ -201,7 +202,7 @@ impl ObjectSubclass for AudioRNNoise {
}
}
fn class_init(klass: &mut subclass::simple::ClassStruct<Self>) {
fn class_init(klass: &mut Self::Class) {
klass.set_metadata(
"Audio denoise",
"Filter/Effect/Audio",
@ -250,7 +251,7 @@ impl ElementImpl for AudioRNNoise {}
impl BaseTransformImpl for AudioRNNoise {
fn set_caps(
&self,
element: &gst_base::BaseTransform,
element: &Self::Type,
incaps: &gst::Caps,
outcaps: &gst::Caps,
) -> Result<(), gst::LoggableError> {
@ -293,7 +294,7 @@ impl BaseTransformImpl for AudioRNNoise {
fn generate_output(
&self,
element: &gst_base::BaseTransform,
element: &Self::Type,
) -> Result<GenerateOutputSuccess, gst::FlowError> {
// Check if there are enough data in the queued buffer and adapter,
// if it is not the case, just notify the parent class to not generate
@ -321,7 +322,7 @@ impl BaseTransformImpl for AudioRNNoise {
Ok(GenerateOutputSuccess::NoOutput)
}
fn sink_event(&self, element: &gst_base::BaseTransform, event: gst::Event) -> bool {
fn sink_event(&self, element: &Self::Type, event: gst::Event) -> bool {
use gst::EventView;
if let EventView::Eos(_) = event.view() {
@ -335,7 +336,7 @@ impl BaseTransformImpl for AudioRNNoise {
fn query(
&self,
element: &gst_base::BaseTransform,
element: &Self::Type,
direction: gst::PadDirection,
query: &mut gst::QueryRef,
) -> bool {
@ -364,19 +365,10 @@ impl BaseTransformImpl for AudioRNNoise {
BaseTransformImplExt::parent_query(self, element, direction, query)
}
fn stop(&self, _element: &gst_base::BaseTransform) -> Result<(), gst::ErrorMessage> {
fn stop(&self, _element: &Self::Type) -> Result<(), gst::ErrorMessage> {
// Drop state
let _ = self.state.lock().unwrap().take();
Ok(())
}
}
pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
gst::Element::register(
Some(plugin),
"audiornnoise",
gst::Rank::None,
AudioRNNoise::get_type(),
)
}

View file

@ -0,0 +1,28 @@
// Copyright (C) 2020 Philippe Normand <philn@igalia.com>
// Copyright (C) 2020 Natanael Mojica <neithanmo@gmail.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use glib::prelude::*;
mod imp;
glib_wrapper! {
pub struct AudioRNNoise(ObjectSubclass<imp::AudioRNNoise>) @extends gst_base::BaseTransform, gst::Element, gst::Object;
}
unsafe impl Send for AudioRNNoise {}
unsafe impl Sync for AudioRNNoise {}
pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
gst::Element::register(
Some(plugin),
"audiornnoise",
gst::Rank::None,
AudioRNNoise::static_type(),
)
}

View file

@ -24,8 +24,9 @@ mod audiornnoise;
fn plugin_init(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
audioecho::register(plugin)?;
audioloudnorm::register(plugin)?;
audiornnoise::register(plugin)?;
audioloudnorm::register(plugin)
Ok(())
}
gst_plugin_define!(

View file

@ -23,13 +23,14 @@ struct State {
audio_info: Option<gst_audio::AudioInfo>,
}
struct ClaxonDec {
pub struct ClaxonDec {
cat: gst::DebugCategory,
state: AtomicRefCell<Option<State>>,
}
impl ObjectSubclass for ClaxonDec {
const NAME: &'static str = "ClaxonDec";
type Type = super::ClaxonDec;
type ParentType = gst_audio::AudioDecoder;
type Instance = gst::subclass::ElementInstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
@ -47,7 +48,7 @@ impl ObjectSubclass for ClaxonDec {
}
}
fn class_init(klass: &mut subclass::simple::ClassStruct<Self>) {
fn class_init(klass: &mut Self::Class) {
klass.set_metadata(
"Claxon FLAC decoder",
"Decoder/Audio",
@ -98,13 +99,13 @@ impl ObjectImpl for ClaxonDec {}
impl ElementImpl for ClaxonDec {}
impl AudioDecoderImpl for ClaxonDec {
fn stop(&self, _element: &gst_audio::AudioDecoder) -> Result<(), gst::ErrorMessage> {
fn stop(&self, _element: &Self::Type) -> Result<(), gst::ErrorMessage> {
*self.state.borrow_mut() = None;
Ok(())
}
fn start(&self, _element: &gst_audio::AudioDecoder) -> Result<(), gst::ErrorMessage> {
fn start(&self, _element: &Self::Type) -> Result<(), gst::ErrorMessage> {
*self.state.borrow_mut() = Some(State {
streaminfo: None,
audio_info: None,
@ -113,11 +114,7 @@ impl AudioDecoderImpl for ClaxonDec {
Ok(())
}
fn set_format(
&self,
element: &gst_audio::AudioDecoder,
caps: &gst::Caps,
) -> Result<(), gst::LoggableError> {
fn set_format(&self, element: &Self::Type, caps: &gst::Caps) -> Result<(), gst::LoggableError> {
gst_debug!(self.cat, obj: element, "Setting format {:?}", caps);
let mut streaminfo: Option<claxon::metadata::StreamInfo> = None;
@ -174,7 +171,7 @@ impl AudioDecoderImpl for ClaxonDec {
#[allow(clippy::verbose_bit_mask)]
fn handle_frame(
&self,
element: &gst_audio::AudioDecoder,
element: &Self::Type,
inbuf: Option<&gst::Buffer>,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst_debug!(self.cat, obj: element, "Handling buffer {:?}", inbuf);
@ -217,7 +214,7 @@ impl AudioDecoderImpl for ClaxonDec {
impl ClaxonDec {
fn handle_streaminfo_header(
&self,
element: &gst_audio::AudioDecoder,
element: &super::ClaxonDec,
state: &mut State,
indata: &[u8],
) -> Result<gst::FlowSuccess, gst::FlowError> {
@ -249,7 +246,7 @@ impl ClaxonDec {
fn handle_data(
&self,
element: &gst_audio::AudioDecoder,
element: &super::ClaxonDec,
state: &mut State,
indata: &[u8],
) -> Result<gst::FlowSuccess, gst::FlowError> {
@ -372,15 +369,6 @@ impl AudioDepth {
}
}
pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
gst::Element::register(
Some(plugin),
"claxondec",
gst::Rank::Marginal,
ClaxonDec::get_type(),
)
}
fn get_claxon_streaminfo(indata: &[u8]) -> Result<claxon::metadata::StreamInfo, &'static str> {
let mut cursor = Cursor::new(indata);
let mut metadata_iter = claxon::metadata::MetadataBlockReader::new(&mut cursor);

View file

@ -0,0 +1,27 @@
// Copyright (C) 2019 Ruben Gonzalez <rgonzalez@fluendo.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use glib::prelude::*;
mod imp;
glib_wrapper! {
pub struct ClaxonDec(ObjectSubclass<imp::ClaxonDec>) @extends gst_audio::AudioDecoder, gst::Element, gst::Object;
}
unsafe impl Send for ClaxonDec {}
unsafe impl Sync for ClaxonDec {}
pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
gst::Element::register(
Some(plugin),
"claxondec",
gst::Rank::Marginal,
ClaxonDec::static_type(),
)
}

View file

@ -75,7 +75,7 @@ struct State {
ksmps: u32,
}
struct CsoundFilter {
pub struct CsoundFilter {
settings: Mutex<Settings>,
state: Mutex<Option<State>>,
csound: Mutex<Csound>,
@ -222,7 +222,7 @@ impl CsoundFilter {
}
}
fn drain(&self, element: &gst_base::BaseTransform) -> Result<gst::FlowSuccess, gst::FlowError> {
fn drain(&self, element: &super::CsoundFilter) -> Result<gst::FlowSuccess, gst::FlowError> {
let csound = self.csound.lock().unwrap();
let mut state_lock = self.state.lock().unwrap();
let state = state_lock.as_mut().unwrap();
@ -293,7 +293,7 @@ impl CsoundFilter {
fn generate_output(
&self,
element: &gst_base::BaseTransform,
element: &super::CsoundFilter,
state: &mut State,
) -> Result<GenerateOutputSuccess, gst::FlowError> {
let output_size = state.max_output_size(state.adapter.available());
@ -361,6 +361,7 @@ impl CsoundFilter {
impl ObjectSubclass for CsoundFilter {
const NAME: &'static str = "CsoundFilter";
type Type = super::CsoundFilter;
type ParentType = gst_base::BaseTransform;
type Instance = gst::subclass::ElementInstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
@ -385,7 +386,7 @@ impl ObjectSubclass for CsoundFilter {
}
}
fn class_init(klass: &mut subclass::simple::ClassStruct<Self>) {
fn class_init(klass: &mut Self::Class) {
klass.set_metadata(
"Audio filter",
"Filter/Effect/Audio",
@ -431,7 +432,7 @@ impl ObjectSubclass for CsoundFilter {
}
impl ObjectImpl for CsoundFilter {
fn set_property(&self, _obj: &glib::Object, id: usize, value: &glib::Value) {
fn set_property(&self, _obj: &Self::Type, id: usize, value: &glib::Value) {
let prop = &PROPERTIES[id];
match *prop {
subclass::Property("loop", ..) => {
@ -464,7 +465,7 @@ impl ObjectImpl for CsoundFilter {
}
}
fn get_property(&self, _obj: &glib::Object, id: usize) -> Result<glib::Value, ()> {
fn get_property(&self, _obj: &Self::Type, id: usize) -> Result<glib::Value, ()> {
let prop = &PROPERTIES[id];
match *prop {
@ -492,10 +493,7 @@ impl ObjectImpl for CsoundFilter {
impl ElementImpl for CsoundFilter {}
impl BaseTransformImpl for CsoundFilter {
fn start(
&self,
_element: &gst_base::BaseTransform,
) -> std::result::Result<(), gst::ErrorMessage> {
fn start(&self, _element: &Self::Type) -> std::result::Result<(), gst::ErrorMessage> {
self.compile_score()?;
let csound = self.csound.lock().unwrap();
@ -509,7 +507,7 @@ impl BaseTransformImpl for CsoundFilter {
Ok(())
}
fn stop(&self, element: &gst_base::BaseTransform) -> Result<(), gst::ErrorMessage> {
fn stop(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> {
let csound = self.csound.lock().unwrap();
csound.stop();
csound.reset();
@ -520,7 +518,7 @@ impl BaseTransformImpl for CsoundFilter {
Ok(())
}
fn sink_event(&self, element: &gst_base::BaseTransform, event: gst::Event) -> bool {
fn sink_event(&self, element: &Self::Type, event: gst::Event) -> bool {
use gst::EventView;
if let EventView::Eos(_) = event.view() {
@ -534,7 +532,7 @@ impl BaseTransformImpl for CsoundFilter {
fn transform_caps(
&self,
element: &gst_base::BaseTransform,
element: &Self::Type,
direction: gst::PadDirection,
caps: &gst::Caps,
filter: Option<&gst::Caps>,
@ -586,7 +584,7 @@ impl BaseTransformImpl for CsoundFilter {
fn set_caps(
&self,
element: &gst_base::BaseTransform,
element: &Self::Type,
incaps: &gst::Caps,
outcaps: &gst::Caps,
) -> Result<(), gst::LoggableError> {
@ -646,7 +644,7 @@ impl BaseTransformImpl for CsoundFilter {
fn generate_output(
&self,
element: &gst_base::BaseTransform,
element: &Self::Type,
) -> Result<GenerateOutputSuccess, gst::FlowError> {
// Check if there are enough data in the queued buffer and adapter,
// if it is not the case, just notify the parent class to not generate
@ -675,12 +673,3 @@ impl BaseTransformImpl for CsoundFilter {
Ok(GenerateOutputSuccess::NoOutput)
}
}
pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
gst::Element::register(
Some(plugin),
"csoundfilter",
gst::Rank::None,
CsoundFilter::get_type(),
)
}

View file

@ -0,0 +1,37 @@
// Copyright (C) 2020 Natanael Mojica <neithanmo@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the
// Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
// Boston, MA 02110-1335, USA.
use glib::glib_wrapper;
use glib::prelude::*;
mod imp;
glib_wrapper! {
pub struct CsoundFilter(ObjectSubclass<imp::CsoundFilter>) @extends gst_base::BaseTransform, gst::Element, gst::Object;
}
unsafe impl Send for CsoundFilter {}
unsafe impl Sync for CsoundFilter {}
pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
gst::Element::register(
Some(plugin),
"csoundfilter",
gst::Rank::None,
CsoundFilter::static_type(),
)
}

View file

@ -28,7 +28,7 @@ struct State {
reorder_map: Option<[usize; 8]>,
}
struct LewtonDec {
pub struct LewtonDec {
state: AtomicRefCell<Option<State>>,
}
@ -42,6 +42,7 @@ lazy_static! {
impl ObjectSubclass for LewtonDec {
const NAME: &'static str = "LewtonDec";
type Type = super::LewtonDec;
type ParentType = gst_audio::AudioDecoder;
type Instance = gst::subclass::ElementInstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
@ -54,7 +55,7 @@ impl ObjectSubclass for LewtonDec {
}
}
fn class_init(klass: &mut subclass::simple::ClassStruct<Self>) {
fn class_init(klass: &mut Self::Class) {
klass.set_metadata(
"lewton Vorbis decoder",
"Decoder/Audio",
@ -97,13 +98,13 @@ impl ObjectImpl for LewtonDec {}
impl ElementImpl for LewtonDec {}
impl AudioDecoderImpl for LewtonDec {
fn stop(&self, _element: &gst_audio::AudioDecoder) -> Result<(), gst::ErrorMessage> {
fn stop(&self, _element: &Self::Type) -> Result<(), gst::ErrorMessage> {
*self.state.borrow_mut() = None;
Ok(())
}
fn start(&self, _element: &gst_audio::AudioDecoder) -> Result<(), gst::ErrorMessage> {
fn start(&self, _element: &Self::Type) -> Result<(), gst::ErrorMessage> {
*self.state.borrow_mut() = Some(State {
header_bufs: (None, None, None),
headerset: None,
@ -115,11 +116,7 @@ impl AudioDecoderImpl for LewtonDec {
Ok(())
}
fn set_format(
&self,
element: &gst_audio::AudioDecoder,
caps: &gst::Caps,
) -> Result<(), gst::LoggableError> {
fn set_format(&self, element: &Self::Type, caps: &gst::Caps) -> Result<(), gst::LoggableError> {
gst_debug!(CAT, obj: element, "Setting format {:?}", caps);
// When the caps are changing we require new headers
@ -160,7 +157,7 @@ impl AudioDecoderImpl for LewtonDec {
Ok(())
}
fn flush(&self, element: &gst_audio::AudioDecoder, _hard: bool) {
fn flush(&self, element: &Self::Type, _hard: bool) {
gst_debug!(CAT, obj: element, "Flushing");
let mut state_guard = self.state.borrow_mut();
@ -171,7 +168,7 @@ impl AudioDecoderImpl for LewtonDec {
fn handle_frame(
&self,
element: &gst_audio::AudioDecoder,
element: &Self::Type,
inbuf: Option<&gst::Buffer>,
) -> Result<gst::FlowSuccess, gst::FlowError> {
gst_debug!(CAT, obj: element, "Handling buffer {:?}", inbuf);
@ -218,7 +215,7 @@ impl AudioDecoderImpl for LewtonDec {
impl LewtonDec {
fn handle_header(
&self,
element: &gst_audio::AudioDecoder,
element: &super::LewtonDec,
state: &mut State,
inbuf: &gst::Buffer,
indata: &[u8],
@ -254,7 +251,7 @@ impl LewtonDec {
fn initialize(
&self,
element: &gst_audio::AudioDecoder,
element: &super::LewtonDec,
state: &mut State,
) -> Result<(), gst::FlowError> {
let (ident_buf, comment_buf, setup_buf) = match state.header_bufs {
@ -369,7 +366,7 @@ impl LewtonDec {
fn handle_data(
&self,
element: &gst_audio::AudioDecoder,
element: &super::LewtonDec,
state: &mut State,
indata: &[u8],
) -> Result<gst::FlowSuccess, gst::FlowError> {
@ -473,15 +470,6 @@ impl LewtonDec {
}
}
pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
gst::Element::register(
Some(plugin),
"lewtondec",
gst::Rank::Marginal,
LewtonDec::get_type(),
)
}
// http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-800004.3.9
const VORBIS_CHANNEL_POSITIONS: [[gst_audio::AudioChannelPosition; 8]; 8] = [
[

View file

@ -0,0 +1,27 @@
// Copyright (C) 2019 Sebastian Dröge <sebastian@centricular.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use glib::prelude::*;
mod imp;
glib_wrapper! {
pub struct LewtonDec(ObjectSubclass<imp::LewtonDec>) @extends gst_audio::AudioDecoder, gst::Element, gst::Object;
}
unsafe impl Send for LewtonDec {}
unsafe impl Sync for LewtonDec {}
pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
gst::Element::register(
Some(plugin),
"lewtondec",
gst::Rank::Marginal,
LewtonDec::static_type(),
)
}