Commit 4cab06ab authored by Emmanuel Milou's avatar Emmanuel Milou
Browse files

Codecs no longer loaded at each frame.

The codecs are loaded at the initialization of the rtp session and destroyed at the end.
GSM audio quality is far better now. Because the dynamic library had to load at every 20ms the libgsm, it introduced a delay at each frame
parent 03cc5544
......@@ -31,7 +31,7 @@ endif
#SUBDIRS = gsm
libaudio_la_SOURCES = audiofile.cpp tonelist.cpp \
libaudio_la_SOURCES = audiofile.cpp tonelist.cpp \
audiortp.cpp dtmf.cpp tone.cpp audiolayer.cpp audiodevice.cpp dtmfgenerator.cpp \
tonegenerator.cpp codecDescriptor.cpp \
audioloop.cpp ringbuffer.cpp $(SPEEX_SOURCES_CPP)
......@@ -40,7 +40,7 @@ AM_CXXFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/libs $(libccext2_CFLAGS) $
-DCODECS_DIR=\""$(sflcodecdir)"\"
libaudio_la_CPPFLAGS = $(SPEEX_FLAG)
noinst_HEADERS = audioloop.h common.h ringbuffer.h audiofile.h \
noinst_HEADERS = audioloop.h common.h ringbuffer.h audiofile.h \
tonelist.h audiortp.h audiocodec.h audiolayer.h audiodevice.h \
dtmfgenerator.h tonegenerator.h \
codecDescriptor.h dtmf.h tone.h \
......@@ -63,8 +63,8 @@ uninstall-libcodec_ulaw_so:
rm -f $(sflcodecdir)/libcodec_ulaw.so
uninstall-libcodec_alaw_so:
rm -f $(sflcodecdir)/libcodec_alaw.so
#uninstall-libcodec_gsm_so:
# rm -f $(sflcodecdir)/libcodec_gsm.so
uninstall-libcodec_gsm_so:
rm -f $(sflcodecdir)/libcodec_gsm.so
uninstall-libcodec_speex_so:
rm -f $(sflcodecdir)/libcodec_speex.so
rm -rf $(sflcodecdir)
......@@ -17,7 +17,6 @@ protected:
unsigned int _channel;
private:
//bool _active;
int _payload;
bool _hasDynamicPayload;
......@@ -27,14 +26,13 @@ public:
_payload = payload;
_clockRate = 8000; // default
_channel = 1; // default
// _active = false;
_hasDynamicPayload = (_payload >= 96 && _payload <= 127) ? true : false;
}
virtual ~AudioCodec() {}
virtual ~AudioCodec() {
}
/**
* @return the number of bytes decoded
*/
......@@ -48,8 +46,6 @@ public:
bool hasDynamicPayload() { return _hasDynamicPayload; }
unsigned int getClockRate() { return _clockRate; }
unsigned int getChannel() { return _channel; }
//bool isActive() { return _active; }
//void setActive(bool active) { _active = active; }
};
......
......@@ -182,8 +182,7 @@ AudioRtpRTX::initAudioRtpSession (void)
try {
if (_ca == 0) { return; }
AudioCodec* audiocodec = loadCodec(_ca->getAudioCodec());
_codecSampleRate = audiocodec->getClockRate();
_codecSampleRate = _audiocodec->getClockRate();
_debug("Init audio RTP session\n");
ost::InetHostAddress remote_ip(_ca->getRemoteIp().c_str());
......@@ -215,12 +214,12 @@ AudioRtpRTX::initAudioRtpSession (void)
}
bool payloadIsSet = false;
if (audiocodec) {
if (audiocodec->hasDynamicPayload()) {
payloadIsSet = _sessionRecv->setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) audiocodec->getPayload(), audiocodec->getClockRate()));
if (_audiocodec) {
if (_audiocodec->hasDynamicPayload()) {
payloadIsSet = _sessionRecv->setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) _audiocodec->getPayload(), _audiocodec->getClockRate()));
} else {
payloadIsSet= _sessionRecv->setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) audiocodec->getPayload()));
payloadIsSet = _sessionSend->setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) audiocodec->getPayload()));
payloadIsSet= _sessionRecv->setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) _audiocodec->getPayload()));
payloadIsSet = _sessionSend->setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) _audiocodec->getPayload()));
}
}
_sessionSend->setMark(true);
......@@ -233,22 +232,21 @@ AudioRtpRTX::initAudioRtpSession (void)
}
bool payloadIsSet = false;
if (audiocodec) {
if (audiocodec->hasDynamicPayload()) {
payloadIsSet = _session->setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) audiocodec->getPayload(), audiocodec->getClockRate()));
if (_audiocodec) {
if (_audiocodec->hasDynamicPayload()) {
payloadIsSet = _session->setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) _audiocodec->getPayload(), _audiocodec->getClockRate()));
} else {
payloadIsSet = _session->setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) audiocodec->getPayload()));
payloadIsSet = _session->setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) _audiocodec->getPayload()));
}
}
}
unloadCodec(audiocodec);
} catch(...) {
_debugException("! ARTP Failure: initialisation failed");
throw;
}
}
AudioCodec*
void
AudioRtpRTX::loadCodec(int payload)
{
using std::cerr;
......@@ -280,11 +278,12 @@ AudioRtpRTX::loadCodec(int payload)
if(dlsym_error){
cerr << "Cannot load symbol create: " << dlsym_error << '\n';
}
return create_codec();
_audiocodec = create_codec();
}
void
AudioRtpRTX::unloadCodec(AudioCodec* audiocodec)
AudioRtpRTX::unloadCodec()
{
using std::cerr;
destroy_t* destroy_codec = (destroy_t*)dlsym(handle_codec, "destroy");
......@@ -292,7 +291,7 @@ AudioRtpRTX::unloadCodec(AudioCodec* audiocodec)
if(dlsym_error){
cerr << "Cannot load symbol destroy" << dlsym_error << '\n';
}
destroy_codec(audiocodec);
destroy_codec(_audiocodec);
dlclose(handle_codec);
}
......@@ -300,7 +299,6 @@ AudioRtpRTX::unloadCodec(AudioCodec* audiocodec)
void
AudioRtpRTX::sendSessionFromMic(int timestamp)
{
AudioCodec* audiocodec = loadCodec(_ca->getAudioCodec());
// STEP:
// 1. get data from mic
// 2. convert it to int16 - good sample, good rate
......@@ -314,8 +312,7 @@ try {
AudioLayer* audiolayer = Manager::instance().getAudioDriver();
if (!audiolayer) { _debug(" !ARTP: No audiolayer available for mic\n"); return; }
//AudioCodec* audiocodec = _ca->getAudioCodec();
if (!audiocodec) { _debug(" !ARTP: No audiocodec available for mic\n"); return; }
if (!_audiocodec) { _debug(" !ARTP: No audiocodec available for mic\n"); return; }
// we have to get 20ms of data from the mic *20/1000 = /50
int maxBytesToGet = _layerSampleRate * _layerFrameSize * sizeof(SFLDataFormat) / 1000;
......@@ -324,13 +321,12 @@ try {
// take the lowest
int bytesAvail = (availBytesFromMic < maxBytesToGet) ? availBytesFromMic : maxBytesToGet;
//printf("clock rate = %i\n", audiocodec->getClockRate());
// Get bytes from micRingBuffer to data_from_mic
int nbSample = audiolayer->getMic(_dataAudioLayer, bytesAvail) / sizeof(SFLDataFormat);
int nb_sample_up = nbSample;
int nbSamplesMax = _layerFrameSize * audiocodec->getClockRate() / 1000;
int nbSamplesMax = _layerFrameSize * _audiocodec->getClockRate() / 1000;
nbSample = reSampleData(audiocodec->getClockRate(), nb_sample_up, DOWN_SAMPLING);
nbSample = reSampleData(_audiocodec->getClockRate(), nb_sample_up, DOWN_SAMPLING);
toSIP = _intBufferDown;
......@@ -344,8 +340,7 @@ try {
//_debug("AR: Nb sample: %d int, [0]=%d [1]=%d [2]=%d\n", nbSample, toSIP[0], toSIP[1], toSIP[2]);
// for the mono: range = 0 to RTP_FRAME2SEND * sizeof(int16)
// codecEncode(char *dest, int16* src, size in bytes of the src)
//int compSize = audiocodec->codecEncode(_sendDataEncoded, toSIP, nbSample*sizeof(int16));
int compSize = audiocodec->codecEncode(_sendDataEncoded, toSIP, nbSample*sizeof(int16));
int compSize = _audiocodec->codecEncode(_sendDataEncoded, toSIP, nbSample*sizeof(int16));
//printf("jusqu'ici tout vas bien\n");
// encode divise by two
......@@ -361,7 +356,6 @@ try {
_debugException("! ARTP: sending failed");
throw;
}
unloadCodec(audiocodec);
}
......@@ -370,7 +364,6 @@ void
AudioRtpRTX::receiveSessionForSpkr (int& countTime)
{
AudioCodec* audiocodec;
if (_ca == 0) { return; }
try {
......@@ -393,11 +386,11 @@ try {
int payload = adu->getType(); // codec type
unsigned char* data = (unsigned char*)adu->getData(); // data in char
unsigned int size = adu->getSize(); // size in char
//_fstream.write((char*) data, size);
audiocodec = loadCodec(payload);
// Decode data with relevant codec
_codecSampleRate = audiocodec->getClockRate();
_codecSampleRate = _audiocodec->getClockRate();
int max = (int)(_codecSampleRate * _layerFrameSize / 1000);
if ( size > max ) {
......@@ -408,9 +401,10 @@ try {
//printf("size = %i\n", size);
if (audiocodec != NULL) {
int expandedSize = audiocodec->codecDecode(_receiveDataDecoded, data, size);
_fstream.write((char*) _receiveDataDecoded, 160);
if (_audiocodec != NULL) {
int expandedSize = _audiocodec->codecDecode(_receiveDataDecoded, data, size);
//_fstream.write((char*) _receiveDataDecoded, );
//buffer _receiveDataDecoded ----> short int or int16, coded on 2 bytes
int nbInt16 = expandedSize / sizeof(int16);
//nbInt16 represents the number of samples we just decoded
......@@ -453,7 +447,6 @@ try {
throw;
}
unloadCodec(audiocodec);
}
......@@ -530,6 +523,7 @@ _layerFrameSize = audiolayer->getFrameSize(); // en ms
_layerSampleRate = audiolayer->getSampleRate();
initBuffers();
int step;
loadCodec(_ca->getAudioCodec());
try {
// Init the session
......@@ -568,6 +562,7 @@ try {
TimerPort::incTimer(_layerFrameSize); // 'frameSize' ms
}
_fstream.close();
unloadCodec();
//_debug("stop stream for audiortp loop\n");
audiolayer->stopStream();
} catch(std::exception &e) {
......
......@@ -123,19 +123,22 @@ class AudioRtpRTX : public ost::Thread, public ost::TimerPort {
/** Pointer on function to handle codecs **/
void* handle_codec;
AudioCodec* _audiocodec;
/**
* Load dynamically a codec (.so library)
* @param payload The payload of the codec you want to load
* @return AudioCodec* A pointer on a audio codec object
*/
AudioCodec* loadCodec(int payload);
void loadCodec(int payload);
/**
* Destroy and close dynamically a codec (.so library)
* @param audiocodec The audio codec you want to unload
*/
void unloadCodec(AudioCodec* audiocodec);
void unloadCodec(void);
};
///////////////////////////////////////////////////////////////////////////////
......
/**
* Copyright (C) 2004-2005 Savoir-Faire Linux inc.
/*
* Copyright (C) 2004-2005-2006 Savoir-Faire Linux inc.
* Author: Yan Morin <yan.morin@savoirfairelinux.com>
* Author: Laurielle Lea <laurielle.lea@savoirfairelinux.com>
* Author: Laurielle Lea <laurielle.lea@savoirfairelinux.com>
*
* 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
......@@ -15,107 +15,58 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <iostream>
extern "C" {
#include <gsm/gsm.h>
}
#include "audiocodec.h"
#include "../global.h"
#define GSM_PACKED_FRAME_SIZE_IN_BYTES 33
#define GSM_UNPACKED_FRAME_SIZE_IN_BYTES 320
#define GSM_UNPACKED_FRAME_SIZE_IN_SHORTS 160
/*
void * GSMCodecHandle = 0;
#include "audiocodec.h"
extern "C"{
#include <gsm.h>
}
void* (*gsm_session_create)() = 0;
void (*gsm_session_destroy)(void *) = 0;
void (*gsm_session_encode)(void*, unsigned char*, short*) = 0 ;
int (*gsm_session_decode)(void*, short* , unsigned char*) = 0 ;
*/
/**
* GSM audio codec C++ class (over gsm/gsm.h)
*/
class Gsm : public AudioCodec {
public:
// 3 GSM A 8000 1 [RFC3551]
Gsm(int payload = 0)
: AudioCodec(payload, "GSM")
{
_clockRate = 8000;
_channel = 1;
//initGSMStruct();
if (!(_decode_gsmhandle = gsm_create() ))
_debug("ERROR: decode_gsm_create\n");
if (!(_encode_gsmhandle = gsm_create() ))
_debug("AudioCodec: ERROR: encode_gsm_create\n");
// _payload should be 3
Gsm (int payload=3): AudioCodec(payload, "GSM"){
_clockRate = 8000;
_channel = 1;
if (!(_decode_gsmhandle = gsm_create() ))
printf("ERROR: decode_gsm_create\n");
if (!(_encode_gsmhandle = gsm_create() ))
printf("AudioCodec: ERROR: encode_gsm_create\n");
}
//_encode_state = gsm_session_create();
//_decode_state = gsm_session_create();
}
~Gsm (void)
{
//gsm_session_destroy(_decode_state);
//gsm_session_destroy(_encode_state);
gsm_destroy(_decode_gsmhandle);
gsm_destroy(_encode_gsmhandle);
}
/*
bool initGSMStruct()
{
if(GSMCodecHandle) return true;
GSMCodecHandle = dlopen("libgsm.so", RTLD_NOW | RTLD_GLOBAL);
if(!GSMCodecHandle) return false;
gsm_session_create = (void * (*)()) dlsym(GSMCodecHandle, "gsm_create");
gsm_session_destroy = (void (*) (void *)) dlsym(GSMCodecHandle, "gsm_destroy");
gsm_session_encode = ( void (*) (void*, unsigned char*, short*)) dlsym(GSMCodecHandle, "gsm_encode");
gsm_session_decode = (int (*) (void*, short*, unsigned char*)) dlsym(GSMCodecHandle, "gsm_decode");
if(!(gsm_session_create && gsm_session_destroy && gsm_session_encode && gsm_session_decode)){
dlclose(GSMCodecHandle);
GSMCodecHandle = 0 ;
return false;}
return true;
}*/
virtual int codecDecode (short *dst, unsigned char *src, unsigned int size)
{
if(gsm_decode(_decode_gsmhandle, (gsm_byte *)src, (gsm_signal*)dst) < 0)
return 0;
return GSM_UNPACKED_FRAME_SIZE_IN_BYTES;
}
virtual int codecEncode (unsigned char *dst, short *src, unsigned int size)
{
if(size < GSM_UNPACKED_FRAME_SIZE_IN_BYTES) return 0;
//if (gsm_session_encode( gsm_signal*)src, (gsm_byte*)dst);
gsm_encode( _encode_gsmhandle, (gsm_signal*)src, (gsm_byte*) dst);
return GSM_PACKED_FRAME_SIZE_IN_BYTES;
}
virtual ~Gsm (void){
gsm_destroy(_decode_gsmhandle);
gsm_destroy(_encode_gsmhandle);
}
virtual int codecDecode (short * dst, unsigned char * src, unsigned int size){
(void)size;
if(gsm_decode(_decode_gsmhandle, (gsm_byte*)src, (gsm_signal*)dst) < 0)
printf("ERROR: gsm_decode\n");
return 320;
}
virtual int codecEncode (unsigned char * dst, short * src, unsigned int size){
(void)size;
gsm_encode(_encode_gsmhandle, (gsm_signal*)src, (gsm_byte*) dst);
return 33;
}
private:
gsm _decode_gsmhandle;
gsm _encode_gsmhandle;
//void * _encode_state;
//void * _decode_state;
gsm _decode_gsmhandle;
gsm _encode_gsmhandle;
};
// the class factories
extern "C" AudioCodec* create() {
return new Gsm(3);
extern "C" AudioCodec* create(){
return new Gsm(3);
}
extern "C" void destroy(AudioCodec* a) {
delete a;
extern "C" void destroy(AudioCodec* a){
delete a;
}
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