diff --git a/src/audio/audio.cpp b/src/audio/audio.cpp index 7762870f0..154a1200b 100644 --- a/src/audio/audio.cpp +++ b/src/audio/audio.cpp @@ -88,6 +88,7 @@ #include "rtp/pbuf.h" #include "tv.h" #include "transmit.h" +#include "types.h" #include "pdb.h" #include "ug_runtime_error.hpp" #include "utils/color_out.h" @@ -305,7 +306,7 @@ int audio_init(struct state_audio **ret, struct module *parent, s->audio_scale = opt->scale; s->audio_sender_thread_started = s->audio_receiver_thread_started = false; - s->resample_to = get_audio_codec_sample_rate(opt->codec_cfg); + s->resample_to = parse_audio_codec_params(opt->codec_cfg).sample_rate; s->exporter = exporter; @@ -417,8 +418,14 @@ int audio_init(struct state_audio **ret, struct module *parent, } if ((s->audio_tx_mode & MODE_SENDER) && strcasecmp(opt->proto, "sdp") == 0) { - if (sdp_add_audio(rtp_is_ipv6(s->audio_network_device), opt->send_port, IF_NOT_NULL_ELSE(get_audio_codec_sample_rate(opt->codec_cfg), 48000), - audio_capture_channels, get_audio_codec(opt->codec_cfg), sdp_change_address_callback, get_root_module(parent)) != 0) { + const audio_codec_params params = + parse_audio_codec_params(opt->codec_cfg); + if (sdp_add_audio(rtp_is_ipv6(s->audio_network_device), + opt->send_port, + IF_NOT_NULL_ELSE(params.sample_rate, kHz48), + audio_capture_channels, params.codec, + sdp_change_address_callback, + get_root_module(parent)) != 0) { assert(0 && "[SDP] Cannot add audio"); } } diff --git a/src/audio/codec.cpp b/src/audio/codec.cpp index 1bc270497..fc64982a0 100644 --- a/src/audio/codec.cpp +++ b/src/audio/codec.cpp @@ -43,6 +43,7 @@ #include "audio/codec.h" #include "audio/utils.h" +#include "compat/misc.h" #include "debug.h" #include "lib_common.h" #include "utils/macros.h" @@ -169,9 +170,9 @@ struct audio_codec_state *audio_codec_init_cfg(const char *audio_codec_cfg, static struct audio_codec_state *audio_codec_init_real(const char *audio_codec_cfg, audio_codec_direction_t direction, bool silent) { - audio_codec_t audio_codec = get_audio_codec(audio_codec_cfg); - int bitrate = get_audio_codec_bitrate(audio_codec_cfg); - if (bitrate < 0) { + const struct audio_codec_params params = + parse_audio_codec_params(audio_codec_cfg); + if (params.codec == AC_NONE) { return nullptr; } void *state = NULL; @@ -182,9 +183,10 @@ static struct audio_codec_state *audio_codec_init_real(const char *audio_codec_c for (auto const &it : audio_compressions) { aci = static_cast(it.second); for (unsigned int j = 0; aci->supported_codecs[j] != AC_NONE; ++j) { - if (aci->supported_codecs[j] == audio_codec) { - state = aci->init(audio_codec, direction, silent, bitrate); - if(state) { + if (aci->supported_codecs[j] == params.codec) { + state = aci->init(params.codec, direction, + silent, params.bitrate); + if (state) { break; } if (!silent) { @@ -202,7 +204,7 @@ static struct audio_codec_state *audio_codec_init_real(const char *audio_codec_c if (!silent) { log_msg(LOG_LEVEL_ERROR, "Unable to find encoder for audio codec '%s'\n", - get_name_to_audio_codec(audio_codec)); + get_name_to_audio_codec(params.codec)); } return NULL; } @@ -213,9 +215,9 @@ static struct audio_codec_state *audio_codec_init_real(const char *audio_codec_c s->state[0] = state; s->state_count = 1; s->funcs = aci; - s->desc.codec = audio_codec; + s->desc.codec = params.codec; s->direction = direction; - s->bitrate = bitrate; + s->bitrate = params.bitrate; return s; } @@ -379,71 +381,51 @@ void audio_codec_done(struct audio_codec_state *s) free(s); } -audio_codec_t get_audio_codec(const char *codec_str) { - char *codec = strdup(codec_str); - if (strchr(codec, ':')) { - *strchr(codec, ':') = '\0'; - } +static audio_codec_t +get_audio_codec(const char *codec) +{ for (auto const &it : audio_codec_info) { - if(strcasecmp(it.second.name, codec) == 0) { - free(codec); + if (strcasecmp(it.second.name, codec) == 0) { return it.first; } } - free(codec); return AC_NONE; } -/** - * Caller must free() the returned buffer - */ -static char *get_val_from_cfg(const char *audio_codec_cfg, const char *key) +struct audio_codec_params +parse_audio_codec_params(const char *ccfg) { - char *cfg = strdup(audio_codec_cfg); - char *tmp = cfg; - char *item, *save_ptr, *ret; + char *cfg = strdupa(ccfg); + char *save_ptr = nullptr; + char *tmp = cfg; + char *item = nullptr; - while ((item = strtok_r(cfg, ":", &save_ptr)) != NULL) { - if (strncasecmp(key, item, strlen(key)) == 0) { - ret = strdup(item + strlen(key)); - free(tmp); - return ret; + struct audio_codec_params params { + }; + while ((item = strtok_r(tmp, ":", &save_ptr)) != nullptr) { + tmp = nullptr; + if (params.codec == AC_NONE) { + params.codec = get_audio_codec(item); + if (params.codec == AC_NONE) { + return {}; + } + continue; } - cfg = NULL; - } - free(tmp); - return NULL; -} - -/** - * @returns user specified sample rate or 0 if unspecified - */ -int get_audio_codec_sample_rate(const char *audio_codec_cfg) -{ - char *val = get_val_from_cfg(audio_codec_cfg, "sample_rate="); - if (val) { - int ret = atoi(val); - free(val); - return ret; - } else { - return 0; - } -} - -int get_audio_codec_bitrate(const char *audio_codec_cfg) -{ - char *val = get_val_from_cfg(audio_codec_cfg, "bitrate="); - if (val) { - long long ret = unit_evaluate(val); - if (ret <= 0 && ret > INT_MAX) { - LOG(LOG_LEVEL_ERROR) << "Wrong bitrate: " << val << "\n"; - return -1; + if (strstr(item, "sample_rate=") == item) { + params.sample_rate = atoi(strchr(item, '=') + 1); + } + if (strstr(item, "bitrate=") == item) { + const char *val = strchr(item, '=') + 1; + long long rate = unit_evaluate(val); + if (rate <= 0 && rate > INT_MAX) { + LOG(LOG_LEVEL_ERROR) + << "Wrong bitrate: " << val << "\n"; + return {}; + } + params.bitrate = (int) rate; } - free(val); - return ret; - } else { - return 0; } + return params; } const char *get_name_to_audio_codec(audio_codec_t codec) @@ -468,7 +450,9 @@ audio_codec_t get_audio_codec_to_tag(uint32_t tag) bool check_audio_codec(const char *audio_codec_cfg) { - if (get_audio_codec(audio_codec_cfg) == AC_NONE) { + const struct audio_codec_params params = + parse_audio_codec_params(audio_codec_cfg); + if (params.codec == AC_NONE) { LOG(LOG_LEVEL_ERROR) << "Unknown audio codec given!\n"; return false; } diff --git a/src/audio/codec.h b/src/audio/codec.h index 44568d48b..58465666f 100644 --- a/src/audio/codec.h +++ b/src/audio/codec.h @@ -89,9 +89,13 @@ extern "C" { #endif // defined __cplusplus void list_audio_codecs(void); -audio_codec_t get_audio_codec(const char *audio_codec_cfg); -int get_audio_codec_sample_rate(const char *audio_codec_cfg); -int get_audio_codec_bitrate(const char *audio_codec_cfg); +struct audio_codec_params { + audio_codec_t codec; + int sample_rate; + int bitrate; +}; +struct audio_codec_params parse_audio_codec_params(const char *ccfg); + const char *get_name_to_audio_codec(audio_codec_t codec); uint32_t get_audio_tag(audio_codec_t codec); audio_codec_t get_audio_codec_to_tag(uint32_t audio_tag); diff --git a/src/main.cpp b/src/main.cpp index 156554327..bf20202af 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1350,7 +1350,10 @@ int main(int argc, char *argv[]) col() << TBOLD("Audio playback : ") << opt.audio.recv_cfg << "\n"; col() << TBOLD("MTU : ") << opt.requested_mtu << " B\n"; col() << TBOLD("Video compression: ") << opt.requested_compression << "\n"; - col() << TBOLD("Audio codec : ") << get_name_to_audio_codec(get_audio_codec(opt.audio.codec_cfg)) << "\n"; + col() << TBOLD("Audio codec : ") + << get_name_to_audio_codec( + parse_audio_codec_params(opt.audio.codec_cfg).codec) + << "\n"; col() << TBOLD("Network protocol : ") << video_rxtx::get_long_name(opt.video_protocol) << "\n"; col() << TBOLD("Audio FEC : ") << opt.audio.fec_cfg << "\n"; col() << TBOLD("Video FEC : ") << opt.requested_video_fec << "\n"; @@ -1472,8 +1475,10 @@ int main(int argc, char *argv[]) params["opts"].str = opt.video_protocol_opts; // RTSP - params["audio_codec"].l = get_audio_codec(opt.audio.codec_cfg); - params["audio_sample_rate"].i = get_audio_codec_sample_rate(opt.audio.codec_cfg) ? get_audio_codec_sample_rate(opt.audio.codec_cfg) : 48000; + auto ac_params = parse_audio_codec_params(opt.audio.codec_cfg); + params["audio_codec"].l = ac_params.codec; + params["audio_sample_rate"].i = + IF_NOT_NULL_ELSE(ac_params.sample_rate, kHz48); params["audio_channels"].i = audio_capture_channels; params["audio_bps"].i = 2; params["a_rx_port"].i = opt.audio.recv_port; diff --git a/src/types.h b/src/types.h index 85867aaf3..fc3ba7b74 100644 --- a/src/types.h +++ b/src/types.h @@ -140,6 +140,7 @@ struct pixfmt_desc { }; enum { + kHz48 = 48000, kHz90 = 90000, ///< timestamp time base };