* 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
sayer/1.4-spce2.6
Raphael Coeffic 20 years ago
parent 385b7ca541
commit 2e28833e88

@ -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];

@ -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<int32_t> 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);

@ -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<AmAdaptivePlayout*>
(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");
}
}
}

@ -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<AmPlayoutBuffer> 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

@ -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){

Loading…
Cancel
Save