From d08a8309e0f1a532ae83c719df728aae010a5d39 Mon Sep 17 00:00:00 2001 From: Brian West <brian@freeswitch.org> Date: Tue, 9 Mar 2010 03:29:25 +0000 Subject: [PATCH] commit contribution from a community member git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@16950 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- src/mod/codecs/mod_silk/mod_silk.c | 297 ++++++++++++++++++----------- 1 file changed, 184 insertions(+), 113 deletions(-) diff --git a/src/mod/codecs/mod_silk/mod_silk.c b/src/mod/codecs/mod_silk/mod_silk.c index ee69639ebf..7b5304d274 100644 --- a/src/mod/codecs/mod_silk/mod_silk.c +++ b/src/mod/codecs/mod_silk/mod_silk.c @@ -1,6 +1,6 @@ /* * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org> + * Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org> * * Version: MPL 1.1 * @@ -36,7 +36,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_silk_load); SWITCH_MODULE_DEFINITION(mod_silk, mod_silk_load, NULL, NULL); -#define MAX_BYTES_PER_FRAME 250 +#define MAX_BYTES_PER_FRAME 250 #define MAX_INPUT_FRAMES 5 #define MAX_LBRR_DELAY 2 #define MAX_FRAME_LENGTH 480 @@ -48,20 +48,21 @@ struct silk_context { void *dec_state; }; -static switch_status_t switch_silk_init(switch_codec_t *codec, switch_codec_flag_t freeswitch_flags, const switch_codec_settings_t *codec_settings) +static switch_status_t switch_silk_init(switch_codec_t *codec, + switch_codec_flag_t freeswitch_flags, + const switch_codec_settings_t *codec_settings) { struct silk_context *context = NULL; - SKP_int useinbandfec = 0, usedtx = 0, maxaveragebitrate = 0; + SKP_int useinbandfec = 0, usedtx = 0, maxaveragebitrate = 0, plpct =0; SKP_int32 encSizeBytes; SKP_int32 decSizeBytes; int encoding = (freeswitch_flags & SWITCH_CODEC_FLAG_ENCODE); int decoding = (freeswitch_flags & SWITCH_CODEC_FLAG_DECODE); - if (!(encoding || decoding) - || (!(context = switch_core_alloc(codec->memory_pool, sizeof(*context))))) { + if (!(encoding || decoding) || (!(context = switch_core_alloc(codec->memory_pool, sizeof(*context))))) { return SWITCH_STATUS_FALSE; } - + if (codec->fmtp_in) { int x, argc; char *argv[10]; @@ -78,6 +79,7 @@ static switch_status_t switch_silk_init(switch_codec_t *codec, switch_codec_flag if (!strcasecmp(data, "useinbandfec")) { if (switch_true(arg)) { useinbandfec = 1; + plpct = 10;// 10% for now } } if (!strcasecmp(data, "usedtx")) { @@ -87,70 +89,70 @@ static switch_status_t switch_silk_init(switch_codec_t *codec, switch_codec_flag } if (!strcasecmp(data, "maxaveragebitrate")) { maxaveragebitrate = atoi(arg); - switch (codec->implementation->actual_samples_per_second) { + switch(codec->implementation->actual_samples_per_second) { case 8000: { - if (maxaveragebitrate < 6000 || maxaveragebitrate > 20000) { + if(maxaveragebitrate < 6000 || maxaveragebitrate > 20000) { maxaveragebitrate = 20000; } break; } case 12000: { - if (maxaveragebitrate < 7000 || maxaveragebitrate > 25000) { + if(maxaveragebitrate < 7000 || maxaveragebitrate > 25000) { maxaveragebitrate = 25000; } break; } case 16000: { - if (maxaveragebitrate < 8000 || maxaveragebitrate > 30000) { + if(maxaveragebitrate < 8000 || maxaveragebitrate > 30000) { maxaveragebitrate = 30000; } break; } case 24000: { - if (maxaveragebitrate < 12000 || maxaveragebitrate > 40000) { + if(maxaveragebitrate < 12000 || maxaveragebitrate > 40000) { maxaveragebitrate = 40000; } break; } - + default: /* this should never happen but 20000 is common among all rates */ maxaveragebitrate = 20000; break; } - + } } } } - - codec->fmtp_out = - switch_core_sprintf(codec->memory_pool, - "useinbandfec=%s; usedtx=%s; maxaveragebitrate=%d", - useinbandfec ? "true" : "false", - usedtx ? "true" : "false", maxaveragebitrate ? maxaveragebitrate : codec->implementation->bits_per_second); + + codec->fmtp_out = switch_core_sprintf(codec->memory_pool, "useinbandfec=%s; usedtx=%s; maxaveragebitrate=%d", + useinbandfec ? "true" : "false", + usedtx ? "true" : "false", + maxaveragebitrate ? maxaveragebitrate : codec->implementation->bits_per_second); if (encoding) { if (SKP_Silk_SDK_Get_Encoder_Size(&encSizeBytes)) { return SWITCH_STATUS_FALSE; } - + context->enc_state = switch_core_alloc(codec->memory_pool, encSizeBytes); if (SKP_Silk_SDK_InitEncoder(context->enc_state, &context->encoder_object)) { return SWITCH_STATUS_FALSE; } - + context->encoder_object.sampleRate = codec->implementation->actual_samples_per_second; context->encoder_object.packetSize = codec->implementation->samples_per_packet; context->encoder_object.useInBandFec = useinbandfec; context->encoder_object.complexity = 2; context->encoder_object.bitRate = maxaveragebitrate ? maxaveragebitrate : codec->implementation->bits_per_second; context->encoder_object.useDtx = usedtx; + context->encoder_object.packetLossPercentage = plpct;; } if (decoding) { @@ -172,56 +174,121 @@ static switch_status_t switch_silk_init(switch_codec_t *codec, switch_codec_flag static switch_status_t switch_silk_destroy(switch_codec_t *codec) { - codec->private_info = NULL; + codec->private_info = NULL; return SWITCH_STATUS_SUCCESS; } +void printSilkError(SKP_int16 ret){ + char * message; + switch (ret) { + case SKP_SILK_NO_ERROR: message = "No errors"; + break; + case SKP_SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES: + message = "Input length is not multiplum of 10 ms, or length is longer than the packet length"; + break; + case SKP_SILK_ENC_FS_NOT_SUPPORTED: + message = "Sampling frequency not 8000 , 12000, 16000 or 24000 Hertz"; + break; + case SKP_SILK_ENC_PACKET_SIZE_NOT_SUPPORTED: + message ="Packet size not 20, 40 , 60 , 80 or 100 ms "; + break; + case SKP_SILK_ENC_PAYLOAD_BUF_TOO_SHORT: + message = "Allocated payload buffer too short"; + break; + case SKP_SILK_ENC_WRONG_LOSS_RATE: + message = " Loss rate not between 0 and 100 % "; + break; + case SKP_SILK_ENC_WRONG_COMPLEXITY_SETTING: + message = "Complexity setting not valid, use 0 ,1 or 2"; + break; + case SKP_SILK_ENC_WRONG_INBAND_FEC_SETTING: + message = "Inband FEC setting not valid, use 0 or 1 "; + break; + case SKP_SILK_ENC_WRONG_DTX_SETTING: + message = "DTX setting not valid, use 0 or 1"; + break; + case SKP_SILK_ENC_INTERNAL_ERROR: + message = "Internal Encoder Error "; + break; + case SKP_SILK_DEC_WRONG_SAMPLING_FREQUENCY: + message = "Output sampling frequency lower than internal decoded sampling frequency"; + break; + case SKP_SILK_DEC_PAYLOAD_TOO_LARGE: + message = "Payload size exceeded the maximum allowed 1024 bytes"; + break; + case SKP_SILK_DEC_PAYLOAD_ERROR : + message = "Payload has bit errors"; + break; + default: + message = "unknown"; + break; + } + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR," Silk Error message= %s\n",message); +} -static switch_status_t -switch_silk_encode(switch_codec_t *codec, - switch_codec_t *other_codec, - void *decoded_data, - uint32_t decoded_data_len, - uint32_t decoded_rate, void *encoded_data, uint32_t *encoded_data_len, uint32_t *encoded_rate, unsigned int *flag) +static switch_status_t switch_silk_encode(switch_codec_t *codec, + switch_codec_t *other_codec, + void *decoded_data, + uint32_t decoded_data_len, + uint32_t decoded_rate, void *encoded_data, uint32_t *encoded_data_len, uint32_t *encoded_rate, unsigned int *flag) { struct silk_context *context = codec->private_info; SKP_int16 ret; - SKP_int16 nBytes = MAX_BYTES_PER_FRAME * MAX_INPUT_FRAMES; - - ret = SKP_Silk_SDK_Encode(context->enc_state, &context->encoder_object, decoded_data, (SKP_int16) decoded_data_len / 2, encoded_data, &nBytes); - - if (ret) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SKP_Silk_Encode returned %d!\n", ret); + SKP_int16 pktsz = context->encoder_object.packetSize; + SKP_int16 nBytes = MAX_BYTES_PER_FRAME * MAX_INPUT_FRAMES; + SKP_int16 *lindata = (SKP_int16 *)decoded_data; + SKP_int16 samples = decoded_data_len /sizeof(SKP_int16); + *encoded_data_len = 0; + while (samples >= pktsz){ + ret = SKP_Silk_SDK_Encode(context->enc_state, + &context->encoder_object, + lindata, + pktsz, + encoded_data, + &nBytes); + + if (ret) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SKP_Silk_Encode returned %d!\n", ret); + printSilkError(ret); + } + *encoded_data_len += nBytes; + samples-=pktsz; + lindata+= pktsz; + } + if (samples != 0){ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "switch_silk_encode dumping partial frame %d!\n", samples); } - - *encoded_data_len = nBytes; return SWITCH_STATUS_SUCCESS; } -static switch_status_t -switch_silk_decode(switch_codec_t *codec, - switch_codec_t *other_codec, - void *encoded_data, - uint32_t encoded_data_len, - uint32_t encoded_rate, void *decoded_data, uint32_t *decoded_data_len, uint32_t *decoded_rate, unsigned int *flag) +static switch_status_t switch_silk_decode(switch_codec_t *codec, + switch_codec_t *other_codec, + void *encoded_data, + uint32_t encoded_data_len, + uint32_t encoded_rate, void *decoded_data, uint32_t *decoded_data_len, uint32_t *decoded_rate, unsigned int *flag) { struct silk_context *context = codec->private_info; - SKP_int16 ret, len; + SKP_int16 ret, len; int16_t *target = decoded_data; *decoded_data_len = 0; do { - ret = SKP_Silk_SDK_Decode(context->dec_state, &context->decoder_object, ((*flag & SFF_PLC)), encoded_data, encoded_data_len, target, &len); - if (ret) { + ret = SKP_Silk_SDK_Decode(context->dec_state, + &context->decoder_object, + ((*flag & SFF_PLC)), + encoded_data, + encoded_data_len, + target, + &len); + if (ret){ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SKP_Silk_Decode returned %d!\n", ret); } target += len; *decoded_data_len += (len * 2); - } - while (context->decoder_object.internalDecoderFrames); + } while (context->decoder_object.internalDecoderFrames); return SWITCH_STATUS_SUCCESS; } @@ -232,77 +299,81 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_silk_load) *module_interface = switch_loadable_module_create_module_interface(pool, modname); SWITCH_ADD_CODEC(codec_interface, "SILK"); - switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ - 117, /* the IANA code number */ - "SILK", /* the IANA code name */ - "useinbandfec=false; usedtx=false", /* default fmtp to send (can be overridden by the init function) */ - 8000, /* samples transferred per second */ - 8000, /* actual samples transferred per second */ - 20000, /* bits transferred per second */ - 20000, /* number of microseconds per frame */ - 160, /* number of samples per frame */ - 320, /* number of bytes per frame decompressed */ - 0, /* number of bytes per frame compressed */ - 1, /* number of channels represented */ - 1, /* number of frames per network packet */ - switch_silk_init, /* function to initialize a codec handle using this implementation */ - switch_silk_encode, /* function to encode raw data into encoded data */ - switch_silk_decode, /* function to decode encoded data into raw data */ - switch_silk_destroy); /* deinitalize a codec handle using this implementation */ + switch_core_codec_add_implementation(pool, codec_interface, + SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ + 117, /* the IANA code number */ + "SILK", /* the IANA code name */ + "useinbandfec=true; usedtx=false", /* default fmtp to send (can be overridden by the init function) */ + 8000, /* samples transferred per second */ + 8000, /* actual samples transferred per second */ + 20000, /* bits transferred per second */ + 20000, /* number of microseconds per frame */ + 160, /* number of samples per frame */ + 320, /* number of bytes per frame decompressed */ + 0, /* number of bytes per frame compressed */ + 1, /* number of channels represented */ + 1, /* number of frames per network packet */ + switch_silk_init, /* function to initialize a codec handle using this implementation */ + switch_silk_encode, /* function to encode raw data into encoded data */ + switch_silk_decode, /* function to decode encoded data into raw data */ + switch_silk_destroy); /* deinitalize a codec handle using this implementation */ - switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ - 118, /* the IANA code number */ - "SILK", /* the IANA code name */ + switch_core_codec_add_implementation(pool, codec_interface, + SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ + 118, /* the IANA code number */ + "SILK", /* the IANA code name */ "useinbandfec=false; usedtx=false", /* default fmtp to send (can be overridden by the init function) */ - 12000, /* samples transferred per second */ - 12000, /* actual samples transferred per second */ - 25000, /* bits transferred per second */ - 20000, /* number of microseconds per frame */ - 240, /* number of samples per frame */ - 480, /* number of bytes per frame decompressed */ - 0, /* number of bytes per frame compressed */ - 1, /* number of channels represented */ - 1, /* number of frames per network packet */ - switch_silk_init, /* function to initialize a codec handle using this implementation */ - switch_silk_encode, /* function to encode raw data into encoded data */ - switch_silk_decode, /* function to decode encoded data into raw data */ - switch_silk_destroy); /* deinitalize a codec handle using this implementation */ + 12000, /* samples transferred per second */ + 12000, /* actual samples transferred per second */ + 25000, /* bits transferred per second */ + 20000, /* number of microseconds per frame */ + 240, /* number of samples per frame */ + 480, /* number of bytes per frame decompressed */ + 0, /* number of bytes per frame compressed */ + 1, /* number of channels represented */ + 1, /* number of frames per network packet */ + switch_silk_init, /* function to initialize a codec handle using this implementation */ + switch_silk_encode, /* function to encode raw data into encoded data */ + switch_silk_decode, /* function to decode encoded data into raw data */ + switch_silk_destroy); /* deinitalize a codec handle using this implementation */ - switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ - 119, /* the IANA code number */ - "SILK", /* the IANA code name */ + switch_core_codec_add_implementation(pool, codec_interface, + SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ + 119, /* the IANA code number */ + "SILK", /* the IANA code name */ "useinbandfec=false; usedtx=false", /* default fmtp to send (can be overridden by the init function) */ - 16000, /* samples transferred per second */ - 16000, /* actual samples transferred per second */ - 30000, /* bits transferred per second */ - 20000, /* number of microseconds per frame */ - 320, /* number of samples per frame */ - 640, /* number of bytes per frame decompressed */ - 0, /* number of bytes per frame compressed */ - 1, /* number of channels represented */ - 1, /* number of frames per network packet */ - switch_silk_init, /* function to initialize a codec handle using this implementation */ - switch_silk_encode, /* function to encode raw data into encoded data */ - switch_silk_decode, /* function to decode encoded data into raw data */ - switch_silk_destroy); /* deinitalize a codec handle using this implementation */ + 16000, /* samples transferred per second */ + 16000, /* actual samples transferred per second */ + 30000, /* bits transferred per second */ + 20000, /* number of microseconds per frame */ + 320, /* number of samples per frame */ + 640, /* number of bytes per frame decompressed */ + 0, /* number of bytes per frame compressed */ + 1, /* number of channels represented */ + 1, /* number of frames per network packet */ + switch_silk_init, /* function to initialize a codec handle using this implementation */ + switch_silk_encode, /* function to encode raw data into encoded data */ + switch_silk_decode, /* function to decode encoded data into raw data */ + switch_silk_destroy); /* deinitalize a codec handle using this implementation */ - switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ - 120, /* the IANA code number */ - "SILK", /* the IANA code name */ + switch_core_codec_add_implementation(pool, codec_interface, + SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ + 120, /* the IANA code number */ + "SILK", /* the IANA code name */ "useinbandfec=false; usedtx=false", /* default fmtp to send (can be overridden by the init function) */ - 24000, /* samples transferred per second */ - 24000, /* actual samples transferred per second */ - 40000, /* bits transferred per second */ - 20000, /* number of microseconds per frame */ - 480, /* number of samples per frame */ - 960, /* number of bytes per frame decompressed */ - 0, /* number of bytes per frame compressed */ - 1, /* number of channels represented */ - 1, /* number of frames per network packet */ - switch_silk_init, /* function to initialize a codec handle using this implementation */ - switch_silk_encode, /* function to encode raw data into encoded data */ - switch_silk_decode, /* function to decode encoded data into raw data */ - switch_silk_destroy); /* deinitalize a codec handle using this implementation */ + 24000, /* samples transferred per second */ + 24000, /* actual samples transferred per second */ + 40000, /* bits transferred per second */ + 20000, /* number of microseconds per frame */ + 480, /* number of samples per frame */ + 960, /* number of bytes per frame decompressed */ + 0, /* number of bytes per frame compressed */ + 1, /* number of channels represented */ + 1, /* number of frames per network packet */ + switch_silk_init, /* function to initialize a codec handle using this implementation */ + switch_silk_encode, /* function to encode raw data into encoded data */ + switch_silk_decode, /* function to decode encoded data into raw data */ + switch_silk_destroy); /* deinitalize a codec handle using this implementation */ /* indicate that the module should continue to be loaded */