mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2024-12-29 21:40:31 +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 gst_base::subclass::prelude::*;
|
||||||
|
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use std::{cmp, i32, iter, u64};
|
use std::{cmp, i32, u64};
|
||||||
|
|
||||||
use byte_slice_cast::*;
|
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_MAX_DELAY: u64 = gst::SECOND_VAL;
|
||||||
const DEFAULT_DELAY: u64 = 500 * gst::MSECOND_VAL;
|
const DEFAULT_DELAY: u64 = 500 * gst::MSECOND_VAL;
|
||||||
const DEFAULT_INTENSITY: f64 = 0.5;
|
const DEFAULT_INTENSITY: f64 = 0.5;
|
||||||
|
@ -57,7 +59,7 @@ struct State {
|
||||||
buffer: RingBuffer,
|
buffer: RingBuffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AudioEcho {
|
pub struct AudioEcho {
|
||||||
settings: Mutex<Settings>,
|
settings: Mutex<Settings>,
|
||||||
state: Mutex<Option<State>>,
|
state: Mutex<Option<State>>,
|
||||||
}
|
}
|
||||||
|
@ -129,6 +131,7 @@ impl AudioEcho {
|
||||||
|
|
||||||
impl ObjectSubclass for AudioEcho {
|
impl ObjectSubclass for AudioEcho {
|
||||||
const NAME: &'static str = "RsAudioEcho";
|
const NAME: &'static str = "RsAudioEcho";
|
||||||
|
type Type = super::AudioEcho;
|
||||||
type ParentType = gst_base::BaseTransform;
|
type ParentType = gst_base::BaseTransform;
|
||||||
type Instance = gst::subclass::ElementInstanceStruct<Self>;
|
type Instance = gst::subclass::ElementInstanceStruct<Self>;
|
||||||
type Class = subclass::simple::ClassStruct<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(
|
klass.set_metadata(
|
||||||
"Audio echo",
|
"Audio echo",
|
||||||
"Filter/Effect/Audio",
|
"Filter/Effect/Audio",
|
||||||
|
@ -194,7 +197,7 @@ impl ObjectSubclass for AudioEcho {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ObjectImpl 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];
|
let prop = &PROPERTIES[id];
|
||||||
|
|
||||||
match *prop {
|
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];
|
let prop = &PROPERTIES[id];
|
||||||
|
|
||||||
match *prop {
|
match *prop {
|
||||||
|
@ -250,7 +253,7 @@ impl ElementImpl for AudioEcho {}
|
||||||
impl BaseTransformImpl for AudioEcho {
|
impl BaseTransformImpl for AudioEcho {
|
||||||
fn transform_ip(
|
fn transform_ip(
|
||||||
&self,
|
&self,
|
||||||
_element: &gst_base::BaseTransform,
|
_element: &Self::Type,
|
||||||
buf: &mut gst::BufferRef,
|
buf: &mut gst::BufferRef,
|
||||||
) -> Result<gst::FlowSuccess, gst::FlowError> {
|
) -> Result<gst::FlowSuccess, gst::FlowError> {
|
||||||
let mut settings = *self.settings.lock().unwrap();
|
let mut settings = *self.settings.lock().unwrap();
|
||||||
|
@ -278,7 +281,7 @@ impl BaseTransformImpl for AudioEcho {
|
||||||
|
|
||||||
fn set_caps(
|
fn set_caps(
|
||||||
&self,
|
&self,
|
||||||
_element: &gst_base::BaseTransform,
|
_element: &Self::Type,
|
||||||
incaps: &gst::Caps,
|
incaps: &gst::Caps,
|
||||||
outcaps: &gst::Caps,
|
outcaps: &gst::Caps,
|
||||||
) -> Result<(), gst::LoggableError> {
|
) -> Result<(), gst::LoggableError> {
|
||||||
|
@ -303,94 +306,10 @@ impl BaseTransformImpl for AudioEcho {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stop(&self, _element: &gst_base::BaseTransform) -> Result<(), gst::ErrorMessage> {
|
fn stop(&self, _element: &Self::Type) -> Result<(), gst::ErrorMessage> {
|
||||||
// Drop state
|
// Drop state
|
||||||
let _ = self.state.lock().unwrap().take();
|
let _ = self.state.lock().unwrap().take();
|
||||||
|
|
||||||
Ok(())
|
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,
|
srcpad: gst::Pad,
|
||||||
sinkpad: gst::Pad,
|
sinkpad: gst::Pad,
|
||||||
settings: Mutex<Settings>,
|
settings: Mutex<Settings>,
|
||||||
|
@ -268,7 +268,7 @@ impl State {
|
||||||
// Drains all full frames that are currently in the adapter
|
// Drains all full frames that are currently in the adapter
|
||||||
fn drain_full_frames(
|
fn drain_full_frames(
|
||||||
&mut self,
|
&mut self,
|
||||||
element: &gst::Element,
|
element: &super::AudioLoudNorm,
|
||||||
) -> Result<Vec<gst::Buffer>, gst::FlowError> {
|
) -> Result<Vec<gst::Buffer>, gst::FlowError> {
|
||||||
let mut outbufs = vec![];
|
let mut outbufs = vec![];
|
||||||
while self.adapter.available() >= self.info.bpf() as usize * self.current_samples_per_frame
|
while self.adapter.available() >= self.info.bpf() as usize * self.current_samples_per_frame
|
||||||
|
@ -308,7 +308,7 @@ impl State {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drains everything
|
// 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");
|
gst_debug!(CAT, obj: element, "Draining");
|
||||||
|
|
||||||
let (pts, distance) = self.adapter.prev_pts();
|
let (pts, distance) = self.adapter.prev_pts();
|
||||||
|
@ -363,7 +363,7 @@ impl State {
|
||||||
|
|
||||||
fn process_first_frame_is_last(
|
fn process_first_frame_is_last(
|
||||||
&mut self,
|
&mut self,
|
||||||
element: &gst::Element,
|
element: &super::AudioLoudNorm,
|
||||||
) -> Result<(), gst::FlowError> {
|
) -> Result<(), gst::FlowError> {
|
||||||
// Calculated loudness in LUFS
|
// Calculated loudness in LUFS
|
||||||
let global = self
|
let global = self
|
||||||
|
@ -411,7 +411,7 @@ impl State {
|
||||||
|
|
||||||
fn process_first_frame(
|
fn process_first_frame(
|
||||||
&mut self,
|
&mut self,
|
||||||
element: &gst::Element,
|
element: &super::AudioLoudNorm,
|
||||||
src: &[f64],
|
src: &[f64],
|
||||||
pts: gst::ClockTime,
|
pts: gst::ClockTime,
|
||||||
) -> Result<(gst::Buffer, gst::ClockTime), gst::FlowError> {
|
) -> Result<(gst::Buffer, gst::ClockTime), gst::FlowError> {
|
||||||
|
@ -485,7 +485,7 @@ impl State {
|
||||||
Ok((outbuf, pts))
|
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
|
// Get gain for this and the next 100ms frame based the delta array
|
||||||
// and smoothened with a gaussian filter.
|
// and smoothened with a gaussian filter.
|
||||||
let gain = self.gaussian_filter(if self.index + 10 < 30 {
|
let gain = self.gaussian_filter(if self.index + 10 < 30 {
|
||||||
|
@ -557,7 +557,7 @@ impl State {
|
||||||
|
|
||||||
fn process_update_gain_inner_frame(
|
fn process_update_gain_inner_frame(
|
||||||
&mut self,
|
&mut self,
|
||||||
element: &gst::Element,
|
element: &super::AudioLoudNorm,
|
||||||
) -> Result<(), gst::FlowError> {
|
) -> Result<(), gst::FlowError> {
|
||||||
// Calculate global, shortterm loudness and relative threshold in LUFS.
|
// Calculate global, shortterm loudness and relative threshold in LUFS.
|
||||||
let global = self
|
let global = self
|
||||||
|
@ -641,7 +641,7 @@ impl State {
|
||||||
|
|
||||||
fn process_inner_frame(
|
fn process_inner_frame(
|
||||||
&mut self,
|
&mut self,
|
||||||
element: &gst::Element,
|
element: &super::AudioLoudNorm,
|
||||||
src: &[f64],
|
src: &[f64],
|
||||||
pts: gst::ClockTime,
|
pts: gst::ClockTime,
|
||||||
) -> Result<(gst::Buffer, gst::ClockTime), gst::FlowError> {
|
) -> Result<(gst::Buffer, gst::ClockTime), gst::FlowError> {
|
||||||
|
@ -681,7 +681,7 @@ impl State {
|
||||||
|
|
||||||
fn process_fill_final_frame(
|
fn process_fill_final_frame(
|
||||||
&mut self,
|
&mut self,
|
||||||
_element: &gst::Element,
|
_element: &super::AudioLoudNorm,
|
||||||
idx: usize,
|
idx: usize,
|
||||||
num_samples: usize,
|
num_samples: usize,
|
||||||
) {
|
) {
|
||||||
|
@ -734,7 +734,7 @@ impl State {
|
||||||
|
|
||||||
fn process_final_frame(
|
fn process_final_frame(
|
||||||
&mut self,
|
&mut self,
|
||||||
element: &gst::Element,
|
element: &super::AudioLoudNorm,
|
||||||
src: &[f64],
|
src: &[f64],
|
||||||
pts: gst::ClockTime,
|
pts: gst::ClockTime,
|
||||||
) -> Result<(gst::Buffer, gst::ClockTime), gst::FlowError> {
|
) -> Result<(gst::Buffer, gst::ClockTime), gst::FlowError> {
|
||||||
|
@ -818,7 +818,7 @@ impl State {
|
||||||
|
|
||||||
fn process_linear_frame(
|
fn process_linear_frame(
|
||||||
&mut self,
|
&mut self,
|
||||||
element: &gst::Element,
|
element: &super::AudioLoudNorm,
|
||||||
src: &[f64],
|
src: &[f64],
|
||||||
pts: gst::ClockTime,
|
pts: gst::ClockTime,
|
||||||
) -> Result<(gst::Buffer, gst::ClockTime), gst::FlowError> {
|
) -> Result<(gst::Buffer, gst::ClockTime), gst::FlowError> {
|
||||||
|
@ -855,7 +855,7 @@ impl State {
|
||||||
|
|
||||||
fn process(
|
fn process(
|
||||||
&mut self,
|
&mut self,
|
||||||
element: &gst::Element,
|
element: &super::AudioLoudNorm,
|
||||||
src: &[f64],
|
src: &[f64],
|
||||||
pts: gst::ClockTime,
|
pts: gst::ClockTime,
|
||||||
) -> Result<(gst::Buffer, gst::ClockTime), gst::FlowError> {
|
) -> Result<(gst::Buffer, gst::ClockTime), gst::FlowError> {
|
||||||
|
@ -882,7 +882,7 @@ impl State {
|
||||||
|
|
||||||
fn true_peak_limiter_out(
|
fn true_peak_limiter_out(
|
||||||
&mut self,
|
&mut self,
|
||||||
element: &gst::Element,
|
element: &super::AudioLoudNorm,
|
||||||
mut smp_cnt: usize,
|
mut smp_cnt: usize,
|
||||||
nb_samples: usize,
|
nb_samples: usize,
|
||||||
) -> usize {
|
) -> usize {
|
||||||
|
@ -923,7 +923,7 @@ impl State {
|
||||||
|
|
||||||
fn true_peak_limiter_attack(
|
fn true_peak_limiter_attack(
|
||||||
&mut self,
|
&mut self,
|
||||||
element: &gst::Element,
|
element: &super::AudioLoudNorm,
|
||||||
mut smp_cnt: usize,
|
mut smp_cnt: usize,
|
||||||
nb_samples: usize,
|
nb_samples: usize,
|
||||||
) -> usize {
|
) -> usize {
|
||||||
|
@ -1136,7 +1136,7 @@ impl State {
|
||||||
|
|
||||||
fn true_peak_limiter_sustain(
|
fn true_peak_limiter_sustain(
|
||||||
&mut self,
|
&mut self,
|
||||||
element: &gst::Element,
|
element: &super::AudioLoudNorm,
|
||||||
mut smp_cnt: usize,
|
mut smp_cnt: usize,
|
||||||
nb_samples: usize,
|
nb_samples: usize,
|
||||||
) -> usize {
|
) -> usize {
|
||||||
|
@ -1252,7 +1252,7 @@ impl State {
|
||||||
|
|
||||||
fn true_peak_limiter_release(
|
fn true_peak_limiter_release(
|
||||||
&mut self,
|
&mut self,
|
||||||
element: &gst::Element,
|
element: &super::AudioLoudNorm,
|
||||||
mut smp_cnt: usize,
|
mut smp_cnt: usize,
|
||||||
nb_samples: usize,
|
nb_samples: usize,
|
||||||
) -> usize {
|
) -> usize {
|
||||||
|
@ -1371,7 +1371,7 @@ impl State {
|
||||||
smp_cnt
|
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;
|
let channels = self.info.channels() as usize;
|
||||||
|
|
||||||
assert_eq!(self.limiter_buf_index, 0);
|
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 channels = self.info.channels() as usize;
|
||||||
let nb_samples = dst.len() / channels;
|
let nb_samples = dst.len() / channels;
|
||||||
|
|
||||||
|
@ -1588,7 +1588,7 @@ impl AudioLoudNorm {
|
||||||
fn sink_chain(
|
fn sink_chain(
|
||||||
&self,
|
&self,
|
||||||
_pad: &gst::Pad,
|
_pad: &gst::Pad,
|
||||||
element: &gst::Element,
|
element: &super::AudioLoudNorm,
|
||||||
buffer: gst::Buffer,
|
buffer: gst::Buffer,
|
||||||
) -> Result<gst::FlowSuccess, gst::FlowError> {
|
) -> Result<gst::FlowSuccess, gst::FlowError> {
|
||||||
gst_log!(CAT, obj: element, "Handling buffer {:?}", buffer);
|
gst_log!(CAT, obj: element, "Handling buffer {:?}", buffer);
|
||||||
|
@ -1629,7 +1629,12 @@ impl AudioLoudNorm {
|
||||||
Ok(gst::FlowSuccess::Ok)
|
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;
|
use gst::EventView;
|
||||||
|
|
||||||
gst_log!(CAT, obj: pad, "Handling event {:?}", event);
|
gst_log!(CAT, obj: pad, "Handling event {:?}", event);
|
||||||
|
@ -1712,7 +1717,12 @@ impl AudioLoudNorm {
|
||||||
pad.event_default(Some(element), event)
|
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;
|
use gst::QueryView;
|
||||||
|
|
||||||
gst_log!(CAT, obj: pad, "Handling query {:?}", query);
|
gst_log!(CAT, obj: pad, "Handling query {:?}", query);
|
||||||
|
@ -1738,13 +1748,14 @@ impl AudioLoudNorm {
|
||||||
|
|
||||||
impl ObjectSubclass for AudioLoudNorm {
|
impl ObjectSubclass for AudioLoudNorm {
|
||||||
const NAME: &'static str = "RsAudioLoudNorm";
|
const NAME: &'static str = "RsAudioLoudNorm";
|
||||||
|
type Type = super::AudioLoudNorm;
|
||||||
type ParentType = gst::Element;
|
type ParentType = gst::Element;
|
||||||
type Instance = gst::subclass::ElementInstanceStruct<Self>;
|
type Instance = gst::subclass::ElementInstanceStruct<Self>;
|
||||||
type Class = subclass::simple::ClassStruct<Self>;
|
type Class = subclass::simple::ClassStruct<Self>;
|
||||||
|
|
||||||
glib_object_subclass!();
|
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 templ = klass.get_pad_template("sink").unwrap();
|
||||||
let sinkpad = gst::Pad::builder_with_template(&templ, Some("sink"))
|
let sinkpad = gst::Pad::builder_with_template(&templ, Some("sink"))
|
||||||
.chain_function(|pad, parent, buffer| {
|
.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(
|
klass.set_metadata(
|
||||||
"Audio loudness normalizer",
|
"Audio loudness normalizer",
|
||||||
"Filter/Effect/Audio",
|
"Filter/Effect/Audio",
|
||||||
|
@ -1824,15 +1835,14 @@ impl ObjectSubclass for AudioLoudNorm {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ObjectImpl for AudioLoudNorm {
|
impl ObjectImpl for AudioLoudNorm {
|
||||||
fn constructed(&self, obj: &glib::Object) {
|
fn constructed(&self, obj: &Self::Type) {
|
||||||
self.parent_constructed(obj);
|
self.parent_constructed(obj);
|
||||||
|
|
||||||
let element = obj.downcast_ref::<gst::Element>().unwrap();
|
obj.add_pad(&self.sinkpad).unwrap();
|
||||||
element.add_pad(&self.sinkpad).unwrap();
|
obj.add_pad(&self.srcpad).unwrap();
|
||||||
element.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];
|
let prop = &PROPERTIES[id];
|
||||||
|
|
||||||
match *prop {
|
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];
|
let prop = &PROPERTIES[id];
|
||||||
|
|
||||||
match *prop {
|
match *prop {
|
||||||
|
@ -1884,7 +1894,7 @@ impl ObjectImpl for AudioLoudNorm {
|
||||||
impl ElementImpl for AudioLoudNorm {
|
impl ElementImpl for AudioLoudNorm {
|
||||||
fn change_state(
|
fn change_state(
|
||||||
&self,
|
&self,
|
||||||
element: &gst::Element,
|
element: &Self::Type,
|
||||||
transition: gst::StateChange,
|
transition: gst::StateChange,
|
||||||
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
|
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
|
||||||
let res = self.parent_change_state(element, transition);
|
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] {
|
fn init_gaussian_filter() -> [f64; 21] {
|
||||||
let mut weights = [0.0f64; 21];
|
let mut weights = [0.0f64; 21];
|
||||||
let mut total_weight = 0.0f64;
|
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,
|
adapter: gst_base::UniqueAdapter,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AudioRNNoise {
|
pub struct AudioRNNoise {
|
||||||
state: Mutex<Option<State>>,
|
state: Mutex<Option<State>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ impl State {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AudioRNNoise {
|
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 mut state_lock = self.state.lock().unwrap();
|
||||||
let state = state_lock.as_mut().unwrap();
|
let state = state_lock.as_mut().unwrap();
|
||||||
|
|
||||||
|
@ -154,7 +154,7 @@ impl AudioRNNoise {
|
||||||
|
|
||||||
fn generate_output(
|
fn generate_output(
|
||||||
&self,
|
&self,
|
||||||
_element: &gst_base::BaseTransform,
|
_element: &super::AudioRNNoise,
|
||||||
state: &mut State,
|
state: &mut State,
|
||||||
) -> Result<GenerateOutputSuccess, gst::FlowError> {
|
) -> Result<GenerateOutputSuccess, gst::FlowError> {
|
||||||
let available = state.adapter.available();
|
let available = state.adapter.available();
|
||||||
|
@ -189,6 +189,7 @@ impl AudioRNNoise {
|
||||||
|
|
||||||
impl ObjectSubclass for AudioRNNoise {
|
impl ObjectSubclass for AudioRNNoise {
|
||||||
const NAME: &'static str = "AudioRNNoise";
|
const NAME: &'static str = "AudioRNNoise";
|
||||||
|
type Type = super::AudioRNNoise;
|
||||||
type ParentType = gst_base::BaseTransform;
|
type ParentType = gst_base::BaseTransform;
|
||||||
type Instance = gst::subclass::ElementInstanceStruct<Self>;
|
type Instance = gst::subclass::ElementInstanceStruct<Self>;
|
||||||
type Class = subclass::simple::ClassStruct<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(
|
klass.set_metadata(
|
||||||
"Audio denoise",
|
"Audio denoise",
|
||||||
"Filter/Effect/Audio",
|
"Filter/Effect/Audio",
|
||||||
|
@ -250,7 +251,7 @@ impl ElementImpl for AudioRNNoise {}
|
||||||
impl BaseTransformImpl for AudioRNNoise {
|
impl BaseTransformImpl for AudioRNNoise {
|
||||||
fn set_caps(
|
fn set_caps(
|
||||||
&self,
|
&self,
|
||||||
element: &gst_base::BaseTransform,
|
element: &Self::Type,
|
||||||
incaps: &gst::Caps,
|
incaps: &gst::Caps,
|
||||||
outcaps: &gst::Caps,
|
outcaps: &gst::Caps,
|
||||||
) -> Result<(), gst::LoggableError> {
|
) -> Result<(), gst::LoggableError> {
|
||||||
|
@ -293,7 +294,7 @@ impl BaseTransformImpl for AudioRNNoise {
|
||||||
|
|
||||||
fn generate_output(
|
fn generate_output(
|
||||||
&self,
|
&self,
|
||||||
element: &gst_base::BaseTransform,
|
element: &Self::Type,
|
||||||
) -> Result<GenerateOutputSuccess, gst::FlowError> {
|
) -> Result<GenerateOutputSuccess, gst::FlowError> {
|
||||||
// Check if there are enough data in the queued buffer and adapter,
|
// 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
|
// 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)
|
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;
|
use gst::EventView;
|
||||||
|
|
||||||
if let EventView::Eos(_) = event.view() {
|
if let EventView::Eos(_) = event.view() {
|
||||||
|
@ -335,7 +336,7 @@ impl BaseTransformImpl for AudioRNNoise {
|
||||||
|
|
||||||
fn query(
|
fn query(
|
||||||
&self,
|
&self,
|
||||||
element: &gst_base::BaseTransform,
|
element: &Self::Type,
|
||||||
direction: gst::PadDirection,
|
direction: gst::PadDirection,
|
||||||
query: &mut gst::QueryRef,
|
query: &mut gst::QueryRef,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
|
@ -364,19 +365,10 @@ impl BaseTransformImpl for AudioRNNoise {
|
||||||
BaseTransformImplExt::parent_query(self, element, direction, query)
|
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
|
// Drop state
|
||||||
let _ = self.state.lock().unwrap().take();
|
let _ = self.state.lock().unwrap().take();
|
||||||
|
|
||||||
Ok(())
|
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> {
|
fn plugin_init(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
|
||||||
audioecho::register(plugin)?;
|
audioecho::register(plugin)?;
|
||||||
|
audioloudnorm::register(plugin)?;
|
||||||
audiornnoise::register(plugin)?;
|
audiornnoise::register(plugin)?;
|
||||||
audioloudnorm::register(plugin)
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_plugin_define!(
|
gst_plugin_define!(
|
||||||
|
|
|
@ -23,13 +23,14 @@ struct State {
|
||||||
audio_info: Option<gst_audio::AudioInfo>,
|
audio_info: Option<gst_audio::AudioInfo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ClaxonDec {
|
pub struct ClaxonDec {
|
||||||
cat: gst::DebugCategory,
|
cat: gst::DebugCategory,
|
||||||
state: AtomicRefCell<Option<State>>,
|
state: AtomicRefCell<Option<State>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ObjectSubclass for ClaxonDec {
|
impl ObjectSubclass for ClaxonDec {
|
||||||
const NAME: &'static str = "ClaxonDec";
|
const NAME: &'static str = "ClaxonDec";
|
||||||
|
type Type = super::ClaxonDec;
|
||||||
type ParentType = gst_audio::AudioDecoder;
|
type ParentType = gst_audio::AudioDecoder;
|
||||||
type Instance = gst::subclass::ElementInstanceStruct<Self>;
|
type Instance = gst::subclass::ElementInstanceStruct<Self>;
|
||||||
type Class = subclass::simple::ClassStruct<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(
|
klass.set_metadata(
|
||||||
"Claxon FLAC decoder",
|
"Claxon FLAC decoder",
|
||||||
"Decoder/Audio",
|
"Decoder/Audio",
|
||||||
|
@ -98,13 +99,13 @@ impl ObjectImpl for ClaxonDec {}
|
||||||
impl ElementImpl for ClaxonDec {}
|
impl ElementImpl for ClaxonDec {}
|
||||||
|
|
||||||
impl AudioDecoderImpl 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;
|
*self.state.borrow_mut() = None;
|
||||||
|
|
||||||
Ok(())
|
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 {
|
*self.state.borrow_mut() = Some(State {
|
||||||
streaminfo: None,
|
streaminfo: None,
|
||||||
audio_info: None,
|
audio_info: None,
|
||||||
|
@ -113,11 +114,7 @@ impl AudioDecoderImpl for ClaxonDec {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_format(
|
fn set_format(&self, element: &Self::Type, caps: &gst::Caps) -> Result<(), gst::LoggableError> {
|
||||||
&self,
|
|
||||||
element: &gst_audio::AudioDecoder,
|
|
||||||
caps: &gst::Caps,
|
|
||||||
) -> Result<(), gst::LoggableError> {
|
|
||||||
gst_debug!(self.cat, obj: element, "Setting format {:?}", caps);
|
gst_debug!(self.cat, obj: element, "Setting format {:?}", caps);
|
||||||
|
|
||||||
let mut streaminfo: Option<claxon::metadata::StreamInfo> = None;
|
let mut streaminfo: Option<claxon::metadata::StreamInfo> = None;
|
||||||
|
@ -174,7 +171,7 @@ impl AudioDecoderImpl for ClaxonDec {
|
||||||
#[allow(clippy::verbose_bit_mask)]
|
#[allow(clippy::verbose_bit_mask)]
|
||||||
fn handle_frame(
|
fn handle_frame(
|
||||||
&self,
|
&self,
|
||||||
element: &gst_audio::AudioDecoder,
|
element: &Self::Type,
|
||||||
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!(self.cat, obj: element, "Handling buffer {:?}", inbuf);
|
||||||
|
@ -217,7 +214,7 @@ impl AudioDecoderImpl for ClaxonDec {
|
||||||
impl ClaxonDec {
|
impl ClaxonDec {
|
||||||
fn handle_streaminfo_header(
|
fn handle_streaminfo_header(
|
||||||
&self,
|
&self,
|
||||||
element: &gst_audio::AudioDecoder,
|
element: &super::ClaxonDec,
|
||||||
state: &mut State,
|
state: &mut State,
|
||||||
indata: &[u8],
|
indata: &[u8],
|
||||||
) -> Result<gst::FlowSuccess, gst::FlowError> {
|
) -> Result<gst::FlowSuccess, gst::FlowError> {
|
||||||
|
@ -249,7 +246,7 @@ impl ClaxonDec {
|
||||||
|
|
||||||
fn handle_data(
|
fn handle_data(
|
||||||
&self,
|
&self,
|
||||||
element: &gst_audio::AudioDecoder,
|
element: &super::ClaxonDec,
|
||||||
state: &mut State,
|
state: &mut State,
|
||||||
indata: &[u8],
|
indata: &[u8],
|
||||||
) -> Result<gst::FlowSuccess, gst::FlowError> {
|
) -> 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> {
|
fn get_claxon_streaminfo(indata: &[u8]) -> Result<claxon::metadata::StreamInfo, &'static str> {
|
||||||
let mut cursor = Cursor::new(indata);
|
let mut cursor = Cursor::new(indata);
|
||||||
let mut metadata_iter = claxon::metadata::MetadataBlockReader::new(&mut cursor);
|
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,
|
ksmps: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CsoundFilter {
|
pub struct CsoundFilter {
|
||||||
settings: Mutex<Settings>,
|
settings: Mutex<Settings>,
|
||||||
state: Mutex<Option<State>>,
|
state: Mutex<Option<State>>,
|
||||||
csound: Mutex<Csound>,
|
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 csound = self.csound.lock().unwrap();
|
||||||
let mut state_lock = self.state.lock().unwrap();
|
let mut state_lock = self.state.lock().unwrap();
|
||||||
let state = state_lock.as_mut().unwrap();
|
let state = state_lock.as_mut().unwrap();
|
||||||
|
@ -293,7 +293,7 @@ impl CsoundFilter {
|
||||||
|
|
||||||
fn generate_output(
|
fn generate_output(
|
||||||
&self,
|
&self,
|
||||||
element: &gst_base::BaseTransform,
|
element: &super::CsoundFilter,
|
||||||
state: &mut State,
|
state: &mut State,
|
||||||
) -> Result<GenerateOutputSuccess, gst::FlowError> {
|
) -> Result<GenerateOutputSuccess, gst::FlowError> {
|
||||||
let output_size = state.max_output_size(state.adapter.available());
|
let output_size = state.max_output_size(state.adapter.available());
|
||||||
|
@ -361,6 +361,7 @@ impl CsoundFilter {
|
||||||
|
|
||||||
impl ObjectSubclass for CsoundFilter {
|
impl ObjectSubclass for CsoundFilter {
|
||||||
const NAME: &'static str = "CsoundFilter";
|
const NAME: &'static str = "CsoundFilter";
|
||||||
|
type Type = super::CsoundFilter;
|
||||||
type ParentType = gst_base::BaseTransform;
|
type ParentType = gst_base::BaseTransform;
|
||||||
type Instance = gst::subclass::ElementInstanceStruct<Self>;
|
type Instance = gst::subclass::ElementInstanceStruct<Self>;
|
||||||
type Class = subclass::simple::ClassStruct<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(
|
klass.set_metadata(
|
||||||
"Audio filter",
|
"Audio filter",
|
||||||
"Filter/Effect/Audio",
|
"Filter/Effect/Audio",
|
||||||
|
@ -431,7 +432,7 @@ impl ObjectSubclass for CsoundFilter {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ObjectImpl 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];
|
let prop = &PROPERTIES[id];
|
||||||
match *prop {
|
match *prop {
|
||||||
subclass::Property("loop", ..) => {
|
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];
|
let prop = &PROPERTIES[id];
|
||||||
|
|
||||||
match *prop {
|
match *prop {
|
||||||
|
@ -492,10 +493,7 @@ impl ObjectImpl for CsoundFilter {
|
||||||
impl ElementImpl for CsoundFilter {}
|
impl ElementImpl for CsoundFilter {}
|
||||||
|
|
||||||
impl BaseTransformImpl for CsoundFilter {
|
impl BaseTransformImpl for CsoundFilter {
|
||||||
fn start(
|
fn start(&self, _element: &Self::Type) -> std::result::Result<(), gst::ErrorMessage> {
|
||||||
&self,
|
|
||||||
_element: &gst_base::BaseTransform,
|
|
||||||
) -> std::result::Result<(), gst::ErrorMessage> {
|
|
||||||
self.compile_score()?;
|
self.compile_score()?;
|
||||||
|
|
||||||
let csound = self.csound.lock().unwrap();
|
let csound = self.csound.lock().unwrap();
|
||||||
|
@ -509,7 +507,7 @@ impl BaseTransformImpl for CsoundFilter {
|
||||||
Ok(())
|
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();
|
let csound = self.csound.lock().unwrap();
|
||||||
csound.stop();
|
csound.stop();
|
||||||
csound.reset();
|
csound.reset();
|
||||||
|
@ -520,7 +518,7 @@ impl BaseTransformImpl for CsoundFilter {
|
||||||
Ok(())
|
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;
|
use gst::EventView;
|
||||||
|
|
||||||
if let EventView::Eos(_) = event.view() {
|
if let EventView::Eos(_) = event.view() {
|
||||||
|
@ -534,7 +532,7 @@ impl BaseTransformImpl for CsoundFilter {
|
||||||
|
|
||||||
fn transform_caps(
|
fn transform_caps(
|
||||||
&self,
|
&self,
|
||||||
element: &gst_base::BaseTransform,
|
element: &Self::Type,
|
||||||
direction: gst::PadDirection,
|
direction: gst::PadDirection,
|
||||||
caps: &gst::Caps,
|
caps: &gst::Caps,
|
||||||
filter: Option<&gst::Caps>,
|
filter: Option<&gst::Caps>,
|
||||||
|
@ -586,7 +584,7 @@ impl BaseTransformImpl for CsoundFilter {
|
||||||
|
|
||||||
fn set_caps(
|
fn set_caps(
|
||||||
&self,
|
&self,
|
||||||
element: &gst_base::BaseTransform,
|
element: &Self::Type,
|
||||||
incaps: &gst::Caps,
|
incaps: &gst::Caps,
|
||||||
outcaps: &gst::Caps,
|
outcaps: &gst::Caps,
|
||||||
) -> Result<(), gst::LoggableError> {
|
) -> Result<(), gst::LoggableError> {
|
||||||
|
@ -646,7 +644,7 @@ impl BaseTransformImpl for CsoundFilter {
|
||||||
|
|
||||||
fn generate_output(
|
fn generate_output(
|
||||||
&self,
|
&self,
|
||||||
element: &gst_base::BaseTransform,
|
element: &Self::Type,
|
||||||
) -> Result<GenerateOutputSuccess, gst::FlowError> {
|
) -> Result<GenerateOutputSuccess, gst::FlowError> {
|
||||||
// Check if there are enough data in the queued buffer and adapter,
|
// 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
|
// 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)
|
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]>,
|
reorder_map: Option<[usize; 8]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LewtonDec {
|
pub struct LewtonDec {
|
||||||
state: AtomicRefCell<Option<State>>,
|
state: AtomicRefCell<Option<State>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ lazy_static! {
|
||||||
|
|
||||||
impl ObjectSubclass for LewtonDec {
|
impl ObjectSubclass for LewtonDec {
|
||||||
const NAME: &'static str = "LewtonDec";
|
const NAME: &'static str = "LewtonDec";
|
||||||
|
type Type = super::LewtonDec;
|
||||||
type ParentType = gst_audio::AudioDecoder;
|
type ParentType = gst_audio::AudioDecoder;
|
||||||
type Instance = gst::subclass::ElementInstanceStruct<Self>;
|
type Instance = gst::subclass::ElementInstanceStruct<Self>;
|
||||||
type Class = subclass::simple::ClassStruct<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(
|
klass.set_metadata(
|
||||||
"lewton Vorbis decoder",
|
"lewton Vorbis decoder",
|
||||||
"Decoder/Audio",
|
"Decoder/Audio",
|
||||||
|
@ -97,13 +98,13 @@ impl ObjectImpl for LewtonDec {}
|
||||||
impl ElementImpl for LewtonDec {}
|
impl ElementImpl for LewtonDec {}
|
||||||
|
|
||||||
impl AudioDecoderImpl 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;
|
*self.state.borrow_mut() = None;
|
||||||
|
|
||||||
Ok(())
|
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 {
|
*self.state.borrow_mut() = Some(State {
|
||||||
header_bufs: (None, None, None),
|
header_bufs: (None, None, None),
|
||||||
headerset: None,
|
headerset: None,
|
||||||
|
@ -115,11 +116,7 @@ impl AudioDecoderImpl for LewtonDec {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_format(
|
fn set_format(&self, element: &Self::Type, caps: &gst::Caps) -> Result<(), gst::LoggableError> {
|
||||||
&self,
|
|
||||||
element: &gst_audio::AudioDecoder,
|
|
||||||
caps: &gst::Caps,
|
|
||||||
) -> Result<(), gst::LoggableError> {
|
|
||||||
gst_debug!(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
|
||||||
|
@ -160,7 +157,7 @@ impl AudioDecoderImpl for LewtonDec {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flush(&self, element: &gst_audio::AudioDecoder, _hard: bool) {
|
fn flush(&self, element: &Self::Type, _hard: bool) {
|
||||||
gst_debug!(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();
|
||||||
|
@ -171,7 +168,7 @@ impl AudioDecoderImpl for LewtonDec {
|
||||||
|
|
||||||
fn handle_frame(
|
fn handle_frame(
|
||||||
&self,
|
&self,
|
||||||
element: &gst_audio::AudioDecoder,
|
element: &Self::Type,
|
||||||
inbuf: Option<&gst::Buffer>,
|
inbuf: Option<&gst::Buffer>,
|
||||||
) -> Result<gst::FlowSuccess, gst::FlowError> {
|
) -> Result<gst::FlowSuccess, gst::FlowError> {
|
||||||
gst_debug!(CAT, obj: element, "Handling buffer {:?}", inbuf);
|
gst_debug!(CAT, obj: element, "Handling buffer {:?}", inbuf);
|
||||||
|
@ -218,7 +215,7 @@ impl AudioDecoderImpl for LewtonDec {
|
||||||
impl LewtonDec {
|
impl LewtonDec {
|
||||||
fn handle_header(
|
fn handle_header(
|
||||||
&self,
|
&self,
|
||||||
element: &gst_audio::AudioDecoder,
|
element: &super::LewtonDec,
|
||||||
state: &mut State,
|
state: &mut State,
|
||||||
inbuf: &gst::Buffer,
|
inbuf: &gst::Buffer,
|
||||||
indata: &[u8],
|
indata: &[u8],
|
||||||
|
@ -254,7 +251,7 @@ impl LewtonDec {
|
||||||
|
|
||||||
fn initialize(
|
fn initialize(
|
||||||
&self,
|
&self,
|
||||||
element: &gst_audio::AudioDecoder,
|
element: &super::LewtonDec,
|
||||||
state: &mut State,
|
state: &mut State,
|
||||||
) -> Result<(), gst::FlowError> {
|
) -> Result<(), gst::FlowError> {
|
||||||
let (ident_buf, comment_buf, setup_buf) = match state.header_bufs {
|
let (ident_buf, comment_buf, setup_buf) = match state.header_bufs {
|
||||||
|
@ -369,7 +366,7 @@ impl LewtonDec {
|
||||||
|
|
||||||
fn handle_data(
|
fn handle_data(
|
||||||
&self,
|
&self,
|
||||||
element: &gst_audio::AudioDecoder,
|
element: &super::LewtonDec,
|
||||||
state: &mut State,
|
state: &mut State,
|
||||||
indata: &[u8],
|
indata: &[u8],
|
||||||
) -> Result<gst::FlowSuccess, gst::FlowError> {
|
) -> 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
|
// http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-800004.3.9
|
||||||
const VORBIS_CHANNEL_POSITIONS: [[gst_audio::AudioChannelPosition; 8]; 8] = [
|
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