Commit 13678274 authored by Simon Morlat's avatar Simon Morlat

fix memory leak in g726 decoder, vad-dtx-plc in progress

parent b70947a4
/*
mediastreamer2 library - modular sound and video processing and streaming
Copyright (C) 2014 Belledonne Communications SARL
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "mediastreamer2/msfilter.h"
typedef struct _MSCngData{
int datasize;
uint8_t data[32];
}MSCngData;
/** Event generated when silence is detected. Payload contains the data encoding the background noise*/
#define MS_VAD_DTX_NO_VOICE MS_FILTER_EVENT(MSVadDtxId, 0, MSCngData)
/*
mediastreamer2 library - modular sound and video processing and streaming
Copyright (C) 2015 Belledonne Communications SARL
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef msgenericplc_h
#define msgenericplc_h
#include "mediastreamer2/msvaddtx.h"
#define MS_GENERIC_PLC_SET_CN MS_FILTER_METHOD(MS_GENERIC_PLC_ID, 0, MSCngData)
#endif
......@@ -97,6 +97,8 @@ MS2_PUBLIC void ms_queue_destroy(MSQueue *q);
#define mblk_get_precious_flag(m) (((m)->reserved2)>>1 & 0x1) /*bit 2*/
#define mblk_set_plc_flag(m,bit) __mblk_set_flag(m,2,bit) /*use to mark a plc generated block*/
#define mblk_get_plc_flag(m) (((m)->reserved2)>>1 & 0x2) /*bit 2*/
#define mblk_set_cng_flag(m,bit) __mblk_set_flag(m,3,bit) /*use to mark a cng generated block*/
#define mblk_get_cng_flag(m) (((m)->reserved2)>>2 & 0x4) /*bit 3*/
#define mblk_set_cseq(m,value) (m)->reserved2=(m)->reserved2| ((value&0xFFFF)<<16);
#define mblk_get_cseq(m) ((m)->reserved2>>16)
......
......@@ -17,6 +17,9 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef msvaddtx_h
#define msvaddtx_h
#include "mediastreamer2/msfilter.h"
typedef struct _MSCngData{
......@@ -27,3 +30,7 @@ typedef struct _MSCngData{
/** Event generated when silence is detected. Payload contains the data encoding the background noise*/
#define MS_VAD_DTX_NO_VOICE MS_FILTER_EVENT(MS_VAD_DTX_ID, 0, MSCngData)
#define MS_VAD_DTX_VOICE MS_FILTER_EVENT_NO_ARG(MS_VAD_DTX_ID, 1)
#endif
......@@ -156,6 +156,7 @@ static void dec_process(MSFilter *f){
mblk_t *om=allocb(decoded_bytes,0);
mblk_meta_copy(im, om);
g726_decode(s->impl,(int16_t*)om->b_wptr,im->b_rptr,size);
freemsg(im);
om->b_wptr+=decoded_bytes;
ms_queue_put(f->outputs[0],om);
}
......
......@@ -21,12 +21,16 @@
#include <mediastreamer2/msfilter.h>
#include <mediastreamer2/mscodecutils.h>
#include <mediastreamer2/msticker.h>
#include "mediastreamer2/msgenericplc.h"
/*filter common method*/
typedef struct {
MSConcealerContext* concealer;
int rate;
int nchannels;
MSCngData cng_data;
bool_t cng_set;
bool_t cng_running;
} generic_plc_struct;
const static unsigned int MAX_PLC_COUNT = UINT32_MAX;
......@@ -36,7 +40,6 @@ static void generic_plc_init(MSFilter *f) {
mgps->concealer = ms_concealer_context_new(MAX_PLC_COUNT);
mgps->nchannels = 1;
f->data = mgps;
}
static void generic_plc_process(MSFilter *f) {
......@@ -47,13 +50,25 @@ static void generic_plc_process(MSFilter *f) {
unsigned int time = (1000*(m->b_wptr - m->b_rptr))/(mgps->rate*sizeof(int16_t)*mgps->nchannels);
ms_concealer_inc_sample_time(mgps->concealer, f->ticker->time, time, TRUE);
ms_queue_put(f->outputs[0], m);
if (mgps->cng_running){
/*we were doing CNG, now resuming with normal audio*/
mgps->cng_running=FALSE;
mgps->cng_set=FALSE;
}
}
if (ms_concealer_context_is_concealement_required(mgps->concealer, f->ticker->time)) {
m = allocb(buff_size, 0);
if (!mgps->cng_running && mgps->cng_set){
mgps->cng_running=TRUE;
mblk_set_cng_flag(m, 1);
/*TODO do something with the buffer*/
}else{
mblk_set_plc_flag(m, 1);
}
memset(m->b_wptr, 0, buff_size);
m->b_wptr += buff_size;
ms_queue_put(f->outputs[0], m);
mblk_set_plc_flag(m, 1);
ms_concealer_inc_sample_time(mgps->concealer, f->ticker->time, f->ticker->interval, FALSE);
}
}
......@@ -82,10 +97,18 @@ static int generic_plc_set_nchannels(MSFilter *f, void *arg) {
return 0;
}
static int generic_plc_set_cn(MSFilter *f, void *arg) {
generic_plc_struct *s = (generic_plc_struct *)f->data;
memcpy(&s->cng_data,arg, sizeof(MSCngData));
s->cng_set=TRUE;
return 0;
}
static MSFilterMethod generic_plc_methods[] = {
{ MS_FILTER_SET_SAMPLE_RATE , generic_plc_set_sr },
{ MS_FILTER_GET_SAMPLE_RATE , generic_plc_get_sr },
{ MS_FILTER_SET_NCHANNELS , generic_plc_set_nchannels },
{ MS_GENERIC_PLC_SET_CN , generic_plc_set_cn },
{ 0 , NULL }
};
......
......@@ -87,10 +87,11 @@ static void vad_dtx_process(MSFilter *f){
}else{
if (ctx->silence_mode){
ms_message("vad_dtx_process(): silence period finished.");
ctx->silence_mode=1;
ctx->silence_mode=0;
ms_filter_notify(f, MS_VAD_DTX_VOICE, NULL);
}
}
if (!ctx->silence_mode) ms_queue_put(f->outputs[0],m);
ms_queue_put(f->outputs[0],m);
}
}
......
......@@ -213,8 +213,7 @@ static int sender_get_ch(MSFilter *f, void *arg) {
}
/* the goal of that function is to return a absolute timestamp closest to real time, with respect of given packet_ts, which is a relative to an undefined origin*/
static uint32_t get_cur_timestamp(MSFilter * f, mblk_t *im)
{
static uint32_t get_cur_timestamp(MSFilter * f, mblk_t *im){
SenderData *d = (SenderData *) f->data;
uint32_t curts = (uint32_t)( (f->ticker->time*(uint64_t)d->rate)/(uint64_t)1000) ;
int diffts;
......@@ -359,6 +358,14 @@ static void check_stun_sending(MSFilter *f) {
}
}
static void process_cn(MSFilter *f, SenderData *d){
if (d->cng_data.datasize>0){
mblk_t *m=rtp_session_create_packet(d->session, 12, d->cng_data.data, d->cng_data.datasize);
rtp_session_sendm_with_ts(d->session,m,d->last_ts);
d->cng_data.datasize=0;
}
}
static void _sender_process(MSFilter * f)
{
SenderData *d = (SenderData *) f->data;
......@@ -402,6 +409,7 @@ static void _sender_process(MSFilter * f)
rtp_session_sendm_with_ts(s, header, timestamp);
} else if (d->mute==TRUE && d->skip == FALSE) {
freemsg(im);
process_cn(f, d);
//Send STUN packet as RTP keep alive
check_stun_sending(f);
......@@ -492,6 +500,7 @@ MSFilterDesc ms_rtp_send_desc = {
struct ReceiverData {
RtpSession *session;
int current_pt;
int rate;
bool_t starting;
bool_t reset_jb;
......@@ -520,13 +529,13 @@ static int receiver_set_session(MSFilter * f, void *arg)
{
ReceiverData *d = (ReceiverData *) f->data;
RtpSession *s = (RtpSession *) arg;
PayloadType *pt = rtp_profile_get_payload(rtp_session_get_profile(s),
rtp_session_get_recv_payload_type
(s));
PayloadType *pt;
d->current_pt=rtp_session_get_recv_payload_type(s);
pt = rtp_profile_get_payload(rtp_session_get_profile(s),d->current_pt);
if (pt != NULL) {
d->rate = pt->clock_rate;
} else {
ms_warning("Receiving undefined payload type %i ?",
ms_warning("receiver_set_session(): receiving undefined payload type %i ?",
rtp_session_get_recv_payload_type(s));
}
d->session = s;
......@@ -582,6 +591,33 @@ static void receiver_preprocess(MSFilter * f){
d->starting=TRUE;
}
/*returns TRUE if the packet is ok to be sent to output queue*/
static bool_t receiver_check_payload_type(MSFilter *f, ReceiverData *d, mblk_t *m){
int ptn=rtp_get_payload_type(m);
PayloadType *pt;
if (ptn==d->current_pt) return TRUE;
pt=rtp_profile_get_payload(rtp_session_get_profile(d->session), ptn);
if (pt==NULL){
ms_warning("Discarding packet with unknown payload type %i",ptn);
return FALSE;
}
if (strcasecmp(pt->mime_type,"CN")==0){
MSCngData cngdata;
uint8_t *data=NULL;
int datasize=rtp_get_payload(m, &data);
if (data){
if (datasize<= sizeof(cngdata.data)){
memcpy(cngdata.data, data, datasize);
cngdata.datasize=datasize;
ms_filter_notify(f, MS_RTP_RECV_GENERIC_CN_RECEIVED, &cngdata);
}else{
ms_warning("CN packet has unexpected size %i", datasize);
}
}
}
return FALSE;
}
static void receiver_process(MSFilter * f)
{
ReceiverData *d = (ReceiverData *) f->data;
......@@ -608,11 +644,15 @@ static void receiver_process(MSFilter * f)
timestamp = (uint32_t) (f->ticker->time * (d->rate/1000));
while ((m = rtp_session_recvm_with_ts(d->session, timestamp)) != NULL) {
mblk_set_timestamp_info(m, rtp_get_timestamp(m));
mblk_set_marker_info(m, rtp_get_markbit(m));
mblk_set_cseq(m, rtp_get_seqnumber(m));
rtp_get_payload(m,&m->b_rptr);
ms_queue_put(f->outputs[0], m);
if (receiver_check_payload_type(f, d, m)){
mblk_set_timestamp_info(m, rtp_get_timestamp(m));
mblk_set_marker_info(m, rtp_get_markbit(m));
mblk_set_cseq(m, rtp_get_seqnumber(m));
rtp_get_payload(m,&m->b_rptr);
ms_queue_put(f->outputs[0], m);
}else{
freemsg(m);
}
}
/*every second compute recv bandwidth*/
if (f->ticker->time % 1000 == 0) rtp_session_compute_recv_bandwidth(d->session);
......
......@@ -34,6 +34,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "mediastreamer2/msaudiomixer.h"
#include "mediastreamer2/mscodecutils.h"
#include "mediastreamer2/msitc.h"
#include "mediastreamer2/msvaddtx.h"
#include "mediastreamer2/msgenericplc.h"
#include "private.h"
......@@ -588,7 +590,28 @@ static void setup_recorder(AudioStream *stream, int sample_rate, int nchannels){
}
static void on_silence_detected(void *data, MSFilter *f, unsigned int event_id, void *event_arg){
ms_message("on_silence_detected(): CN packet to be sent !");
AudioStream *as=(AudioStream*)data;
if (as->ms.rtpsend){
switch(event_id){
case MS_VAD_DTX_NO_VOICE:
ms_message("on_silence_detected(): CN packet to be sent !");
ms_filter_call_method(as->ms.rtpsend, MS_RTP_SEND_SEND_GENERIC_CN, event_arg);
ms_filter_call_method(as->ms.rtpsend, MS_RTP_SEND_MUTE, event_arg);
break;
case MS_VAD_DTX_VOICE:
ms_message("on_silence_detected(): resuming audio");
ms_filter_call_method(as->ms.rtpsend, MS_RTP_SEND_UNMUTE, event_arg);
break;
}
}
}
static void on_cn_received(void *data, MSFilter *f, unsigned int event_id, void *event_arg){
AudioStream *as=(AudioStream*)data;
if (as->plc){
ms_message("CN packet received, given to MSGenericPlc filter.");
ms_filter_call_method(as->plc, MS_GENERIC_PLC_SET_CN, event_arg);
}
}
static void setup_generic_confort_noise(AudioStream *stream){
......@@ -600,6 +623,7 @@ static void setup_generic_confort_noise(AudioStream *stream){
/* RFC3389 CN can be used*/
stream->vaddtx=ms_filter_new(MS_VAD_DTX_ID);
ms_filter_add_notify_callback(stream->vaddtx, on_silence_detected, stream, TRUE);
ms_filter_add_notify_callback(stream->ms.rtprecv, on_cn_received, stream, TRUE);
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment