Module: sems Branch: master Commit: 53e5b576b5142ee9e232dfd5300db5c478e8fb22 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sems/?a=commit;h=53e5b576b5142ee9e232dfd5300db5c478e8fb22
Author: Raphael Coeffic <[email protected]> Committer: Raphael Coeffic <[email protected]> Date: Tue Mar 6 11:22:23 2012 +0100 silk: added support for SILK codec (8-24kHz). --- .gitignore | 3 +- core/amci/codecs.h | 5 + core/plug-in/silk/Makefile | 19 +++ core/plug-in/silk/silk.c | 281 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 307 insertions(+), 1 deletions(-) diff --git a/.gitignore b/.gitignore index d8bca16..81004d1 100644 --- a/.gitignore +++ b/.gitignore @@ -19,4 +19,5 @@ sems-logfile-callextract cscope.out cscope.files semantic.cache -apps/rtmp/flash_phone/*.swf \ No newline at end of file +apps/rtmp/flash_phone/*.swf +core/plug-in/silk/SILK_SDK_* \ No newline at end of file diff --git a/core/amci/codecs.h b/core/amci/codecs.h index b4720bf..627cf01 100644 --- a/core/amci/codecs.h +++ b/core/amci/codecs.h @@ -78,4 +78,9 @@ #define CODEC_SPEEX_WB 26 +#define CODEC_SILK_NB 27 +#define CODEC_SILK_MB 28 +#define CODEC_SILK_WB 29 +#define CODEC_SILK_UB 30 + #endif diff --git a/core/plug-in/silk/Makefile b/core/plug-in/silk/Makefile new file mode 100644 index 0000000..7a1fec9 --- /dev/null +++ b/core/plug-in/silk/Makefile @@ -0,0 +1,19 @@ +plug_in_name = silk +COREPATH =../.. + +SILK_DIR=SILK_SDK_SRC_v1.0.8/SILK_SDK_SRC_FIX_v1.0.8 +SILK_INC=$(SILK_DIR)/interface +SILK_LIB = $(SILK_DIR)/libSKP_SILK_SDK.a + +module_cflags = -I $(SILK_INC) +module_extra_objs = $(SILK_LIB) +extra_clean = clean_silk + +include ../Makefile.audio_module + +$(SILK_LIB): + $(MAKE) -C $(SILK_DIR) lib + +.PHONY: clean_silk +clean_silk: + $(MAKE) -C $(SILK_DIR) clean diff --git a/core/plug-in/silk/silk.c b/core/plug-in/silk/silk.c new file mode 100644 index 0000000..7bfd3ce --- /dev/null +++ b/core/plug-in/silk/silk.c @@ -0,0 +1,281 @@ +/* + This is a simple interface to the SILK SDK for SEMS. + Copyright (C) 2012 Raphael Coeffic + + This code is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation. + + This code is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "amci.h" +#include "codecs.h" +#include "SKP_Silk_SDK_API.h" +#include "../../log.h" + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> + +// TODO: +// - use integrated PLC (without FEC) +// - set 'useinbandfec=0' in SDP + + +int Pcm16_2_SILK( unsigned char* out_buf, unsigned char* in_buf, unsigned int size, + unsigned int channels, unsigned int rate, long h_codec ); +int SILK_2_Pcm16( unsigned char* out_buf, unsigned char* in_buf, unsigned int size, + unsigned int channels, unsigned int rate, long h_codec ); + +long SILK_NB_create(const char* format_parameters, amci_codec_fmt_info_t* format_description); +long SILK_MB_create(const char* format_parameters, amci_codec_fmt_info_t* format_description); +long SILK_WB_create(const char* format_parameters, amci_codec_fmt_info_t* format_description); +long SILK_UB_create(const char* format_parameters, amci_codec_fmt_info_t* format_description); +void SILK_destroy(long handle); + +static unsigned int SILK_bytes2samples(long, unsigned int); +static unsigned int SILK_samples2bytes(long, unsigned int); + +BEGIN_EXPORTS("silk", AMCI_NO_MODULEINIT, AMCI_NO_MODULEDESTROY) + +BEGIN_CODECS +#if SYSTEM_SAMPLECLOCK_RATE >=24000 +CODEC(CODEC_SILK_UB, Pcm16_2_SILK, SILK_2_Pcm16, AMCI_NO_CODEC_PLC, + SILK_UB_create, SILK_destroy, + SILK_bytes2samples, SILK_samples2bytes) +#endif +#if SYSTEM_SAMPLECLOCK_RATE >=16000 +CODEC(CODEC_SILK_WB, Pcm16_2_SILK, SILK_2_Pcm16, AMCI_NO_CODEC_PLC, + SILK_WB_create, SILK_destroy, + SILK_bytes2samples, SILK_samples2bytes) +#endif +#if SYSTEM_SAMPLECLOCK_RATE >=12000 +CODEC(CODEC_SILK_MB, Pcm16_2_SILK, SILK_2_Pcm16, AMCI_NO_CODEC_PLC, + SILK_MB_create, SILK_destroy, + SILK_bytes2samples, SILK_samples2bytes) +#endif +CODEC(CODEC_SILK_NB, Pcm16_2_SILK, SILK_2_Pcm16, AMCI_NO_CODEC_PLC, + SILK_NB_create, SILK_destroy, + SILK_bytes2samples, SILK_samples2bytes) +END_CODECS + +BEGIN_PAYLOADS +#if SYSTEM_SAMPLECLOCK_RATE >=24000 +PAYLOAD(-1, "SILK", 24000, 24000, 1, CODEC_SILK_UB, AMCI_PT_AUDIO_FRAME) +#endif +#if SYSTEM_SAMPLECLOCK_RATE >=16000 +PAYLOAD(-1, "SILK", 16000, 16000, 1, CODEC_SILK_WB, AMCI_PT_AUDIO_FRAME) +#endif +#if SYSTEM_SAMPLECLOCK_RATE >=12000 +PAYLOAD(-1, "SILK", 12000, 12000, 1, CODEC_SILK_MB, AMCI_PT_AUDIO_FRAME) +#endif +PAYLOAD(-1, "SILK", 8000, 8000, 1, CODEC_SILK_NB, AMCI_PT_AUDIO_FRAME) +END_PAYLOADS + +BEGIN_FILE_FORMATS +END_FILE_FORMATS + +END_EXPORTS + +typedef struct +{ + SKP_SILK_SDK_EncControlStruct encControl; + void* psEnc; + + SKP_SILK_SDK_DecControlStruct decControl; + void* psDec; +} SILK_state; + + +static int create_SILK_encoder(SILK_state* st, + unsigned int rtp_Hz, + unsigned int avg_bit_rate) +{ + SKP_int32 ret,encSizeBytes; + + /* Create Encoder */ + ret = SKP_Silk_SDK_Get_Encoder_Size( &encSizeBytes ); + if( ret ) { + ERROR( "SKP_Silk_create_encoder returned %d", ret ); + return ret; + } + + st->psEnc = malloc( encSizeBytes ); + if(st->psEnc == NULL) { + ERROR( "could not allocate SILK encoder state" ); + return -1; + } + + /* Reset Encoder */ + ret = SKP_Silk_SDK_InitEncoder( st->psEnc, &st->encControl ); + if( ret ) { + ERROR( "SKP_Silk_SDK_InitEncoder returned %d", ret ); + return ret; + } + + /* Set Encoder parameters */ + st->encControl.API_sampleRate = rtp_Hz; + st->encControl.maxInternalSampleRate = rtp_Hz; + st->encControl.packetSize = ( 20 * rtp_Hz ) / 1000; + st->encControl.packetLossPercentage = 0; + st->encControl.useInBandFEC = 0; + st->encControl.useDTX = 0; + st->encControl.complexity = 2; + st->encControl.bitRate = avg_bit_rate; + + return 0; +} + +static int create_SILK_decoder(SILK_state* st, + unsigned int rtp_Hz) +{ + SKP_int32 ret, decSizeBytes; + + /* Set the samplingrate that is requested for the output */ + st->decControl.API_sampleRate = rtp_Hz; + + /* Initialize to one frame per packet, for proper concealment before first packet arrives */ + st->decControl.framesPerPacket = 1; + + /* Create decoder */ + ret = SKP_Silk_SDK_Get_Decoder_Size( &decSizeBytes ); + if( ret ) { + ERROR( "SKP_Silk_SDK_Get_Decoder_Size returned %d", ret ); + return ret; + } + + st->psDec = malloc( decSizeBytes ); + if(st->psDec == NULL) { + ERROR( "could not allocate SILK decoder state" ); + return -1; + } + + /* Reset decoder */ + ret = SKP_Silk_SDK_InitDecoder( st->psDec ); + if( ret ) { + ERROR( "SKP_Silk_InitDecoder returned %d", ret ); + return ret; + } + + return 0; +} + +static long SILK_create(unsigned int rtp_Hz, + unsigned int avg_bit_rate, + const char* format_parameters, + amci_codec_fmt_info_t* format_description) +{ + SILK_state* st = malloc(sizeof(SILK_state)); + if(st == NULL) { + ERROR("could not allocate SILK state\n"); + return 0; + } + + if(create_SILK_encoder(st,rtp_Hz,avg_bit_rate)) + goto error; + + if(create_SILK_decoder(st,rtp_Hz)) + goto error; + + return (long)st; + + error: + if(st->psEnc) free(st->psEnc); + if(st->psDec) free(st->psDec); + free(st); + + return 0; +} + +long SILK_NB_create(const char* format_parameters, amci_codec_fmt_info_t* format_description) +{ + return SILK_create(8000,20000,format_parameters,format_description); +} + +long SILK_MB_create(const char* format_parameters, amci_codec_fmt_info_t* format_description) +{ + return SILK_create(12000,25000,format_parameters,format_description); +} + +long SILK_WB_create(const char* format_parameters, amci_codec_fmt_info_t* format_description) +{ + return SILK_create(16000,30000,format_parameters,format_description); +} + +long SILK_UB_create(const char* format_parameters, amci_codec_fmt_info_t* format_description) +{ + return SILK_create(24000,40000,format_parameters,format_description); +} + +void SILK_destroy(long handle) +{ + SILK_state* st = (SILK_state*)handle; + if(st->psEnc) free(st->psEnc); + if(st->psDec) free(st->psDec); + free(st); +} + +static unsigned int SILK_bytes2samples(long h_codec, unsigned int num_bytes) { + return num_bytes / 2; +} + +static unsigned int SILK_samples2bytes(long h_codec, unsigned int num_samples) { + return num_samples * 2; +} + +int Pcm16_2_SILK( unsigned char* out_buf, unsigned char* in_buf, unsigned int size, + unsigned int channels, unsigned int rate, long h_codec ) +{ + SILK_state* st = (SILK_state*)h_codec; + SKP_int16 ret; + + /* max payload size */ + SKP_int16 nBytes = AUDIO_BUFFER_SIZE; + + /* Silk Encoder */ + ret = SKP_Silk_SDK_Encode( st->psEnc, &st->encControl, (SKP_int16*)in_buf, + (SKP_int16)size/2, out_buf, &nBytes ); + if( ret ) { + ERROR( "SKP_Silk_Encode returned %d (size=%u)\n", ret, size ); + return -1; + } + + return nBytes; +} + +int SILK_2_Pcm16( unsigned char* out_buf, unsigned char* in_buf, unsigned int size, + unsigned int channels, unsigned int rate, long h_codec ) +{ + SILK_state* st = (SILK_state*)h_codec; + SKP_int16 ret, len, *outPtr = (SKP_int16*)out_buf; + + do { + /* Decode 20 ms */ + ret = SKP_Silk_SDK_Decode( st->psDec, &st->decControl, 0/*lost*/, + in_buf, size, outPtr, &len ); + if( ret ) { + ERROR( "SKP_Silk_SDK_Decode returned %d\n", ret ); + return ret; + } + + outPtr += len; + + if( (unsigned char*)outPtr - out_buf > AUDIO_BUFFER_SIZE ) { + /* Oooops!!! buffer overflow !!! */ + ERROR("Buffer overflow (size=%li)\n", + (unsigned char*)outPtr - out_buf); + return -1; // TODO + } + /* Until last 20 ms frame of packet has been decoded */ + } while( st->decControl.moreInternalDecoderFrames ); + + return (unsigned char*)outPtr - out_buf; +} _______________________________________________ Semsdev mailing list [email protected] http://lists.iptel.org/mailman/listinfo/semsdev
