Commit 93fc9bd9 authored by Emmanuel Milou's avatar Emmanuel Milou
Browse files

Dynamic loading of audio codecs

Note: Manually copy the .so library in /usr/lib , then ldconfig
parent 1319d055
......@@ -12,9 +12,9 @@ SPEEX_FLAG=
SPEEX_LIB=
endif
libaudio_la_SOURCES = audiofile.cpp g711.cpp tonelist.cpp \
libaudio_la_SOURCES = audiofile.cpp tonelist.cpp \
audiortp.cpp dtmf.cpp tone.cpp audiolayer.cpp audiodevice.cpp dtmfgenerator.cpp gsmcodec.cpp \
tonegenerator.cpp ulaw.cpp codecDescriptor.cpp \
tonegenerator.cpp codecDescriptor.cpp \
audioloop.cpp ringbuffer.cpp $(SPEEX_SOURCES_CPP)
AM_CXXFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/libs $(libccext2_CFLAGS) $(libdbuscpp_CFLAGS) $(libccrtp1_CFLAGS) $(USER_INCLUDES)
......@@ -22,8 +22,8 @@ AM_CXXFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/libs $(libccext2_CFLAGS) $
libaudio_la_CPPFLAGS = $(SPEEX_FLAG)
noinst_HEADERS = audioloop.h common.h ringbuffer.h audiofile.h g711.h \
noinst_HEADERS = audioloop.h common.h ringbuffer.h audiofile.h \
tonelist.h audiortp.h audiocodec.h audiolayer.h audiodevice.h \
dtmfgenerator.h gsmcodec.h tonegenerator.h ulaw.h \
dtmfgenerator.h gsmcodec.h tonegenerator.h \
codecDescriptor.h dtmf.h tone.h \
CodecSpeex.h
......@@ -76,10 +76,6 @@ virtual int codecEncode (unsigned char *dst, short *src, unsigned int size)
return size;
}
virtual void test()
{
printf("MON OSTIE ALAW!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
}
uint8 ALawEncode (int16 pcm16)
{
......@@ -124,11 +120,11 @@ uint8 ALawEncode (int16 pcm16)
};
// the class factories
extern "C" AudioCodec* create_alaw() {
extern "C" AudioCodec* create() {
return new Alaw();
}
extern "C" void destroy_alaw(AudioCodec* a) {
extern "C" void destroy(AudioCodec* a) {
delete a;
}
......@@ -3,6 +3,7 @@
#include <string>
#include <iostream>
#include <dlfcn.h>
class AudioCodec {
protected:
......@@ -41,7 +42,6 @@ public:
*/
virtual int codecDecode(short *, unsigned char *, unsigned int) = 0;
virtual int codecEncode(unsigned char *, short *, unsigned int) = 0;
virtual void test()=0;
/** Returns description for GUI usage */
std::string getDescription() { return _description; }
......@@ -53,6 +53,7 @@ public:
unsigned int getChannel() { return _channel; }
bool isActive() { return _active; }
void setActive(bool active) { _active = active; }
};
......
......@@ -25,20 +25,40 @@
#include <fstream>
#include <math.h>
#include <samplerate.h>
#include <dlfcn.h>
AudioFile::AudioFile()
: AudioLoop()
{
// could vary later...
_ulaw = new Ulaw(PAYLOAD_CODEC_ULAW);
//_ulaw = new Ulaw(PAYLOAD_CODEC_ULAW);
_start = false;
using std::cout;
using std::cerr;
void* codec = dlopen("codec_ulaw.so", RTLD_LAZY);
if(!codec){
cerr<<"cannot load library: "<< dlerror() <<'\n';
}
dlerror();
create_t* create_codec = (create_t*)dlsym(codec, "create");
const char* dlsym_error = dlerror();
if(dlsym_error){
cerr << "Cannot load symbol create: " << dlsym_error << '\n';
}
destroy_t* destroy_codec = (destroy_t*) dlsym(codec, "destroy");
dlsym_error = dlerror();
if(dlsym_error){
cerr << "Cannot load symbol destroy" << dlsym_error << '\n';
}
_ulaw = create_codec();
}
AudioFile::~AudioFile()
{
delete _ulaw;
delete _ulaw;
}
// load file in mono format
......@@ -82,6 +102,7 @@ AudioFile::loadFile(const std::string& filename, unsigned int sampleRate=8000)
file.read (fileBuffer,length);
file.close();
// Decode file.ul
// expandedsize is the number of bytes, not the number of int
// expandedsize should be exactly two time more, else failed
......@@ -145,7 +166,7 @@ AudioFile::loadFile(const std::string& filename, unsigned int sampleRate=8000)
_buffer = bufferTmp; // just send the buffer pointer;
bufferTmp = 0;
}
return true;
}
......@@ -24,7 +24,7 @@
#define __AUDIOFILE_H__
#include "audioloop.h"
#include "ulaw.h"
#include "audiocodec.h"
/**
@author Yan Morin <yan.morin@savoirfairelinux.com>
......@@ -42,7 +42,7 @@ public:
private:
std::string _filename;
Ulaw* _ulaw;
AudioCodec* _ulaw;
bool _start;
};
......
......@@ -107,8 +107,10 @@ AudioRtpRTX::AudioRtpRTX (SIPCall *sipcall, bool sym)
_sym = sym;
// AudioRtpRTX should be close if we change sample rate
_codecSampleRate = _ca->getAudioCodec()->getClockRate();
//_codecSampleRate = _ca->getAudioCodec()->getClockRate();
_codecSampleRate = 8000;
// TODO: Change bind address according to user settings.
// TODO: this should be the local ip not the external (router) IP
std::string localipConfig = _ca->getLocalIp(); // _ca->getLocalIp();
......@@ -212,15 +214,19 @@ AudioRtpRTX::initAudioRtpSession (void)
return;
}
AudioCodec* audiocodec = _ca->getAudioCodec();
//AudioCodec* audiocodec = _ca->getAudioCodec();
CodecType audiocodec = _ca->getAudioCodec();
bool payloadIsSet = false;
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()));
}
/*if (audiocodec->hasDynamicPayload()) {
//payloadIsSet = _sessionRecv->setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) audiocodec->getPayload(), audiocodec->getClockRate()));
payloadIsSet = _sessionRecv->setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) audiocodec, 8000));
} 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));
payloadIsSet = _sessionSend->setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) audiocodec));
//}
}
_sessionSend->setMark(true);
} else {
......@@ -231,14 +237,16 @@ AudioRtpRTX::initAudioRtpSession (void)
return;
}
AudioCodec* audiocodec = _ca->getAudioCodec();
//AudioCodec* audiocodec = _ca->getAudioCodec();
CodecType audiocodec = _ca->getAudioCodec();
bool payloadIsSet = false;
if (audiocodec) {
if (audiocodec->hasDynamicPayload()) {
/*if (audiocodec->hasDynamicPayload()) {
payloadIsSet = _session->setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) audiocodec->getPayload(), audiocodec->getClockRate()));
} else {
payloadIsSet = _session->setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) audiocodec->getPayload()));
}
} else {*/
//payloadIsSet = _session->setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) audiocodec->getPayload()));
payloadIsSet = _session->setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) audiocodec));
//}
}
}
} catch(...) {
......@@ -246,35 +254,51 @@ AudioRtpRTX::initAudioRtpSession (void)
throw;
}
}
void
AudioRtpRTX::sendSessionFromMic(int timestamp)
AudioCodec*
AudioRtpRTX::loadCodec(int payload)
{
using std::cout;
using std::cerr;
void* codec = dlopen("codec_alaw.so", RTLD_LAZY);
if(!codec){
cerr<<"cannot load library: "<< dlerror() <<'\n';
}
using std::cerr;
void* codec;
//reset errors
dlerror();
switch(payload){
case 0:
codec = dlopen("codec_ulaw.so", RTLD_LAZY);
break;
case 3:
codec = dlopen("codec_gsm.so", RTLD_LAZY);
break;
case 8:
codec = dlopen("codec_alaw.so", RTLD_LAZY);
break;
}
if(!codec){
cerr<<"cannot load library: "<< dlerror() <<'\n';
}
dlerror();
create_t* create_codec = (create_t*)dlsym(codec, "create");
const char* dlsym_error = dlerror();
if(dlsym_error){
cerr << "Cannot load symbol create: " << dlsym_error << '\n';
}
destroy_t* destroy_codec = (destroy_t*) dlsym(codec, "destroy");
dlsym_error = dlerror();
if(dlsym_error){
cerr << "Cannot load symbol destroy" << dlsym_error << '\n';
}
return create_codec();
//load the symbols
create_t* create_codec = (create_t*)dlsym(codec, "create_alaw");
const char* dlsym_error = dlerror();
if(dlsym_error){
cerr << "Cannot load symbol create: " << dlsym_error << '\n';
}
destroy_t* destroy_codec = (destroy_t*) dlsym(codec, "destroy_alaw");
dlsym_error = dlerror();
if(dlsym_error){
cerr << "Cannot load symbol destroy" << dlsym_error << '\n';
}
int pl = 0;
AudioCodec* audiocodec = create_codec();
audiocodec->test();
void
AudioRtpRTX::sendSessionFromMic(int timestamp)
{
AudioCodec* audiocodec = loadCodec(_ca->getAudioCodec());
// STEP:
// 1. get data from mic
......@@ -289,7 +313,6 @@ try {
AudioLayer* audiolayer = Manager::instance().getAudioDriver();
if (!audiolayer) { _debug(" !ARTP: No audiolayer available for mic\n"); return; }
//AudioCodec* audiocodec = _ca->getAudioCodec();
//AudioCodec* audiocodec = _ca->getAudioCodec();
if (!audiocodec) { _debug(" !ARTP: No audiocodec available for mic\n"); return; }
......@@ -338,8 +361,8 @@ try {
}
destroy_codec(audiocodec);
dlclose(codec);
//destroy_codec(audiocodec);
//dlclose(codec);
}
......@@ -369,7 +392,7 @@ try {
unsigned char* data = (unsigned char*)adu->getData(); // data in char
unsigned int size = adu->getSize(); // size in char
using std::cout;
/*using std::cout;
using std::cerr;
void* codec = dlopen("codec_alaw.so", RTLD_LAZY);
if(!codec){
......@@ -380,21 +403,20 @@ if(!codec){
dlerror();
//load the symbols
create_t* create_codec = (create_t*)dlsym(codec, "create_alaw");
create_t* create_codec = (create_t*)dlsym(codec, "create");
const char* dlsym_error = dlerror();
if(dlsym_error){
cerr << "Cannot load symbol create: " << dlsym_error << '\n';
}
destroy_t* destroy_codec = (destroy_t*) dlsym(codec, "destroy_alaw");
destroy_t* destroy_codec = (destroy_t*) dlsym(codec, "destroy");
dlsym_error = dlerror();
if(dlsym_error){
cerr << "Cannot load symbol destroy" << dlsym_error << '\n';
}
int pl = 0;
AudioCodec* audiocodec = create_codec();
//audiocodec1->test();
*/
AudioCodec* audiocodec = loadCodec(payload);
// Decode data with relevant codec
//AudioCodec* audiocodec = _ca->getCodecMap().getCodec((CodecType)payload);
_codecSampleRate = audiocodec->getClockRate();
......@@ -446,8 +468,8 @@ AudioCodec* audiocodec = create_codec();
}
delete adu; adu = NULL;
destroy_codec(audiocodec);
dlclose(codec);
//destroy_codec(audiocodec);
//dlclose(codec);
} catch(...) {
_debugException("! ARTP: receiving failed");
throw;
......
......@@ -119,6 +119,9 @@ class AudioRtpRTX : public ost::Thread, public ost::TimerPort {
* @return int The number of samples after the operation
*/
int downSampleData(int, int);
AudioCodec* loadCodec(int payload);
};
///////////////////////////////////////////////////////////////////////////////
......
......@@ -23,63 +23,63 @@
#include "audiocodec.h"
#include "gsmcodec.h"
//#include "alaw.h"
#include "ulaw.h"
#include "codecDescriptor.h"
#ifdef HAVE_SPEEX
/*#ifdef HAVE_SPEEX
#include "CodecSpeex.h"
#endif
#endif*/
CodecDescriptorMap::CodecDescriptorMap()
CodecDescriptor::CodecDescriptor()
{
//_codecMap[PAYLOAD_CODEC_ALAW] = new Alaw();
_codecMap[PAYLOAD_CODEC_ALAW] = new Ulaw();
_codecMap[PAYLOAD_CODEC_ULAW] = new Ulaw();
_codecMap[PAYLOAD_CODEC_GSM] = new Gsm();
// Default codecs
_codecMap[PAYLOAD_CODEC_ALAW] = "PCMA";
_codecMap[PAYLOAD_CODEC_ULAW] = "PCMU";
_codecMap[PAYLOAD_CODEC_GSM] = "GSM";
#ifdef HAVE_SPEEX
_codecMap[PAYLOAD_CODEC_SPEEX] = new CodecSpeex(PAYLOAD_CODEC_SPEEX); // TODO: this is a variable payload!
//_codecMap[PAYLOAD_CODEC_SPEEX] = new CodecSpeex(PAYLOAD_CODEC_SPEEX); // TODO: this is a variable payload!
#endif
// theses one are not implemented yet..
// _codecMap[PAYLOAD_CODEC_ILBC] = Ilbc();
// _codecMap[PAYLOAD_CODEC_SPEEX] = Speex();
}
AudioCodec*
CodecDescriptorMap::getCodec(CodecType payload)
std::string&
CodecDescriptor::getCodecName(CodecType payload)
{
CodecMap::iterator iter = _codecMap.find(payload);
if (iter!=_codecMap.end()) {
return (iter->second);
}
return NULL;
//return ;
}
void
CodecDescriptorMap::setActive(const std::string& codecDescription)
bool
CodecDescriptor::setActive(CodecType payload)
{
CodecMap::iterator iter = _codecMap.begin();
while(iter!=_codecMap.end()) {
if (iter->second!=0) {
if (iter->second->getDescription() == codecDescription) {
iter->second->setActive(true);
break;
if (iter->first == payload) {
// codec is already in the map --> nothing to do
_debug("Codec with payload %i already in the map\n", payload);
//break;
return true;
}
}
iter++;
}
///TODO: add the codec in the activ codecs list
return false;
}
void
CodecDescriptorMap::setInactive(const std::string& codecDescription)
CodecDescriptor::setInactive(CodecType payload)
{
CodecMap::iterator iter = _codecMap.begin();
while(iter!=_codecMap.end()) {
if (iter->second!=0) {
if (iter->second->getDescription() == codecDescription) {
iter->second->setActive(false);
if (iter->first == payload) {
///TODO : erase the codec from the list ()
//iter->second->setActive(false);
break;
}
}
iter++;
}
......
......@@ -2,6 +2,7 @@
* Copyright (C) 2004-2005 Savoir-Faire Linux inc.
* Author: Yan Morin <yan.morin@savoirfairelinux.com>
* Author: Laurielle Lea <laurielle.lea@savoirfairelinux.com>
* Author: Emmanuel Milou <emmanuel.milou@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
......@@ -25,6 +26,7 @@
#include <string>
#include <map>
#include "../global.h"
typedef enum {
// http://www.iana.org/assignments/rtp-parameters
// http://www.gnu.org/software/ccrtp/doc/refman/html/formats_8h.html#a0
......@@ -45,33 +47,36 @@ typedef enum {
} CodecType;
#include "audiocodec.h"
typedef std::map<CodecType, AudioCodec*> CodecMap;
class CodecDescriptorMap {
/* A codec is identified by its payload. A payload is associated with a name. */
typedef std::map<CodecType, std::string> CodecMap;
class CodecDescriptor {
public:
/**
* Initialize all codec
*/
CodecDescriptorMap();
~CodecDescriptorMap() {};
CodecMap getMap() { return _codecMap; }
CodecDescriptor();
~CodecDescriptor() {};
CodecMap& getCodecMap() { return _codecMap; }
/**
* Get codec with is associated payload
* @param payload the payload associated with the payload
* same as getPayload()
* @return the address of the codec or 0
* @return the name of the codec
*/
AudioCodec* getCodec(CodecType payload);
std::string& getCodecName(CodecType payload);
/**
* Get codec with is associated payload
* Put a codec active, with it's codec's _description
* Put a codec active, with its codec's _description
* O(n) if not found where n is the number of element
* @param codecDescription is the same as with getCodec(number)->getDescription()
*/
void setActive(const std::string& codecDescription);
void setInactive(const std::string& codecDescription);
//void setActive(const std::string& codecName);
bool setActive(CodecType payload);
//void setInactive(const std::string& codecName);
void setInactive(CodecType payload);
private:
CodecMap _codecMap;
};
......
No preview for this file type
No preview for this file type
No preview for this file type
......@@ -63,10 +63,6 @@ virtual int codecEncode (unsigned char *dst, short *src, unsigned int size)
return 33;
}
virtual void test()
{
printf("MOn OSTIE GSM!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
}
private:
gsm _decode_gsmhandle;
......@@ -75,10 +71,10 @@ private:
};
// the class factories
extern "C" AudioCodec* create_gsm() {
extern "C" AudioCodec* create() {
return new Gsm();
}
extern "C" void destroy_gsm(AudioCodec* a) {
extern "C" void destroy(AudioCodec* a) {
delete a;
}
......@@ -12,9 +12,6 @@ public:
_channel = 1;
}
virtual void test(){
printf("MON OSTIE !!!!!!!!!!!!!!!!!!!!!!!!!! ULAW\n");
}
virtual int codecDecode (short *dst, unsigned char *src, unsigned int size) {
int16* end = dst+size;
......@@ -91,10 +88,10 @@ public:
};
// the class factories
extern "C" AudioCodec* create_ulaw() {
extern "C" AudioCodec* create() {
return new Ulaw();
}
extern "C" void destroy_ulaw(AudioCodec* a) {
extern "C" void destroy(AudioCodec* a) {
delete a;
}
......@@ -25,7 +25,7 @@ Call::Call(const CallID& id, Call::CallType type) : _id(id), _type(type),
{
_connectionState = Call::Disconnected;
_callState = Call::Inactive;
_audioCodec = 0;
//_audioCodec = 0;
_localAudioPort = 0;
_localExternalAudioPort = 0;
_remoteAudioPort = 0;
......@@ -65,7 +65,7 @@ Call::getState()
return _callState;
}
CodecDescriptorMap&
CodecDescriptor&
Call::getCodecMap()
{
return _codecMap;
......@@ -99,7 +99,7 @@ Call::getRemoteIp()
return _remoteIPAddress;
}
AudioCodec*
CodecType
Call::getAudioCodec()
{
ost::MutexLock m(_callMutex);
......
......@@ -121,8 +121,8 @@ public:
// AUDIO
/** Set internal codec Map: initialization only, not protected */
void setCodecMap(const CodecDescriptorMap& map) { _codecMap = map; }
CodecDescriptorMap& getCodecMap();
void setCodecMap(const CodecDescriptor& map) { _codecMap = map; }
CodecDescriptor& getCodecMap();
/** Set my IP [not protected] */
void setLocalIp(const std::string& ip) { _localIPAddress = ip; }
......@@ -149,7 +149,7 @@ public:
const std::string& getRemoteIp();
/** Return audio codec [mutex protected] */
AudioCodec* getAudioCodec();
CodecType getAudioCodec();
......@@ -164,13 +164,14 @@ protected:
void setRemoteAudioPort(unsigned int port) { _remoteAudioPort = port; }
/** Set the audio codec used. [not protected] */
void setAudioCodec(AudioCodec* audioCodec) { _audioCodec = audioCodec; }
void setAudioCodec(CodecType audioCodec) { _audioCodec = audioCodec; }
/** Codec Map */
CodecDescriptorMap _codecMap;
CodecDescriptor _codecMap;
/** Codec pointer */
AudioCodec* _audioCodec;
//AudioCodec* _audioCodec;
CodecType _audioCodec;
bool _audioStarted;
......