From 914de977a027d9e4e0117e9c752ec5cebc50ee6e Mon Sep 17 00:00:00 2001 From: narspt Date: Sun, 5 Jun 2022 02:14:36 +0100 Subject: [PATCH 1/2] implement transcoder options and auto mode --- config/xlxd.transcoder | 19 ++++++ dashboard/pgs/config.inc.php | 1 + dashboard/pgs/modules.php | 37 +++++++++-- scripts/xlxd | 2 +- src/cpacketstream.cpp | 8 ++- src/cpacketstream.h | 2 +- src/creflector.cpp | 25 +++++++- src/ctranscoder.cpp | 120 +++++++++++++++++++++++++++++++++++ src/ctranscoder.h | 15 +++++ src/main.cpp | 8 +-- src/main.h | 1 + 11 files changed, 224 insertions(+), 14 deletions(-) create mode 100644 config/xlxd.transcoder diff --git a/config/xlxd.transcoder b/config/xlxd.transcoder new file mode 100644 index 0000000..3b17d46 --- /dev/null +++ b/config/xlxd.transcoder @@ -0,0 +1,19 @@ +######################################################################################### +# XLXD transcoder options file +# +# One line per entry, each entry specifies a transcoder option. +# +# Valid options (case-sensitive): +# Address - Ip address of the ambed server used for transcoding. +# ModulesOn - A string with all modules which transcoding should be enabled, +# "*" means all modules. +# ModulesAuto - A string with all modules which transcoding should be enabled +# in automatic mode (transcoding will get enabled only if there +# are clients linked on the module with different codecs), +# "*" means all modules. ModulesOn supersedes ModulesAuto. +# +######################################################################################### + +Address 127.0.0.1 +ModulesOn ABCD +ModulesAuto * diff --git a/dashboard/pgs/config.inc.php b/dashboard/pgs/config.inc.php index 3c25f58..b55d129 100755 --- a/dashboard/pgs/config.inc.php +++ b/dashboard/pgs/config.inc.php @@ -23,6 +23,7 @@ $PageOptions['PageRefreshActive'] = true; // Activate automa $PageOptions['PageRefreshDelay'] = '10000'; // Page refresh time in miliseconds $PageOptions['NumberOfModules'] = 10; // Number of Modules enabled on reflector +$PageOptions['TranscoderFile'] = '/xlxd/xlxd.transcoder'; // Path to transcoder file $PageOptions['RepeatersPage'] = array(); $PageOptions['RepeatersPage']['LimitTo'] = 99; // Number of Repeaters to show diff --git a/dashboard/pgs/modules.php b/dashboard/pgs/modules.php index c20caaa..0656d0c 100644 --- a/dashboard/pgs/modules.php +++ b/dashboard/pgs/modules.php @@ -1,8 +1,9 @@ - + - + + @@ -11,17 +12,35 @@ - + - + - + GetReflectorName(), 3, 3); $NumberOfModules = isset($PageOptions['NumberOfModules']) ? min(max($PageOptions['NumberOfModules'],0),26) : 26; +$TranscoderModulesOn = ''; +$TranscoderModulesAuto = ''; +if (isset($PageOptions['TranscoderFile']) && file_exists($PageOptions['TranscoderFile']) && is_readable($PageOptions['TranscoderFile'])) { + $TranscoderFileContent = file($PageOptions['TranscoderFile']); + for ($i=0; $i < count($TranscoderFileContent); $i++) { + if (substr(trim($TranscoderFileContent[$i]), 0, 1) != '#') { + $TranscoderOption = explode(" ", trim($TranscoderFileContent[$i])); + if (isset($TranscoderOption[0]) && isset($TranscoderOption[1])) { + if ($TranscoderOption[0] === 'ModulesOn') { + $TranscoderModulesOn = trim($TranscoderOption[1]); + } else if ($TranscoderOption[0] === 'ModulesAuto') { + $TranscoderModulesAuto = trim($TranscoderOption[1]); + } + } + } + } +} + $odd = ""; for ($i = 1; $i <= $NumberOfModules; $i++) { @@ -30,11 +49,19 @@ for ($i = 1; $i <= $NumberOfModules; $i++) { if ($odd == "#FFFFFF") { $odd = "#F1FAFA"; } else { $odd = "#FFFFFF"; } + $transcoderstate = 'Off'; + if ((strstr($TranscoderModulesOn,'*') !== false) || (strstr($TranscoderModulesOn,$module) !== false)) { + $transcoderstate = 'On'; + } else if ((strstr($TranscoderModulesAuto,'*') !== false) || (strstr($TranscoderModulesAuto,$module) !== false)) { + $transcoderstate = 'Auto'; + } + echo ' + diff --git a/scripts/xlxd b/scripts/xlxd index 6e86018..5683e5f 100755 --- a/scripts/xlxd +++ b/scripts/xlxd @@ -19,7 +19,7 @@ PATH=/sbin:/bin:/usr/sbin:/usr/bin # change below settings according to your system NAME="xlxd" DAEMON="/xlxd/xlxd" -ARGUMENTS="XLX999 192.168.1.240 127.0.0.1" +ARGUMENTS="XLX999 192.168.1.240" PIDFILE="/var/log/xlxd.pid" USER=root GROUP=root diff --git a/src/cpacketstream.cpp b/src/cpacketstream.cpp index 27776b7..c6cfe07 100644 --- a/src/cpacketstream.cpp +++ b/src/cpacketstream.cpp @@ -40,7 +40,7 @@ CPacketStream::CPacketStream() //////////////////////////////////////////////////////////////////////////////////////// // open / close -bool CPacketStream::Open(const CDvHeaderPacket &DvHeader, CClient *client) +bool CPacketStream::Open(const CDvHeaderPacket &DvHeader, CClient *client, bool enableTranscoding) { bool ok = false; @@ -54,7 +54,11 @@ bool CPacketStream::Open(const CDvHeaderPacket &DvHeader, CClient *client) m_DvHeader = DvHeader; m_OwnerClient = client; m_LastPacketTime.Now(); - m_CodecStream = g_Transcoder.GetStream(this, client->GetCodec()); + if (enableTranscoding) { + m_CodecStream = g_Transcoder.GetStream(this, client->GetCodec()); + } else { + m_CodecStream = g_Transcoder.GetStream(this, CODEC_NONE); + } ok = true; } return ok; diff --git a/src/cpacketstream.h b/src/cpacketstream.h index c910158..82507f3 100644 --- a/src/cpacketstream.h +++ b/src/cpacketstream.h @@ -48,7 +48,7 @@ public: virtual ~CPacketStream() {}; // open / close - bool Open(const CDvHeaderPacket &, CClient *); + bool Open(const CDvHeaderPacket &, CClient *, bool enableTranscoding); void Close(void); // push & pop diff --git a/src/creflector.cpp b/src/creflector.cpp index a813df9..22b7eec 100644 --- a/src/creflector.cpp +++ b/src/creflector.cpp @@ -214,13 +214,36 @@ CPacketStream *CReflector::OpenStream(CDvHeaderPacket *DvHeader, CClient *client { // get the module's queue char module = DvHeader->GetRpt2Module(); + + bool enableTranscoding = false; + if (g_Transcoder.IsModuleOn(module)) + { + enableTranscoding = true; + } + else if (g_Transcoder.IsModuleAuto(module)) + { + // enable transcoding only if we have clients on the module with different codecs + uint8 clientCodecs = 0; + for ( int i = 0; i < m_Clients.GetSize(); i++ ) + { + if ( m_Clients.GetClient(i)->GetReflectorModule() == module ) + { + clientCodecs |= m_Clients.GetClient(i)->GetCodec(); + if ( clientCodecs == (CODEC_AMBEPLUS | CODEC_AMBE2PLUS) ) { + enableTranscoding = true; + break; + } + } + } + } + CPacketStream *stream = GetStream(module); if ( stream != NULL ) { // lock it stream->Lock(); // is it available ? - if ( stream->Open(*DvHeader, client) ) + if ( stream->Open(*DvHeader, client, enableTranscoding) ) { // stream open, mark client as master // so that it can't be deleted diff --git a/src/ctranscoder.cpp b/src/ctranscoder.cpp index 668b058..6a2293b 100644 --- a/src/ctranscoder.cpp +++ b/src/ctranscoder.cpp @@ -22,6 +22,8 @@ // along with Foobar. If not, see . // ---------------------------------------------------------------------------- +#include +#include #include "main.h" #include "creflector.h" #include "ctranscoder.h" @@ -55,6 +57,10 @@ CTranscoder::CTranscoder() m_bStreamOpened = false; m_StreamidOpenStream = 0; m_PortOpenStream = 0; + m_ModulesOn = "*"; // default if xlxd.transcoder does not exist + m_ModulesAuto = ""; + m_LastNeedReloadTime.Now(); + m_LastModTime = 0; } //////////////////////////////////////////////////////////////////////////////////////// @@ -89,6 +95,8 @@ CTranscoder::~CTranscoder() bool CTranscoder::Init(void) { bool ok; + + ReadOptions(); // reset stop flag m_bStopThread = false; @@ -197,6 +205,16 @@ void CTranscoder::Task(void) // update time m_LastKeepaliveTime.Now(); } + + // check if options need reload every 30 seconds + if ( m_LastNeedReloadTime.DurationSinceNow() > 30 ) + { + // reload options if needed + NeedReload(); + + // update time + m_LastNeedReloadTime.Now(); + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -399,3 +417,105 @@ void CTranscoder::EncodeClosestreamPacket(CBuffer *Buffer, uint16 uiStreamId) Buffer->Append((uint16)uiStreamId); } +//////////////////////////////////////////////////////////////////////////////////////// +// options helpers + +char *CTranscoder::TrimWhiteSpaces(char *str) +{ + char *end; + while ((*str == ' ') || (*str == '\t')) str++; + if (*str == 0) + return str; + end = str + strlen(str) - 1; + while ((end > str) && ((*end == ' ') || (*end == '\t') || (*end == '\r'))) end --; + *(end + 1) = 0; + return str; +} + +void CTranscoder::NeedReload(void) +{ + struct stat fileStat; + + if (::stat(TRANSCODEROPTIONS_PATH, &fileStat) != -1) + { + if (m_LastModTime != fileStat.st_mtime) + { + ReadOptions(); + } + } +} + +void CTranscoder::ReadOptions(void) +{ + char sz[256]; + int opts = 0; + + std::ifstream file(TRANSCODEROPTIONS_PATH); + if (file.is_open()) + { + m_ModulesOn = ""; + m_ModulesAuto = ""; + + while (file.getline(sz, sizeof(sz)).good()) + { + char *szt = TrimWhiteSpaces(sz); + char *szval; + + if ((::strlen(szt) > 0) && szt[0] != '#') + { + if ((szt = ::strtok(szt, " ,\t")) != NULL) + { + if ((szval = ::strtok(NULL, " ,\t")) != NULL) + { + if (::strncmp(szt, "Address", 7) == 0) + { + CIp Ip = CIp(szval); + if (Ip.GetAddr()) + { + std::cout << "Transcoder Address set to " << Ip << std::endl; + g_Reflector.SetTranscoderIp(Ip); + m_Ip = Ip; + opts++; + } + } + else if (strncmp(szt, "ModulesOn", 9) == 0) + { + std::cout << "Transcoder ModulesOn set to " << szval << std::endl; + m_ModulesOn = szval; + opts++; + } + else if (strncmp(szt, "ModulesAuto", 11) == 0) + { + std::cout << "Transcoder ModulesAuto set to " << szval << std::endl; + m_ModulesAuto = szval; + opts++; + } + else + { + // unknown option - ignore + } + } + } + } + } + std::cout << "Transcoder loaded " << opts << " options from file " << TRANSCODEROPTIONS_PATH << std::endl; + file.close(); + + struct stat fileStat; + + if (::stat(TRANSCODEROPTIONS_PATH, &fileStat) != -1) + { + m_LastModTime = fileStat.st_mtime; + } + } +} + +bool CTranscoder::IsModuleOn(char module) +{ + return ( strchr(m_ModulesOn.c_str(), '*') || strchr(m_ModulesOn.c_str(), module) ); +} + +bool CTranscoder::IsModuleAuto(char module) +{ + return ( strchr(m_ModulesAuto.c_str(), '*') || strchr(m_ModulesAuto.c_str(), module) ); +} diff --git a/src/ctranscoder.h b/src/ctranscoder.h index 7d54c58..3886a61 100644 --- a/src/ctranscoder.h +++ b/src/ctranscoder.h @@ -66,6 +66,10 @@ public: static void Thread(CTranscoder *); void Task(void); + // options + bool IsModuleOn(char); + bool IsModuleAuto(char); + protected: // keepalive helpers void HandleKeepalives(void); @@ -79,6 +83,11 @@ protected: void EncodeKeepAlivePacket(CBuffer *); void EncodeOpenstreamPacket(CBuffer *, uint8, uint8); void EncodeClosestreamPacket(CBuffer *, uint16); + + // options + char *TrimWhiteSpaces(char *); + void NeedReload(void); + void ReadOptions(void); protected: // streams @@ -103,6 +112,12 @@ protected: // time CTimePoint m_LastKeepaliveTime; CTimePoint m_LastActivityTime; + + // options + std::string m_ModulesOn; + std::string m_ModulesAuto; + CTimePoint m_LastNeedReloadTime; + time_t m_LastModTime; }; diff --git a/src/main.cpp b/src/main.cpp index 723ab5b..0296c05 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -87,10 +87,10 @@ int main(int argc, const char * argv[]) #endif // check arguments - if ( argc != 4 ) + if ( argc != 3 ) { - std::cout << "Usage: xlxd callsign xlxdip ambedip" << std::endl; - std::cout << "example: xlxd XLX999 192.168.178.212 127.0.0.1" << std::endl; + std::cout << "Usage: xlxd callsign xlxdip" << std::endl; + std::cout << "example: xlxd XLX999 192.168.178.212" << std::endl; return 1; } @@ -100,7 +100,7 @@ int main(int argc, const char * argv[]) // initialize reflector g_Reflector.SetCallsign(argv[1]); g_Reflector.SetListenIp(CIp(argv[2])); - g_Reflector.SetTranscoderIp(CIp(CIp(argv[3]))); + g_Reflector.SetTranscoderIp(CIp("127.0.0.1")); // default if xlxd.transcoder does not exist // and let it run if ( !g_Reflector.Start() ) diff --git a/src/main.h b/src/main.h index 861439e..03a021e 100644 --- a/src/main.h +++ b/src/main.h @@ -181,6 +181,7 @@ #define BLACKLIST_PATH "/xlxd/xlxd.blacklist" #define INTERLINKLIST_PATH "/xlxd/xlxd.interlink" #define TERMINALOPTIONS_PATH "/xlxd/xlxd.terminal" +#define TRANSCODEROPTIONS_PATH "/xlxd/xlxd.transcoder" #define DEBUGDUMP_PATH "/var/log/xlxd.debug" // system constants --------------------------------------------- From 2225f4e17f7db2b626370fdfe67c53d9ac336dd7 Mon Sep 17 00:00:00 2001 From: narspt Date: Sun, 3 Dec 2023 19:02:34 +0000 Subject: [PATCH 2/2] copy xlxd.transcoder on make install --- src/makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/makefile b/src/makefile index 2d7b587..2670654 100644 --- a/src/makefile +++ b/src/makefile @@ -31,3 +31,6 @@ install: [ -f /xlxd/xlxd.terminal ] && \ cp ../config/xlxd.terminal /xlxd/xlxd.terminal.sample || \ cp ../config/xlxd.terminal /xlxd/xlxd.terminal + [ -f /xlxd/xlxd.transcoder ] && \ + cp ../config/xlxd.transcoder /xlxd/xlxd.transcoder.sample || \ + cp ../config/xlxd.transcoder /xlxd/xlxd.transcoder
ModuleModule NameUsersUsersTrans
coder
DPlus DExtra DCS
URCALLDTMFDTMF URCALLDTMFDTMF URCALLDTMFDTMF
'. $module .' '. (empty($PageOptions['ModuleNames'][$module]) ? '-' : $PageOptions['ModuleNames'][$module]) .' '. count($Reflector->GetNodesInModulesByID($module)) .''. $transcoderstate .' '. 'REF' . $ReflectorNumber . $module . 'L' .' '. (is_numeric($ReflectorNumber) ? '*' . sprintf('%01d',$ReflectorNumber) . (($i<=4)?$module:sprintf('%02d',$i)) : '-') .' '. 'XRF' . $ReflectorNumber . $module . 'L' .'