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
