/src/mpv/audio/out/buffer.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * This file is part of mpv. |
3 | | * |
4 | | * mpv is free software; you can redistribute it and/or |
5 | | * modify it under the terms of the GNU Lesser General Public |
6 | | * License as published by the Free Software Foundation; either |
7 | | * version 2.1 of the License, or (at your option) any later version. |
8 | | * |
9 | | * mpv is distributed in the hope that it will be useful, |
10 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | | * GNU Lesser General Public License for more details. |
13 | | * |
14 | | * You should have received a copy of the GNU Lesser General Public |
15 | | * License along with mpv. If not, see <http://www.gnu.org/licenses/>. |
16 | | */ |
17 | | |
18 | | #include <stddef.h> |
19 | | #include <inttypes.h> |
20 | | #include <math.h> |
21 | | #include <errno.h> |
22 | | #include <assert.h> |
23 | | |
24 | | #include "ao.h" |
25 | | #include "internal.h" |
26 | | #include "audio/aframe.h" |
27 | | #include "audio/format.h" |
28 | | |
29 | | #include "common/msg.h" |
30 | | #include "common/common.h" |
31 | | |
32 | | #include "filters/f_async_queue.h" |
33 | | #include "filters/filter_internal.h" |
34 | | |
35 | | #include "osdep/timer.h" |
36 | | #include "osdep/threads.h" |
37 | | |
38 | | struct buffer_state { |
39 | | // Buffer and AO |
40 | | mp_mutex lock; |
41 | | mp_cond wakeup; |
42 | | |
43 | | // AO thread sleep |
44 | | mp_mutex pt_lock; |
45 | | mp_cond pt_wakeup; |
46 | | |
47 | | // Access from AO driver's thread only. |
48 | | char *convert_buffer; |
49 | | |
50 | | // Immutable. |
51 | | struct mp_async_queue *queue; |
52 | | |
53 | | // --- protected by lock |
54 | | |
55 | | struct mp_filter *filter_root; |
56 | | struct mp_filter *input; // connected to queue |
57 | | struct mp_aframe *pending; // last, not fully consumed output |
58 | | |
59 | | bool streaming; // AO streaming active |
60 | | bool playing; // logically playing audio from buffer |
61 | | bool paused; // logically paused |
62 | | bool hw_paused; // driver->set_pause() was used successfully |
63 | | |
64 | | int64_t end_time_ns; // absolute output time of last played sample |
65 | | int64_t queued_time_ns; // duration of samples that have been queued to |
66 | | // the device but have not been played. |
67 | | // This field is only set in ao_set_paused(), |
68 | | // and is considered as a temporary solution; |
69 | | // DO NOT USE IT IN OTHER PLACES. |
70 | | |
71 | | // "Push" AOs only (AOs with driver->write). |
72 | | bool recover_pause; // non-hw_paused: needs to recover delay |
73 | | struct mp_pcm_state prepause_state; |
74 | | mp_thread thread; // thread shoveling data to AO |
75 | | bool thread_valid; // thread is running |
76 | | struct mp_aframe *temp_buf; |
77 | | |
78 | | // --- protected by pt_lock |
79 | | bool need_wakeup; |
80 | | bool terminate; // exit thread |
81 | | }; |
82 | | |
83 | | static MP_THREAD_VOID ao_thread(void *arg); |
84 | | |
85 | | void ao_wakeup(struct ao *ao) |
86 | 3.20M | { |
87 | 3.20M | struct buffer_state *p = ao->buffer_state; |
88 | 3.20M | mp_mutex_lock(&p->pt_lock); |
89 | 3.20M | p->need_wakeup = true; |
90 | 3.20M | mp_cond_broadcast(&p->pt_wakeup); |
91 | 3.20M | mp_mutex_unlock(&p->pt_lock); |
92 | 3.20M | } |
93 | | |
94 | | // called locked |
95 | | static void get_dev_state(struct ao *ao, struct mp_pcm_state *state) |
96 | 6.47M | { |
97 | 6.47M | struct buffer_state *p = ao->buffer_state; |
98 | | |
99 | 6.47M | if (p->paused && p->playing && !ao->stream_silence) { |
100 | 0 | *state = p->prepause_state; |
101 | 0 | return; |
102 | 0 | } |
103 | | |
104 | 6.47M | *state = (struct mp_pcm_state){ |
105 | 6.47M | .free_samples = -1, |
106 | 6.47M | .queued_samples = -1, |
107 | 6.47M | .delay = -1, |
108 | 6.47M | }; |
109 | 6.47M | ao->driver->get_state(ao, state); |
110 | 6.47M | } |
111 | | |
112 | | struct mp_async_queue *ao_get_queue(struct ao *ao) |
113 | 29.1k | { |
114 | 29.1k | struct buffer_state *p = ao->buffer_state; |
115 | 29.1k | return p->queue; |
116 | 29.1k | } |
117 | | |
118 | | // Special behavior with data==NULL: caller uses p->pending. |
119 | | static int read_buffer(struct ao *ao, void **data, int samples, bool *eof, |
120 | | bool pad_silence) |
121 | 6.18M | { |
122 | 6.18M | struct buffer_state *p = ao->buffer_state; |
123 | 6.18M | int pos = 0; |
124 | 6.18M | *eof = false; |
125 | | |
126 | 10.4M | while (p->playing && !p->paused && pos < samples) { |
127 | 10.0M | if (!p->pending || !mp_aframe_get_size(p->pending)) { |
128 | 9.71M | TA_FREEP(&p->pending); |
129 | 9.71M | struct mp_frame frame = mp_pin_out_read(p->input->pins[0]); |
130 | 9.71M | if (!frame.type) |
131 | 5.83M | break; // we can't/don't want to block |
132 | 3.87M | if (frame.type != MP_FRAME_AUDIO) { |
133 | 24.7k | if (frame.type == MP_FRAME_EOF) |
134 | 24.7k | *eof = true; |
135 | 24.7k | mp_frame_unref(&frame); |
136 | 24.7k | continue; |
137 | 24.7k | } |
138 | 3.85M | p->pending = frame.data; |
139 | 3.85M | } |
140 | | |
141 | 4.19M | if (!data) |
142 | 0 | break; |
143 | | |
144 | 4.19M | int copy = mp_aframe_get_size(p->pending); |
145 | 4.19M | uint8_t **fdata = mp_aframe_get_data_ro(p->pending); |
146 | 4.19M | copy = MPMIN(copy, samples - pos); |
147 | 8.62M | for (int n = 0; n < ao->num_planes; n++) { |
148 | 4.43M | memcpy((char *)data[n] + pos * ao->sstride, |
149 | 4.43M | fdata[n], copy * ao->sstride); |
150 | 4.43M | } |
151 | 4.19M | mp_aframe_skip_samples(p->pending, copy); |
152 | 4.19M | pos += copy; |
153 | 4.19M | *eof = false; |
154 | 4.19M | } |
155 | | |
156 | 6.18M | if (!data) { |
157 | 0 | if (!p->pending) |
158 | 0 | return 0; |
159 | 0 | void **pd = (void *)mp_aframe_get_data_rw(p->pending); |
160 | 0 | if (pd) |
161 | 0 | ao_post_process_data(ao, pd, mp_aframe_get_size(p->pending)); |
162 | 0 | return 1; |
163 | 0 | } |
164 | | |
165 | | // pad with silence (underflow/paused/eof) |
166 | 6.18M | if (pad_silence) { |
167 | 12.6M | for (int n = 0; n < ao->num_planes; n++) { |
168 | 6.47M | af_fill_silence((char *)data[n] + pos * ao->sstride, |
169 | 6.47M | (samples - pos) * ao->sstride, |
170 | 6.47M | ao->format); |
171 | 6.47M | } |
172 | 6.18M | } |
173 | | |
174 | 6.18M | ao_post_process_data(ao, data, pos); |
175 | 6.18M | return pos; |
176 | 6.18M | } |
177 | | |
178 | | static int ao_read_data_locked(struct ao *ao, void **data, int samples, |
179 | | int64_t out_time_ns, bool *eof, bool pad_silence) |
180 | 0 | { |
181 | 0 | struct buffer_state *p = ao->buffer_state; |
182 | 0 | mp_assert(!ao->driver->write); |
183 | | |
184 | 0 | int pos = read_buffer(ao, data, samples, eof, pad_silence); |
185 | |
|
186 | 0 | if (pos > 0) |
187 | 0 | p->end_time_ns = out_time_ns; |
188 | |
|
189 | 0 | if (pos < samples && p->playing && !p->paused) { |
190 | 0 | p->playing = false; |
191 | 0 | ao->wakeup_cb(ao->wakeup_ctx); |
192 | | // For ao_drain(). |
193 | 0 | mp_cond_broadcast(&p->wakeup); |
194 | 0 | } |
195 | |
|
196 | 0 | return pos; |
197 | 0 | } |
198 | | |
199 | | // Read the given amount of samples in the user-provided data buffer. Returns |
200 | | // the number of samples copied. If there is not enough data (buffer underrun |
201 | | // or EOF), return the number of samples that could be copied, and fill the |
202 | | // rest of the user-provided buffer with silence. |
203 | | // This basically assumes that the audio device doesn't care about underruns. |
204 | | // If this is called in paused mode, it will always return 0. |
205 | | // The caller should set out_time_ns to the expected delay until the last sample |
206 | | // reaches the speakers, in nanoseconds, using mp_time_ns() as reference. |
207 | | int ao_read_data(struct ao *ao, void **data, int samples, int64_t out_time_ns, bool *eof, bool pad_silence, bool blocking) |
208 | 0 | { |
209 | 0 | struct buffer_state *p = ao->buffer_state; |
210 | |
|
211 | 0 | if (blocking) { |
212 | 0 | mp_mutex_lock(&p->lock); |
213 | 0 | } else if (mp_mutex_trylock(&p->lock)) { |
214 | 0 | return 0; |
215 | 0 | } |
216 | | |
217 | 0 | bool eof_buf; |
218 | 0 | if (eof == NULL) { |
219 | | // This is a public API. We want to reduce the cognitive burden of the caller. |
220 | 0 | eof = &eof_buf; |
221 | 0 | } |
222 | |
|
223 | 0 | int pos = ao_read_data_locked(ao, data, samples, out_time_ns, eof, pad_silence); |
224 | |
|
225 | 0 | mp_mutex_unlock(&p->lock); |
226 | |
|
227 | 0 | return pos; |
228 | 0 | } |
229 | | |
230 | | // Same as ao_read_data(), but convert data according to *fmt. |
231 | | // fmt->src_fmt and fmt->channels must be the same as the AO parameters. |
232 | | int ao_read_data_converted(struct ao *ao, struct ao_convert_fmt *fmt, |
233 | | void **data, int samples, int64_t out_time_ns) |
234 | 0 | { |
235 | 0 | struct buffer_state *p = ao->buffer_state; |
236 | 0 | void *ndata[MP_NUM_CHANNELS] = {0}; |
237 | |
|
238 | 0 | if (!ao_need_conversion(fmt)) |
239 | 0 | return ao_read_data(ao, data, samples, out_time_ns, NULL, true, true); |
240 | | |
241 | 0 | mp_assert(ao->format == fmt->src_fmt); |
242 | 0 | mp_assert(ao->channels.num == fmt->channels); |
243 | | |
244 | 0 | bool planar = af_fmt_is_planar(fmt->src_fmt); |
245 | 0 | int planes = planar ? fmt->channels : 1; |
246 | 0 | int plane_samples = samples * (planar ? 1: fmt->channels); |
247 | 0 | int src_plane_size = plane_samples * af_fmt_to_bytes(fmt->src_fmt); |
248 | 0 | int dst_plane_size = plane_samples * fmt->dst_bits / 8; |
249 | |
|
250 | 0 | int needed = src_plane_size * planes; |
251 | 0 | if (needed > talloc_get_size(p->convert_buffer) || !p->convert_buffer) { |
252 | 0 | talloc_free(p->convert_buffer); |
253 | 0 | p->convert_buffer = talloc_size(NULL, needed); |
254 | 0 | } |
255 | |
|
256 | 0 | for (int n = 0; n < planes; n++) |
257 | 0 | ndata[n] = p->convert_buffer + n * src_plane_size; |
258 | |
|
259 | 0 | int res = ao_read_data(ao, ndata, samples, out_time_ns, NULL, true, true); |
260 | |
|
261 | 0 | ao_convert_inplace(fmt, ndata, samples); |
262 | 0 | for (int n = 0; n < planes; n++) |
263 | 0 | memcpy(data[n], ndata[n], dst_plane_size); |
264 | |
|
265 | 0 | return res; |
266 | 0 | } |
267 | | |
268 | | // Called by pull-based AO to indicate the AO has stopped requesting more data, |
269 | | // usually when EOF is got from ao_read_data(). |
270 | | // After this function is called, the core will call ao->driver->start() again |
271 | | // when more audio data after EOF arrives. |
272 | | void ao_stop_streaming(struct ao *ao) |
273 | 0 | { |
274 | 0 | struct buffer_state *p = ao->buffer_state; |
275 | 0 | p->streaming = false; |
276 | 0 | } |
277 | | |
278 | | int ao_control(struct ao *ao, enum aocontrol cmd, void *arg) |
279 | 29.2k | { |
280 | 29.2k | struct buffer_state *p = ao->buffer_state; |
281 | 29.2k | int r = CONTROL_UNKNOWN; |
282 | 29.2k | if (ao->driver->control) { |
283 | | // Only need to lock in push mode. |
284 | 0 | if (ao->driver->write) |
285 | 0 | mp_mutex_lock(&p->lock); |
286 | |
|
287 | 0 | r = ao->driver->control(ao, cmd, arg); |
288 | |
|
289 | 0 | if (ao->driver->write) |
290 | 0 | mp_mutex_unlock(&p->lock); |
291 | 0 | } |
292 | 29.2k | return r; |
293 | 29.2k | } |
294 | | |
295 | | double ao_get_delay(struct ao *ao) |
296 | 284k | { |
297 | 284k | struct buffer_state *p = ao->buffer_state; |
298 | | |
299 | 284k | mp_mutex_lock(&p->lock); |
300 | | |
301 | 284k | double driver_delay; |
302 | 284k | if (ao->driver->write) { |
303 | 284k | struct mp_pcm_state state; |
304 | 284k | get_dev_state(ao, &state); |
305 | 284k | driver_delay = state.delay; |
306 | 284k | } else { |
307 | 0 | int64_t end = p->end_time_ns; |
308 | 0 | int64_t now = mp_time_ns(); |
309 | 0 | driver_delay = MPMAX(0, MP_TIME_NS_TO_S(end - now)); |
310 | 0 | } |
311 | | |
312 | 284k | int64_t pending = mp_async_queue_get_samples(p->queue); |
313 | 284k | if (p->pending) |
314 | 312 | pending += mp_aframe_get_size(p->pending); |
315 | | |
316 | 284k | mp_mutex_unlock(&p->lock); |
317 | 284k | return driver_delay + pending / (double)ao->samplerate; |
318 | 284k | } |
319 | | |
320 | | // Fully stop playback; clear buffers, including queue. |
321 | | void ao_reset(struct ao *ao) |
322 | 11.1k | { |
323 | 11.1k | struct buffer_state *p = ao->buffer_state; |
324 | 11.1k | bool wakeup = false; |
325 | 11.1k | bool do_reset = false; |
326 | | |
327 | 11.1k | mp_mutex_lock(&p->lock); |
328 | | |
329 | 11.1k | TA_FREEP(&p->pending); |
330 | 11.1k | mp_async_queue_reset(p->queue); |
331 | 11.1k | mp_filter_reset(p->filter_root); |
332 | 11.1k | mp_async_queue_resume_reading(p->queue); |
333 | | |
334 | 11.1k | if (!ao->stream_silence && ao->driver->reset) { |
335 | 11.1k | if (ao->driver->write) { |
336 | 11.1k | ao->driver->reset(ao); |
337 | 11.1k | } else { |
338 | | // Pull AOs may wait for ao_read_data() to return. |
339 | | // That would deadlock if called from within the lock. |
340 | 0 | do_reset = true; |
341 | 0 | } |
342 | 11.1k | p->streaming = false; |
343 | 11.1k | } |
344 | 11.1k | wakeup = p->playing; |
345 | 11.1k | p->playing = false; |
346 | 11.1k | p->recover_pause = false; |
347 | 11.1k | p->hw_paused = false; |
348 | 11.1k | p->end_time_ns = 0; |
349 | | |
350 | 11.1k | mp_mutex_unlock(&p->lock); |
351 | | |
352 | 11.1k | if (do_reset) |
353 | 0 | ao->driver->reset(ao); |
354 | | |
355 | 11.1k | if (wakeup) |
356 | 4.43k | ao_wakeup(ao); |
357 | 11.1k | } |
358 | | |
359 | | // Initiate playback. This moves from the stop/underrun state to actually |
360 | | // playing (orthogonally taking the paused state into account). Plays all |
361 | | // data in the queue, and goes into underrun state if no more data available. |
362 | | // No-op if already running. |
363 | | void ao_start(struct ao *ao) |
364 | 29.1k | { |
365 | 29.1k | struct buffer_state *p = ao->buffer_state; |
366 | 29.1k | bool do_start = false; |
367 | | |
368 | 29.1k | mp_mutex_lock(&p->lock); |
369 | | |
370 | 29.1k | p->playing = true; |
371 | | |
372 | 29.1k | if (!ao->driver->write && !p->paused && !p->streaming) { |
373 | 0 | p->streaming = true; |
374 | 0 | do_start = true; |
375 | 0 | } |
376 | | |
377 | 29.1k | mp_mutex_unlock(&p->lock); |
378 | | |
379 | | // Pull AOs might call ao_read_data() so do this outside the lock. |
380 | 29.1k | if (do_start) |
381 | 0 | ao->driver->start(ao); |
382 | | |
383 | 29.1k | ao_wakeup(ao); |
384 | 29.1k | } |
385 | | |
386 | | void ao_set_paused(struct ao *ao, bool paused, bool eof) |
387 | 29.1k | { |
388 | 29.1k | struct buffer_state *p = ao->buffer_state; |
389 | 29.1k | bool wakeup = false; |
390 | 29.1k | bool do_change_state = false; |
391 | 29.1k | bool is_hw_paused; |
392 | | |
393 | | // If we are going to pause on eof and ao is still playing, |
394 | | // be sure to drain the ao first for gapless. |
395 | 29.1k | if (eof && paused && ao_is_playing(ao)) |
396 | 0 | ao_drain(ao); |
397 | | |
398 | 29.1k | mp_mutex_lock(&p->lock); |
399 | | |
400 | 29.1k | if ((p->playing || !ao->driver->write) && !p->paused && paused) { |
401 | 0 | if (p->streaming && !ao->stream_silence) { |
402 | 0 | if (ao->driver->write) { |
403 | 0 | if (!p->recover_pause) |
404 | 0 | get_dev_state(ao, &p->prepause_state); |
405 | 0 | if (ao->driver->set_pause && ao->driver->set_pause(ao, true)) { |
406 | 0 | p->hw_paused = true; |
407 | 0 | } else { |
408 | 0 | ao->driver->reset(ao); |
409 | 0 | p->streaming = false; |
410 | 0 | p->recover_pause = !ao->untimed; |
411 | 0 | } |
412 | 0 | } else if (ao->driver->reset || ao->driver->set_pause) { |
413 | | // See ao_reset() why this is done outside of the lock. |
414 | 0 | do_change_state = true; |
415 | 0 | p->streaming = false; |
416 | 0 | is_hw_paused = p->hw_paused = !!ao->driver->set_pause; |
417 | 0 | } |
418 | 0 | } |
419 | 0 | wakeup = true; |
420 | 29.1k | } else if (p->playing && p->paused && !paused) { |
421 | 0 | if (ao->driver->write) { |
422 | 0 | if (p->hw_paused) |
423 | 0 | ao->driver->set_pause(ao, false); |
424 | 0 | p->hw_paused = false; |
425 | 0 | } else { |
426 | 0 | if (!p->streaming) |
427 | 0 | do_change_state = true; |
428 | 0 | p->streaming = true; |
429 | 0 | is_hw_paused = p->hw_paused; |
430 | 0 | p->hw_paused = false; |
431 | 0 | } |
432 | 0 | wakeup = true; |
433 | 0 | } |
434 | 29.1k | p->paused = paused; |
435 | | |
436 | 29.1k | mp_mutex_unlock(&p->lock); |
437 | | |
438 | 29.1k | if (do_change_state) { |
439 | 0 | if (is_hw_paused) { |
440 | 0 | if (paused) { |
441 | 0 | ao->driver->set_pause(ao, true); |
442 | 0 | p->queued_time_ns = p->end_time_ns - mp_time_ns(); |
443 | 0 | } else { |
444 | 0 | p->end_time_ns = p->queued_time_ns + mp_time_ns(); |
445 | 0 | ao->driver->set_pause(ao, false); |
446 | 0 | } |
447 | 0 | } else { |
448 | 0 | if (paused) |
449 | 0 | ao->driver->reset(ao); |
450 | 0 | else |
451 | 0 | ao->driver->start(ao); |
452 | 0 | } |
453 | 0 | } |
454 | | |
455 | 29.1k | if (wakeup) |
456 | 0 | ao_wakeup(ao); |
457 | 29.1k | } |
458 | | |
459 | | // Whether audio is playing. This means that there is still data in the buffers, |
460 | | // and ao_start() was called. This returns true even if playback was logically |
461 | | // paused. On false, EOF was reached, or an underrun happened, or ao_reset() |
462 | | // was called. |
463 | | bool ao_is_playing(struct ao *ao) |
464 | 1.04M | { |
465 | 1.04M | struct buffer_state *p = ao->buffer_state; |
466 | | |
467 | 1.04M | mp_mutex_lock(&p->lock); |
468 | 1.04M | bool playing = p->playing; |
469 | 1.04M | mp_mutex_unlock(&p->lock); |
470 | | |
471 | 1.04M | return playing; |
472 | 1.04M | } |
473 | | |
474 | | // Block until the current audio buffer has played completely. |
475 | | void ao_drain(struct ao *ao) |
476 | 4.33k | { |
477 | 4.33k | struct buffer_state *p = ao->buffer_state; |
478 | | |
479 | 4.33k | mp_mutex_lock(&p->lock); |
480 | 4.34k | while (!p->paused && p->playing) { |
481 | 4.33k | mp_mutex_unlock(&p->lock); |
482 | 4.33k | double delay = ao_get_delay(ao); |
483 | 4.33k | mp_mutex_lock(&p->lock); |
484 | | |
485 | | // Wait for buffer + arbitrary ~250ms for EOF signal from AO. |
486 | 4.33k | if (mp_cond_timedwait(&p->wakeup, &p->lock, |
487 | 4.33k | MP_TIME_S_TO_NS(MPMAX(delay, 0) + 0.25))) |
488 | 4.33k | { |
489 | 4.33k | MP_VERBOSE(ao, "drain timeout\n"); |
490 | 4.33k | break; |
491 | 4.33k | } |
492 | | |
493 | 7 | if (!p->playing && mp_async_queue_get_samples(p->queue)) { |
494 | 0 | MP_WARN(ao, "underrun during draining\n"); |
495 | 0 | mp_mutex_unlock(&p->lock); |
496 | 0 | ao_start(ao); |
497 | 0 | mp_mutex_lock(&p->lock); |
498 | 0 | } |
499 | 7 | } |
500 | 4.33k | mp_mutex_unlock(&p->lock); |
501 | | |
502 | 4.33k | ao_reset(ao); |
503 | 4.33k | } |
504 | | |
505 | | static void wakeup_filters(void *ctx) |
506 | 3.17M | { |
507 | 3.17M | struct ao *ao = ctx; |
508 | 3.17M | ao_wakeup(ao); |
509 | 3.17M | } |
510 | | |
511 | | void ao_uninit(struct ao *ao) |
512 | 29.2k | { |
513 | 29.2k | struct buffer_state *p = ao->buffer_state; |
514 | | |
515 | 29.2k | if (p && p->thread_valid) { |
516 | 29.1k | mp_mutex_lock(&p->pt_lock); |
517 | 29.1k | p->terminate = true; |
518 | 29.1k | mp_cond_broadcast(&p->pt_wakeup); |
519 | 29.1k | mp_mutex_unlock(&p->pt_lock); |
520 | | |
521 | 29.1k | mp_thread_join(p->thread); |
522 | 29.1k | p->thread_valid = false; |
523 | 29.1k | } |
524 | | |
525 | 29.2k | if (ao->driver_initialized) |
526 | 29.2k | ao->driver->uninit(ao); |
527 | | |
528 | 29.2k | if (p) { |
529 | 29.2k | talloc_free(p->filter_root); |
530 | 29.2k | talloc_free(p->queue); |
531 | 29.2k | talloc_free(p->pending); |
532 | 29.2k | talloc_free(p->convert_buffer); |
533 | 29.2k | talloc_free(p->temp_buf); |
534 | | |
535 | 29.2k | mp_cond_destroy(&p->wakeup); |
536 | 29.2k | mp_mutex_destroy(&p->lock); |
537 | | |
538 | 29.2k | mp_cond_destroy(&p->pt_wakeup); |
539 | 29.2k | mp_mutex_destroy(&p->pt_lock); |
540 | 29.2k | } |
541 | | |
542 | 29.2k | talloc_free(ao); |
543 | 29.2k | } |
544 | | |
545 | | void init_buffer_pre(struct ao *ao) |
546 | 29.2k | { |
547 | 29.2k | ao->buffer_state = talloc_zero(ao, struct buffer_state); |
548 | 29.2k | } |
549 | | |
550 | | bool init_buffer_post(struct ao *ao) |
551 | 29.1k | { |
552 | 29.1k | struct buffer_state *p = ao->buffer_state; |
553 | | |
554 | 29.1k | mp_assert(ao->driver->start); |
555 | 29.1k | if (ao->driver->write) { |
556 | 29.1k | mp_assert(ao->driver->reset); |
557 | 29.1k | mp_assert(ao->driver->get_state); |
558 | 29.1k | } |
559 | | |
560 | 29.1k | mp_mutex_init(&p->lock); |
561 | 29.1k | mp_cond_init(&p->wakeup); |
562 | | |
563 | 29.1k | mp_mutex_init(&p->pt_lock); |
564 | 29.1k | mp_cond_init(&p->pt_wakeup); |
565 | | |
566 | 29.1k | p->queue = mp_async_queue_create(); |
567 | 29.1k | p->filter_root = mp_filter_create_root(ao->global); |
568 | 29.1k | p->input = mp_async_queue_create_filter(p->filter_root, MP_PIN_OUT, p->queue); |
569 | | |
570 | 29.1k | mp_async_queue_resume_reading(p->queue); |
571 | | |
572 | 29.1k | struct mp_async_queue_config cfg = { |
573 | 29.1k | .sample_unit = AQUEUE_UNIT_SAMPLES, |
574 | 29.1k | .max_samples = ao->buffer, |
575 | 29.1k | .max_bytes = INT64_MAX, |
576 | 29.1k | }; |
577 | 29.1k | mp_async_queue_set_config(p->queue, cfg); |
578 | | |
579 | 29.1k | if (ao->driver->write) { |
580 | 29.1k | mp_filter_graph_set_wakeup_cb(p->filter_root, wakeup_filters, ao); |
581 | | |
582 | 29.1k | p->thread_valid = true; |
583 | 29.1k | if (mp_thread_create(&p->thread, ao_thread, ao)) { |
584 | 0 | p->thread_valid = false; |
585 | 0 | return false; |
586 | 0 | } |
587 | 29.1k | } else { |
588 | 0 | if (ao->stream_silence) { |
589 | 0 | ao->driver->start(ao); |
590 | 0 | p->streaming = true; |
591 | 0 | } |
592 | 0 | } |
593 | | |
594 | 29.1k | if (ao->stream_silence) { |
595 | 0 | MP_WARN(ao, "The --audio-stream-silence option is set. This will break " |
596 | 0 | "certain player behavior.\n"); |
597 | 0 | } |
598 | | |
599 | 29.1k | return true; |
600 | 29.1k | } |
601 | | |
602 | | static bool realloc_buf(struct ao *ao, int samples) |
603 | 6.18M | { |
604 | 6.18M | struct buffer_state *p = ao->buffer_state; |
605 | | |
606 | 6.18M | samples = MPMAX(1, samples); |
607 | | |
608 | 6.18M | if (!p->temp_buf || samples > mp_aframe_get_size(p->temp_buf)) { |
609 | 29.0k | TA_FREEP(&p->temp_buf); |
610 | 29.0k | p->temp_buf = mp_aframe_create(); |
611 | 29.0k | if (!mp_aframe_set_format(p->temp_buf, ao->format) || |
612 | 29.0k | !mp_aframe_set_chmap(p->temp_buf, &ao->channels) || |
613 | 29.0k | !mp_aframe_set_rate(p->temp_buf, ao->samplerate) || |
614 | 29.0k | !mp_aframe_alloc_data(p->temp_buf, samples)) |
615 | 497 | { |
616 | 497 | TA_FREEP(&p->temp_buf); |
617 | 497 | return false; |
618 | 497 | } |
619 | 29.0k | } |
620 | | |
621 | 6.18M | return true; |
622 | 6.18M | } |
623 | | |
624 | | // called locked |
625 | | static bool ao_play_data(struct ao *ao) |
626 | 6.27M | { |
627 | 6.27M | struct buffer_state *p = ao->buffer_state; |
628 | | |
629 | 6.27M | if ((!p->playing || p->paused) && !ao->stream_silence) |
630 | 88.6k | return false; |
631 | | |
632 | 6.18M | struct mp_pcm_state state; |
633 | 6.18M | get_dev_state(ao, &state); |
634 | | |
635 | 6.18M | if (p->streaming && !state.playing && !ao->untimed) |
636 | 0 | goto eof; |
637 | | |
638 | 6.18M | void **planes = NULL; |
639 | 6.18M | int space = state.free_samples; |
640 | 6.18M | if (!space) |
641 | 0 | return false; |
642 | 6.18M | mp_assert(space >= 0); |
643 | | |
644 | 6.18M | int samples = 0; |
645 | 6.18M | bool got_eof = false; |
646 | 6.18M | if (ao->driver->write_frames) { |
647 | 0 | TA_FREEP(&p->pending); |
648 | 0 | samples = read_buffer(ao, NULL, 1, &got_eof, false); |
649 | 0 | planes = (void **)&p->pending; |
650 | 6.18M | } else { |
651 | 6.18M | if (!realloc_buf(ao, space)) { |
652 | 497 | MP_ERR(ao, "Failed to allocate buffer.\n"); |
653 | 497 | return false; |
654 | 497 | } |
655 | 6.18M | planes = (void **)mp_aframe_get_data_rw(p->temp_buf); |
656 | 6.18M | mp_assert(planes); |
657 | | |
658 | 6.18M | if (p->recover_pause) { |
659 | 0 | samples = MPCLAMP(p->prepause_state.delay * ao->samplerate, 0, space); |
660 | 0 | p->recover_pause = false; |
661 | 0 | mp_aframe_set_silence(p->temp_buf, 0, space); |
662 | 0 | } |
663 | | |
664 | 6.18M | if (!samples) { |
665 | 6.18M | samples = read_buffer(ao, planes, space, &got_eof, true); |
666 | 6.18M | if (p->paused || (ao->stream_silence && !p->playing)) |
667 | 0 | samples = space; // read_buffer() sets remainder to silent |
668 | 6.18M | } |
669 | 6.18M | } |
670 | | |
671 | 6.18M | if (samples) { |
672 | 3.35M | MP_STATS(ao, "start ao fill"); |
673 | 3.35M | if (!ao->driver->write(ao, planes, samples)) |
674 | 3.35M | MP_ERR(ao, "Error writing audio to device.\n"); |
675 | 3.35M | MP_STATS(ao, "end ao fill"); |
676 | | |
677 | 3.35M | if (!p->streaming) { |
678 | 28.4k | MP_VERBOSE(ao, "starting AO\n"); |
679 | 28.4k | ao->driver->start(ao); |
680 | 28.4k | p->streaming = true; |
681 | 28.4k | state.playing = true; |
682 | 28.4k | } |
683 | 3.35M | } |
684 | | |
685 | 6.18M | MP_TRACE(ao, "in=%d space=%d(%d) pl=%d, eof=%d\n", |
686 | 6.18M | samples, space, state.free_samples, p->playing, got_eof); |
687 | | |
688 | 6.18M | if (got_eof) |
689 | 24.7k | goto eof; |
690 | | |
691 | 6.16M | return samples > 0 && (samples < space || ao->untimed); |
692 | | |
693 | 24.7k | eof: |
694 | 24.7k | MP_VERBOSE(ao, "audio end or underrun\n"); |
695 | | // Normal AOs signal EOF on underrun, untimed AOs never signal underruns. |
696 | 24.7k | if (ao->untimed || !state.playing || ao->stream_silence) { |
697 | 24.7k | p->streaming = state.playing && !ao->untimed; |
698 | 24.7k | p->playing = false; |
699 | 24.7k | } |
700 | 24.7k | ao->wakeup_cb(ao->wakeup_ctx); |
701 | | // For ao_drain(). |
702 | 24.7k | mp_cond_broadcast(&p->wakeup); |
703 | 24.7k | return true; |
704 | 6.18M | } |
705 | | |
706 | | static MP_THREAD_VOID ao_thread(void *arg) |
707 | 29.1k | { |
708 | 29.1k | struct ao *ao = arg; |
709 | 29.1k | struct buffer_state *p = ao->buffer_state; |
710 | 29.1k | mp_thread_set_name("ao"); |
711 | 6.27M | while (1) { |
712 | 6.27M | mp_mutex_lock(&p->lock); |
713 | | |
714 | 6.27M | bool retry = ao_play_data(ao); |
715 | | |
716 | | // Wait until the device wants us to write more data to it. |
717 | | // Fallback to guessing. |
718 | 6.27M | int64_t timeout = INT64_MAX; |
719 | 6.27M | if (p->streaming && !retry && (!p->paused || ao->stream_silence)) { |
720 | | // Wake up again if half of the audio buffer has been played. |
721 | | // Since audio could play at a faster or slower pace, wake up twice |
722 | | // as often as ideally needed. |
723 | 2.82M | timeout = MP_TIME_S_TO_NS(ao->device_buffer / (double)ao->samplerate * 0.25); |
724 | 2.82M | } |
725 | | |
726 | 6.27M | mp_mutex_unlock(&p->lock); |
727 | | |
728 | 6.27M | mp_mutex_lock(&p->pt_lock); |
729 | 6.27M | if (p->terminate) { |
730 | 29.1k | mp_mutex_unlock(&p->pt_lock); |
731 | 29.1k | break; |
732 | 29.1k | } |
733 | 6.24M | if (!p->need_wakeup && !retry) { |
734 | 2.74M | MP_STATS(ao, "start audio wait"); |
735 | 2.74M | mp_cond_timedwait(&p->pt_wakeup, &p->pt_lock, timeout); |
736 | 2.74M | MP_STATS(ao, "end audio wait"); |
737 | 2.74M | } |
738 | 6.24M | p->need_wakeup = false; |
739 | 6.24M | mp_mutex_unlock(&p->pt_lock); |
740 | 6.24M | } |
741 | 29.1k | MP_THREAD_RETURN(); |
742 | 29.1k | } |