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 /* base on kernel api at the time we wrote this code */
29 STATIC u8
*kernel_ts_types_str_l
[] = {
38 * XXX: if it is ever used significantly, a fine granularity wiring strategy
39 * will be implemented instead of using the default wiring
41 STATIC
void pcm_chmaps2ff_chans_layout(AVChannelLayout
*ff_chans_layout
,
42 snd_pcm_t
*pcm
, unsigned int pcm_chans_n
, bool print_info
)
45 snd_pcm_chmap_t
*pcm_chmap
;
46 u8 chans_layout_str
[STR_SZ
]; /* should be overkill */
48 pcm_chmap
= snd_pcm_get_chmap(pcm
);
51 pout("alsa:no pcm channel map available, wiring to default ffmpeg channel layout\n");
54 pout("alsa:your pcm device support channel maps, but fine granularity wiring strategy is not implemented, using default ffmpeg layout\n");
57 /* XXX: will need to get back at it if a wiring strategy is required */
58 av_channel_layout_default(ff_chans_layout
, (int)pcm_chans_n
);
59 av_channel_layout_describe(ff_chans_layout
, chans_layout_str
,
60 sizeof(chans_layout_str
));
62 pout("alsa channel map wired to ffmpeg channel layout:\"%s\" (%u pcm channels)\n", chans_layout_str
, pcm_chans_n
);
64 STATIC
bool ff_fmt2pcm_layout_best_effort(enum avutil_audio_fr_fmt_t ff_fmt
,
65 snd_pcm_fmt_t
*alsa_fmt
, snd_pcm_access_t
*alsa_access
)
67 static u8 ff_fmt_str
[STR_SZ
];
69 avutil_get_audio_fr_fmt_str(ff_fmt_str
, STR_SZ
, ff_fmt
);
70 /* XXX: only classic non-mmap ones */
72 case AVUTIL_AUDIO_FR_FMT_U8
:
73 *alsa_fmt
= SND_PCM_FMT_U8
;
74 *alsa_access
= SND_PCM_ACCESS_RW_INTERLEAVED
;
76 case AVUTIL_AUDIO_FR_FMT_S16
:
77 *alsa_fmt
= SND_PCM_FMT_S16
;
78 *alsa_access
= SND_PCM_ACCESS_RW_INTERLEAVED
;
80 case AVUTIL_AUDIO_FR_FMT_S32
:
81 *alsa_fmt
= SND_PCM_FMT_S32
;
82 *alsa_access
= SND_PCM_ACCESS_RW_INTERLEAVED
;
84 case AVUTIL_AUDIO_FR_FMT_FLT
:
85 *alsa_fmt
= SND_PCM_FMT_FLOAT
;
86 *alsa_access
= SND_PCM_ACCESS_RW_INTERLEAVED
;
88 /* ff "planar" fmts are actually non interleaved fmts */
89 case AVUTIL_AUDIO_FR_FMT_U8P
:
90 *alsa_fmt
= SND_PCM_FMT_U8
;
91 *alsa_access
= SND_PCM_ACCESS_RW_NONINTERLEAVED
;
93 case AVUTIL_AUDIO_FR_FMT_S16P
:
94 *alsa_fmt
= SND_PCM_FMT_S16
;
95 *alsa_access
= SND_PCM_ACCESS_RW_NONINTERLEAVED
;
97 case AVUTIL_AUDIO_FR_FMT_S32P
:
98 *alsa_fmt
= SND_PCM_FMT_S32
;
99 *alsa_access
= SND_PCM_ACCESS_RW_NONINTERLEAVED
;
101 case AVUTIL_AUDIO_FR_FMT_FLTP
:
102 *alsa_fmt
= SND_PCM_FMT_FLOAT
;
103 *alsa_access
= SND_PCM_ACCESS_RW_NONINTERLEAVED
;
106 pout("best effort:unable to wire ffmpeg sample format \"%sbits\" to alsa sample format, \n,", ff_fmt_str
);
109 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
));
112 STATIC
void pcm_hw_chans_n_decide(snd_pcm_t
*pcm
,
113 snd_pcm_hw_params_t
*pcm_hw_params
, int chans_n
)
116 unsigned int chans_n_max
;
117 unsigned int chans_n_min
;
119 r
= snd_pcm_hw_params_test_chans_n(pcm
, pcm_hw_params
,
120 (unsigned int)chans_n
);
122 r
= snd_pcm_hw_params_set_chans_n(pcm
, pcm_hw_params
,
123 (unsigned int)chans_n
);
125 fatal("alsa:unable to restrict pcm device to %d channels, count which was successfully tested\n", chans_n
);
126 pout("alsa:using %d channels\n", chans_n
);
129 pout("alsa:unable to use %d channels\n", chans_n
);
130 /* try to use the max chans n the pcm can */
131 r
= snd_pcm_hw_params_get_chans_n_max(pcm_hw_params
, &chans_n_max
);
133 fatal("alsa:unable to get the maximum count of pcm device channels\n");
134 r
= snd_pcm_hw_params_test_chans_n(pcm
, pcm_hw_params
, chans_n_max
);
136 r
= snd_pcm_hw_params_set_chans_n(pcm
, pcm_hw_params
,
139 fatal("alsa:unable to restrict pcm device to %u channels, count which was successfully tested\n", chans_n_max
);
140 pout("alsa:using pcm maximum %u channels\n", chans_n_max
);
143 /* ok... last try, the pcm dev min chans n */
144 r
= snd_pcm_hw_params_get_chans_n_min(pcm_hw_params
, &chans_n_min
);
146 fatal("alsa:unable to get the minimum count of pcm device channels\n");
147 r
= snd_pcm_hw_params_test_chans_n(pcm
, pcm_hw_params
, chans_n_min
);
149 r
= snd_pcm_hw_params_set_chans_n(pcm
, pcm_hw_params
,
152 fatal("alsa:unable to restrict pcm device to %u channels, count which was successfully tested\n", chans_n_min
);
153 pout("alsa:using pcm device minimum %u channels\n", chans_n_min
);
156 fatal("alsa:unable to find a suitable count of channels\n");
158 STATIC
void pcm_hw_rate_decide(snd_pcm_t
*pcm
,
159 snd_pcm_hw_params_t
*pcm_hw_params
, int rate
)
162 unsigned int rate_max
;
163 unsigned int rate_near
;
164 unsigned int rate_min
;
166 r
= snd_pcm_hw_params_test_rate(pcm
, pcm_hw_params
, (unsigned int)rate
,
167 SND_PCM_ST_PLAYBACK
);
169 r
= snd_pcm_hw_params_set_rate(pcm
, pcm_hw_params
,
170 (unsigned int)rate
, SND_PCM_ST_PLAYBACK
);
172 fatal("alsa:unable to restrict pcm device to %dHz, which was successfully tested\n", rate
);
173 pout("alsa:using %dHz\n", rate
);
176 pout("alsa:unable to use %dHz\n", rate
);
177 /* try to use the max rate the pcm can */
178 r
= snd_pcm_hw_params_get_rate_max(pcm_hw_params
, &rate_max
,
179 SND_PCM_ST_PLAYBACK
);
181 fatal("alsa:unable to get the maximum rate of pcm device\n");
182 r
= snd_pcm_hw_params_test_rate(pcm
, pcm_hw_params
, rate_max
,
183 SND_PCM_ST_PLAYBACK
);
185 r
= snd_pcm_hw_params_set_rate(pcm
, pcm_hw_params
, rate_max
,
186 SND_PCM_ST_PLAYBACK
);
188 fatal("alsa:unable to restrict pcm device to %uHz, which was successfully tested\n", rate_max
);
189 pout("alsa:using pcm device %uHz\n", rate_max
);
192 /* try to use a rate "near" of what the pcm dev can */
194 r
= snd_pcm_hw_params_set_rate_near(pcm
, pcm_hw_params
, &rate_near
,
195 SND_PCM_ST_PLAYBACK
);
197 pout("alsa:using pcm device %uHz\n", rate_near
);
200 /* even a "near" rate did failed... try the min */
201 r
= snd_pcm_hw_params_get_rate_min(pcm_hw_params
, &rate_min
,
202 SND_PCM_ST_PLAYBACK
);
204 fatal("alsa:unable to get the minimum rate of pcm device\n");
205 r
= snd_pcm_hw_params_test_rate(pcm
, pcm_hw_params
, rate_min
,
206 SND_PCM_ST_PLAYBACK
);
208 r
= snd_pcm_hw_params_set_rate(pcm
, pcm_hw_params
, rate_min
,
209 SND_PCM_ST_PLAYBACK
);
211 fatal("alsa:unable to restrict pcm device to %uHz, which was successfully tested\n", rate_min
);
212 pout("alsa:using pcm device %uHz\n", rate_min
);
215 fatal("alsa:unable to find a suitable rate\n");
217 STATIC
bool pcm_hw_fmt_decide_x(snd_pcm_t
*pcm
,
218 snd_pcm_hw_params_t
*pcm_hw_params
, snd_pcm_fmt_t fmt
)
222 r
= snd_pcm_hw_params_test_fmt(pcm
, pcm_hw_params
, fmt
);
225 r
= snd_pcm_hw_params_set_fmt(pcm
, pcm_hw_params
, fmt
);
227 fatal("alsa:unable to restrict pcm device to \"%s\", which was successfully tested\n", snd_pcm_fmt_desc(fmt
));
228 pout("alsa:using last resort \"%s\" format\n", snd_pcm_fmt_desc(fmt
));
231 #define PCM_HW_FMT_DECIDE_X(fmt) pcm_hw_fmt_decide_x(pcm, pcm_hw_params, fmt)
232 STATIC
void pcm_hw_fmt_decide(snd_pcm_t
*pcm
,
233 snd_pcm_hw_params_t
*pcm_hw_params
, bool best_effort
,
234 snd_pcm_fmt_t best_effort_fmt
)
240 r
= snd_pcm_hw_params_test_fmt(pcm
, pcm_hw_params
,
243 r
= snd_pcm_hw_params_set_fmt(pcm
, pcm_hw_params
,
246 fatal("alsa:unable to restrict pcm device to \"%s\", which was successfully tested\n", snd_pcm_fmt_desc(best_effort_fmt
));
247 pout("alsa:using best effort \"%s\" format\n", snd_pcm_fmt_desc(best_effort_fmt
));
251 /* then we try to select from the reasonable "best" to the lowest */
252 /* prefer fmts we know supported by ff */
253 if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_FLOAT
))
255 if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_S32
))
257 if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_S16
))
259 if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_U8
))
262 * from here, at the time of writting, those fmts have no ff
263 * wiring, but we are alsa centric here, validate that later
265 if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_U32
))
267 if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_S24
))
269 if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_U24
))
271 if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_U16
))
273 if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_S8
))
275 fatal("alsa:unable to find a suitable format\n");
277 #undef PCM_HW_FMT_DECIDE_X
278 STATIC
bool pcm_hw_access_decide_x(snd_pcm_t
*pcm
,
279 snd_pcm_hw_params_t
*pcm_hw_params
, snd_pcm_access_t access
)
283 r
= snd_pcm_hw_params_test_access(pcm
, pcm_hw_params
, access
);
286 r
= snd_pcm_hw_params_set_access(pcm
, pcm_hw_params
, access
);
288 fatal("alsa:unable to restrict pcm device to \"%s\", which was successfully tested\n", snd_pcm_access_name(access
));
289 pout("alsa:using last resort \"%s\" access\n", snd_pcm_access_name(access
));
292 #define PCM_HW_ACCESS_DECIDE_X(access) \
293 pcm_hw_access_decide_x(pcm, pcm_hw_params, access)
294 /* XXX: only classic non-mmap ones */
295 STATIC
void pcm_hw_access_decide(snd_pcm_t
*pcm
,
296 snd_pcm_hw_params_t
*pcm_hw_params
, bool best_effort
,
297 snd_pcm_access_t best_effort_access
)
300 snd_pcm_access_t access
;
303 r
= snd_pcm_hw_params_test_access(pcm
, pcm_hw_params
,
306 r
= snd_pcm_hw_params_set_access(pcm
, pcm_hw_params
,
309 fatal("alsa:unable to restrict pcm device to \"%s\", which was successfully tested\n", snd_pcm_access_name(best_effort_access
));
310 pout("alsa:using best effort \"%s\" access\n", snd_pcm_access_name(best_effort_access
));
315 if (PCM_HW_ACCESS_DECIDE_X(SND_PCM_ACCESS_RW_INTERLEAVED
))
317 if (PCM_HW_ACCESS_DECIDE_X(SND_PCM_ACCESS_RW_NONINTERLEAVED
))
319 fatal("alsa:unable to find a suitable access\n");
321 #undef PCM_HW_ACCESS_DECIDE_X
323 * latency control: some audio bufs can be huge (tested on a pulseaudio with 10
324 * secs audio buf). if we are careless, we will quickly fill this buf which is
325 * worth a significant amount of time, hence will add huge latency to our
326 * interactive audio filtering (vol...). in the case of the 10 secs pulseaudio
327 * buf, it means if you want to mute the audio, it will happen 10 secs later.
328 * we add lantency control by limiting the sz of the dev audio buf, in periods
330 * we choose roughly 0.25 secs, or roughly (rate / 4) frs.
332 STATIC
void pcm_hw_buf_sz_cfg(snd_pcm_t
*pcm
,
333 snd_pcm_hw_params_t
*pcm_hw_params
)
336 snd_pcm_ufrs_t latency_control_target_buf_ufrs_n
;
337 snd_pcm_ufrs_t latency_control_buf_ufrs_n
;
340 r
= snd_pcm_hw_params_get_rate(pcm_hw_params
, &rate
, 0);
342 warning("alsa:latency control:DISABLING LATENCY CONTROL:unable to get the decided rate from the current device parameters\n");
345 latency_control_target_buf_ufrs_n
= (snd_pcm_ufrs_t
)rate
;
346 latency_control_target_buf_ufrs_n
/= 4;
347 latency_control_buf_ufrs_n
= latency_control_target_buf_ufrs_n
;
348 r
= snd_pcm_hw_params_set_buf_sz_near(pcm
, pcm_hw_params
,
349 &latency_control_buf_ufrs_n
);
351 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
);
354 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
);
357 * this function will "decide" the pcm dev cfg:
358 * the goal is to be the "closest" to the provided params,
359 * the "gap" will have to "filled" with ff filts
361 * the "strategy" is a "fall-thru" (chans n then ... then ...) which
362 * will "restrict" the pcm dev cfg further at each step
364 * we try to use a sensible restrict order regarding audio props
366 STATIC
void pcm_cfg_hw_core_best_effort(snd_pcm_t
*pcm
,
367 snd_pcm_hw_params_t
*pcm_hw_params
, int chans_n
,
368 int rate
, enum avutil_audio_fr_fmt_t ff_fmt
)
371 bool best_effort_wiring_success
;
372 snd_pcm_fmt_t fmt_from_best_effort
;
373 snd_pcm_access_t access_from_best_effort
;
375 /* the return value is from a first refine of the raw hw params */
376 r
= snd_pcm_hw_params_any(pcm
, pcm_hw_params
);
378 fatal("alsa:unable to populate the hardware parameters context\n");
379 pcm_hw_chans_n_decide(pcm
, pcm_hw_params
, chans_n
);
380 pcm_hw_rate_decide(pcm
, pcm_hw_params
, rate
);
381 /* try our best with the fmt */
382 best_effort_wiring_success
= ff_fmt2pcm_layout_best_effort(
383 ff_fmt
, &fmt_from_best_effort
, &access_from_best_effort
);
384 pcm_hw_fmt_decide(pcm
, pcm_hw_params
, best_effort_wiring_success
,
385 fmt_from_best_effort
);
386 pcm_hw_access_decide(pcm
, pcm_hw_params
, best_effort_wiring_success
,
387 access_from_best_effort
);
388 pcm_hw_buf_sz_cfg(pcm
, pcm_hw_params
);
390 STATIC
void dec_a_grow(void)
394 new_idx
= dec_sets_p
.n_max
;
395 dec_sets_p
.a
= realloc(dec_sets_p
.a
, sizeof(*dec_sets_p
.a
)
396 * (dec_sets_p
.n_max
+ 1));
397 if (dec_sets_p
.a
== 0)
398 fatal("unable to allocate memory for an additional pointer on a reference of a decoder set of frames\n");
399 dec_sets_p
.a
[new_idx
] = avutil_audio_set_ref_alloc();
400 if (dec_sets_p
.a
[new_idx
] == 0)
401 fatal("ffmpeg:unable to allocate a reference of a decoder set of frames\n");
407 STATIC u8
alsa_recover(snd_pcm_sfrs_t r
)
414 else if (r
== -EPIPE
|| r
== -ESTRPIPE
) {
415 /* underrun or suspended */
418 r_recovered
= snd_pcm_recover(pcm_p
, (int)r
, 0);
419 if (r_recovered
== 0) {
420 warning("alsa:pcm recovered\n");
423 fatal("alsa:unable to recover from suspend/underrun\n");
425 fatal("alsa:fatal/unhandled error\n");
433 STATIC
void pcm_silence_frs_write(snd_pcm_ufrs_t ufrs_n
) { loop
441 is_planar_fmt
= avutil_audio_fr_fmt_is_planar(
442 npv_audio_filt_p
.set
->fmt
);
443 if (is_planar_fmt
== NO
)
444 alsa_r
= snd_pcm_writei(pcm_p
, pcm_silence_bufs_l
[0], ufrs_n
);
446 alsa_r
= snd_pcm_writen(pcm_p
, pcm_silence_bufs_l
, ufrs_n
);
447 r_recover
= alsa_recover(alsa_r
);
448 if (r_recover
== AGAIN
)
450 else if (r_recover
== RECOVERED
)
452 /* r_recover == CONTINUE */
453 ufrs_n
-= (snd_pcm_ufrs_t
)alsa_r
;
459 STATIC
void chans_buf_init(u8
**chans_buf
, int start_fr_idx
)
464 sample_bytes_n
= avutil_get_bytes_per_sample(npv_audio_filt_p
.set
->fmt
);
465 is_planar_fmt
= avutil_audio_fr_fmt_is_planar(
466 npv_audio_filt_p
.set
->fmt
);
467 if (is_planar_fmt
== NO
) { /* or is pcm interleaved */
470 fr_bytes_n
= sample_bytes_n
471 * npv_audio_filt_p
.set
->ch_layout
.nb_channels
;
472 chans_buf
[0] = (u8
*)npv_audio_filt_p
.set
->data
[0] + start_fr_idx
474 } else { /* ff planar or pcm noninterleaved */
479 if (p
== npv_audio_filt_p
.set
->ch_layout
.nb_channels
)
481 chans_buf
[p
] = (u8
*)npv_audio_filt_p
.set
->data
[p
]
482 + start_fr_idx
* sample_bytes_n
;
489 STATIC
void chans_buf_inc(u8
**chans_buf
, int inc
)
494 sample_bytes_n
= avutil_get_bytes_per_sample(npv_audio_filt_p
.set
->fmt
);
495 is_planar_fmt
= avutil_audio_fr_fmt_is_planar(
496 npv_audio_filt_p
.set
->fmt
);
497 if (is_planar_fmt
== NO
) { /* or is pcm interleaved */
500 fr_bytes_n
= sample_bytes_n
501 * npv_audio_filt_p
.set
->ch_layout
.nb_channels
;
502 chans_buf
[0] = (u8
*)chans_buf
[0] + inc
* fr_bytes_n
;
503 } else { /* ff planar or pcm noninterleaved */
508 if (p
== npv_audio_filt_p
.set
->ch_layout
.nb_channels
)
510 chans_buf
[p
] = (u8
*)chans_buf
[p
] + inc
* sample_bytes_n
;
516 STATIC
void draining_state_handle(void)
520 r
= snd_pcm_drain(pcm_p
);
522 snd_pcm_state_t state
;
527 * the pcm state can change asynchronously.
529 * if the draining was successful, the pcm should be in SETUP
530 * state, and in this state, snd_pcm_drain will fail
531 * _new and fixed__ behavior:
532 * this won't happen because calling snd_pcm_drain while in
533 * the SETUP state won't return an error anymore
535 state
= snd_pcm_state(pcm_p
);
536 if (state
!= SND_PCM_STATE_SETUP
)
537 fatal("alsa:an error occured switching to/checking the pcm draining state\n");
538 /* here pcm state is SND_PCM_STATE_SETUP */
540 npv_exit("alsa pcm drained or similar, exiting\n");
542 STATIC
void draining_state_switch(void)
549 draining_state_handle();
550 /* remove the alsa epoll fds */
553 if (i
== pcm_pollfds_n_p
)
555 /* in theory, it is thread safe */
556 r
= epoll_ctl(npv_ep_fd_p
, EPOLL_CTL_DEL
, pcm_pollfds_p
[i
].fd
,
559 fatal("unable to remove the alsa file descriptors from epoll\n");
562 /* start the draining timer */
563 memset(&t
, 0, sizeof(t
));
564 /* initial and interval */
565 t
.it_value
.tv_nsec
= DRAINING_TIMER_INTERVAL_NSECS_N
;
566 t
.it_interval
.tv_nsec
= DRAINING_TIMER_INTERVAL_NSECS_N
;
567 r
= timerfd_settime(draining_timer_fd_p
, 0, &t
, 0);
569 fatal("unable to arm the draining timer\n");
571 /* fatal if the wiring cannot be done */
572 STATIC
void pcm_layout2ff_fmt_strict(snd_pcm_fmt_t alsa_fmt
,
573 snd_pcm_access_t alsa_access
, enum avutil_audio_fr_fmt_t
*ff_fmt
,
577 * ff fmt byte order is always native.
578 * here we handle little endian only
581 case SND_PCM_FMT_FLOAT
:
582 if (alsa_access
== SND_PCM_ACCESS_RW_INTERLEAVED
)
583 *ff_fmt
= AVUTIL_AUDIO_FR_FMT_FLT
;
585 *ff_fmt
= AVUTIL_AUDIO_FR_FMT_FLTP
;
587 case SND_PCM_FMT_S32
:
588 if (alsa_access
== SND_PCM_ACCESS_RW_INTERLEAVED
)
589 *ff_fmt
= AVUTIL_AUDIO_FR_FMT_S32
;
591 *ff_fmt
= AVUTIL_AUDIO_FR_FMT_S32P
;
593 case SND_PCM_FMT_S16
:
594 if (alsa_access
== SND_PCM_ACCESS_RW_INTERLEAVED
)
595 *ff_fmt
= AVUTIL_AUDIO_FR_FMT_S16
;
597 *ff_fmt
= AVUTIL_AUDIO_FR_FMT_S16P
;
600 if (alsa_access
== SND_PCM_ACCESS_RW_INTERLEAVED
)
601 *ff_fmt
= AVUTIL_AUDIO_FR_FMT_U8
;
603 *ff_fmt
= AVUTIL_AUDIO_FR_FMT_U8P
;
606 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
));
609 u8 ff_fmt_str
[STR_SZ
];
611 avutil_get_audio_fr_fmt_str(ff_fmt_str
, sizeof(ff_fmt_str
),
613 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
);
616 STATIC
void pcm2ff_strict(snd_pcm_t
*pcm
, AVChannelLayout
*ff_chans_layout
,
617 int *ff_rate
, enum avutil_audio_fr_fmt_t
*ff_fmt
, bool print_info
)
620 snd_pcm_hw_params_t
*hw_params
;
621 unsigned int pcm_chans_n
;
622 unsigned int pcm_rate
;
623 snd_pcm_fmt_t pcm_fmt
;
624 snd_pcm_access_t pcm_access
;
626 r
= snd_pcm_hw_params_malloc(&hw_params
);
628 fatal("alsa:unable to allocate hardware parameters context for ffmpeg filter wiring\n");
629 r
= snd_pcm_hw_params_current(pcm
, hw_params
);
631 fatal("alsa:unable to get current hardware parameters for ffmpeg filter wiring\n");
632 r
= snd_pcm_hw_params_get_access(hw_params
, &pcm_access
);
634 fatal("alsa:unable to get the pcm access for ffmpeg filter wiring\n");
635 r
= snd_pcm_hw_params_get_fmt(hw_params
, &pcm_fmt
);
637 fatal("alsa:unable to get the pcm format for ffmpeg filter wiring\n");
638 /*--------------------------------------------------------------------*/
639 pcm_layout2ff_fmt_strict(pcm_fmt
, pcm_access
, ff_fmt
, print_info
);
640 /*--------------------------------------------------------------------*/
641 r
= snd_pcm_hw_params_get_rate(hw_params
, &pcm_rate
,
642 SND_PCM_ST_PLAYBACK
);
644 fatal("alsa:unable to get the pcm rate for ffmpeg filter wiring\n");
645 *ff_rate
= (int)pcm_rate
;
646 r
= snd_pcm_hw_params_get_chans_n(hw_params
, &pcm_chans_n
);
648 fatal("alsa:unable to get the pcm count of channels for ffmpeg filter wiring\n");
649 /*--------------------------------------------------------------------*/
650 pcm_chmaps2ff_chans_layout(ff_chans_layout
, pcm
, pcm_chans_n
,
652 /*--------------------------------------------------------------------*/
653 snd_pcm_hw_params_free(hw_params
);
656 #define FILT_RECFG_REQUIRED 4
659 #define HAVE_FILT_SET 1
660 #define PRINT_INFO true
661 /* synchronous filt or will end up asynchronous in the pipeline one day */
662 STATIC u8
dec_set_filter(void)
667 AVChannelLayout new_chans_layout
;
669 enum avutil_audio_fr_fmt_t new_fmt
;
670 AVChannelLayout dst_chans_layout
;
672 enum avutil_audio_fr_fmt_t dst_fmt
;
674 memset(&new_chans_layout
, 0, sizeof(new_chans_layout
));
675 memset(&dst_chans_layout
, 0, sizeof(dst_chans_layout
));
677 r
= filt_push_dec_set(&new_chans_layout
, &new_rate
, &new_fmt
);
678 if (r
== NO_DEC_SET
) {/* pipeline not fast enough */
679 av_channel_layout_uninit(&new_chans_layout
);
682 else if (r
!= FILT_RECFG_REQUIRED
) {
683 /* FILT_SWITCHED_TO_DRAINING | PUSHED_ONE_SET | AGAIN */
684 av_channel_layout_uninit(&new_chans_layout
);
687 /* FILT_RECFG_REQUIRED */
688 pcm2ff_strict(npv_audio_pcm_p
, &dst_chans_layout
, &dst_rate
,
689 &dst_fmt
, PRINT_INFO
);
691 &new_chans_layout
, new_rate
, new_fmt
,
692 filt_p
.muted
, filt_p
.vol
,
693 &dst_chans_layout
, dst_rate
, dst_fmt
, PRINT_INFO
);
694 av_channel_layout_uninit(&new_chans_layout
);
695 av_channel_layout_uninit(&dst_chans_layout
);
697 r
= npv_audio_filt_set_get();
699 draining_state_switch();
702 return HAVE_FILT_SET
;
705 #undef FILT_RECFG_REQUIRED
715 #define ALL_FRS_WRITTEN 0
716 /* #define RECOVERED 1 */
717 #define INCOMPLETE_WRITE 2
719 #define PRINT_INFO true
720 STATIC u8
pcm_filt_frs_write(snd_pcm_ufrs_t
*ufrs_n
) { loop
723 u8
*chans_buf
[AVUTIL_DATA_PTRS_N
];
724 snd_pcm_ufrs_t ufrs_to_write_n
;
725 snd_pcm_ufrs_t filt_set_remaining_ufrs_n
; /* for clarity */
727 snd_pcm_ufrs_t written_ufrs_n
; /* for clarity */
730 return ALL_FRS_WRITTEN
;
731 /* synchronous filtering */
732 if (npv_audio_filt_p
.set
->frs_n
== 0) {
735 r
= dec_set_filter();
736 if (r
== NO_DEC_SET
|| r
== DRAINING
)
739 npv_audio_filt_p
.pcm_written_ufrs_n
= 0;
741 chans_buf_init(chans_buf
, (int)npv_audio_filt_p
.pcm_written_ufrs_n
);
742 filt_set_remaining_ufrs_n
= (snd_pcm_ufrs_t
)npv_audio_filt_p
.set
->frs_n
743 - npv_audio_filt_p
.pcm_written_ufrs_n
;
744 if (filt_set_remaining_ufrs_n
> *ufrs_n
)
745 ufrs_to_write_n
= *ufrs_n
;
747 ufrs_to_write_n
= filt_set_remaining_ufrs_n
;
748 is_planar_fmt
= avutil_audio_fr_fmt_is_planar(
749 npv_audio_filt_p
.set
->fmt
);
751 loop
{ /* short write loop */
752 snd_pcm_sfrs_t alsa_r
;
755 if (is_planar_fmt
== NO
)
756 alsa_r
= snd_pcm_writei(pcm_p
, chans_buf
[0],
757 ufrs_to_write_n
- written_ufrs_n
);
759 alsa_r
= snd_pcm_writen(pcm_p
, (void**)chans_buf
,
760 ufrs_to_write_n
- written_ufrs_n
);
761 r_recover
= alsa_recover(alsa_r
);
762 if (r_recover
== AGAIN
)
764 else if (r_recover
== RECOVERED
) {
765 /* account for the written frs anyway */
766 if (npv_audio_filt_p
.pcm_written_ufrs_n
== 0)
767 npv_clk_ref_time_point_update(
768 npv_audio_filt_p
.set
->pts
,
770 npv_audio_filt_p
.pcm_written_ufrs_n
+= written_ufrs_n
;
771 if ((int)npv_audio_filt_p
.pcm_written_ufrs_n
==
772 npv_audio_filt_p
.set
->frs_n
)
773 /* set audio_filt_p.set->frs_n = 0 */
774 avutil_audio_set_unref(npv_audio_filt_p
.set
);
777 /* r_recover == CONTINUE */
778 written_ufrs_n
+= (snd_pcm_ufrs_t
)alsa_r
;
779 if (written_ufrs_n
== ufrs_to_write_n
)
781 chans_buf_inc(chans_buf
, (int)alsa_r
);
784 * this is here we update our ref time point for the audio clk
785 * because with a new filt set of frs, we get a new ts
787 * XXX: getting the "right" ts from ff is shady/convoluted?
789 if (npv_audio_filt_p
.pcm_written_ufrs_n
== 0)
790 npv_clk_ref_time_point_update(npv_audio_filt_p
.set
->pts
,
792 npv_audio_filt_p
.pcm_written_ufrs_n
+= written_ufrs_n
;
793 *ufrs_n
-= written_ufrs_n
;
795 if ((int)npv_audio_filt_p
.pcm_written_ufrs_n
796 == npv_audio_filt_p
.set
->frs_n
)
797 /* set audio_filt_p.av->frs_n = 0 */
798 avutil_audio_set_unref(npv_audio_filt_p
.set
);
805 #undef ALL_FRS_WRITTEN
806 #undef INCOMPLETE_WRITE
809 STATIC
void init_pcm_once_public(u8
*pcm_str
)
813 r
= snd_pcm_open(&pcm_p
, pcm_str
, SND_PCM_ST_PLAYBACK
,
817 fatal("alsa:\"%s\" pcm is already in use\n", pcm_str
);
819 fatal("alsa:unable to open \"%s\" pcm for playback\n", pcm_str
);
822 STATIC
void init_once_public(u8
*pcm_str
)
826 memset(&st_p
, 0, sizeof(st_p
));
827 pkt_q_p
= npv_pkt_q_new("audio");
829 dec_sets_p
.eof_receive
= false;
830 dec_sets_p
.n_max
= 0;
833 init_pcm_once_public(pcm_str
);
834 selected_ts_type_p
= -1;
835 /* linux bug: still no CLOCK_MONOTONIC_RAW for timerfd */
837 draining_timer_fd_p
= timerfd_create(CLOCK_MONOTONIC
, TFD_NONBLOCK
);
838 if (draining_timer_fd_p
== -1)
839 fatal("unable to get a draining timer file descriptor:%s\n", strerror(errno
));
841 r
= pthread_mutex_init(&dec_ctx_mutex_l
, 0);
843 fatal("%d:unable to init the decoder mutex\n", r
);
844 r
= pthread_mutex_init(&dec_sets_p
.mutex
, 0);
846 fatal("%d:unable to init the mutex for the array of decoder sets\n", r
);
848 STATIC
void init_once_local(void)
853 r
= snd_output_stdio_attach(&pcm_pout_l
, stdout
, 0);
855 fatal("alsa:unable to attach stdout\n");
856 r
= snd_output_stdio_attach(&pcm_perr_l
, stderr
, 0);
858 fatal("alsa:unable to attach stderr\n");
859 memset(pcm_silence_bufs_l
, 0, sizeof(pcm_silence_bufs_l
));
861 STATIC
void dec_a_unref_all(void)
867 if (set
== dec_sets_p
.n
)
869 avutil_audio_set_unref(dec_sets_p
.a
[set
]);