@@ -168,6 +168,67 @@ static void s16_to_sink(struct sof_sink *dst, int16_t src[][WEBRTC_AEC_FIFO_FRAM
168168 sink_commit_buffer (dst , nbytes );
169169}
170170
171+ static void src_drop_frames (struct sof_source * src , int frames )
172+ {
173+ size_t frame_bytes = source_get_frame_bytes (src );
174+ const void * data_ptr , * buf_start ;
175+ size_t buf_size , nbytes ;
176+
177+ if (frames <= 0 || !frame_bytes )
178+ return ;
179+
180+ nbytes = (size_t )frames * frame_bytes ;
181+ if (!source_get_data (src , nbytes , & data_ptr , & buf_start , & buf_size ))
182+ source_release_data (src , nbytes );
183+ }
184+
185+ static void webrtc_aec_resolve_sources (struct sof_source * * sources , int num_of_sources ,
186+ struct sof_sink * * sinks , int num_of_sinks ,
187+ int * mic_idx , int * ref_idx )
188+ {
189+ * mic_idx = 0 ;
190+ * ref_idx = -1 ;
191+
192+ if (num_of_sources <= 1 )
193+ return ;
194+
195+ #ifdef CONFIG_IPC_MAJOR_4
196+ {
197+ uint32_t q0 = IPC4_SINK_QUEUE_ID (source_get_id (sources [0 ]));
198+ uint32_t q1 = IPC4_SINK_QUEUE_ID (source_get_id (sources [1 ]));
199+
200+ if (q0 != q1 ) {
201+ if (q0 == 0 ) {
202+ * mic_idx = 0 ;
203+ * ref_idx = 1 ;
204+ } else {
205+ * mic_idx = 1 ;
206+ * ref_idx = 0 ;
207+ }
208+ return ;
209+ }
210+ }
211+ #endif
212+
213+ if (num_of_sinks > 0 ) {
214+ if (source_get_pipeline_id (sources [0 ]) == sink_get_pipeline_id (sinks [0 ]) &&
215+ source_get_pipeline_id (sources [1 ]) != sink_get_pipeline_id (sinks [0 ])) {
216+ * mic_idx = 0 ;
217+ * ref_idx = 1 ;
218+ return ;
219+ }
220+ if (source_get_pipeline_id (sources [1 ]) == sink_get_pipeline_id (sinks [0 ]) &&
221+ source_get_pipeline_id (sources [0 ]) != sink_get_pipeline_id (sinks [0 ])) {
222+ * mic_idx = 1 ;
223+ * ref_idx = 0 ;
224+ return ;
225+ }
226+ }
227+
228+ * mic_idx = 0 ;
229+ * ref_idx = 1 ;
230+ }
231+
171232/* ----------------------------------------------------------------
172233 * module_interface operations
173234 * ---------------------------------------------------------------- */
@@ -226,21 +287,8 @@ __cold static int webrtc_aec_prepare(struct processing_module *mod,
226287 return - EINVAL ;
227288 }
228289
229- if (num_of_sources == 1 ) {
230- cd -> mic_src = 0 ;
231- cd -> ref_src = -1 ;
232- } else if (source_get_pipeline_id (sources [0 ]) == sink_get_pipeline_id (sinks [0 ]) &&
233- source_get_pipeline_id (sources [1 ]) != sink_get_pipeline_id (sinks [0 ])) {
234- cd -> mic_src = 0 ;
235- cd -> ref_src = 1 ;
236- } else if (source_get_pipeline_id (sources [1 ]) == sink_get_pipeline_id (sinks [0 ]) &&
237- source_get_pipeline_id (sources [0 ]) != sink_get_pipeline_id (sinks [0 ])) {
238- cd -> mic_src = 1 ;
239- cd -> ref_src = 0 ;
240- } else {
241- cd -> mic_src = 0 ;
242- cd -> ref_src = 1 ;
243- }
290+ webrtc_aec_resolve_sources (sources , num_of_sources , sinks , num_of_sinks ,
291+ & cd -> mic_src , & cd -> ref_src );
244292
245293 mic_fmt = source_get_frm_fmt (sources [cd -> mic_src ]);
246294 mic_rate = source_get_rate (sources [cd -> mic_src ]);
@@ -344,29 +392,52 @@ static int webrtc_aec_process(struct processing_module *mod,
344392 struct sof_sink * * sinks , int num_of_sinks )
345393{
346394 struct webrtc_aec_comp_data * cd = module_get_private_data (mod );
347- struct sof_source * mic = sources [ cd -> mic_src ] ;
348- struct sof_source * ref = cd -> ref_src >= 0 ? sources [ cd -> ref_src ] : NULL ;
349- struct sof_sink * out = sinks [ 0 ] ;
350- int fmic = ( int ) source_get_data_frames_available ( mic ) ;
351- int fref = ref ? ( int ) source_get_data_frames_available ( ref ) : 0 ;
352- int n , drain , c ;
353-
354- if (fmic <= 0 )
395+ struct sof_source * mic ;
396+ struct sof_source * ref ;
397+ struct sof_sink * out ;
398+ int mic_idx , ref_idx ;
399+ int fmic , fref , n , drain , c ;
400+ bool ref_s32 ;
401+
402+ if (num_of_sources < 1 || num_of_sinks < 1 )
355403 return 0 ;
356404
357- /* Cap to available space in input accumulation buffers */
405+ webrtc_aec_resolve_sources (sources , num_of_sources , sinks , num_of_sinks ,
406+ & mic_idx , & ref_idx );
407+ cd -> mic_src = mic_idx ;
408+ cd -> ref_src = ref_idx ;
409+
410+ mic = sources [mic_idx ];
411+ ref = ref_idx >= 0 ? sources [ref_idx ] : NULL ;
412+ out = sinks [0 ];
413+ fmic = (int )source_get_data_frames_available (mic );
414+ fref = ref ? (int )source_get_data_frames_available (ref ) : 0 ;
415+
416+ /* Cap to available space in input accumulation and output sink buffers */
358417 n = MIN (fmic , WEBRTC_AEC_FIFO_FRAMES - cd -> buffered_in_frames );
359- if (n <= 0 )
418+ n = MIN (n , (int )sink_get_free_frames (out ));
419+ if (n <= 0 ) {
420+ if (ref && fref > 0 ) {
421+ size_t fb = source_get_frame_bytes (ref );
422+ int keep = fb ? (int )(source_get_min_available (ref ) / fb ) : 0 ;
423+
424+ if (fref > keep )
425+ src_drop_frames (ref , fref - keep );
426+ }
360427 return 0 ;
428+ }
361429
362430 /* Convert mic input to per-channel S16 */
363431 src_to_s16 (mic , n , cd -> mic_buf , cd -> buffered_in_frames , cd -> channels , cd -> is_s32 );
364432
365433 /* Convert ref input to per-channel S16; if starved/silent, fill with silence */
434+ ref_s32 = ref ? (source_get_frm_fmt (ref ) == SOF_IPC_FRAME_S32_LE ) : cd -> is_s32 ;
366435 if (fref >= n ) {
367- src_to_s16 (ref , n , cd -> ref_buf , cd -> buffered_in_frames , cd -> channels , cd -> is_s32 );
436+ if (fref > n )
437+ src_drop_frames (ref , fref - n );
438+ src_to_s16 (ref , n , cd -> ref_buf , cd -> buffered_in_frames , cd -> channels , ref_s32 );
368439 } else if (fref > 0 ) {
369- src_to_s16 (ref , fref , cd -> ref_buf , cd -> buffered_in_frames , cd -> channels , cd -> is_s32 );
440+ src_to_s16 (ref , fref , cd -> ref_buf , cd -> buffered_in_frames , cd -> channels , ref_s32 );
370441 for (c = 0 ; c < cd -> channels ; c ++ )
371442 memset (& cd -> ref_buf [c ][cd -> buffered_in_frames + fref ], 0 ,
372443 (size_t )(n - fref ) * sizeof (int16_t ));
@@ -649,17 +720,27 @@ static bool webrtc_aec_is_ready_to_process(struct processing_module *mod,
649720 int num_of_sinks )
650721{
651722 struct webrtc_aec_comp_data * cd = module_get_private_data (mod );
652- struct sof_source * mic ;
723+ struct sof_source * mic , * ref ;
653724 struct sof_sink * out ;
725+ int mic_idx , ref_idx ;
654726
655- if (!cd || !cd -> configured || num_of_sources <= cd -> mic_src || num_of_sinks < 1 )
727+ if (!cd || !cd -> configured || num_of_sources < 1 || num_of_sinks < 1 )
656728 return false;
657729
658- mic = sources [cd -> mic_src ];
730+ webrtc_aec_resolve_sources (sources , num_of_sources , sinks , num_of_sinks ,
731+ & mic_idx , & ref_idx );
732+ mic = sources [mic_idx ];
733+ ref = ref_idx >= 0 ? sources [ref_idx ] : NULL ;
659734 out = sinks [0 ];
660735
661- return source_get_data_available (mic ) >= source_get_min_available (mic ) &&
662- sink_get_free_size (out ) >= sink_get_min_free_space (out );
736+ if (source_get_data_available (mic ) >= source_get_min_available (mic ) &&
737+ sink_get_free_size (out ) >= sink_get_min_free_space (out ))
738+ return true;
739+
740+ if (ref && source_get_data_available (ref ) >= 2 * source_get_min_available (ref ))
741+ return true;
742+
743+ return false;
663744}
664745
665746static const struct module_interface webrtc_aec_interface = {
0 commit comments