Module: sems
Branch: master
Commit: 8237ba0050603c7bb4db6d4ddcf176ee3064f536
URL:    
http://git.sip-router.org/cgi-bin/gitweb.cgi/sems/?a=commit;h=8237ba0050603c7bb4db6d4ddcf176ee3064f536

Author: Václav Kubart <[email protected]>
Committer: Václav Kubart <[email protected]>
Date:   Wed Apr 25 10:50:33 2012 +0200

transcoder: statistics about output codec usage

---

 apps/sbc/SBC.cpp     |    2 +
 core/AmB2BMedia.cpp  |  111 +++++++++++++++++++++++++++++++++++++++++++++++++-
 core/AmB2BMedia.h    |   23 ++++++++++
 core/AmRtpStream.cpp |   11 +++++
 core/AmRtpStream.h   |    1 +
 5 files changed, 146 insertions(+), 2 deletions(-)

diff --git a/apps/sbc/SBC.cpp b/apps/sbc/SBC.cpp
index 974fd03..c39394b 100644
--- a/apps/sbc/SBC.cpp
+++ b/apps/sbc/SBC.cpp
@@ -629,6 +629,8 @@ void SBCFactory::invoke(const string& method, const AmArg& 
args,
     ret.push(AmArg("setRegexMap"));
     ret.push(AmArg("loadCallcontrolModules"));
     ret.push(AmArg("postControlCmd"));
+  } else if(method == "printCallStats"){ 
+    B2BMediaStatistics::instance()->getReport(args, ret);
   }  else
     throw AmDynInvoke::NotImplemented(method);
 }
diff --git a/core/AmB2BMedia.cpp b/core/AmB2BMedia.cpp
index 235deb3..31a7212 100644
--- a/core/AmB2BMedia.cpp
+++ b/core/AmB2BMedia.cpp
@@ -5,11 +5,76 @@
 #include "AmB2BSession.h"
 #include "AmRtpReceiver.h"
 
+#include <algorithm>
+
 #define TRACE DBG
+#define UNDEFINED_PAYLOAD (-1)
+
+static B2BMediaStatistics b2b_stats;
+
+void B2BMediaStatistics::incCodecWriteUsage(const string &codec_name)
+{
+  if (codec_name.empty()) return;
+
+  mutex.lock();
+  map<string, int>::iterator i = codec_write_usage.find(codec_name);
+  if (i != codec_write_usage.end()) i->second++;
+  else codec_write_usage[codec_name] = 1;
+  mutex.unlock();
+}
+
+void B2BMediaStatistics::decCodecWriteUsage(const string &codec_name)
+{
+  if (codec_name.empty()) return;
+
+  mutex.lock();
+  map<string, int>::iterator i = codec_write_usage.find(codec_name);
+  if (i != codec_write_usage.end()) {
+    if (i->second > 0) i->second--;
+  }
+  mutex.unlock();
+}
+
+B2BMediaStatistics *B2BMediaStatistics::instance()
+{
+  return &b2b_stats;
+}
+    
+void B2BMediaStatistics::reportCodecWriteUsage(string &dst)
+{
+  bool first = true;
+  dst.clear();
+  for (map<string, int>::iterator i = codec_write_usage.begin();
+      i != codec_write_usage.end(); ++i) 
+  {
+    if (first) first = false;
+    else dst += ",";
+    dst += i->first;
+    dst += "=";
+    dst += int2str(i->second);
+  }
+}
+    
+void B2BMediaStatistics::getReport(const AmArg &args, AmArg &ret)
+{
+  AmArg write_usage;
+  for (map<string, int>::iterator i = codec_write_usage.begin();
+      i != codec_write_usage.end(); ++i) 
+  {
+    AmArg avp;
+    avp["codec"] = i->first;
+    avp["count"] = i->second;
+    write_usage.push(avp);
+  }
+  ret["write"] = write_usage;
+}
+
+//////////////////////////////////////////////////////////////////////////////////
 
 AudioStreamData::AudioStreamData(AmB2BSession *session):
   in(NULL), initialized(false),
-  dtmf_detector(NULL), dtmf_queue(NULL)
+  dtmf_detector(NULL), dtmf_queue(NULL),
+  outgoing_payload(UNDEFINED_PAYLOAD)
 {
   stream = new AmRtpAudio(session, session->getRtpRelayInterface());
   stream->setRtpRelayTransparentSeqno(session->getRtpRelayTransparentSeqno());
@@ -18,6 +83,7 @@ AudioStreamData::AudioStreamData(AmB2BSession *session):
 
 void AudioStreamData::clear()
 {
+  resetStats();
   if (in) {
     in->close();
     delete in;
@@ -115,6 +181,7 @@ bool AudioStreamData::initStream(AmSession *session,
 
 bool AudioStreamData::resetInitializedStream()
 {
+  resetStats();
   if (initialized) {
     initialized = false;
 
@@ -131,6 +198,42 @@ bool AudioStreamData::resetInitializedStream()
   return false;
 }
 
+void AudioStreamData::resetStats()
+{
+  if (outgoing_payload != UNDEFINED_PAYLOAD) {
+    b2b_stats.decCodecWriteUsage(outgoing_payload_name);
+    outgoing_payload = UNDEFINED_PAYLOAD;
+    outgoing_payload_name.clear();
+  }
+}
+
+void AudioStreamData::updateStats()
+{
+  if (!initialized) {
+    resetStats();
+    return;
+  }
+
+  int payload = stream->getPayloadType();
+  if (payload != outgoing_payload) { 
+    // payload used to send has changed
+
+    // decrement usage of previous payload if set
+    if (outgoing_payload != UNDEFINED_PAYLOAD) 
+      b2b_stats.decCodecWriteUsage(outgoing_payload_name);
+    
+    if (payload != UNDEFINED_PAYLOAD) {
+      // remember payload name (in lowercase to simulate case insensitivity)
+      outgoing_payload_name = stream->getPayloadName();
+      transform(outgoing_payload_name.begin(), outgoing_payload_name.end(), 
+          outgoing_payload_name.begin(), ::tolower);
+      b2b_stats.incCodecWriteUsage(outgoing_payload_name);
+    }
+    else outgoing_payload_name.clear();
+    outgoing_payload = payload;
+  }
+}
+
 int AudioStreamData::writeStream(unsigned long long ts, unsigned char *buffer, 
AudioStreamData &src)
 {
   if (!initialized) return 0;
@@ -151,7 +254,11 @@ int AudioStreamData::writeStream(unsigned long long ts, 
unsigned char *buffer, A
       }
     }
     if (got < 0) return -1;
-    if (got > 0) return stream->put(ts, buffer, sample_rate, got);
+    if (got > 0) {
+      // we have data to be sent
+      updateStats();
+      return stream->put(ts, buffer, sample_rate, got);
+    }
   }
   return 0;
 }
diff --git a/core/AmB2BMedia.h b/core/AmB2BMedia.h
index adaefe6..2fe93da 100644
--- a/core/AmB2BMedia.h
+++ b/core/AmB2BMedia.h
@@ -7,8 +7,25 @@
 #include "AmMediaProcessor.h"
 #include "AmDtmfDetector.h"
 
+#include <map>
+
 class AmB2BSession;
 
+class B2BMediaStatistics
+{
+  private:
+    std::map<string, int> codec_write_usage;
+    AmMutex mutex;
+
+  public:
+    void reportCodecWriteUsage(string &dst);
+    void getReport(const AmArg &args, AmArg &ret);
+
+    static B2BMediaStatistics *instance();
+    void incCodecWriteUsage(const string &codec_name);
+    void decCodecWriteUsage(const string &codec_name);
+};
+
 /** \brief Storage for several data items required to be held with one RTP
  * stream for B2B media processing.
  *
@@ -41,6 +58,12 @@ class AudioStreamData {
      * to be done independently for each stream. */
     AmDtmfEventQueue *dtmf_queue;
 
+    // for performance monitoring
+    int outgoing_payload;
+    string outgoing_payload_name;
+    void updateStats();
+    void resetStats();
+
   public:
     /** Creates data based on associated signaling leg data. */
     AudioStreamData(AmB2BSession *session);
diff --git a/core/AmRtpStream.cpp b/core/AmRtpStream.cpp
index 4016416..78a9568 100644
--- a/core/AmRtpStream.cpp
+++ b/core/AmRtpStream.cpp
@@ -966,6 +966,17 @@ void AmRtpStream::setRtpRelayTransparentSSRC(bool 
transparent) {
   relay_transparent_ssrc = transparent;
 }
 
+string AmRtpStream::getPayloadName()
+{
+  for(PayloadCollection::iterator it = payloads.begin();
+      it != payloads.end(); ++it){
+
+    if (it->pt == payload) return it->name;
+  }
+
+  return string("");
+}
+
 
 PacketMem::PacketMem() {
   memset(used, 0, sizeof(used));
diff --git a/core/AmRtpStream.h b/core/AmRtpStream.h
index 833b6ca..187f009 100644
--- a/core/AmRtpStream.h
+++ b/core/AmRtpStream.h
@@ -369,6 +369,7 @@ public:
   int getSdpMediaIndex() { return sdp_media_index; }
   void forceSdpMediaIndex(int idx) { sdp_media_index = idx; offer_answer_used 
= false; }
   int getPayloadType() { return payload; }
+  string getPayloadName();
 
   /**
    * send a DTMF as RTP payload (RFC4733)

_______________________________________________
Semsdev mailing list
[email protected]
http://lists.iptel.org/mailman/listinfo/semsdev

Reply via email to