Commit d4829668 authored by jehan's avatar jehan

Merge branch 'master' of git.linphone.org:mediastreamer2

Conflicts:
	include/mediastreamer2/msinterfaces.h
parents 6a5c222c ed415ced
......@@ -30,6 +30,7 @@ mediastreamer2_include_HEADERS= ice.h \
msitc.h \
msextdisplay.h \
msjpegwriter.h \
mstonedetector.h \
msjava.h
EXTRA_DIST=$(mediastreamer2_include_HEADERS)
......
......@@ -106,7 +106,8 @@ typedef enum MSFilterId{
MS_X11VIDEO_ID,
MS_ANDROID_DISPLAY_ID,
MS_ANDROID_VIDEO_READ_ID,
MS_ANDROID_VIDEO_WRITE_ID
MS_ANDROID_VIDEO_WRITE_ID,
MS_TONE_DETECTOR_ID
} MSFilterId;
......
......@@ -23,13 +23,30 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "msfilter.h"
#define MS_DTMF_GEN_PUT MS_FILTER_METHOD(MS_DTMF_GEN_ID,0,const char)
/** Plays dtmf tone given in argument with default duration*/
#define MS_DTMF_GEN_PLAY MS_FILTER_METHOD(MS_DTMF_GEN_ID,0,const char) /*alias to put*/
/**Start playing a dtmf */
/**Start playing a given dtmf, then it has to be stopped using MS_DTMF_GEN_STOP */
#define MS_DTMF_GEN_START MS_FILTER_METHOD(MS_DTMF_GEN_ID,1,const char)
/**Stop currently played dtmf*/
#define MS_DTMF_GEN_STOP MS_FILTER_METHOD_NO_ARG(MS_DTMF_GEN_ID,2)
/**
* Structure describing a custom tone.
**/
struct _MSDtmfGenCustomTone{
int duration; /**<Duration of the tone in milliseconds*/
int frequency; /**<Frequency of the tone to be played */
float amplitude; /**<Amplitude of the tone, 1.0 being the 0dbm normalized level*/
};
typedef struct _MSDtmfGenCustomTone MSDtmfGenCustomTone;
/**Play a custom tone according to the supplied tone description*/
#define MS_DTMF_GEN_PLAY_CUSTOM MS_FILTER_METHOD(MS_DTMF_GEN_ID,3,MSDtmfGenCustomTone)
extern MSFilterDesc ms_dtmf_gen_desc;
#endif
......@@ -166,6 +166,9 @@ void audio_stream_get_local_rtp_stats(AudioStream *stream, rtp_stats_t *stats);
*****************/
typedef void (*VideoStreamRenderCallback)(void *user_pointer, const MSPicture *local_view, const MSPicture *remote_view);
typedef void (*VideoStreamEventCallback)(void *user_pointer, const MSFilter *f, const unsigned int event_id, const void *args);
typedef enum _VideoStreamDir{
VideoStreamSendRecv,
......@@ -194,6 +197,8 @@ struct _VideoStream
int corner; /*for selfview*/
VideoStreamRenderCallback rendercb;
void *render_pointer;
VideoStreamEventCallback eventcb;
void *event_pointer;
char *display_name;
unsigned long window_id;
unsigned long preview_window_id;
......@@ -211,6 +216,7 @@ VideoStream *video_stream_new(int locport, bool_t use_ipv6);
void video_stream_set_direction(VideoStream *vs, VideoStreamDir dir);
void video_stream_enable_adaptive_bitrate_control(VideoStream *s, bool_t yesno);
void video_stream_set_render_callback(VideoStream *s, VideoStreamRenderCallback cb, void *user_pointer);
void video_stream_set_event_callback(VideoStream *s, VideoStreamEventCallback cb, void *user_pointer);
void video_stream_set_display_filter_name(VideoStream *s, const char *fname);
int video_stream_start(VideoStream * stream, RtpProfile *profile, const char *remip, int remport, int rem_rtcp_port,
int payload, int jitt_comp, MSWebCam *device);
......
......@@ -58,7 +58,7 @@ typedef int (*MSFilterMethodFunc)(struct _MSFilter *f, void *arg);
* Structure for filter's methods used as a callback to notify events.
* @var MSFilterNotifyFunc
*/
typedef void (*MSFilterNotifyFunc)(void *userdata , unsigned int id, void *arg);
typedef void (*MSFilterNotifyFunc)(void *userdata, struct _MSFilter *f, unsigned int id, void *arg);
struct _MSFilterMethod{
int id;
......@@ -515,7 +515,8 @@ enum _MSFilterInterfaceId{
MSFilterPlayerInterface,
MSFilterRecorderInterface,
MSFilterVideoDisplayInterface,
MSFilterEchoCancellerInterface
MSFilterEchoCancellerInterface,
MSFilterVideoDecoderInterface
};
typedef enum _MSFilterInterfaceId MSFilterInterfaceId;
......
......@@ -87,7 +87,7 @@ typedef enum _MSPlayerState MSPlayerState;
MS_FILTER_METHOD(MSFilterPlayerInterface,5,int)
/** Interface definitions for echo cancellers*/
/** Interface definitions for echo cancellers */
/** sets the echo delay in milliseconds*/
#define MS_ECHO_CANCELLER_SET_DELAY \
......@@ -100,6 +100,11 @@ typedef enum _MSPlayerState MSPlayerState;
#define MS_ECHO_CANCELLER_SET_TAIL_LENGTH \
MS_FILTER_METHOD(MSFilterEchoCancellerInterface,2,int)
/** Interface definitions for video decoders */
#define MS_VIDEO_DECODER_DECODING_ERRORS \
MS_FILTER_EVENT_NO_ARG(MSFilterVideoDecoderInterface,0)
/** put filter in bypass mode */
#define MS_ECHO_CANCELLER_SET_BYPASS_MODE \
MS_FILTER_METHOD(MSFilterEchoCancellerInterface,3,bool_t)
......
/*
mediastreamer2 library - modular sound and video processing and streaming
Copyright (C) 2011 Belledonne Communications SARL.
Author: Simon Morlat (simon.morlat@linphone.org)
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 mstonedetector_h
#define mstonedetector_h
#include "mediastreamer2/msfilter.h"
/**
* Structure describing which tone is to be detected.
**/
struct _MSToneDetectorDef{
char tone_name[8];
int frequency; /**<Expected frequency of the tone*/
int min_duration; /**<Min duration of the tone in milliseconds */
float min_amplitude; /**<Minimum amplitude of the tone, 1.0 corresponding to the normalized 0dbm level */
};
typedef struct _MSToneDetectorDef MSToneDetectorDef;
/**
* Structure carried as argument of the MS_TONE_DETECTOR_EVENT
**/
struct _MSToneDetectorEvent{
char tone_name[8];
uint64_t tone_start_time; /**<Tone start time in millisecond */
};
typedef struct _MSToneDetectorEvent MSToneDetectorEvent;
/** Method to as the tone detector filter to monitor a new tone type.*/
#define MS_TONE_DETECTOR_ADD_SCAN MS_FILTER_METHOD(MS_TONE_DETECTOR_ID,0,MSToneDetectorDef)
/** Remove previously added scans*/
#define MS_TONE_DETECTOR_CLEAR_SCANS MS_FILTER_METHOD_NO_ARG(MS_TONE_DETECTOR_ID,1)
/** Event generated when a tone is detected */
#define MS_TONE_DETECTOR_EVENT MS_FILTER_EVENT(MS_TONE_DETECTOR_ID,0,MSToneDetectorEvent)
#endif
......@@ -46,7 +46,8 @@ libmediastreamer_la_SOURCES= mscommon.c \
equalizer.c \
chanadapt.c \
audiomixer.c \
itc.c
itc.c \
tonedetector.c
#dummy c++ file to force libtool to use c++ linking (because of msdscap-mingw.cc)
nodist_EXTRA_libmediastreamer_la_SOURCES = dummy.cxx
......
......@@ -36,6 +36,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define TRAILLING_SILENCE 500 /*ms*/
#endif
static const int default_amplitude=10000;
struct DtmfGenState{
int rate;
int dur;
......@@ -44,6 +46,7 @@ struct DtmfGenState{
float lowfreq;
int nosamples_time;
int silence;
int amplitude;
char dtmf;
};
......@@ -57,6 +60,7 @@ static void dtmfgen_init(MSFilter *f){
s->dtmf=0;
s->nosamples_time=0;
s->silence=0;
s->amplitude=default_amplitude;
f->data=s;
}
......@@ -142,11 +146,24 @@ static int dtmfgen_put(MSFilter *f, void *arg){
s->highfreq=s->highfreq/s->rate;
s->dur=s->rate/10; /*100 ms duration */
s->silence=0;
s->amplitude=default_amplitude;
s->dtmf=dtmf[0];
ms_filter_unlock(f);
return 0;
}
static int dtmfgen_play_tone(MSFilter *f, void *arg){
DtmfGenState *s=(DtmfGenState*)f->data;
MSDtmfGenCustomTone *def=(MSDtmfGenCustomTone*)arg;
s->dur=(s->rate*def->duration)/1000;
s->lowfreq=def->frequency;
s->highfreq=0;
s->silence=0;
s->amplitude=def->amplitude* 0.7*32767.0;
s->dtmf='?';
return 0;
}
static int dtmfgen_start(MSFilter *f, void *arg){
if (dtmfgen_put(f,arg)==0){
DtmfGenState *s=(DtmfGenState*)f->data;
......@@ -178,8 +195,8 @@ static int dtmfgen_set_rate(MSFilter *f, void *arg){
static void write_dtmf(DtmfGenState *s , int16_t *sample, int nsamples){
int i;
for (i=0;i<nsamples && s->pos<s->dur;i++,s->pos++){
sample[i]=(int16_t)(10000.0*sin(2*M_PI*(float)s->pos*s->lowfreq));
sample[i]+=(int16_t)(10000.0*sin(2*M_PI*(float)s->pos*s->highfreq));
sample[i]=(int16_t)(((float)s->amplitude)*sin(2*M_PI*(float)s->pos*s->lowfreq));
if (s->highfreq!=0) sample[i]+=(int16_t)(((float)s->amplitude)*sin(2*M_PI*(float)s->pos*s->highfreq));
}
for (;i<nsamples;++i){
sample[i]=0;
......@@ -233,6 +250,7 @@ MSFilterMethod dtmfgen_methods[]={
{ MS_DTMF_GEN_PLAY , dtmfgen_put },
{ MS_DTMF_GEN_START , dtmfgen_start },
{ MS_DTMF_GEN_STOP , dtmfgen_stop },
{ MS_DTMF_GEN_PLAY_CUSTOM, dtmfgen_play_tone },
{ 0 , NULL }
};
......
......@@ -75,7 +75,7 @@ static bool_t read_event(MSEventQueue *q){
evsize=argsize+16;
data=q->rptr+16;
if (f->notify!=NULL)
f->notify(f->notify_ud,id,argsize>0 ? data : NULL);
f->notify(f->notify_ud,f,id,argsize>0 ? data : NULL);
q->rptr+=evsize;
if (q->rptr>=q->endptr){
q->rptr=q->buffer;
......@@ -121,7 +121,7 @@ void ms_filter_notify(MSFilter *f, unsigned int id, void *arg){
if (f->notify!=NULL){
if (ms_global_event_queue==NULL){
/* synchronous notification */
f->notify(f->notify_ud,id,arg);
f->notify(f->notify_ud,f,id,arg);
}else{
write_event(ms_global_event_queue,f,id,arg);
}
......
......@@ -21,11 +21,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "mediastreamer2/msfilter.h"
#include "mediastreamer2/rfc3984.h"
#include "mediastreamer2/msvideo.h"
#include "mediastreamer2/msticker.h"
#include "ffmpeg-priv.h"
#include "ortp/b64.h"
static uint64_t fpu_last_requested_time=0;
typedef struct _DecData{
mblk_t *yuv_msg;
mblk_t *sps,*pps;
......@@ -130,36 +135,39 @@ static void update_pps(DecData *d, mblk_t *pps){
else d->pps=NULL;
}
static bool_t check_sps_pps_change(DecData *d, mblk_t *sps, mblk_t *pps){
bool_t ret1=FALSE,ret2=FALSE;
static bool_t check_sps_change(DecData *d, mblk_t *sps){
bool_t ret=FALSE;
if (d->sps){
if (sps){
ret1=(msgdsize(sps)!=msgdsize(d->sps)) || (memcmp(d->sps->b_rptr,sps->b_rptr,msgdsize(sps))!=0);
if (ret1) {
update_sps(d,sps);
ms_message("SPS changed !");
update_pps(d,NULL);
}
ret=(msgdsize(sps)!=msgdsize(d->sps)) || (memcmp(d->sps->b_rptr,sps->b_rptr,msgdsize(sps))!=0);
if (ret) {
ms_message("SPS changed ! %i,%i",msgdsize(sps),msgdsize(d->sps));
update_sps(d,sps);
update_pps(d,NULL);
}
}else if (sps) {
} else {
ms_message("Receiving first SPS");
update_sps(d,sps);
}
return ret;
}
static bool_t check_pps_change(DecData *d, mblk_t *pps){
bool_t ret=FALSE;
if (d->pps){
if (pps){
ret2=(msgdsize(pps)!=msgdsize(d->pps)) || (memcmp(d->pps->b_rptr,pps->b_rptr,msgdsize(pps))!=0);
if (ret2) {
ms_message("PPS changed ! %i,%i",msgdsize(pps),msgdsize(d->pps));
update_pps(d,pps);
}
ret=(msgdsize(pps)!=msgdsize(d->pps)) || (memcmp(d->pps->b_rptr,pps->b_rptr,msgdsize(pps))!=0);
if (ret) {
ms_message("PPS changed ! %i,%i",msgdsize(pps),msgdsize(d->pps));
update_pps(d,pps);
}
}else if (pps) {
}else {
ms_message("Receiving first PPS");
update_pps(d,pps);
}
return ret1 || ret2;
return ret;
}
static void enlarge_bitstream(DecData *d, int new_size){
d->bitstream_size=new_size;
d->bitstream=ms_realloc(d->bitstream,d->bitstream_size);
......@@ -184,9 +192,9 @@ static int nalusToFrame(DecData *d, MSQueue *naluq, bool_t *new_sps_pps){
}
nalu_type=(*src) & ((1<<5)-1);
if (nalu_type==7)
*new_sps_pps=check_sps_pps_change(d,im,NULL) || *new_sps_pps;
*new_sps_pps=check_sps_change(d,im) || *new_sps_pps;
if (nalu_type==8)
*new_sps_pps=check_sps_pps_change(d,NULL,im) || *new_sps_pps;
*new_sps_pps=check_pps_change(d,im) || *new_sps_pps;
if (start_picture || nalu_type==7/*SPS*/ || nalu_type==8/*PPS*/ ){
*dst++=0;
start_picture=FALSE;
......@@ -251,6 +259,10 @@ static void dec_process(MSFilter *f){
len=avcodec_decode_video2(&d->av_context,&orig,&got_picture,&pkt);
if (len<=0) {
ms_warning("ms_AVdecoder_process: error %i.",len);
if ((f->ticker->time - fpu_last_requested_time)>5000 || fpu_last_requested_time==0) {
fpu_last_requested_time=f->ticker->time;
ms_filter_notify_no_arg(f,MS_VIDEO_DECODER_DECODING_ERRORS);
}
break;
}
if (got_picture) {
......
/*
mediastreamer2 library - modular sound and video processing and streaming
Copyright (C) 2011 Belledonne Communications SARL.
Author: Simon Morlat (simon.morlat@linphone.org)
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/mstonedetector.h"
#include "mediastreamer2/msticker.h"
#include <math.h>
static const float energy_min=500;
typedef struct _GoertzelState{
float coef;
}GoertzelState;
static void goertzel_state_init(GoertzelState *gs, int frequency, int sampling_frequency){
gs->coef=(float)2*(float)cos(2*M_PI*((float)frequency/(float)sampling_frequency));
}
static float goertzel_state_run(GoertzelState *gs,int16_t *samples, int nsamples, float total_energy){
int i;
float tmp;
float q1=0;
float q2=0;
float freq_en;
for(i=0;i<nsamples;++i){
tmp=q1;
q1=(gs->coef*q1) - q2 + (float)samples[i];
q2=tmp;
}
freq_en= (q1*q1) + (q2*q2) - (q1*q2*gs->coef);
/*return a relative frequency energy compared over the total signal energy */
return freq_en/(total_energy*(float)nsamples*0.5);
}
static float compute_energy(int16_t *samples, int nsamples){
float en=0;
int i;
for(i=0;i<nsamples;++i){
float s=(float)samples[i];
en+=s*s;
}
return en;
}
typedef struct _DetectorState{
MSToneDetectorDef tone_def;
GoertzelState tone_gs;
int dur;
MSBufferizer *buf;
int rate;
int framesize;
int frame_ms;
}DetectorState;
static void detector_init(MSFilter *f){
DetectorState *s=ms_new0(DetectorState,1);
s->buf=ms_bufferizer_new();
s->rate=8000;
s->frame_ms=10;
s->framesize=2*(s->frame_ms*s->rate)/1000;
f->data=s;
}
static void detector_uninit(MSFilter *f){
DetectorState *s=(DetectorState *)f->data;
ms_bufferizer_destroy (s->buf);
ms_free(f->data);
}
static int detector_add_scan(MSFilter *f, void *arg){
DetectorState *s=(DetectorState *)f->data;
MSToneDetectorDef *def=(MSToneDetectorDef*)arg;
s->tone_def=*def;
goertzel_state_init(&s->tone_gs,def->frequency,s->rate);
return 0;
}
static int detector_clear_scans(MSFilter *f, void *arg){
DetectorState *s=(DetectorState *)f->data;
memset(&s->tone_def,0,sizeof(s->tone_def));
return 0;
}
static void detector_process(MSFilter *f){
DetectorState *s=(DetectorState *)f->data;
mblk_t *m;
if (s->tone_def.frequency==0){
/*nothing to do, just bypass*/
while ((m=ms_queue_get(f->inputs[0]))!=NULL)
ms_queue_put(f->outputs[0],m);
}else{
uint8_t *buf=alloca(s->framesize);
ms_bufferizer_put_from_queue (s->buf,f->inputs[0]);
while(ms_bufferizer_read(s->buf,buf,s->framesize)!=0){
float en=compute_energy((int16_t*)buf,s->framesize/2);
if (en>energy_min){
float freq_en=goertzel_state_run(&s->tone_gs,(int16_t*)buf,s->framesize/2,en);
if (freq_en>=s->tone_def.min_amplitude){
s->dur+=s->frame_ms;
if (s->dur>s->tone_def.min_duration){
MSToneDetectorEvent event;
strncpy(event.tone_name,s->tone_def.tone_name,sizeof(event.tone_name));
event.tone_start_time=f->ticker->time;
ms_filter_notify(f,MS_TONE_DETECTOR_EVENT,&event);
}
}else s->dur=0;
}else s->dur=0;
}
}
}
static MSFilterMethod detector_methods[]={
{ MS_TONE_DETECTOR_ADD_SCAN, detector_add_scan },
{ MS_TONE_DETECTOR_CLEAR_SCANS, detector_clear_scans },
{ 0 , NULL }
};
#ifndef _MSC_VER
MSFilterDesc ms_tone_detector_desc={
.id=MS_TONE_DETECTOR_ID,
.name="MSToneDetector",
.category=MS_FILTER_OTHER,
.ninputs=1,
.noutputs=1,
.init=detector_init,
.process=detector_process,
.uninit=detector_uninit,
.methods=detector_methods
};
#else
#error "Tone detector desc not written, fix me"
#endif
MS_FILTER_DESC_EXPORT(ms_tone_detector_desc)
......@@ -25,11 +25,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "mediastreamer2/msfilter.h"
#include "mediastreamer2/msvideo.h"
#include "mediastreamer2/msticker.h"
#include "rfc2429.h"
extern void ms_ffmpeg_check_init();
static uint64_t fpu_last_requested_time=0;
typedef struct DecState{
AVCodecContext av_context;
AVCodec *av_codec;
......@@ -65,6 +69,7 @@ static void dec_init(MSFilter *f, enum CodecID cid){
if (s->av_codec==NULL){
ms_error("Could not find decoder %i!",s->codec);
}
/*
s->av_context.width=MS_VIDEO_SIZE_QCIF_W;
s->av_context.height=MS_VIDEO_SIZE_QCIF_H;
......@@ -668,6 +673,10 @@ static void dec_process_frame(MSFilter *f, mblk_t *inm){
len=avcodec_decode_video2(&s->av_context,&orig,&got_picture,&pkt);
if (len<=0) {
ms_warning("ms_AVdecoder_process: error %i.",len);
if ((f->ticker->time - fpu_last_requested_time)>5000 || fpu_last_requested_time==0) {
fpu_last_requested_time=f->ticker->time;
ms_filter_notify_no_arg(f,MS_VIDEO_DECODER_DECODING_ERRORS);
}
break;
}
if (got_picture) {
......@@ -690,6 +699,7 @@ static void dec_process(MSFilter *f){
}
static MSFilterMethod methods[]={
{ MS_FILTER_ADD_FMTP , dec_add_fmtp },
{ 0 , NULL }
......
......@@ -73,6 +73,14 @@ void video_stream_free (VideoStream * stream)
ms_free (stream);
}
static void event_cb(void *ud, MSFilter* f, unsigned int event, void *eventdata){
ms_message("event_cb called %u", event);
VideoStream *st=(VideoStream*)ud;
if (st->eventcb!=NULL){
st->eventcb(st->event_pointer,f,event,eventdata);
}
}
/*this function must be called from the MSTicker thread:
it replaces one filter by another one.
This is a dirty hack that works anyway.
......@@ -96,7 +104,7 @@ void video_stream_change_decoder(VideoStream *stream, int payload){
ms_filter_link (stream->rtprecv, 0, stream->decoder, 0);
ms_filter_link (stream->decoder,0 , stream->output, 0);
ms_filter_preprocess(stream->decoder,stream->ticker);
ms_filter_set_notify_callback(dec, event_cb, stream);
}else{
ms_warning("No decoder found for %s",pt->mime_type);
}
......@@ -223,6 +231,11 @@ void video_stream_set_render_callback (VideoStream *s, VideoStreamRenderCallback
s->render_pointer=user_pointer;
}
void video_stream_set_event_callback (VideoStream *s, VideoStreamEventCallback cb, void *user_pointer){
s->eventcb=cb;
s->event_pointer=user_pointer;
}
void video_stream_set_display_filter_name(VideoStream *s, const char *fname){
if (s->display_name!=NULL){
ms_free(s->display_name);
......@@ -232,7 +245,8 @@ void video_stream_set_display_filter_name(VideoStream *s, const char *fname){
s->display_name=ms_strdup(fname);
}
static void ext_display_cb(void *ud, unsigned int event, void *eventdata){
static void ext_display_cb(void *ud, MSFilter* f, unsigned int event, void *eventdata){
MSExtDisplayOutput *output=(MSExtDisplayOutput*)eventdata;
VideoStream *st=(VideoStream*)ud;
if (st->rendercb!=NULL){
......@@ -373,6 +387,8 @@ int video_stream_start (VideoStream *stream, RtpProfile *profile, const char *re
ms_error("videostream.c: No decoder available for payload %i:%s.",payload,pt->mime_type);
return -1;
}
ms_filter_set_notify_callback(stream->decoder, event_cb, stream);
stream->rtprecv = ms_filter_new (MS_RTP_RECV_ID);
ms_filter_call_method(stream->rtprecv,MS_RTP_RECV_SET_SESSION,stream->session);
......@@ -383,7 +399,7 @@ int video_stream_start (VideoStream *stream, RtpProfile *profile, const char *re
if (stream->rendercb!=NULL){
stream->output=ms_filter_new(MS_EXT_DISPLAY_ID);
ms_filter_set_notify_callback (stream->output,ext_display_cb,stream);
ms_filter_set_notify_callback(stream->output,ext_display_cb,stream);
}else{
stream->output=ms_filter_new_from_name (stream->display_name);
}
......@@ -472,6 +488,8 @@ void video_stream_send_vfu(VideoStream *stream){
void
video_stream_stop (VideoStream * stream)
{
stream->eventcb = NULL;
stream->event_pointer = NULL;
if (stream->ticker){
if (stream->source)
ms_ticker_detach(stream->ticker,stream->source);
......
if BUILD_TESTS
noinst_PROGRAMS=echo ring mtudiscover bench
noinst_PROGRAMS=echo ring mtudiscover bench tones
if BUILD_VIDEO
noinst_PROGRAMS+=videodisplay test_x11window
......@@ -14,6 +14,7 @@ videodisplay_SOURCES=videodisplay.c
mtudiscover_SOURCES=mtudiscover.c
bench_SOURCES=bench.c
test_x11window_SOURCES=test_x11window.c
tones_SOURCES=tones.c
libexec_PROGRAMS=mediastream
......
/*
mediastreamer2 library - modular sound and video processing and streaming
Copyright (C) 2011 Belledonne Communications SARL.
Author: Simon Morlat (simon.morlat@linphone.org)
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/mstonedetector.h"
#include "mediastreamer2/msfilerec.h"
#include "mediastreamer2/dtmfgen.h"
#include "mediastreamer2/msticker.h"
static void tone_detected_cb(void *data, MSToneDetectorEvent *ev){
ms_message("Tone detected !");
}
int main(int argc, char *argv[]){
MSFilter *src, *gen, *det, *rec;
MSTicker *ticker;
ms_init();
src=ms_filter_new(MS_FILE_PLAYER_ID);
rec=ms_filter_new(MS_FILE_REC_ID);
gen=ms_filter_new(MS_DTMF_GEN_ID);
det=ms_filter_new(MS_TONE_DETECTOR_ID);
ms_filter_link(src,0,gen,0);
ms_filter_link(gen,0,det,0);
ms_filter_link(det,0,rec,0);
ticker=ms_ticker_new();
ms_ticker_attach(ticker,src);
ms_filter_call_method(rec,MS_FILE_REC_OPEN,"/tmp/output.wav");
ms_filter_call_method_noarg(rec,MS_FILE_REC_START);
{
/*generate and detect the tones*/
MSDtmfGenCustomTone tone;
MSToneDetectorDef expected_tone;
tone.frequency=2000;
tone.duration=400;
tone.amplitude=0.6;
expected_tone.frequency=2000;
expected_tone.min_duration=200;
expected_tone.min_amplitude=0.5;
ms_filter_set_notify_callback (det,(MSFilterNotifyFunc)tone_detected_cb,NULL);
ms_filter_call_method(det,MS_TONE_DETECTOR_ADD_SCAN,&expected_tone);
ms_filter_call_method(gen,MS_DTMF_GEN_PLAY_CUSTOM,&tone);
sleep(1);
ms_filter_call_method(gen,MS_DTMF_GEN_PLAY_CUSTOM,&tone);
sleep(1);
ms_filter_call_method(gen,MS_DTMF_GEN_PLAY_CUSTOM,&tone);
sleep(1);
}
ms_ticker_detach(ticker,src);