mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2024-12-20 09:06:32 +00:00
audio: Update for subclassing API changes
This commit is contained in:
parent
f43436056e
commit
f54f9f977e
14 changed files with 366 additions and 218 deletions
|
@ -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;
|
||||
}
|
||||
}
|
28
audio/audiofx/src/audioecho/mod.rs
Normal file
28
audio/audiofx/src/audioecho/mod.rs
Normal 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(),
|
||||
)
|
||||
}
|
84
audio/audiofx/src/audioecho/ring_buffer.rs
Normal file
84
audio/audiofx/src/audioecho/ring_buffer.rs
Normal 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;
|
||||
}
|
||||
}
|
|
@ -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;
|
39
audio/audiofx/src/audioloudnorm/mod.rs
Normal file
39
audio/audiofx/src/audioloudnorm/mod.rs
Normal 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(),
|
||||
)
|
||||
}
|
|
@ -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(),
|
||||
)
|
||||
}
|
28
audio/audiofx/src/audiornnoise/mod.rs
Normal file
28
audio/audiofx/src/audiornnoise/mod.rs
Normal 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(),
|
||||
)
|
||||
}
|
|
@ -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!(
|
||||
|
|
|
@ -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);
|
27
audio/claxon/src/claxondec/mod.rs
Normal file
27
audio/claxon/src/claxondec/mod.rs
Normal 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(),
|
||||
)
|
||||
}
|
|
@ -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(),
|
||||
)
|
||||
}
|
37
audio/csound/src/filter/mod.rs
Normal file
37
audio/csound/src/filter/mod.rs
Normal 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(),
|
||||
)
|
||||
}
|
|
@ -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] = [
|
||||
[
|
27
audio/lewton/src/lewtondec/mod.rs
Normal file
27
audio/lewton/src/lewtondec/mod.rs
Normal 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(),
|
||||
)
|
||||
}
|
Loading…
Reference in a new issue