28
28
29
29
#include < libaudcore/i18n.h>
30
30
#include < libaudcore/plugin.h>
31
+ #include < libaudcore/ringbuf.h>
31
32
#include < libaudcore/runtime.h>
32
33
33
34
#if !PW_CHECK_VERSION(0, 3, 33)
@@ -103,8 +104,9 @@ class PipeWireOutput : public OutputPlugin
103
104
int m_aud_format = 0 ;
104
105
int m_core_init_seq = 0 ;
105
106
106
- unsigned char * m_buffer = nullptr ;
107
- unsigned int m_buffer_at = 0 ;
107
+ timespec m_time {};
108
+
109
+ RingBuf<unsigned char > m_buffer;
108
110
unsigned int m_buffer_size = 0 ;
109
111
unsigned int m_frames = 0 ;
110
112
unsigned int m_stride = 0 ;
@@ -159,36 +161,61 @@ void PipeWireOutput::pause(bool pause)
159
161
{
160
162
pw_thread_loop_lock (m_loop);
161
163
pw_stream_set_active (m_stream, !pause );
164
+ clock_gettime (CLOCK_REALTIME, &m_time);
162
165
pw_thread_loop_unlock (m_loop);
163
166
}
164
167
165
168
int PipeWireOutput::get_delay ()
166
169
{
167
- return (m_buffer_at / m_stride + m_frames) * 1000 / m_rate;
170
+ int buff_time = (((m_buffer.len () + m_buffer_size) / m_stride) * 1000 ) / m_rate;
171
+
172
+ // Get time difference from last buffer fill
173
+ timespec time_now {};
174
+ clock_gettime (CLOCK_REALTIME, &time_now);
175
+
176
+ int time_diff =
177
+ (((time_now.tv_sec - m_time.tv_sec ) * 1000000000 ) +
178
+ (time_now.tv_nsec - m_time.tv_nsec )) / 1000000 ;
179
+
180
+ if (time_diff < 0 )
181
+ time_diff = 0 ;
182
+ if (time_diff > buff_time)
183
+ time_diff = buff_time;
184
+
185
+ return buff_time - time_diff;
168
186
}
169
187
170
188
void PipeWireOutput::drain ()
171
189
{
172
190
pw_thread_loop_lock (m_loop);
173
- if (m_buffer_at > 0 )
174
- pw_thread_loop_timed_wait (m_loop, 2 );
191
+
192
+ int buflen;
193
+ while ((buflen = m_buffer.len ()) > 0 )
194
+ {
195
+ pw_thread_loop_timed_wait (m_loop, 1 );
196
+ if (buflen <= m_buffer.len ())
197
+ {
198
+ AUDERR (" PipeWireOutput: buffer drain lock\n " );
199
+ break ;
200
+ }
201
+ }
175
202
176
203
pw_stream_flush (m_stream, true );
177
- pw_thread_loop_timed_wait (m_loop, 2 );
204
+ pw_thread_loop_timed_wait (m_loop, 1 );
178
205
pw_thread_loop_unlock (m_loop);
179
206
}
180
207
181
208
void PipeWireOutput::flush ()
182
209
{
183
210
pw_thread_loop_lock (m_loop);
184
- m_buffer_at = 0 ;
211
+ m_buffer. discard () ;
185
212
pw_thread_loop_unlock (m_loop);
186
213
pw_stream_flush (m_stream, false );
187
214
}
188
215
189
216
void PipeWireOutput::period_wait ()
190
217
{
191
- if (m_buffer_at != m_buffer_size )
218
+ if (m_buffer. space () )
192
219
return ;
193
220
194
221
pw_thread_loop_lock (m_loop);
@@ -200,12 +227,11 @@ int PipeWireOutput::write_audio(const void * data, int length)
200
227
{
201
228
pw_thread_loop_lock (m_loop);
202
229
203
- auto size = aud::min<size_t >(m_buffer_size - m_buffer_at, length);
204
- memcpy (m_buffer + m_buffer_at, data, size);
205
- m_buffer_at += size;
230
+ length = aud::min (length, m_buffer.space ());
231
+ m_buffer.copy_in (static_cast <const unsigned char *>(data), length);
206
232
207
233
pw_thread_loop_unlock (m_loop);
208
- return size ;
234
+ return length ;
209
235
}
210
236
211
237
void PipeWireOutput::close_audio ()
@@ -248,11 +274,7 @@ void PipeWireOutput::close_audio()
248
274
m_loop = nullptr ;
249
275
}
250
276
251
- if (m_buffer)
252
- {
253
- delete[] m_buffer;
254
- m_buffer = nullptr ;
255
- }
277
+ m_buffer.destroy ();
256
278
}
257
279
258
280
bool PipeWireOutput::open_audio (int format, int rate, int channels, String & error)
@@ -267,6 +289,7 @@ bool PipeWireOutput::open_audio(int format, int rate, int channels, String & err
267
289
return false ;
268
290
}
269
291
292
+ clock_gettime (CLOCK_REALTIME, &m_time);
270
293
return true ;
271
294
}
272
295
@@ -343,10 +366,9 @@ bool PipeWireOutput::init_core()
343
366
return false ;
344
367
}
345
368
369
+ m_frames = aud_get_int (" output_buffer_size" ) * m_rate / 1000 ;
346
370
m_stride = FMT_SIZEOF (m_aud_format) * m_channels;
347
- m_frames = aud::clamp<int >(64 , ceilf (2048 * m_rate / 48000 .0f ), 8192 );
348
- m_buffer_size = m_frames * m_stride;
349
- m_buffer = new unsigned char [m_buffer_size];
371
+ m_buffer.alloc (m_frames * m_stride);
350
372
351
373
return true ;
352
374
}
@@ -490,7 +512,9 @@ void PipeWireOutput::on_process(void * data)
490
512
struct spa_buffer * buf;
491
513
void * dst;
492
514
493
- if (!o->m_buffer_at )
515
+ clock_gettime (CLOCK_REALTIME, &o->m_time );
516
+
517
+ if (!o->m_buffer .len ())
494
518
{
495
519
pw_thread_loop_signal (o->m_loop , false );
496
520
return ;
@@ -510,13 +534,12 @@ void PipeWireOutput::on_process(void * data)
510
534
return ;
511
535
}
512
536
513
- auto size = aud::min<uint32_t >(buf->datas [0 ].maxsize , o->m_buffer_at );
514
- memcpy (dst, o->m_buffer , size);
515
- o->m_buffer_at -= size;
516
- memmove (o->m_buffer , o->m_buffer + size, o->m_buffer_at );
537
+ auto size = aud::min<uint32_t >(buf->datas [0 ].maxsize , o->m_buffer .len ());
538
+ o->m_buffer_size = size;
539
+ o->m_buffer .move_out (static_cast <unsigned char *>(dst), size);
517
540
518
541
b->buffer ->datas [0 ].chunk ->offset = 0 ;
519
- b->buffer ->datas [0 ].chunk ->size = o-> m_buffer_size ;
542
+ b->buffer ->datas [0 ].chunk ->size = size ;
520
543
b->buffer ->datas [0 ].chunk ->stride = o->m_stride ;
521
544
522
545
pw_stream_queue_buffer (o->m_stream , b);
@@ -570,15 +593,18 @@ void PipeWireOutput::set_channel_map(struct spa_audio_info_raw * info, int chann
570
593
info->position [8 ] = SPA_AUDIO_CHANNEL_RC;
571
594
// Fall through
572
595
case 8 :
596
+ case 7 :
573
597
info->position [6 ] = SPA_AUDIO_CHANNEL_FLC;
574
598
info->position [7 ] = SPA_AUDIO_CHANNEL_FRC;
575
599
// Fall through
576
600
case 6 :
601
+ case 5 :
577
602
info->position [4 ] = SPA_AUDIO_CHANNEL_RL;
578
603
info->position [5 ] = SPA_AUDIO_CHANNEL_RR;
579
604
// Fall through
580
605
case 4 :
581
- info->position [3 ] = SPA_AUDIO_CHANNEL_LFE;
606
+ if (channels != 5 && channels != 7 )
607
+ info->position [3 ] = SPA_AUDIO_CHANNEL_LFE;
582
608
// Fall through
583
609
case 3 :
584
610
info->position [2 ] = SPA_AUDIO_CHANNEL_FC;
0 commit comments