From 2e28833e885e69e5aca81fad76d462c4679e57e9 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Wed, 7 Jun 2006 15:29:59 +0000 Subject: [PATCH] * fixes timestamp overflow problem after about 7 days. this would have cause SEMS to stop send any packets after about 7 days. * adds a simple playout buffer for application which do not need adaptive playout (voicemail, annoucement, ...). git-svn-id: http://svn.berlios.de/svnroot/repos/sems/trunk@51 8eb893ce-cfd4-0310-b710-fb5ebe64c474 --- core/AmPlayoutBuffer.cpp | 48 ++++++++++++++++++++++---- core/AmPlayoutBuffer.h | 30 +++++++++++----- core/AmRtpAudio.cpp | 68 ++++++++++++++++++++++++++++++++----- core/AmRtpAudio.h | 14 ++++++-- core/AmSessionScheduler.cpp | 5 +-- 5 files changed, 137 insertions(+), 28 deletions(-) diff --git a/core/AmPlayoutBuffer.cpp b/core/AmPlayoutBuffer.cpp index d4e3835c..b5de8198 100644 --- a/core/AmPlayoutBuffer.cpp +++ b/core/AmPlayoutBuffer.cpp @@ -1,4 +1,6 @@ #include "AmPlayoutBuffer.h" +#include "AmAudio.h" + #define PACKET_SAMPLES 160 #define PACKET_SIZE (PACKET_SAMPLES<<1) @@ -16,7 +18,41 @@ #define PI 3.14 + AmPlayoutBuffer::AmPlayoutBuffer() + : r_ts(0),w_ts(0) +{ +} + +void AmPlayoutBuffer::direct_write(unsigned int ts, ShortSample* buf, unsigned int len) +{ + buffer_put(w_ts,buf,len); +} + +void AmPlayoutBuffer::write(u_int32_t ref_ts, u_int32_t ts, int16_t* buf, u_int32_t len) +{ + buffer_put(w_ts,buf,len); +} + +u_int32_t AmPlayoutBuffer::read(u_int32_t ts, int16_t* buf, u_int32_t len) +{ + if(ts_less()(r_ts,w_ts)){ + + u_int32_t rlen=0; + if(ts_less()(r_ts+PCM16_B2S(AUDIO_BUFFER_SIZE),w_ts)) + rlen = PCM16_B2S(AUDIO_BUFFER_SIZE); + else + rlen = w_ts - r_ts; + + buffer_get(r_ts,buf,rlen); + return rlen; + } + + return 0; +} + + +AmAdaptivePlayout::AmAdaptivePlayout() : idx(0), loss_rate(ORDER_STAT_LOSS_RATE), wsola_off(WSOLA_START_OFF), @@ -27,7 +63,7 @@ AmPlayoutBuffer::AmPlayoutBuffer() memset(n_stat,0,sizeof(int32_t)*ORDER_STAT_WIN_SIZE); } -u_int32_t AmPlayoutBuffer::next_delay(u_int32_t ref_ts, u_int32_t ts) +u_int32_t AmAdaptivePlayout::next_delay(u_int32_t ref_ts, u_int32_t ts) { int32_t n = (int32_t)(ref_ts - ts); @@ -84,8 +120,8 @@ u_int32_t AmPlayoutBuffer::next_delay(u_int32_t ref_ts, u_int32_t ts) return D; } -void AmPlayoutBuffer::write(u_int32_t ref_ts, u_int32_t ts, - int16_t* buf, u_int32_t len) +void AmAdaptivePlayout::write(u_int32_t ref_ts, u_int32_t ts, + int16_t* buf, u_int32_t len) { u_int32_t p_delay = next_delay(ref_ts,ts); @@ -152,7 +188,7 @@ void AmPlayoutBuffer::write(u_int32_t ref_ts, u_int32_t ts, short_scaled.push(100.0); } -u_int32_t AmPlayoutBuffer::read(u_int32_t ts, int16_t* buf, u_int32_t len) +u_int32_t AmAdaptivePlayout::read(u_int32_t ts, int16_t* buf, u_int32_t len) { bool do_plc=false; @@ -190,7 +226,7 @@ u_int32_t AmPlayoutBuffer::read(u_int32_t ts, int16_t* buf, u_int32_t len) return len; } -void AmPlayoutBuffer::direct_write(unsigned int ts, ShortSample* buf, unsigned int len) +void AmAdaptivePlayout::direct_write(unsigned int ts, ShortSample* buf, unsigned int len) { buffer_put(ts+wsola_off,buf,len); } @@ -234,7 +270,7 @@ short* find_best_corr(short *ts, short *sr_beg,short* sr_end) return best_sr; } -unsigned int AmPlayoutBuffer::time_scale(unsigned int ts, float factor) +unsigned int AmAdaptivePlayout::time_scale(unsigned int ts, float factor) { short p_buf[PACKET_SAMPLES*4]; short merge_buf[TEMPLATE_SEG]; diff --git a/core/AmPlayoutBuffer.h b/core/AmPlayoutBuffer.h index f38b0139..b20fbacd 100644 --- a/core/AmPlayoutBuffer.h +++ b/core/AmPlayoutBuffer.h @@ -18,6 +18,26 @@ using std::multiset; #define WSOLA_SCALED_WIN 50 class AmPlayoutBuffer +{ + // Playout buffer + SampleArrayShort buffer; + +protected: + u_int32_t r_ts,w_ts; + + void buffer_put(unsigned int ts, ShortSample* buf, unsigned int len); + void buffer_get(unsigned int ts, ShortSample* buf, unsigned int len); + +public: + AmPlayoutBuffer(); + virtual ~AmPlayoutBuffer() {} + + virtual void direct_write(unsigned int ts, ShortSample* buf, unsigned int len); + virtual void write(u_int32_t ref_ts, u_int32_t ts, int16_t* buf, u_int32_t len); + virtual u_int32_t read(u_int32_t ts, int16_t* buf, u_int32_t len); +}; + +class AmAdaptivePlayout: public AmPlayoutBuffer { // Order statistics delay estimation multiset o_stat; @@ -34,18 +54,12 @@ class AmPlayoutBuffer int plc_cnt; LowcFE fec; - // Playout buffer - SampleArrayShort buffer; - u_int32_t r_ts,w_ts; - - void buffer_put(unsigned int ts, ShortSample* buf, unsigned int len); - void buffer_get(unsigned int ts, ShortSample* buf, unsigned int len); - u_int32_t time_scale(u_int32_t ts, float factor); u_int32_t next_delay(u_int32_t ref_ts, u_int32_t ts); public: - AmPlayoutBuffer(); + + AmAdaptivePlayout(); void direct_write(unsigned int ts, ShortSample* buf, unsigned int len); diff --git a/core/AmRtpAudio.cpp b/core/AmRtpAudio.cpp index 2a296754..8bbf8529 100644 --- a/core/AmRtpAudio.cpp +++ b/core/AmRtpAudio.cpp @@ -32,10 +32,36 @@ AmRtpAudio::AmRtpAudio(AmSession* _s) : AmRtpStream(_s), AmAudio(0), last_ts_i(false), use_default_plc(true), - send_only(false) + send_only(false), playout_buffer(new AmPlayoutBuffer()), + last_check(0),last_check_i(false),send_int(false) { } +bool AmRtpAudio::checkInterval(unsigned int ts) +{ + if(!last_check_i){ + send_int = true; + last_check_i = true; + last_check = ts; + } + else { + if((ts - last_check) >= getFrameSize()){ + send_int = true; + last_check = ts; + } + else { + send_int = false; + } + } + + return send_int; +} + +bool AmRtpAudio::sendIntReached() +{ + return send_int; +} + /* @param audio_buffer_ts [in] the current ts in the audio buffer */ @@ -67,9 +93,9 @@ int AmRtpAudio::receive(unsigned int audio_buffer_ts) int l_size = conceal_loss(ts - last_ts); if(l_size>0){ - playout_buffer.direct_write(last_ts, - (ShortSample*)samples.back_buffer(), - PCM16_B2S(l_size)); + playout_buffer->direct_write(last_ts, + (ShortSample*)samples.back_buffer(), + PCM16_B2S(l_size)); } } @@ -82,9 +108,9 @@ int AmRtpAudio::receive(unsigned int audio_buffer_ts) if(use_default_plc) add_to_history(size); - playout_buffer.write(audio_buffer_ts, ts, - (ShortSample*)((unsigned char*)samples), - PCM16_B2S(size)); + playout_buffer->write(audio_buffer_ts, ts, + (ShortSample*)((unsigned char*)samples), + PCM16_B2S(size)); last_ts = ts + PCM16_B2S(size); } @@ -101,8 +127,13 @@ int AmRtpAudio::get(unsigned int user_ts, unsigned char* buffer, unsigned int nb int AmRtpAudio::read(unsigned int user_ts, unsigned int size) { - playout_buffer.read(user_ts,(ShortSample*)((unsigned char*)samples),PCM16_B2S(size)); - return size; + u_int32_t rlen = + playout_buffer + ->read(user_ts, + (ShortSample*)((unsigned char*)samples), + PCM16_B2S(size)); + + return PCM16_S2B(rlen); } int AmRtpAudio::write(unsigned int user_ts, unsigned int size) @@ -170,3 +201,22 @@ void AmRtpAudio::add_to_history(unsigned int size) buf_offset += FRAMESZ; } } + +void AmRtpAudio::setAdaptivePlayout(bool on) +{ + bool is_adaptive = + dynamic_cast + (playout_buffer.get()) != 0; + + if(on == !is_adaptive){ + + if(is_adaptive){ + playout_buffer.reset(new AmAdaptivePlayout()); + DBG("Adaptive playout buffer activated\n"); + } + else{ + playout_buffer.reset(new AmPlayoutBuffer()); + DBG("Adaptive playout buffer deactivated\n"); + } + } +} diff --git a/core/AmRtpAudio.h b/core/AmRtpAudio.h index 1903ce7b..dff38842 100644 --- a/core/AmRtpAudio.h +++ b/core/AmRtpAudio.h @@ -31,7 +31,6 @@ #include "AmAudio.h" #include "AmRtpStream.h" #include "AmPlayoutBuffer.h" -//#include "SampleArray.h" #include "LowcFE.h" // Maximum value: AUDIO_BUFFER_SIZE / 2 @@ -40,12 +39,15 @@ class AmRtpAudio: public AmRtpStream, public AmAudio { - //SampleArrayShort timed_buffer; - AmPlayoutBuffer playout_buffer; + auto_ptr playout_buffer; LowcFE fec; bool use_default_plc; + unsigned int last_check; + bool last_check_i; + bool send_int; + unsigned int last_ts; bool last_ts_i; @@ -67,6 +69,10 @@ class AmRtpAudio: public AmRtpStream, public AmAudio public: AmRtpAudio(AmSession* _s=0); + + bool checkInterval(unsigned int ts); + bool sendIntReached(); + int receive(unsigned int audio_buffer_ts); void setSendOnly(bool so){ @@ -82,6 +88,8 @@ public: // AmRtpStream interface void init(const SdpPayload* sdp_payload); + + void setAdaptivePlayout(bool on); }; #endif diff --git a/core/AmSessionScheduler.cpp b/core/AmSessionScheduler.cpp index 883dc8db..2f58070d 100644 --- a/core/AmSessionScheduler.cpp +++ b/core/AmSessionScheduler.cpp @@ -215,8 +215,9 @@ void AmSessionSchedulerThread::processAudio(unsigned int ts) s->lockAudio(); AmAudio* input = s->getInput(); - if(!(ts % s->rtp_str.getFrameSize())){ + if(s->rtp_str.checkInterval(ts)){ + DBG("ts = %u\n",ts); int ret = s->rtp_str.receive(ts); if(ret < 0){ switch(ret){ @@ -259,7 +260,7 @@ void AmSessionSchedulerThread::processAudio(unsigned int ts) s->lockAudio(); AmAudio* output = s->getOutput(); - if(output && !(ts % s->rtp_str.getFrameSize())){ + if(s->rtp_str.sendIntReached()){ int size = output->get(ts,buffer,s->rtp_str.getFrameSize()); if(size <= 0){