blob: b2dfff98b8558e859effb86651e84ff995faf92f [file] [log] [blame]
/*
The mediastreamer library aims at providing modular media processing and I/O
for linphone, but also for any telephony application.
Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
This library 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; either
version 2.1 of the License, or (at your option) any later version.
This library 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 <config.h>
#ifdef HAVE_ILBC
#include "msilbcdec.h"
#include "msilbcenc.h"
#include "mscodec.h"
#include <stdlib.h>
#include <stdio.h>
extern MSFilter * ms_ilbc_encoder_new(void);
MSCodecInfo ilbc_info={
{
"iLBC codec",
0,
MS_FILTER_AUDIO_CODEC,
ms_ilbc_encoder_new,
"A speech codec suitable for robust voice communication over IP"
},
ms_ilbc_encoder_new,
ms_ilbc_decoder_new,
0, /* not applicable, 2 modes */
0, /* not applicable, 2 modes */
15200,
8000,
97,
"iLBC",
1,
1,
};
void ms_ilbc_codec_init()
{
ms_filter_register(MS_FILTER_INFO(&ilbc_info));
}
static MSILBCDecoderClass *ms_ilbc_decoder_class=NULL;
MSFilter * ms_ilbc_decoder_new(void)
{
MSILBCDecoder *r;
r=g_new(MSILBCDecoder,1);
ms_ilbc_decoder_init(r);
if (ms_ilbc_decoder_class==NULL)
{
ms_ilbc_decoder_class=g_new(MSILBCDecoderClass,1);
ms_ilbc_decoder_class_init(ms_ilbc_decoder_class);
}
MS_FILTER(r)->klass=MS_FILTER_CLASS(ms_ilbc_decoder_class);
return(MS_FILTER(r));
}
int ms_ilbc_decoder_set_property(MSILBCDecoder *obj, MSFilterProperty prop, char *value)
{
switch(prop){
case MS_FILTER_PROPERTY_FMTP:
if (value == NULL) return 0;
if (strstr(value,"ptime=20")!=NULL) obj->ms_per_frame=20;
else if (strstr(value,"ptime=30")!=NULL) obj->ms_per_frame=30;
else g_warning("Unrecognized fmtp parameter for ilbc encoder!");
break;
}
return 0;
}
int ms_ilbc_decoder_get_property(MSILBCDecoder *obj, MSFilterProperty prop, char *value)
{
switch(prop){
case MS_FILTER_PROPERTY_FMTP:
if (obj->ms_per_frame==20) strncpy(value,"ptime=20",MS_FILTER_PROPERTY_STRING_MAX_SIZE);
if (obj->ms_per_frame==30) strncpy(value,"ptime=30",MS_FILTER_PROPERTY_STRING_MAX_SIZE);
break;
}
return 0;
}
void ms_ilbc_decoder_setup(MSILBCDecoder *r)
{
MSFilterClass *klass = NULL;
switch (r->ms_per_frame) {
case 20:
r->samples_per_frame = BLOCKL_20MS;
r->bytes_per_compressed_frame = NO_OF_BYTES_20MS;
break;
case 30:
r->samples_per_frame = BLOCKL_30MS;
r->bytes_per_compressed_frame = NO_OF_BYTES_30MS;
break;
default:
g_error("ms_ilbc_decoder_setup: Bad value for ptime (%i)",r->ms_per_frame);
}
g_message("Using ilbc decoder with %i ms frames mode.",r->ms_per_frame);
initDecode(&r->ilbc_dec, r->ms_per_frame /* ms frames */, /* user enhancer */ 0);
}
/* FOR INTERNAL USE*/
void ms_ilbc_decoder_init(MSILBCDecoder *r)
{
/* default bitrate */
r->bitrate = 15200;
r->ms_per_frame = 30;
r->samples_per_frame = BLOCKL_20MS;
r->bytes_per_compressed_frame = NO_OF_BYTES_20MS;
ms_filter_init(MS_FILTER(r));
MS_FILTER(r)->inqueues=r->q_inputs;
MS_FILTER(r)->outfifos=r->f_outputs;
memset(r->q_inputs,0,sizeof(MSFifo*)*MSILBCDECODER_MAX_INPUTS);
memset(r->f_outputs,0,sizeof(MSFifo*)*MSILBCDECODER_MAX_INPUTS);
}
void ms_ilbc_decoder_class_init(MSILBCDecoderClass *klass)
{
ms_filter_class_init(MS_FILTER_CLASS(klass));
ms_filter_class_set_name(MS_FILTER_CLASS(klass),"ILBCDec");
MS_FILTER_CLASS(klass)->max_qinputs=MSILBCDECODER_MAX_INPUTS;
MS_FILTER_CLASS(klass)->max_foutputs=MSILBCDECODER_MAX_INPUTS;
MS_FILTER_CLASS(klass)->w_maxgran= ILBC_MAX_SAMPLES_PER_FRAME*2;
MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_ilbc_decoder_destroy;
MS_FILTER_CLASS(klass)->set_property=(MSFilterPropertyFunc)ms_ilbc_decoder_set_property;
MS_FILTER_CLASS(klass)->get_property=(MSFilterPropertyFunc)ms_ilbc_decoder_get_property;
MS_FILTER_CLASS(klass)->setup=(MSFilterSetupFunc)ms_ilbc_decoder_setup;
MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_ilbc_decoder_process;
MS_FILTER_CLASS(klass)->info=(MSFilterInfo*)&ilbc_info;
}
void ms_ilbc_decoder_process(MSILBCDecoder *r)
{
MSFifo *fo;
MSQueue *qi;
int err1;
void *dst=NULL;
float speech[ILBC_MAX_SAMPLES_PER_FRAME];
MSMessage *m;
qi=r->q_inputs[0];
fo=r->f_outputs[0];
m=ms_queue_get(qi);
ms_fifo_get_write_ptr(fo, r->samples_per_frame*2, &dst);
if (dst!=NULL){
if (m->data!=NULL){
if (m->size<r->bytes_per_compressed_frame) {
g_warning("Invalid ilbc frame ?");
}
iLBC_decode(speech, m->data, &r->ilbc_dec, /* mode */1);
}else{
iLBC_decode(speech,NULL, &r->ilbc_dec,0);
}
ilbc_write_16bit_samples((gint16*)dst, speech, r->samples_per_frame);
}
ms_message_destroy(m);
}
void ms_ilbc_decoder_uninit(MSILBCDecoder *obj)
{
}
void ms_ilbc_decoder_destroy( MSILBCDecoder *obj)
{
ms_ilbc_decoder_uninit(obj);
g_free(obj);
}
#endif