From 36b5a5de821e1f48daaf7fea25dad545c04dff61 Mon Sep 17 00:00:00 2001
From: Emmanuel Milou
 <emmanuel.milou@savoirfairelinux.comemmanuel.milou@savoirfairelinux.com>
Date: Fri, 25 Jan 2008 13:58:18 -0500
Subject: [PATCH] Improve IAX dynamic codec loading

---
 src/audio/audiortp.cpp        |  3 +-
 src/audio/codecDescriptor.cpp | 16 ++++---
 src/audio/codecDescriptor.h   | 25 ++++++++---
 src/iaxcall.cpp               |  1 -
 src/iaxvoiplink.cpp           | 85 +++++++++++++++--------------------
 src/iaxvoiplink.h             |  6 +++
 src/managerimpl.cpp           | 11 -----
 src/sipcall.cpp               |  4 +-
 8 files changed, 73 insertions(+), 78 deletions(-)

diff --git a/src/audio/audiortp.cpp b/src/audio/audiortp.cpp
index f91414d530..e4b16cbdfa 100644
--- a/src/audio/audiortp.cpp
+++ b/src/audio/audiortp.cpp
@@ -260,8 +260,7 @@ AudioRtpRTX::loadCodec(int payload)
 {
 	using std::cout;
         using std::cerr;
-	void* codec;
-	
+    	void* codec;	
 
 	switch(payload){
 	  case 0:
diff --git a/src/audio/codecDescriptor.cpp b/src/audio/codecDescriptor.cpp
index 92cf39c6aa..1c066f867d 100644
--- a/src/audio/codecDescriptor.cpp
+++ b/src/audio/codecDescriptor.cpp
@@ -53,7 +53,7 @@ CodecDescriptor::getCodecName(CodecType payload)
 }
 
 bool 
-CodecDescriptor::setActive(CodecType payload) 
+CodecDescriptor::isSupported(CodecType payload) 
 {
   CodecMap::iterator iter = _codecMap.begin();
   while(iter!=_codecMap.end()) {
@@ -65,19 +65,17 @@ CodecDescriptor::setActive(CodecType payload)
       }
     iter++;
   }
-
-  ///TODO: add the codec in the activ codecs list
    return false;
 }
 
 void 
-CodecDescriptor::setInactive(CodecType payload)
+CodecDescriptor::removeCodec(CodecType payload)
 {
   CodecMap::iterator iter = _codecMap.begin();
   while(iter!=_codecMap.end()) {
       if (iter->first == payload) {
-	///TODO : erase the codec from the list ()
-        //iter->second->setActive(false);
+	_debug("Codec %s removed from the list", getCodecName(payload).data());
+	_codecMap.erase(iter);
         break;
       }
     iter++;
@@ -85,3 +83,9 @@ CodecDescriptor::setInactive(CodecType payload)
 	
 }
 
+void
+CodecDescriptor::addCodec(CodecType payload)
+{
+}
+
+
diff --git a/src/audio/codecDescriptor.h b/src/audio/codecDescriptor.h
index 193ea88933..22c920cf26 100644
--- a/src/audio/codecDescriptor.h
+++ b/src/audio/codecDescriptor.h
@@ -69,14 +69,25 @@ public:
   std::string& getCodecName(CodecType payload);
 
   /**
-   * 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()
+   * Check in the map codec if the specified codec is supported 
+   * @param payload unique identifier of a codec (RFC)
+   * @return true if the codec specified is supported
+   * 	     false otherwise
    */
-  //void setActive(const std::string& codecName);
-  bool setActive(CodecType payload);
-  //void setInactive(const std::string& codecName);
-  void setInactive(CodecType payload);
+  bool isSupported(CodecType payload);
+
+ /**
+  * Remove the codec with payload payload from the list
+  * @param payload the codec to erase
+  */ 
+  void removeCodec(CodecType payload);
+
+ /**
+  * Add a codec in the list
+  * @param payload the codec to add
+  */
+  void addCodec(CodecType payload);
+
 private:
   CodecMap _codecMap;
 };
diff --git a/src/iaxcall.cpp b/src/iaxcall.cpp
index a2c07838f5..7a58d91caa 100644
--- a/src/iaxcall.cpp
+++ b/src/iaxcall.cpp
@@ -34,7 +34,6 @@ void
 IAXCall::setFormat(int format)
 {
   _format = format;
-
   switch(format) {
   /*case AST_FORMAT_ULAW:
     setAudioCodec(_codecMap.getCodec(PAYLOAD_CODEC_ULAW)); break;
diff --git a/src/iaxvoiplink.cpp b/src/iaxvoiplink.cpp
index fa77f7ce95..de824d06d9 100644
--- a/src/iaxvoiplink.cpp
+++ b/src/iaxvoiplink.cpp
@@ -228,39 +228,50 @@ IAXVoIPLink::getEvent()
   _evThread->sleep(3);
 }
 
-
-void
-IAXVoIPLink::sendAudioFromMic(void)
+AudioCodec* 
+IAXVoIPLink::loadCodec(int payload)
 {
-  
-  IAXCall* currentCall = getIAXCall(Manager::instance().getCurrentCallId());
-  //CodecType audiocodec = (CodecType) -1;
-  
    using std::cout;
    using std::cerr;
-   void* codec = dlopen("codec_alaw.so", RTLD_LAZY);
-   if(!codec){
+   void* handle_codec;
+
+   switch(payload)
+   {
+     case 0:
+       handle_codec = dlopen("codec_ulaw.so", RTLD_LAZY);
+       break;
+     case 3:
+       handle_codec = dlopen("codec_gsm.so", RTLD_LAZY);
+       break;
+     case 8:
+       handle_codec = dlopen("codec_alaw.so", RTLD_LAZY);
+       break;
+   }
+   if(!handle_codec){
         cerr<<"cannot load library: "<< dlerror() <<'\n';
    }
+   // reset errors
+   dlerror();   
 
-//reset errors
-  dlerror();
-
-//load the symbols
-  create_t* create_codec = (create_t*)dlsym(codec, "create");
+   // load the symbols
+  create_t* create_codec = (create_t*)dlsym(handle_codec, "create");
   const char* dlsym_error = dlerror();
   if(dlsym_error){
-        cerr << "Cannot load symbol create: " << dlsym_error << '\n';        
+        cerr << "Cannot load symbol create: " << dlsym_error << '\n';
   }
-  destroy_t* destroy_codec = (destroy_t*) dlsym(codec, "destroy");
+  destroy_t* destroy_codec = (destroy_t*) dlsym(handle_codec, "destroy");
   dlsym_error = dlerror();
   if(dlsym_error){
        cerr << "Cannot load symbol destroy" << dlsym_error << '\n';
   }
+  return create_codec();
+}
 
-
-  AudioCodec* audiocodec = create_codec();
-
+void
+IAXVoIPLink::sendAudioFromMic(void)
+{
+  
+  IAXCall* currentCall = getIAXCall(Manager::instance().getCurrentCallId());
 
   if (!currentCall) {
     // Let's mind our own business.
@@ -277,8 +288,7 @@ IAXVoIPLink::sendAudioFromMic(void)
     return;
   }
 
-  //audiocodec = currentCall->getAudioCodec();
-
+  AudioCodec* audiocodec = loadCodec(currentCall->getAudioCodec());
   if (!audiocodec) {
     // Audio codec still not determined.
     if (audiolayer) {
@@ -395,8 +405,8 @@ IAXVoIPLink::sendAudioFromMic(void)
     _mutexIAX.leaveMutex();
   }
 
-  destroy_codec(audiocodec);
-  dlclose(codec);
+  //destroy_codec(audiocodec);
+  //dlclose(codec);
 }
 
 
@@ -786,40 +796,17 @@ IAXVoIPLink::iaxHandleVoiceEvent(iax_event* event, IAXCall* call)
       //_debug("IAX: Skipping empty jitter-buffer interpolated packet\n");
       return;
     }
-
-   using std::cout;
-using std::cerr;
-void* codec = dlopen("codec_alaw.so", RTLD_LAZY);
-if(!codec){
-        cerr<<"cannot load library: "<< dlerror() <<'\n';
-}
-
-//reset errors
-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';
-}
 AudioCodec* audiocodec;
 
     if (audiolayer) {
-      //AudioCodec* audiocodec = call->getAudioCodec();
-      audiocodec = create_codec();
       
       // On-the-fly codec changing (normally, when we receive a full packet)
       // as per http://tools.ietf.org/id/draft-guy-iax-03.txt
       // - subclass holds the voiceformat property.
       if (event->subclass && event->subclass != call->getFormat()) {
 	call->setFormat(event->subclass);
-	//audiocodec = call->getAudioCodec();
       }
-
+      audiocodec = loadCodec(call->getAudioCodec());
       //_debug("Receive: len=%d, format=%d, _receiveDataDecoded=%p\n", event->datalen, call->getFormat(), _receiveDataDecoded);
      
       unsigned char* data = (unsigned char*)event->data;
@@ -880,8 +867,8 @@ AudioCodec* audiocodec;
     } else {
       _debug("IAX: incoming audio, but no sound card open");
     }
-destroy_codec(audiocodec);
-dlclose(codec);
+//destroy_codec(audiocodec);
+//dlclose(codec);
 
 
 }
diff --git a/src/iaxvoiplink.h b/src/iaxvoiplink.h
index b0f5ea17a4..02e910c342 100644
--- a/src/iaxvoiplink.h
+++ b/src/iaxvoiplink.h
@@ -152,6 +152,12 @@ private:
    */
   int iaxCodecMapToFormat(IAXCall* call);
 
+ /**
+  * Dynamically load an audio codec
+  * @return audiocodec a pointer on an audiocodec object
+  */ 
+  AudioCodec* loadCodec(int payload);
+
   /** Threading object */
   EventThread* _evThread;
 
diff --git a/src/managerimpl.cpp b/src/managerimpl.cpp
index 7887e499db..e2446b543b 100644
--- a/src/managerimpl.cpp
+++ b/src/managerimpl.cpp
@@ -1087,12 +1087,6 @@ void
 ManagerImpl::initAudioCodec (void)
 {
   _debugInit("Active Codecs");
-  //_codecDescriptorMap.setActive(getConfigString("Audio", "Codecs.codec1"));
-  //_codecDescriptorMap.setActive(getConfigString("Audio", "Codec.codec2"));
-  //_codecDescriptorMap.setActive(getConfigString("Audio", "Codec.codec3"));
-  //_codecDescriptorMap.setActive("G711a");
-  //_codecDescriptorMap.setActive("G711u");
-  //_codecDescriptorMap.setActive("GSM");
 }
 
 void
@@ -1106,11 +1100,6 @@ ManagerImpl::setPreferedCodec(const ::DBus::String& codec_name)
 	tmp = list[0];
 	list[0] = list[i];
 	list[i] = tmp; 
-	//_codecDescriptorMap.setActive(list[0]);
-	//_codecDescriptorMap.setInactive(list[1]);
-	//_codecDescriptorMap.setInactive(list[2]);
-	//_codecDescriptorMap.setActive(list[1]);
-	//_codecDescriptorMap.setActive(list[2]);
         setConfig("Audio", "Codecs.codec1", list[0]);	
 	setConfig("Audio", "Codecs.codec2", list[1]);
 	setConfig("Audio", "Codecs.codec3", list[2]);
diff --git a/src/sipcall.cpp b/src/sipcall.cpp
index 3bbb6f361d..0b01f94626 100644
--- a/src/sipcall.cpp
+++ b/src/sipcall.cpp
@@ -360,7 +360,7 @@ SIPCall::sdp_complete_message(sdp_message_t * remote_sdp, osip_message_t * msg)
 	  _debug("remote payload = %s\n", tmp);
           CodecType audiocodec = (CodecType)payload;
           //if (audiocodec != NULL && audiocodec->isActive()) {
-          if (audiocodec != (CodecType)-1 && _codecMap.setActive(audiocodec))  { //TODO: check if the remote payload matches with one of the codec map
+          if (audiocodec != (CodecType)-1 && _codecMap.isSupported(audiocodec))  { 
             listCodec << payload << " ";
             //listRtpMap << "a=rtpmap:" << payload << " " << audiocodec->getCodecName() << "/" << audiocodec->getClockRate();
             listRtpMap << "a=rtpmap:" << payload << " " << _codecMap.getCodecName(audiocodec) << "/" << 8000;
@@ -586,7 +586,7 @@ SIPCall::setAudioCodecFromSDP(sdp_media_t* remote_med, int tid)
     if (tmp != NULL ) {
       int payload = atoi(tmp);
       // stop if we find a correct codec
-      if (_codecMap.setActive((CodecType)payload)){
+      if (_codecMap.isSupported((CodecType)payload)){
           break;
       }
     }
-- 
GitLab