[ekiga] CodecDescription: Large rework of CodecDescription and CodecList.



commit d4466fd82d7ad06b611f63aef97c4716198f8e34
Author: Damien Sandras <dsandras seconix com>
Date:   Tue Dec 30 12:09:32 2014 +0100

    CodecDescription: Large rework of CodecDescription and CodecList.
    
    The general idea behind this change is to move codec list loading from
    the configuration where it belongs: in the child Opal class and not in
    the main base class. This allows more control over what we are doing and
    different CallManager could have different codec handling mechanisms.
    The newly introduced load method allows loading codecs descriptions from
    the configuration is dependant on the child implementation. The Opal
    component uses its own "load" method.
    
    The CodecList class has been simplified. Instead of handling an internal
    list, it inherits of a std::list of std::string, where std::string is
    the internal representation of the enabled/disabled codec.
    
    The codecs blacklist is now handled in the Opal CodecList
    implementation. This is cleaner.
    
    Furthermore, we do not rely on the SDP encoding name for the codec. This
    allows the user to change the priority between several variations of the
    same codecs, e.g. H.264 High-Profile and H.264.
    
    Finally, a known-codecs.h file has been added. Even though codecs are
    plugins, it allows giving more useful information to the user.

 .../components/opal/opal-codec-description.cpp     |  134 ++++++++++++++------
 .../components/opal/opal-codec-description.h       |   27 +++--
 lib/engine/protocol/codec-description.cpp          |  114 +++--------------
 lib/engine/protocol/codec-description.h            |   68 +++++------
 lib/engine/protocol/known-codecs.h                 |   71 +++++++++++
 5 files changed, 235 insertions(+), 179 deletions(-)
---
diff --git a/lib/engine/components/opal/opal-codec-description.cpp 
b/lib/engine/components/opal/opal-codec-description.cpp
index 349db5c..b5e460a 100644
--- a/lib/engine/components/opal/opal-codec-description.cpp
+++ b/lib/engine/components/opal/opal-codec-description.cpp
@@ -33,65 +33,123 @@
  *
  */
 
+#include <glib/gi18n.h>
 #include <algorithm>
+#include <boost/algorithm/string.hpp>
 
 #include "opal-codec-description.h"
+#include "known-codecs.h"
 
 
 using namespace Opal;
 
 
-static bool
-same_codec_desc (Ekiga::CodecDescription a, Ekiga::CodecDescription b)
+CodecDescription::CodecDescription (const OpalMediaFormat & _format,
+                                    bool _active)
 {
-  return (a.name == b.name && a.rate == b.rate);
-}
-
-
-CodecDescription::CodecDescription (OpalMediaFormat & format)
-  : Ekiga::CodecDescription ()
-{
-  name = (const char *) format.GetEncodingName ();
-  // if a codec does not have a IANA encoding name, use its name instead
-  // (it is the case for MS-IMA-ADPCM for ex.)
-  if (name.empty())
-    name = (const char *) format.GetName ();
-  if (name.empty()) {
-    PTRACE (1, "OpalCodecDescription\tError: found unnamed codec, it will not be used");
-  }
+  name = (const char *) _format;
   if (name == "G722")  // G722 has the wrong rate in RFC
     rate = 16000;
   else
-    rate = format.GetClockRate ();
-  audio = (format.GetMediaType () == OpalMediaType::Audio ());
-  if (format.IsValidForProtocol ("SIP"))
+    rate = _format.GetClockRate ();
+  audio = (_format.GetMediaType () == OpalMediaType::Audio ());
+  video = (_format.GetMediaType () == OpalMediaType::Video ());
+  if (_format.IsValidForProtocol ("SIP"))
     protocols.push_back ("SIP");
-  if (format.IsValidForProtocol ("H.323"))
+  if (_format.IsValidForProtocol ("H.323"))
     protocols.push_back ("H.323");
   protocols.sort ();
+  for (PINDEX i = 0 ; KnownCodecs[i][0] ; i++) {
+    if (name == KnownCodecs[i][0]) {
+      display_name = gettext (KnownCodecs[i][1]);
+      display_info = gettext (KnownCodecs[i][2]);
+      break;
+    }
+  }
+  if (display_name.empty ())
+    display_name = name;
+
+  format = _format;
+  active = _active;
 }
 
 
-CodecList::CodecList (OpalMediaFormatList & list)
+void
+CodecList::load (const std::list<std::string> & codecs_config)
 {
-  for (PINDEX i = 0 ; i < list.GetSize () ; i++) {
-
-    if (list [i].IsTransportable ()) {
+  OpalMediaFormatList formats;
+  GetAllowedFormats (formats);
+
+  clear ();
+
+  // FIXME: This is not very efficient.
+  // We add each codec of the string list to our own internal list
+  for (std::list<std::string>::const_iterator iter = codecs_config.begin ();
+       iter != codecs_config.end ();
+       iter++) {
+
+    std::vector<std::string> strs;
+    boost::split (strs, *iter, boost::is_any_of (":"));
+
+    for (int i = 0 ; i < formats.GetSize () ; i++) {
+      // Found our codec in the formats, add it to our
+      // internal lists
+      if (strs[0] == (const char *) formats[i]) {
+        CodecDescription d (formats[i], (strs[1] == "1"));
+        append (d);
+        formats -= formats[i];
+        break;
+      }
+    }
+  }
 
-      Ekiga::CodecDescription desc = Opal::CodecDescription (list [i]);
+  // We will now add codecs which were not part of the codecs_config
+  // list but that we support (ie all codecs from "list").
+  for (int i = 0 ; i < formats.GetSize () ; i++) {
+    CodecDescription d (formats[i], false);
+    append (d);
+  }
+}
 
-      if (desc.name.empty ())
-        continue;
 
-      Ekiga::CodecList::iterator it =
-        search_n (begin (), end (), 1, desc, same_codec_desc);
-      if (it == end ())
-        append (desc);
-      else {
-        it->protocols.sort ();
-        it->protocols.merge (desc.protocols);
-        it->protocols.unique ();
-      }
-    }
+void
+CodecList::GetAllowedFormats (OpalMediaFormatList & formats)
+{
+  OpalMediaFormat::GetAllRegisteredMediaFormats (formats);
+  formats.RemoveNonTransportable ();
+
+  OpalMediaFormatList black_list;
+
+  black_list += "Linear-16-Stereo-48kHz";
+  black_list += "LPC-10";
+  black_list += "Speex*";
+  black_list += "FECC*";
+  black_list += "RFC4175*";
+
+  // Blacklist NSE, since it is unused in ekiga and might create
+  // problems with some registrars (such as Eutelia)
+  black_list += "NamedSignalEvent";
+
+  // Only keep OPUS in mono mode (for VoIP chat)
+  // and with the maximum sample rate
+  black_list += "Opus-8*";
+  black_list += "Opus-12*";
+  black_list += "Opus-16*";
+  black_list += "Opus-24*";
+  black_list += "Opus-48S";
+
+  // Only include the VP8 RFC version of the capability
+  black_list += "VP8-OM";
+
+  // Purge blacklisted codecs
+  formats -= black_list;
+
+  // Only keep audio and video codecs
+  for (int i = 0 ; i < formats.GetSize () ; i++) {
+    if (formats[i].GetMediaType () != OpalMediaType::Audio ()
+        && formats[i].GetMediaType () != OpalMediaType::Video ())
+      formats -= formats[i];
   }
+
+  PTRACE(4, "Ekiga\tAll available audio & video media formats: " << setfill (',') << formats);
 }
diff --git a/lib/engine/components/opal/opal-codec-description.h 
b/lib/engine/components/opal/opal-codec-description.h
index 24ea6a3..3a04468 100644
--- a/lib/engine/components/opal/opal-codec-description.h
+++ b/lib/engine/components/opal/opal-codec-description.h
@@ -27,9 +27,9 @@
 /*
  *                         opal-codec-description.h  -  description
  *                         ------------------------------------------
- *   begin                : written in January 2008 by Damien Sandras 
+ *   begin                : written in January 2008 by Damien Sandras
  *   copyright            : (c) 2008 by Damien Sandras
- *   description          : declaration of the interface of an Opal codec 
+ *   description          : declaration of the interface of an Opal codec
  *                          description.
  *
  */
@@ -45,18 +45,19 @@
 namespace Opal {
 
   /*** Codec description ***/
-  class CodecDescription 
+  class CodecDescription
     : public Ekiga::CodecDescription
     {
   public:
-      /** Create a codec description from the given OpalMediaFormat
-       * @param format is a valid OpalMediaFormat
-       */
-      CodecDescription (OpalMediaFormat & format);
+      CodecDescription (const OpalMediaFormat & format,
+                        bool active);
+
+  private:
+      OpalMediaFormat format;
     };
 
 
-  class CodecList 
+  class CodecList
     : public Ekiga::CodecList
     {
   public :
@@ -66,10 +67,14 @@ namespace Opal {
       CodecList () {};
 
 
-      /** Constructor that creates a CodecList from an OpalMediaFormatList
-       * @param list is an OpalMediaFormatList
+      /** Load a CodecList from a list of format names
+       * @param list of codec names under the form : format_name|active
        */
-      CodecList (OpalMediaFormatList & list);
+      void load (const std::list<std::string> & codecs_config);
+
+
+  private:
+      void GetAllowedFormats (OpalMediaFormatList & list);
     };
 }
 #endif
diff --git a/lib/engine/protocol/codec-description.cpp b/lib/engine/protocol/codec-description.cpp
index 304122c..e3000bf 100644
--- a/lib/engine/protocol/codec-description.cpp
+++ b/lib/engine/protocol/codec-description.cpp
@@ -41,13 +41,19 @@
 
 using namespace Ekiga;
 
+bool same_codec_description (CodecDescription a, CodecDescription b)
+{
+  return (a == b);
+}
+
+
 CodecDescription::CodecDescription ()
   : rate (0), active (true), audio (false)
 {
 }
 
 
-CodecDescription::CodecDescription (std::string _name,
+CodecDescription::CodecDescription (const std::string & _name,
                                     unsigned _rate,
                                     bool _audio,
                                     std::string _protocols,
@@ -75,58 +81,12 @@ CodecDescription::CodecDescription (std::string _name,
 }
 
 
-CodecDescription::CodecDescription (std::string codec)
-{
-  int i = 0;
-  gchar** vect = NULL;
-  std::string tmp [5];
-
-  vect = g_strsplit (codec.c_str (), "*", -1);
-
-  for (gchar** ptr = vect; *ptr != NULL; ptr++) {
-
-    tmp[i] = *ptr;
-    i++;
-  }
-
-  g_strfreev (vect);
-
-  if (i < 4)
-    return;
-
-  vect = g_strsplit (tmp[3].c_str (), " ", -1);
-  for (gchar** ptr = vect; *ptr != NULL; ptr++) {
-
-    protocols.push_back (*ptr);
-  }
-
-  g_strfreev (vect);
-
-  name = tmp [0];
-  rate = atoi (tmp [1].c_str ());
-  audio = atoi (tmp [2].c_str ());
-  active = atoi (tmp [4].c_str ());
-}
-
-
 std::string
 CodecDescription::str ()
 {
   std::stringstream val;
-  std::stringstream proto;
-
-  val << name << "*" << rate << "*" << audio << "*";
-  protocols.sort ();
-  for (std::list<std::string>::iterator iter = protocols.begin ();
-       iter != protocols.end ();
-       iter++) {
 
-    if (iter != protocols.begin ())
-      proto << " ";
-
-    proto << *iter;
-  }
-  val << proto.str () << "*" << (active ? "1" : "0");
+  val << name << ":" << (active ? "1" : "0");
 
   return val.str ();
 }
@@ -138,7 +98,7 @@ CodecDescription::operator== (const CodecDescription & c) const
   CodecDescription d = c;
   CodecDescription e = (*this);
 
-  return (e.str () == d.str ());
+  return (e.name == d.name);
 }
 
 
@@ -149,60 +109,28 @@ CodecDescription::operator!= (const CodecDescription & c) const
 }
 
 
-CodecList::CodecList (const std::list<std::string> & codecs_config)
-{
-  for (std::list<std::string>::const_iterator iter = codecs_config.begin ();
-       iter != codecs_config.end ();
-       iter++) {
-
-    Ekiga::CodecDescription d = Ekiga::CodecDescription (*iter);
-    if (!d.name.empty ())
-      codecs.push_back (d);
-  }
-}
-
-
-CodecList::iterator
-CodecList::begin ()
-{
-  return codecs.begin ();
-}
-
-CodecList::const_iterator CodecList::begin () const
-{
-  return codecs.begin ();
-}
-
-CodecList::iterator
-CodecList::end ()
+void
+CodecList::append (const CodecList& other)
 {
-  return codecs.end ();
+  insert (end (), other.begin (), other.end ());
+  unique (same_codec_description);
 }
 
-CodecList::const_iterator
-CodecList::end () const
-{
-  return codecs.end ();
-}
 
 void
-CodecList::append (CodecList& other)
+CodecList::append (const CodecDescription& descr)
 {
-  codecs.insert (end (), other.begin (), other.end ());
+  push_back (descr);
 }
 
-void
-CodecList::append (CodecDescription& descr)
-{
-  codecs.push_back (descr);
-}
 
 void
 CodecList::remove (iterator it)
 {
-  codecs.erase (it);
+  erase (it);
 }
 
+
 CodecList
 CodecList::get_audio_list ()
 {
@@ -213,7 +141,7 @@ CodecList::get_audio_list ()
        it++) {
 
     if ((*it).audio)
-      result.codecs.push_back (*it);
+      result.push_back (*it);
   }
 
   return result;
@@ -229,8 +157,8 @@ CodecList::get_video_list ()
        it != end ();
        it++) {
 
-    if (!(*it).audio)
-      result.codecs.push_back (*it);
+    if ((*it).video)
+      result.push_back (*it);
   }
 
   return result;
@@ -258,7 +186,7 @@ CodecList::operator== (const CodecList & c) const
 {
   CodecList::const_iterator it2 = c.begin ();
 
-  if (codecs.size () != c.codecs.size ())
+  if (size () != c.size ())
     return false;
 
   for (const_iterator it = begin ();
diff --git a/lib/engine/protocol/codec-description.h b/lib/engine/protocol/codec-description.h
index 546c43b..4fa243d 100644
--- a/lib/engine/protocol/codec-description.h
+++ b/lib/engine/protocol/codec-description.h
@@ -27,7 +27,7 @@
 /*
  *                         codec-description.h  -  description
  *                         ------------------------------------------
- *   begin                : written in January 2008 by Damien Sandras 
+ *   begin                : written in January 2008 by Damien Sandras
  *   copyright            : (c) 2008 by Damien Sandras
  *   description          : declaration of the interface of a codec description.
  *
@@ -49,11 +49,11 @@ namespace Ekiga
  * @{
  */
 
-  /** This class holds the representation of a codec. 
+  /** This class holds the representation of a codec.
    * That representation is different from the codec itself, but can be used
    * at several places in the engine.
    */
-  class CodecDescription 
+  class CodecDescription
     {
   public:
 
@@ -62,39 +62,40 @@ namespace Ekiga
       CodecDescription ();
 
       /** Create a codec description based on the parameters
-       * @param name is the codec name as defined in the RFC
-       * @param rate is the clock rate 
+       * @param name is the codec name uniquely representing it
+       * @param rate is the clock rate
        * @param audio is true if it reprensents an audio codec
-       * @param protocols is a comma separated list of protocols supported 
+       * @param protocols is a comma separated list of protocols supported
        *        by the codec
        * @param active is true if the codec is active
        */
-      CodecDescription (std::string name,
+      CodecDescription (const std::string & name,
                         unsigned rate,
                         bool audio,
                         std::string protocols,
                         bool active);
 
-      /** Create a codec description from a string
-       * @param codec is a string representing the codec description.
-       *        All fields are separated by a *
-       */
-      CodecDescription (std::string codec);
-
       virtual ~CodecDescription ()
       {}
 
       /** Return the codec description under the form of a string.
        * @return the std::string representing the string description.
+       *         (ie name:active, e.g. G.711:1)
        */
       std::string str ();
 
 
-      /** name is the codec name as defined in the RFC
+      /** name is the codec name
       */
       std::string name;
 
-      /** rate is the clock rate 
+      /* nice display name
+       * and information for "known" codecs
+       */
+      std::string display_name;
+      std::string display_info;
+
+      /** rate is the clock rate
       */
       unsigned rate;
 
@@ -106,6 +107,10 @@ namespace Ekiga
       */
       bool audio;
 
+      /** video is true if it reprensents an video codec
+      */
+      bool video;
+
       /** protocols is a list of protocols supported by the codec
       */
       std::list<std::string> protocols;
@@ -124,55 +129,47 @@ namespace Ekiga
 
 
   class CodecList
+      : public std::list<CodecDescription>
     {
   public :
 
-      typedef std::list<CodecDescription> container_type;
-      typedef container_type::iterator iterator;
-      typedef container_type::const_iterator const_iterator;
-
       /** Constructor that creates an empty CodecList
        */
       CodecList () {};
 
-      /** Constructor that creates a CodecList from a GSList whose elements
-       * are CodecDescription objects formatted as a string.
-       */
-      CodecList (const std::list<std::string> &);
-
       virtual ~CodecList ()
       {}
 
-      /** Iterators to loop on the list
-       *
+      /** Load a CodecList from a list of format names
+       *  The CodecList will contain all codecs from the config list
+       *  and all supported codecs if they were not present in the
+       *  configuration.
+       * @param list of codec names under the form : format_name|active
        */
-      iterator begin ();
-      const_iterator begin () const;
-      iterator end ();
-      const_iterator end () const;
+      virtual void load (G_GNUC_UNUSED const std::list<std::string> & codecs_config) {};
 
       /** Append the given CodecList at the end of the current CodecList.
        * @param other is the CodecList to append to the current one
        */
-      void append (CodecList& other);
+      void append (const CodecList& other);
 
       /** Append the given codec description to the current CodecList.
        * @param descr is the CodecDescription to append to the current list
        */
-      void append (CodecDescription& descr);
+      void append (const CodecDescription& descr);
 
       /** Remove the codec description pointed to by the iterator
        * @param iter is the iterator
        */
       void remove (iterator it);
 
-      /** Return the list of audio codecs descriptions in the current CodecList 
+      /** Return the list of audio codecs descriptions in the current CodecList
        * @return the list of audio CodecDescription
        */
       CodecList get_audio_list ();
 
 
-      /** Return the list of video codecs descriptions in the current CodecList 
+      /** Return the list of video codecs descriptions in the current CodecList
        * @return the list of video CodecDescription
        */
       CodecList get_video_list ();
@@ -194,9 +191,6 @@ namespace Ekiga
        * @return true if both CodecList are different, false otherwise
        */
       bool operator!= (const CodecList & c) const;
-
-    private:
-      container_type codecs;
     };
 
 /**
diff --git a/lib/engine/protocol/known-codecs.h b/lib/engine/protocol/known-codecs.h
new file mode 100644
index 0000000..65a1360
--- /dev/null
+++ b/lib/engine/protocol/known-codecs.h
@@ -0,0 +1,71 @@
+
+/*
+ * Ekiga -- A VoIP and Video-Conferencing application
+ * Copyright (C) 2000-2015 Damien Sandras <dsandras seconix 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
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version. This program is distributed in the hope
+ * that it will be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * 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.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Ekiga is licensed under the GPL license and as a special exception, you
+ * have permission to link or otherwise combine this program with the
+ * programs OPAL, OpenH323 and PWLIB, and distribute the combination, without
+ * applying the requirements of the GNU GPL to the OPAL, OpenH323 and PWLIB
+ * programs, as long as you do follow the requirements of the GNU GPL for all
+ * the rest of the software thus combined.
+ */
+
+
+/*
+ *                         know-codecs.h  -  description
+ *                         ------------------------------
+ *   begin                : written in December 2014 by Damien Sandras
+ *   copyright            : (c) 2014 by Damien Sandras
+ *   description          : Codec descriptions.
+ *
+ */
+
+#ifndef __KNOWN_CODECS_H
+#define __KNOWN_CODECS_H
+
+static const char* KnownCodecs[][3] = {
+    { "G.722.1C-24K",   N_("G.722.1C"),        N_("Annex C, 14 kHz mode at 24 kbit/s")        },
+    { "G.722.1C-32K",   N_("G.722.1C"),        N_("Annex C, 14 kHz mode at 32 kbit/s")        },
+    { "G.722.1C-48K",   N_("G.722.1C"),        N_("Annex C, 14 kHz mode at 48 kbit/s")        },
+    { "Opus-48",        N_("Opus"),            N_("Opus codec, 48 kHz mode")                  },
+    { "iSAC-16kHz",     N_("iSAC"),            N_("internet Speech Audio Codec, 16 kHz mode") },
+    { "iSAC-32kHz",     N_("iSAC"),            N_("internet Speech Audio Codec, 32 kHz mode") },
+    { "G.722-64k",      N_("G.722"),           N_("Basic G.722")                              },
+    { "G.722.1-24K",    N_("G.722.1"),         N_("7 kHz mode at 24 kbits/s")                 },
+    { "G.722.1-32K",    N_("G.722.1"),         N_("7 kHz mode at 32 kbits/s")                 },
+    { "G.722.2",        N_("G.722.2"),         N_("AMR Wideband")                             },
+    { "GSM-AMR",        N_("AMR-NB"),          N_("AMR Narrowband")                           },
+    { "SILK-8",         N_("SILK"),            N_("Skype SILK 8 kbits/s")                     },
+    { "SILK-16",        N_("SILK"),            N_("Skype SILK 16 kbits/s")                    },
+    { "G.711-ALaw-64k", N_("G.711 A-Law"),     N_("Standard G.711")                           },
+    { "G.711-uLaw-64k", N_("G.711 ยต-Law"),     N_("Standard G.711")                           },
+    { "G.726-16k",      N_("G.726"),           N_("G.726 at 16 kbits/s")                      },
+    { "G.726-24k",      N_("G.726"),           N_("G.726 at 24 kbits/s")                      },
+    { "G.726-32k",      N_("G.726"),           N_("G.726 at 32 kbits/s")                      },
+    { "G.726-40k",      N_("G.726"),           N_("G.726 at 40 kbits/s")                      },
+    { "MS-IMA-ADPCM",   N_("IMA ADPCM"),       N_("Microsoft IMA ADPCM")                      },
+    { "H.261",          N_("H.261"),           N_("Basic H.261")                              },
+    { "H.263",          N_("H.263"),           N_("H.263")                                    },
+    { "H.263plus",      N_("H.263+"),          N_("H.263 Version 1998")                       },
+    { "H.264-0",        N_("H.264"),           N_("H.264 Single NAL mode")                    },
+    { "H.264-1",        N_("H.264"),           N_("H.264 Interleaved mode")                   },
+    { "H.264-High",     N_("H.264"),           N_("H.264 Interleaved mode, High-Profile")     },
+    { "MPEG4",          N_("MPEG-4"),          N_("MPEG-4")                                   },
+    { "VP8-WebM",       N_("VP8"),             N_("VP8")                                      },
+    { NULL,             NULL,                  NULL                                           }
+};
+
+#endif


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]