Skip to content
Snippets Groups Projects
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
No related branches found
No related tags found
No related merge requests found
...@@ -63,8 +63,8 @@ uninstall-libcodec_ulaw_so: ...@@ -63,8 +63,8 @@ uninstall-libcodec_ulaw_so:
rm -f $(sflcodecdir)/libcodec_ulaw.so rm -f $(sflcodecdir)/libcodec_ulaw.so
uninstall-libcodec_alaw_so: uninstall-libcodec_alaw_so:
rm -f $(sflcodecdir)/libcodec_alaw.so rm -f $(sflcodecdir)/libcodec_alaw.so
#uninstall-libcodec_gsm_so: uninstall-libcodec_gsm_so:
# rm -f $(sflcodecdir)/libcodec_gsm.so rm -f $(sflcodecdir)/libcodec_gsm.so
uninstall-libcodec_speex_so: uninstall-libcodec_speex_so:
rm -f $(sflcodecdir)/libcodec_speex.so rm -f $(sflcodecdir)/libcodec_speex.so
rm -rf $(sflcodecdir) rm -rf $(sflcodecdir)
...@@ -17,7 +17,6 @@ protected: ...@@ -17,7 +17,6 @@ protected:
unsigned int _channel; unsigned int _channel;
private: private:
//bool _active;
int _payload; int _payload;
bool _hasDynamicPayload; bool _hasDynamicPayload;
...@@ -27,14 +26,13 @@ public: ...@@ -27,14 +26,13 @@ public:
_payload = payload; _payload = payload;
_clockRate = 8000; // default _clockRate = 8000; // default
_channel = 1; // default _channel = 1; // default
// _active = false;
_hasDynamicPayload = (_payload >= 96 && _payload <= 127) ? true : false; _hasDynamicPayload = (_payload >= 96 && _payload <= 127) ? true : false;
} }
virtual ~AudioCodec() {} virtual ~AudioCodec() {
}
/** /**
* @return the number of bytes decoded * @return the number of bytes decoded
*/ */
...@@ -48,8 +46,6 @@ public: ...@@ -48,8 +46,6 @@ public:
bool hasDynamicPayload() { return _hasDynamicPayload; } bool hasDynamicPayload() { return _hasDynamicPayload; }
unsigned int getClockRate() { return _clockRate; } unsigned int getClockRate() { return _clockRate; }
unsigned int getChannel() { return _channel; } unsigned int getChannel() { return _channel; }
//bool isActive() { return _active; }
//void setActive(bool active) { _active = active; }
}; };
......
...@@ -182,8 +182,7 @@ AudioRtpRTX::initAudioRtpSession (void) ...@@ -182,8 +182,7 @@ AudioRtpRTX::initAudioRtpSession (void)
try { try {
if (_ca == 0) { return; } if (_ca == 0) { return; }
AudioCodec* audiocodec = loadCodec(_ca->getAudioCodec()); _codecSampleRate = _audiocodec->getClockRate();
_codecSampleRate = audiocodec->getClockRate();
_debug("Init audio RTP session\n"); _debug("Init audio RTP session\n");
ost::InetHostAddress remote_ip(_ca->getRemoteIp().c_str()); ost::InetHostAddress remote_ip(_ca->getRemoteIp().c_str());
...@@ -215,12 +214,12 @@ AudioRtpRTX::initAudioRtpSession (void) ...@@ -215,12 +214,12 @@ AudioRtpRTX::initAudioRtpSession (void)
} }
bool payloadIsSet = false; bool payloadIsSet = false;
if (audiocodec) { if (_audiocodec) {
if (audiocodec->hasDynamicPayload()) { if (_audiocodec->hasDynamicPayload()) {
payloadIsSet = _sessionRecv->setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) audiocodec->getPayload(), audiocodec->getClockRate())); payloadIsSet = _sessionRecv->setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) _audiocodec->getPayload(), _audiocodec->getClockRate()));
} else { } else {
payloadIsSet= _sessionRecv->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())); payloadIsSet = _sessionSend->setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) _audiocodec->getPayload()));
} }
} }
_sessionSend->setMark(true); _sessionSend->setMark(true);
...@@ -233,22 +232,21 @@ AudioRtpRTX::initAudioRtpSession (void) ...@@ -233,22 +232,21 @@ AudioRtpRTX::initAudioRtpSession (void)
} }
bool payloadIsSet = false; bool payloadIsSet = false;
if (audiocodec) { if (_audiocodec) {
if (audiocodec->hasDynamicPayload()) { if (_audiocodec->hasDynamicPayload()) {
payloadIsSet = _session->setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) audiocodec->getPayload(), audiocodec->getClockRate())); payloadIsSet = _session->setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) _audiocodec->getPayload(), _audiocodec->getClockRate()));
} else { } else {
payloadIsSet = _session->setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) audiocodec->getPayload())); payloadIsSet = _session->setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) _audiocodec->getPayload()));
} }
} }
} }
unloadCodec(audiocodec);
} catch(...) { } catch(...) {
_debugException("! ARTP Failure: initialisation failed"); _debugException("! ARTP Failure: initialisation failed");
throw; throw;
} }
} }
AudioCodec* void
AudioRtpRTX::loadCodec(int payload) AudioRtpRTX::loadCodec(int payload)
{ {
using std::cerr; using std::cerr;
...@@ -280,11 +278,12 @@ AudioRtpRTX::loadCodec(int payload) ...@@ -280,11 +278,12 @@ AudioRtpRTX::loadCodec(int payload)
if(dlsym_error){ if(dlsym_error){
cerr << "Cannot load symbol create: " << dlsym_error << '\n'; cerr << "Cannot load symbol create: " << dlsym_error << '\n';
} }
return create_codec();
_audiocodec = create_codec();
} }
void void
AudioRtpRTX::unloadCodec(AudioCodec* audiocodec) AudioRtpRTX::unloadCodec()
{ {
using std::cerr; using std::cerr;
destroy_t* destroy_codec = (destroy_t*)dlsym(handle_codec, "destroy"); destroy_t* destroy_codec = (destroy_t*)dlsym(handle_codec, "destroy");
...@@ -292,7 +291,7 @@ AudioRtpRTX::unloadCodec(AudioCodec* audiocodec) ...@@ -292,7 +291,7 @@ AudioRtpRTX::unloadCodec(AudioCodec* audiocodec)
if(dlsym_error){ if(dlsym_error){
cerr << "Cannot load symbol destroy" << dlsym_error << '\n'; cerr << "Cannot load symbol destroy" << dlsym_error << '\n';
} }
destroy_codec(audiocodec); destroy_codec(_audiocodec);
dlclose(handle_codec); dlclose(handle_codec);
} }
...@@ -300,7 +299,6 @@ AudioRtpRTX::unloadCodec(AudioCodec* audiocodec) ...@@ -300,7 +299,6 @@ AudioRtpRTX::unloadCodec(AudioCodec* audiocodec)
void void
AudioRtpRTX::sendSessionFromMic(int timestamp) AudioRtpRTX::sendSessionFromMic(int timestamp)
{ {
AudioCodec* audiocodec = loadCodec(_ca->getAudioCodec());
// STEP: // STEP:
// 1. get data from mic // 1. get data from mic
// 2. convert it to int16 - good sample, good rate // 2. convert it to int16 - good sample, good rate
...@@ -314,8 +312,7 @@ try { ...@@ -314,8 +312,7 @@ try {
AudioLayer* audiolayer = Manager::instance().getAudioDriver(); AudioLayer* audiolayer = Manager::instance().getAudioDriver();
if (!audiolayer) { _debug(" !ARTP: No audiolayer available for mic\n"); return; } 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 // we have to get 20ms of data from the mic *20/1000 = /50
int maxBytesToGet = _layerSampleRate * _layerFrameSize * sizeof(SFLDataFormat) / 1000; int maxBytesToGet = _layerSampleRate * _layerFrameSize * sizeof(SFLDataFormat) / 1000;
...@@ -324,13 +321,12 @@ try { ...@@ -324,13 +321,12 @@ try {
// take the lowest // take the lowest
int bytesAvail = (availBytesFromMic < maxBytesToGet) ? availBytesFromMic : maxBytesToGet; int bytesAvail = (availBytesFromMic < maxBytesToGet) ? availBytesFromMic : maxBytesToGet;
//printf("clock rate = %i\n", audiocodec->getClockRate());
// Get bytes from micRingBuffer to data_from_mic // Get bytes from micRingBuffer to data_from_mic
int nbSample = audiolayer->getMic(_dataAudioLayer, bytesAvail) / sizeof(SFLDataFormat); int nbSample = audiolayer->getMic(_dataAudioLayer, bytesAvail) / sizeof(SFLDataFormat);
int nb_sample_up = nbSample; 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; toSIP = _intBufferDown;
...@@ -344,8 +340,7 @@ try { ...@@ -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]); //_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) // for the mono: range = 0 to RTP_FRAME2SEND * sizeof(int16)
// codecEncode(char *dest, int16* src, size in bytes of the src) // 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"); //printf("jusqu'ici tout vas bien\n");
// encode divise by two // encode divise by two
...@@ -361,7 +356,6 @@ try { ...@@ -361,7 +356,6 @@ try {
_debugException("! ARTP: sending failed"); _debugException("! ARTP: sending failed");
throw; throw;
} }
unloadCodec(audiocodec);
} }
...@@ -370,7 +364,6 @@ void ...@@ -370,7 +364,6 @@ void
AudioRtpRTX::receiveSessionForSpkr (int& countTime) AudioRtpRTX::receiveSessionForSpkr (int& countTime)
{ {
AudioCodec* audiocodec;
if (_ca == 0) { return; } if (_ca == 0) { return; }
try { try {
...@@ -394,10 +387,10 @@ try { ...@@ -394,10 +387,10 @@ try {
unsigned char* data = (unsigned char*)adu->getData(); // data in char unsigned char* data = (unsigned char*)adu->getData(); // data in char
unsigned int size = adu->getSize(); // size in char unsigned int size = adu->getSize(); // size in char
//_fstream.write((char*) data, size); //_fstream.write((char*) data, size);
audiocodec = loadCodec(payload);
// Decode data with relevant codec // Decode data with relevant codec
_codecSampleRate = audiocodec->getClockRate(); _codecSampleRate = _audiocodec->getClockRate();
int max = (int)(_codecSampleRate * _layerFrameSize / 1000); int max = (int)(_codecSampleRate * _layerFrameSize / 1000);
if ( size > max ) { if ( size > max ) {
...@@ -408,9 +401,10 @@ try { ...@@ -408,9 +401,10 @@ try {
//printf("size = %i\n", size); //printf("size = %i\n", size);
if (audiocodec != NULL) { if (_audiocodec != NULL) {
int expandedSize = audiocodec->codecDecode(_receiveDataDecoded, data, size);
_fstream.write((char*) _receiveDataDecoded, 160); int expandedSize = _audiocodec->codecDecode(_receiveDataDecoded, data, size);
//_fstream.write((char*) _receiveDataDecoded, );
//buffer _receiveDataDecoded ----> short int or int16, coded on 2 bytes //buffer _receiveDataDecoded ----> short int or int16, coded on 2 bytes
int nbInt16 = expandedSize / sizeof(int16); int nbInt16 = expandedSize / sizeof(int16);
//nbInt16 represents the number of samples we just decoded //nbInt16 represents the number of samples we just decoded
...@@ -453,7 +447,6 @@ try { ...@@ -453,7 +447,6 @@ try {
throw; throw;
} }
unloadCodec(audiocodec);
} }
...@@ -530,6 +523,7 @@ _layerFrameSize = audiolayer->getFrameSize(); // en ms ...@@ -530,6 +523,7 @@ _layerFrameSize = audiolayer->getFrameSize(); // en ms
_layerSampleRate = audiolayer->getSampleRate(); _layerSampleRate = audiolayer->getSampleRate();
initBuffers(); initBuffers();
int step; int step;
loadCodec(_ca->getAudioCodec());
try { try {
// Init the session // Init the session
...@@ -568,6 +562,7 @@ try { ...@@ -568,6 +562,7 @@ try {
TimerPort::incTimer(_layerFrameSize); // 'frameSize' ms TimerPort::incTimer(_layerFrameSize); // 'frameSize' ms
} }
_fstream.close(); _fstream.close();
unloadCodec();
//_debug("stop stream for audiortp loop\n"); //_debug("stop stream for audiortp loop\n");
audiolayer->stopStream(); audiolayer->stopStream();
} catch(std::exception &e) { } catch(std::exception &e) {
......
...@@ -124,18 +124,21 @@ class AudioRtpRTX : public ost::Thread, public ost::TimerPort { ...@@ -124,18 +124,21 @@ class AudioRtpRTX : public ost::Thread, public ost::TimerPort {
/** Pointer on function to handle codecs **/ /** Pointer on function to handle codecs **/
void* handle_codec; void* handle_codec;
AudioCodec* _audiocodec;
/** /**
* Load dynamically a codec (.so library) * Load dynamically a codec (.so library)
* @param payload The payload of the codec you want to load * @param payload The payload of the codec you want to load
* @return AudioCodec* A pointer on a audio codec object * @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) * Destroy and close dynamically a codec (.so library)
* @param audiocodec The audio codec you want to unload * @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: Yan Morin <yan.morin@savoirfairelinux.com>
* Author: Laurielle Lea <laurielle.lea@savoirfairelinux.com> * Author: Laurielle Lea <laurielle.lea@savoirfairelinux.com>
* *
...@@ -18,99 +18,51 @@ ...@@ -18,99 +18,51 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#include <iostream>
#include "audiocodec.h"
extern "C"{ extern "C"{
#include <gsm/gsm.h> #include <gsm.h>
} }
#include "audiocodec.h"
#include "../global.h"
#define GSM_PACKED_FRAME_SIZE_IN_BYTES 33 /**
#define GSM_UNPACKED_FRAME_SIZE_IN_BYTES 320 * GSM audio codec C++ class (over gsm/gsm.h)
#define GSM_UNPACKED_FRAME_SIZE_IN_SHORTS 160
/*
void * GSMCodecHandle = 0;
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 ;
*/ */
class Gsm : public AudioCodec { class Gsm : public AudioCodec {
public: public:
// 3 GSM A 8000 1 [RFC3551] // _payload should be 3
Gsm(int payload = 0) Gsm (int payload=3): AudioCodec(payload, "GSM"){
: AudioCodec(payload, "GSM")
{
_clockRate = 8000; _clockRate = 8000;
_channel = 1; _channel = 1;
//initGSMStruct();
if (!(_decode_gsmhandle = gsm_create() )) if (!(_decode_gsmhandle = gsm_create() ))
_debug("ERROR: decode_gsm_create\n"); printf("ERROR: decode_gsm_create\n");
if (!(_encode_gsmhandle = gsm_create() )) if (!(_encode_gsmhandle = gsm_create() ))
_debug("AudioCodec: ERROR: encode_gsm_create\n"); printf("AudioCodec: ERROR: encode_gsm_create\n");
//_encode_state = gsm_session_create();
//_decode_state = gsm_session_create();
} }
~Gsm (void) virtual ~Gsm (void){
{
//gsm_session_destroy(_decode_state);
//gsm_session_destroy(_encode_state);
gsm_destroy(_decode_gsmhandle); gsm_destroy(_decode_gsmhandle);
gsm_destroy(_encode_gsmhandle); gsm_destroy(_encode_gsmhandle);
} }
/* virtual int codecDecode (short * dst, unsigned char * src, unsigned int size){
bool initGSMStruct() (void)size;
{
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) if(gsm_decode(_decode_gsmhandle, (gsm_byte*)src, (gsm_signal*)dst) < 0)
return 0; printf("ERROR: gsm_decode\n");
return 320;
return GSM_UNPACKED_FRAME_SIZE_IN_BYTES;
} }
virtual int codecEncode (unsigned char *dst, short *src, unsigned int size) virtual int codecEncode (unsigned char * dst, short * src, unsigned int size){
{ (void)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); gsm_encode(_encode_gsmhandle, (gsm_signal*)src, (gsm_byte*) dst);
return GSM_PACKED_FRAME_SIZE_IN_BYTES; return 33;
} }
private: private:
gsm _decode_gsmhandle; gsm _decode_gsmhandle;
gsm _encode_gsmhandle; gsm _encode_gsmhandle;
//void * _encode_state;
//void * _decode_state;
}; };
// the class factories
extern "C" AudioCodec* create(){ extern "C" AudioCodec* create(){
return new Gsm(3); return new Gsm(3);
} }
...@@ -118,4 +70,3 @@ extern "C" AudioCodec* create() { ...@@ -118,4 +70,3 @@ extern "C" AudioCodec* create() {
extern "C" void destroy(AudioCodec* a){ extern "C" void destroy(AudioCodec* a){
delete a; delete a;
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment