12
12
// See the License for the specific language governing permissions and
13
13
// limitations under the License.
14
14
15
- use std:: { sync:: Arc , time:: Duration } ;
16
-
17
15
use cxx:: SharedPtr ;
18
- use livekit_runtime:: interval;
19
- use tokio:: sync:: {
20
- mpsc:: { self , error:: TryRecvError } ,
21
- Mutex as AsyncMutex ,
22
- } ;
16
+ use tokio:: sync:: oneshot;
23
17
use webrtc_sys:: audio_track as sys_at;
24
18
25
19
use crate :: { audio_frame:: AudioFrame , audio_source:: AudioSourceOptions , RtcError , RtcErrorType } ;
26
20
27
- const BUFFER_SIZE_MS : usize = 50 ;
28
-
29
21
#[ derive( Clone ) ]
30
22
pub struct NativeAudioSource {
31
23
sys_handle : SharedPtr < sys_at:: ffi:: AudioTrackSource > ,
32
- inner : Arc < AsyncMutex < AudioSourceInner > > ,
33
24
sample_rate : u32 ,
34
25
num_channels : u32 ,
35
- samples_10ms : usize ,
36
- // whether to queue audio frames or send them immediately
37
- // defaults to true
38
- enable_queue : bool ,
39
- po_tx : mpsc:: Sender < Vec < i16 > > ,
40
- }
41
-
42
- struct AudioSourceInner {
43
- buf : Box < [ i16 ] > ,
44
-
45
- // Amount of data from the previous frame that hasn't been sent to the libwebrtc source
46
- // (because it requires 10ms of data)
47
- len : usize ,
26
+ queue_size_samples : u32 ,
48
27
}
49
28
50
29
impl NativeAudioSource {
51
30
pub fn new (
52
31
options : AudioSourceOptions ,
53
32
sample_rate : u32 ,
54
33
num_channels : u32 ,
55
- enable_queue : Option < bool > ,
34
+ queue_size_ms : u32 ,
56
35
) -> NativeAudioSource {
57
- let samples_10ms = ( sample_rate / 100 * num_channels) as usize ;
58
- let ( po_tx, mut po_rx) = mpsc:: channel ( BUFFER_SIZE_MS / 10 ) ;
59
-
60
- let source = Self {
61
- sys_handle : sys_at:: ffi:: new_audio_track_source ( options. into ( ) ) ,
62
- inner : Arc :: new ( AsyncMutex :: new ( AudioSourceInner {
63
- buf : vec ! [ 0 ; samples_10ms] . into_boxed_slice ( ) ,
64
- len : 0 ,
65
- } ) ) ,
66
- sample_rate,
67
- num_channels,
68
- samples_10ms,
69
- enable_queue : enable_queue. unwrap_or ( true ) ,
70
- po_tx,
71
- } ;
72
-
73
- livekit_runtime:: spawn ( {
74
- let source = source. clone ( ) ;
75
- async move {
76
- let mut interval = interval ( Duration :: from_millis ( 10 ) ) ;
77
- interval. set_missed_tick_behavior ( livekit_runtime:: MissedTickBehavior :: Delay ) ;
78
- let blank_data = vec ! [ 0 ; samples_10ms] ;
79
- let enable_queue = source. enable_queue ;
80
-
81
- loop {
82
- if enable_queue {
83
- interval. tick ( ) . await ;
84
- }
85
-
86
- let frame = po_rx. try_recv ( ) ;
87
- if let Err ( TryRecvError :: Disconnected ) = frame {
88
- break ;
89
- }
90
-
91
- if let Err ( TryRecvError :: Empty ) = frame {
92
- if enable_queue {
93
- source. sys_handle . on_captured_frame (
94
- & blank_data,
95
- sample_rate,
96
- num_channels,
97
- blank_data. len ( ) / num_channels as usize ,
98
- ) ;
99
- }
100
- continue ;
101
- }
102
-
103
- let frame = frame. unwrap ( ) ;
104
- source. sys_handle . on_captured_frame (
105
- & frame,
106
- sample_rate,
107
- num_channels,
108
- frame. len ( ) / num_channels as usize ,
109
- ) ;
110
- }
111
- }
112
- } ) ;
113
-
114
- source
36
+ assert ! ( queue_size_ms % 10 == 0 , "queue_size_ms must be a multiple of 10" ) ;
37
+
38
+ print ! (
39
+ "new audio source {} {} {} {}" ,
40
+ sample_rate, num_channels, queue_size_ms, options. echo_cancellation
41
+ ) ;
42
+
43
+ let sys_handle = sys_at:: ffi:: new_audio_track_source (
44
+ options. into ( ) ,
45
+ sample_rate. try_into ( ) . unwrap ( ) ,
46
+ num_channels. try_into ( ) . unwrap ( ) ,
47
+ queue_size_ms. try_into ( ) . unwrap ( ) ,
48
+ ) ;
49
+
50
+ let queue_size_samples = ( queue_size_ms * sample_rate / 1000 ) * num_channels;
51
+ Self { sys_handle, sample_rate, num_channels, queue_size_samples }
115
52
}
116
53
117
54
pub fn sys_handle ( & self ) -> SharedPtr < sys_at:: ffi:: AudioTrackSource > {
@@ -134,8 +71,8 @@ impl NativeAudioSource {
134
71
self . num_channels
135
72
}
136
73
137
- pub fn enable_queue ( & self ) -> bool {
138
- self . enable_queue
74
+ pub fn clear_buffer ( & self ) {
75
+ self . sys_handle . clear_buffer ( ) ;
139
76
}
140
77
141
78
pub async fn capture_frame ( & self , frame : & AudioFrame < ' _ > ) -> Result < ( ) , RtcError > {
@@ -146,38 +83,36 @@ impl NativeAudioSource {
146
83
} ) ;
147
84
}
148
85
149
- let mut inner = self . inner . lock ( ) . await ;
150
- let mut samples = 0 ;
151
- // split frames into 10ms chunks
152
- loop {
153
- let remaining_samples = frame. data . len ( ) - samples;
154
- if remaining_samples == 0 {
155
- break ;
156
- }
86
+ extern "C" fn lk_audio_source_complete ( userdata : * const sys_at:: SourceContext ) {
87
+ let tx = unsafe { Box :: from_raw ( userdata as * mut oneshot:: Sender < ( ) > ) } ;
88
+ let _ = tx. send ( ( ) ) ;
89
+ }
157
90
158
- if ( inner. len != 0 && remaining_samples > 0 ) || remaining_samples < self . samples_10ms {
159
- let missing_len = self . samples_10ms - inner. len ;
160
- let to_add = missing_len. min ( remaining_samples) ;
161
- let start = inner. len ;
162
- inner. buf [ start..start + to_add]
163
- . copy_from_slice ( & frame. data [ samples..samples + to_add] ) ;
164
- inner. len += to_add;
165
- samples += to_add;
166
-
167
- if inner. len == self . samples_10ms {
168
- let data = inner. buf . clone ( ) . to_vec ( ) ;
169
- let _ = self . po_tx . send ( data) . await ;
170
- inner. len = 0 ;
91
+ // iterate over chunks of self._queue_size_samples
92
+ for chunk in frame. data . chunks ( self . queue_size_samples as usize ) {
93
+ let nb_frames = chunk. len ( ) / self . num_channels as usize ;
94
+ let ( tx, rx) = oneshot:: channel :: < ( ) > ( ) ;
95
+ let ctx = Box :: new ( tx) ;
96
+ let ctx_ptr = Box :: into_raw ( ctx) as * const sys_at:: SourceContext ;
97
+
98
+ unsafe {
99
+ if !self . sys_handle . capture_frame (
100
+ chunk,
101
+ self . sample_rate ,
102
+ self . num_channels ,
103
+ nb_frames,
104
+ ctx_ptr,
105
+ sys_at:: CompleteCallback ( lk_audio_source_complete) ,
106
+ ) {
107
+ return Err ( RtcError {
108
+ error_type : RtcErrorType :: InvalidState ,
109
+ message : "failed to capture frame" . to_owned ( ) ,
110
+ } ) ;
171
111
}
172
- continue ;
173
112
}
174
113
175
- if remaining_samples >= self . samples_10ms {
176
- // TODO(theomonnom): avoid copying
177
- let data = frame. data [ samples..samples + self . samples_10ms ] . to_vec ( ) ;
178
- let _ = self . po_tx . send ( data) . await ;
179
- samples += self . samples_10ms ;
180
- }
114
+ let _ = rx. await ;
115
+ println ! ( "captured frame" ) ;
181
116
}
182
117
183
118
Ok ( ( ) )
0 commit comments