1 STATIC
void fatal(u8
*fmt
, ...)
8 va_end(ap
); /* unreachable */
10 STATIC
void warning(u8
*fmt
, ...)
16 npv_vwarning(fmt
, ap
);
19 STATIC
void pout(u8
*fmt
, ...)
28 STATIC
bool ff_fmt2pcm_layout_best_effort(enum avutil_audio_fr_fmt_t ff_fmt
,
29 snd_pcm_fmt_t
*alsa_fmt
, snd_pcm_access_t
*alsa_access
)
31 static u8 ff_fmt_str
[STR_SZ
];
33 avutil_get_audio_fr_fmt_str(ff_fmt_str
, STR_SZ
, ff_fmt
);
34 /* XXX: only classic non-mmap ones */
36 case AVUTIL_AUDIO_FR_FMT_U8
:
37 *alsa_fmt
= SND_PCM_FMT_U8
;
38 *alsa_access
= SND_PCM_ACCESS_RW_INTERLEAVED
;
40 case AVUTIL_AUDIO_FR_FMT_S16
:
41 *alsa_fmt
= SND_PCM_FMT_S16
;
42 *alsa_access
= SND_PCM_ACCESS_RW_INTERLEAVED
;
44 case AVUTIL_AUDIO_FR_FMT_S32
:
45 *alsa_fmt
= SND_PCM_FMT_S32
;
46 *alsa_access
= SND_PCM_ACCESS_RW_INTERLEAVED
;
48 case AVUTIL_AUDIO_FR_FMT_FLT
:
49 *alsa_fmt
= SND_PCM_FMT_FLOAT
;
50 *alsa_access
= SND_PCM_ACCESS_RW_INTERLEAVED
;
52 /* ff "planar" fmts are actually non interleaved fmts */
53 case AVUTIL_AUDIO_FR_FMT_U8P
:
54 *alsa_fmt
= SND_PCM_FMT_U8
;
55 *alsa_access
= SND_PCM_ACCESS_RW_NONINTERLEAVED
;
57 case AVUTIL_AUDIO_FR_FMT_S16P
:
58 *alsa_fmt
= SND_PCM_FMT_S16
;
59 *alsa_access
= SND_PCM_ACCESS_RW_NONINTERLEAVED
;
61 case AVUTIL_AUDIO_FR_FMT_S32P
:
62 *alsa_fmt
= SND_PCM_FMT_S32
;
63 *alsa_access
= SND_PCM_ACCESS_RW_NONINTERLEAVED
;
65 case AVUTIL_AUDIO_FR_FMT_FLTP
:
66 *alsa_fmt
= SND_PCM_FMT_FLOAT
;
67 *alsa_access
= SND_PCM_ACCESS_RW_NONINTERLEAVED
;
70 pout("best effort:unable to wire ffmpeg sample format \"%sbits\" to alsa sample format, \n,", ff_fmt_str
);
73 pout("best effort:ffmpeg format \"%sbits\" (%u bytes) to alsa layout \"%s\" and access \"%s\"\n", ff_fmt_str
, av_get_bytes_per_sample(ff_fmt
), snd_pcm_fmt_desc(*alsa_fmt
), snd_pcm_access_name(*alsa_access
));
76 STATIC
void pcm_hw_chans_n_decide(snd_pcm_t
*pcm
,
77 snd_pcm_hw_params_t
*pcm_hw_params
, unsigned int chans_n
)
80 unsigned int chans_n_max
;
81 unsigned int chans_n_min
;
83 r
= snd_pcm_hw_params_test_chans_n(pcm
, pcm_hw_params
, chans_n
);
85 r
= snd_pcm_hw_params_set_chans_n(pcm
, pcm_hw_params
, chans_n
);
87 fatal("alsa:unable to restrict pcm device to %u channels, count which was successfully tested\n", chans_n
);
88 pout("alsa:using %u channels\n", chans_n
);
91 pout("alsa:unable to use %u channels\n", chans_n
);
92 /* try to use the max chans n the pcm can */
93 r
= snd_pcm_hw_params_get_chans_n_max(pcm_hw_params
, &chans_n_max
);
95 fatal("alsa:unable to get the maximum count of pcm device channels\n");
96 r
= snd_pcm_hw_params_test_chans_n(pcm
, pcm_hw_params
, chans_n_max
);
98 r
= snd_pcm_hw_params_set_chans_n(pcm
, pcm_hw_params
,
101 fatal("alsa:unable to restrict pcm device to %u channels, count which was successfully tested\n", chans_n_max
);
102 pout("alsa:using pcm maximum %u channels\n", chans_n_max
);
105 /* ok... last try, the pcm dev min chans n */
106 r
= snd_pcm_hw_params_get_chans_n_min(pcm_hw_params
, &chans_n_min
);
108 fatal("alsa:unable to get the minimum count of pcm device channels\n");
109 r
= snd_pcm_hw_params_test_chans_n(pcm
, pcm_hw_params
, chans_n_min
);
111 r
= snd_pcm_hw_params_set_chans_n(pcm
, pcm_hw_params
,
114 fatal("alsa:unable to restrict pcm device to %u channels, count which was successfully tested\n", chans_n_min
);
115 pout("alsa:using pcm device minimum %u channels\n", chans_n_min
);
118 fatal("alsa:unable to find a suitable count of channels\n");
120 STATIC
void pcm_hw_rate_decide(snd_pcm_t
*pcm
,
121 snd_pcm_hw_params_t
*pcm_hw_params
, unsigned int rate
)
124 unsigned int rate_max
;
125 unsigned int rate_near
;
126 unsigned int rate_min
;
128 r
= snd_pcm_hw_params_test_rate(pcm
, pcm_hw_params
, rate
,
129 SND_PCM_ST_PLAYBACK
);
131 r
= snd_pcm_hw_params_set_rate(pcm
, pcm_hw_params
, rate
,
132 SND_PCM_ST_PLAYBACK
);
134 fatal("alsa:unable to restrict pcm device to %uHz, which was successfully tested\n", rate
);
135 pout("alsa:using %uHz\n", rate
);
138 pout("alsa:unable to use %uHz\n", rate
);
139 /* try to use the max rate the pcm can */
140 r
= snd_pcm_hw_params_get_rate_max(pcm_hw_params
, &rate_max
,
141 SND_PCM_ST_PLAYBACK
);
143 fatal("alsa:unable to get the maximum rate of pcm device\n");
144 r
= snd_pcm_hw_params_test_rate(pcm
, pcm_hw_params
, rate_max
,
145 SND_PCM_ST_PLAYBACK
);
147 r
= snd_pcm_hw_params_set_rate(pcm
, pcm_hw_params
, rate_max
,
148 SND_PCM_ST_PLAYBACK
);
150 fatal("alsa:unable to restrict pcm device to %uHz, which was successfully tested\n", rate_max
);
151 pout("alsa:using pcm device %uHz\n", rate_max
);
154 /* try to use a rate "near" of what the pcm dev can */
156 r
= snd_pcm_hw_params_set_rate_near(pcm
, pcm_hw_params
, &rate_near
,
157 SND_PCM_ST_PLAYBACK
);
159 pout("alsa:using pcm device %uHz\n", rate_near
);
162 /* even a "near" rate did failed... try the min */
163 r
= snd_pcm_hw_params_get_rate_min(pcm_hw_params
, &rate_min
,
164 SND_PCM_ST_PLAYBACK
);
166 fatal("alsa:unable to get the minimum rate of pcm device\n");
167 r
= snd_pcm_hw_params_test_rate(pcm
, pcm_hw_params
, rate_min
,
168 SND_PCM_ST_PLAYBACK
);
170 r
= snd_pcm_hw_params_set_rate(pcm
, pcm_hw_params
, rate_min
,
171 SND_PCM_ST_PLAYBACK
);
173 fatal("alsa:unable to restrict pcm device to %uHz, which was successfully tested\n", rate_min
);
174 pout("alsa:using pcm device %uHz\n", rate_min
);
177 fatal("alsa:unable to find a suitable rate\n");
179 STATIC
bool pcm_hw_fmt_decide_x(snd_pcm_t
*pcm
,
180 snd_pcm_hw_params_t
*pcm_hw_params
, snd_pcm_fmt_t fmt
)
184 r
= snd_pcm_hw_params_test_fmt(pcm
, pcm_hw_params
, fmt
);
187 r
= snd_pcm_hw_params_set_fmt(pcm
, pcm_hw_params
, fmt
);
189 fatal("alsa:unable to restrict pcm device to \"%s\", which was successfully tested\n", snd_pcm_fmt_desc(fmt
));
190 pout("alsa:using \"%s\" format\n", snd_pcm_fmt_desc(fmt
));
193 #define PCM_HW_FMT_DECIDE_X(fmt) pcm_hw_fmt_decide_x(pcm, pcm_hw_params, fmt)
194 STATIC
void pcm_hw_fmt_decide(snd_pcm_t
*pcm
,
195 snd_pcm_hw_params_t
*pcm_hw_params
, bool force
,
196 snd_pcm_fmt_t forced_fmt
)
202 r
= snd_pcm_hw_params_test_fmt(pcm
, pcm_hw_params
, forced_fmt
);
204 r
= snd_pcm_hw_params_set_fmt(pcm
, pcm_hw_params
,
207 fatal("alsa:unable to restrict pcm device to \"%s\", which was successfully tested\n", snd_pcm_fmt_desc(forced_fmt
));
208 pout("alsa:using forced \"%s\" format\n", snd_pcm_fmt_desc(forced_fmt
));
212 /* then we try to select from the reasonable "best" to the lowest */
213 /* prefer fmts we know supported by ff */
214 if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_FLOAT
))
216 if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_S32
))
218 if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_S16
))
220 if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_U8
))
223 * from here, at the time of writting, those fmts have no ff
224 * wiring, but we are alsa centric here, validate that later
226 if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_U32
))
228 if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_S24
))
230 if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_U24
))
232 if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_U16
))
234 if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_S8
))
236 fatal("alsa:unable to find a suitable format\n");
238 #undef PCM_HW_FMT_DECIDE_X
239 STATIC
bool pcm_hw_access_decide_x(snd_pcm_t
*pcm
,
240 snd_pcm_hw_params_t
*pcm_hw_params
, snd_pcm_access_t access
)
244 r
= snd_pcm_hw_params_test_access(pcm
, pcm_hw_params
, access
);
247 r
= snd_pcm_hw_params_set_access(pcm
, pcm_hw_params
, access
);
249 fatal("alsa:unable to restrict pcm device to \"%s\", which was successfully tested\n", snd_pcm_access_name(access
));
250 pout("alsa:using \"%s\" access\n", snd_pcm_access_name(access
));
253 #define PCM_HW_ACCESS_DECIDE_X(access) \
254 pcm_hw_access_decide_x(pcm, pcm_hw_params, access)
255 /* XXX: only classic non-mmap ones */
256 STATIC
void pcm_hw_access_decide(snd_pcm_t
*pcm
,
257 snd_pcm_hw_params_t
*pcm_hw_params
, bool force
,
258 snd_pcm_access_t forced_access
)
261 snd_pcm_access_t access
;
264 r
= snd_pcm_hw_params_test_access(pcm
, pcm_hw_params
,
267 r
= snd_pcm_hw_params_set_access(pcm
, pcm_hw_params
,
270 fatal("alsa:unable to restrict pcm device to \"%s\", which was successfully tested\n", snd_pcm_access_name(forced_access
));
271 pout("alsa:using forced \"%s\" access\n", snd_pcm_access_name(forced_access
));
276 if (PCM_HW_ACCESS_DECIDE_X(SND_PCM_ACCESS_RW_INTERLEAVED
))
278 if (PCM_HW_ACCESS_DECIDE_X(SND_PCM_ACCESS_RW_NONINTERLEAVED
))
280 fatal("alsa:unable to find a suitable access\n");
282 #undef PCM_HW_ACCESS_DECIDE_X
284 * latency control: some audio bufs can be huge (tested on a pulseaudio with 10
285 * secs audio buf). if we are careless, we will quickly fill this buf which is
286 * worth a significant amount of time, hence will add huge latency to our
287 * interactive audio filtering (vol...). in the case of the 10 secs pulseaudio
288 * buf, it means if you want to mute the audio, it will happen 10 secs later.
289 * we add lantency control by limiting the sz of the dev audio buf, in periods
291 * we choose roughly 0.25 secs, or roughly (rate / 4) frs.
293 STATIC
void pcm_hw_buf_sz_cfg(snd_pcm_t
*pcm
,
294 snd_pcm_hw_params_t
*pcm_hw_params
)
297 snd_pcm_ufrs_t latency_control_target_buf_ufrs_n
;
298 snd_pcm_ufrs_t latency_control_buf_ufrs_n
;
301 r
= snd_pcm_hw_params_get_rate(pcm_hw_params
, &rate
, 0);
303 warning("alsa:latency control:DISABLING LATENCY CONTROL:unable to get the decided rate from the current device parameters\n");
306 latency_control_target_buf_ufrs_n
= (snd_pcm_ufrs_t
)rate
;
307 latency_control_target_buf_ufrs_n
/= 4;
308 latency_control_buf_ufrs_n
= latency_control_target_buf_ufrs_n
;
309 r
= snd_pcm_hw_params_set_buf_sz_near(pcm
, pcm_hw_params
,
310 &latency_control_buf_ufrs_n
);
312 warning("alsa:latency control:DISABLING_LATENCY_CONTROL:unable to set the audio buffer size (count of frames) to %u periods for the current device parameters\n", latency_control_buf_ufrs_n
);
315 pout("alsa:latency control:target buffer frame count is %u (~0.25 sec), got an audio buffer size set to %u frames\n", latency_control_target_buf_ufrs_n
, latency_control_buf_ufrs_n
);
318 * this function will "decide" the pcm dev cfg:
319 * the goal is to be the "closest" to the provided params,
320 * the "gap" will have to "filled" with ff filts
322 * the "strategy" is a "fall-thru" (chans n then ... then ...) which
323 * will "restrict" the pcm dev cfg further at each step
325 * we try to use a sensible restrict order regarding audio props
327 STATIC
void pcm_cfg_hw_core(snd_pcm_t
*pcm
, snd_pcm_hw_params_t
*pcm_hw_params
,
328 int chans_n
, int rate
, enum avutil_audio_fr_fmt_t ff_fmt
)
331 bool best_effort_wiring_success
;
332 snd_pcm_fmt_t fmt_from_best_effort
;
333 snd_pcm_access_t access_from_best_effort
;
335 /* the return value is from a first refine of the raw hw params */
336 r
= snd_pcm_hw_params_any(pcm
, pcm_hw_params
);
338 fatal("alsa:unable to populate the hardware parameters context\n");
339 pcm_hw_chans_n_decide(pcm
, pcm_hw_params
, (unsigned int)chans_n
);
340 pcm_hw_rate_decide(pcm
, pcm_hw_params
, (unsigned int)rate
);
342 best_effort_wiring_success
= ff_fmt2pcm_layout_best_effort(
343 ff_fmt
, &fmt_from_best_effort
, &access_from_best_effort
);
344 pcm_hw_fmt_decide(pcm
, pcm_hw_params
, best_effort_wiring_success
,
345 fmt_from_best_effort
);
346 pcm_hw_access_decide(pcm
, pcm_hw_params
, best_effort_wiring_success
,
347 access_from_best_effort
);
348 pcm_hw_buf_sz_cfg(pcm
, pcm_hw_params
);
350 /* base on kernel api at the time we wrote this code */
351 STATIC u8
*kernel_ts_types_str
[] = {
359 STATIC
void pcm_cfg_hw(snd_pcm_t
*pcm
, unsigned int chans_n
, unsigned int rate
,
360 enum avutil_audio_fr_fmt_t ff_fmt
)
364 snd_pcm_access_t access
;
365 snd_pcm_hw_params_t
*hw_params
;
367 pout("ALSA:HW_PARAMS START------------------------------------------------------------\n");
368 r
= snd_pcm_hw_params_malloc(&hw_params
);
370 fatal("alsa:unable to allocate hardware parameters context\n");
372 pcm_cfg_hw_core(pcm
, hw_params
, chans_n
, rate
, ff_fmt
);
374 r
= snd_pcm_hw_params(pcm
, hw_params
);
376 fatal("alsa:unable to install the hardware parameters\n");
377 r
= snd_pcm_hw_params_current(pcm
, hw_params
);
379 fatal("alsa:unable to get current hardware parameters\n");
380 snd_pcm_hw_params_dump(hw_params
, pcm_pout_l
);
383 selected_ts_type_p
= -1;
385 if (i
== ARRAY_N(kernel_ts_types_str
))
387 r
= snd_pcm_hw_params_supports_audio_ts_type(hw_params
, i
);
389 selected_ts_type_p
= i
;
390 pout("kernel audio timestamp type \"%s\" is supported for the current configuration\n", kernel_ts_types_str
[i
]);
395 * we selected the most accurate, namely with the highest idx, audio ts
398 pout("%s will be used for the audio based clock\n", kernel_ts_types_str
[selected_ts_type_p
]);
399 snd_pcm_hw_params_free(hw_params
);
400 pout("ALSA:HW_PARAMS END--------------------------------------------------------------\n");
402 STATIC
void pcm_cfg_sw(snd_pcm_t
*pcm
)
405 snd_pcm_sw_params_t
*sw_params
;
407 pout("ALSA:SW_PARAMS START------------------------------------------------------------\n");
408 r
= snd_pcm_sw_params_malloc(&sw_params
);
410 fatal("alsa:unable to allocate software parameters structure\n");
411 r
= snd_pcm_sw_params_current(pcm
, sw_params
);
413 fatal("alsa:unable to get current software parameters\n");
414 r
= snd_pcm_sw_params_set_period_evt(pcm
, sw_params
, 1);
416 fatal("alsa:unable to enable period event\n");
417 /* enable ts to be sure */
418 r
= snd_pcm_sw_params_set_tstamp_mode(pcm
, sw_params
,
419 SND_PCM_TSTAMP_ENABLE
);
421 fatal("unable to set timestamp mode:%s\n", snd_strerror(r
));
422 r
= snd_pcm_sw_params(pcm
, sw_params
);
424 fatal("alsa:unable to install sotfware parameters\n");
425 snd_pcm_sw_params_dump(sw_params
, pcm_pout_l
);
426 snd_pcm_sw_params_free(sw_params
);
427 pout("ALSA:SW_PARAMS END--------------------------------------------------------------\n");
429 STATIC
void dec_a_grow(void)
433 new_idx
= dec_sets_p
.n_max
;
434 dec_sets_p
.a
= realloc(dec_sets_p
.a
, sizeof(*dec_sets_p
.a
)
435 * (dec_sets_p
.n_max
+ 1));
436 if (dec_sets_p
.a
== 0)
437 fatal("unable to allocate memory for an additional pointer on a reference of a decoder set of frames\n");
438 dec_sets_p
.a
[new_idx
] = avutil_audio_set_ref_alloc();
439 if (dec_sets_p
.a
[new_idx
] == 0)
440 fatal("ffmpeg:unable to allocate a reference of a decoder set of frames\n");
446 STATIC u8
alsa_recover(snd_pcm_sfrs_t r
)
453 else if (r
== -EPIPE
|| r
== -ESTRPIPE
) {
454 /* underrun or suspended */
457 r_recovered
= snd_pcm_recover(pcm_p
, (int)r
, 0);
458 if (r_recovered
== 0) {
459 warning("alsa:pcm recovered\n");
462 fatal("alsa:unable to recover from suspend/underrun\n");
464 fatal("alsa:fatal/unhandled error\n");
472 STATIC
void pcm_silence_frs_write(snd_pcm_ufrs_t ufrs_n
) { loop
480 is_planar_fmt
= avutil_audio_fr_fmt_is_planar(
481 npv_audio_filt_p
.set
->fmt
);
482 if (is_planar_fmt
== NO
)
483 alsa_r
= snd_pcm_writei(pcm_p
, pcm_silence_bufs_l
[0], ufrs_n
);
485 alsa_r
= snd_pcm_writen(pcm_p
, pcm_silence_bufs_l
, ufrs_n
);
486 r_recover
= alsa_recover(alsa_r
);
487 if (r_recover
== AGAIN
)
489 else if (r_recover
== RECOVERED
)
491 /* r_recover == CONTINUE */
492 ufrs_n
-= (snd_pcm_ufrs_t
)alsa_r
;
498 STATIC
void chans_buf_init(u8
**chans_buf
, int start_fr_idx
)
503 sample_bytes_n
= avutil_get_bytes_per_sample(npv_audio_filt_p
.set
->fmt
);
504 is_planar_fmt
= avutil_audio_fr_fmt_is_planar(
505 npv_audio_filt_p
.set
->fmt
);
506 if (is_planar_fmt
== NO
) { /* or is pcm interleaved */
509 fr_bytes_n
= sample_bytes_n
* npv_audio_filt_p
.set
->chans_n
;
510 chans_buf
[0] = (u8
*)npv_audio_filt_p
.set
->data
[0] + start_fr_idx
512 } else { /* ff planar or pcm noninterleaved */
517 if (p
== npv_audio_filt_p
.set
->chans_n
)
519 chans_buf
[p
] = (u8
*)npv_audio_filt_p
.set
->data
[p
]
520 + start_fr_idx
* sample_bytes_n
;
527 STATIC
void chans_buf_inc(u8
**chans_buf
, int inc
)
532 sample_bytes_n
= avutil_get_bytes_per_sample(npv_audio_filt_p
.set
->fmt
);
533 is_planar_fmt
= avutil_audio_fr_fmt_is_planar(
534 npv_audio_filt_p
.set
->fmt
);
535 if (is_planar_fmt
== NO
) { /* or is pcm interleaved */
538 fr_bytes_n
= sample_bytes_n
* npv_audio_filt_p
.set
->chans_n
;
539 chans_buf
[0] = (u8
*)chans_buf
[0] + inc
* fr_bytes_n
;
540 } else { /* ff planar or pcm noninterleaved */
545 if (p
== npv_audio_filt_p
.set
->chans_n
)
547 chans_buf
[p
] = (u8
*)chans_buf
[p
] + inc
* sample_bytes_n
;
553 STATIC
void draining_state_handle(void)
557 r
= snd_pcm_drain(pcm_p
);
559 snd_pcm_state_t state
;
564 * the pcm state can change asynchronously, and if the draining
565 * was successful, the pcm should be in SETUP state, and in
566 * this state, snd_pcm_drain _must_ fail (direct from alsa
569 state
= snd_pcm_state(pcm_p
);
570 if (state
!= SND_PCM_STATE_SETUP
)
571 fatal("alsa:an error occured switching to/checking the pcm draining state\n");
572 /* here pcm state is SND_PCM_STATE_SETUP */
574 npv_exit("alsa pcm drained or similar, exiting\n");
576 STATIC
void draining_state_switch(void)
583 draining_state_handle();
584 /* remove the alsa epoll fds */
587 if (i
== pcm_pollfds_n_p
)
589 /* in theory, it is thread safe */
590 r
= epoll_ctl(npv_ep_fd_p
, EPOLL_CTL_DEL
, pcm_pollfds_p
[i
].fd
,
593 fatal("unable to remove the alsa file descriptors from epoll\n");
596 /* start the draining timer */
597 memset(&t
, 0, sizeof(t
));
598 /* initial and interval */
599 t
.it_value
.tv_nsec
= DRAINING_TIMER_INTERVAL_NSECS_N
;
600 t
.it_interval
.tv_nsec
= DRAINING_TIMER_INTERVAL_NSECS_N
;
601 r
= timerfd_settime(draining_timer_fd_p
, 0, &t
, 0);
603 fatal("unable to arm the draining timer\n");
609 #define HAVE_FILT_SET 1
612 STATIC
void pcm_filt_frs_write(snd_pcm_ufrs_t ufrs_n
) { loop
615 u8
*chans_buf
[AVUTIL_DATA_PTRS_N
];
616 snd_pcm_ufrs_t ufrs_to_write_n
;
617 snd_pcm_ufrs_t filt_set_remaining_ufrs_n
; /* for clarity */
619 snd_pcm_ufrs_t written_ufrs_n
; /* for clarity */
624 * in this loop we try to get some filt frs from what we got from the
627 if (npv_audio_filt_p
.set
->frs_n
== 0) loop
{
630 /* we _really_ want audio data */
631 (void)filt_push_dec_sets();
632 r
= npv_audio_filt_set_try_get();
634 draining_state_switch();
636 } else if (r
== HAVE_FILT_SET
) {
637 npv_audio_filt_p
.pcm_written_ufrs_n
= 0;
642 chans_buf_init(chans_buf
, (int)npv_audio_filt_p
.pcm_written_ufrs_n
);
643 filt_set_remaining_ufrs_n
= (snd_pcm_ufrs_t
)npv_audio_filt_p
.set
->frs_n
644 - npv_audio_filt_p
.pcm_written_ufrs_n
;
645 if (filt_set_remaining_ufrs_n
> ufrs_n
)
646 ufrs_to_write_n
= ufrs_n
;
648 ufrs_to_write_n
= filt_set_remaining_ufrs_n
;
649 is_planar_fmt
= avutil_audio_fr_fmt_is_planar(
650 npv_audio_filt_p
.set
->fmt
);
652 loop
{ /* short write loop */
653 snd_pcm_sfrs_t alsa_r
;
656 if (is_planar_fmt
== NO
)
657 alsa_r
= snd_pcm_writei(pcm_p
, chans_buf
[0],
658 ufrs_to_write_n
- written_ufrs_n
);
660 alsa_r
= snd_pcm_writen(pcm_p
, (void**)chans_buf
,
661 ufrs_to_write_n
- written_ufrs_n
);
662 r_recover
= alsa_recover(alsa_r
);
663 if (r_recover
== AGAIN
)
665 else if (r_recover
== RECOVERED
) {
666 /* account for the written frs anyway */
667 if (npv_audio_filt_p
.pcm_written_ufrs_n
== 0)
668 npv_clk_ref_time_point_update(
669 npv_audio_filt_p
.set
->pts
,
671 npv_audio_filt_p
.pcm_written_ufrs_n
+= written_ufrs_n
;
672 if ((int)npv_audio_filt_p
.pcm_written_ufrs_n
==
673 npv_audio_filt_p
.set
->frs_n
)
674 /* set audio_filt_p.set->frs_n = 0 */
675 avutil_audio_set_unref(npv_audio_filt_p
.set
);
678 /* r_recover == CONTINUE */
679 written_ufrs_n
+= (snd_pcm_ufrs_t
)alsa_r
;
680 if (written_ufrs_n
== ufrs_to_write_n
)
682 chans_buf_inc(chans_buf
, (int)alsa_r
);
685 * this is here we update our ref time point for the audio clk
686 * because with a new filt set of frs, we get a new ts
688 * XXX: getting the "right" ts from ff is convoluted
690 if (npv_audio_filt_p
.pcm_written_ufrs_n
== 0)
691 npv_clk_ref_time_point_update(npv_audio_filt_p
.set
->pts
,
693 npv_audio_filt_p
.pcm_written_ufrs_n
+= written_ufrs_n
;
694 ufrs_n
-= written_ufrs_n
;
696 if ((int)npv_audio_filt_p
.pcm_written_ufrs_n
697 == npv_audio_filt_p
.set
->frs_n
)
698 /* set audio_filt_p.av->frs_n = 0 */
699 avutil_audio_set_unref(npv_audio_filt_p
.set
);
708 /* fatal if the wiring cannot be done */
709 STATIC
void pcm_layout2ff_fmt_strict(snd_pcm_fmt_t alsa_fmt
,
710 snd_pcm_access_t alsa_access
, enum avutil_audio_fr_fmt_t
*ff_fmt
,
714 * ff fmt byte order is always native.
715 * here we handle little endian only
718 case SND_PCM_FMT_FLOAT
:
719 if (alsa_access
== SND_PCM_ACCESS_RW_INTERLEAVED
)
720 *ff_fmt
= AVUTIL_AUDIO_FR_FMT_FLT
;
722 *ff_fmt
= AVUTIL_AUDIO_FR_FMT_FLTP
;
724 case SND_PCM_FMT_S32
:
725 if (alsa_access
== SND_PCM_ACCESS_RW_INTERLEAVED
)
726 *ff_fmt
= AVUTIL_AUDIO_FR_FMT_S32
;
728 *ff_fmt
= AVUTIL_AUDIO_FR_FMT_S32P
;
730 case SND_PCM_FMT_S16
:
731 if (alsa_access
== SND_PCM_ACCESS_RW_INTERLEAVED
)
732 *ff_fmt
= AVUTIL_AUDIO_FR_FMT_S16
;
734 *ff_fmt
= AVUTIL_AUDIO_FR_FMT_S16P
;
737 if (alsa_access
== SND_PCM_ACCESS_RW_INTERLEAVED
)
738 *ff_fmt
= AVUTIL_AUDIO_FR_FMT_U8
;
740 *ff_fmt
= AVUTIL_AUDIO_FR_FMT_U8P
;
743 fatal("unable to wire strictly alsa layout \"%s\"/\"%s\" to a ffmpeg format\n", snd_pcm_fmt_desc(alsa_fmt
), snd_pcm_access_name(alsa_access
));
746 u8 ff_fmt_str
[STR_SZ
];
748 avutil_get_audio_fr_fmt_str(ff_fmt_str
, sizeof(ff_fmt_str
),
750 pout("alsa pcm layout \"%s\"/\"%s\" wired strictly to ffmpeg format \"%sbits\"\n", snd_pcm_fmt_desc(alsa_fmt
), snd_pcm_access_name(alsa_access
), ff_fmt_str
);
754 * XXX: if it is ever used significantly, a fine granularity wiring strategy
755 * will be implemented instead of using the default wiring
757 STATIC
uint64_t pcm_chmaps2ff_chans_layout(snd_pcm_t
*pcm
,
758 unsigned int pcm_chans_n
, bool print_info
)
761 uint64_t ff_chans_layout
;
762 snd_pcm_chmap_t
*pcm_chmap
;
763 u8 chans_layout_str
[STR_SZ
]; /* should be overkill */
765 pcm_chmap
= snd_pcm_get_chmap(pcm
);
766 if (pcm_chmap
== 0) {
768 pout("alsa:no pcm channel map available, wiring to default ffmpeg channel layout\n");
771 pout("alsa:your pcm device support channel maps, but fine granularity wiring strategy is not implemented\n");
774 ff_chans_layout
= avutil_get_default_chans_layout((int)pcm_chans_n
);
775 avutil_get_chans_layout_str(chans_layout_str
, sizeof(chans_layout_str
),
776 (int)pcm_chans_n
, ff_chans_layout
);
778 pout("alsa channel map wired to ffmpeg channel layout:\"%s\" (%u pcm channels)\n", chans_layout_str
, pcm_chans_n
);
779 return ff_chans_layout
;
781 STATIC
void init_pcm_once_public(u8
*pcm_str
)
785 r
= snd_pcm_open(&pcm_p
, pcm_str
, SND_PCM_ST_PLAYBACK
,
789 fatal("alsa:\"%s\" pcm is already in use\n", pcm_str
);
791 fatal("alsa:unable to open \"%s\" pcm for playback\n", pcm_str
);
794 r
= snd_pcm_poll_descriptors_n(pcm_p
);
795 pout("alsa:have %d poll file descriptors\n", r
);
796 if ((r
<= 0) || (r
> pcm_pollfds_n_max
))
797 fatal("alsa:invalid count of alsa poll file descriptors\n");
798 pcm_pollfds_n_p
=(u8
)r
;
799 memset(pcm_pollfds_p
, 0, sizeof(pcm_pollfds_p
));
800 snd_pcm_poll_descriptors(pcm_p
, pcm_pollfds_p
, pcm_pollfds_n_max
);
802 STATIC
void init_once_public(u8
*pcm_str
)
806 memset(&st_p
, 0, sizeof(st_p
));
807 pkt_q_p
= npv_pkt_q_new("audio");
809 dec_sets_p
.eof_receive
= false;
810 dec_sets_p
.n_max
= 0;
813 init_pcm_once_public(pcm_str
);
814 selected_ts_type_p
= -1;
815 /* linux bug: still no CLOCK_MONOTONIC_RAW for timerfd */
817 draining_timer_fd_p
= timerfd_create(CLOCK_MONOTONIC
, TFD_NONBLOCK
);
818 if (draining_timer_fd_p
== -1)
819 fatal("unable to get a draining timer file descriptor:%s\n", strerror(errno
));
821 r
= pthread_mutex_init(&dec_ctx_mutex_l
, 0);
823 fatal("%d:unable to init the decoder mutex\n", r
);
824 r
= pthread_mutex_init(&dec_sets_p
.mutex
, 0);
826 fatal("%d:unable to init the mutex for the array of decoder sets\n", r
);
828 STATIC
void init_once_local(void)
833 r
= snd_output_stdio_attach(&pcm_pout_l
, stdout
, 0);
835 fatal("alsa:unable to attach stdout\n");
836 r
= snd_output_stdio_attach(&pcm_perr_l
, stderr
, 0);
838 fatal("alsa:unable to attach stderr\n");
839 memset(pcm_silence_bufs_l
, 0, sizeof(pcm_silence_bufs_l
));
841 STATIC
void dec_a_unref_all(void)
847 if (set
== dec_sets_p
.n
)
849 avutil_audio_set_unref(dec_sets_p
.a
[set
]);