From 7a056ef2cb94fb2fa45d8ecaed9dd97e99749fde Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Fri, 22 Aug 2014 11:38:14 +0200 Subject: Add experimental EDI to configuration file --- doc/example.mux | 18 +++++ src/DabMux.cpp | 148 +++++++++++++++++++++++----------------- src/DabMux.h | 12 ++++ src/ParserConfigfile.cpp | 62 ++++++++++------- src/ParserConfigfile.h | 4 +- src/dabOutput/edi/AFPacket.cpp | 13 ++-- src/dabOutput/edi/AFPacket.h | 7 +- src/dabOutput/edi/PFT.cpp | 10 +-- src/dabOutput/edi/PFT.h | 9 ++- src/dabOutput/edi/TagItems.cpp | 6 +- src/dabOutput/edi/TagPacket.cpp | 4 +- 11 files changed, 190 insertions(+), 103 deletions(-) diff --git a/doc/example.mux b/doc/example.mux index 65127d9..efe9504 100644 --- a/doc/example.mux +++ b/doc/example.mux @@ -264,6 +264,24 @@ outputs { ; Throttle output to real-time (one ETI frame every 24ms) ;throttle "simul://" + ; The edi output has a different syntax + edi { + destination "192.168.23.23" + port 12000 + sourceport 13000 + + ; EDI uses the UDP protocol + + ; Enable the PFT subsystem. If false, AFPackets are sent. + enable_pft false + + ; Save the packets sent over ethernet to the file ./edi.debug + dump false + + ; show more debugging info + verbose true + } + ; Other outputs: ; TCP listen on port ;net "tcp://host:port" diff --git a/src/DabMux.cpp b/src/DabMux.cpp index 655985f..08a3c15 100644 --- a/src/DabMux.cpp +++ b/src/DabMux.cpp @@ -27,10 +27,6 @@ # include "config.h" #endif -#define EDI_DEBUG 0 -#define EDI_DUMP 1 -#define EDI_PFT 1 - #include #include #include @@ -331,6 +327,17 @@ int main(int argc, char *argv[]) int statsserverport = 0; + edi_configuration_t edi_conf; + + // Defaults for edi + edi_conf.enabled = false; + edi_conf.dest_addr = ""; + edi_conf.dest_port = 0; + edi_conf.source_port = 0; + edi_conf.dump = false; + edi_conf.enable_pft = false; + + struct timeval mnsc_time; /* TODO: @@ -355,7 +362,7 @@ int main(int argc, char *argv[]) string conf_file = argv[2]; parse_configfile(conf_file, outputs, ensemble, &enableTist, &FICL, - &factumAnalyzer, &limit, &rc, &statsserverport); + &factumAnalyzer, &limit, &rc, &statsserverport, &edi_conf); } catch (runtime_error &e) { @@ -658,6 +665,13 @@ int main(int argc, char *argv[]) etiLog.log(info, "--- Output list ---"); printOutputs(outputs); + if (edi_conf.enabled) { + etiLog.level(warn) << "EXPERIMENTAL EDI OUTPUT ENABLED!"; + etiLog.level(info) << "edi to " << edi_conf.dest_addr << ":" << edi_conf.dest_port; + etiLog.level(info) << "source port " << edi_conf.source_port; + etiLog.level(info) << "verbose " << edi_conf.verbose; + } + /* These iterators are used to fill the respective FIG. * It is necessary to cycle through all the FIGs that have @@ -674,23 +688,29 @@ int main(int argc, char *argv[]) serviceFIG0_17 = ensemble->services.end(); subchannelFIG0_1 = ensemble->subchannels.end(); + if (edi_conf.verbose) { + etiLog.log(info, "Setup EDI debug"); + } + std::ofstream edi_debug_file; -#if EDI_DEBUG - etiLog.log(info, "Setup EDI debug"); -# if EDI_DUMP - std::ofstream edi_debug_file("./edi.debug"); -# endif - UdpSocket edi_output(13000); - etiLog.log(info, "EDI debug set up"); -#endif + if (edi_conf.dump) { + edi_debug_file.open("./edi.debug"); + } + UdpSocket edi_output; + + if (edi_conf.enabled) { + edi_output.create(edi_conf.source_port); + } + + if (edi_conf.verbose) { + etiLog.log(info, "EDI debug set up"); + } // The TagPacket will then be placed into an AFPacket - AFPacketiser edi_afPacketiser(EDI_AFPACKET_PROTOCOLTYPE_TAGITEMS); + AFPacketiser edi_afPacketiser(edi_conf.verbose); -#if EDI_PFT // The AF Packet will be protected with reed-solomon and split in fragments - PFT edi_pft(207, 3); -#endif + PFT edi_pft(207, 3, edi_conf.verbose); /* Each iteration of the main loop creates one ETI frame */ for (currentFrame = 0; running; currentFrame++) { @@ -2019,66 +2039,70 @@ int main(int argc, char *argv[]) *********** Finalise and send EDI ******************************** **********************************************************************/ -#if EDI_DEBUG - // put tags *ptr, DETI and all subchannels into one TagPacket - edi_tagpacket.tag_items.push_back(&edi_tagStarPtr); - edi_tagpacket.tag_items.push_back(&edi_tagDETI); + if (edi_conf.enabled) { + // put tags *ptr, DETI and all subchannels into one TagPacket + edi_tagpacket.tag_items.push_back(&edi_tagStarPtr); + edi_tagpacket.tag_items.push_back(&edi_tagDETI); - list::iterator tag; - for (tag = edi_subchannels.begin(); tag != edi_subchannels.end(); ++tag) { - edi_tagpacket.tag_items.push_back(&(*tag)); - } + list::iterator tag; + for (tag = edi_subchannels.begin(); tag != edi_subchannels.end(); ++tag) { + edi_tagpacket.tag_items.push_back(&(*tag)); + } - // Assemble into one AF Packet - AFPacket edi_afpacket = edi_afPacketiser.Assemble(edi_tagpacket); + // Assemble into one AF Packet + AFPacket edi_afpacket = edi_afPacketiser.Assemble(edi_tagpacket); -# if EDI_PFT - // Apply PFT layer to AF Packet (Reed Solomon FEC and Fragmentation) - vector< PFTFragment > edi_fragments = - edi_pft.Assemble(edi_afpacket); + if (edi_conf.enable_pft) { + // Apply PFT layer to AF Packet (Reed Solomon FEC and Fragmentation) + vector< PFTFragment > edi_fragments = + edi_pft.Assemble(edi_afpacket); - // Send over ethernet - vector< vector >::iterator edi_frag; - for (edi_frag = edi_fragments.begin(); - edi_frag != edi_fragments.end(); - ++edi_frag) { + // Send over ethernet + vector< vector >::iterator edi_frag; + for (edi_frag = edi_fragments.begin(); + edi_frag != edi_fragments.end(); + ++edi_frag) { - UdpPacket udppacket; + UdpPacket udppacket; - InetAddress& addr = udppacket.getAddress(); - addr.setAddress("127.0.0.1"); - addr.setPort(12000); + InetAddress& addr = udppacket.getAddress(); + addr.setAddress(edi_conf.dest_addr.c_str()); + addr.setPort(edi_conf.dest_port); - udppacket.addData(&(edi_frag->front()), edi_frag->size()); + udppacket.addData(&(edi_frag->front()), edi_frag->size()); - edi_output.send(udppacket); + edi_output.send(udppacket); -# if EDI_DUMP - std::ostream_iterator debug_iterator(edi_debug_file); - std::copy(edi_frag->begin(), edi_frag->end(), debug_iterator); -# endif - } + if (edi_conf.dump) { + std::ostream_iterator debug_iterator(edi_debug_file); + std::copy(edi_frag->begin(), edi_frag->end(), debug_iterator); + } + } - fprintf(stderr, "EDI number of PFT fragments %zu\n", edi_fragments.size()); -# else - // Send over ethernet + if (edi_conf.verbose) { + fprintf(stderr, "EDI number of PFT fragments %zu\n", + edi_fragments.size()); + } + } + else { + // Send over ethernet - UdpPacket udppacket; + UdpPacket udppacket; - InetAddress& addr = udppacket.getAddress(); - addr.setAddress("192.168.3.2"); - addr.setPort(12000); + InetAddress& addr = udppacket.getAddress(); + addr.setAddress(edi_conf.dest_addr.c_str()); + addr.setPort(edi_conf.dest_port); - udppacket.addData(&(edi_afpacket.front()), edi_afpacket.size()); + udppacket.addData(&(edi_afpacket.front()), edi_afpacket.size()); - edi_output.send(udppacket); -# endif + edi_output.send(udppacket); + } -# if EDI_DUMP - std::ostream_iterator debug_iterator(edi_debug_file); - std::copy(edi_afpacket.begin(), edi_afpacket.end(), debug_iterator); -# endif -#endif + if (edi_conf.dump) { + std::ostream_iterator debug_iterator(edi_debug_file); + std::copy(edi_afpacket.begin(), edi_afpacket.end(), debug_iterator); + } + } #if _DEBUG /********************************************************************** diff --git a/src/DabMux.h b/src/DabMux.h index d54d818..18e362a 100644 --- a/src/DabMux.h +++ b/src/DabMux.h @@ -29,6 +29,9 @@ #define _DABMUX_H #include +#include +#include +#include "RemoteControl.h" #include "dabOutput/dabOutput.h" #include "dabInput.h" #include "Eti.h" @@ -63,6 +66,15 @@ #define DEFAULT_SERVICE_ID 50 #define DEFAULT_PACKET_ADDRESS 0 +struct edi_configuration_t { + bool enabled; + unsigned int source_port; + bool dump; + bool verbose; + bool enable_pft; + std::string dest_addr; + unsigned int dest_port; +}; /***************************************************************************** ***************** Definition of FIG structures **************************** diff --git a/src/ParserConfigfile.cpp b/src/ParserConfigfile.cpp index f4c1075..2ae6555 100644 --- a/src/ParserConfigfile.cpp +++ b/src/ParserConfigfile.cpp @@ -128,7 +128,8 @@ void parse_configfile(string configuration_file, bool* factumAnalyzer, unsigned long* limit, BaseRemoteController** rc, - int* statsServerPort + int* statsServerPort, + edi_configuration_t* edi ) { using boost::property_tree::ptree; @@ -479,40 +480,55 @@ void parse_configfile(string configuration_file, } - /******************** READ OUTPUT PARAMETERS ***************/ map alloutputs; ptree pt_outputs = pt.get_child("outputs"); for (ptree::iterator it = pt_outputs.begin(); it != pt_outputs.end(); ++it) { string outputuid = it->first; - string uri = pt_outputs.get(outputuid); - size_t proto_pos = uri.find("://"); - if (proto_pos == std::string::npos) { - stringstream ss; - ss << "Output with uid " << outputuid << " no protocol defined!"; - throw runtime_error(ss.str()); + if (outputuid == "edi") { + ptree pt_edi = pt_outputs.get_child("edi"); + + edi->enabled = true; + + edi->dest_addr = pt_edi.get("destination"); + edi->dest_port = pt_edi.get("port"); + edi->source_port = pt_edi.get("sourceport"); + + edi->dump = pt_edi.get("dump"); + edi->enable_pft = pt_edi.get("enable_pft"); + edi->verbose = pt_edi.get("verbose"); } + else { + string uri = pt_outputs.get(outputuid); - char* uri_c = new char[512]; - memset(uri_c, 0, 512); - uri.copy(uri_c, 511); + size_t proto_pos = uri.find("://"); + if (proto_pos == std::string::npos) { + stringstream ss; + ss << "Output with uid " << outputuid << " no protocol defined!"; + throw runtime_error(ss.str()); + } - uri_c[proto_pos] = '\0'; + char* uri_c = new char[512]; + memset(uri_c, 0, 512); + uri.copy(uri_c, 511); - char* outputName = uri_c + proto_pos + 3; + uri_c[proto_pos] = '\0'; - dabOutput* output = new dabOutput(uri_c, outputName); - outputs.push_back(output); + char* outputName = uri_c + proto_pos + 3; - // keep outputs in map, and check for uniqueness of the uid - if (alloutputs.count(outputuid) == 0) { - alloutputs[outputuid] = output; - } - else { - stringstream ss; - ss << "output with uid " << outputuid << " not unique!"; - throw runtime_error(ss.str()); + dabOutput* output = new dabOutput(uri_c, outputName); + outputs.push_back(output); + + // keep outputs in map, and check for uniqueness of the uid + if (alloutputs.count(outputuid) == 0) { + alloutputs[outputuid] = output; + } + else { + stringstream ss; + ss << "output with uid " << outputuid << " not unique!"; + throw runtime_error(ss.str()); + } } } diff --git a/src/ParserConfigfile.h b/src/ParserConfigfile.h index 75f4f13..95951d1 100644 --- a/src/ParserConfigfile.h +++ b/src/ParserConfigfile.h @@ -31,6 +31,7 @@ #include #include #include "MuxElements.h" +#include "DabMux.h" #include void parse_configfile(std::string configuration_file, @@ -41,7 +42,8 @@ void parse_configfile(std::string configuration_file, bool* factumAnalyzer, unsigned long* limit, BaseRemoteController** rc, - int* statsServerPort); + int* statsServerPort, + edi_configuration_t* edi); void setup_subchannel_from_ptree(dabSubchannel* subchan, boost::property_tree::ptree &pt, diff --git a/src/dabOutput/edi/AFPacket.cpp b/src/dabOutput/edi/AFPacket.cpp index ae2bdd6..3b69f1c 100644 --- a/src/dabOutput/edi/AFPacket.cpp +++ b/src/dabOutput/edi/AFPacket.cpp @@ -45,13 +45,16 @@ AFPacket AFPacketiser::Assemble(TagPacket tag_packet) { std::vector payload = tag_packet.Assemble(); - std::cerr << "Assemble AFPacket " << seq << std::endl; + if (m_verbose) + std::cerr << "Assemble AFPacket " << seq << std::endl; std::string pack_data("AF"); // SYNC std::vector packet(pack_data.begin(), pack_data.end()); uint32_t taglength = payload.size(); - std::cerr << " AFPacket payload size " << payload.size() << std::endl; + + if (m_verbose) + std::cerr << " AFPacket payload size " << payload.size() << std::endl; // write length into packet packet.push_back((taglength >> 24) & 0xFF); @@ -73,12 +76,14 @@ AFPacket AFPacketiser::Assemble(TagPacket tag_packet) crc = crc16(crc, &(packet.front()), packet.size()); crc ^= 0xffff; - fprintf(stderr, " AFPacket crc %x\n", crc); + if (m_verbose) + fprintf(stderr, " AFPacket crc %x\n", crc); packet.push_back((crc >> 8) & 0xFF); packet.push_back(crc & 0xFF); - std::cerr << " AFPacket length " << packet.size() << std::endl; + if (m_verbose) + std::cerr << " AFPacket length " << packet.size() << std::endl; return packet; } diff --git a/src/dabOutput/edi/AFPacket.h b/src/dabOutput/edi/AFPacket.h index ac3cc28..5f62456 100644 --- a/src/dabOutput/edi/AFPacket.h +++ b/src/dabOutput/edi/AFPacket.h @@ -33,15 +33,14 @@ #include "TagItems.h" #include "TagPacket.h" -#define EDI_AFPACKET_PROTOCOLTYPE_TAGITEMS ('T') - typedef std::vector AFPacket; // ETSI TS 102 821, 6.1 AF packet structure class AFPacketiser { public: - AFPacketiser(char protocolType) : protocol_type(protocolType) {}; + AFPacketiser(bool verbose) : + m_verbose(verbose) {}; AFPacket Assemble(TagPacket tag_packet); @@ -50,7 +49,7 @@ class AFPacketiser uint16_t seq; //counter that overflows at 0xFFFF - char protocol_type; + bool m_verbose; }; #endif diff --git a/src/dabOutput/edi/PFT.cpp b/src/dabOutput/edi/PFT.cpp index ac53f5d..5eaac09 100644 --- a/src/dabOutput/edi/PFT.cpp +++ b/src/dabOutput/edi/PFT.cpp @@ -88,8 +88,9 @@ vector< vector > PFT::ProtectAndFragment(AFPacket af_packet) const size_t fragment_size = m_num_chunks * (m_k + ParityBytes) / max_payload_size; const size_t num_fragments = m_num_chunks * (m_k + ParityBytes) / fragment_size; - fprintf(stderr, " PnF fragment_size %zu, num frag %zu\n", - fragment_size, num_fragments); + if (m_verbose) + fprintf(stderr, " PnF fragment_size %zu, num frag %zu\n", + fragment_size, num_fragments); vector< vector > fragments(num_fragments); @@ -154,8 +155,9 @@ std::vector< PFTFragment > PFT::Assemble(AFPacket af_packet) pft_fragments.push_back(packet); - fprintf(stderr, "* PFT pseq %d, findex %d, fcount %d, plen %d\n", - m_pseq, findex, fcount, plen & ~0x8000); + if (m_verbose) + fprintf(stderr, "* PFT pseq %d, findex %d, fcount %d, plen %d\n", + m_pseq, findex, fcount, plen & ~0x8000); } m_pseq++; diff --git a/src/dabOutput/edi/PFT.h b/src/dabOutput/edi/PFT.h index 54c229f..02380ec 100644 --- a/src/dabOutput/edi/PFT.h +++ b/src/dabOutput/edi/PFT.h @@ -48,11 +48,14 @@ class PFT public: static const int ParityBytes = 48; - PFT(unsigned int RSDataWordLength, unsigned int NumRecoverableFragments) : + PFT(unsigned int RSDataWordLength, + unsigned int NumRecoverableFragments, + bool verbose) : m_k(RSDataWordLength), m_m(NumRecoverableFragments), m_pseq(0), - m_encoder(m_k + ParityBytes, m_k) + m_encoder(m_k + ParityBytes, m_k), + m_verbose(verbose) { if (m_k > 207) { etiLog.level(warn) << @@ -88,6 +91,8 @@ class PFT ReedSolomon m_encoder; + bool m_verbose; + }; #endif diff --git a/src/dabOutput/edi/TagItems.cpp b/src/dabOutput/edi/TagItems.cpp index d4f73d2..488f8c3 100644 --- a/src/dabOutput/edi/TagItems.cpp +++ b/src/dabOutput/edi/TagItems.cpp @@ -36,7 +36,7 @@ std::vector TagStarPTR::Assemble() { - std::cerr << "TagItem *ptr" << std::endl; + //std::cerr << "TagItem *ptr" << std::endl; std::string pack_data("*ptr"); std::vector packet(pack_data.begin(), pack_data.end()); @@ -118,9 +118,11 @@ std::vector TagDETI::Assemble() dflc = (dflc+1) % 5000; + /* std::cerr << "TagItem deti, packet.size " << packet.size() << std::endl; std::cerr << " fic length " << fic_length << std::endl; std::cerr << " length " << taglength / 8 << std::endl; + */ return packet; } @@ -159,8 +161,10 @@ std::vector TagESTn::Assemble() packet[6] = (taglength >> 8) & 0xFF; packet[7] = taglength & 0xFF; + /* std::cerr << "TagItem ESTn, length " << packet.size() << std::endl; std::cerr << " mst_length " << mst_length << std::endl; + */ return packet; } #endif diff --git a/src/dabOutput/edi/TagPacket.cpp b/src/dabOutput/edi/TagPacket.cpp index 0fc9a17..fbb0f8b 100644 --- a/src/dabOutput/edi/TagPacket.cpp +++ b/src/dabOutput/edi/TagPacket.cpp @@ -39,7 +39,7 @@ std::vector TagPacket::Assemble() std::vector packet; - std::cerr << "Assemble TAGPacket" << std::endl; + //std::cerr << "Assemble TAGPacket" << std::endl; size_t packet_length = 0; for (tag = tag_items.begin(); tag != tag_items.end(); ++tag) { @@ -48,7 +48,7 @@ std::vector TagPacket::Assemble() packet_length += tag_data.size(); - std::cerr << " Add TAGItem of length " << tag_data.size() << std::endl; + //std::cerr << " Add TAGItem of length " << tag_data.size() << std::endl; } // Add padding -- cgit v1.2.3