summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlfred E. Heggestad <alfred.heggestad@gmail.com>2018-01-06 16:20:25 +0100
committerAlfred E. Heggestad <alfred.heggestad@gmail.com>2018-01-06 16:20:25 +0100
commit96b9b6c0d94606b346bc67b5ce78bb20f2e28769 (patch)
treef4b56a89140cd593a913e1d39f2dc3822f63570c /src
parent4d6e0dfbad11b6d8f65d15ac5a1743cc8d2afc4d (diff)
audio: sample format for audio encoder/decoder
config: auenc_format s16 # s16, float audec_format s16 # s16, float modules: only opus module supports this for now. default is s16
Diffstat (limited to 'src')
-rw-r--r--src/audio.c117
-rw-r--r--src/config.c6
2 files changed, 98 insertions, 25 deletions
diff --git a/src/audio.c b/src/audio.c
index cc6e41f..0a18454 100644
--- a/src/audio.c
+++ b/src/audio.c
@@ -86,7 +86,7 @@ struct autx {
struct list filtl; /**< Audio filters in encoding order */
struct mbuf *mb; /**< Buffer for outgoing RTP packets */
char device[64]; /**< Audio source device name */
- int16_t *sampv; /**< Sample buffer */
+ void *sampv; /**< Sample buffer */
int16_t *sampv_rs; /**< Sample buffer for resampler */
uint32_t ptime; /**< Packet time for sending */
uint64_t ts_ext; /**< Ext. Timestamp for outgoing RTP */
@@ -97,6 +97,7 @@ struct autx {
bool muted; /**< Audio source is muted */
int cur_key; /**< Currently transmitted event */
enum aufmt src_fmt; /**< Sample format for audio source */
+ enum aufmt enc_fmt;
bool need_conv; /**< Sample format conversion needed */
struct {
@@ -141,13 +142,14 @@ struct aurx {
struct auresamp resamp; /**< Optional resampler for DSP */
struct list filtl; /**< Audio filters in decoding order */
char device[64]; /**< Audio player device name */
- int16_t *sampv; /**< Sample buffer */
+ void *sampv; /**< Sample buffer */
int16_t *sampv_rs; /**< Sample buffer for resampler */
uint32_t ptime; /**< Packet time for receiving */
int pt; /**< Payload type for incoming RTP */
double level_last;
bool level_set;
enum aufmt play_fmt; /**< Sample format for audio playback*/
+ enum aufmt dec_fmt;
bool need_conv; /**< Sample format conversion needed */
struct timestamp_recv ts_recv;/**< Receive timestamp state */
uint64_t n_discard;
@@ -448,7 +450,20 @@ static void encode_rtp_send(struct audio *a, struct autx *tx,
len = mbuf_get_space(tx->mb);
- err = tx->ac->ench(tx->enc, mbuf_buf(tx->mb), &len, sampv, sampc);
+ if (tx->enc_fmt == AUFMT_S16LE) {
+ err = tx->ac->ench(tx->enc, mbuf_buf(tx->mb), &len,
+ sampv, sampc);
+ }
+ else if (tx->ac->encfmth) {
+ err = tx->ac->encfmth(tx->enc, mbuf_buf(tx->mb), &len,
+ tx->enc_fmt, sampv, sampc);
+ }
+ else {
+ warning("audio: sample format not supported by encoder (%s)\n",
+ aufmt_name(tx->enc_fmt));
+ return;
+ }
+
if ((err & 0xffff0000) == 0x00010000) {
/* MPA needs some special treatment here */
tx->ts_ext = err & 0xffff;
@@ -514,7 +529,7 @@ static void poll_aubuf_tx(struct audio *a)
/* timed read from audio-buffer */
- if (tx->src_fmt == AUFMT_S16LE) {
+ if (tx->src_fmt == tx->enc_fmt) {
aubuf_read(tx->aubuf, (uint8_t *)tx->sampv, num_bytes);
}
@@ -545,6 +560,13 @@ static void poll_aubuf_tx(struct audio *a)
if (tx->resamp.resample) {
size_t sampc_rs = AUDIO_SAMPSZ;
+ if (tx->enc_fmt != AUFMT_S16LE) {
+ warning("audio: skipping resampler due to"
+ " incompatible format (%s)\n",
+ aufmt_name(tx->enc_fmt));
+ return;
+ }
+
err = auresamp(&tx->resamp,
tx->sampv_rs, &sampc_rs,
tx->sampv, sampc);
@@ -555,15 +577,23 @@ static void poll_aubuf_tx(struct audio *a)
sampc = sampc_rs;
}
- /* Process exactly one audio-frame in list order */
- for (le = tx->filtl.head; le; le = le->next) {
- struct aufilt_enc_st *st = le->data;
+ if (tx->enc_fmt == AUFMT_S16LE) {
- if (st->af && st->af->ench)
- err |= st->af->ench(st, sampv, &sampc);
+ /* Process exactly one audio-frame in list order */
+ for (le = tx->filtl.head; le; le = le->next) {
+ struct aufilt_enc_st *st = le->data;
+
+ if (st->af && st->af->ench)
+ err |= st->af->ench(st, sampv, &sampc);
+ }
+ if (err) {
+ warning("audio: aufilter encode: %m\n", err);
+ }
}
- if (err) {
- warning("audio: aufilter encode: %m\n", err);
+ else if (!list_isempty(&tx->filtl)) {
+ warning("audio: skipping audio-filters due to"
+ " incompatible format (%s)\n",
+ aufmt_name(tx->enc_fmt));
}
/* Encode and send */
@@ -726,7 +756,7 @@ static void handle_telev(struct audio *a, struct mbuf *mb)
static int aurx_stream_decode(struct aurx *rx, struct mbuf *mb)
{
size_t sampc = AUDIO_SAMPSZ;
- int16_t *sampv;
+ void *sampv;
struct le *le;
int err = 0;
@@ -735,10 +765,25 @@ static int aurx_stream_decode(struct aurx *rx, struct mbuf *mb)
return 0;
if (mbuf_get_left(mb)) {
- err = rx->ac->dech(rx->dec, rx->sampv, &sampc,
- mbuf_buf(mb), mbuf_get_left(mb));
+
+ if (rx->dec_fmt == AUFMT_S16LE) {
+ err = rx->ac->dech(rx->dec, rx->sampv, &sampc,
+ mbuf_buf(mb), mbuf_get_left(mb));
+
+ }
+ else if (rx->ac->decfmth) {
+ err = rx->ac->decfmth(rx->dec,
+ rx->dec_fmt, rx->sampv, &sampc,
+ mbuf_buf(mb), mbuf_get_left(mb));
+ }
+ else {
+ warning("audio: sample format not supported"
+ " by decoder (%s)\n",
+ aufmt_name(rx->dec_fmt));
+ return ENOTSUP;
+ }
}
- else if (rx->ac->plch) {
+ else if (rx->ac->plch && rx->dec_fmt == AUFMT_S16LE) {
sampc = rx->ac->srate * rx->ac->ch * rx->ptime / 1000;
err = rx->ac->plch(rx->dec, rx->sampv, &sampc);
@@ -754,12 +799,19 @@ static int aurx_stream_decode(struct aurx *rx, struct mbuf *mb)
goto out;
}
- /* Process exactly one audio-frame in reverse list order */
- for (le = rx->filtl.tail; le; le = le->prev) {
- struct aufilt_dec_st *st = le->data;
+ if (rx->dec_fmt == AUFMT_S16LE) {
+ /* Process exactly one audio-frame in reverse list order */
+ for (le = rx->filtl.tail; le; le = le->prev) {
+ struct aufilt_dec_st *st = le->data;
- if (st->af && st->af->dech)
- err |= st->af->dech(st, rx->sampv, &sampc);
+ if (st->af && st->af->dech)
+ err |= st->af->dech(st, rx->sampv, &sampc);
+ }
+ }
+ else if (!list_isempty(&rx->filtl)) {
+ warning("audio: skipping audio-filters due to"
+ " incompatible format (%s)\n",
+ aufmt_name(rx->dec_fmt));
}
if (!rx->aubuf)
@@ -771,6 +823,13 @@ static int aurx_stream_decode(struct aurx *rx, struct mbuf *mb)
if (rx->resamp.resample) {
size_t sampc_rs = AUDIO_SAMPSZ;
+ if (rx->dec_fmt != AUFMT_S16LE) {
+ warning("audio: skipping resampler due to"
+ " incompatible format (%s)\n",
+ aufmt_name(rx->dec_fmt));
+ return ENOTSUP;
+ }
+
err = auresamp(&rx->resamp,
rx->sampv_rs, &sampc_rs,
rx->sampv, sampc);
@@ -789,15 +848,17 @@ static int aurx_stream_decode(struct aurx *rx, struct mbuf *mb)
rx->stats.aubuf_overrun);
}
- if (rx->play_fmt == AUFMT_S16LE) {
- err = aubuf_write_samp(rx->aubuf, sampv, sampc);
+ if (rx->play_fmt == rx->dec_fmt) {
+
+ size_t num_bytes = sampc * aufmt_sample_size(rx->play_fmt);
+
+ err = aubuf_write(rx->aubuf, sampv, num_bytes);
if (err)
goto out;
}
else {
/* Convert from 16-bit to auplay format */
-
void *tmp_sampv;
size_t num_bytes = sampc * aufmt_sample_size(rx->play_fmt);
@@ -1057,6 +1118,9 @@ int audio_alloc(struct audio **ap, const struct stream_param *stream_prm,
tx->src_fmt = cfg->audio.src_fmt;
rx->play_fmt = cfg->audio.play_fmt;
+ tx->enc_fmt = cfg->audio.enc_fmt;
+ rx->dec_fmt = cfg->audio.dec_fmt;
+
err = stream_alloc(&a->strm, stream_prm, &cfg->avt, call, sdp_sess,
"audio", label,
mnat, mnat_sess, menc, menc_sess,
@@ -1101,8 +1165,11 @@ int audio_alloc(struct audio **ap, const struct stream_param *stream_prm,
}
tx->mb = mbuf_alloc(STREAM_PRESZ + 4096);
- tx->sampv = mem_zalloc(AUDIO_SAMPSZ * sizeof(int16_t), NULL);
- rx->sampv = mem_zalloc(AUDIO_SAMPSZ * sizeof(int16_t), NULL);
+ tx->sampv = mem_zalloc(AUDIO_SAMPSZ * aufmt_sample_size(tx->enc_fmt),
+ NULL);
+
+ rx->sampv = mem_zalloc(AUDIO_SAMPSZ * aufmt_sample_size(rx->dec_fmt),
+ NULL);
if (!tx->mb || !tx->sampv || !rx->sampv) {
err = ENOMEM;
goto out;
diff --git a/src/config.c b/src/config.c
index ce748d3..1d010e0 100644
--- a/src/config.c
+++ b/src/config.c
@@ -58,6 +58,8 @@ static struct config core_config = {
false,
AUFMT_S16LE,
AUFMT_S16LE,
+ AUFMT_S16LE,
+ AUFMT_S16LE,
},
#ifdef USE_VIDEO
@@ -270,6 +272,8 @@ int config_parse_conf(struct config *cfg, const struct conf *conf)
conf_get_aufmt(conf, "ausrc_format", &cfg->audio.src_fmt);
conf_get_aufmt(conf, "auplay_format", &cfg->audio.play_fmt);
+ conf_get_aufmt(conf, "auenc_format", &cfg->audio.enc_fmt);
+ conf_get_aufmt(conf, "audec_format", &cfg->audio.dec_fmt);
#ifdef USE_VIDEO
/* Video */
@@ -541,6 +545,8 @@ static int core_config_template(struct re_printf *pf, const struct config *cfg)
"audio_level\t\tno\n"
"ausrc_format\t\ts16\t\t# s16, float, ..\n"
"auplay_format\t\ts16\t\t# s16, float, ..\n"
+ "auenc_format\t\ts16\t\t# s16, float, ..\n"
+ "audec_format\t\ts16\t\t# s16, float, ..\n"
,
poll_method_name(poll_method_best()),
cfg->call.local_timeout,