You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

216 lines
6.5 KiB

/*
bcg729_enc.c
Copyright (C) 2011 Belledonne Communications, Grenoble, France
Author : Jehan Monnier
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "mediastreamer2/msfilter.h"
#include "mediastreamer2/mscodecutils.h"
#include "bcg729/encoder.h"
#ifdef HAVE_ms_bufferizer_fill_current_metas
#define ms_bufferizer_fill_current_metas(b,m) ms_bufferizer_fill_current_metas(b,m)
#else
#define ms_bufferizer_fill_current_metas(b,m)
#endif
/*filter common method*/
struct bcg729Encoder_struct {
bcg729EncoderChannelContextStruct *encoderChannelContext;
MSBufferizer *bufferizer;
unsigned char ptime;
unsigned char max_ptime;
uint32_t ts;
uint8_t enableVAD;
};
static void filter_init(MSFilter *f){
struct bcg729Encoder_struct* obj;
f->data = ms_new0(struct bcg729Encoder_struct,1);
obj = (struct bcg729Encoder_struct*) f->data;
obj->ptime=20;
obj->max_ptime=100;
obj->enableVAD=0;
}
static void filter_preprocess(MSFilter *f){
struct bcg729Encoder_struct* obj= (struct bcg729Encoder_struct*) f->data;
obj->encoderChannelContext = initBcg729EncoderChannel(obj->enableVAD); /* initialize bcg729 encoder, return context */
obj->bufferizer=ms_bufferizer_new();
}
static void filter_process(MSFilter *f){
struct bcg729Encoder_struct* obj= (struct bcg729Encoder_struct*) f->data;
mblk_t *inputMessage;
mblk_t *outputMessage=NULL;
uint8_t inputBuffer[160]; /* 2bytes per sample at 8000Hz -> 16 bytes per ms */
uint8_t bufferIndex=0;
/* get all input data into a buffer */
while((inputMessage=ms_queue_get(f->inputs[0]))!=NULL){
ms_bufferizer_put(obj->bufferizer,inputMessage);
}
/* process ptimes ms of data : (ptime in ms)/1000->ptime is seconds * 8000(sample rate) * 2(byte per sample) */
while(ms_bufferizer_get_avail(obj->bufferizer)>=obj->ptime*16){
uint16_t totalPacketDataLength = 0;
uint8_t bitStreamLength = 0;
outputMessage = allocb(obj->ptime,0); /* output bitStream is 80 bits long * number of samples */
/* process buffer in 10 ms frames */
/* RFC3551 section 4.5.6 we must end the RTP payload of G729 frames when transmitting a SID frame : bitStreamLength == 2 */
for (bufferIndex=0; (bufferIndex<obj->ptime) && (bitStreamLength!=2); bufferIndex+=10) {
ms_bufferizer_read(obj->bufferizer,inputBuffer,160);
bcg729Encoder(obj->encoderChannelContext, (int16_t *)inputBuffer, outputMessage->b_wptr, &bitStreamLength);
outputMessage->b_wptr+=bitStreamLength;
totalPacketDataLength+=bitStreamLength;
}
obj->ts+=bufferIndex*8;
/* do not enqueue the message if no data out (DTX untransmitted frames) */
if (totalPacketDataLength>0) {
mblk_set_timestamp_info(outputMessage,obj->ts);
ms_bufferizer_fill_current_metas(obj->bufferizer, outputMessage);
ms_queue_put(f->outputs[0],outputMessage);
}
}
}
static void filter_postprocess(MSFilter *f){
struct bcg729Encoder_struct* obj= (struct bcg729Encoder_struct*) f->data;
ms_bufferizer_destroy(obj->bufferizer);
closeBcg729EncoderChannel(obj->encoderChannelContext);
}
static void filter_uninit(MSFilter *f){
ms_free(f->data);
}
/*filter specific method*/
static int filter_add_fmtp(MSFilter *f, void *arg){
char buf[64];
struct bcg729Encoder_struct* obj= (struct bcg729Encoder_struct*) f->data;
const char *fmtp=(const char *)arg;
buf[0] ='\0';
if (fmtp_get_value(fmtp,"maxptime:",buf,sizeof(buf))){
obj->max_ptime=atoi(buf);
if (obj->max_ptime <10 || obj->max_ptime >100 ) {
ms_warning("MSBCG729Enc: unknown value [%i] for maxptime, use default value (100) instead",obj->max_ptime);
obj->max_ptime=100;
}
ms_message("MSBCG729Enc: got maxptime=%i",obj->max_ptime);
}
if (fmtp_get_value(fmtp,"ptime",buf,sizeof(buf))){
obj->ptime=atoi(buf);
if (obj->ptime > obj->max_ptime) {
obj->ptime=obj->max_ptime;
} else if (obj->ptime%10) {
//if the ptime is not a mulptiple of 10, go to the next multiple
obj->ptime = obj->ptime - obj->ptime%10 + 10;
}
ms_message("MSBCG729Enc: got ptime=%i",obj->ptime);
}
if (fmtp_get_value(fmtp,"annexb",buf,sizeof(buf))){
if (strncmp(buf, "yes",3) == 0) {
obj->enableVAD = 1;
ms_message("MSBCG729Enc: enable VAD/DTX - AnnexB");
}
}
/* parse annexB param here */
return 0;
}
static MSFilterMethod filter_methods[]={
{ MS_FILTER_ADD_FMTP , filter_add_fmtp },
{ 0, NULL}
};
#define MS_BCG729_ENC_ID MS_FILTER_PLUGIN_ID
#define MS_BCG729_ENC_NAME "MSBCG729Enc"
#define MS_BCG729_ENC_DESCRIPTION "G729 audio encoder filter"
#define MS_BCG729_ENC_CATEGORY MS_FILTER_ENCODER
#define MS_BCG729_ENC_ENC_FMT "G729"
#define MS_BCG729_ENC_NINPUTS 1
#define MS_BCG729_ENC_NOUTPUTS 1
#define MS_BCG729_ENC_FLAGS 0
#ifndef _MSC_VER
MSFilterDesc ms_bcg729_enc_desc={
.id=MS_BCG729_ENC_ID,
.name=MS_BCG729_ENC_NAME,
.text=MS_BCG729_ENC_DESCRIPTION,
.category=MS_BCG729_ENC_CATEGORY,
.enc_fmt=MS_BCG729_ENC_ENC_FMT,
.ninputs=MS_BCG729_ENC_NINPUTS, /*number of inputs*/
.noutputs=MS_BCG729_ENC_NOUTPUTS, /*number of outputs*/
.init=filter_init,
.preprocess=filter_preprocess,
.process=filter_process,
.postprocess=filter_postprocess,
.uninit=filter_uninit,
.methods=filter_methods,
.flags=MS_BCG729_ENC_FLAGS
};
#else
MSFilterDesc ms_bcg729_enc_desc={
MS_BCG729_ENC_ID,
MS_BCG729_ENC_NAME,
MS_BCG729_ENC_DESCRIPTION,
MS_BCG729_ENC_CATEGORY,
MS_BCG729_ENC_ENC_FMT,
MS_BCG729_ENC_NINPUTS,
MS_BCG729_ENC_NOUTPUTS,
filter_init,
filter_preprocess,
filter_process,
filter_postprocess,
filter_uninit,
filter_methods,
MS_BCG729_ENC_FLAGS
};
#endif
MS_FILTER_DESC_EXPORT(ms_bcg729_enc_desc)
#ifdef _MSC_VER
#define MS_PLUGIN_DECLARE(type) __declspec(dllexport) type
#else
#define MS_PLUGIN_DECLARE(type) type
#endif
extern MSFilterDesc ms_bcg729_dec_desc;
#ifndef VERSION
#define VERSION "debug"
#endif
MS_PLUGIN_DECLARE(void) libmsbcg729_init(MSFactory * factory){
ms_factory_register_filter(factory, &ms_bcg729_enc_desc);
ms_factory_register_filter(factory, &ms_bcg729_dec_desc);
ms_message(" libmsbcg729 " VERSION " plugin loaded");
}