4 * code protected with a GNU affero GPLv3 license
5 * copyright (C) 2020 Sylvain BERTRAND
11 * async : ASYNChronous
12 * b(s) : Byte(S) (often)
15 * chan(s) : CHANnel(S)
17 * cp(s) : Code Point(s)
20 * dec : DECoder/DECoded
23 * e : End (usually a pointer on the byte past the last valid byte)
29 * fd : File Descriptor
36 * l10n : LocalizatioN (10 chars between L and N)
38 * msec(s) : MilliSECond(S)
43 * pts : Presentation TimeStamp
45 * ref(s) : REFerence(S)
61 * this is not a library, then we could not care less about memory management
62 * and/or similar cleanup: we have a virtual machine with a garbage collector,
65 * we do presume we won't play more than 8 chans and ff chans layout will
68 * XXX: we don't know how the alsa silence machinery works, then we use brutal
71 /*----------------------------------------------------------------------------*/
87 #include <stdatomic.h>
92 /* linux and compatible */
93 #include <sys/epoll.h>
94 #include <sys/signalfd.h>
95 #include <sys/timerfd.h>
97 #include <libavformat/avformat.h>
98 #include <libavcodec/avcodec.h>
99 #include <libavfilter/avfilter.h>
100 #include <libavfilter/buffersrc.h>
101 #include <libavfilter/buffersink.h>
102 #include <libavutil/opt.h>
104 #include <alsa/asoundlib.h>
105 /*============================================================================*/
106 /* namespaces -- START */
107 /*----------------------------------------------------------------------------*/
117 #define atomic_u8 atomic_uchar
120 #define atomic_uint unsigned int
121 #define atomic_int int
122 #define atomic_load(x) __atomic_load_n(x,__ATOMIC_SEQ_CST)
123 #define atomic_store(x,y) __atomic_store_n(x,y,__ATOMIC_SEQ_CST)
126 #error "unable to find the right atomic for a 8 bits byte, be sure to have __STDC_WANT_IEC_60559_BFP_EXT__ defined on recent gcc"
129 /*----------------------------------------------------------------------------*/
130 /* ff namespace -- START*/
131 #define AV_FR_FMT_NONE AV_SAMPLE_FMT_NONE
132 #define av_bufsink_get_frs av_buffersink_get_frame
133 #define av_bufsrc_add_frs_flags av_buffersrc_add_frame_flags
134 #define AV_BUFSRC_FLAG_KEEP_REF AV_BUFFERSRC_FLAG_KEEP_REF
135 #define AV_BUFSRC_FLAG_PUSH AV_BUFFERSRC_FLAG_PUSH
136 #define av_codec const AVCodec
137 #define av_codec_ctx AVCodecContext
138 #define av_dump_fmt av_dump_format
139 #define av_duration_estimation_method AVDurationEstimationMethod
140 #define av_filt AVFilter
141 #define av_filt_ctx AVFilterContext
142 #define av_filt_get_by_name avfilter_get_by_name
143 #define av_filt_graph AVFilterGraph
144 #define av_filt_graph_alloc avfilter_graph_alloc
145 #define av_filt_graph_alloc_filt avfilter_graph_alloc_filter
146 #define av_filt_graph_cfg avfilter_graph_config
147 #define av_filt_graph_dump avfilter_graph_dump
148 #define av_filt_graph_free avfilter_graph_free
149 #define av_filt_graph_send_cmd avfilter_graph_send_command
150 #define av_filt_init_str avfilter_init_str
151 #define av_filt_link avfilter_link
152 #define av_find_best_st av_find_best_stream
153 #define av_flush_bufs avcodec_flush_buffers
154 #define av_fmt_ctx AVFormatContext
155 #define AV_FMT_DURATION_FROM_BITRATE AVFMT_DURATION_FROM_BITRATE
156 #define AV_FMT_DURATION_FROM_PTS AVFMT_DURATION_FROM_PTS
157 #define AV_FMT_DURATION_FROM_ST AVFMT_DURATION_FROM_STREAM
158 #define av_fmt_find_st_info avformat_find_stream_info
159 #define av_fmt_flush avformat_flush
160 #define av_fmt_open_input avformat_open_input
161 #define av_fr_fmt_is_planar av_sample_fmt_is_planar
162 #define AV_FR_FMT_DBL AV_SAMPLE_FMT_DBL
163 #define AV_FR_FMT_DBLP AV_SAMPLE_FMT_DBLP
164 #define AV_FR_FMT_FLT AV_SAMPLE_FMT_FLT
165 #define AV_FR_FMT_FLTP AV_SAMPLE_FMT_FLTP
166 #define AV_FR_FMT_S16 AV_SAMPLE_FMT_S16
167 #define AV_FR_FMT_S16P AV_SAMPLE_FMT_S16P
168 #define AV_FR_FMT_S32 AV_SAMPLE_FMT_S32
169 #define AV_FR_FMT_S32P AV_SAMPLE_FMT_S32P
170 #define AV_FR_FMT_U8P AV_SAMPLE_FMT_U8P
171 #define AV_FR_FMT_U8 AV_SAMPLE_FMT_U8
172 #define av_frs_alloc av_frame_alloc
173 #define av_frs_set_silence av_samples_set_silence
174 #define av_frs_unref av_frame_unref
175 #define av_get_fr_fmt_name av_get_sample_fmt_name
176 #define av_get_fr_fmt_str av_get_sample_fmt_string
177 #define av_io_flush avio_flush
178 #define AV_MEDIA_TYPE_AUDIO AVMEDIA_TYPE_AUDIO
179 #define av_pkt AVPacket
180 #define av_pkt_unref av_packet_unref
181 #define av_read_pkt av_read_frame
182 #define av_rational AVRational
183 #define av_seek_pkt av_seek_frame
184 #define av_receive_frs avcodec_receive_frame
185 #define av_fr_fmt AVSampleFormat
186 #define av_frs AVFrame
187 #define av_sd_pkt avcodec_send_packet
188 #define av_st AVStream
190 #define fr_fmt sample_fmt
191 #define fr_rate sample_rate
192 #define frs_n nb_samples
193 #define st_idx stream_index
196 /* ff namespace -- END */
197 /*----------------------------------------------------------------------------*/
198 /* alsa namespace -- START */
199 #define snd_pcm_fmt_desc snd_pcm_format_description
200 #define snd_pcm_fmt_set_silence snd_pcm_format_set_silence
201 #define SND_PCM_FMT_FLT SND_PCM_FORMAT_FLOAT
202 #define SND_PCM_FMT_S16 SND_PCM_FORMAT_S16
203 #define SND_PCM_FMT_S24 SND_PCM_FORMAT_S24
204 #define SND_PCM_FMT_S32 SND_PCM_FORMAT_S32
205 #define SND_PCM_FMT_S8 SND_PCM_FORMAT_S8
206 #define snd_pcm_fmt_t snd_pcm_format_t
207 #define SND_PCM_FMT_U16 SND_PCM_FORMAT_U16
208 #define SND_PCM_FMT_U24 SND_PCM_FORMAT_U24
209 #define SND_PCM_FMT_U32 SND_PCM_FORMAT_U32
210 #define SND_PCM_FMT_U8 SND_PCM_FORMAT_U8
211 #define snd_pcm_frs_to_bytes snd_pcm_frames_to_bytes
212 #define snd_pcm_hw_params_get_buf_size snd_pcm_hw_params_get_buffer_size
213 #define snd_pcm_hw_params_get_chans snd_pcm_hw_params_get_channels
214 #define snd_pcm_hw_params_get_chans_max snd_pcm_hw_params_get_channels_max
215 #define snd_pcm_hw_params_get_chans_min snd_pcm_hw_params_get_channels_min
216 #define snd_pcm_hw_params_get_fmt snd_pcm_hw_params_get_format
217 #define snd_pcm_hw_params_set_buf_size_near snd_pcm_hw_params_set_buffer_size_near
218 #define snd_pcm_hw_params_set_chans snd_pcm_hw_params_set_channels
219 #define snd_pcm_hw_params_set_fmt snd_pcm_hw_params_set_format
220 #define snd_pcm_hw_params_test_chans snd_pcm_hw_params_test_channels
221 #define snd_pcm_hw_params_test_fmt snd_pcm_hw_params_test_format
222 #define snd_pcm_sfrs_t snd_pcm_sframes_t
223 #define SND_PCM_ST_PLAYBACK SND_PCM_STREAM_PLAYBACK
224 #define snd_pcm_ufrs_t snd_pcm_uframes_t
225 /* alsa namespace -- END */
226 /* namespaces -- END */
227 /*============================================================================*/
228 #define ARRAY_N(x) (sizeof(x) / sizeof((x)[0]))
229 #define STR_SZ 255 /* sz and idx fit in 1 byte */
230 /*---------------------------------------------------------------------------*/
231 static u8
*current_url
;
232 static int current_st_idx
;
233 /* cmd_info must be fast, then a lockless copy of its data */
237 enum av_duration_estimation_method m
;
245 /*---------------------------------------------------------------------------*/
246 /* linux and compatible */
249 /*---------------------------------------------------------------------------*/
251 static snd_pcm_t
*pcm_g
;
252 static snd_output_t
*pcm_pout
;
253 static snd_output_t
*pcm_perr
;
254 #define PCM_POLLFDS_N_MAX 16 /* banzai */
255 static struct pollfd pcm_pollfds
[PCM_POLLFDS_N_MAX
];
256 static u8 pcm_pollfds_n
;
257 /*---------------------------------------------------------------------------*/
259 static av_pkt
*rd_thd_pkt
;
260 static av_fmt_ctx
*fmt_ctx
;
261 static pthread_mutex_t fmt_ctx_mutex
;
262 static av_codec
*dec
;
263 static av_codec_ctx
*dec_ctx
;
264 /*---------------------------------------------------------------------------*/
266 static av_filt_graph
*filt_graph
;
267 static av_filt_ctx
*abufsrc_ctx
;
268 static const av_filt
*abufsrc_filt
;
269 static struct { /* used to detected reconfiguration */
270 AVChannelLayout chans_layout
;
274 static av_filt_ctx
*vol_ctx
;
275 static const av_filt
*vol_filt
;
276 static u8 double_zero_l10n_str
[sizeof("xxx.xx")];
277 static av_filt_ctx
*afmt_ctx
;
278 static const av_filt
*afmt_filt
;
279 static av_filt_ctx
*abufsink_ctx
;
280 static const av_filt
*abufsink_filt
;
281 /*---------------------------------------------------------------------------*/
282 /* a formally proven concurrently accessed lockless cb */
296 bool pushed_in_filt_graph
;
297 int64_t most_recent_ts
; /* a very "coarse-grained" clock */
303 snd_pcm_ufrs_t pcm_written_ufrs_n
;
305 /* we will inject silence frs while paused */
307 void *silence_bufs
[AV_NUM_DATA_POINTERS
];
308 /*----------------------------------------------------------------------------*/
310 static bool stdin_tty_cfg_modified
;
311 static struct termios stdin_tio_save
;
312 static int stdin_flags_save
;
313 static bool stdout_is_tty
;
314 /*----------------------------------------------------------------------------*/
315 static void cmd_quit(void);
316 static void cmd_rewind(void);
317 static void cmd_fastforward(void);
318 static void cmd_rewind_big(void);
319 static void cmd_fastforward_big(void);
320 static void cmd_vol_up(void);
321 static void cmd_vol_down(void);
322 static void cmd_vol_up_small(void);
323 static void cmd_vol_down_small(void);
324 static void cmd_mute(void);
325 static void cmd_info(void);
326 static void cmd_pause(void);
327 /*--------------------------------------------------------------------------*/
328 #include "npa_config.h"
329 /*----------------------------------------------------------------------------*/
330 /* input "state" machine (2 major states: "utf8" and "esc seq" */
331 static int input_timer_fd
;
332 static bool input_esc_seq_mode
;
333 static u8 input_b
; /* input byte */
335 static u8 utf8_cp
[4];
336 static u8 utf8_cp_next_byte
; /* idx in utf8_cp */
337 static u8 utf8_cp_sz
;
339 static u8 esc_seq
[STR_SZ
];
340 static u8 esc_seq_next_byte
; /* idx in esc_seq */
341 #define esc_seq_sz esc_seq_next_byte /* the idx of the next byte is its sz */
342 /*----------------------------------------------------------------------------*/
343 static void pout(u8
*fmt
, ...);
344 static void perr(u8
*fmt
, ...);
345 static void warning(u8
*fmt
, ...);
346 static void fatal(u8
*fmt
, ...);
347 static void exit_ok(u8
*fmt
, ...);
348 /*----------------------------------------------------------------------------*/
349 static void stdin_flags_restore(void)
353 r
= fcntl(0, F_SETFL
, stdin_flags_save
);
355 warning("input:unable to restore the file flags of the standard input\n");
357 static void stdin_tty_cfg_restore(void)
360 struct termios tio_chk
;
362 if (!stdin_tty_cfg_modified
)
364 r
= tcsetattr(0, TCSANOW
, &stdin_tio_save
);
366 warning("input:unable to restore the terminal line attributes\t");
369 memset(&tio_chk
, 0, sizeof(tio_chk
));
370 r
= tcgetattr(0, &tio_chk
);
372 warning("input:unable to get the current terminal line attributes for restoration checking\n");
375 r
= memcmp(&tio_chk
, &stdin_tio_save
, sizeof(tio_chk
));
377 warning("input:only partial restoration of the terminal line attributes\n");
379 /*----------------------------------------------------------------------------*/
380 static void pout(u8
*fmt
, ...)
385 vfprintf(stdout
, fmt
, ap
);
388 static void perr(u8
*fmt
, ...)
393 vfprintf(stderr
, fmt
, ap
);
396 static void warning(u8
*fmt
, ...)
400 fprintf(stderr
, "warning:");
402 vfprintf(stderr
, fmt
, ap
);
405 static void fatal(u8
*fmt
, ...)
409 fprintf(stderr
, "fatal:");
411 vfprintf(stderr
, fmt
, ap
);
413 stdin_flags_restore();
414 stdin_tty_cfg_restore();
417 static void exit_ok(u8
*fmt
, ...)
421 fprintf(stderr
, "exit_ok:");
423 vfprintf(stderr
, fmt
, ap
);
425 stdin_flags_restore();
426 stdin_tty_cfg_restore();
429 /*----------------------------------------------------------------------------*/
430 static void fmt_ctx_lock(void)
434 r
= pthread_mutex_lock(&fmt_ctx_mutex
);
436 fatal("unable to lock the format context\n");
438 static void fmt_ctx_unlock(void)
442 r
= pthread_mutex_unlock(&fmt_ctx_mutex
);
444 fatal("unable to unlock the format context\n");
446 static u8
*duration_estimate_to_str(enum av_duration_estimation_method m
)
449 case AV_FMT_DURATION_FROM_PTS
:
450 return "from PTS(Presentation TimeStamp)";
451 case AV_FMT_DURATION_FROM_ST
:
452 return "from stream";
453 case AV_FMT_DURATION_FROM_BITRATE
:
454 return "from bitrate";
460 static u8
*ts_to_str(int64_t ts
, av_rational tb
, int64_t *remaining
)
462 static u8 str
[sizeof("~S00:00:00.000 remains S9223372036854775807 time base units")];
468 int64_t one_hour
; /* in ff tb units */
469 int64_t one_min
; /* in ff tb units */
470 int64_t one_sec
; /* in ff tb units */
471 int64_t one_msec
; /* in ff tb units */
478 one_hour
= INT64_C(3600) * (int64_t)tb
.den
/ (int64_t)tb
.num
;
479 one_min
= INT64_C(60) * (int64_t)tb
.den
/ (int64_t)tb
.num
;
480 one_sec
= (int64_t)tb
.den
/ (int64_t)tb
.num
;
481 one_msec
= one_sec
/ INT64_C(1000);
483 hours_n
= ts
/ one_hour
;
485 *remaining
= ts
% one_hour
;
486 mins_n
= *remaining
/ one_min
;
488 *remaining
= *remaining
% one_min
;
489 secs_n
= *remaining
/ one_sec
;
491 *remaining
= *remaining
% one_sec
;
492 msecs_n
= *remaining
/ one_msec
;
494 /* account for all rounding errors */
495 *remaining
= ts
- (hours_n
* one_hour
+ mins_n
* one_min
496 + secs_n
* one_sec
+ msecs_n
* one_msec
);
498 snprintf(str
, sizeof(str
), "%02"PRId64
":%02"PRId64
":%02"PRId64
".%03"PRId64
, hours_n
, mins_n
, secs_n
, msecs_n
);
501 snprintf(str
+ 1, sizeof(str
) - 1, "%02"PRId64
":%02"PRId64
":%02"PRId64
".%03"PRId64
, hours_n
, mins_n
, secs_n
, msecs_n
);
505 #define RED if (stdout_is_tty) pout("\x1b[38;2;255;0;0m")
506 #define GREEN if (stdout_is_tty) pout("\x1b[38;2;0;255;0m")
507 #define BLUE if (stdout_is_tty) pout("\x1b[38;2;0;0;255m")
508 #define PURPLE if (stdout_is_tty) pout("\x1b[38;2;255;0;255m")
509 #define RESTORE if (stdout_is_tty) pout("\x1b[39;49m")
510 static void cmd_info(void)
514 u8 duration_str
[sizeof("S9223372036854775807")];
517 GREEN
;pout("================================================================================\n");RESTORE
;
518 PURPLE
;pout("%s\n", current_url
);RESTORE
;
519 ts_str
= ts_to_str(dec_frs
.most_recent_ts
, cmd_info_data
.st
.tb
, &remaining
);
520 RED
;pout("%s", ts_str
);RESTORE
;
522 pout(" remaining %"PRId64
" time base units", remaining
);
525 pout("\t%"PRId64
" stream time base units (%d/%d seconds)\n", dec_frs
.most_recent_ts
, cmd_info_data
.st
.tb
.num
, cmd_info_data
.st
.tb
.den
);
526 BLUE
;pout("--------------------------------------------------------------------------------\n");RESTORE
;
528 if (cmd_info_data
.fmt
.duration
== AV_NOPTS_VALUE
) {
529 pout("duration is not provided\n");
531 snprintf(duration_str
, sizeof(duration_str
), "%"PRId64
, cmd_info_data
.fmt
.duration
);
532 ts_str
= ts_to_str(cmd_info_data
.fmt
.duration
, AV_TIME_BASE_Q
,
534 pout("duration=");RED
;pout("%s", ts_str
);RESTORE
;
536 pout(" remaining %"PRId64
" av_time_base units\n", remaining
);
539 pout("\t%s av_time_base units (1/%d seconds)\n\testimation method is %s\n", duration_str
, AV_TIME_BASE
, duration_estimate_to_str(cmd_info_data
.fmt
.m
));
541 pout("stream:id=%d", cmd_info_data
.st
.id
);
542 if (cmd_info_data
.st
.duration
== AV_NOPTS_VALUE
) {
543 pout(";duration is not provided\n");
545 snprintf(duration_str
, sizeof(duration_str
), "%"PRId64
, cmd_info_data
.st
.duration
);
546 ts_str
= ts_to_str(cmd_info_data
.st
.duration
, cmd_info_data
.st
.tb
, &remaining
);
547 pout(";duration=");RED
;pout("%s\n", ts_str
);RESTORE
;
549 pout(" remaining %"PRId64
" stream time base units\n", remaining
);
552 pout("\t%s stream time base units (%d/%d seconds)\n", duration_str
, cmd_info_data
.st
.tb
.num
, cmd_info_data
.st
.tb
.den
);
554 BLUE
;pout("--------------------------------------------------------------------------------\n");RESTORE
;
555 pout("circular buffer: %u/%u/%u (read/send/max)\n", atomic_load(&cb
.rd
), atomic_load(&cb
.sd
), cb
.pkts_n
);
557 RED
;pout("paused\n");RESTORE
;
559 if (filt_frs
.muted
) {
560 RED
;pout("muted\n");RESTORE
;
562 GREEN
;pout("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");RESTORE
;
569 static void wait(long ns
)
571 struct timespec wanted
;
574 memset(&wanted
, 0, sizeof(wanted
));
575 memset(&rem
, 0, sizeof(rem
));
580 /* linux bug: cannot specify CLOCK_MONOTONIC_RAW */
581 r
= clock_nanosleep(CLOCK_MONOTONIC
, 0, &wanted
, &rem
);
585 fatal("wait timer failed:%d\n", r
);
587 memcpy(&wanted
, &rem
, sizeof(wanted
));
588 memset(&rem
, 0, sizeof(rem
));
591 static void wait_cb_filling(void)
593 struct timespec wanted
;
596 memset(&wanted
, 0, sizeof(wanted
));
597 memset(&rem
, 0, sizeof(rem
));
598 wanted
.tv_nsec
= 4000000; /* 4 ms */
602 /* linux bug: cannot specify CLOCK_MONOTONIC_RAW */
603 r
= clock_nanosleep(CLOCK_MONOTONIC
, 0, &wanted
, &rem
);
607 rd
= atomic_load(&cb
.rd
);
608 if (rd
== (cb
.pkts_n
- 1))
610 memset(&wanted
, 0, sizeof(wanted
));
611 memset(&rem
, 0, sizeof(rem
));
612 wanted
.tv_nsec
= 4000000; /* 4 ms */
616 fatal("wait cb filling timer failed:%d\n", r
);
618 memcpy(&wanted
, &rem
, sizeof(wanted
));
619 memset(&rem
, 0, sizeof(rem
));
623 static void do_reset(void)
628 av_fmt_flush(fmt_ctx
);
629 av_io_flush(fmt_ctx
->pb
);
633 av_pkt_unref(cb
.pkts
[i
]);
638 atomic_store(&cb
.rd
, 0);
639 atomic_store(&cb
.sd
, 0);
640 atomic_store(&cb
.reset
, RESET_DONE
);
645 static void rd_loop(void) { loop
/* infinite loop */
649 unsigned int next_rd
;
655 * XXX: we actually perform reset on this thd, with a little lockfree
656 * protocol and reasonable wait loops
658 reset
= atomic_load(&cb
.reset
);
659 if (reset
== DO_RESET
)
661 /*--------------------------------------------------------------------*/
662 hold
= atomic_load(&cb
.hold
);
664 wait(1000000); /* 1ms */
667 /*--------------------------------------------------------------------*/
668 rd
= atomic_load(&cb
.rd
);
669 sd
= atomic_load(&cb
.sd
);
670 next_rd
= (rd
+ 1) % cb
.pkts_n
;
671 if (next_rd
== sd
) { /* must sd first the sd slot */
672 wait(1000000); /* 1ms */
675 /*--------------------------------------------------------------------*/
677 r
= av_read_pkt(fmt_ctx
, rd_thd_pkt
);
679 if (r
== AVERROR(EAGAIN
)) {
680 /* 1ms: it is sort of aggressive to check for reset */
683 } else if (r
== AVERROR_EOF
) {
684 /* The "NULL" pkt ref to signal the EOF to the dec */
685 cb
.pkts
[rd
]->data
= 0;
686 cb
.pkts
[rd
]->size
= 0;
688 fatal("ffmpeg:error while demuxing coded/compressed data into packets\n");
690 st_idx
= atomic_load(&cb
.st_idx
);
691 if (rd_thd_pkt
->st_idx
!= st_idx
) { /* sd_idx can be -1 */
692 av_pkt_unref(rd_thd_pkt
);
695 av_packet_move_ref(cb
.pkts
[rd
], rd_thd_pkt
);
697 atomic_store(&cb
.rd
, next_rd
);
701 static void *rd_thd_entry(void *arg
)
706 r
= sigfillset(&sset
);
708 fatal("read thread:unable to get a full signal mask\n");
709 r
= pthread_sigmask(SIG_SETMASK
, &sset
, 0);
711 fatal("read thread:unable to \"block\" \"all\" signals\n");
715 static void rd_thd_start(int st_index
)
721 atomic_store(&cb
.st_idx
, st_index
);
722 r
= pthread_attr_init(&attr
);
724 fatal("read thread:unable to initialize read thread attribute\n");
725 r
= pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
727 fatal("read thread:unable to set the read thread attribute to detach mode\n");
728 r
= pthread_create(&id
, &attr
, &rd_thd_entry
, 0);
730 fatal("read thread:unable to create the read thread\n");
731 pout("read thread %lu\n", (unsigned long)id
);
732 pthread_attr_destroy(&attr
);
734 static void cmd_quit(void)
736 exit_ok("quit command received\n");
740 static void rd_thd_reset(int st_idx
)
745 /* reset = RESET_DONE */
746 atomic_store(&cb
.st_idx
, st_idx
);
747 atomic_store(&cb
.reset
, DO_RESET
);
751 reset
= atomic_load(&cb
.reset
);
752 if (reset
== RESET_DONE
)
754 wait(1000000); /* 1ms */
756 if (loops_n
== 4000) /* 1ms * 4000 = 4s */
757 fatal("read thread reset timeout\n");
759 /* reset = DO_RESET */
764 * XXX: if it is ever used significantly, a fine granularity wiring strategy
765 * will be implemented instead of using the default wiring
767 static void pcm_chmaps2ff_chans_layout(AVChannelLayout
*ff_chans_layout
,
768 snd_pcm_t
*pcm
, unsigned int pcm_chans_n
, bool print_info
)
772 snd_pcm_chmap_t
*pcm_chmap
;
773 u8 chans_layout_str
[STR_SZ
]; /* should be overkill */
775 pcm_chmap
= snd_pcm_get_chmap(pcm
);
776 if (pcm_chmap
== 0) {
778 pout("alsa:no pcm channel map available, wiring to default ffmpeg channel layout\n");
781 pout("alsa:your pcm device support channel maps, but fine granularity wiring strategy is not implemented\n");
784 av_channel_layout_default(ff_chans_layout
, (int)pcm_chans_n
);
785 av_channel_layout_describe(ff_chans_layout
, chans_layout_str
,
786 sizeof(chans_layout_str
));
788 pout("alsa channel map wired to ffmpeg channel layout:\"%s\" (%u pcm channels)\n", chans_layout_str
, pcm_chans_n
);
790 /* fatal if the wiring cannot be done */
791 static void pcm_layout2ff_fmt_strict(snd_pcm_fmt_t alsa_fmt
,
792 snd_pcm_access_t alsa_access
, enum av_fr_fmt
*ff_fmt
, bool print_info
)
795 * ff fmt byte order is always native.
796 * here we handle little endian only
799 case SND_PCM_FMT_FLT
:
800 if (alsa_access
== SND_PCM_ACCESS_RW_INTERLEAVED
)
801 *ff_fmt
= AV_FR_FMT_FLT
;
803 *ff_fmt
= AV_FR_FMT_FLTP
;
805 case SND_PCM_FMT_S32
:
806 if (alsa_access
== SND_PCM_ACCESS_RW_INTERLEAVED
)
807 *ff_fmt
= AV_FR_FMT_S32
;
809 *ff_fmt
= AV_FR_FMT_S32P
;
811 case SND_PCM_FMT_S16
:
812 if (alsa_access
== SND_PCM_ACCESS_RW_INTERLEAVED
)
813 *ff_fmt
= AV_FR_FMT_S16
;
815 *ff_fmt
= AV_FR_FMT_S16P
;
818 if (alsa_access
== SND_PCM_ACCESS_RW_INTERLEAVED
)
819 *ff_fmt
= AV_FR_FMT_U8
;
821 *ff_fmt
= AV_FR_FMT_U8P
;
824 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
));
827 u8 ff_fmt_str
[STR_SZ
];
829 av_get_fr_fmt_str(ff_fmt_str
, sizeof(ff_fmt_str
), *ff_fmt
);
830 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
);
833 static void pcm2ff(snd_pcm_t
*pcm
, enum av_fr_fmt
*ff_fmt
, int *ff_rate
,
834 AVChannelLayout
*ff_chans_layout
, bool print_info
)
837 snd_pcm_hw_params_t
*hw_params
;
838 snd_pcm_access_t pcm_access
;
839 snd_pcm_fmt_t pcm_fmt
;
840 unsigned int pcm_rate
;
841 unsigned int pcm_chans_n
;
843 r
= snd_pcm_hw_params_malloc(&hw_params
);
845 fatal("alsa:unable to allocate hardware parameters context for ffmpeg filter wiring\n");
846 r
= snd_pcm_hw_params_current(pcm
, hw_params
);
848 fatal("alsa:unable to get current hardware parameters for ffmpeg filter wiring\n");
849 r
= snd_pcm_hw_params_get_access(hw_params
, &pcm_access
);
851 fatal("alsa:unable to get the pcm access for ffmpeg filter wiring\n");
852 r
= snd_pcm_hw_params_get_fmt(hw_params
, &pcm_fmt
);
854 fatal("alsa:unable to get the pcm format for ffmpeg filter wiring\n");
855 /*--------------------------------------------------------------------*/
856 pcm_layout2ff_fmt_strict(pcm_fmt
, pcm_access
, ff_fmt
, print_info
);
857 /*--------------------------------------------------------------------*/
858 r
= snd_pcm_hw_params_get_rate(hw_params
, &pcm_rate
,
859 SND_PCM_ST_PLAYBACK
);
861 fatal("alsa:unable to get the pcm rate for ffmpeg filter wiring\n");
862 *ff_rate
= (int)pcm_rate
;
863 r
= snd_pcm_hw_params_get_chans(hw_params
, &pcm_chans_n
);
865 fatal("alsa:unable to get the pcm count of channels for ffmpeg filter wiring\n");
866 /*--------------------------------------------------------------------*/
867 pcm_chmaps2ff_chans_layout(ff_chans_layout
, pcm
, pcm_chans_n
,
869 /*--------------------------------------------------------------------*/
870 snd_pcm_hw_params_free(hw_params
);
872 /* XXX: we don't program the tb of the filter since it should not be used */
873 static void abufsrc_cfg(enum av_fr_fmt fmt
, int rate
,
874 AVChannelLayout
*chans_layout
, bool print_info
)
877 u8 chans_layout_str
[STR_SZ
]; /* should be overkill */
879 abufsrc_filt
= av_filt_get_by_name("abuffer");
880 if (abufsrc_filt
== 0)
881 fatal("audio buffer source:could not find the filter\n");
882 abufsrc_ctx
= av_filt_graph_alloc_filt(filt_graph
, abufsrc_filt
,
884 if (abufsrc_ctx
== 0)
885 fatal("audio buffer source context:could not allocate the instance in the filter graph\n");
886 r
= av_opt_set(abufsrc_ctx
, "sample_fmt", av_get_fr_fmt_name(fmt
),
887 AV_OPT_SEARCH_CHILDREN
);
889 fatal("audio buffer source context:unable to set the decoder frame format option\n");
890 r
= av_opt_set_int(abufsrc_ctx
, "sample_rate", rate
,
891 AV_OPT_SEARCH_CHILDREN
);
893 fatal("audio buffer source context:unable to set the decoder rate option\n");
894 av_channel_layout_describe(chans_layout
, chans_layout_str
,
895 sizeof(chans_layout_str
));
897 pout("audio buffer source context:using channels layout \"%s\"\n", chans_layout_str
);
898 r
= av_opt_set(abufsrc_ctx
, "channel_layout", chans_layout_str
,
899 AV_OPT_SEARCH_CHILDREN
);
901 fatal("audio buffer source context:unable to set the decoder channel layout option\n");
902 r
= av_filt_init_str(abufsrc_ctx
, 0);
904 fatal("audio buffer source context:unable to initialize\n");
906 static void vol_cfg(bool muted
, double vol
)
909 u8 vol_l10n_str
[sizeof("xxx.xx")]; /* should be overkill */
912 vol_filt
= av_filt_get_by_name("volume");
914 fatal("volume:could not find the filter\n");
915 vol_ctx
= av_filt_graph_alloc_filt(filt_graph
, vol_filt
, "vol");
917 fatal("volume context:could not allocate the instance in the filter graph\n");
922 /* yeah the radix is localized, can be '.', ','... */
923 snprintf(vol_l10n_str
, sizeof(vol_l10n_str
), "%f", vol_double
);
924 r
= av_opt_set(vol_ctx
, "volume", vol_l10n_str
, AV_OPT_SEARCH_CHILDREN
);
926 fatal("volume context:unable to set the volume option\n");
927 r
= av_filt_init_str(vol_ctx
, 0);
929 fatal("volume buffer context:unable to initialize\n");
931 static void afmt_cfg(enum av_fr_fmt fmt
, int rate
,
932 AVChannelLayout
*chans_layout
, bool print_info
)
935 u8 rate_str
[sizeof("dddddd")];
936 u8 chans_layout_str
[STR_SZ
]; /* should be overkill */
938 afmt_filt
= av_filt_get_by_name("aformat");
940 fatal("audio format:could not find the filter");
941 afmt_ctx
= av_filt_graph_alloc_filt(filt_graph
, afmt_filt
, "afmt");
943 fatal("audio format:could not allocate the instance in the filter graph\n");
944 r
= av_opt_set(afmt_ctx
, "sample_fmts", av_get_fr_fmt_name(fmt
),
945 AV_OPT_SEARCH_CHILDREN
);
947 fatal("audio format context:could to set the pcm sample format\n");
948 snprintf(rate_str
, sizeof(rate_str
), "%d", rate
);
949 r
= av_opt_set(afmt_ctx
, "sample_rates", rate_str
,
950 AV_OPT_SEARCH_CHILDREN
);
952 fatal("audio format context:could not set the pcm rate\n");
953 av_channel_layout_describe(chans_layout
, chans_layout_str
,
954 sizeof(chans_layout_str
));
955 r
= av_opt_set(afmt_ctx
, "channel_layouts", chans_layout_str
,
956 AV_OPT_SEARCH_CHILDREN
);
958 fatal("audio format context:could not set the layout of channels\n");
960 pout("audio format context:channel layout is \"%s\"\n", chans_layout_str
);
961 r
= av_filt_init_str(afmt_ctx
, 0);
963 fatal("audio format context:unable to initialize\n");
965 static void abufsink_cfg(void)
969 abufsink_filt
= av_filt_get_by_name("abuffersink");
970 if (abufsink_filt
== 0)
971 fatal("audio buffer sink:could not find the filter\n");
972 abufsink_ctx
= av_filt_graph_alloc_filt(filt_graph
, abufsink_filt
,
974 if (abufsink_ctx
== 0)
975 fatal("audio buffer sink context:could not allocate the instance in the filter graph\n");
976 r
= av_filt_init_str(abufsink_ctx
, 0);
978 fatal("audio buffer sink context:unable to initialize\n");
980 static void dec_ctx_cfg(AVCodecParameters
*params
)
984 dec
= avcodec_find_decoder(params
->codec_id
);
986 fatal("ffmpeg:unable to find a proper decoder\n");
987 avcodec_free_context(&dec_ctx
);
988 dec_ctx
= avcodec_alloc_context3(dec
);
990 fatal("ffmpeg:unable to allocate a decoder context\n");
992 r
= avcodec_parameters_to_context(dec_ctx
, params
);
994 fatal("ffmpeg:unable to apply codec parameters in codec context\n");
995 /* XXX: ffmpeg thread count default is 1, set to 0 = auto */
996 dec_ctx
->thread_count
= 0;
997 r
= avcodec_open2(dec_ctx
, dec
, 0);
999 fatal("ffmpeg:unable to open the decoder context\n");
1001 static void filt_graph_cfg(
1002 enum av_fr_fmt src_fmt
, int src_rate
,
1003 AVChannelLayout
*src_chans_layout
,
1004 bool muted
, double vol
,
1005 enum av_fr_fmt dst_fmt
, int dst_rate
,
1006 AVChannelLayout
*dst_chans_layout
, bool print_info
)
1011 av_filt_graph_free(&filt_graph
);
1013 filt_graph
= av_filt_graph_alloc();
1014 if (filt_graph
== 0)
1015 fatal("unable to create filter graph\n");
1016 abufsrc_cfg(src_fmt
, src_rate
, src_chans_layout
, print_info
);
1017 /*--------------------------------------------------------------------*/
1018 r
= av_channel_layout_copy(&abufsrc_key
.chans_layout
, src_chans_layout
);
1020 fatal("unable to copy the source channel layout in the key\n");
1021 abufsrc_key
.rate
= src_rate
;
1022 abufsrc_key
.fmt
= src_fmt
;
1023 /*--------------------------------------------------------------------*/
1024 vol_cfg(muted
, vol
);
1025 afmt_cfg(dst_fmt
, dst_rate
, dst_chans_layout
, print_info
);
1027 r
= av_filt_link(abufsrc_ctx
, 0, vol_ctx
, 0);
1029 fatal("unable to connect the audio buffer source filter to the volume filter\n");
1030 r
= av_filt_link(vol_ctx
, 0, afmt_ctx
, 0);
1032 fatal("unable to connect the volume filter to the audio format filter\n");
1033 r
= av_filt_link(afmt_ctx
, 0, abufsink_ctx
, 0);
1035 fatal("unable to connect the audio format filter to the audio buffer sink filter\n");
1036 r
= av_filt_graph_cfg(filt_graph
, 0);
1038 fatal("unable to configure the filter graph\n");
1039 /*--------------------------------------------------------------------*/
1042 dump_str
= av_filt_graph_dump(filt_graph
, 0);
1043 if (dump_str
== 0) {
1044 warning("unable to get a filter graph description\n");
1047 pout("GRAPH START-------------------------------------------------------\n");
1048 pout("%s", dump_str
);
1050 pout("GRAPH END---------------------------------------------------------\n");
1052 #define DONT_PRINT_INFO false
1053 static void filt_flush(void)
1055 enum av_fr_fmt dst_fmt
;
1058 AVChannelLayout src_chans_layout
;
1059 AVChannelLayout dst_chans_layout
;
1062 memset(&src_chans_layout
, 0, sizeof(src_chans_layout
));
1063 memset(&dst_chans_layout
, 0, sizeof(dst_chans_layout
));
1065 av_frs_unref(filt_frs
.av
);
1066 filt_frs
.pcm_written_ufrs_n
= 0;
1068 pcm2ff(pcm_g
, &dst_fmt
, &dst_rate
, &dst_chans_layout
,
1070 /* the audio dec ctx may not have a valid chans layout */
1071 r
= av_channel_layout_check(&dec_ctx
->ch_layout
);
1072 if (r
== 0) /* XXX: we expect at least chans_n to be valid */
1073 av_channel_layout_default(&src_chans_layout
,
1074 dec_ctx
->ch_layout
.nb_channels
);
1076 av_channel_layout_copy(&src_chans_layout
, &dec_ctx
->ch_layout
);
1078 dec_ctx
->fr_fmt
, dec_ctx
->fr_rate
, &src_chans_layout
,
1079 filt_frs
.muted
, filt_frs
.vol
,
1080 dst_fmt
, dst_rate
, &dst_chans_layout
,
1082 av_channel_layout_uninit(&src_chans_layout
);
1083 av_channel_layout_uninit(&dst_chans_layout
);
1085 #undef DONT_PRINT_INFO
1086 static void stdin_tty_init_once(void)
1089 struct termios tio_new
;
1090 struct termios tio_chk
;
1094 pout("input:standard input is not a terminal\n");
1097 memset(&tio_new
, 0, sizeof(tio_new
));
1098 memset(&tio_chk
, 0, sizeof(tio_chk
));
1099 memset(&stdin_tio_save
, 0, sizeof(stdin_tio_save
));
1100 r
= tcgetattr(0, &stdin_tio_save
);
1102 fatal("input:unable to get the current standard input terminal line attributes\n");
1103 tio_new
= stdin_tio_save
;
1104 tio_new
.c_lflag
&= ~(ICANON
|ECHO
);
1105 tio_new
.c_cc
[VMIN
] = 1; /* 1 "char", could be bytes from a utf8 code point */
1106 tio_new
.c_cc
[VTIME
] = 0;
1107 r
= tcsetattr(0, TCSANOW
, &tio_new
);
1108 stdin_tty_cfg_modified
= true;
1110 fatal("input:unable to set all standard input terminal line\n");
1111 r
= tcgetattr(0, &tio_chk
);
1113 fatal("input:unable to get the current standard input terminal line attributes for checking\n");
1114 r
= memcmp(&tio_chk
, &tio_new
, sizeof(tio_chk
));
1116 fatal("input:setting the wanted terminal line attributes failed\n");
1118 static void stdin_flags_init_once(void)
1121 /* switch the standard input to non-blocking */
1122 r
= fcntl(0, F_GETFL
);
1124 fatal("input:unable to get the file flags of the standard input\n");
1125 stdin_flags_save
= r
;
1127 r
= fcntl(0, F_SETFL
, r
);
1129 fatal("input:unable to set non-blocking operations on the standard input\n");
1131 static void stdout_init_once(void)
1137 pout("output:standard output not is not a terminal\n");
1138 stdout_is_tty
= false;
1141 stdout_is_tty
= true;
1144 * block as much as possible.
1145 * handle only async "usual" sigs, with sync signalfd.
1146 * allow some signals to go thru though.
1147 * always presume the process "controlling terminal" is different than the
1148 * terminal connected on standard input and standard output
1150 static void sigs_init_once(void)
1155 r
= sigfillset(&sset
);
1157 fatal("unable to get a full signal mask\n");
1158 /* the "controlling terminal" line asks for a core dump, leave it be */
1159 r
= sigdelset(&sset
, SIGQUIT
);
1161 fatal("unable to remove SIGQUIT from our signal mask\n");
1162 r
= pthread_sigmask(SIG_SETMASK
, &sset
, 0);
1164 fatal("unable to \"block\" \"all\" signals\n");
1165 /* from here, we "steal" signals with signalfd */
1166 r
= sigemptyset(&sset
);
1168 fatal("unable to get an empty signal mask\n");
1169 /* we are asked nicely to terminate */
1170 r
= sigaddset(&sset
, SIGTERM
);
1172 fatal("unable to add SIGTERM to our signal mask\n");
1173 /* the "controlling terminal" line (^c) asks nicely to terminate */
1174 r
= sigaddset(&sset
, SIGINT
);
1176 fatal("unable to add SIGINT to our signal mask\n");
1177 r
= signalfd(-1, &sset
, SFD_NONBLOCK
);
1179 fatal("unable to get a signalfd file descriptor\n");
1182 static void evt_init_once(void)
1186 struct epoll_event evt
;
1188 ep_fd
= epoll_create1(0);
1190 fatal("unable to create the epoll file descriptor\n");
1191 /*--------------------------------------------------------------------*/
1193 evt
.events
= EPOLLIN
;
1194 evt
.data
.fd
= sig_fd
;
1195 r
= epoll_ctl(ep_fd
, EPOLL_CTL_ADD
, sig_fd
, &evt
);
1197 fatal("unable to add the signalfd file descriptior to the epoll file descriptor\n");
1198 /*--------------------------------------------------------------------*/
1199 /* standard input/terminal */
1200 evt
.events
= EPOLLIN
;
1202 r
= epoll_ctl(ep_fd
, EPOLL_CTL_ADD
, 0, &evt
);
1204 fatal("unable to add the standard input to the epoll file descriptor\n");
1205 /*--------------------------------------------------------------------*/
1206 /* the timer in charge of accounting unknown esc seq */
1207 evt
.events
= EPOLLIN
;
1208 evt
.data
.fd
= input_timer_fd
;
1209 r
= epoll_ctl(ep_fd
, EPOLL_CTL_ADD
, input_timer_fd
, &evt
);
1211 fatal("unable to add the timer file descriptor accounting for unknown escape sequences to epoll file descriptor\n");
1213 static void input_state_init_once(void)
1215 input_timer_fd
= timerfd_create(CLOCK_MONOTONIC
, TFD_NONBLOCK
);
1216 if (input_timer_fd
== -1)
1217 fatal("unable to get a timer file descriptor\n");
1219 input_esc_seq_mode
= false;
1221 esc_seq_next_byte
= 0;
1222 utf8_cp_next_byte
= 0;
1224 static void input_utf8_cp_bind_cmd(void)
1230 struct tty_bind_t
*bind
;
1232 if (i
== ARRAY_N(tty_binds
))
1234 bind
= tty_binds
+ i
;
1236 /* exclude esc seq binds */
1237 if ((bind
->c
[0] != 0x1b) && (utf8_cp_sz
== bind
->sz
)) {
1240 r
= memcmp(utf8_cp
, bind
->c
, utf8_cp_sz
);
1250 * to exit the esc seq input mode, we could implement a smart tree in order to
1251 * know if it is not possible to get any defined esc seq, or we could already
1252 * use the maximum bind esc seq sz
1254 static bool input_esc_seq_bind_cmd(void)
1260 struct tty_bind_t
*bind
;
1262 if (i
== ARRAY_N(tty_binds
))
1264 bind
= tty_binds
+ i
;
1265 /* only esc seq binds */
1266 if ((bind
->c
[0] == 0x1b) && (esc_seq_sz
== bind
->sz
)) {
1269 r
= memcmp(esc_seq
, bind
->c
, esc_seq_sz
);
1279 static void input_byte_esc_seq(void)
1282 struct itimerspec t
;
1284 if (input_b
== 0x1b) {
1286 esc_seq_next_byte
= 1;
1287 memset(&t
, 0, sizeof(t
));
1288 t
.it_value
.tv_sec
= INPUT_ESC_SEQ_TIMEOUT_SECS_N
;
1289 r
= timerfd_settime(input_timer_fd
, 0, &t
, 0);
1291 fatal("unable to arm the timer to account for unknown input escape sequence from the terminal\n");
1294 esc_seq
[esc_seq_next_byte
] = input_b
;
1295 ++esc_seq_next_byte
;
1296 if (!input_esc_seq_bind_cmd() && (esc_seq_next_byte
!= STR_SZ
))
1298 memset(&t
, 0, sizeof(t
));
1299 r
= timerfd_settime(input_timer_fd
, 0, &t
, 0);
1301 fatal("unable to disarm the timer used to account for unknown input escape sequence from the terminal\n");
1302 esc_seq_next_byte
= 0;
1303 input_esc_seq_mode
= false;
1304 utf8_cp_next_byte
= 0;
1306 static void input_byte_utf8_cp(void)
1308 if ((input_b
& 0x80) != 0) { /* utf8 cp > 0x7f */
1309 if ((input_b
& 0x40) != 0) { /* utf8 cp start byte */
1310 utf8_cp
[0] = input_b
;
1311 utf8_cp_next_byte
= 1;
1312 if ((input_b
& 0x20) == 0)
1314 else if ((input_b
& 0x10) == 0)
1316 else /* if ((input_b & 0x08) == 0) */
1317 utf8_cp_sz
= 4; /* must be 4 */
1320 /* (b & 0x40) == 0, utf8 cp continuation byte */
1322 * no start byte, discard (but should skip all following
1323 * continuation bytes and send the utf8 "invalid" cp)
1325 if (utf8_cp_next_byte
== 0)
1327 utf8_cp
[utf8_cp_next_byte
] = input_b
;
1328 ++utf8_cp_next_byte
;
1329 if (utf8_cp_next_byte
!= utf8_cp_sz
)
1331 } else {/* ascii 0x00 - 0x7f */
1332 if (input_b
== 0x1b) {/* esc */
1333 /* change state and process the esc byte */
1334 input_esc_seq_mode
= true;
1335 input_byte_esc_seq();
1338 utf8_cp
[0] = input_b
;
1341 input_utf8_cp_bind_cmd();
1343 /* we are either reading an utf8 cp or an esc seq */
1344 static void evt_input_drain(void) { loop
1349 r
= read(0, &input_b
, 1);
1351 if (errno
== EAGAIN
) /* no more input data */
1353 if (errno
== EINTR
) /* restart manually the call */
1355 fatal("an error occured while reading the input\n");
1358 fatal("input end of file\n");
1359 if (!input_esc_seq_mode
)
1360 input_byte_utf8_cp();
1362 input_byte_esc_seq();
1364 static void evt_sigs(void)
1367 struct signalfd_siginfo siginfo
;
1369 /* no short reads */
1370 r
= read(sig_fd
, &siginfo
, sizeof(siginfo
));
1371 if (r
!= sizeof(siginfo
))
1372 fatal("unable to read signal information\n");
1374 switch (siginfo
.ssi_signo
) {
1376 exit_ok("received SIGTERM\n");
1378 exit_ok("received SIGINT\n");
1380 warning("signal handle:unwanted signal %d received, discarding\n", siginfo
.ssi_signo
);
1383 static void evt_timer(void)
1386 struct itimerspec t
;
1388 memset(&t
, 0, sizeof(t
));
1389 r
= timerfd_settime(input_timer_fd
, 0, &t
, 0);
1391 fatal("unable to disarm the timer used to account for unknown input escape sequences from the terminal\n");
1393 esc_seq_next_byte
= 0;
1394 input_esc_seq_mode
= false;
1396 utf8_cp_next_byte
= 0;
1398 static void evt_handle(struct epoll_event
*evt
, bool *pcm_evt
)
1400 if (evt
->data
.fd
== 0) {
1401 if ((evt
->events
& EPOLLIN
) != 0)
1404 fatal("event loop wait:input:unexpected event\n");
1405 } else if (evt
->data
.fd
== sig_fd
) {
1406 if ((evt
->events
& EPOLLIN
) != 0)
1409 fatal("event loop wait:signal:unexpected event\n");
1410 } else if (evt
->data
.fd
== input_timer_fd
) {
1411 if ((evt
->events
& EPOLLIN
) != 0)
1414 fatal("event loop wait:timer:unexpected event\n");
1415 } else { /* only update alsa fds */
1420 if (i
== pcm_pollfds_n
)
1423 if (evt
->data
.fd
== pcm_pollfds
[i
].fd
) {
1424 pcm_pollfds
[i
].revents
= evt
->events
;
1431 /* fill the dec with pkts */
1432 static void dec_fill(void) { loop
1436 unsigned int next_sd
;
1439 rd
= atomic_load(&cb
.rd
);
1440 sd
= atomic_load(&cb
.sd
);
1441 /* at start, we must read pkt before we can send one */
1444 r
= av_sd_pkt(dec_ctx
, cb
.pkts
[sd
]);
1445 /* dec is full and the pkt was rejected, or the decoder is in EOF */
1446 if (r
== AVERROR(EAGAIN
) || r
== AVERROR_EOF
)
1449 fatal("ffmpeg:error while sending the packet to the decoder\n");
1451 av_pkt_unref(cb
.pkts
[sd
]);
1452 next_sd
= (sd
+ 1) % cb
.pkts_n
;
1453 atomic_store(&cb
.sd
, next_sd
);
1455 static void dec_frs_get(void) { loop
1461 /* will unref the dec_frs.av bufs for us */
1462 r
= av_receive_frs(dec_ctx
, dec_frs
.av
);
1463 if (r
== AVERROR(EAGAIN
))
1466 if (dec_frs
.av
->pts
!= AV_NOPTS_VALUE
)
1467 dec_frs
.most_recent_ts
= dec_frs
.av
->pts
;
1468 else if (dec_frs
.av
->pkt_dts
!= AV_NOPTS_VALUE
)
1469 dec_frs
.most_recent_ts
= dec_frs
.av
->pkt_dts
;
1471 dec_frs
.most_recent_ts
= dec_frs
.av
->pkt_dts
;
1472 dec_frs
.pushed_in_filt_graph
= false;
1473 return; /* "return" the current dec_frs.av */
1474 } else if (r
== AVERROR_EOF
) {
1475 pout("ffmpeg:last decoder frames reached (receiving)\n");
1476 loop
{ /* spinning */
1477 snd_pcm_state_t state
;
1479 r
= snd_pcm_drain(pcm_g
);
1485 * the pcm state can change asynchronously.
1487 * if the draining was successful, the pcm
1488 * should be in SETUP state, and in this
1489 * state, snd_pcm_drain will fail
1490 * _new and fixed__ behavior:
1491 * this won't happen because calling
1492 * snd_pcm_drain while in the SETUP state
1493 * won't return an error anymore
1495 state
= snd_pcm_state(pcm_g
);
1496 if (state
== SND_PCM_STATE_SETUP
)
1499 /**********************************************/
1500 exit_ok("finished playing\n");
1501 /**********************************************/
1503 fatal("ffmpeg:error while receiving frames from the decoder\n");
1505 static bool is_recfg_required(av_frs
*frs
)
1507 if (av_channel_layout_compare(&frs
->ch_layout
,
1508 &abufsrc_key
.chans_layout
) != 0
1509 || frs
->fr_rate
!= abufsrc_key
.rate
1510 || frs
->fmt
!= abufsrc_key
.fmt
)
1516 #define FILT_RECFG_REQUIRED 2
1517 static u8
filt_graph_push_dec_frs(AVChannelLayout
*new_chans_layout
,
1518 int *new_fr_rate
, enum av_fr_fmt
*new_fmt
)
1522 if (dec_frs
.pushed_in_filt_graph
)
1524 if (is_recfg_required(dec_frs
.av
)) {
1525 r
= av_channel_layout_copy(new_chans_layout
,
1526 &dec_frs
.av
->ch_layout
);
1528 fatal("ffmpeg:unable to copy the decoder channel layout as the new channel layout\n");
1529 *new_fr_rate
= dec_frs
.av
->fr_rate
;
1530 *new_fmt
= dec_frs
.av
->fmt
;
1531 return FILT_RECFG_REQUIRED
;
1533 /* the dec_frs.av bufs will be unref in av_receive_frs */
1534 r
= av_bufsrc_add_frs_flags(abufsrc_ctx
, dec_frs
.av
,
1535 AV_BUFSRC_FLAG_KEEP_REF
);
1537 dec_frs
.pushed_in_filt_graph
= true;
1539 } else if (r
== AVERROR(EAGAIN
))
1541 fatal("ffmpeg:unable to submit a decoder set of frames to the filter source audio buffer context\n");
1545 #undef FILT_RECFG_REQUIRED
1546 static void filt_frs_get(void)
1550 r
= av_bufsink_get_frs(abufsink_ctx
, filt_frs
.av
);
1552 filt_frs
.pcm_written_ufrs_n
= 0;
1555 fatal("ffmpeg:error while getting frames from the filter\n");
1557 #define FILT_RECFG_REQUIRED 2
1560 #define HAVE_FILT_SET 1
1561 #define PRINT_INFO true
1562 /* synchronous filtering */
1563 static void dec_frs_filter(void)
1567 AVChannelLayout new_chans_layout
;
1569 enum av_fr_fmt new_fmt
;
1570 AVChannelLayout dst_chans_layout
;
1572 enum av_fr_fmt dst_fmt
;
1574 memset(&new_chans_layout
, 0, sizeof(new_chans_layout
));
1575 memset(&dst_chans_layout
, 0, sizeof(dst_chans_layout
));
1577 r
= filt_graph_push_dec_frs(&new_chans_layout
, &new_fr_rate
,
1579 if (r
!= FILT_RECFG_REQUIRED
) {
1580 /* PUSHED | AGAIN */
1581 av_channel_layout_uninit(&new_chans_layout
);
1584 /* FILT_RECFG_REQUIRED */
1585 pcm2ff(pcm_g
, &dst_fmt
, &dst_rate
, &dst_chans_layout
,
1588 new_fmt
, new_fr_rate
, &new_chans_layout
,
1589 filt_frs
.muted
, filt_frs
.vol
,
1590 dst_fmt
, dst_rate
, &dst_chans_layout
, PRINT_INFO
);
1591 av_channel_layout_uninit(&new_chans_layout
);
1592 av_channel_layout_uninit(&dst_chans_layout
);
1596 #undef FILT_RECFG_REQUIRED
1599 #undef HAVE_FILT_SET
1602 static void chans_buf_init(u8
**chans_buf
, int start_fr_idx
)
1607 sample_bytes_n
= av_get_bytes_per_sample(filt_frs
.av
->fmt
);
1609 is_planar_fmt
= av_fr_fmt_is_planar(filt_frs
.av
->fmt
);
1610 if (is_planar_fmt
== NO
) { /* or is pcm interleaved */
1613 fr_bytes_n
= sample_bytes_n
1614 * filt_frs
.av
->ch_layout
.nb_channels
;
1615 chans_buf
[0] = (u8
*)filt_frs
.av
->data
[0] + start_fr_idx
1617 } else { /* ff planar or pcm noninterleaved */
1622 if (p
== filt_frs
.av
->ch_layout
.nb_channels
)
1624 chans_buf
[p
] = (u8
*)filt_frs
.av
->data
[p
]
1625 + start_fr_idx
* sample_bytes_n
;
1632 static void chans_buf_inc(u8
**chans_buf
, int frs_inc
)
1637 sample_bytes_n
= av_get_bytes_per_sample(filt_frs
.av
->fmt
);
1639 is_planar_fmt
= av_fr_fmt_is_planar(filt_frs
.av
->fmt
);
1640 if (is_planar_fmt
== NO
) { /* or is pcm interleaved */
1643 fr_bytes_n
= sample_bytes_n
1644 * filt_frs
.av
->ch_layout
.nb_channels
;
1645 chans_buf
[0] += frs_inc
* fr_bytes_n
;
1646 } else { /* ff planar or pcm noninterleaved */
1651 if (p
== filt_frs
.av
->ch_layout
.nb_channels
)
1653 chans_buf
[p
] += frs_inc
* sample_bytes_n
;
1660 static void pcm_silence_frs_write(snd_pcm_ufrs_t ufrs_n
)
1667 is_planar_fmt
= av_fr_fmt_is_planar(filt_frs
.av
->fmt
);
1668 if (is_planar_fmt
== NO
)
1669 (void)snd_pcm_writei(pcm_g
, silence_bufs
[0], ufrs_n
);
1671 (void)snd_pcm_writen(pcm_g
, silence_bufs
, ufrs_n
);
1675 static void pcm_filt_frs_write(snd_pcm_ufrs_t ufrs_n
) { loop
1678 u8
*chans_buf
[AV_NUM_DATA_POINTERS
];
1680 snd_pcm_ufrs_t ufrs_to_write_n
;
1681 snd_pcm_ufrs_t filt_frs_remaining_ufrs_n
; /* for clarity */
1685 if (filt_frs
.pcm_written_ufrs_n
== (snd_pcm_ufrs_t
)filt_frs
.av
->frs_n
) {
1686 av_frs_unref(filt_frs
.av
);
1687 dec_frs_filter(); /* synchronous filtering */
1689 /* create the chan buf pointers */
1690 chans_buf_init(chans_buf
, (int)filt_frs
.pcm_written_ufrs_n
);
1691 filt_frs_remaining_ufrs_n
= (snd_pcm_ufrs_t
)filt_frs
.av
->frs_n
1692 - filt_frs
.pcm_written_ufrs_n
;
1693 if (filt_frs_remaining_ufrs_n
> ufrs_n
)
1694 ufrs_to_write_n
= ufrs_n
;
1696 ufrs_to_write_n
= filt_frs_remaining_ufrs_n
;
1700 snd_pcm_ufrs_t written_ufrs_n
;
1702 is_planar_fmt
= av_fr_fmt_is_planar(filt_frs
.av
->fmt
);
1703 if (is_planar_fmt
== NO
)
1704 r0
= snd_pcm_writei(pcm_g
, chans_buf
[0],
1707 r0
= snd_pcm_writen(pcm_g
, (void**)chans_buf
,
1710 if (r0
== -EAGAIN
) /* return to epoll */
1712 else if (r0
== -EPIPE
|| r0
== -ESTRPIPE
) {
1713 /* underrun or suspended */
1716 r1
= snd_pcm_recover(pcm_g
, (int)r0
, 0);
1718 warning("alsa:pcm recovered going back to epoll\n");
1719 return; /* recovered, go back to epoll */
1721 fatal("alsa:unable to recover from suspend/underrun\n");
1723 fatal("alsa:fatal/unhandled error while writing the frames\n");
1726 written_ufrs_n
= (snd_pcm_ufrs_t
)r0
;
1727 filt_frs
.pcm_written_ufrs_n
+= written_ufrs_n
;
1728 ufrs_n
-= written_ufrs_n
;
1729 ufrs_to_write_n
-= written_ufrs_n
;
1730 chans_buf_inc(chans_buf
, (int)written_ufrs_n
);
1731 if (ufrs_to_write_n
== 0)
1736 static void evt_pcm_write(void)
1739 /* try only 2 times */
1740 r0
= snd_pcm_avail(pcm_g
);
1742 if (r0
== -EPIPE
|| r0
== -ESTRPIPE
) {
1743 /* underrun or suspended */
1746 r1
= snd_pcm_recover(pcm_g
, (int)r0
, 0);
1748 warning("alsa:pcm recovered retrying to get some available frames\n");
1749 r0
= snd_pcm_avail(pcm_g
);
1751 fatal("alsa:unable to get some available frames after recovery\n");
1753 fatal("alsa:unable to recover from suspend/underrun\n");
1755 fatal("alsa:error getting some available frames\n");
1759 pcm_silence_frs_write((snd_pcm_ufrs_t
)r0
);
1761 pcm_filt_frs_write((snd_pcm_ufrs_t
)r0
);
1763 #define EPOLL_EVTS_N 8 /* why not */
1764 static void evts_loop(void)
1768 struct epoll_event evts
[EPOLL_EVTS_N
];
1774 memset(evts
, 0, sizeof(evts
));
1775 fds_n
= epoll_wait(ep_fd
, evts
, EPOLL_EVTS_N
, -1);
1777 if (errno
== EINTR
) {
1778 warning("event loop wait:was interrupted by a signal\n");
1781 fatal("event loop wait:an error occured\n");
1786 if (fd_idx
== fds_n
)
1788 evt_handle(&evts
[fd_idx
], &pcm_evt
);
1794 * since alsa could use several file descriptors, only once the
1795 * pollfds were properly updated we can actually know we got
1796 * something from alsa
1798 r
= snd_pcm_poll_descriptors_revents(pcm_g
, pcm_pollfds
, pcm_pollfds_n
,
1801 fatal("alsa:error processing the poll file descriptors\n");
1802 if ((pcm_evts
& ~POLLOUT
) != 0)
1803 fatal("alsa:unexpected events\n");
1804 if ((pcm_evts
& POLLOUT
) != 0)
1808 static void silence_bufs_init_once(void)
1810 memset(silence_bufs
, 0, sizeof(silence_bufs
));
1812 static void silence_bufs_cfg(snd_pcm_t
*pcm
, bool print_info
)
1815 snd_pcm_hw_params_t
*hw_params
;
1816 snd_pcm_ufrs_t buf_ufrs_n
;
1818 snd_pcm_access_t access
;
1819 unsigned int chans_n
;
1822 r
= snd_pcm_hw_params_malloc(&hw_params
);
1824 fatal("silence:alsa:unable to allocate memory for a hardware parameters container\n");
1825 r
= snd_pcm_hw_params_current(pcm
, hw_params
);
1827 fatal("silence:alsa:unable to get the pcm hardware parameters\n");
1828 r
= snd_pcm_hw_params_get_buf_size(hw_params
, &buf_ufrs_n
);
1830 fatal("silence:alsa:unable to get the number of frs in the pcm buffer\n");
1831 r
= snd_pcm_hw_params_get_fmt(hw_params
, &fmt
);
1833 fatal("silence:alsa:unable to get the pcm format\n");
1834 r
= snd_pcm_hw_params_get_access(hw_params
, &access
);
1836 fatal("silence:alsa:unable to get the pcm access mode\n");
1837 r
= snd_pcm_hw_params_get_chans(hw_params
, &chans_n
);
1839 fatal("silence:alsa:unable to get the pcm number of channels\n");
1840 /* wipe silence bufs first */
1843 if (c
== AV_NUM_DATA_POINTERS
)
1845 if (silence_bufs
[c
] != 0) {
1846 free(silence_bufs
[c
]);
1847 silence_bufs
[c
] = 0;
1851 if (access
== SND_PCM_ACCESS_RW_INTERLEAVED
1852 || access
== SND_PCM_ACCESS_MMAP_INTERLEAVED
) {
1853 ssize_t buf_bytes_n
;
1855 buf_bytes_n
= snd_pcm_frs_to_bytes(pcm
,
1856 (snd_pcm_sfrs_t
)buf_ufrs_n
);
1857 if (buf_bytes_n
<= 0)
1858 fatal("silence:alsa:interleaved:unable to get the pcm number of bytes of all buffer frames\n");
1859 silence_bufs
[0] = malloc((size_t)buf_bytes_n
);
1860 if (silence_bufs
[0] == 0)
1861 fatal("silence:interleaved:unable to allocate the silence buffer of %d bytes\n", (int)buf_bytes_n
);
1863 pout("silence:interleaved:buffer of %d bytes is allocated\n", (int)buf_bytes_n
);
1864 r
= snd_pcm_fmt_set_silence(fmt
, silence_bufs
[0],
1865 (unsigned int)buf_ufrs_n
);
1867 fatal("silence:interleaved:unable to fill with silence the buffer\n");
1868 pout("silence:interleaved:silence buffer filled with %u silence frames\n", buf_ufrs_n
);
1869 } else if (access
== SND_PCM_ACCESS_RW_NONINTERLEAVED
1870 || access
== SND_PCM_ACCESS_MMAP_NONINTERLEAVED
) {
1871 ssize_t buf_bytes_n
;
1874 buf_samples_n
= (long)buf_ufrs_n
;
1875 buf_bytes_n
= snd_pcm_samples_to_bytes(pcm
, buf_samples_n
);
1876 if (buf_bytes_n
<= 0)
1877 fatal("silence:alsa:non interleaved:unable to get the pcm number of total bytes of all buffer samples\n");
1882 silence_bufs
[c
] = malloc((size_t)buf_bytes_n
);
1883 if (silence_bufs
[c
] == 0)
1884 fatal("silence:non interleaved:unable to allocate silence buffer %u of %d bytes\n", c
, (int)buf_bytes_n
);
1885 r
= snd_pcm_fmt_set_silence(fmt
, silence_bufs
[c
],
1886 (unsigned int)buf_samples_n
);
1888 fatal("silence:non interleaved:unable to fill with silence the buffer\n");
1890 pout("silence:non interleaved:buffer[%u] of %d bytes is allocated\n", c
, (int)buf_bytes_n
);
1894 pout("silence:non interleaved:allocated %u silence buffers for %u frames\n", chans_n
, (unsigned int)buf_ufrs_n
);
1896 fatal("silence:the pcm access type is not supported\n");
1897 snd_pcm_hw_params_free(hw_params
);
1899 static void ff_log_stdout(void *a
, int b
, const char *fmt
, va_list ap
)
1903 struct ff_supported_fr_fmt_t
{
1907 /* this is the intersection of ff audio fr fmt and alsa pcm fmt */
1908 static struct ff_supported_fr_fmt_t ff_supported_fr_fmts
[] = {
1909 {"u8", AV_FR_FMT_U8
},
1910 {"u8planar", AV_FR_FMT_U8P
},
1911 {"s16", AV_FR_FMT_S16
},
1912 {"s16planar", AV_FR_FMT_S16P
},
1913 {"s32", AV_FR_FMT_S32
},
1914 {"s32planar", AV_FR_FMT_S32P
},
1915 {"float32", AV_FR_FMT_FLT
},
1916 {"float32planar", AV_FR_FMT_FLTP
},
1917 {"float64", AV_FR_FMT_DBL
},
1918 {"float64planar", AV_FR_FMT_DBLP
},
1921 static void usage(void)
1923 struct ff_supported_fr_fmt_t
*fmt
;
1926 npa [-p alsa pcm] [-v volume(0..100)] [-cb circular buffer slots]\n\
1927 [-fc override initial ffmpeg count of channels used to approximate the alsa\n\
1928 pcm configuration]\n\
1929 [-fr override initial ffmpeg rate(hz) used to approximate the alsa pcm\n\
1931 [-ff override initial ffmpeg audio frame format used to approximate the alsa\n\
1932 pcm configuration, see below for a list]\n\
1936 the ffmpeg audio frame formats which intersect alsa pcm audio formats are:\n");
1938 fmt
= ff_supported_fr_fmts
;
1942 pout("\t%s\n", fmt
->str
);
1946 static void opts_parse(int argc
, u8
**args
, u8
**url
, u8
**pcm_str
,
1947 double *initial_vol
, unsigned int *cb_slots_n
,
1948 int *override_initial_ff_chans_n
,
1949 int *override_initial_ff_rate
,
1950 enum av_fr_fmt
*override_initial_ff_fr_fmt
)
1960 if (strcmp("-p", args
[i
]) == 0) {
1961 if ((i
+ 1) == argc
)
1962 fatal("-p:alsa pcm is missing\n");
1963 *pcm_str
= args
[i
+ 1];
1964 pout("-p:alsa pcm \"%s\"\n", *pcm_str
);
1966 } else if (strcmp("-v", args
[i
]) == 0) {
1967 unsigned long vol_ul
;
1969 if ((i
+ 1) == argc
)
1970 fatal("-v:initial volume option is missing\n");
1971 vol_ul
= strtoul(args
[i
+ 1], 0, 10);
1972 if (vol_ul
< 0 || 100 < vol_ul
)
1973 fatal("-v:invalid volume value %lu (0..100)\n", vol_ul
);
1974 *initial_vol
= (double)vol_ul
/ 100.0;
1975 pout("-v:using initial volume %f\n", *initial_vol
);
1977 } else if (strcmp("-cb", args
[i
]) == 0) {
1978 if ((i
+ 1) == argc
)
1979 fatal("-cb:count of slots is missing\n");
1980 *cb_slots_n
= (unsigned int)strtoul(args
[i
+ 1], 0, 10);
1981 pout("-cb:using %u circular buffer slots\n",
1984 /*------------------------------------------------------------*/
1985 /* ff initial override for alsa pcm cfg -- start */
1986 } else if (strcmp("-fr", args
[i
]) == 0) {
1987 if ((i
+ 1) == argc
) {
1988 perr("-fr:override initial ffmpeg rate(hz) is missing\n");
1992 *override_initial_ff_rate
= (int)strtol(args
[i
+ 1], 0,
1994 pout("-fr:override initial ffmpeg audio rate to %dHz used for alsa pcm configuration\n", *override_initial_ff_rate
);
1996 } else if (strcmp("-fc", args
[i
]) == 0) {
1997 if ((i
+ 1) == argc
) {
1998 perr("-fc:override initial ffmpeg channel count is missing\n");
2002 *override_initial_ff_chans_n
= (int)strtol(args
[i
+ 1],
2004 pout("-fc:override initial ffmpeg count of channels to %d used for alsa pcm configuration\n", *override_initial_ff_chans_n
);
2006 } else if (strcmp("-ff", args
[i
]) == 0) {
2007 struct ff_supported_fr_fmt_t
*fmt
;
2009 if ((i
+ 1) == argc
) {
2010 perr("-fc:override initial ffmpeg audio frame format is missing\n");
2014 fmt
= ff_supported_fr_fmts
;
2016 if (fmt
->str
== 0) {
2017 perr("-ff:unknown ffmpeg audio frame format\n");
2021 if (strcmp(fmt
->str
, args
[i
+ 1]) == 0) {
2022 *override_initial_ff_fr_fmt
= fmt
->fmt
;
2027 pout("-ff:override initial ffmpeg audio frame format is %s\n", av_get_fr_fmt_name(*override_initial_ff_fr_fmt
));
2029 /* ff initial override for alsa pcm cfg -- end */
2030 /*------------------------------------------------------------*/
2031 } else if (strcmp("-h", args
[i
]) == 0) {
2040 fatal("missing url\n");
2041 *url
= args
[url_idx
];
2042 pout("playing ####%s####\n", *url
);
2044 #define RESET_DONE 0
2046 static void cb_init_once(unsigned int cb_slots_n
)
2050 cb
.pkts
= malloc(cb_slots_n
* sizeof(*cb
.pkts
));
2053 cb
.pkts
[i
] = av_packet_alloc();
2054 if (cb
.pkts
[i
] == 0)
2055 fatal("unable to allocate a packet reference for the circular buffer\n");
2056 if (i
== cb_slots_n
)
2060 cb
.pkts_n
= cb_slots_n
;
2061 atomic_store(&cb
.rd
, 0);
2062 atomic_store(&cb
.sd
, 0);
2063 atomic_store(&cb
.st_idx
, -1);
2064 atomic_store(&cb
.reset
, RESET_DONE
);
2065 atomic_store(&cb
.hold
, DONT_HOLD
);
2069 static void filt_graph_init_once(void)
2074 memset(&abufsrc_key
, 0, sizeof(abufsrc_key
));
2081 /* floating point strs are localized... */
2082 snprintf(double_zero_l10n_str
, sizeof(double_zero_l10n_str
), "%f", 0.);
2083 memset(&filt_frs
, 0, sizeof(filt_frs
));
2084 filt_frs
.av
= av_frs_alloc();
2085 if (filt_frs
.av
== 0)
2086 fatal("ffmpeg:unable to allocate a filtered frames structure\n");
2087 filt_frs
.pcm_written_ufrs_n
= 0;
2089 static void dec_init_once(void)
2093 dec_frs
.av
= av_frs_alloc();
2094 if (dec_frs
.av
== 0)
2095 fatal("ffmpeg:unable to allocate a decoded frames structure\n");
2096 dec_frs
.pushed_in_filt_graph
= true;
2097 dec_frs
.most_recent_ts
= AV_NOPTS_VALUE
;
2099 static void rd_thd_init_once(void)
2101 rd_thd_pkt
= av_packet_alloc();
2102 if (rd_thd_pkt
== 0)
2103 fatal("ffmpeg:unable to allocate a packet for the read thread\n");
2105 static void fmt_init_once(u8
*url
)
2110 r
= av_fmt_open_input(&fmt_ctx
, url
, NULL
, NULL
);
2112 fatal("ffmpeg:unable to open \"%s\"\n", url
);
2113 /* probe beyond the header, if any */
2114 r
= av_fmt_find_st_info(fmt_ctx
, 0);
2116 fatal("ffmpeg:unable to probe \"%s\"\n", url
);
2117 r
= pthread_mutex_init(&fmt_ctx_mutex
, 0);
2119 fatal("unable to init the format context mutex\n");
2121 static void pcm_init_once(u8
*pcm_str
)
2125 r
= snd_output_stdio_attach(&pcm_pout
, stdout
, 0);
2127 fatal("alsa:unable to attach stdout\n");
2128 r
= snd_output_stdio_attach(&pcm_perr
, stderr
, 0);
2130 fatal("alsa:unable to attach stderr\n");
2131 r
= snd_pcm_open(&pcm_g
, pcm_str
, SND_PCM_ST_PLAYBACK
,
2135 fatal("alsa:\"%s\" pcm is already in use\n", pcm_str
);
2137 fatal("alsa:unable to open \"%s\" pcm for playback\n", pcm_str
);
2139 r
= snd_pcm_poll_descriptors_count(pcm_g
);
2140 pout("alsa:have %d poll file descriptors\n", r
);
2141 if ((r
<= 0) || (r
> PCM_POLLFDS_N_MAX
))
2142 fatal("alsa:invalid count of alsa poll file descriptors\n");
2143 pcm_pollfds_n
=(u8
)r
;
2144 memset(pcm_pollfds
, 0, sizeof(pcm_pollfds
));
2145 snd_pcm_poll_descriptors(pcm_g
, pcm_pollfds
, PCM_POLLFDS_N_MAX
);
2147 static void init_once(u8
*url
, u8
*pcm_str
, unsigned int cb_slots_n
)
2149 stdin_tty_cfg_modified
= false;
2154 stdin_tty_init_once();
2155 stdin_flags_init_once();
2157 input_state_init_once();
2158 cb_init_once(cb_slots_n
);
2159 filt_graph_init_once();
2160 silence_bufs_init_once();
2162 pcm_init_once(pcm_str
);
2167 static int find_best_st(void)
2171 r
= av_find_best_st(fmt_ctx
, AV_MEDIA_TYPE_AUDIO
, -1, -1, 0, 0);
2173 fatal("ffmpeg:no audio stream found\n");
2176 static void pcm_hw_chans_n_decide(snd_pcm_t
*pcm
,
2177 snd_pcm_hw_params_t
*pcm_hw_params
, unsigned int chans_n
)
2180 unsigned int chans_n_max
;
2181 unsigned int chans_n_min
;
2183 r
= snd_pcm_hw_params_test_chans(pcm
, pcm_hw_params
, chans_n
);
2185 r
= snd_pcm_hw_params_set_chans(pcm
, pcm_hw_params
, chans_n
);
2187 fatal("alsa:unable to restrict pcm device to %u channels, count which was successfully tested\n", chans_n
);
2188 pout("alsa:using %u channels\n", chans_n
);
2191 pout("alsa:unable to use %u channels\n", chans_n
);
2192 /* try to use the max chans n the pcm can */
2193 r
= snd_pcm_hw_params_get_chans_max(pcm_hw_params
, &chans_n_max
);
2195 fatal("alsa:unable to get the maximum count of pcm device channels\n");
2196 r
= snd_pcm_hw_params_test_chans(pcm
, pcm_hw_params
, chans_n_max
);
2198 r
= snd_pcm_hw_params_set_chans(pcm
, pcm_hw_params
,
2201 fatal("alsa:unable to restrict pcm device to %u channels, count which was successfully tested\n", chans_n_max
);
2202 pout("alsa:using pcm maximum %u channels\n", chans_n_max
);
2205 /* ok... last try, the pcm dev min chans n */
2206 r
= snd_pcm_hw_params_get_chans_min(pcm_hw_params
, &chans_n_min
);
2208 fatal("alsa:unable to get the minimum count of pcm device channels\n");
2209 r
= snd_pcm_hw_params_test_chans(pcm
, pcm_hw_params
, chans_n_min
);
2211 r
= snd_pcm_hw_params_set_chans(pcm
, pcm_hw_params
,
2214 fatal("alsa:unable to restrict pcm device to %u channels, count which was successfully tested\n", chans_n_min
);
2215 pout("alsa:using pcm device minimum %u channels\n", chans_n_min
);
2218 fatal("alsa:unable to find a suitable count of channels\n");
2220 static void pcm_hw_rate_decide(snd_pcm_t
*pcm
,
2221 snd_pcm_hw_params_t
*pcm_hw_params
, unsigned int rate
)
2224 unsigned int rate_max
;
2225 unsigned int rate_near
;
2226 unsigned int rate_min
;
2228 r
= snd_pcm_hw_params_test_rate(pcm
, pcm_hw_params
, rate
,
2229 SND_PCM_ST_PLAYBACK
);
2231 r
= snd_pcm_hw_params_set_rate(pcm
, pcm_hw_params
, rate
,
2232 SND_PCM_ST_PLAYBACK
);
2234 fatal("alsa:unable to restrict pcm device to %uHz, which was successfully tested\n", rate
);
2235 pout("alsa:using %uHz\n", rate
);
2238 pout("alsa:unable to use %uHz\n", rate
);
2239 /* try to use the max rate the pcm can */
2240 r
= snd_pcm_hw_params_get_rate_max(pcm_hw_params
, &rate_max
,
2241 SND_PCM_ST_PLAYBACK
);
2243 fatal("alsa:unable to get the maximum rate of pcm device\n");
2244 r
= snd_pcm_hw_params_test_rate(pcm
, pcm_hw_params
, rate_max
,
2245 SND_PCM_ST_PLAYBACK
);
2247 r
= snd_pcm_hw_params_set_rate(pcm
, pcm_hw_params
, rate_max
,
2248 SND_PCM_ST_PLAYBACK
);
2250 fatal("alsa:unable to restrict pcm device to %uHz, which was successfully tested\n", rate_max
);
2251 pout("alsa:using pcm device %uHz\n", rate_max
);
2254 /* try to use a rate "near" of what the pcm dev can */
2256 r
= snd_pcm_hw_params_set_rate_near(pcm
, pcm_hw_params
, &rate_near
,
2257 SND_PCM_ST_PLAYBACK
);
2259 pout("alsa:using pcm device %uHz\n", rate_near
);
2262 /* even a "near" rate did failed... try the min */
2263 r
= snd_pcm_hw_params_get_rate_min(pcm_hw_params
, &rate_min
,
2264 SND_PCM_ST_PLAYBACK
);
2266 fatal("alsa:unable to get the minimum rate of pcm device\n");
2267 r
= snd_pcm_hw_params_test_rate(pcm
, pcm_hw_params
, rate_min
,
2268 SND_PCM_ST_PLAYBACK
);
2270 r
= snd_pcm_hw_params_set_rate(pcm
, pcm_hw_params
, rate_min
,
2271 SND_PCM_ST_PLAYBACK
);
2273 fatal("alsa:unable to restrict pcm device to %uHz, which was successfully tested\n", rate_min
);
2274 pout("alsa:using pcm device %uHz\n", rate_min
);
2277 fatal("alsa:unable to find a suitable rate\n");
2279 static bool ff_fmt2pcm_layout_best_effort(enum av_fr_fmt ff_fmt
,
2280 snd_pcm_fmt_t
*alsa_fmt
, snd_pcm_access_t
*alsa_access
)
2282 static u8 ff_fmt_str
[STR_SZ
];
2284 av_get_fr_fmt_str(ff_fmt_str
, STR_SZ
, ff_fmt
);
2285 /* XXX: only classic non-mmap ones */
2288 *alsa_fmt
= SND_PCM_FMT_U8
;
2289 *alsa_access
= SND_PCM_ACCESS_RW_INTERLEAVED
;
2292 *alsa_fmt
= SND_PCM_FMT_S16
;
2293 *alsa_access
= SND_PCM_ACCESS_RW_INTERLEAVED
;
2296 *alsa_fmt
= SND_PCM_FMT_S32
;
2297 *alsa_access
= SND_PCM_ACCESS_RW_INTERLEAVED
;
2300 *alsa_fmt
= SND_PCM_FMT_FLT
;
2301 *alsa_access
= SND_PCM_ACCESS_RW_INTERLEAVED
;
2303 /* ff "planar" fmts are actually non interleaved fmts */
2305 *alsa_fmt
= SND_PCM_FMT_U8
;
2306 *alsa_access
= SND_PCM_ACCESS_RW_NONINTERLEAVED
;
2308 case AV_FR_FMT_S16P
:
2309 *alsa_fmt
= SND_PCM_FMT_S16
;
2310 *alsa_access
= SND_PCM_ACCESS_RW_NONINTERLEAVED
;
2312 case AV_FR_FMT_S32P
:
2313 *alsa_fmt
= SND_PCM_FMT_S32
;
2314 *alsa_access
= SND_PCM_ACCESS_RW_NONINTERLEAVED
;
2316 case AV_FR_FMT_FLTP
:
2317 *alsa_fmt
= SND_PCM_FMT_FLT
;
2318 *alsa_access
= SND_PCM_ACCESS_RW_NONINTERLEAVED
;
2321 pout("best effort:unable to wire ffmpeg sample format \"%sbits\" to alsa sample format, \n,", ff_fmt_str
);
2324 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
));
2327 static bool pcm_hw_fmt_decide_x(snd_pcm_t
*pcm
,
2328 snd_pcm_hw_params_t
*pcm_hw_params
, snd_pcm_fmt_t fmt
)
2332 r
= snd_pcm_hw_params_test_fmt(pcm
, pcm_hw_params
, fmt
);
2335 r
= snd_pcm_hw_params_set_fmt(pcm
, pcm_hw_params
, fmt
);
2337 fatal("alsa:unable to restrict pcm device to \"%s\", which was successfully tested\n", snd_pcm_fmt_desc(fmt
));
2338 pout("alsa:using \"%s\" format\n", snd_pcm_fmt_desc(fmt
));
2341 #define PCM_HW_FMT_DECIDE_X(fmt) pcm_hw_fmt_decide_x(pcm, pcm_hw_params, fmt)
2342 static void pcm_hw_fmt_decide(snd_pcm_t
*pcm
,
2343 snd_pcm_hw_params_t
*pcm_hw_params
, bool force
,
2344 snd_pcm_fmt_t forced_fmt
)
2350 r
= snd_pcm_hw_params_test_fmt(pcm
, pcm_hw_params
, forced_fmt
);
2352 r
= snd_pcm_hw_params_set_fmt(pcm
, pcm_hw_params
,
2355 fatal("alsa:unable to restrict pcm device to \"%s\", which was successfully tested\n", snd_pcm_fmt_desc(forced_fmt
));
2356 pout("alsa:using forced \"%s\" format\n", snd_pcm_fmt_desc(forced_fmt
));
2360 /* then we try to select from the reasonable "best" to the lowest */
2361 /* prefer fmts we know supported by ff */
2362 if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_FLT
))
2364 if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_S32
))
2366 if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_S16
))
2368 if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_U8
))
2371 * from here, at the time of writting, those fmts have no ff
2372 * wiring, but we are alsa centric here, validate that later
2374 if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_U32
))
2376 if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_S24
))
2378 if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_U24
))
2380 if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_U16
))
2382 if (PCM_HW_FMT_DECIDE_X(SND_PCM_FMT_S8
))
2384 fatal("alsa:unable to find a suitable format\n");
2386 #undef PCM_HW_FMT_DECIDE_X
2387 static bool pcm_hw_access_decide_x(snd_pcm_t
*pcm
,
2388 snd_pcm_hw_params_t
*pcm_hw_params
, snd_pcm_access_t access
)
2392 r
= snd_pcm_hw_params_test_access(pcm
, pcm_hw_params
, access
);
2395 r
= snd_pcm_hw_params_set_access(pcm
, pcm_hw_params
, access
);
2397 fatal("alsa:unable to restrict pcm device to \"%s\", which was successfully tested\n", snd_pcm_access_name(access
));
2398 pout("alsa:using \"%s\" access\n", snd_pcm_access_name(access
));
2401 #define PCM_HW_ACCESS_DECIDE_X(access) \
2402 pcm_hw_access_decide_x(pcm, pcm_hw_params, access)
2403 /* XXX: only classic non-mmap ones */
2404 static void pcm_hw_access_decide(snd_pcm_t
*pcm
,
2405 snd_pcm_hw_params_t
*pcm_hw_params
, bool force
,
2406 snd_pcm_access_t forced_access
)
2409 snd_pcm_access_t access
;
2412 r
= snd_pcm_hw_params_test_access(pcm
, pcm_hw_params
,
2415 r
= snd_pcm_hw_params_set_access(pcm
, pcm_hw_params
,
2418 fatal("alsa:unable to restrict pcm device to \"%s\", which was successfully tested\n", snd_pcm_access_name(forced_access
));
2419 pout("alsa:using forced \"%s\" access\n", snd_pcm_access_name(forced_access
));
2424 if (PCM_HW_ACCESS_DECIDE_X(SND_PCM_ACCESS_RW_INTERLEAVED
))
2426 if (PCM_HW_ACCESS_DECIDE_X(SND_PCM_ACCESS_RW_NONINTERLEAVED
))
2428 fatal("alsa:unable to find a suitable access\n");
2430 #undef PCM_HW_ACCESS_DECIDE_X
2432 * latency control: some audio bufs can be huge (tested on a pulseaudio with 10
2433 * secs audio buf). if we are careless, we will quickly fill this buf which is
2434 * worth a significant amount of time, hence will add huge latency to our
2435 * interactive audio filtering (vol...). in the case of the 10 secs pulseaudio
2436 * buf, it means if you want to mute the audio, it will happen 10 secs later.
2437 * we add lantency control by limiting the sz of the dev audio buf, in periods
2439 * we choose roughly 0.25 secs, or roughly (rate / 4) frs.
2441 static void pcm_hw_buf_sz_cfg(snd_pcm_t
*pcm
,
2442 snd_pcm_hw_params_t
*pcm_hw_params
)
2445 snd_pcm_ufrs_t latency_control_target_buf_ufrs_n
;
2446 snd_pcm_ufrs_t latency_control_buf_ufrs_n
;
2449 r
= snd_pcm_hw_params_get_rate(pcm_hw_params
, &rate
, 0);
2451 warning("alsa:latency control:DISABLING LATENCY CONTROL:unable to get the decided rate from the current device parameters\n");
2454 latency_control_target_buf_ufrs_n
= (snd_pcm_ufrs_t
)rate
;
2455 latency_control_target_buf_ufrs_n
/= 4;
2456 latency_control_buf_ufrs_n
= latency_control_target_buf_ufrs_n
;
2457 r
= snd_pcm_hw_params_set_buf_size_near(pcm
, pcm_hw_params
,
2458 &latency_control_buf_ufrs_n
);
2460 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
);
2463 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
);
2465 static void pcm_cfg_sw(snd_pcm_t
*pcm
)
2468 snd_pcm_sw_params_t
*sw_params
;
2470 pout("ALSA:SW_PARAMS START------------------------------------------------------------\n");
2471 r
= snd_pcm_sw_params_malloc(&sw_params
);
2473 fatal("alsa:unable to allocate software parameters structure\n");
2474 r
= snd_pcm_sw_params_current(pcm
, sw_params
);
2476 fatal("alsa:unable to get current software parameters\n");
2477 r
= snd_pcm_sw_params_set_period_event(pcm
, sw_params
, 1);
2479 fatal("alsa:unable to enable period event\n");
2480 r
= snd_pcm_sw_params(pcm
, sw_params
);
2482 fatal("alsa:unable to install sotfware parameters\n");
2483 snd_pcm_sw_params_dump(sw_params
, pcm_pout
);
2484 snd_pcm_sw_params_free(sw_params
);
2485 pout("ALSA:SW_PARAMS END--------------------------------------------------------------\n");
2488 * this function will "decide" the pcm dev cfg:
2489 * the goal is to be the "closest" to the provided params,
2490 * the "gap" will have to "filled" with ff filts
2492 * the "strategy" is a "fall-thru" (chans n then ... then ...) which
2493 * will "restrict" the pcm dev cfg further at each step
2495 * we try to use a sensible restrict order regarding audio props
2497 static void pcm_cfg_hw_core(snd_pcm_t
*pcm
, snd_pcm_hw_params_t
*pcm_hw_params
,
2498 int chans_n
, int rate
, enum av_fr_fmt ff_fmt
)
2501 bool best_effort_wiring_success
;
2502 snd_pcm_fmt_t fmt_from_best_effort
;
2503 snd_pcm_access_t access_from_best_effort
;
2505 /* the return value is from a first refine of the raw hw params */
2506 r
= snd_pcm_hw_params_any(pcm
, pcm_hw_params
);
2508 fatal("alsa:unable to populate the hardware parameters context\n");
2509 pcm_hw_chans_n_decide(pcm
, pcm_hw_params
, (unsigned int)chans_n
);
2510 pcm_hw_rate_decide(pcm
, pcm_hw_params
, (unsigned int)rate
);
2512 best_effort_wiring_success
= ff_fmt2pcm_layout_best_effort(
2513 ff_fmt
, &fmt_from_best_effort
, &access_from_best_effort
);
2514 pcm_hw_fmt_decide(pcm
, pcm_hw_params
, best_effort_wiring_success
,
2515 fmt_from_best_effort
);
2516 pcm_hw_access_decide(pcm
, pcm_hw_params
, best_effort_wiring_success
,
2517 access_from_best_effort
);
2518 pcm_hw_buf_sz_cfg(pcm
, pcm_hw_params
);
2520 static void pcm_cfg_hw(snd_pcm_t
*pcm
, unsigned int chans_n
, unsigned int rate
,
2521 enum av_fr_fmt ff_fmt
)
2524 snd_pcm_access_t access
;
2525 snd_pcm_hw_params_t
*hw_params
;
2527 pout("ALSA:HW_PARAMS START------------------------------------------------------------\n");
2528 r
= snd_pcm_hw_params_malloc(&hw_params
);
2530 fatal("alsa:unable to allocate hardware parameters context\n");
2531 pcm_cfg_hw_core(pcm
, hw_params
, chans_n
, rate
, ff_fmt
);
2532 r
= snd_pcm_hw_params(pcm
, hw_params
);
2534 fatal("alsa:unable to install the hardware parameters\n");
2535 r
= snd_pcm_hw_params_current(pcm
, hw_params
);
2537 fatal("alsa:unable to get current hardware parameters\n");
2538 snd_pcm_hw_params_dump(hw_params
, pcm_pout
);
2539 snd_pcm_hw_params_free(hw_params
);
2540 pout("ALSA:HW_PARAMS END--------------------------------------------------------------\n");
2542 static void pcm_cfg(snd_pcm_t
*pcm
, unsigned int chans_n
, unsigned int rate
,
2543 enum av_fr_fmt ff_fmt
)
2545 pcm_cfg_hw(pcm
, chans_n
, rate
, ff_fmt
);
2547 pout("ALSA PCM DUMP START-------------------------------------------------------------\n");
2548 snd_pcm_dump(pcm
, pcm_pout
);
2549 pout("ALSA PCM DUMP END---------------------------------------------------------------\n");
2551 static void evt_pcm_install(void)
2557 struct epoll_event evt
;
2560 if (i
== pcm_pollfds_n
)
2562 evt
.events
= pcm_pollfds
[i
].events
;
2563 evt
.data
.fd
= pcm_pollfds
[i
].fd
;
2564 r
= epoll_ctl(ep_fd
, EPOLL_CTL_ADD
, pcm_pollfds
[i
].fd
, &evt
);
2566 fatal("unable to add alsa poll file descriptor[%d]=%d to epoll file descriptor\n", i
, pcm_pollfds
[i
].fd
);
2569 pout("alsa:pcm events installed\n");
2571 #define PRINT_INFO true
2572 #define CHANS_N_NOT_OVERRIDDEN 0
2573 #define RATE_NOT_OVERRIDDEN 0
2574 #define FR_FMT_NOT_OVERRIDDEN AV_FR_FMT_NONE
2575 static void prepare(int st_idx
, double initial_vol
,
2576 int override_initial_ff_chans_n
, int override_initial_ff_rate
,
2577 enum av_fr_fmt override_initial_ff_audio_fr_fmt
)
2579 enum av_fr_fmt dst_fmt
;
2580 int initial_ff_chans_n
;
2581 int initial_ff_rate
;
2582 enum av_fr_fmt initial_ff_audio_fr_fmt
;
2584 current_st_idx
= st_idx
;
2586 dec_ctx_cfg(fmt_ctx
->sts
[st_idx
]->codecpar
);
2587 dec_frs
.most_recent_ts
= fmt_ctx
->sts
[st_idx
]->start_time
;
2588 cmd_info_data
.fmt
.duration
= fmt_ctx
->duration
;
2589 cmd_info_data
.fmt
.m
= fmt_ctx
->duration_estimation_method
;
2590 cmd_info_data
.st
.tb
= fmt_ctx
->sts
[st_idx
]->tb
;
2591 cmd_info_data
.st
.id
= fmt_ctx
->sts
[st_idx
]->id
;
2592 cmd_info_data
.st
.duration
= fmt_ctx
->sts
[st_idx
]->duration
;
2595 if (override_initial_ff_chans_n
== CHANS_N_NOT_OVERRIDDEN
)
2596 initial_ff_chans_n
= dec_ctx
->ch_layout
.nb_channels
;
2598 initial_ff_chans_n
= override_initial_ff_chans_n
;
2599 if (override_initial_ff_rate
== RATE_NOT_OVERRIDDEN
)
2600 initial_ff_rate
= dec_ctx
->fr_rate
;
2602 initial_ff_rate
= override_initial_ff_rate
;
2603 if (override_initial_ff_audio_fr_fmt
== FR_FMT_NOT_OVERRIDDEN
)
2604 initial_ff_audio_fr_fmt
= dec_ctx
->fr_fmt
;
2606 initial_ff_audio_fr_fmt
= override_initial_ff_audio_fr_fmt
;
2607 /* best effort configuration of the pcm based on initial ff params */
2608 pcm_cfg(pcm_g
, initial_ff_chans_n
, initial_ff_rate
,
2609 initial_ff_audio_fr_fmt
);
2610 silence_bufs_cfg(pcm_g
, PRINT_INFO
);
2612 filt_frs
.vol
= initial_vol
;
2615 #undef CHANS_N_NOT_OVERRIDDEN
2616 #undef RATE_NOT_OVERRIDDEN
2617 #undef AUDIO_FR_FMT_NOT_OVERRIDDEN
2620 static void seek_x(int64_t delta
)
2627 if (dec_frs
.most_recent_ts
== AV_NOPTS_VALUE
)
2628 warning("unable to seek because no time stamp are currently available\n");
2630 st
= fmt_ctx
->sts
[current_st_idx
];
2634 new_ts
= dec_frs
.most_recent_ts
+ delta
* (int64_t)st_tb
.den
2635 / (int64_t)st_tb
.num
;
2636 /* rewind capping */
2637 pout("trying to seek to %"PRId64
" stream time base units\n", new_ts
);
2639 atomic_store(&cb
.hold
, HOLD
);
2640 rd_thd_reset(current_st_idx
);
2642 r
= av_seek_pkt(fmt_ctx
, st
->id
, new_ts
, 0);
2645 warning("unable to seek to %"PRId64
" stream time base units\n", new_ts
);
2646 dec_frs
.most_recent_ts
= AV_NOPTS_VALUE
;
2647 av_flush_bufs(dec_ctx
);
2649 atomic_store(&cb
.hold
, DONT_HOLD
);
2653 static void cmd_rewind(void)
2655 pout("COMMAND:rewind\n");
2656 seek_x(-SEEK_DELTA
);
2658 static void cmd_rewind_big(void)
2660 pout("COMMAND:rewind big\n");
2661 seek_x(-SEEK_DELTA_BIG
);
2663 static void cmd_fastforward(void)
2665 pout("COMMAND:fastforward\n");
2668 static void cmd_fastforward_big(void)
2670 pout("COMMAND:fastforward big\n");
2671 seek_x(SEEK_DELTA_BIG
);
2673 static void cmd_pause(void)
2676 pout("COMMAND:unpause\n");
2679 pout("COMMAND:pause\n");
2683 static void cmd_vol_up(void)
2686 u8 vol_l10n_str
[sizeof("xxx.xx")]; /* should be overkill */
2687 u8 response
[STR_SZ
];
2689 filt_frs
.vol
+= VOL_DELTA
;
2690 if (filt_frs
.vol
> 1.0)
2692 snprintf(vol_l10n_str
, sizeof(vol_l10n_str
), "%f", filt_frs
.vol
);
2693 pout("COMMAND:volume up to value %s(%s)\n", vol_l10n_str
, filt_frs
.muted
? "muted" : "unmuted");
2696 r
= av_filt_graph_send_cmd(filt_graph
, "vol", "volume", vol_l10n_str
,
2697 response
, sizeof(response
), 0);
2699 warning("ffmpeg:volume context:unable to set the volume up to \"%s\":response from volume filter:\"%s\"\n", response
);
2701 static void cmd_vol_down(void)
2704 u8 vol_l10n_str
[sizeof("xxx.xx")]; /* should be overkill */
2705 u8 response
[STR_SZ
];
2707 filt_frs
.vol
-= VOL_DELTA
;
2708 if (filt_frs
.vol
< 0.0)
2710 snprintf(vol_l10n_str
, sizeof(vol_l10n_str
), "%f", filt_frs
.vol
);
2711 pout("COMMAND:volume down to value %s(%s)\n", vol_l10n_str
, filt_frs
.muted
? "muted" : "unmuted");
2714 r
= av_filt_graph_send_cmd(filt_graph
, "vol", "volume", vol_l10n_str
,
2715 response
, sizeof(response
), 0);
2717 warning("ffmpeg:volume context:unable to set the volume down to \"%s\":response from volume filter:\"%s\"\n", response
);
2719 static void cmd_vol_up_small(void)
2722 u8 vol_l10n_str
[sizeof("xxx.xx")]; /* should be overkill */
2723 u8 response
[STR_SZ
];
2725 filt_frs
.vol
+= VOL_DELTA_SMALL
;
2726 if (filt_frs
.vol
> 1.0)
2728 snprintf(vol_l10n_str
, sizeof(vol_l10n_str
), "%f", filt_frs
.vol
);
2729 pout("COMMAND:volume up to value %s(%s)\n", vol_l10n_str
, filt_frs
.muted
? "muted" : "unmuted");
2732 r
= av_filt_graph_send_cmd(filt_graph
, "vol", "volume", vol_l10n_str
,
2733 response
, sizeof(response
), 0);
2735 warning("ffmpeg:volume context:unable to set the volume up to \"%s\":response from volume filter:\"%s\"\n", response
);
2737 static void cmd_vol_down_small(void)
2740 u8 vol_l10n_str
[sizeof("xxx.xx")]; /* should be overkill */
2741 u8 response
[STR_SZ
];
2743 filt_frs
.vol
-= VOL_DELTA_SMALL
;
2744 if (filt_frs
.vol
< 0.0)
2746 snprintf(vol_l10n_str
, sizeof(vol_l10n_str
), "%f", filt_frs
.vol
);
2747 pout("COMMAND:volume down to value %s(%s)\n", vol_l10n_str
, filt_frs
.muted
? "muted" : "unmuted");
2750 r
= av_filt_graph_send_cmd(filt_graph
, "vol", "volume", vol_l10n_str
,
2751 response
, sizeof(response
), 0);
2753 warning("ffmpeg:volume context:unable to set the volume down to \"%s\":response from volume filter:\"%s\"\n", response
);
2755 static void cmd_mute(void)
2758 u8 vol_l10n_str
[sizeof("xxx.xx")]; /* should be overkill */
2759 u8 response
[STR_SZ
];
2761 if (filt_frs
.muted
) {
2762 pout("COMMAND:unmuting\n");
2764 snprintf(vol_l10n_str
, sizeof(vol_l10n_str
), "%f",
2766 r
= av_filt_graph_send_cmd(filt_graph
, "vol", "volume",
2767 vol_l10n_str
, response
, sizeof(response
), 0);
2769 warning("ffmpeg:volume context:unable to mute the volume to 0:response from volume filter:%s\n", response
);
2771 filt_frs
.muted
= false;
2774 pout("COMMAND:muting\n");
2776 r
= av_filt_graph_send_cmd(filt_graph
, "vol", "volume",
2777 double_zero_l10n_str
, response
, sizeof(response
), 0);
2779 warning("ffmpeg:volume context:unable to mute the volume to 0:response from volume filter:%s\n", response
);
2781 filt_frs
.muted
= true;
2785 #define CHANS_N_NOT_OVERRIDDEN 0
2786 #define RATE_NOT_OVERRIDDEN 0
2787 #define FR_FMT_NOT_OVERRIDDEN AV_FR_FMT_NONE
2788 int main(int argc
, u8
**args
)
2793 unsigned int cb_slots_n
;
2795 /* audio override -- start */
2797 * we could have got direct parameters for alsa, but doing only an
2798 * override triggers an autoconfiguration of any missing parameters
2799 * based on initial codec params. In other words, the user is not
2800 * required to provide all audio params, the code will try to fit the
2801 * missing ones with the initial codec params, which is the default
2804 int override_initial_ff_chans_n
;
2805 int override_initial_ff_rate
;
2806 enum av_fr_fmt override_initial_ff_audio_fr_fmt
;
2807 /* audio override -- end */
2808 /* "turn on utf8" processing in used libs if any *AND* locale system */
2809 setlocale(LC_ALL
, "");
2810 /* av_log_set_level(AV_LOG_VERBOSE); */
2811 /* av_log_set_level(AV_LOG_DEBUG); */
2813 override_initial_ff_chans_n
= CHANS_N_NOT_OVERRIDDEN
;
2814 override_initial_ff_rate
= RATE_NOT_OVERRIDDEN
;
2815 override_initial_ff_audio_fr_fmt
= FR_FMT_NOT_OVERRIDDEN
;
2816 pcm_str
= "default";
2819 opts_parse(argc
, args
, &url
, &pcm_str
, &initial_vol
, &cb_slots_n
,
2820 &override_initial_ff_chans_n
, &override_initial_ff_rate
,
2821 &override_initial_ff_audio_fr_fmt
);
2822 init_once(url
, pcm_str
, cb_slots_n
);
2823 best_st_idx
= find_best_st();
2824 rd_thd_start(best_st_idx
);
2825 prepare(best_st_idx
, initial_vol
, override_initial_ff_chans_n
,
2826 override_initial_ff_rate
, override_initial_ff_audio_fr_fmt
);
2828 /* switch the ff log to stdout for metadata/etc dump */
2829 av_log_set_callback(ff_log_stdout
);
2831 av_dump_fmt(fmt_ctx
, 0, url
, 0);
2833 av_log_set_callback(av_log_default_callback
);
2837 #undef CHANS_N_NOT_OVERRIDDEN
2838 #undef RATE_NOT_OVERRIDDEN
2839 #undef AUDIO_FR_FMT_NOT_OVERRIDDEN
2840 /*----------------------------------------------------------------------------*/
2842 #undef snd_pcm_fmt_desc
2843 #undef snd_pcm_fmt_set_silence
2844 #undef SND_PCM_FMT_FLT
2845 #undef SND_PCM_FMT_S16
2846 #undef SND_PCM_FMT_S24
2847 #undef SND_PCM_FMT_S32
2848 #undef SND_PCM_FMT_S8
2849 #undef snd_pcm_fmt_t
2850 #undef SND_PCM_FMT_U16
2851 #undef SND_PCM_FMT_U24
2852 #undef SND_PCM_FMT_U32
2853 #undef SND_PCM_FMT_U8
2854 #undef SND_PCM_ST_PLAYBACK
2855 #undef snd_pcm_frs_to_bytes
2856 #undef snd_pcm_hw_params_get_chans
2857 #undef snd_pcm_hw_params_get_chans_max
2858 #undef snd_pcm_hw_params_get_chans_min
2859 #undef snd_pcm_hw_params_get_buf_size
2860 #undef snd_pcm_hw_params_get_fmt
2861 #undef snd_pcm_hw_params_set_buf_size_near
2862 #undef snd_pcm_hw_params_set_chans
2863 #undef snd_pcm_hw_params_set_fmt
2864 #undef snd_pcm_hw_params_test_chans
2865 #undef snd_pcm_hw_params_test_fmt
2866 #undef snd_pcm_sfrs_t
2867 #undef snd_pcm_ufrs_t
2868 /*----------------------------------------------------------------------------*/
2870 #undef AV_AUDIO_FR_FMT_NONE
2871 #undef av_bufsink_get_frs
2872 #undef av_bufsrc_add_frs_flags
2873 #undef AV_BUFSRC_FLAG_KEEP_REF
2874 #undef AV_BUFSRC_FLAG_PUSH
2878 #undef av_duration_estimation_method
2881 #undef av_filt_get_by_name
2882 #undef av_filt_graph
2883 #undef av_filt_graph_alloc
2884 #undef av_filt_graph_alloc_filt
2885 #undef av_filt_graph_cfg
2886 #undef av_filt_graph_dump
2887 #undef av_filt_graph_free
2888 #undef av_filt_graph_send_cmd
2889 #undef av_filt_init_str
2891 #undef av_find_best_st
2892 #undef av_flush_bufs
2894 #undef AV_FMT_DURATION_FROM_BITRATE
2895 #undef AV_FMT_DURATION_FROM_PTS
2896 #undef AV_FMT_DURATION_FROM_ST
2897 #undef av_fmt_find_st_info
2899 #undef av_fmt_open_input
2900 #undef av_fr_fmt_is_planar
2901 #undef AV_FR_FMT_FLT
2902 #undef AV_FR_FMT_FLTP
2903 #undef AV_FR_FMT_S16
2904 #undef AV_FR_FMT_S16P
2905 #undef AV_FR_FMT_S32
2906 #undef AV_FR_FMT_S32P
2907 #undef AV_FR_FMT_U8P
2910 #undef av_frs_set_silence
2912 #undef av_get_fr_fmt_name
2913 #undef av_get_fr_fmt_str
2915 #undef AV_MEDIA_TYPE_AUDIO
2921 #undef av_receive_frs
2932 /*----------------------------------------------------------------------------*/
2942 /*----------------------------------------------------------------------------*/
2946 #undef INPUT_ESC_SEQ_TIMEOUT_SECS_N
2948 #undef PCM_POLLFDS_N_MAX
2951 #undef SEEK_DELTA_BIG