2020-12-15 10:53:31 +00:00
// Take a look at the license at the top of the repository in the LICENSE file.
2020-04-10 14:52:32 +00:00
use std ::fmt ;
2023-05-04 05:55:48 +00:00
#[ cfg(feature = " v1_16 " ) ]
#[ cfg_attr(docsrs, doc(cfg(feature = " v1_16 " ))) ]
2020-06-07 11:15:47 +00:00
use std ::ptr ;
2023-05-04 05:55:48 +00:00
#[ cfg(feature = " v1_16 " ) ]
#[ cfg_attr(docsrs, doc(cfg(feature = " v1_16 " ))) ]
2020-06-07 11:15:47 +00:00
use std ::slice ;
2020-04-10 14:52:32 +00:00
2021-04-27 15:15:46 +00:00
use glib ::translate ::{ from_glib , IntoGlib } ;
2023-05-04 05:55:48 +00:00
#[ cfg(feature = " v1_16 " ) ]
#[ cfg_attr(docsrs, doc(cfg(feature = " v1_16 " ))) ]
2020-06-07 11:15:47 +00:00
use glib ::translate ::{ from_glib_none , ToGlibPtr } ;
2020-04-10 14:52:32 +00:00
use gst ::prelude ::* ;
2024-06-02 08:48:53 +00:00
use crate ::ffi ;
2020-10-24 17:06:59 +00:00
#[ repr(transparent) ]
2021-06-01 13:15:59 +00:00
#[ doc(alias = " GstAudioClippingMeta " ) ]
2020-11-21 18:17:20 +00:00
pub struct AudioClippingMeta ( ffi ::GstAudioClippingMeta ) ;
2020-04-10 14:52:32 +00:00
unsafe impl Send for AudioClippingMeta { }
unsafe impl Sync for AudioClippingMeta { }
impl AudioClippingMeta {
2021-05-19 20:35:47 +00:00
#[ doc(alias = " gst_buffer_add_audio_clipping_meta " ) ]
2022-10-09 16:37:45 +00:00
pub fn add < V : gst ::format ::FormattedValue > (
2020-04-10 14:52:32 +00:00
buffer : & mut gst ::BufferRef ,
start : V ,
end : V ,
) -> gst ::MetaRefMut < Self , gst ::meta ::Standalone > {
2020-03-22 14:18:47 +00:00
skip_assert_initialized! ( ) ;
2021-04-11 19:39:50 +00:00
assert_eq! ( start . format ( ) , end . format ( ) ) ;
2020-04-10 14:52:32 +00:00
unsafe {
2020-11-21 18:17:20 +00:00
let meta = ffi ::gst_buffer_add_audio_clipping_meta (
2020-04-10 14:52:32 +00:00
buffer . as_mut_ptr ( ) ,
2021-04-27 15:15:46 +00:00
start . format ( ) . into_glib ( ) ,
2022-07-03 16:04:06 +00:00
start . into_raw_value ( ) as u64 ,
end . into_raw_value ( ) as u64 ,
2020-04-10 14:52:32 +00:00
) ;
Self ::from_mut_ptr ( buffer , meta )
}
}
2021-05-02 09:41:18 +00:00
#[ doc(alias = " get_start " ) ]
2022-12-18 08:18:31 +00:00
#[ inline ]
2021-04-11 19:39:50 +00:00
pub fn start ( & self ) -> gst ::GenericFormattedValue {
2020-12-08 14:07:12 +00:00
unsafe { gst ::GenericFormattedValue ::new ( from_glib ( self . 0. format ) , self . 0. start as i64 ) }
2020-04-10 14:52:32 +00:00
}
2021-05-02 09:41:18 +00:00
#[ doc(alias = " get_end " ) ]
2022-12-18 08:18:31 +00:00
#[ inline ]
2021-04-11 19:39:50 +00:00
pub fn end ( & self ) -> gst ::GenericFormattedValue {
2020-12-08 14:07:12 +00:00
unsafe { gst ::GenericFormattedValue ::new ( from_glib ( self . 0. format ) , self . 0. end as i64 ) }
2020-04-10 14:52:32 +00:00
}
}
unsafe impl MetaAPI for AudioClippingMeta {
2020-11-21 18:17:20 +00:00
type GstType = ffi ::GstAudioClippingMeta ;
2020-04-10 14:52:32 +00:00
2021-05-19 20:35:47 +00:00
#[ doc(alias = " gst_audio_clipping_meta_api_get_type " ) ]
2022-12-18 08:18:31 +00:00
#[ inline ]
2021-04-20 10:23:24 +00:00
fn meta_api ( ) -> glib ::Type {
2020-11-21 18:17:20 +00:00
unsafe { from_glib ( ffi ::gst_audio_clipping_meta_api_get_type ( ) ) }
2020-04-10 14:52:32 +00:00
}
}
impl fmt ::Debug for AudioClippingMeta {
fn fmt ( & self , f : & mut fmt ::Formatter ) -> fmt ::Result {
f . debug_struct ( " AudioClippingMeta " )
2021-04-11 19:39:50 +00:00
. field ( " start " , & self . start ( ) )
. field ( " end " , & self . end ( ) )
2020-04-10 14:52:32 +00:00
. finish ( )
}
}
2023-05-04 05:55:48 +00:00
#[ cfg(feature = " v1_16 " ) ]
#[ cfg_attr(docsrs, doc(cfg(feature = " v1_16 " ))) ]
2020-10-24 17:06:59 +00:00
#[ repr(transparent) ]
2021-06-01 13:15:59 +00:00
#[ doc(alias = " GstAudioMeta " ) ]
2020-11-21 18:17:20 +00:00
pub struct AudioMeta ( ffi ::GstAudioMeta ) ;
2020-06-07 11:15:47 +00:00
2023-05-04 05:55:48 +00:00
#[ cfg(feature = " v1_16 " ) ]
#[ cfg_attr(docsrs, doc(cfg(feature = " v1_16 " ))) ]
2020-06-07 11:15:47 +00:00
unsafe impl Send for AudioMeta { }
2023-05-04 05:55:48 +00:00
#[ cfg(feature = " v1_16 " ) ]
#[ cfg_attr(docsrs, doc(cfg(feature = " v1_16 " ))) ]
2020-06-07 11:15:47 +00:00
unsafe impl Sync for AudioMeta { }
2023-05-04 05:55:48 +00:00
#[ cfg(feature = " v1_16 " ) ]
#[ cfg_attr(docsrs, doc(cfg(feature = " v1_16 " ))) ]
2020-06-07 11:15:47 +00:00
impl AudioMeta {
2021-05-19 20:35:47 +00:00
#[ doc(alias = " gst_buffer_add_audio_meta " ) ]
2020-06-07 11:15:47 +00:00
pub fn add < ' a > (
buffer : & ' a mut gst ::BufferRef ,
2020-11-21 18:17:20 +00:00
info : & crate ::AudioInfo ,
2020-06-07 11:15:47 +00:00
samples : usize ,
offsets : & [ usize ] ,
) -> Result < gst ::MetaRefMut < ' a , Self , gst ::meta ::Standalone > , glib ::BoolError > {
skip_assert_initialized! ( ) ;
if ! info . is_valid ( ) {
2020-12-17 22:38:06 +00:00
return Err ( glib ::bool_error! ( " Invalid audio info " ) ) ;
2020-06-07 11:15:47 +00:00
}
if info . rate ( ) = = 0
| | info . channels ( ) = = 0
2020-11-21 18:17:20 +00:00
| | info . format ( ) = = crate ::AudioFormat ::Unknown
| | info . format ( ) = = crate ::AudioFormat ::Encoded
2020-06-07 11:15:47 +00:00
{
2020-12-17 22:38:06 +00:00
return Err ( glib ::bool_error! ( " Unsupported audio format {:?} " , info ) ) ;
2020-06-07 11:15:47 +00:00
}
2020-11-21 18:17:20 +00:00
if ! offsets . is_empty ( ) & & info . layout ( ) ! = crate ::AudioLayout ::NonInterleaved {
2020-12-17 22:38:06 +00:00
return Err ( glib ::bool_error! (
2020-06-07 11:15:47 +00:00
" Channel offsets only supported for non-interleaved audio "
) ) ;
}
if ! offsets . is_empty ( ) & & offsets . len ( ) ! = info . channels ( ) as usize {
2020-12-17 22:38:06 +00:00
return Err ( glib ::bool_error! (
2020-06-07 11:15:47 +00:00
" Number of channel offsets different than number of channels ({} != {}) " ,
offsets . len ( ) ,
info . channels ( )
) ) ;
}
2020-11-21 18:17:20 +00:00
if info . layout ( ) = = crate ::AudioLayout ::NonInterleaved {
2020-06-07 11:15:47 +00:00
let plane_size = samples * ( info . width ( ) / 8 ) as usize ;
let max_offset = if offsets . is_empty ( ) {
plane_size * ( info . channels ( ) - 1 ) as usize
} else {
let mut max_offset = None ;
for ( i , offset ) in offsets . iter ( ) . copied ( ) . enumerate ( ) {
if let Some ( current_max_offset ) = max_offset {
max_offset = Some ( std ::cmp ::max ( current_max_offset , offset ) ) ;
} else {
max_offset = Some ( offset ) ;
}
for ( j , other_offset ) in offsets . iter ( ) . copied ( ) . enumerate ( ) {
if i ! = j
& & ! ( other_offset + plane_size < = offset
| | offset + plane_size < = other_offset )
{
2020-12-17 22:38:06 +00:00
return Err ( glib ::bool_error! ( " Overlapping audio channel offsets: offset {} for channel {} and offset {} for channel {} with a plane size of {} " , offset , i , other_offset , j , plane_size ) ) ;
2020-06-07 11:15:47 +00:00
}
}
}
max_offset . unwrap ( )
} ;
2021-04-11 19:39:50 +00:00
if max_offset + plane_size > buffer . size ( ) {
return Err ( glib ::bool_error! ( " Audio channel offsets out of bounds: max offset {} with plane size {} and buffer size {} " , max_offset , plane_size , buffer . size ( ) ) ) ;
2020-06-07 11:15:47 +00:00
}
}
unsafe {
2020-11-21 18:17:20 +00:00
let meta = ffi ::gst_buffer_add_audio_meta (
2020-06-07 11:15:47 +00:00
buffer . as_mut_ptr ( ) ,
info . to_glib_none ( ) . 0 ,
samples ,
if offsets . is_empty ( ) {
ptr ::null_mut ( )
} else {
offsets . as_ptr ( ) as * mut _
} ,
) ;
if meta . is_null ( ) {
2020-12-17 22:38:06 +00:00
return Err ( glib ::bool_error! ( " Failed to add audio meta " ) ) ;
2020-06-07 11:15:47 +00:00
}
Ok ( Self ::from_mut_ptr ( buffer , meta ) )
}
}
2021-05-02 09:41:18 +00:00
#[ doc(alias = " get_info " ) ]
2022-12-18 08:18:31 +00:00
#[ inline ]
2021-04-11 19:39:50 +00:00
pub fn info ( & self ) -> crate ::AudioInfo {
2023-11-29 09:24:47 +00:00
unsafe { from_glib_none ( & self . 0. info as * const _ ) }
2020-06-07 11:15:47 +00:00
}
2021-05-02 09:41:18 +00:00
#[ doc(alias = " get_samples " ) ]
2022-12-18 08:18:31 +00:00
#[ inline ]
2021-04-11 19:39:50 +00:00
pub fn samples ( & self ) -> usize {
2020-06-07 11:15:47 +00:00
self . 0. samples
}
2021-05-02 09:41:18 +00:00
#[ doc(alias = " get_offsets " ) ]
2022-12-18 08:18:31 +00:00
#[ inline ]
2021-04-11 19:39:50 +00:00
pub fn offsets ( & self ) -> & [ usize ] {
2020-06-07 11:15:47 +00:00
if self . 0. offsets . is_null ( ) | | self . 0. info . channels < 1 {
return & [ ] ;
}
unsafe { slice ::from_raw_parts ( self . 0. offsets , self . 0. info . channels as usize ) }
}
}
2023-05-04 05:55:48 +00:00
#[ cfg(feature = " v1_16 " ) ]
#[ cfg_attr(docsrs, doc(cfg(feature = " v1_16 " ))) ]
2020-06-07 11:15:47 +00:00
unsafe impl MetaAPI for AudioMeta {
2020-11-21 18:17:20 +00:00
type GstType = ffi ::GstAudioMeta ;
2020-06-07 11:15:47 +00:00
2021-05-19 20:35:47 +00:00
#[ doc(alias = " gst_audio_meta_api_get_type " ) ]
2022-12-18 08:18:31 +00:00
#[ inline ]
2021-04-20 10:23:24 +00:00
fn meta_api ( ) -> glib ::Type {
2020-11-21 18:17:20 +00:00
unsafe { from_glib ( ffi ::gst_audio_meta_api_get_type ( ) ) }
2020-06-07 11:15:47 +00:00
}
}
2023-05-04 05:55:48 +00:00
#[ cfg(feature = " v1_16 " ) ]
#[ cfg_attr(docsrs, doc(cfg(feature = " v1_16 " ))) ]
2020-06-07 11:15:47 +00:00
impl fmt ::Debug for AudioMeta {
fn fmt ( & self , f : & mut fmt ::Formatter ) -> fmt ::Result {
f . debug_struct ( " AudioMeta " )
2021-04-11 19:39:50 +00:00
. field ( " info " , & self . info ( ) )
. field ( " samples " , & self . samples ( ) )
. field ( " offsets " , & self . offsets ( ) )
2020-06-07 11:15:47 +00:00
. finish ( )
}
}
2023-05-04 05:55:48 +00:00
#[ cfg(feature = " v1_20 " ) ]
#[ cfg_attr(docsrs, doc(cfg(feature = " v1_20 " ))) ]
2021-05-24 10:35:00 +00:00
#[ repr(transparent) ]
#[ doc(alias = " GstAudioLevelMeta " ) ]
pub struct AudioLevelMeta ( ffi ::GstAudioLevelMeta ) ;
2023-05-04 05:55:48 +00:00
#[ cfg(feature = " v1_20 " ) ]
#[ cfg_attr(docsrs, doc(cfg(feature = " v1_20 " ))) ]
2021-05-24 10:35:00 +00:00
unsafe impl Send for AudioLevelMeta { }
2023-05-04 05:55:48 +00:00
#[ cfg(feature = " v1_20 " ) ]
#[ cfg_attr(docsrs, doc(cfg(feature = " v1_20 " ))) ]
2021-05-24 10:35:00 +00:00
unsafe impl Sync for AudioLevelMeta { }
2023-05-04 05:55:48 +00:00
#[ cfg(feature = " v1_20 " ) ]
#[ cfg_attr(docsrs, doc(cfg(feature = " v1_20 " ))) ]
2021-05-24 10:35:00 +00:00
impl AudioLevelMeta {
#[ doc(alias = " gst_buffer_add_audio_level_meta " ) ]
pub fn add (
buffer : & mut gst ::BufferRef ,
level : u8 ,
voice_activity : bool ,
) -> gst ::MetaRefMut < Self , gst ::meta ::Standalone > {
skip_assert_initialized! ( ) ;
unsafe {
let meta = ffi ::gst_buffer_add_audio_level_meta (
buffer . as_mut_ptr ( ) ,
level ,
voice_activity . into_glib ( ) ,
) ;
Self ::from_mut_ptr ( buffer , meta )
}
}
#[ doc(alias = " get_level " ) ]
2022-12-18 08:18:31 +00:00
#[ inline ]
2021-05-24 10:35:00 +00:00
pub fn level ( & self ) -> u8 {
self . 0. level
}
#[ doc(alias = " get_voice_activity " ) ]
2022-12-18 08:18:31 +00:00
#[ inline ]
2021-05-24 10:35:00 +00:00
pub fn voice_activity ( & self ) -> bool {
unsafe { from_glib ( self . 0. voice_activity ) }
}
}
2023-05-04 05:55:48 +00:00
#[ cfg(feature = " v1_20 " ) ]
#[ cfg_attr(docsrs, doc(cfg(feature = " v1_20 " ))) ]
2021-05-24 10:35:00 +00:00
unsafe impl MetaAPI for AudioLevelMeta {
type GstType = ffi ::GstAudioLevelMeta ;
#[ doc(alias = " gst_audio_level_meta_api_get_type " ) ]
2022-12-18 08:18:31 +00:00
#[ inline ]
2021-05-24 10:35:00 +00:00
fn meta_api ( ) -> glib ::Type {
unsafe { from_glib ( ffi ::gst_audio_level_meta_api_get_type ( ) ) }
}
}
2023-05-04 05:55:48 +00:00
#[ cfg(feature = " v1_20 " ) ]
#[ cfg_attr(docsrs, doc(cfg(feature = " v1_20 " ))) ]
2021-05-24 10:35:00 +00:00
impl fmt ::Debug for AudioLevelMeta {
fn fmt ( & self , f : & mut fmt ::Formatter ) -> fmt ::Result {
f . debug_struct ( " AudioLevelMeta " )
. field ( " level " , & self . level ( ) )
. field ( " voice_activity " , & self . voice_activity ( ) )
. finish ( )
}
}
2024-02-08 23:07:06 +00:00
pub mod tags {
2024-06-02 08:48:53 +00:00
gst ::impl_meta_tag! ( Audio , crate ::ffi ::GST_META_TAG_AUDIO_STR ) ;
gst ::impl_meta_tag! ( Channels , crate ::ffi ::GST_META_TAG_AUDIO_CHANNELS_STR ) ;
gst ::impl_meta_tag! ( Rate , crate ::ffi ::GST_META_TAG_AUDIO_RATE_STR ) ;
2024-02-08 23:07:06 +00:00
#[ cfg(feature = " v1_24 " ) ]
2024-06-02 08:48:53 +00:00
gst ::impl_meta_tag! (
DSDPlaneOffsets ,
crate ::ffi ::GST_META_TAG_DSD_PLANE_OFFSETS_STR
) ;
2024-02-08 23:07:06 +00:00
}
2020-04-10 14:52:32 +00:00
#[ cfg(test) ]
mod tests {
use super ::* ;
#[ test ]
2021-05-24 10:35:00 +00:00
fn test_add_get_audio_clipping_meta ( ) {
2022-10-17 21:43:41 +00:00
use gst ::prelude ::* ;
2020-04-10 14:52:32 +00:00
gst ::init ( ) . unwrap ( ) ;
let mut buffer = gst ::Buffer ::with_size ( 1024 ) . unwrap ( ) ;
2022-10-17 21:43:41 +00:00
let start = 1. default_format ( ) ;
let stop = 2. default_format ( ) ;
2022-10-10 11:31:24 +00:00
2020-04-10 14:52:32 +00:00
{
2022-10-10 11:31:24 +00:00
let cmeta = AudioClippingMeta ::add ( buffer . get_mut ( ) . unwrap ( ) , start , stop ) ;
assert_eq! ( cmeta . start ( ) . try_into ( ) , Ok ( Some ( start ) ) ) ;
assert_eq! ( cmeta . end ( ) . try_into ( ) , Ok ( Some ( stop ) ) ) ;
2020-04-10 14:52:32 +00:00
}
{
2021-04-20 10:24:17 +00:00
let cmeta = buffer . meta ::< AudioClippingMeta > ( ) . unwrap ( ) ;
2022-10-10 11:31:24 +00:00
assert_eq! ( cmeta . start ( ) . try_into ( ) , Ok ( Some ( start ) ) ) ;
assert_eq! ( cmeta . end ( ) . try_into ( ) , Ok ( Some ( stop ) ) ) ;
2024-02-08 23:07:06 +00:00
assert! ( cmeta . has_tag ::< tags ::Audio > ( ) ) ;
2020-04-10 14:52:32 +00:00
}
}
2021-05-24 10:35:00 +00:00
#[ cfg(feature = " v1_20 " ) ]
#[ test ]
fn test_add_get_audio_level_meta ( ) {
gst ::init ( ) . unwrap ( ) ;
let mut buffer = gst ::Buffer ::with_size ( 1024 ) . unwrap ( ) ;
{
let cmeta = AudioLevelMeta ::add ( buffer . get_mut ( ) . unwrap ( ) , 10 , true ) ;
assert_eq! ( cmeta . level ( ) , 10 ) ;
2021-06-20 07:03:46 +00:00
assert! ( cmeta . voice_activity ( ) ) ;
2021-05-24 10:35:00 +00:00
}
{
let cmeta = buffer . meta ::< AudioLevelMeta > ( ) . unwrap ( ) ;
assert_eq! ( cmeta . level ( ) , 10 ) ;
2021-06-20 07:03:46 +00:00
assert! ( cmeta . voice_activity ( ) ) ;
2021-05-24 10:35:00 +00:00
}
}
2020-04-10 14:52:32 +00:00
}