diff options
-rw-r--r-- | modules/mpa/decode.c | 123 | ||||
-rw-r--r-- | modules/mpa/encode.c | 104 | ||||
-rw-r--r-- | modules/mpa/mpa.c | 111 | ||||
-rw-r--r-- | modules/mpa/mpa.h | 9 | ||||
-rw-r--r-- | modules/mpa/sdp.c | 19 |
5 files changed, 204 insertions, 162 deletions
diff --git a/modules/mpa/decode.c b/modules/mpa/decode.c index 65035e4..d62bd60 100644 --- a/modules/mpa/decode.c +++ b/modules/mpa/decode.c @@ -11,12 +11,12 @@ #include <string.h> #include "mpa.h" -#undef DEBUG - struct audec_state { mpg123_handle *dec; SpeexResamplerState *resampler; int channels; + int16_t intermediate_buffer[MPA_FRAMESIZE*2]; + int start; }; @@ -36,7 +36,7 @@ int mpa_decode_update(struct audec_state **adsp, const struct aucodec *ac, const char *fmtp) { struct audec_state *ads; - int mpaerr, err=0; + int result, err=0; if (!adsp || !ac || !ac->ch) return EINVAL; @@ -49,42 +49,47 @@ int mpa_decode_update(struct audec_state **adsp, const struct aucodec *ac, if (ads) mem_deref(ads); - + ads = mem_zalloc(sizeof(*ads), destructor); if (!ads) return ENOMEM; ads->channels = 0; ads->resampler = NULL; + ads->start = 0; - ads->dec = mpg123_new(NULL,&mpaerr); + ads->dec = mpg123_new(NULL,&result); if (!ads->dec) { - error("mpa: decoder create: %s\n", mpg123_plain_strerror(mpaerr)); + error("mpa: decoder create: %s\n", + mpg123_plain_strerror(result)); err = ENOMEM; goto out; } #ifdef DEBUG - mpaerr = mpg123_param(ads->dec, MPG123_VERBOSE, 4, 4.); + result = mpg123_param(ads->dec, MPG123_VERBOSE, 4, 4.); #else - mpaerr = mpg123_param(ads->dec, MPG123_VERBOSE, 0, 0.); + result = mpg123_param(ads->dec, MPG123_VERBOSE, 0, 0.); #endif - if(mpaerr != MPG123_OK) { - error("MPA libmpg123 param error %s", mpg123_plain_strerror(mpaerr)); + if (result != MPG123_OK) { + error("MPA libmpg123 param error %s", + mpg123_plain_strerror(result)); err = EINVAL; goto out; } - mpaerr = mpg123_format_all(ads->dec); - if(mpaerr != MPG123_OK) { - error("MPA libmpg123 format error %s", mpg123_plain_strerror(mpaerr)); + result = mpg123_format_all(ads->dec); + if (result != MPG123_OK) { + error("MPA libmpg123 format error %s", + mpg123_plain_strerror(result)); err = EINVAL; goto out; } - mpaerr = mpg123_open_feed(ads->dec); - if(mpaerr != MPG123_OK) { - error("MPA libmpg123 open feed error %s", mpg123_plain_strerror(mpaerr)); + result = mpg123_open_feed(ads->dec); + if (result != MPG123_OK) { + error("MPA libmpg123 open feed error %s", + mpg123_plain_strerror(result)); err = EINVAL; goto out; } @@ -103,74 +108,86 @@ int mpa_decode_update(struct audec_state **adsp, const struct aucodec *ac, int mpa_decode_frm(struct audec_state *ads, int16_t *sampv, size_t *sampc, const uint8_t *buf, size_t len) { - int mpaerr, channels, encoding, i; - long samplerate,res; + int result, channels, encoding, i; + long samplerate; size_t n; - uint32_t header; - static int16_t ds[2304]; - spx_uint32_t ds_len; - spx_uint32_t in_len; + spx_uint32_t intermediate_len; + spx_uint32_t out_len; - if (!ads || !sampv || !sampc || !buf) + if (!ads || !sampv || !sampc || !buf || len<=4) return EINVAL; - if(len<=4) - return EINVAL; - header = *(uint32_t*)buf; - if(header != 0) { - error("MPA header is not zero %08X\n", header); + if(*(uint32_t*)buf != 0) { + error("MPA header is not zero %08X, not supported yet\n", + *(uint32_t*)buf); return EPROTO; } - if(ads->resampler) { - in_len = *sampc; - ds_len = 2304*2; - mpaerr = mpg123_decode(ads->dec, buf+4, len-4, (unsigned char*)ds, sizeof(ds), &n); /* n counts bytes */ - ds_len = n / 4; /* ds_len counts samples per channel */ - res=speex_resampler_process_interleaved_int(ads->resampler, ds, &ds_len, sampv, &in_len); - if (res!=RESAMPLER_ERR_SUCCESS) { - error("mpa: upsample error: %s %d %d\n", strerror(res), in_len, *sampc/2); + if (ads->resampler) { + result = mpg123_decode(ads->dec, buf+4, len-4, + (unsigned char*)ads->intermediate_buffer, + sizeof(ads->intermediate_buffer), &n); + /* n counts bytes */ + intermediate_len = n / 2 / ads->channels; + /* intermediate_len counts samples per channel */ + out_len = *sampc; + result=speex_resampler_process_interleaved_int( + ads->resampler, ads->intermediate_buffer, + &intermediate_len, sampv, &out_len); + if (result!=RESAMPLER_ERR_SUCCESS) { + error("mpa: upsample error: %s %d %d\n", + strerror(result), out_len, *sampc/2); return EPROTO; } #ifdef DEBUG - debug("mpa decode %d %d %d %d\n",ds_len,*sampc,in_len,n); + info("mpa decode %d %d %d %d\n",intermediate_len,*sampc, + out_len,n); #endif - *sampc = in_len * 2; + *sampc = out_len * ads->channels; } else { - mpaerr = mpg123_decode(ads->dec, buf+4, len-4, (unsigned char*)sampv, *sampc*2, &n); + result = mpg123_decode(ads->dec, buf+4, len-4, + (unsigned char*)sampv, *sampc*2, &n); #ifdef DEBUG - debug("mpa decode %d %d\n",*sampc,n); + info("mpa decode %d %d\n",*sampc,n); #endif *sampc = n / 2; } - if(ads->channels==1) { - for(i=*sampc-1;i>=0;i--) + + if (ads->start<100) { /* mpg123 needs some to sync */ + ads->start++; + *sampc=0; + } + if (ads->channels==1) { + for (i=*sampc-1;i>=0;i--) sampv[i+i+1]=sampv[i+i]=sampv[i]; *sampc *= 2; } - if(mpaerr == MPG123_NEW_FORMAT) { + if (result == MPG123_NEW_FORMAT) { mpg123_getformat(ads->dec, &samplerate, &channels, &encoding); - info("MPA libmpg123 format change %d %d %04X\n",samplerate,channels,encoding); + info("MPA libmpg123 format change %d %d %04X\n",samplerate + ,channels,encoding); ads->channels = channels; - - if(samplerate != 48000) { - ads->resampler = speex_resampler_init(channels, samplerate, 48000, 3, &mpaerr); - if(mpaerr!=RESAMPLER_ERR_SUCCESS || ads->resampler==NULL) { - error("mpa: upsampler init failed %d\n",mpaerr); + ads->start = 0; + if (samplerate != 48000) { + ads->resampler = speex_resampler_init(channels, + samplerate, 48000, 3, &result); + if (result!=RESAMPLER_ERR_SUCCESS + || ads->resampler==NULL) { + error("mpa: upsampler failed %d\n",result); return EINVAL; } } else ads->resampler = NULL; - } - else if(mpaerr == MPG123_NEED_MORE) + else if (result == MPG123_NEED_MORE) return 0; - else if(mpaerr != MPG123_OK) { - error("MPA libmpg123 feed error %d %s", mpaerr, mpg123_plain_strerror(mpaerr)); + else if (result != MPG123_OK) { + error("MPA libmpg123 feed error %d %s", result, + mpg123_plain_strerror(result)); return EPROTO; } diff --git a/modules/mpa/encode.c b/modules/mpa/encode.c index f9a7476..6ed6493 100644 --- a/modules/mpa/encode.c +++ b/modules/mpa/encode.c @@ -11,12 +11,11 @@ #include <speex/speex_resampler.h> #include "mpa.h" -#undef DEBUG - -struct auenc_state { +struct auenc_state { twolame_options *enc; int channels; SpeexResamplerState *resampler; + int16_t intermediate_buffer[BARESIP_FRAMESIZE]; }; @@ -36,8 +35,7 @@ int mpa_encode_update(struct auenc_state **aesp, const struct aucodec *ac, { struct auenc_state *aes; struct mpa_param prm; - const struct aucodec *auc = aucodec_find("MPA", 90000, 1); - int mpares; + int result,err=0; (void)param; @@ -45,11 +43,11 @@ int mpa_encode_update(struct auenc_state **aesp, const struct aucodec *ac, return EINVAL; aes = *aesp; - if (aes) { + info("ever?"); mem_deref(aes); } - + aes = mem_zalloc(sizeof(*aes), destructor); aes->enc = twolame_init(); if (!aes->enc) { @@ -57,8 +55,7 @@ int mpa_encode_update(struct auenc_state **aesp, const struct aucodec *ac, mem_deref(aes); return ENOMEM; } - aes->channels = auc->ch; - *aesp = aes; + aes->channels = ac->ch; #ifdef DEBUG debug("mpa: encoder created %s\n",fmtp); #endif @@ -66,50 +63,62 @@ int mpa_encode_update(struct auenc_state **aesp, const struct aucodec *ac, prm.samplerate = 32000; prm.bitrate = 128000; prm.layer = 2; - prm.mode = STEREO; + prm.mode = SINGLE_CHANNEL; mpa_decode_fmtp(&prm, fmtp); - mpares = 0; + result = 0; #ifdef DEBUG - mpares |= twolame_set_verbosity(aes->enc, 5); + result |= twolame_set_verbosity(aes->enc, 5); #else - mpares |= twolame_set_verbosity(aes->enc, 0); + result |= twolame_set_verbosity(aes->enc, 0); #endif - mpares |= twolame_set_mode(aes->enc, prm.mode == SINGLE_CHANNEL ? TWOLAME_MONO : - prm.mode == DUAL_CHANNEL ? TWOLAME_DUAL_CHANNEL : - prm.mode == JOINT_STEREO ? TWOLAME_JOINT_STEREO : - prm.mode == STEREO ? TWOLAME_STEREO : TWOLAME_AUTO_MODE); - mpares |= twolame_set_version(aes->enc, prm.samplerate < 32000 ? TWOLAME_MPEG2 : TWOLAME_MPEG1); - mpares |= twolame_set_bitrate(aes->enc, prm.bitrate/1000); - mpares |= twolame_set_in_samplerate(aes->enc, prm.samplerate); - mpares |= twolame_set_out_samplerate(aes->enc, prm.samplerate); - mpares |= twolame_set_num_channels(aes->enc, 2); - if(mpares!=0) { + result |= twolame_set_mode(aes->enc, + prm.mode == SINGLE_CHANNEL ? TWOLAME_MONO : + prm.mode == DUAL_CHANNEL ? TWOLAME_DUAL_CHANNEL : + prm.mode == JOINT_STEREO ? TWOLAME_JOINT_STEREO : + prm.mode == STEREO ? TWOLAME_STEREO : TWOLAME_AUTO_MODE); + result |= twolame_set_version(aes->enc, + prm.samplerate < 32000 ? TWOLAME_MPEG2 : TWOLAME_MPEG1); + result |= twolame_set_bitrate(aes->enc, prm.bitrate/1000); + result |= twolame_set_in_samplerate(aes->enc, prm.samplerate); + result |= twolame_set_out_samplerate(aes->enc, prm.samplerate); + result |= twolame_set_num_channels(aes->enc, 2); + if (result!=0) { error("mpa: encoder set failed\n"); - return EINVAL; + err=EINVAL; + goto out; } - mpares = twolame_init_params(aes->enc); - if(mpares!=0) { + result = twolame_init_params(aes->enc); + if (result!=0) { error("mpa: encoder init params failed\n"); - return EINVAL; + err=EINVAL; + goto out; } twolame_print_config(aes->enc); - - if(prm.samplerate != 48000) { - aes->resampler = speex_resampler_init(2, 48000, prm.samplerate, 3, &mpares); - if(mpares!=RESAMPLER_ERR_SUCCESS) { - error("mpa: resampler init failed %d\n",mpares); - return EINVAL; + if (prm.samplerate != 48000) { + aes->resampler = speex_resampler_init(2, 48000, + prm.samplerate, 3, &result); + if (result!=RESAMPLER_ERR_SUCCESS) { + error("mpa: resampler init failed %d\n",result); + err=EINVAL; + goto out; } } else aes->resampler = NULL; - return 0; + +out: + if (err) + mem_deref(aes); + else + *aesp = aes; + + return err; } @@ -117,36 +126,41 @@ int mpa_encode_frm(struct auenc_state *aes, uint8_t *buf, size_t *len, const int16_t *sampv, size_t sampc) { int n; - spx_uint32_t ds_len,in_len; - static int16_t ds[1920]; + spx_uint32_t intermediate_len,in_len; if (!aes || !buf || !len || !sampv) return EINVAL; - if(aes->resampler) { + if (aes->resampler) { in_len = sampc/2; - ds_len = 1920; - n=speex_resampler_process_interleaved_int(aes->resampler, sampv, &in_len, ds, &ds_len); + intermediate_len = sizeof(aes->intermediate_buffer) + / sizeof(aes->intermediate_buffer[0]); + n=speex_resampler_process_interleaved_int(aes->resampler, + sampv, &in_len, aes->intermediate_buffer, + &intermediate_len); if (n!=RESAMPLER_ERR_SUCCESS || in_len != sampc/2) { - warning("mpa: downsample error: %s %d %d\n", strerror(n), in_len, sampc/2); + warning("mpa: downsample error: %s %d %d\n", + strerror(n), in_len, sampc/2); return EPROTO; } - n = twolame_encode_buffer_interleaved(aes->enc, ds, ds_len, + n = twolame_encode_buffer_interleaved(aes->enc, + aes->intermediate_buffer, intermediate_len, buf+4, (*len)-4); #ifdef DEBUG - debug("mpa encode %d %d %d %d %d\n",ds_len,sampc,aes->channels,*len,n); + debug("mpa encode %d %d %d %d %d\n",intermediate_len,sampc, + aes->channels,*len,n); #endif } else - n = twolame_encode_buffer_interleaved(aes->enc, sampv, (int)(sampc/2), - buf+4, (*len)-4); + n = twolame_encode_buffer_interleaved(aes->enc, sampv, + (int)(sampc/2), buf+4, (*len)-4); if (n < 0) { error("mpa: encode error: %s\n", strerror((int)n)); return EPROTO; } - if(n > 0) { + if (n > 0) { *(uint32_t*)buf = 0; *len = n+4; } diff --git a/modules/mpa/mpa.c b/modules/mpa/mpa.c index 04a6a8c..88ebfbe 100644 --- a/modules/mpa/mpa.c +++ b/modules/mpa/mpa.c @@ -16,7 +16,7 @@ * * The mpa audio codec * - * Supported version: + * Supported version: * libmpg123 1.16.0 or later * libtwolame 0.3.13 or later * @@ -36,35 +36,35 @@ Required parameters: None Optional parameters: - layer: which layer of MPEG audio encoding; permissible values - are 1, 2, 3. + layer: which layer of MPEG audio encoding; permissible values + are 1, 2, 3. - samplerate: the rate at which audio is sampled. MPEG-1 audio - supports sampling rates of 32, 44.1, and 48 kHz; MPEG-2 - supports sampling rates of 16, 22.05 and 24 kHz. This parameter - is separate from the RTP timestamp clock rate which is always - 90000 Hz for MPA. + samplerate: the rate at which audio is sampled. MPEG-1 audio + supports sampling rates of 32, 44.1, and 48 kHz; MPEG-2 + supports sampling rates of 16, 22.05 and 24 kHz. This parameter + is separate from the RTP timestamp clock rate which is always + 90000 Hz for MPA. - mode: permissible values are "stereo", "joint_stereo", - "single_channel", "dual_channel". The "channels" parameter - does not apply to MPA. It is undefined to put a number of - channels in the SDP rtpmap attribute for MPA. + mode: permissible values are "stereo", "joint_stereo", + "single_channel", "dual_channel". The "channels" parameter + does not apply to MPA. It is undefined to put a number of + channels in the SDP rtpmap attribute for MPA. - bitrate: the data rate for the audio bit stream. + bitrate: the data rate for the audio bit stream. - ptime: RECOMMENDED duration of each packet in milliseconds. + ptime: RECOMMENDED duration of each packet in milliseconds. - maxptime: maximum duration of each packet in milliseconds. + maxptime: maximum duration of each packet in milliseconds. - Parameters which are omitted are left to the encoder to choose - based on the session bandwidth, configuration information, or - other constraints. The selected layer as well as the sampling - rate and mode are indicated in the payload so receivers can - process the data without these parameters being specified - externally. + Parameters which are omitted are left to the encoder to choose + based on the session bandwidth, configuration information, or + other constraints. The selected layer as well as the sampling + rate and mode are indicated in the payload so receivers can + process the data without these parameters being specified + externally. Encoding considerations: - This type is only defined for transfer via RTP [RFC 3550]. + This type is only defined for transfer via RTP [RFC 3550]. Security considerations: See Section 5 of RFC 3555 @@ -73,16 +73,17 @@ Published specification: RFC 3551 Applications which use this media type: - Audio and video streaming and conferencing tools. + Audio and video streaming and conferencing tools. */ static struct aucodec mpa = { - .pt = NULL, + .pt = NULL, /* for the time being, to cope +with AVT AC1 interop problems, we do not use "14" here */ .name = "MPA", .srate = 90000, - .ch = 1, + .ch = 1, .fmtp = "", .encupdh = mpa_encode_update, .ench = mpa_encode_frm, @@ -100,30 +101,31 @@ static int module_init(void) int res; /** generate fmtp string based on config file */ - + strcpy(mode,mpa.fmtp); if (0 == conf_get_u32(conf, "mpa_bitrate", &value)) { - if(value<8000 || value>384000) { - error("MPA bitrate between 8000 and 384000 are allowed."); + if (value<8000 || value>384000) { + error("MPA bitrate between 8000 and " + "384000 are allowed."); return -1; } - (void)re_snprintf(fmtp+strlen(fmtp), sizeof(fmtp)-strlen(fmtp), - "; bitrate=%d", - value); + (void)re_snprintf(fmtp+strlen(fmtp), + sizeof(fmtp)-strlen(fmtp), + "; bitrate=%d", value); } if (0 == conf_get_u32(conf, "mpa_layer", &value)) { - if(value<1 || value>4) { + if (value<1 || value>4) { error("MPA layer 1, 2 or 3 are allowed."); return -1; } - (void)re_snprintf(fmtp+strlen(fmtp), sizeof(fmtp)-strlen(fmtp), - "; layer=%d", - value); + (void)re_snprintf(fmtp+strlen(fmtp), + sizeof(fmtp)-strlen(fmtp), + "; layer=%d", value); } if (0 == conf_get_u32(conf, "mpa_samplerate", &value)) { - switch(value) { + switch (value) { case 32000: case 44100: case 48000: @@ -132,40 +134,45 @@ static int module_init(void) case 24000: break; default: - error("MPA samplerates of 16, 22.05, 24, 32, 44.1, and 48 kHz are allowed."); + error("MPA samplerates of 16, 22.05, 24, 32, " + "44.1, and 48 kHz are allowed."); return -1; } - (void)re_snprintf(fmtp+strlen(fmtp), sizeof(fmtp)-strlen(fmtp), - "; samplerate=%d", - value); + (void)re_snprintf(fmtp+strlen(fmtp), + sizeof(fmtp)-strlen(fmtp), + "; samplerate=%d", value); } if (0 == conf_get_str(conf, "mpa_mode", mode, sizeof(mode))) { char *p = mode; - while(*p) { + while (*p) { *p = tolower(*p); - p++; + ++p; } - - if(strcmp(mode,"stereo") && strcmp(mode,"joint_stereo") && strcmp(mode,"single_channel") && strcmp(mode,"dual_channel")) { - error("MPA mode: Permissible values are stereo, joint_stereo, single_channel, dual_channel"); + + if (strcmp(mode,"stereo") + && strcmp(mode,"joint_stereo") + && strcmp(mode,"single_channel") + && strcmp(mode,"dual_channel")) { + error("MPA mode: Permissible values are stereo, " + "joint_stereo, single_channel, dual_channel"); return -1; } - - (void)re_snprintf(fmtp+strlen(fmtp), sizeof(fmtp)-strlen(fmtp), - "; mode=%s", - mode); + (void)re_snprintf(fmtp+strlen(fmtp), + sizeof(fmtp)-strlen(fmtp), + "; mode=%s", mode); } - if(fmtp[0]==';' && fmtp[1]==' ') + if (fmtp[0]==';' && fmtp[1]==' ') mpa.fmtp = fmtp+2; else mpa.fmtp = fmtp; /* init decoder library */ res = mpg123_init(); - if(res != MPG123_OK) { - error("MPA libmpg123 init error %s", mpg123_plain_strerror(res)); + if (res != MPG123_OK) { + error("MPA libmpg123 init error %s", + mpg123_plain_strerror(res)); return -1; } diff --git a/modules/mpa/mpa.h b/modules/mpa/mpa.h index f9c2934..35055b6 100644 --- a/modules/mpa/mpa.h +++ b/modules/mpa/mpa.h @@ -4,12 +4,17 @@ * Copyright (C) 2016 Symonics GmbH */ +#define MPA_FRAMESIZE 1152 +#define BARESIP_FRAMESIZE (48000/50*2) + +#undef DEBUG struct mpa_param { unsigned samplerate; unsigned bitrate; unsigned layer; - enum { AUTO=0, STEREO, JOINT_STEREO, SINGLE_CHANNEL, DUAL_CHANNEL } mode; + enum { AUTO=0, STEREO, JOINT_STEREO, SINGLE_CHANNEL, DUAL_CHANNEL } + mode; }; @@ -25,8 +30,6 @@ int mpa_decode_update(struct audec_state **adsp, const struct aucodec *ac, const char *fmtp); int mpa_decode_frm(struct audec_state *ads, int16_t *sampv, size_t *sampc, const uint8_t *buf, size_t len); -int mpa_decode_pkloss(struct audec_state *st, int16_t *sampv, size_t *sampc); - /* SDP */ void mpa_decode_fmtp(struct mpa_param *prm, const char *fmtp); diff --git a/modules/mpa/sdp.c b/modules/mpa/sdp.c index ed0c2fd..363b72c 100644 --- a/modules/mpa/sdp.c +++ b/modules/mpa/sdp.c @@ -10,7 +10,7 @@ #include "mpa.h" -static void assign_if(uint32_t *v, const struct pl *pl, +static void assign_if (uint32_t *v, const struct pl *pl, uint32_t min, uint32_t max) { const uint32_t val = pl_u32(pl); @@ -32,23 +32,24 @@ void mpa_decode_fmtp(struct mpa_param *prm, const char *fmtp) pl_set_str(&pl, fmtp); if (fmt_param_get(&pl, "bitrate", &val)) - assign_if(&prm->bitrate, &val, 8000, 384000); + assign_if (&prm->bitrate, &val, 8000, 384000); if (fmt_param_get(&pl, "samplerate", &val)) - assign_if(&prm->samplerate, &val, 16000, 48000); + assign_if (&prm->samplerate, &val, 16000, 48000); if (fmt_param_get(&pl, "layer", &val)) - assign_if(&prm->layer, &val, 1, 3); + assign_if (&prm->layer, &val, 1, 3); if (fmt_param_get(&pl, "mode", &val)) { - if(!strncmp("stereo",pl.p,pl.l)) + if (!strncmp("stereo",pl.p,pl.l)) prm->mode = STEREO; - else if(!strncmp("joint_stereo",pl.p,pl.l)) + else if (!strncmp("joint_stereo",pl.p,pl.l)) prm->mode = JOINT_STEREO; - else if(!strncmp("single_channel",pl.p,pl.l)) + else if (!strncmp("single_channel",pl.p,pl.l)) prm->mode = SINGLE_CHANNEL; - else if(!strncmp("dual_channel",pl.p,pl.l)) + else if (!strncmp("dual_channel",pl.p,pl.l)) prm->mode = DUAL_CHANNEL; - } + } } + |