96using std::ostringstream;
97using std::setprecision;
100using std::unique_ptr;
101using namespace std::string_literals;
109#define DEFAULT_AUDIO_RECV_BUF_SIZE (256 * 1024)
110#define MOD_NAME "[audio] "
207 printf(
"\t--audio-channel-map <mapping> mapping of input audio channels\n");
208 printf(
"\t to output audio channels comma-separated\n");
209 printf(
"\t list of channel mapping (receiver only)\n");
210 printf(
"\t eg. 0:0,1:0 - mixes first 2 channels\n");
211 printf(
"\t 0:0 - play only first channel\n");
212 printf(
"\t 0:0,:1 - sets second channel to\n");
213 printf(
"\t a silence, first one is\n");
214 printf(
"\t left as is\n");
215 printf(
"\t 0:0,0:1 - splits mono into\n");
216 printf(
"\t 2 channels\n");
222 col() <<
TBOLD(
TRED(
"\t--audio-scale [<factor>|<method>]\n"));
223 col() <<
"\t Floating point number that tells a static scaling factor for all\n";
224 col() <<
"\t output channels. Scaling method can be one from these:\n";
225 col() <<
TBOLD(
"\t 0.0-1.0") <<
" - factor to scale to (usually 0-1 but can be more)\n";
226 col() <<
TBOLD(
"\t mixauto") <<
" - automatically adjust volume if using channel\n";
227 col() <<
"\t mixing/remapping (default)\n";
228 col() <<
TBOLD(
"\t auto") <<
" - automatically adjust volume\n";
229 col() <<
TBOLD(
"\t none") <<
" - no scaling will be performed\n";
234 s->should_exit =
true;
242 array<char, 1024> pathV{};
247 auto *msgV2 =
reinterpret_cast<struct
msg_sender *
>(
249 strncpy(
static_cast<char *
>(msgV2->receiver), address,
250 sizeof(msgV2->receiver) - 1);
254 reinterpret_cast<struct
message *
>(msgV2));
257 <<
"[SDP] Changing address to " << address <<
"\n";
260 <<
"[SDP] Unable to change address to " << address <<
" ("
276 char *tmp, *unused = NULL;
290 strcmp(
"help", opt->
scale) == 0) {
309 fprintf(stderr,
"Echo cancellation is currently experimental "
310 "and may not work as expected.");
313 fprintf(stderr,
"Speex not compiled in. Could not enable echo cancellation.\n");
323 std::string_view
item;
334 assert(opt->
host !=
nullptr);
335 tmp = strdup(opt->
host);
337 addr = strtok_r(tmp,
",", &unused);
338 assert(addr !=
nullptr);
346 strlen(s->
opts.mcast_if) > 0 ? s->
opts.mcast_if :
nullptr;
350 if (strcmp(opt->
send_cfg,
"none") != 0) {
351 const char *cfg =
"";
352 char *device = strdup(opt->
send_cfg);
353 if(strchr(device,
':')) {
354 char *delim = strchr(device,
':');
369 fprintf(stderr,
"Unable to initialize audio transmit.\n");
378 if (strcmp(opt->
recv_cfg,
"none") != 0) {
379 const char *cfg =
"";
380 char *device = strdup(opt->
recv_cfg);
381 if(strchr(device,
':')) {
382 char *delim = strchr(device,
':');
407 size_t len =
sizeof(
struct rtp *);
421 if (strcasecmp(
opt->proto,
"ultragrid_rtp") == 0) {
424 }
else if (strcasecmp(
opt->proto,
"rtsp") == 0 || strcasecmp(
opt->proto,
"sdp") == 0) {
427 if (strcasecmp(
opt->proto,
"sdp") == 0) {
432 }
else if (strcasecmp(
opt->proto,
"JACK") == 0) {
433#ifndef HAVE_JACK_TRANS
434 fprintf(stderr,
"[Audio] JACK transport requested, "
435 "but JACK support isn't compiled.\n");
464#ifdef HAVE_JACK_TRANS
487 s->audio_sender_thread_started =
true;
497 s->audio_receiver_thread_started =
true;
555 (uint8_t *)
params->participants,
556 params->force_ip_version,
false);
563 PACKAGE_STRING, strlen(PACKAGE_VERSION));
591 string err = string(
"Changing audio RX port to ") +
592 to_string(
msg->new_rx_port) +
" failed!";
599 <<
msg->new_rx_port <<
".\n";
604 char volume_str[128] =
"";
605 snprintf(volume_str,
sizeof volume_str,
"%lf,%d", ret,
626 double db = 20.0 * log10(new_volume);
633 "Playback volume: %.2f%% (%+.2f dB)\n",
634 new_volume * 100.0,
db);
638 while (cp !=
nullptr) {
641 if (dec_state !=
nullptr) {
643 dec_state->pbuf_data.decoder, new_volume);
659 assert(dec_state != NULL);
660 dec_state->enabled =
true;
661 dec_state->pbuf_data.decoder =
666 if (!dec_state->pbuf_data.decoder) {
686 size_t new_size = curr_frame_len * 2;
690 LOG(
LOG_LEVEL_DEBUG) <<
"[Audio receiver] Recv buffer adjusted to " << new_size <<
"\n";
702 bool playback_supports_multiple_streams;
706#ifdef HAVE_JACK_TRANS
708 current_pbuf = &jack_pbuf;
711 size_t len =
sizeof playback_supports_multiple_streams;
713 &playback_supports_multiple_streams, &
len)) {
714 playback_supports_multiple_streams =
false;
718 printf(
"Audio receiving started.\n");
726 bool decoded =
false;
730 uint32_t
ts = (curr_time - s->
start_time) / 100'000 * 9;
733 struct timeval timeout;
737 if ((curr_time - last_not_timeout) >
NS_IN_SEC) {
738 timeout.tv_usec = 100000;
740 timeout.tv_usec = 1000;
744 last_not_timeout = curr_time;
753 if (!playback_supports_multiple_streams) {
777 if (dec_state && dec_state->
enabled) {
793 if (decoded && !playback_supports_multiple_streams)
798#ifdef HAVE_JACK_TRANS
816 msg =
"Audio reconfiguration failed";
821 msg =
"Audio reconfiguration succeeded";
822 device_desc = curr_desc;
840 if (!playback_supports_multiple_streams) {
859#ifdef HAVE_JACK_TRANS
872 if (strcmp(
msg->fec_cfg,
"flush") == 0) {
873 delete old_fec_state;
879 if (strstr(
msg->fec_cfg,
"help") !=
884 <<
"[control] Unable to initalize FEC!\n";
888 delete old_fec_state;
890 "[control] Fec changed successfully\n");
905 "Changing receiver failed!");
909 MSG(NOTICE,
"Changed receiver to %s\n",
msg->receiver);
918 if (
msg->rx_port != 0) {
927 "Changing receiver failed!");
930 MSG(NOTICE,
"Changed TX port to %d\n",
msg->tx_port);
959 "[control] Audio: Unable to change SSRC!\n");
965 "[control] Audio: changed SSRC from 0x%08" PRIx32
" to "
966 "0x%08" PRIx32
".\n",
983 d->frame.get_sample_count(),
987 char *vol_start = volume;
988 for (
int i = 0; i < d->frame.get_channel_count(); ++i) {
994 volume +
sizeof volume);
998 volume, d->muted_sender ?
TBOLD(
TRED(
" (muted)")) :
"");
1034 const int *tmp = supported;
1039 if (*tmp >
sample_rate && (rate_hi == 0 || *tmp < rate_hi)) {
1043 if (*tmp < sample_rate && *tmp > rate_lo) {
1049 return rate_hi > 0 ? rate_hi : rate_lo;
1054 struct rtp *netdev,
int tx_port,
bool *audio_spec_to_vrxtx_set)
1056 if (*audio_spec_to_vrxtx_set) {
1060 *audio_spec_to_vrxtx_set =
true;
1065 MSG(VERBOSE,
"Setting audio desc %s, rx port=%d to RXTX.\n",
1068 assert(vrxtx !=
nullptr);
1076 bool audio_spec_to_vrxtx_set =
false;
1078 unique_ptr<audio_frame2_resampler> resampler_state;
1087 printf(
"Audio sending started.\n");
1098 uint32_t
ts = (curr_time - s->
start_time) / 10'0000 * 9;
1103 struct timeval timeout;
1105 timeout.tv_usec = 0;
1132 if (resample_to == 0) {
1142 bf_n.
resample(*resampler_state, resample_to);
1154 uncompressed = NULL;
1161 uncompressed = NULL;
1163 s->
vrxtx, &compressed,
1166 &audio_spec_to_vrxtx_set);
1169#ifdef HAVE_JACK_TRANS
1201 (bool (*)(
void *,
int,
int,
1203 (bool (*)(
void *,
int,
void *,
struct video_frame * frame
This file contains definition of some common audio types.
void audio_register_aux_data(struct state_audio *s, struct additional_audio_data data)
static void should_exit_audio(void *state)
unsigned int audio_get_display_flags(struct state_audio *s)
void(* audio_device_help_t)(void)
static struct rtp * initialize_audio_network(struct audio_network_parameters *params)
static int find_codec_sample_rate(int sample_rate, const int *supported)
static void audio_scale_usage(void)
static void audio_update_recv_buf(struct state_audio *s, size_t curr_frame_len)
static void set_audio_spec_to_vrxtx(struct video_rxtx *vrxtx, audio_frame2 *compressed_frm, struct rtp *netdev, int tx_port, bool *audio_spec_to_vrxtx_set)
void audio_join(struct state_audio *s)
static struct response * audio_sender_process_message(struct state_audio *s, struct msg_sender *msg)
static struct response * audio_receiver_process_message(struct state_audio *s, struct msg_receiver *msg)
static struct audio_decoder * audio_decoder_state_create(struct state_audio *s)
static void * audio_sender_thread(void *arg)
void audio_sdi_send(struct state_audio *s, struct audio_frame *frame)
static void * audio_receiver_thread(void *arg)
static void audio_decoder_state_deleter(void *state)
#define DEFAULT_AUDIO_RECV_BUF_SIZE
void audio_done(struct state_audio *s)
static void process_statistics(struct state_audio *s, audio_frame2 *buffer)
int audio_init(struct state_audio **ret, const struct audio_options *opt, const struct common_opts *common)
static void * asend_compute_and_print_stats(void *arg)
static void audio_channel_map_usage(void)
void sdp_send_change_address_message(struct module *root, const enum module_class *path, const char *address)
void audio_start(struct state_audio *s)
std::ostream & operator<<(std::ostream &os, const audio_desc &desc)
int audio_capture_init(struct module *parent, const char *driver, const char *cfg, struct state_audio_capture **state)
struct state_audio_capture * audio_capture_init_null_device()
unsigned int audio_capture_get_vidcap_flags(const char *const_device_name)
void audio_capture_done(struct state_audio_capture *s)
void * audio_capture_get_state_pointer(struct state_audio_capture *s)
const char * audio_capture_get_driver_name(struct state_audio_capture *s)
struct audio_frame * audio_capture_read(struct state_audio_capture *s)
void audio_decoder_destroy(void *state)
int decode_audio_frame_mulaw(struct coded_data *cdata, void *data, struct pbuf_stats *)
void * audio_decoder_init(char *audio_channel_map, const char *audio_scale, const char *encryption, audio_playback_ctl_t c, void *p_state, struct module *parent)
int decode_audio_frame(struct coded_data *cdata, void *pbuf_data, struct pbuf_stats *)
void audio_decoder_set_volume(void *state, double val)
bool(* audio_playback_ctl_t)(void *state, int request, void *data, size_t *len)
bool audio_playback_ctl(struct state_audio_playback *s, int request, void *data, size_t *len)
void * audio_playback_get_state_pointer(struct state_audio_playback *s)
unsigned int audio_playback_get_display_flags(struct state_audio_playback *s)
bool audio_playback_reconfigure(struct state_audio_playback *s, int quant_samples, int channels, int sample_rate)
int audio_playback_init(const char *device, const char *cfg, struct state_audio_playback **state)
struct state_audio_playback * audio_playback_init_null_device(void)
void audio_playback_put_frame(struct state_audio_playback *s, const struct audio_frame *frame)
void audio_playback_done(struct state_audio_playback *s)
#define AUDIO_PLAYBACK_CTL_MULTIPLE_STREAMS
#define AUDIO_PLAYBACK_PUT_NETWORK_DEVICE
bool emplace_new(std::string_view cfg)
af_result_code filter(struct audio_frame **frame)
void change_bps(int new_bps)
struct audio_desc get_desc() const
bool has_same_prop_as(audio_frame2 const &frame) const
void init(int nr_channels, audio_codec_t codec, int bps, int sample_rate)
Initializes audio_frame2 for use. If already initialized, data are dropped.
audio_codec_t get_codec() const
int get_channel_count() const
bool resample(audio_frame2_resampler &resampler_state, int new_sample_rate)
int get_sample_rate() const
void append(audio_frame2 const &frame)
struct audio_codec_state * audio_codec_init_cfg(const char *audio_codec_cfg, audio_codec_direction_t direction)
struct audio_codec_params parse_audio_codec_params(const char *ccfg)
const char * get_name_to_audio_codec(audio_codec_t codec)
audio_frame2 audio_codec_compress(struct audio_codec_state *s, const audio_frame2 *frame)
const int * audio_codec_get_supported_samplerates(struct audio_codec_state *s)
void audio_codec_done(struct audio_codec_state *s)
static void new_message(struct module *m)
void log_msg(int level, const char *format,...)
#define LOG_LEVEL_NOTICE
information that may be interesting
#define LOG_LEVEL_INFO
normal reporting
#define LOG_LEVEL_ERROR
general errors
#define LOG_LEVEL_FATAL
errors that prevent UG run
#define LOG_LEVEL_WARNING
less severe errors
struct echo_cancellation * echo_cancellation_init(void)
void echo_play(struct echo_cancellation *s, struct audio_frame *frame)
struct audio_frame * echo_cancel(struct echo_cancellation *s, struct audio_frame *frame)
void export_audio(struct exporter *s, struct audio_frame *frame)
void module_done(struct module *module_data)
struct module * get_root_module(struct module *node)
void append_message_path(char *buf, int buflen, const enum module_class *modules)
void register_should_exit_callback(struct module *mod, void(*callback)(void *), void *udata)
volatile int audio_offset
added audio delay in ms (non-negative), can be used to tune AV sync
const char * get_commandline_param(const char *key)
void unregister_should_exit_callback(struct module *mod, void(*callback)(void *), void *udata)
void * jack_start(const char *cfg)
int is_jack_receiver(void *state)
void jack_send(void *state, struct audio_frame *frame)
bool jack_receive(void *state, void *data)
Receives data from JACK.
int is_jack_sender(void *state)
@ STR_LEN
"standard" string length placeholder
void free_message(struct message *msg, struct response *r)
struct response * new_response(int status, const char *text)
int response_get_status(struct response *r)
struct response * send_message(struct module *root, const char *const_path, struct message *msg)
Sends message without waiting for response.
struct message * check_message(struct module *mod)
void free_response(struct response *r)
@ SENDER_MSG_QUERY_VIDEO_MODE
@ SENDER_MSG_CHANGE_RECEIVER
@ RECEIVER_MSG_MUTE_TOGGLE
@ RECEIVER_MSG_DECREASE_VOLUME
@ RECEIVER_MSG_CHANGE_RX_PORT
@ RECEIVER_MSG_INCREASE_VOLUME
@ RECEIVER_MSG_GET_AUDIO_STATUS
@ RECEIVER_MSG_VIDEO_PROP_CHANGED
#define RESPONSE_BAD_REQUEST
#define RESPONSE_INT_SERV_ERR
#define IN6_BLACKHOLE_SERVER_MODE_STR
int pbuf_decode(struct pbuf *playout_buf, time_ns_t curr_time, decode_frame_t decode_func, void *data)
void pbuf_set_playout_delay(struct pbuf *playout_buf, double playout_delay)
int pbuf_is_empty(struct pbuf *playout_buf)
void pbuf_remove(struct pbuf *playout_buf, time_ns_t curr_time)
void pdb_iter_done(pdb_iter_t *it)
struct pdb_e * pdb_iter_next(pdb_iter_t *it)
struct pdb_e * pdb_iter_init(struct pdb *db, pdb_iter_t *it)
struct pdb * pdb_init(volatile int *delay_ms)
int pdb_add(struct pdb *db, uint32_t ssrc)
void pdb_destroy(struct pdb **db_p)
void rtp_flush_recv_buf(struct rtp *session)
bool rtp_set_recv_buf(struct rtp *session, int bufsize)
bool rtp_set_option(struct rtp *session, rtp_option optname, int optval)
void rtp_update(struct rtp *session, time_ns_t curr_time)
struct rtp * rtp_init_if(const char *addr, const char *iface, uint16_t rx_port, uint16_t tx_port, int ttl, double rtcp_bw, int tfrc_on, rtp_callback callback, uint8_t *userdata, int force_ip_version, bool multithreaded)
uint32_t rtp_my_ssrc(struct rtp *session)
void rtp_send_ctrl(struct rtp *session, uint32_t rtp_ts, rtcp_app_callback appcallback, time_ns_t curr_time)
bool rtp_set_sdes(struct rtp *session, uint32_t ssrc, rtcp_sdes_type type, const char *value, int length)
int rtp_get_udp_rx_port(struct rtp *session)
bool rtp_recv_r(struct rtp *session, struct timeval *timeout, uint32_t curr_rtp_ts)
Receive RTP packets and dispatch them.
bool rtp_is_ipv6(struct rtp *session)
bool rtcp_recv_r(struct rtp *session, struct timeval *timeout, uint32_t curr_rtp_ts)
void rtp_done(struct rtp *session)
@ RTP_OPT_WEAK_VALIDATION
void rtp_recv_callback(struct rtp *session, rtp_event *e)
void sdi_register_display_callbacks(void *state, void *udata, void(*putf)(void *, const struct audio_frame *), bool(*reconfigure)(void *, int, int, int), bool(*get_property)(void *, int, void *, size_t *))
void sdi_capture_new_incoming_frame(void *state, struct audio_frame *frame)
int sdp_set_options(const char *opts)
std::string_view tokenize(std::string_view &str, char delim, char quot)
Tokenizer for string_view.
struct additional_audio_data::@2 display_callbacks
void(* putf)(struct display *, const struct audio_frame *)
bool(* reconfigure)(struct display *, int, int, int)
bool(* get_property)(struct display *, int, void *, size_t *)
struct video_rxtx * vrxtx
struct pbuf_audio_data pbuf_data
struct used to comunicate with audio capture/playback device
struct pdb * participants
struct exporter * exporter
static fec * create_from_config(const char *str, bool is_audio) noexcept
virtual std::shared_ptr< video_frame > encode(std::shared_ptr< video_frame >)=0
struct sockaddr_storage source
size_t frame_size
currently decoded audio frame size (used similarly as vcodec_state::max_frame_size to allow caller ad...
struct state_audio_decoder * decoder
decoder_state_deleter_t decoder_state_deleter
decoder state deleter
void * decoder_state
state of decoder for participant
struct pbuf * playout_buffer
pthread_t audio_sender_thread_id
bool audio_receiver_thread_started
pthread_t audio_receiver_thread_id
struct video_rxtx * vrxtx
state_audio(struct module *parent, time_ns_t st)
enum audio_transport_device sender
module_raii audio_sender_module
struct pdb * audio_participants
module_raii audio_receiver_module
bool audio_sender_thread_started
enum audio_transport_device receiver
Filter_chain filter_chain
struct state_audio_playback * audio_playback_device
struct audio_codec_state * audio_encoder
struct rtp * audio_network_device
echo_cancellation_t * echo_state
struct state_audio_capture * audio_capture_device
struct exporter * exporter
virtual void set_audio_spec(const struct audio_desc *desc, int audio_rx_port, int audio_tx_port, bool ipv6)
void set_thread_name(const char *name)
void audio_tx_send(struct tx *tx, struct rtp *rtp_session, const audio_frame2 *buffer)
void audio_tx_send_standard(struct tx *tx, struct rtp *rtp_session, const audio_frame2 *buffer)
struct tx * tx_init(struct module *parent, unsigned mtu, enum tx_media_type media_type, const char *fec, const char *encryption, long long int bitrate)
static time_ns_t get_time_in_ns()
struct audio_desc audio_desc_from_frame(const struct audio_frame *frame)
bool audio_desc_eq(struct audio_desc a1, struct audio_desc a2)
double calculate_rms(audio_frame2 *frame, int channel, double *peak)
Calculates mean and peak RMS from audio samples.
void format_audio_channel_volume(int chan_idx, double rms, double peak, const char *format_color, char **volume_start, char *volume_end)
format per channel incrementally volume string (eg. "[0]-18.00/-14.99, [1] -18.00/-14....
const char * audio_desc_to_cstring(struct audio_desc desc)
void task_run_async_detached(runnable_t task, void *data)
Runs task asynchronously in a detached state.