diff options
author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2016-11-12 16:30:30 +0100 |
---|---|---|
committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2016-11-12 16:30:30 +0100 |
commit | 96b4dc4efca1b164f79a7f7394449866f034ac31 (patch) | |
tree | 101b796f40fee444c8193ccc3e13cf5644c83d5f /src | |
parent | 5132756f09c7a0dafe4644db92718ee3d1a58d6c (diff) | |
parent | fedab89cd4625617b3e481f1f59ba0fc97b7305b (diff) | |
download | dabmux-96b4dc4efca1b164f79a7f7394449866f034ac31.tar.gz dabmux-96b4dc4efca1b164f79a7f7394449866f034ac31.tar.bz2 dabmux-96b4dc4efca1b164f79a7f7394449866f034ac31.zip |
Merge branch 'next' into servicelinking
Diffstat (limited to 'src')
58 files changed, 1076 insertions, 4292 deletions
diff --git a/src/ConfigParser.cpp b/src/ConfigParser.cpp index fa12521..1b6093e 100644 --- a/src/ConfigParser.cpp +++ b/src/ConfigParser.cpp @@ -48,29 +48,16 @@ #include <map> #include <cstring> #include "dabOutput/dabOutput.h" -#include "dabInput.h" +#include "input/inputs.h" #include "utils.h" -#include "dabInputFile.h" -#include "dabInputFifo.h" -#include "dabInputMpegFile.h" -#include "dabInputMpegFifo.h" -#include "dabInputDabplusFile.h" -#include "dabInputDabplusFifo.h" -#include "dabInputPacketFile.h" -#include "dabInputEnhancedPacketFile.h" -#include "dabInputEnhancedFifo.h" -#include "dabInputUdp.h" -#include "dabInputBridgeUdp.h" -#include "dabInputTest.h" -#include "dabInputPrbs.h" -#include "dabInputRawFile.h" -#include "dabInputRawFifo.h" -#include "dabInputDmbFile.h" -#include "dabInputDmbUdp.h" -#include "dabInputZmq.h" #include "DabMux.h" #include "ManagementServer.h" +#include "input/Prbs.h" +#include "input/Zmq.h" +#include "input/File.h" +#include "input/Udp.h" + #ifdef _WIN32 # pragma warning ( disable : 4103 ) @@ -112,24 +99,6 @@ static void setup_subchannel_from_ptree(DabSubchannel* subchan, std::shared_ptr<dabEnsemble> ensemble, const string& subchanuid); -/* a helper class to parse hexadecimal ids */ -static int hexparse(std::string input) -{ - int value; - if (input.find("0x") == 0) { - value = strtoll(input.c_str() + 2, nullptr, 16); - } - else { - value = strtoll(input.c_str(), nullptr, 10); - } - - if (errno == ERANGE) { - throw runtime_error("hex conversion: value out of range"); - } - - return value; -} - static uint16_t get_announcement_flag_from_ptree( boost::property_tree::ptree& pt ) @@ -490,7 +459,7 @@ void parse_ptree( catch (runtime_error &e) { etiLog.log(error, "%s\n", e.what()); - throw e; + throw; } @@ -649,13 +618,13 @@ void parse_ptree( parse_linkage(pt, ensemble); } -static dab_input_zmq_config_t setup_zmq_input( +static Inputs::dab_input_zmq_config_t setup_zmq_input( const boost::property_tree::ptree &pt, const std::string& subchanuid) { using boost::property_tree::ptree_error; - dab_input_zmq_config_t zmqconfig; + Inputs::dab_input_zmq_config_t zmqconfig; try { zmqconfig.buffer_size = pt.get<int>("zmq-buffer"); @@ -702,20 +671,19 @@ static void setup_subchannel_from_ptree(DabSubchannel* subchan, throw runtime_error(ss.str()); } - string inputUri = ""; - // fail if no inputUri given unless type is test - if (type != "test") { - inputUri = pt.get<string>("inputuri", ""); + /* Both inputfile and inputuri are supported, and are equivalent. + * inputuri has precedence + */ + string inputUri = pt.get<string>("inputuri", ""); - if (inputUri == "") { - try { - inputUri = pt.get<string>("inputfile"); - } - catch (ptree_error &e) { - stringstream ss; - ss << "Subchannel with uid " << subchanuid << " has no inputUri defined!"; - throw runtime_error(ss.str()); - } + if (inputUri == "") { + try { + inputUri = pt.get<string>("inputfile"); + } + catch (ptree_error &e) { + stringstream ss; + ss << "Subchannel with uid " << subchanuid << " has no inputUri defined!"; + throw runtime_error(ss.str()); } } @@ -730,80 +698,44 @@ static void setup_subchannel_from_ptree(DabSubchannel* subchan, subchan->inputUri = inputUri; - /* The input is of the old_style type, - * with the struct of function pointers, - * and needs to be a DabInputCompatible - */ - bool input_is_old_style = true; - dabInputOperations operations; dabProtection* protection = &subchan->protection; + const bool nonblock = pt.get("nonblock", false); + if (nonblock) { + etiLog.level(warn) << "The nonblock option is not supported"; + } - if (0) { -#if defined(HAVE_FORMAT_MPEG) - } else if (type == "audio") { + if (type == "dabplus" or type == "audio") { subchan->type = subchannel_type_t::Audio; subchan->bitrate = 0; - if (0) { -#if defined(HAVE_INPUT_FILE) - } else if (proto == "file") { - operations = dabInputMpegFileOperations; -#endif // defined(HAVE_INPUT_FILE) -#if defined(HAVE_INPUT_ZEROMQ) - } - else if (proto == "tcp" || - proto == "epgm" || - proto == "ipc") { - input_is_old_style = false; - - auto zmqconfig = setup_zmq_input(pt, subchanuid); - - DabInputZmqMPEG* inzmq = - new DabInputZmqMPEG(subchanuid, zmqconfig); - rcs.enrol(inzmq); - subchan->input = inzmq; - - if (proto == "epgm") { - etiLog.level(warn) << "Using untested epgm:// zeromq input"; + if (proto == "file") { + if (type == "audio") { + subchan->input = make_shared<Inputs::MPEGFile>(); } - else if (proto == "ipc") { - etiLog.level(warn) << "Using untested ipc:// zeromq input"; + else if (type == "dabplus") { + subchan->input = make_shared<Inputs::RawFile>(); + } + else { + throw logic_error("Incomplete handling of file input"); } - -#endif // defined(HAVE_INPUT_ZEROMQ) - } else { - stringstream ss; - ss << "Subchannel with uid " << subchanuid << - ": Invalid protocol for MPEG input (" << - proto << ")" << endl; - throw runtime_error(ss.str()); - } -#endif // defined(HAVE_INPUT_FILE) && defined(HAVE_FORMAT_MPEG) -#if defined(HAVE_FORMAT_DABPLUS) - } else if (type == "dabplus") { - subchan->type = subchannel_type_t::Audio; - subchan->bitrate = 32; - - if (0) { -#if defined(HAVE_INPUT_FILE) - } else if (proto == "file") { - operations = dabInputDabplusFileOperations; -#endif // defined(HAVE_INPUT_FILE) -#if defined(HAVE_INPUT_ZEROMQ) } else if (proto == "tcp" || proto == "epgm" || proto == "ipc") { - input_is_old_style = false; auto zmqconfig = setup_zmq_input(pt, subchanuid); - DabInputZmqAAC* inzmq = - new DabInputZmqAAC(subchanuid, zmqconfig); - - rcs.enrol(inzmq); - subchan->input = inzmq; + if (type == "audio") { + auto inzmq = make_shared<Inputs::ZmqMPEG>(subchanuid, zmqconfig); + rcs.enrol(inzmq.get()); + subchan->input = inzmq; + } + else if (type == "dabplus") { + auto inzmq = make_shared<Inputs::ZmqAAC>(subchanuid, zmqconfig); + rcs.enrol(inzmq.get()); + subchan->input = inzmq; + } if (proto == "epgm") { etiLog.level(warn) << "Using untested epgm:// zeromq input"; @@ -811,44 +743,25 @@ static void setup_subchannel_from_ptree(DabSubchannel* subchan, else if (proto == "ipc") { etiLog.level(warn) << "Using untested ipc:// zeromq input"; } -#endif // defined(HAVE_INPUT_ZEROMQ) - } else { + } + else { stringstream ss; ss << "Subchannel with uid " << subchanuid << - ": Invalid protocol for DAB+ input (" << + ": Invalid protocol for " << type << " input (" << proto << ")" << endl; throw runtime_error(ss.str()); } -#endif // defined(HAVE_FORMAT_DABPLUS) - } else if (type == "bridge") { - // TODO default proto should be udp:// - if (0) { -#if defined(HAVE_FORMAT_BRIDGE) -#if defined(HAVE_INPUT_UDP) - } else if (proto == "udp") { - operations = dabInputBridgeUdpOperations; -#endif // defined(HAVE_INPUT_UDP) -#endif // defined(HAVE_FORMAT_BRIDGE) - } - } else if (type == "data" and proto == "prbs") { - input_is_old_style = false; - - subchan->input = new DabInputPrbs(); + } + else if (type == "data" and proto == "prbs") { + subchan->input = make_shared<Inputs::Prbs>(); subchan->type = subchannel_type_t::DataDmb; subchan->bitrate = DEFAULT_DATA_BITRATE; - } else if (type == "data") { - // TODO default proto should be udp:// - if (0) { -#if defined(HAVE_INPUT_UDP) - } else if (proto == "udp") { - operations = dabInputUdpOperations; -#endif -#if defined(HAVE_INPUT_FILE) && defined(HAVE_FORMAT_RAW) - } else if (proto == "file") { - operations = dabInputRawFileOperations; -#endif - } else if (proto == "fifo") { - operations = dabInputRawFifoOperations; + } + else if (type == "data" or type == "dmb") { + if (proto == "udp") { + subchan->input = make_shared<Inputs::Udp>(); + } else if (proto == "file" or proto == "fifo") { + subchan->input = make_shared<Inputs::RawFile>(); } else { stringstream ss; ss << "Subchannel with uid " << subchanuid << @@ -859,52 +772,23 @@ static void setup_subchannel_from_ptree(DabSubchannel* subchan, subchan->type = subchannel_type_t::DataDmb; subchan->bitrate = DEFAULT_DATA_BITRATE; -#if defined(HAVE_INPUT_TEST) && defined(HAVE_FORMAT_RAW) - } else if (type == "test") { - subchan->type = subchannel_type_t::DataDmb; - subchan->bitrate = DEFAULT_DATA_BITRATE; - operations = dabInputTestOperations; -#endif // defined(HAVE_INPUT_TEST)) && defined(HAVE_FORMAT_RAW) -#ifdef HAVE_FORMAT_PACKET - } else if (type == "packet") { - subchan->type = subchannel_type_t::Packet; - subchan->bitrate = DEFAULT_PACKET_BITRATE; -#ifdef HAVE_INPUT_FILE - operations = dabInputPacketFileOperations; -#elif defined(HAVE_INPUT_FIFO) - operations = dabInputFifoOperations; -#else -# pragma error("Must define at least one packet input") -#endif // defined(HAVE_INPUT_FILE) -#ifdef HAVE_FORMAT_EPM - } else if (type == "enhancedpacket") { + + if (type == "dmb") { + /* The old dmb input took care of interleaving and Reed-Solomon encoding. This + * code is unported. + * See dabInputDmbFile.cpp + */ + etiLog.level(warn) << "uid " << subchanuid << " of type Dmb uses RAW input"; + } + } + else if (type == "packet" or type == "enhancedpacket") { subchan->type = subchannel_type_t::Packet; subchan->bitrate = DEFAULT_PACKET_BITRATE; - operations = dabInputEnhancedPacketFileOperations; -#endif // defined(HAVE_FORMAT_EPM) -#endif // defined(HAVE_FORMAT_PACKET) -#ifdef HAVE_FORMAT_DMB - } else if (type == "dmb") { - // TODO default proto should be UDP - if (0) { -#if defined(HAVE_INPUT_UDP) - } else if (proto == "udp") { - operations = dabInputDmbUdpOperations; -#endif - } else if (proto == "file") { - operations = dabInputDmbFileOperations; - } else { - stringstream ss; - ss << "Subchannel with uid " << subchanuid << - ": Invalid protocol for DMB input (" << - proto << ")" << endl; - throw runtime_error(ss.str()); - } - subchan->type = subchannel_type_t::DataDmb; - subchan->bitrate = DEFAULT_DATA_BITRATE; -#endif - } else { + bool enhanced = (type == "enhancedpacket"); + subchan->input = make_shared<Inputs::PacketFile>(enhanced); + } + else { stringstream ss; ss << "Subchannel with uid " << subchanuid << " has unknown type!"; throw runtime_error(ss.str()); @@ -915,7 +799,8 @@ static void setup_subchannel_from_ptree(DabSubchannel* subchan, protection->form = UEP; protection->level = 2; protection->uep.tableIndex = 0; - } else { + } + else { protection->level = 2; protection->form = EEP; protection->eep.profile = EEP_A; @@ -937,55 +822,7 @@ static void setup_subchannel_from_ptree(DabSubchannel* subchan, throw runtime_error(ss.str()); } -#if defined(HAVE_INPUT_FIFO) && defined(HAVE_INPUT_FILE) - /* Get nonblock */ - bool nonblock = pt.get("nonblock", false); - if (nonblock) { - switch (subchan->type) { -#ifdef HAVE_FORMAT_PACKET - case subchannel_type_t::Packet: - if (operations == dabInputPacketFileOperations) { - operations = dabInputFifoOperations; -#ifdef HAVE_FORMAT_EPM - } else if (operations == dabInputEnhancedPacketFileOperations) { - operations = dabInputEnhancedFifoOperations; -#endif // defined(HAVE_FORMAT_EPM) - } else { - stringstream ss; - ss << "Error, wrong packet operations for subchannel " << - subchanuid; - throw runtime_error(ss.str()); - } - break; -#endif // defined(HAVE_FORMAT_PACKET) -#ifdef HAVE_FORMAT_MPEG - case subchannel_type_t::Audio: - if (operations == dabInputMpegFileOperations) { - operations = dabInputMpegFifoOperations; - } else if (operations == dabInputDabplusFileOperations) { - operations = dabInputDabplusFifoOperations; - } else { - stringstream ss; - ss << "Error, wrong audio operations for subchannel " << - subchanuid; - throw runtime_error(ss.str()); - } - break; -#endif // defined(HAVE_FORMAT_MPEG) - case subchannel_type_t::DataDmb: - case subchannel_type_t::Fidc: - default: - stringstream ss; - ss << "Subchannel with uid " << subchanuid << - " non-blocking I/O only available for audio or packet services!"; - throw runtime_error(ss.str()); - } -#endif // defined(HAVE_INPUT_FIFO) && defined(HAVE_INPUT_FILE) - } - - /* Get id */ - try { subchan->id = hexparse(pt.get<std::string>("id")); } @@ -1045,11 +882,5 @@ static void setup_subchannel_from_ptree(DabSubchannel* subchan, ": protection level undefined!"; throw runtime_error(ss.str()); } - - /* Create object */ - if (input_is_old_style) { - subchan->input = new DabInputCompatible(operations); - } - // else { it's already been created! } } diff --git a/src/DabMux.cpp b/src/DabMux.cpp index 2af58c5..04d1980 100644 --- a/src/DabMux.cpp +++ b/src/DabMux.cpp @@ -94,24 +94,8 @@ typedef DWORD32 uint32_t; # include "Eti.h" #endif -#include "dabInputFile.h" -#include "dabInputFifo.h" -#include "dabInputMpegFile.h" -#include "dabInputMpegFifo.h" -#include "dabInputDabplusFile.h" -#include "dabInputDabplusFifo.h" -#include "dabInputPacketFile.h" -#include "dabInputEnhancedPacketFile.h" -#include "dabInputEnhancedFifo.h" -#include "dabInputUdp.h" -#include "dabInputBridgeUdp.h" -#include "dabInputTest.h" -#include "dabInputPrbs.h" -#include "dabInputRawFile.h" -#include "dabInputRawFifo.h" -#include "dabInputDmbFile.h" -#include "dabInputDmbUdp.h" - +#include "input/Prbs.h" +#include "input/Zmq.h" #include "dabOutput/dabOutput.h" #include "dabOutput/edi/TagItems.h" @@ -411,7 +395,7 @@ int main(int argc, char *argv[]) if (outputs.size() == 0) { - etiLog.log(emerg, "no output defined"); + etiLog.log(alert, "no output defined"); throw MuxInitException(); } @@ -491,7 +475,7 @@ int main(int argc, char *argv[]) outputs.clear(); if (returnCode != 0) { - etiLog.log(emerg, "...aborting\n"); + etiLog.log(alert, "...aborting\n"); } else { etiLog.log(debug, "...done\n"); } diff --git a/src/DabMux.h b/src/DabMux.h index 5dda759..80b4881 100644 --- a/src/DabMux.h +++ b/src/DabMux.h @@ -25,8 +25,7 @@ You should have received a copy of the GNU General Public License along with ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef _DABMUX_H -#define _DABMUX_H +#pragma once #include <stdint.h> #include <string> @@ -34,7 +33,7 @@ #include "DabMultiplexer.h" #include "RemoteControl.h" #include "dabOutput/dabOutput.h" -#include "dabInput.h" +#include "input/inputs.h" #include "Eti.h" #include "MuxElements.h" @@ -44,5 +43,3 @@ # include <sys/time.h> #endif -#endif - diff --git a/src/Makefile.am b/src/Makefile.am index 1d33231..de2aa37 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -47,25 +47,11 @@ odr_dabmux_LDADD =$(ZMQ_LIBS) $(CURL_LIBS) \ odr_dabmux_SOURCES =DabMux.cpp DabMux.h \ DabMultiplexer.cpp DabMultiplexer.h \ - dabInput.h dabInput.cpp \ - dabInputBridgeUdp.h dabInputBridgeUdp.cpp \ - dabInputDabplusFifo.h dabInputDabplusFifo.cpp \ - dabInputDabplusFile.h dabInputDabplusFile.cpp \ - dabInputDmbFile.h dabInputDmbFile.cpp \ - dabInputDmbUdp.h dabInputDmbUdp.cpp \ - dabInputEnhancedFifo.h dabInputEnhancedFifo.cpp \ - dabInputEnhancedPacketFile.h dabInputEnhancedPacketFile.cpp \ - dabInputFifo.h dabInputFifo.cpp \ - dabInputFile.h dabInputFile.cpp \ - dabInputMpegFifo.h dabInputMpegFifo.cpp \ - dabInputMpegFile.h dabInputMpegFile.cpp \ - dabInputPacketFile.h dabInputPacketFile.cpp \ - dabInputPrbs.h dabInputPrbs.cpp \ - dabInputRawFile.h dabInputRawFile.cpp \ - dabInputRawFifo.h dabInputRawFifo.cpp \ - dabInputTest.h dabInputTest.cpp \ - dabInputUdp.h dabInputUdp.cpp \ - dabInputZmq.h dabInputZmq.cpp \ + input/inputs.h \ + input/Prbs.cpp input/Prbs.h \ + input/Zmq.cpp input/Zmq.h \ + input/File.cpp input/File.h \ + input/Udp.cpp input/Udp.h \ dabOutput/dabOutput.h \ dabOutput/dabOutputFile.cpp \ dabOutput/dabOutputFifo.cpp \ @@ -80,7 +66,6 @@ odr_dabmux_SOURCES =DabMux.cpp DabMux.h \ dabOutput/edi/PFT.cpp dabOutput/edi/PFT.h \ ClockTAI.h ClockTAI.cpp \ ConfigParser.cpp ConfigParser.h \ - Dmb.h Dmb.cpp \ Eti.h Eti.cpp \ InetAddress.h InetAddress.cpp \ Interleaver.h Interleaver.cpp \ @@ -93,7 +78,6 @@ odr_dabmux_SOURCES =DabMux.cpp DabMux.h \ TcpSocket.h TcpSocket.cpp \ UdpSocket.h UdpSocket.cpp \ ThreadsafeQueue.h \ - bridge.h bridge.c \ crc.h crc.c \ fig/FIG.h fig/FIG.cpp \ fig/FIG0.h fig/FIG0structs.h \ diff --git a/src/MuxElements.cpp b/src/MuxElements.cpp index 2215bda..7f92652 100644 --- a/src/MuxElements.cpp +++ b/src/MuxElements.cpp @@ -385,7 +385,7 @@ void DabComponent::set_parameter(const string& parameter, throw ParameterError(ss.str()); default: ss << m_name << " short label definition: program error !"; - etiLog.level(emerg) << ss.str(); + etiLog.level(alert) << ss.str(); throw ParameterError(ss.str()); } } @@ -500,7 +500,7 @@ void DabService::set_parameter(const string& parameter, throw ParameterError(ss.str()); default: ss << m_name << " short label definition: program error !"; - etiLog.level(emerg) << ss.str(); + etiLog.level(alert) << ss.str(); throw ParameterError(ss.str()); } } diff --git a/src/MuxElements.h b/src/MuxElements.h index 79100a9..7ff23a6 100644 --- a/src/MuxElements.h +++ b/src/MuxElements.h @@ -40,7 +40,7 @@ #include <boost/optional.hpp> #include <stdint.h> #include "dabOutput/dabOutput.h" -#include "dabInput.h" +#include "input/inputs.h" #include "RemoteControl.h" #include "Eti.h" @@ -297,7 +297,7 @@ public: std::string uid; std::string inputUri; - DabInputBase* input; + std::shared_ptr<Inputs::InputBase> input; unsigned char id; subchannel_type_t type; uint16_t startAddress; diff --git a/src/TcpSocket.cpp b/src/TcpSocket.cpp index 433e5c1..b9824fa 100644 --- a/src/TcpSocket.cpp +++ b/src/TcpSocket.cpp @@ -39,31 +39,30 @@ using namespace std; TcpSocket::TcpSocket() : m_sock(INVALID_SOCKET) { - if ((m_sock = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { - throw std::runtime_error("Can't create socket"); - } } TcpSocket::TcpSocket(int port, const string& name) : m_sock(INVALID_SOCKET) { - if ((m_sock = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { - throw std::runtime_error("Can't create socket"); - } + if (port) { + if ((m_sock = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { + throw std::runtime_error("Can't create socket"); + } - reuseopt_t reuse = 1; - if (setsockopt(m_sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) - == SOCKET_ERROR) { - throw std::runtime_error("Can't reuse address"); - } + reuseopt_t reuse = 1; + if (setsockopt(m_sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) + == SOCKET_ERROR) { + throw std::runtime_error("Can't reuse address"); + } - m_own_address.setAddress(name); - m_own_address.setPort(port); + m_own_address.setAddress(name); + m_own_address.setPort(port); - if (bind(m_sock, m_own_address.getAddress(), sizeof(sockaddr_in)) == SOCKET_ERROR) { - ::close(m_sock); - m_sock = INVALID_SOCKET; - throw std::runtime_error("Can't bind socket"); + if (bind(m_sock, m_own_address.getAddress(), sizeof(sockaddr_in)) == SOCKET_ERROR) { + ::close(m_sock); + m_sock = INVALID_SOCKET; + throw std::runtime_error("Can't bind socket"); + } } } @@ -116,6 +115,11 @@ TcpSocket::~TcpSocket() close(); } +bool TcpSocket::isValid() +{ + return m_sock != INVALID_SOCKET; +} + ssize_t TcpSocket::recv(void* data, size_t size) { ssize_t ret = ::recv(m_sock, (char*)data, size, 0); @@ -167,7 +171,7 @@ TcpSocket TcpSocket::accept() } } -boost::optional<TcpSocket> TcpSocket::accept(int timeout_ms) +TcpSocket TcpSocket::accept(int timeout_ms) { struct pollfd fds[1]; fds[0].fd = m_sock; @@ -184,7 +188,8 @@ boost::optional<TcpSocket> TcpSocket::accept(int timeout_ms) return accept(); } else { - return boost::none; + TcpSocket invalidsock(0, ""); + return invalidsock; } } diff --git a/src/TcpSocket.h b/src/TcpSocket.h index 5a4a808..660515d 100644 --- a/src/TcpSocket.h +++ b/src/TcpSocket.h @@ -46,7 +46,7 @@ #include <iostream> #include <string> -#include <boost/optional.hpp> +#include <memory> /** * This class represents a TCP socket. @@ -67,8 +67,12 @@ class TcpSocket ~TcpSocket(); TcpSocket(TcpSocket&& other); TcpSocket& operator=(TcpSocket&& other); + TcpSocket(const TcpSocket& other) = delete; + TcpSocket& operator=(const TcpSocket& other) = delete; - int close(); + bool isValid(void); + + int close(void); /** Send data over the TCP connection. * @param data The buffer that will be sent. @@ -86,7 +90,12 @@ class TcpSocket void listen(void); TcpSocket accept(void); - boost::optional<TcpSocket> accept(int timeout_ms); + + /* Returns either valid socket if a connection was + * accepted before the timeout expired, or an invalid + * socket otherwise. + */ + TcpSocket accept(int timeout_ms); /** Retrieve address this socket is bound to */ InetAddress getOwnAddress() const; @@ -94,8 +103,6 @@ class TcpSocket private: TcpSocket(SOCKET sock, InetAddress own, InetAddress remote); - TcpSocket(const TcpSocket& other) = delete; - TcpSocket& operator=(const TcpSocket& other) = delete; /// The address on which the socket is bound. InetAddress m_own_address; diff --git a/src/UdpSocket.cpp b/src/UdpSocket.cpp index 020e3f5..ccdd7ed 100644 --- a/src/UdpSocket.cpp +++ b/src/UdpSocket.cpp @@ -37,19 +37,19 @@ using namespace std; UdpSocket::UdpSocket() : listenSocket(INVALID_SOCKET) { - init_sock(0, ""); + reinit(0, ""); } UdpSocket::UdpSocket(int port) : listenSocket(INVALID_SOCKET) { - init_sock(port, ""); + reinit(port, ""); } UdpSocket::UdpSocket(int port, const std::string& name) : listenSocket(INVALID_SOCKET) { - init_sock(port, name); + reinit(port, name); } @@ -67,7 +67,7 @@ int UdpSocket::setBlocking(bool block) return 0; } -int UdpSocket::init_sock(int port, const std::string& name) +int UdpSocket::reinit(int port, const std::string& name) { if (listenSocket != INVALID_SOCKET) { ::close(listenSocket); @@ -98,6 +98,16 @@ int UdpSocket::init_sock(int port, const std::string& name) return 0; } +int UdpSocket::close() +{ + if (listenSocket != INVALID_SOCKET) { + ::close(listenSocket); + } + + listenSocket = INVALID_SOCKET; + + return 0; +} UdpSocket::~UdpSocket() { diff --git a/src/UdpSocket.h b/src/UdpSocket.h index 535499e..dfeaac1 100644 --- a/src/UdpSocket.h +++ b/src/UdpSocket.h @@ -80,6 +80,15 @@ class UdpSocket UdpSocket(const UdpSocket& other) = delete; const UdpSocket& operator=(const UdpSocket& other) = delete; + /** reinitialise socket. Close the already open socket, and + * create a new one + */ + int reinit(int port, const std::string& name); + + /** Close the socket + */ + int close(void); + /** Send an UDP packet. * @param packet The UDP packet to be sent. It includes the data and the * destination address @@ -111,7 +120,6 @@ class UdpSocket int setBlocking(bool block); protected: - int init_sock(int port, const std::string& name); /// The address on which the socket is bound. InetAddress address; diff --git a/src/bridge.c b/src/bridge.c deleted file mode 100644 index d66a7b2..0000000 --- a/src/bridge.c +++ /dev/null @@ -1,515 +0,0 @@ -/* - Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the - Queen in Right of Canada (Communications Research Center Canada) - */ -/* - This file is part of ODR-DabMux. - - ODR-DabMux 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 3 of the - License, or (at your option) any later version. - - ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdio.h> -#ifdef _WIN32 -# include <winsock2.h> -#else -# include <netinet/in.h> -#endif // _WIN32 -#include <string.h> -#include "bridge.h" -#include "crc.h" - -#include <assert.h> -#include "PcDebug.h" - -#ifdef _WIN32 -# ifdef _DEBUG - int bridgeVerbosity = 0; -# endif -#else -# ifdef DEBUG - int bridgeVerbosity = 0; -# endif -#endif - -void printStats(struct bridgeInfo* info, FILE* out) -{ - struct bridgeStats stats = getStats(info); - fprintf(out, "frames : %lu\n", stats.frames); - fprintf(out, " valids : %lu\n", stats.valids); - fprintf(out, " invalids : %lu\n", stats.invalids); - fprintf(out, " bytes : %lu\n", stats.bytes); - fprintf(out, " packets : %lu\n", stats.packets); - fprintf(out, " errors : %lu\n", stats.errors); - fprintf(out, " missings : %lu\n", stats.missings); - fprintf(out, " dropped : %lu\n", stats.dropped); - fprintf(out, " crc : %lu\n", stats.crc); - fprintf(out, " overruns : %lu\n", stats.overruns); -} - - -void resetStats(struct bridgeInfo* info) -{ - memset(&info->stats, 0, sizeof(info->stats)); -} - - -struct bridgeStats getStats(struct bridgeInfo* info) -{ - return info->stats; -} - - -void bridgeInitInfo(struct bridgeInfo* info) -{ - memset(info, 0, sizeof(*info)); - info->transmitted = -8; -}; - - -int writePacket(void* dataIn, int sizeIn, void* dataOut, int sizeOut, - struct bridgeInfo* info) -{ - static struct bridgeHdr header = { 0 }; - - PDEBUG4_VERBOSE(1, bridgeVerbosity, "writePacket\n sizeIn: %i, sizeOut: %i, " - "offset: %i, transmitted: %i\n", - sizeIn, sizeOut, info->offset, info->transmitted); - - assert(info->transmitted < sizeIn); - - if ((info->offset == 0) && (sizeIn > 0)) { - ((unsigned short*)dataOut)[0] = 0xb486; - info->offset = 2; - } - if (sizeIn == 0) { - memset((unsigned char*)dataOut + info->offset, 0, sizeOut - info->offset); - info->offset = 0; - info->transmitted = -8; - PDEBUG1_VERBOSE(1, bridgeVerbosity, " return %i (sizeIn == 0)\n", - sizeOut); - return 0; - } - - while (info->offset < sizeOut) { - switch (info->transmitted) { - case (-8): - ((unsigned char*)dataOut)[info->offset++] = 0xcb; - ++info->transmitted; - break; - case (-7): - ((unsigned char*)dataOut)[info->offset++] = 0x28; - ++info->transmitted; - break; - case (-6): - header.size = htons((unsigned short)sizeIn); - header.crc = htons((unsigned short)(crc16(0xffff, &header, 4) ^ 0xffff)); - ((unsigned char*)dataOut)[info->offset++] = ((char*)&header)[0]; - ++info->transmitted; - break; - case (-5): - ((unsigned char*)dataOut)[info->offset++] = ((char*)&header)[1]; - ++info->transmitted; - break; - case (-4): - ((unsigned char*)dataOut)[info->offset++] = ((char*)&header)[2]; - ++info->transmitted; - break; - case (-3): - ((unsigned char*)dataOut)[info->offset++] = ((char*)&header)[3]; - ++info->transmitted; - break; - case (-2): - ((unsigned char*)dataOut)[info->offset++] = ((char*)&header)[4]; - ++info->transmitted; - break; - case (-1): - ((unsigned char*)dataOut)[info->offset++] = ((char*)&header)[5]; - ++info->transmitted; - header.seqNb = htons((unsigned short)(ntohs(header.seqNb) + 1)); - break; - default: - ((unsigned char*)dataOut)[info->offset++] = - ((unsigned char*)dataIn)[info->transmitted++]; - if (info->transmitted == sizeIn) { - PDEBUG2_VERBOSE(1, bridgeVerbosity, - " Packet done, %i bytes at offset %i\n", - info->transmitted, info->offset); - PDEBUG1_VERBOSE(1, bridgeVerbosity, - " return %i (sizeIn == transmitted)\n", info->offset); - info->transmitted = -8; - return info->offset; - } - } - } - - PDEBUG1_VERBOSE(1, bridgeVerbosity, " return %i (offset >= sizeOut)\n", - info->offset); - info->offset = 0; - return 0; -} - - -int getPacket(void* dataIn, int sizeIn, void* dataOut, int sizeOut, - struct bridgeInfo* info, char async) -{ - unsigned char* in = (unsigned char*)dataIn; - unsigned char* out = (unsigned char*)dataOut; - unsigned char ch; - unsigned short crc; - unsigned short diff; - - PDEBUG3_VERBOSE(1, bridgeVerbosity, - "getPacket\n pos\t%i\n state\t%i\n received\t%i\n", - info->pos, info->state, info->received); - - if (info->pos == 0) { - ++info->stats.frames; - if (((unsigned short*)dataIn)[0] != 0xb486) { - if (((unsigned short*)dataIn)[0] != 0) { - ++info->stats.invalids; - printf("WARNING: processing frame with invalid magic " - "number!\n"); - } else { - PDEBUG0_VERBOSE(1, bridgeVerbosity, - "getPacket: not a valid frame\n"); - return 0; - } - } else { - PDEBUG0_VERBOSE(2, bridgeVerbosity, "Valid frame\n"); - info->pos += 2; - ++info->stats.valids; - } - info->stats.bytes += sizeIn; - } - while (info->pos < sizeIn) { - ch = in[info->pos++]; - switch (info->state) { - case 0: // sync search - info->sync <<= 8; - info->sync |= ch; - if (info->sync == 0xcb28) { - PDEBUG0_VERBOSE(2, bridgeVerbosity, "Sync found\n"); - ++info->stats.packets; - info->received = 0; - info->state = 1; - } - if (info->sync == 0) { // Padding - info->pos = 0; - return 0; - } - break; - case 1: // header search - ((char*)&info->header)[info->received++] = ch; - if (info->received == sizeof(struct bridgeHdr)) { - PDEBUG0_VERBOSE(2, bridgeVerbosity, "Header found\n"); - out = (unsigned char*)dataOut; - info->received = 0; - info->state = 2; - crc = crc16(0xffff, &info->header, 4); - crc ^= 0xffff; - info->header.size = ntohs(info->header.size); - info->header.seqNb = ntohs(info->header.seqNb); - info->header.crc = ntohs(info->header.crc); - PDEBUG4_VERBOSE(2, bridgeVerbosity, - " size\t%i\n seq\t%i\n crc\t0x%.4x (0x%.4x)\n", - info->header.size, info->header.seqNb, - info->header.crc, crc); - if (crc != info->header.crc) { - PDEBUG0_VERBOSE(2, bridgeVerbosity, "CRC error\n"); - ++info->stats.errors; - ++info->stats.crc; - info->state = 0; - if (info->pos < sizeof(struct bridgeHdr) + 2 + 2) { - info->pos = 2; - } - } else { - if (!info->initSeq) { - info->lastSeq = info->header.seqNb; - info->initSeq = 1; - } else { - if (info->header.seqNb > info->lastSeq) { - diff = (info->header.seqNb - info->lastSeq) - 1; - } else { - diff = ((short)info->lastSeq - - (short)info->header.seqNb) - 1; - } - info->stats.errors += diff; - info->stats.missings += diff; - info->lastSeq = info->header.seqNb; - } - } - } - break; - case 2: // data - out[info->received++] = ch; - if (info->received == info->header.size) { - PDEBUG0_VERBOSE(2, bridgeVerbosity, "data found\n"); - info->state = 0; - return info->received; - } - if (info->received == sizeOut) { - PDEBUG1_VERBOSE(1, bridgeVerbosity, "To much data: %i\n", - info->received); - ++info->stats.errors; - ++info->stats.overruns; - info->sync = 0; - info->state = 0; - return -1; - } - break; - case 3: // Padding or sync - if (ch == 0) { // Padding - info->pos = 0; - return 0; - } - if (ch != 0xcb) { // error - info->sync = ch; - info->state = 0; - } else { - info->state = 4; - } - break; - case 4: // Low byte sync - if (ch != 28) { // error - info->sync <<= 8; - info->sync |= ch; - info->state = 0; - } else { - info->state = 2; - } - break; - } - } - info->pos = 0; - return 0; -} - - -void dump(void* data, int size, FILE* stream) -{ - int i; - fprintf(stream, "%i bytes\n", size); - for (i = 0; i < size; ++i) { - fprintf(stream, " 0x%.2x", ((unsigned char*)data)[i]); - if (i % 8 == 7) - fprintf(stream, "\n"); - } - fprintf(stream, "\n"); -} - - -#ifdef BRIDGE_TEST -#include <stdlib.h> - - -int test(const unsigned char* data) -{ - unsigned char bridgeSize = data[0]; - unsigned char nbInput = data[1]; - unsigned char nbBridge = 1; - struct bridgeInfo info; - - int i, j; - int index = 0; - int max = 0; - int nbBytes; - - unsigned char** inputData; - unsigned char** bridgeData; - unsigned char* outputData; - - inputData = malloc(nbInput * 4); - bridgeData = malloc(nbBridge * 4); - for (i = 0; i < nbInput; ++i) { - if (data[i + 2] > 0) - inputData[i] = malloc(data[i + 2]); - if (data[i + 2] > max) { - max = data[i + 2]; - } - for (j = 0; j < data[i + 2]; ++j) { - inputData[i][j] = index++; - } - } - bridgeData[0] = malloc(bridgeSize); - memset(bridgeData[0], 0, bridgeSize); - outputData = malloc(max); - bridgeInitInfo(&info); - - // Write packets - index = 0; - while (1) { - if (data[index + 2] == 0) { - if (++index == nbInput) - break; - } - while ((nbBytes = writePacket(inputData[index], data[index + 2], - bridgeData[nbBridge - 1], bridgeSize, &info)) - != 0) { - if (++index == nbInput) { - break; - } - } - if (index == nbInput) - break; - // TODO check null - bridgeData = realloc(bridgeData, (++nbBridge) * 4); - bridgeData[nbBridge - 1] = malloc(bridgeSize); - memset(bridgeData[nbBridge - 1], 0, bridgeSize); - } -// if (nbBytes != bridgeSize) { - writePacket(NULL, 0, bridgeData[nbBridge - 1], bridgeSize, &info); -// } - - // read packets - index = 0; - for (i = 0; i < nbBridge; ++i) { - while ((nbBytes = getPacket(bridgeData[i], bridgeSize, outputData, max, - &info, 0)) != 0) { - while (data[index + 2] == 0) { - ++index; - } - if (nbBytes != data[index + 2]) { - printf("FAILED\n"); - printf("Invalid size at bridge %i, data %i: %i != %i\n", - i, index, nbBytes, data[index + 2]); - for (i = 0; i < nbInput; ++i) { - printf("Input %i: ", i); - dump(inputData[i], data[i + 2], stdout); - } - for (i = 0; i < nbBridge; ++i) { - printf("Bridge %i: ", i); - dump(bridgeData[i], bridgeSize, stdout); - } - printf("Output %i: ", index); - dump(outputData, nbBytes, stdout); - return -1; - } - if (memcmp(outputData, inputData[index], data[index + 2]) != 0) { - printf("FAILED\n"); - printf("output != input\n"); - for (i = 0; i < nbInput; ++i) { - printf("Input %i: ", i); - dump(inputData[i], data[i + 2], stdout); - } - for (i = 0; i < nbBridge; ++i) { - printf("Bridge %i: ", i); - dump(bridgeData[i], bridgeSize, stdout); - } - printf("Output %i: ", index); - dump(outputData, nbBytes, stdout); - } - ++index; - } - } - - printf("SUCCESS\n"); - - for (i = 0; i < nbInput; ++i) { - if (data[i + 2] > 0) - free(inputData[i]); - } - free(inputData); - free(outputData); - for (i = 0; i < nbBridge; ++i) { - free(bridgeData[i]); - } - free(bridgeData); - - return -1; -} - - -int main(int argc, char* argv[]) -{ - int i; - // test: bridgesize, nbinput [, input1, input2, ... ] - const unsigned char complete[] = { 32, 1, 16 }; - const unsigned char split[] = { 32, 1, 48 }; - const unsigned char twice[] = {32, 2, 8, 4 }; - const unsigned char secondSplit[] = { 32, 2, 16, 16 }; - const unsigned char headerSplit[][4] = { - { 32, 2, 23, 16 }, - { 32, 2, 22, 16 }, - { 32, 2, 21, 16 }, - { 32, 2, 20, 16 }, - { 32, 2, 19, 16 }, - { 32, 2, 18, 16 }, - { 32, 2, 17, 16 } - }; - const unsigned char two[] = { 32, 3, 16, 0, 16 }; - const unsigned char doubleSplit[] = { 32, 2, 32, 32 }; - const unsigned char full[] = { 32, 2, 24, 12 }; - const unsigned char empty[] = { 32, 3, 0, 0, 5 }; - -#ifdef _WIN32 - #ifdef _DEBUG - bridgeVerbosity = argc - 1; - #endif // DEBUG -#else - #ifdef DEBUG - bridgeVerbosity = argc - 1; - #endif // DEBUG -#endif // _WIN32 - - printf("Complete: "); - test(complete); - // printStats(stdout); - fflush(stdout); - - printf("split: "); - test(split); - // printStats(stdout); - fflush(stdout); - - printf("twice: "); - test(twice); - // printStats(stdout); - fflush(stdout); - - printf("second split: "); - test(secondSplit); - // printStats(stdout); - fflush(stdout); - - for (i = 0; i < sizeof(headerSplit) / sizeof(headerSplit[0]); ++i) { - printf("headerSplit%i: ", i); - test(headerSplit[i]); - // printStats(stdout); - fflush(stdout); - } - - printf("two: "); - test(two); - // printStats(stdout); - fflush(stdout); - - printf("doubleSplit: "); - test(doubleSplit); - // printStats(stdout); - fflush(stdout); - - printf("full: "); - test(full); - // printStats(stdout); - fflush(stdout); - - printf("empty: "); - test(empty); - // printStats(stdout); - fflush(stdout); - - return 0; -} - -#endif // BRIDGE_TEST diff --git a/src/bridge.h b/src/bridge.h deleted file mode 100644 index 0bae007..0000000 --- a/src/bridge.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the - Queen in Right of Canada (Communications Research Center Canada) - */ -/* - This file is part of ODR-DabMux. - - ODR-DabMux 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 3 of the - License, or (at your option) any later version. - - ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef _BRIDGE -#define _BRIDGE - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdio.h> - - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _WIN32 -# ifdef _DEBUG - extern int bridgeVerbosity; -# endif // _DEBUG -#else -# ifndef DEBUG -# ifndef NDEBUG -# define NDEBUG -# endif -# else - extern int bridgeVerbosity; -# endif // DEBUG -#endif // _WIN32 - -struct bridgeStats { - unsigned long frames; // Number of frames analyzed - unsigned long valids; // Nb of frames with a good magic number - unsigned long invalids; // Nb of frames with a good magic number - unsigned long bytes; // Nb of data bytes - unsigned long packets; // Nb of packets found - unsigned long errors; - unsigned long missings; - unsigned long dropped; - unsigned long crc; // Nb of crc errors - unsigned long overruns; // Nb of packet too big -}; - - -struct bridgeHdr { - unsigned short size; - unsigned short seqNb; - unsigned short crc; -}; - - -struct bridgeInfo { - // Tx - int transmitted; // Nb bytes written - int offset; // Offset of the next byte to write - // Rx - int received; - int pos; - int state; - unsigned short lastSeq; - unsigned short sync; - char initSeq; - // General - struct bridgeHdr header; - struct bridgeStats stats; -}; - - - -void dump(void* data, int size, FILE* stream); - -/* - * Example of usae: - * if (data.length == 0) - * read(data) - * while (writePacket() != 0) - * read(read) - * ... - */ -int writePacket(void* dataIn, int sizeIn, void* dataOut, int sizeOut, struct bridgeInfo* info); - -int getPacket(void* dataIn, int sizeIn, void* dataOut, int sizeOut, struct bridgeInfo* info, char async); - -void bridgeInitInfo(struct bridgeInfo* info); -struct bridgeStats getStats(struct bridgeInfo* info); -void resetStats(struct bridgeInfo* info); -void printStats(struct bridgeInfo* info, FILE* out); - -#ifdef __cplusplus -} -#endif - -#endif // _BRIDGE diff --git a/src/dabInput.h b/src/dabInput.h deleted file mode 100644 index f1b4348..0000000 --- a/src/dabInput.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in - Right of Canada (Communications Research Center Canada) - */ -/* - This file is part of ODR-DabMux. - - ODR-DabMux 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 3 of the - License, or (at your option) any later version. - - ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef DAB_INPUT_H -#define DAB_INPUT_H - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif -#include "Log.h" -#include "RemoteControl.h" -#include <string> - -extern Logger etiLog; - -// TODO replace usage of dabInputOperations by a -// class hierarchy -struct dabInputOperations { - int (*init)(void** args); - int (*open)(void* args, const char* name); - int (*setbuf)(void* args, int size); - int (*read)(void* args, void* buffer, int size); - int (*lock)(void* args); - int (*unlock)(void* args); - int (*readFrame)(dabInputOperations* ops, void* args, void* buffer, int size); - int (*setBitrate)(dabInputOperations* ops, void* args, int bitrate); - int (*close)(void* args); - int (*clean)(void** args); - int (*rewind)(void* args); - bool operator==(const dabInputOperations&); -}; - -/* New input object base */ -class DabInputBase { - public: - virtual int open(const std::string name) = 0; - virtual int readFrame(void* buffer, int size) = 0; - virtual int setBitrate(int bitrate) = 0; - virtual int close() = 0; - - virtual ~DabInputBase() {} - protected: - DabInputBase() {} -}; - -/* Wrapper class for old-style dabInputOperations inputs */ -class DabInputCompatible : public DabInputBase { - public: - DabInputCompatible(dabInputOperations ops) - : m_ops(ops) - { m_ops.init(&args); } - - virtual ~DabInputCompatible() - { m_ops.clean(&args); } - - virtual int open(const std::string name) - { return m_ops.open(args, name.c_str()); } - - virtual int setbuf(int size) - { return m_ops.setbuf(args, size); } - - virtual int readFrame(void* buffer, int size) - { - if (m_ops.lock) { - m_ops.lock(args); - } - int result = m_ops.readFrame(&m_ops, args, buffer, size); - if (m_ops.unlock) { - m_ops.unlock(args); - } - return result; - } - - virtual int setBitrate(int bitrate) - { return m_ops.setBitrate(&m_ops, args, bitrate); } - - virtual int close() - { return m_ops.close(args); } - - virtual int rewind() - { return m_ops.rewind(args); } - - virtual int read(void* buffer, int size) - { return m_ops.read(args, buffer, size); } - - virtual dabInputOperations getOpts() { return m_ops; } - - private: - DabInputCompatible& operator=(const DabInputCompatible& other); - DabInputCompatible(const DabInputCompatible& other); - - dabInputOperations m_ops; - void* args; -}; - -int dabInputSetbuf(void* args, int size); -int dabInputSetbitrate(dabInputOperations* ops, void* args, int bitrate); - - -#endif // DAB_INPUT_H diff --git a/src/dabInputBridgeUdp.cpp b/src/dabInputBridgeUdp.cpp deleted file mode 100644 index fdf3d1f..0000000 --- a/src/dabInputBridgeUdp.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* - Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications - Research Center Canada) - */ -/* - This file is part of ODR-DabMux. - - ODR-DabMux 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 3 of the - License, or (at your option) any later version. - - ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "dabInputBridgeUdp.h" -#include "dabInputUdp.h" -#include "bridge.h" - -#ifdef HAVE_FORMAT_BRIDGE -# ifdef HAVE_INPUT_UDP - -struct dabInputBridgeUdpData { - dabInputUdpData* udpData; - bridgeInfo* info; -}; - - -struct dabInputOperations dabInputBridgeUdpOperations = { - dabInputBridgeUdpInit, - dabInputBridgeUdpOpen, - dabInputSetbuf, - NULL, - NULL, - NULL, - dabInputBridgeUdpRead, - dabInputSetbitrate, - dabInputBridgeUdpClose, - dabInputBridgeUdpClean, - NULL -}; - - -int dabInputBridgeUdpInit(void** args) -{ - dabInputBridgeUdpData* input = new dabInputBridgeUdpData; - dabInputUdpInit((void**)&input->udpData); - input->info = new bridgeInfo; - bridgeInitInfo(input->info); - *args = input; - - return 0; -} - - -int dabInputBridgeUdpOpen(void* args, const char* inputName) -{ - dabInputBridgeUdpData* input = (dabInputBridgeUdpData*)args; - - return dabInputUdpOpen(input->udpData, inputName); -} - - -int dabInputBridgeUdpRead(dabInputOperations* ops, void* args, void* buffer, int size) -{ - int nbBytes = 0; - dabInputBridgeUdpData* input = (dabInputBridgeUdpData*)args; - dabInputFifoStats* stats = (dabInputFifoStats*)&input->udpData->stats; - - stats->frameRecords[stats->frameCount].curSize = 0; - stats->frameRecords[stats->frameCount].maxSize = size; - - if (input->udpData->packet->getSize() == 0) { - input->udpData->socket->receive(*input->udpData->packet); - } - while ((nbBytes = writePacket(input->udpData->packet->getData(), - input->udpData->packet->getSize(), buffer, size, - input->info)) - != 0) { - stats->frameRecords[stats->frameCount].curSize = nbBytes; - input->udpData->socket->receive(*input->udpData->packet); - } - - if (input->udpData->packet->getSize() != 0) { - stats->frameRecords[stats->frameCount].curSize = size; - } - - if (++stats->frameCount == NB_RECORDS) { - etiLog.log(info, "Data subchannel usage: (%i)", - stats->id); - for (int i = 0; i < stats->frameCount; ++i) { - etiLog.log(info, " %i/%i", - stats->frameRecords[i].curSize, - stats->frameRecords[i].maxSize); - } - etiLog.log(info, "\n"); - stats->frameCount = 0; - } - return size; -} - - -int dabInputBridgeUdpClose(void* args) -{ - dabInputBridgeUdpData* input = (dabInputBridgeUdpData*)args; - - return dabInputUdpClose(input->udpData); -} - - -int dabInputBridgeUdpClean(void** args) -{ - dabInputBridgeUdpData* input = (dabInputBridgeUdpData*)(*args); - dabInputUdpClean((void**)&input->udpData); - delete input->info; - delete input; - return 0; -} - - -# endif // HAVE_INPUT_UDP -#endif // HAVE_FORMAT_BRIDGE - diff --git a/src/dabInputBridgeUdp.h b/src/dabInputBridgeUdp.h deleted file mode 100644 index ed00952..0000000 --- a/src/dabInputBridgeUdp.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications - Research Center Canada) - */ -/* - This file is part of ODR-DabMux. - - ODR-DabMux 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 3 of the - License, or (at your option) any later version. - - ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef DAB_INPUT_BRIDGE_UDP_H -#define DAB_INPUT_BRIDGE_UDP_H - - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif -#include "dabInput.h" - - -#ifdef HAVE_FORMAT_BRIDGE -# ifdef HAVE_INPUT_UDP - - -extern struct dabInputOperations dabInputBridgeUdpOperations; - -int dabInputBridgeUdpInit(void** args); -int dabInputBridgeUdpOpen(void* args, const char* inputName); -int dabInputBridgeUdpRead(dabInputOperations* ops, void* args, void* buffer, int size); -int dabInputBridgeUdpClose(void* args); -int dabInputBridgeUdpClean(void** args); - - -# endif -#endif - - -#endif // DAB_INPUT_BRIDGE_UDP_H diff --git a/src/dabInputDabplusFifo.cpp b/src/dabInputDabplusFifo.cpp deleted file mode 100644 index 94aec13..0000000 --- a/src/dabInputDabplusFifo.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/* - Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications - Research Center Canada) - */ -/* - This file is part of ODR-DabMux. - - ODR-DabMux 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 3 of the - License, or (at your option) any later version. - - ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "dabInputDabplusFifo.h" -#include "dabInputDabplusFile.h" -#include "dabInputFifo.h" -#include "dabInput.h" - -#include <stdint.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <fcntl.h> - -#ifndef _WIN32 -# define O_BINARY 0 -#endif - - -#ifdef HAVE_FORMAT_DABPLUS -# ifdef HAVE_INPUT_FILE - - -struct dabInputDabplusFifoData { - void* fifoData; - uint8_t* buffer; - size_t bufferSize; - size_t bufferIndex; - size_t bufferOffset; -}; - - -struct dabInputOperations dabInputDabplusFifoOperations = { - dabInputDabplusFifoInit, - dabInputDabplusFifoOpen, - dabInputDabplusFifoSetbuf, - dabInputDabplusFifoRead, - dabInputDabplusFifoLock, - dabInputDabplusFifoUnlock, - dabInputDabplusFileReadFrame, - dabInputSetbitrate, - dabInputDabplusFifoClose, - dabInputDabplusFifoClean, - dabInputDabplusFifoRewind -}; - - -int dabInputDabplusFifoInit(void** args) -{ - dabInputDabplusFifoData* data = new dabInputDabplusFifoData; - - dabInputFifoInit(&data->fifoData); - data->buffer = nullptr; - data->bufferSize = 0; - data->bufferIndex = 0; - data->bufferOffset = 0; - - *args = data; - - return 0; -} - - -int dabInputDabplusFifoOpen(void* args, const char* filename) -{ - dabInputDabplusFifoData* data = (dabInputDabplusFifoData*)args; - - return dabInputFifoOpen(data->fifoData, filename); -} - - -int dabInputDabplusFifoSetbuf(void* args, int size) -{ - dabInputDabplusFifoData* data = (dabInputDabplusFifoData*)args; - - return dabInputFifoSetbuf(data->fifoData, size); -} - - -int dabInputDabplusFifoRead(void* args, void* buffer, int size) -{ - dabInputDabplusFifoData* data = (dabInputDabplusFifoData*)args; - - if (data->bufferSize != (size_t)size * 5) { - if (data->buffer != nullptr) { - delete[] data->buffer; - } - data->buffer = new uint8_t[size * 5]; - data->bufferSize = size * 5; - data->bufferIndex = 0; - } - - if (data->bufferOffset < data->bufferSize) { - int ret = dabInputFifoRead(data->fifoData, - &data->buffer[data->bufferOffset], - data->bufferSize - data->bufferOffset); - if (ret < 0) { - return ret; - } - data->bufferOffset += ret; - if (data->bufferOffset != data->bufferSize) { - etiLog.log(alert, "ERROR: Incomplete DAB+ frame!\n"); - return 0; - } - } - - memcpy(buffer, &data->buffer[data->bufferIndex], size); - data->bufferIndex += size; - if (data->bufferIndex >= data->bufferSize) { - data->bufferIndex = 0; - data->bufferOffset = 0; - } - return size; -} - - -int dabInputDabplusFifoLock(void* args) -{ - dabInputDabplusFifoData* data = (dabInputDabplusFifoData*)args; - - return dabInputFifoLock(data->fifoData); -} - - -int dabInputDabplusFifoUnlock(void* args) -{ - dabInputDabplusFifoData* data = (dabInputDabplusFifoData*)args; - - return dabInputFifoUnlock(data->fifoData); -} - - -int dabInputDabplusFifoReadFrame(dabInputOperations* ops, void* args, - void* buffer, int size) -{ - return ops->read(args, buffer, size); -} - - -int dabInputDabplusFifoClose(void* args) -{ - dabInputDabplusFifoData* data = (dabInputDabplusFifoData*)args; - - return dabInputFifoClose(data->fifoData); -} - - -int dabInputDabplusFifoClean(void** args) -{ - dabInputDabplusFifoData* data = (dabInputDabplusFifoData*)args; - - dabInputFifoClean(&data->fifoData); - delete data; - - return 0; -} - - -int dabInputDabplusFifoRewind(void* args) -{ - dabInputDabplusFifoData* data = (dabInputDabplusFifoData*)args; - - return dabInputFifoRewind(data->fifoData); -} - - -# endif -#endif diff --git a/src/dabInputDabplusFifo.h b/src/dabInputDabplusFifo.h deleted file mode 100644 index 83368d6..0000000 --- a/src/dabInputDabplusFifo.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications - Research Center Canada) - */ -/* - This file is part of ODR-DabMux. - - ODR-DabMux 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 3 of the - License, or (at your option) any later version. - - ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef DAB_INPUT_DABPLUS_FIFO_H -#define DAB_INPUT_DABPLUS_FIFO_H - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - - -#ifdef HAVE_FORMAT_DABPLUS -# ifdef HAVE_INPUT_FIFO - - -extern struct dabInputOperations dabInputDabplusFifoOperations; - - -int dabInputDabplusFifoInit(void** args); -int dabInputDabplusFifoOpen(void* args, const char* filename); -int dabInputDabplusFifoSetbuf(void* args, int size); -int dabInputDabplusFifoRead(void* args, void* buffer, int size); -int dabInputDabplusFifoLock(void* args); -int dabInputDabplusFifoUnlock(void* args); -int dabInputDabplusFifoReadFrame(dabInputOperations* ops, void* args, - void* buffer, int size); -int dabInputDabplusFifoClose(void* args); -int dabInputDabplusFifoClean(void** args); -int dabInputDabplusFifoRewind(void* args); - - -# endif -#endif - - -#endif // DAB_INPUT_DABPLUS_FIFO_H diff --git a/src/dabInputDabplusFile.cpp b/src/dabInputDabplusFile.cpp deleted file mode 100644 index 64b7f07..0000000 --- a/src/dabInputDabplusFile.cpp +++ /dev/null @@ -1,177 +0,0 @@ -/* - Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications - Research Center Canada) - */ -/* - This file is part of ODR-DabMux. - - ODR-DabMux 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 3 of the - License, or (at your option) any later version. - - ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "dabInputDabplusFile.h" -#include "dabInput.h" - -#include <stdio.h> -#include <string.h> -#include <fcntl.h> - -#ifndef _WIN32 -# define O_BINARY 0 -#endif - - -#ifdef HAVE_FORMAT_DABPLUS -# ifdef HAVE_INPUT_FILE - - -struct dabInputOperations dabInputDabplusFileOperations = { - dabInputDabplusFileInit, - dabInputDabplusFileOpen, - dabInputSetbuf, - dabInputDabplusFileRead, - nullptr, - nullptr, - dabInputDabplusFileReadFrame, - dabInputSetbitrate, - dabInputDabplusFileClose, - dabInputDabplusFileClean, - dabInputDabplusFileRewind -}; - - -int dabInputDabplusFileInit(void** args) -{ - dabInputDabplusFileData* data = new dabInputDabplusFileData; - data->file = -1; - data->buffer = nullptr; - data->bufferSize = 0; - data->bufferIndex = 0; - - *args = data; - return 0; -} - - -int dabInputDabplusFileOpen(void* args, const char* filename) -{ - dabInputDabplusFileData* data = (dabInputDabplusFileData*)args; - data->file = open(filename, O_RDONLY | O_BINARY); - if (data->file == -1) { - perror(filename); - return -1; - } - - return 0; -} - - -int dabInputDabplusFileRead(void* args, void* buffer, int size) -{ - dabInputDabplusFileData* data = (dabInputDabplusFileData*)args; - if (data->bufferSize != (size_t)size * 5) { - if (data->buffer == nullptr) { - delete[] data->buffer; - } - data->buffer = new uint8_t[size * 5]; - memset(data->buffer, 0, size * 5); - data->bufferSize = size * 5; - data->bufferIndex = 0; - } - - if (data->bufferIndex + size > data->bufferSize) { - int ret = read(data->file, data->buffer, data->bufferSize); - if (ret != (int)data->bufferSize) { - if (ret != 0) { - etiLog.log(alert, "ERROR: Incomplete DAB+ frame!\n"); - } - return 0; - } - data->bufferIndex = 0; - } - - memcpy(buffer, &data->buffer[data->bufferIndex], size); - data->bufferIndex += size; - - return size; -} - - -int dabInputDabplusFileReadFrame(dabInputOperations* ops, void* args, - void* buffer, int size) -{ - //dabInputDabplusFileData* data = (dabInputDabplusFileData*)args; - int result; - uint8_t* dataOut = reinterpret_cast<uint8_t*>(buffer); - - result = ops->read(args, dataOut, size); - if (result == -1) { - etiLog.log(alert, "ERROR: Can't read file\n"); - perror(""); - return -1; - } - if (result < size) { - int sizeOut = result; - etiLog.log(info, "reach end of file -> rewinding\n"); - if (ops->rewind(args) == -1) { - etiLog.log(alert, "ERROR: Can't rewind file\n"); - return -1; - } - - result = ops->read(args, dataOut + sizeOut, size - sizeOut); - if (result == -1) { - etiLog.log(alert, "ERROR: Can't read file\n"); - perror(""); - return -1; - } - - if (result < size) { - etiLog.log(alert, "ERROR: Not enought data in file\n"); - return -1; - } - } - - return size; -} - - -int dabInputDabplusFileClose(void* args) -{ - dabInputDabplusFileData* data = (dabInputDabplusFileData*)args; - if (data->file != -1) { - close(data->file); - } - return 0; -} - - -int dabInputDabplusFileClean(void** args) -{ - dabInputDabplusFileData* data = (dabInputDabplusFileData*)*args; - if (data->buffer != nullptr) { - delete[] data->buffer; - } - delete data; - return 0; -} - - -int dabInputDabplusFileRewind(void* args) -{ - dabInputDabplusFileData* data = (dabInputDabplusFileData*)args; - return lseek(data->file, 0, SEEK_SET); -} - - -# endif -#endif diff --git a/src/dabInputDabplusFile.h b/src/dabInputDabplusFile.h deleted file mode 100644 index 5fe2dec..0000000 --- a/src/dabInputDabplusFile.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications - Research Center Canada) - */ -/* - This file is part of ODR-DabMux. - - ODR-DabMux 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 3 of the - License, or (at your option) any later version. - - ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef DAB_INPUT_DABPLUS_FILE_H -#define DAB_INPUT_DABPLUS_FILE_H - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdint.h> -#include <unistd.h> - - -#ifdef HAVE_FORMAT_DABPLUS -# ifdef HAVE_INPUT_FILE - - -extern struct dabInputOperations dabInputDabplusFileOperations; - - -struct dabInputDabplusFileData { - int file; - uint8_t* buffer; - size_t bufferSize; - size_t bufferIndex; -}; - - -int dabInputDabplusFileInit(void** args); -int dabInputDabplusFileOpen(void* args, const char* filename); -int dabInputDabplusFileRead(void* args, void* buffer, int size); -int dabInputDabplusFileReadFrame(dabInputOperations* ops, void* args, - void* buffer, int size); -int dabInputDabplusFileClose(void* args); -int dabInputDabplusFileClean(void** args); -int dabInputDabplusFileRewind(void* args); - - -# endif -#endif - - -#endif // DAB_INPUT_DABPLUS_FILE_H diff --git a/src/dabInputEnhancedFifo.cpp b/src/dabInputEnhancedFifo.cpp deleted file mode 100644 index 3a8a27c..0000000 --- a/src/dabInputEnhancedFifo.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications - Research Center Canada) - */ -/* - This file is part of ODR-DabMux. - - ODR-DabMux 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 3 of the - License, or (at your option) any later version. - - ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "dabInputEnhancedFifo.h" -#include "dabInputPacketFile.h" -#include "dabInputFifo.h" - - -#ifdef HAVE_FORMAT_PACKET -# ifdef HAVE_FORMAT_EPM -# ifdef HAVE_INPUT_FIFO - - -struct dabInputOperations dabInputEnhancedFifoOperations = { - dabInputEnhancedFifoInit, - dabInputFifoOpen, - dabInputFifoSetbuf, - dabInputFifoRead, - dabInputFifoLock, - dabInputFifoUnlock, - dabInputPacketFileRead, - dabInputSetbitrate, - dabInputFifoClose, - dabInputFifoClean, - dabInputFifoRewind -}; - - -int dabInputEnhancedFifoInit(void** args) -{ - dabInputFifoInit(args); - dabInputFifoData* data = (dabInputFifoData*)*args; - - data->packetData = new unsigned char[96]; - data->enhancedPacketData = new unsigned char*[12]; - for (int i = 0; i < 12; ++i) { - data->enhancedPacketData[i] = new unsigned char[204]; - } - - return 0; -} - - -# endif -# endif -#endif diff --git a/src/dabInputEnhancedFifo.h b/src/dabInputEnhancedFifo.h deleted file mode 100644 index 4c87e24..0000000 --- a/src/dabInputEnhancedFifo.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications - Research Center Canada) - */ -/* - This file is part of ODR-DabMux. - - ODR-DabMux 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 3 of the - License, or (at your option) any later version. - - ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef DAB_INPUT_ENHANCED_FIFO_H -#define DAB_INPUT_ENHANCED_FIFO_H - - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif -#include "dabInput.h" - - -#ifdef HAVE_FORMAT_PACKET -# ifdef HAVE_FORMAT_EPM -# ifdef HAVE_INPUT_FIFO - - -extern struct dabInputOperations dabInputEnhancedFifoOperations; -int dabInputEnhancedFifoInit(void** args); - - -# endif -# endif -#endif - - -#endif // DAB_INPUT_ENHANCED_FIFO_H diff --git a/src/dabInputEnhancedPacketFile.cpp b/src/dabInputEnhancedPacketFile.cpp deleted file mode 100644 index 3b12e0b..0000000 --- a/src/dabInputEnhancedPacketFile.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications - Research Center Canada) - */ -/* - This file is part of ODR-DabMux. - - ODR-DabMux 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 3 of the - License, or (at your option) any later version. - - ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "dabInputEnhancedPacketFile.h" -#include "dabInputPacketFile.h" -#include "dabInputFile.h" - - -struct dabInputOperations dabInputEnhancedPacketFileOperations = { - dabInputEnhancedFileInit, - dabInputFileOpen, - dabInputSetbuf, - dabInputFileRead, - nullptr, - nullptr, - dabInputPacketFileRead, - dabInputSetbitrate, - dabInputFileClose, - dabInputFileClean, - dabInputFileRewind -}; - - -int dabInputEnhancedFileInit(void** args) -{ - dabInputFileInit(args); - dabInputFileData* data = (dabInputFileData*)*args; - - data->enhancedPacketData = new unsigned char*[12]; - for (int i = 0; i < 12; ++i) { - data->enhancedPacketData[i] = new unsigned char[204]; - } - - return 0; -} diff --git a/src/dabInputEnhancedPacketFile.h b/src/dabInputEnhancedPacketFile.h deleted file mode 100644 index 74f59de..0000000 --- a/src/dabInputEnhancedPacketFile.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications - Research Center Canada) - */ -/* - This file is part of ODR-DabMux. - - ODR-DabMux 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 3 of the - License, or (at your option) any later version. - - ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef DAB_INPUT_ENHANCED_PACKET_FILE_H -#define DAB_INPUT_ENHANCED_PACKET_FILE_H - - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif -#include "dabInput.h" - - -#ifdef HAVE_FORMAT_PACKET -# ifdef HAVE_FORMAT_EPM -# ifdef HAVE_INPUT_FILE - - -extern struct dabInputOperations dabInputEnhancedPacketFileOperations; - -int dabInputEnhancedFileInit(void** args); - - -# endif -# endif -#endif - - -#endif // DAB_INPUT_ENHANCED_PACKET_FILE_H diff --git a/src/dabInputFifo.cpp b/src/dabInputFifo.cpp deleted file mode 100644 index 6fa3aad..0000000 --- a/src/dabInputFifo.cpp +++ /dev/null @@ -1,518 +0,0 @@ -/* - Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications - Research Center Canada) - - Copyright (C) 2016 - Matthias P. Braendli, matthias.braendli@mpb.li - - http://www.opendigitalradio.org - */ -/* - This file is part of ODR-DabMux. - - ODR-DabMux 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 3 of the - License, or (at your option) any later version. - - ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "dabInputFifo.h" -#include "dabInputPacketFile.h" -#include "dabInput.h" - -#include <unistd.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <fcntl.h> - - -#ifdef HAVE_FORMAT_PACKET -# ifdef HAVE_INPUT_FIFO - - -int dabInputFifoData::nb = 0; - - -struct dabInputOperations dabInputFifoOperations = { - dabInputFifoInit, - dabInputFifoOpen, - dabInputFifoSetbuf, - dabInputFifoRead, - dabInputFifoLock, - dabInputFifoUnlock, - dabInputPacketFileRead, - dabInputSetbitrate, - dabInputFifoClose, - dabInputFifoClean, - dabInputFifoRewind -}; - - -int dabInputFifoInit(void** args) -{ - dabInputFifoData* data = new dabInputFifoData; - memset(data, 0, sizeof(*data)); - data->stats.id = dabInputFifoData::nb++; - data->maxSize = 0; - data->curSize = 0; - data->head = 0; - data->tail = 0; - data->buffer = nullptr; - data->packetData = nullptr; - data->enhancedPacketData = nullptr; - data->packetLength = 0; - data->enhancedPacketLength = 0; - data->enhancedPacketWaiting = 0; - data->full = false; - data->running = true; - data->thread = (pthread_t)NULL; -#ifdef _WIN32 - char semName[32]; - sprintf(semName, "semInfo%i", data->stats.id); - data->semInfo = CreateSemaphore(NULL, 1, 1, semName); - if (data->semInfo == NULL) { - fprintf(stderr, "Can't init FIFO data semaphore %s\n", semName); - return -1; - } - sprintf(semName, "semBuffer%i", data->stats.id); - data->semBuffer = CreateSemaphore(NULL, 1, 1, semName); - if (data->semBuffer == NULL) { - fprintf(stderr, "Can't init FIFO buffer semaphore %s\n", semName); - return -1; - } - sprintf(semName, "semFull%i", data->stats.id); - data->semFull = CreateSemaphore(NULL, 1, 1, semName); - if (data->semFull == NULL) { - fprintf(stderr, "Can't init FIFO semaphore %s\n", semName); - return -1; - } -#else - if (sem_init(&data->semInfo, 0, 1) == -1) { - perror("Can't init FIFO data semaphore"); - return -1; - } - if (sem_init(&data->semBuffer, 0, 0) == -1) { - perror("Can't init fIFO buffer semaphore"); - return -1; - } - if (sem_init(&data->semFull, 0, 0) == -1) { - perror("Can't init FIFO semaphore"); - return -1; - } -#endif - - if (data->maxSize > 0) { -#ifdef _WIN32 - ReleaseSemaphore(data->semBuffer, 1, NULL); -#else - sem_post(&data->semBuffer); -#endif - } - *args = data; - return 0; -} - - -int dabInputFifoOpen(void* args, const char* filename) -{ - dabInputFifoData* data = (dabInputFifoData*)args; - data->file = open(filename, O_RDONLY | O_BINARY | O_NONBLOCK); - if (data->file == -1) { - perror(filename); - return -1; - } -#ifdef _WIN32 -#else - int flags = fcntl(data->file, F_GETFL); - if (flags == -1) { - perror(filename); - return -1; - } - if (fcntl(data->file, F_SETFL, flags & ~O_NONBLOCK) == -1) { - perror(filename); - return -1; - } -#endif - -#ifdef _WIN32 - data->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)dabInputFifoThread, data, 0, NULL); - if (data->thread == NULL) { - fprintf(stderr, "Can't create FIFO child\n"); - return -1; - } -#else - if (pthread_create(&data->thread, nullptr, dabInputFifoThread, data)) { - perror("Can't create FIFO child"); - return -1; - } -#endif - - return 0; -} - - -int dabInputFifoSetbuf(void* args, int size) -{ - dabInputFifoData* data = (dabInputFifoData*)args; - - if (data->maxSize > 0) { -#ifdef _WIN32 - WaitForSingleObject(data->semBuffer, INFINITE); -#else - sem_wait(&data->semBuffer); -#endif - } - if (data->buffer != nullptr) { - delete data->buffer; - } - if (size == 0) { - size = 1024; - } - data->buffer = new unsigned char[size * 16]; - data->maxSize = size * 16; -#ifdef _WIN32 - ReleaseSemaphore(data->semBuffer, 1, NULL); -#else - sem_post(&data->semBuffer); -#endif - - return 0; -} - - -int dabInputFifoRead(void* args, void* buffer, int size) -{ - //fprintf(stderr, "INFO: read %i bytes\n", size); - dabInputFifoData* data = (dabInputFifoData*)args; - dabInputFifoStats* stats = &data->stats; - int head; - int tail; - int curSize; - int maxSize; -#ifdef _WIN32 - WaitForSingleObject(data->semInfo, INFINITE); -#else - sem_wait(&data->semInfo); -#endif - head = data->head; - tail = data->tail; - curSize = data->curSize; - maxSize = data->maxSize; -#ifdef _WIN32 - ReleaseSemaphore(data->semInfo, 1, NULL); -#else - sem_post(&data->semInfo); -#endif - //fprintf(stderr, "head: %i, tail: %i, curSize: %i\n", head, tail, curSize); - if (size > curSize) { - if (curSize == 0) { - stats->empty = true; - } else { - etiLog.log(warn, "Not enough data in FIFO buffer: (%i) %i/%i\n", - data->stats.id, curSize, size); - } - return 0; - } - if (head > tail) { - memcpy(buffer, data->buffer + tail, size); -#ifdef _WIN32 - WaitForSingleObject(data->semInfo, INFINITE); -#else - sem_wait(&data->semInfo); -#endif - data->tail += size; - data->curSize -= size; -#ifdef _WIN32 - ReleaseSemaphore(data->semInfo, 1, NULL); -#else - sem_post(&data->semInfo); -#endif - return size; - } else { - if (maxSize - tail >= size) { - memcpy(buffer, data->buffer + tail, size); -#ifdef _WIN32 - WaitForSingleObject(data->semInfo, INFINITE); -#else - sem_wait(&data->semInfo); -#endif - data->tail += size; - data->curSize -= size; -#ifdef _WIN32 - ReleaseSemaphore(data->semInfo, 1, NULL); -#else - sem_post(&data->semInfo); -#endif - return size; - } else { - memcpy(buffer, data->buffer + tail, maxSize - tail); -#ifdef _WIN32 - WaitForSingleObject(data->semInfo, INFINITE); -#else - sem_wait(&data->semInfo); -#endif - data->tail = 0; - data->curSize -= maxSize - tail; -#ifdef _WIN32 - ReleaseSemaphore(data->semInfo, 1, NULL); -#else - sem_post(&data->semInfo); -#endif - return maxSize - tail + dabInputFifoRead(data, (char*)buffer + maxSize - tail, size - (maxSize - tail)); - } - } - return -1; -} - - -int dabInputFifoLock(void* args) { - dabInputFifoData* data = (dabInputFifoData*)args; - dabInputFifoStats* stats = &data->stats; - - int maxSize; - int curSize; -#ifdef _WIN32 - WaitForSingleObject(data->semInfo, INFINITE); -#else - sem_wait(&data->semInfo); -#endif - maxSize = data->maxSize; - curSize = data->curSize; -#ifdef _WIN32 - ReleaseSemaphore(data->semInfo, 1, NULL); -#else - sem_post(&data->semInfo); -#endif - - stats->bufferRecords[stats->bufferCount].curSize = curSize; - stats->bufferRecords[stats->bufferCount].maxSize = maxSize; - - if (++stats->bufferCount == NB_RECORDS) { - etiLog.log(info, "FIFO buffer state: (%i)", stats->id); - for (int i = 0; i < stats->bufferCount; ++i) { - etiLog.log(info, " %i/%i", - stats->bufferRecords[i].curSize, - stats->bufferRecords[i].maxSize); - } - etiLog.log(info, "\n"); - - if (stats->full) { - etiLog.log(warn, "FIFO buffer full: (%i)\n", - data->stats.id); - stats->full = false; - } - if (stats->empty) { - etiLog.log(warn, "FIFO buffer empty: (%i)\n", - data->stats.id); - stats->empty = false; - } - if (stats->error) { - etiLog.log(error, "FIFO input read error: (%i)\n", - data->stats.id); - stats->error = false; - } - if (stats->input) { - etiLog.log(error, "FIFO input not connected: (%i)\n", - data->stats.id); - stats->input = false; - } - - stats->bufferCount = 0; - } - return 0; -} - - -int dabInputFifoUnlock(void* args) { - dabInputFifoData* data = (dabInputFifoData*)args; - if (data->full) { -#ifdef _WIN32 - ReleaseSemaphore(data->semFull, 1, NULL); -#else - sem_post(&data->semFull); -#endif - } - return 0; -} - - -int dabInputFifoClose(void* args) -{ - dabInputFifoData* data = (dabInputFifoData*)args; - close(data->file); - return 0; -} - - -int dabInputFifoClean(void** args) -{ - dabInputFifoData* data = (dabInputFifoData*)*args; - data->running = false; - etiLog.log(debug, "Wait FIFO child...\n"); -#ifdef WIN32 - DWORD status; - for (int i = 0; i < 5; ++i) { - if (GetExitCodeThread(data->thread, &status)) { - break; - } - Sleep(100); - } - TerminateThread(data->thread, 1); - if (CloseHandle(data->thread) == 0) { - etiLog.log(debug, "ERROR: Failed to close FIFO child thread\n"); - } -#else - if (data->thread != (pthread_t)NULL) { - if (pthread_join(data->thread, nullptr)) { - etiLog.log(debug, "ERROR: FIFO child thread had not exit normally\n"); - } - } -#endif - etiLog.log(debug, "Done\n"); -#ifdef _WIN32 - CloseHandle(data->semInfo); - CloseHandle(data->semFull); - CloseHandle(data->semBuffer); -#else - sem_destroy(&data->semInfo); - sem_destroy(&data->semFull); - sem_destroy(&data->semBuffer); -#endif - if (data->packetData != nullptr) { - delete[] data->packetData; - } - if (data->enhancedPacketData != nullptr) { - for (int i = 0; i < 12; ++i) { - if (data->enhancedPacketData[i] != nullptr) { - delete[] data->enhancedPacketData[i]; - } - } - delete[] data->enhancedPacketData; - } - delete data->buffer; - delete data; - return 0; -} - - -int dabInputFifoRewind(void* args) -{ - return -1; -} - - -void* dabInputFifoThread(void* args) -{ - dabInputFifoData* data = (dabInputFifoData*)args; - int head; - int tail; - int curSize; - int maxSize; - int ret; - while (data->running) { -#ifdef _WIN32 - WaitForSingleObject(data->semBuffer, INFINITE); - WaitForSingleObject(data->semInfo, INFINITE); -#else - sem_wait(&data->semBuffer); - sem_wait(&data->semInfo); -#endif - head = data->head; - tail = data->tail; - curSize = data->curSize; - maxSize = data->maxSize; -#ifdef _WIN32 - ReleaseSemaphore(data->semInfo, 1, NULL); -#else - sem_post(&data->semInfo); -#endif - //fprintf(stderr, "thread, head: %i, tail: %i, curSize: %i\n", head, tail, curSize); - - if (curSize == maxSize) { - data->stats.full = true; - data->full = true; -#ifdef _WIN32 - WaitForSingleObject(data->semFull, INFINITE); -#else - sem_wait(&data->semFull); -#endif - } else if (head >= tail) { // 2 blocks - ret = read(data->file, data->buffer + head, maxSize - head); - if (ret == 0) { - data->stats.input = true; - data->full = true; -#ifdef _WIN32 - WaitForSingleObject(data->semFull, INFINITE); -#else - sem_wait(&data->semFull); -#endif - } else if (ret == -1) { - data->stats.error = true; - } else { -#ifdef _WIN32 - WaitForSingleObject(data->semInfo, INFINITE); -#else - sem_wait(&data->semInfo); -#endif - data->head += ret; - data->curSize += ret; - if (data->head == maxSize) { - data->head = 0; - } -#ifdef _WIN32 - ReleaseSemaphore(data->semInfo, 1, NULL); -#else - sem_post(&data->semInfo); -#endif - } - } else { // 1 block - ret = read(data->file, data->buffer + head, tail - head); - if (ret == 0) { - data->stats.input = true; - data->full = true; -#ifdef _WIN32 - WaitForSingleObject(data->semFull, INFINITE); -#else - sem_wait(&data->semFull); -#endif - } else if (ret == -1) { - data->stats.error = true; - } else { -#ifdef _WIN32 - WaitForSingleObject(data->semInfo, INFINITE); -#else - sem_wait(&data->semInfo); -#endif - data->head += ret; - data->curSize += ret; - if (data->head == maxSize) { - data->head = 0; - } -#ifdef _WIN32 - ReleaseSemaphore(data->semInfo, 1, NULL); -#else - sem_post(&data->semInfo); -#endif - } - } -#ifdef _WIN32 - ReleaseSemaphore(data->semBuffer, 1, NULL); -#else - sem_post(&data->semBuffer); -#endif - } - return nullptr; -} - - -# endif -#endif diff --git a/src/dabInputFifo.h b/src/dabInputFifo.h deleted file mode 100644 index 99edac6..0000000 --- a/src/dabInputFifo.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications - Research Center Canada) - - Copyright (C) 2016 - Matthias P. Braendli, matthias.braendli@mpb.li - - http://www.opendigitalradio.org - */ -/* - This file is part of ODR-DabMux. - - ODR-DabMux 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 3 of the - License, or (at your option) any later version. - - ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "dabInputFile.h" -#include "Log.h" - - -#ifdef _WIN32 -# include <io.h> -# define sem_t HANDLE -# define O_NONBLOCK 0 -#else -# include <semaphore.h> -# define O_BINARY 0 -#endif - - -#ifdef HAVE_FORMAT_PACKET -# ifdef HAVE_INPUT_FIFO -extern struct dabInputOperations dabInputFifoOperations; - - -struct dabInputFifoStatRecord { - int curSize; - int maxSize; -}; - - -#define NB_RECORDS 10 -struct dabInputFifoStats { - int id; - bool full; - bool empty; - bool error; - bool input; - int bufferCount; - dabInputFifoStatRecord bufferRecords[NB_RECORDS]; - int frameCount; - dabInputFifoStatRecord frameRecords[NB_RECORDS]; -}; - - -struct dabInputFifoData : dabInputFileData { - static int nb; - int maxSize; - int curSize; - int head; - int tail; - dabInputFifoStats stats; - unsigned char* buffer; - pthread_t thread; - sem_t semInfo; - sem_t semBuffer; - sem_t semFull; - bool full; - bool running; -}; - - -int dabInputFifoInit(void** args); -int dabInputFifoOpen(void* args, const char* filename); -int dabInputFifoSetbuf(void* args, int size); -int dabInputFifoRead(void* args, void* buffer, int size); -int dabInputFifoLock(void* args); -int dabInputFifoUnlock(void* args); -int dabInputFifoClose(void* args); -int dabInputFifoClean(void** args); -int dabInputFifoRewind(void* args); -void* dabInputFifoThread(void* args); - - -# endif -#endif - diff --git a/src/dabInputFile.cpp b/src/dabInputFile.cpp deleted file mode 100644 index 2847caa..0000000 --- a/src/dabInputFile.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - Copyright (C) 2009,2011 Her Majesty the Queen in Right of Canada - (Communications Research Center Canada) - */ -/* - This file is part of ODR-DabMux. - - ODR-DabMux 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 3 of the - License, or (at your option) any later version. - - ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "dabInputFile.h" - -#include <stdlib.h> -#include <stdio.h> -#include <fcntl.h> -#include <unistd.h> - -#ifndef _WIN32 -# define O_BINARY 0 -#endif - - -int dabInputFileInit(void** args) -{ - dabInputFileData* data = new dabInputFileData; - data->file = -1; - data->parity = false; - data->packetLength = 0; - data->packetData = new unsigned char[96]; - data->enhancedPacketData = nullptr; - data->enhancedPacketLength = 0; - data->enhancedPacketWaiting = 0; - - *args = data; - return 0; -} - - -int dabInputFileOpen(void* args, const char* filename) -{ - dabInputFileData* data = (dabInputFileData*)args; - data->file = open(filename, O_RDONLY | O_BINARY); - if (data->file == -1) { - perror(filename); - return -1; - } - return 0; -} - - -int dabInputFileRead(void* args, void* buffer, int size) -{ - dabInputFileData* data = (dabInputFileData*)args; - return read(data->file, buffer, size); -} - - -int dabInputFileClose(void* args) -{ - dabInputFileData* data = (dabInputFileData*)args; - if (data->file != -1) { - close(data->file); - } - return 0; -} - - -int dabInputFileClean(void** args) -{ - dabInputFileData* data = (dabInputFileData*)*args; - if (data->packetData != nullptr) { - delete[] data->packetData; - } - if (data->enhancedPacketData != nullptr) { - for (int i = 0; i < 12; ++i) { - if (data->enhancedPacketData[i] != nullptr) { - delete[] data->enhancedPacketData[i]; - } - } - delete[] data->enhancedPacketData; - } - delete data; - return 0; -} - - -int dabInputFileRewind(void* args) -{ - dabInputFileData* data = (dabInputFileData*)args; - return lseek(data->file, 0, SEEK_SET); -} - - diff --git a/src/dabInputFile.h b/src/dabInputFile.h deleted file mode 100644 index e3eaa48..0000000 --- a/src/dabInputFile.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications - Research Center Canada) - */ -/* - This file is part of ODR-DabMux. - - ODR-DabMux 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 3 of the - License, or (at your option) any later version. - - ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef DAB_INPUT_FILE_H -#define DAB_INPUT_FILE_H - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - - -struct dabInputFileData { - int file; - bool parity; - unsigned packetLength; - unsigned char* packetData; - unsigned char** enhancedPacketData; - unsigned enhancedPacketLength; - unsigned enhancedPacketWaiting; -}; - - -int dabInputFileInit(void** args); -int dabInputFileOpen(void* args, const char* filename); -int dabInputFileRead(void* args, void* buffer, int size); -int dabInputFileClose(void* args); -int dabInputFileClean(void** args); -int dabInputFileRewind(void* args); - - -#endif // DAB_INPUT_FILE_H diff --git a/src/dabInputMpegFifo.cpp b/src/dabInputMpegFifo.cpp deleted file mode 100644 index 0f1d3b0..0000000 --- a/src/dabInputMpegFifo.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications - Research Center Canada) - */ -/* - This file is part of ODR-DabMux. - - ODR-DabMux 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 3 of the - License, or (at your option) any later version. - - ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "dabInputMpegFifo.h" -#include "dabInputFifo.h" -#include "dabInputMpegFile.h" - - -#ifdef HAVE_FORMAT_MPEG -# ifdef HAVE_INPUT_FIFO - - -struct dabInputOperations dabInputMpegFifoOperations = { - dabInputFifoInit, - dabInputFifoOpen, - dabInputFifoSetbuf, - dabInputFifoRead, - dabInputFifoLock, - dabInputFifoUnlock, - dabInputMpegFileRead, - dabInputSetbitrate, - dabInputFifoClose, - dabInputFifoClean, - dabInputFifoRewind -}; - - -# endif -#endif diff --git a/src/dabInputMpegFifo.h b/src/dabInputMpegFifo.h deleted file mode 100644 index a14ccbd..0000000 --- a/src/dabInputMpegFifo.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications - Research Center Canada) - */ -/* - This file is part of ODR-DabMux. - - ODR-DabMux 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 3 of the - License, or (at your option) any later version. - - ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef DAB_INPUT_MPEG_FIFO_H -#define DAB_INPUT_MPEG_FIFO_H - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - - -#ifdef HAVE_FORMAT_MPEG -# ifdef HAVE_INPUT_FIFO -extern struct dabInputOperations dabInputMpegFifoOperations; -# endif -#endif - - -#endif // DAB_INPUT_MPEG_FIFO_H diff --git a/src/dabInputMpegFile.cpp b/src/dabInputMpegFile.cpp deleted file mode 100644 index 804ea29..0000000 --- a/src/dabInputMpegFile.cpp +++ /dev/null @@ -1,201 +0,0 @@ -/* - Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications - Research Center Canada) - */ -/* - This file is part of ODR-DabMux. - - ODR-DabMux 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 3 of the - License, or (at your option) any later version. - - ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "dabInputMpegFile.h" -#include "dabInputFile.h" -#include "mpeg.h" - -#include <stdio.h> -#include <errno.h> -#include <string.h> - - -#ifdef HAVE_FORMAT_MPEG -# ifdef HAVE_INPUT_FILE - - -struct dabInputOperations dabInputMpegFileOperations = { - dabInputFileInit, - dabInputFileOpen, - dabInputSetbuf, - dabInputFileRead, - nullptr, - nullptr, - dabInputMpegFileRead, - dabInputMpegSetbitrate, - dabInputFileClose, - dabInputFileClean, - dabInputFileRewind -}; - - -#define MPEG_FREQUENCY -2 -#define MPEG_PADDING -3 -#define MPEG_COPYRIGHT -4 -#define MPEG_ORIGINAL -5 -#define MPEG_EMPHASIS -6 -int checkDabMpegFrame(void* data) { - mpegHeader* header = (mpegHeader*)data; - unsigned long* headerData = (unsigned long*)data; - if ((*headerData & 0x0f0ffcff) == 0x0004fcff) return 0; - if ((*headerData & 0x0f0ffcff) == 0x0004f4ff) return 0; - if (getMpegFrequency(header) != 48000) { - if (getMpegFrequency(header) != 24000) { - return MPEG_FREQUENCY; - } - } - if (header->padding != 0) { - return MPEG_PADDING; - } - if (header->copyright != 0) { - return MPEG_COPYRIGHT; - } - if (header->original != 0) { - return MPEG_ORIGINAL; - } - if (header->emphasis != 0) { - return MPEG_EMPHASIS; - } - return -1; -} - - -int dabInputMpegFileRead(dabInputOperations* ops, void* args, void* buffer, int size) -{ - dabInputFileData* data = (dabInputFileData*)args; - int result; - bool rewind = false; -READ_SUBCHANNEL: - if (data->parity) { - result = readData(data->file, buffer, size, 2); - data->parity = false; - return 0; - } else { - result = readMpegHeader(data->file, buffer, size); - if (result > 0) { - result = readMpegFrame(data->file, buffer, size); - if (result < 0 && getMpegFrequency(buffer) == 24000) { - data->parity = true; - result = size; - } - } - } - switch (result) { - case MPEG_BUFFER_UNDERFLOW: - etiLog.log(warn, "data underflow -> frame muted\n"); - goto MUTE_SUBCHANNEL; - case MPEG_BUFFER_OVERFLOW: - etiLog.log(warn, "bitrate too high -> frame muted\n"); - goto MUTE_SUBCHANNEL; - case MPEG_FILE_EMPTY: - if (rewind) { - etiLog.log(error, "file rewinded and still empty " - "-> frame muted\n"); - goto MUTE_SUBCHANNEL; - } else { - rewind = true; - etiLog.log(info, "reach end of file -> rewinding\n"); - lseek(data->file, 0, SEEK_SET); - goto READ_SUBCHANNEL; - } - case MPEG_FILE_ERROR: - etiLog.log(alert, "can't read file (%i) -> frame muted\n", errno); - perror(""); - goto MUTE_SUBCHANNEL; - case MPEG_SYNC_NOT_FOUND: - etiLog.log(alert, "mpeg sync not found, maybe is not a valid file " - "-> frame muted\n"); - goto MUTE_SUBCHANNEL; - case MPEG_INVALID_FRAME: - etiLog.log(alert, "file is not a valid mpeg file " - "-> frame muted\n"); - goto MUTE_SUBCHANNEL; - default: - if (result < 0) { - etiLog.log(alert, - "unknown error (code = %i) -> frame muted\n", - result); -MUTE_SUBCHANNEL: - memset(buffer, 0, size); - } else { - if (result < size) { - etiLog.log(warn, "bitrate too low from file " - "-> frame padded\n"); - memset((char*)buffer + result, 0, size - result); - } - result = checkDabMpegFrame(buffer); - switch (result) { - case MPEG_FREQUENCY: - etiLog.log(error, "file has a frame with an invalid " - "frequency: %i, should be 48000 or 24000\n", - getMpegFrequency(buffer)); - break; - case MPEG_PADDING: - etiLog.log(warn, - "file has a frame with padding bit set\n"); - break; - case MPEG_COPYRIGHT: - etiLog.log(warn, - "file has a frame with copyright bit set\n"); - break; - case MPEG_ORIGINAL: - etiLog.log(warn, - "file has a frame with original bit set\n"); - break; - case MPEG_EMPHASIS: - etiLog.log(warn, - "file has a frame with emphasis bits set\n"); - break; - default: - if (result < 0) { - etiLog.log(alert, "mpeg file has an invalid DAB " - "mpeg frame (unknown reason: %i)\n", result); - } - break; - } - } - } - return result; -} - - -int dabInputMpegSetbitrate(dabInputOperations* ops, void* args, int bitrate) -{ - //dabInputFileData* data = (dabInputFileData*)args; - if (bitrate == 0) { - char buffer[4]; - - if (ops->readFrame(ops, args, buffer, 4) == 0) { - bitrate = getMpegBitrate(buffer); - } else { - bitrate = -1; - } - ops->rewind(args); - } - if (ops->setbuf(args, bitrate * 3) != 0) { - bitrate = -1; - } - return bitrate; -} - - -# endif -#endif diff --git a/src/dabInputMpegFile.h b/src/dabInputMpegFile.h deleted file mode 100644 index a7dcb76..0000000 --- a/src/dabInputMpegFile.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications - Research Center Canada) - */ -/* - This file is part of ODR-DabMux. - - ODR-DabMux 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 3 of the - License, or (at your option) any later version. - - ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef DAB_INPUT_MPEG_FILE_H -#define DAB_INPUT_MPEG_FILE_H - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif -#include "dabInput.h" - - -#ifdef HAVE_FORMAT_MPEG -# ifdef HAVE_INPUT_FILE -extern struct dabInputOperations dabInputMpegFileOperations; - -int dabInputMpegFileRead(dabInputOperations* ops, void* args, void* buffer, int size); -int dabInputMpegSetbitrate(dabInputOperations* ops, void* args, int bitrate); -int checkDabMpegFrame(void* data); -# endif -#endif - - -#endif // DAB_INPUT_MPEG_FILE_H diff --git a/src/dabInputPacketFile.cpp b/src/dabInputPacketFile.cpp deleted file mode 100644 index 867d9fc..0000000 --- a/src/dabInputPacketFile.cpp +++ /dev/null @@ -1,263 +0,0 @@ -/* - Copyright (C) 2009, 2011 Her Majesty the Queen in Right of Canada - (Communications Research Center Canada) - */ -/* - This file is part of ODR-DabMux. - - ODR-DabMux 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 3 of the - License, or (at your option) any later version. - - ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "dabInputPacketFile.h" -#include "dabInputFile.h" -#include "dabInputFifo.h" -#include "ReedSolomon.h" - -#ifdef HAVE_FORMAT_PACKET -# ifdef HAVE_INPUT_FILE - - -#include <string.h> -#include <stdio.h> -#include <errno.h> - - -#ifdef _WIN32 -# pragma pack(push, 1) -#endif -struct packetHeader { - unsigned char addressHigh:2; - unsigned char last:1; - unsigned char first:1; - unsigned char continuityIndex:2; - unsigned char packetLength:2; - unsigned char addressLow; - unsigned char dataLength:7; - unsigned char command; -} -#ifdef _WIN32 -# pragma pack(pop) -#else -__attribute((packed)) -#endif -; - - -struct dabInputOperations dabInputPacketFileOperations = { - dabInputFileInit, - dabInputFileOpen, - dabInputSetbuf, - dabInputFileRead, - nullptr, - nullptr, - dabInputPacketFileRead, - dabInputSetbitrate, - dabInputFileClose, - dabInputFileClean, - dabInputFileRewind -}; - - -int dabInputPacketFileRead(dabInputOperations* ops, void* args, void* buffer, - int size) -{ - dabInputFileData* data = (dabInputFileData*)args; - unsigned char* dataBuffer = (unsigned char*)buffer; - int written = 0; - int length; - packetHeader* header; - int indexRow; - int indexCol; - - while (written < size) { - if (data->enhancedPacketWaiting > 0) { - *dataBuffer = 192 - data->enhancedPacketWaiting; - *dataBuffer /= 22; - *dataBuffer <<= 2; - *(dataBuffer++) |= 0x03; - *(dataBuffer++) = 0xfe; - indexCol = 188; - indexCol += (192 - data->enhancedPacketWaiting) / 12; - indexRow = 0; - indexRow += (192 - data->enhancedPacketWaiting) % 12; - for (int j = 0; j < 22; ++j) { - if (data->enhancedPacketWaiting == 0) { - *(dataBuffer++) = 0; - } else { - *(dataBuffer++) = data->enhancedPacketData[indexRow][indexCol]; - if (++indexRow == 12) { - indexRow = 0; - ++indexCol; - } - --data->enhancedPacketWaiting; - } - } - written += 24; - if (data->enhancedPacketWaiting == 0) { - data->enhancedPacketLength = 0; - } - } else if (data->packetLength != 0) { - header = (packetHeader*)data->packetData; - if (written + data->packetLength > (unsigned)size) { - memset(dataBuffer, 0, 22); - dataBuffer[22] = 0x60; - dataBuffer[23] = 0x4b; - length = 24; - } else if (data->enhancedPacketData != nullptr) { - if (data->enhancedPacketLength + data->packetLength - > (12 * 188)) { - memset(dataBuffer, 0, 22); - dataBuffer[22] = 0x60; - dataBuffer[23] = 0x4b; - length = 24; - } else { - memcpy(dataBuffer, data->packetData, data->packetLength); - length = data->packetLength; - data->packetLength = 0; - } - } else { - memcpy(dataBuffer, data->packetData, data->packetLength); - length = data->packetLength; - data->packetLength = 0; - } - if (data->enhancedPacketData != nullptr) { - indexCol = data->enhancedPacketLength / 12; - indexRow = data->enhancedPacketLength % 12; // TODO Check if always 0 - for (int j = 0; j < length; ++j) { - data->enhancedPacketData[indexRow][indexCol] = dataBuffer[j]; - if (++indexRow == 12) { - indexRow = 0; - ++indexCol; - } - } - data->enhancedPacketLength += length; - if (data->enhancedPacketLength >= (12 * 188)) { - data->enhancedPacketLength = (12 * 188); - ReedSolomon encoder(204, 188); - for (int j = 0; j < 12; ++j) { - encoder.encode(data->enhancedPacketData[j], 188); - } - data->enhancedPacketWaiting = 192; - } - } - written += length; - dataBuffer += length; - } else { - int nbBytes = ops->read(args, dataBuffer, 3); - header = (packetHeader*)dataBuffer; - if (nbBytes == -1) { - if (errno == EAGAIN) goto END_PACKET; - perror("Packet file"); - return -1; - } else if (nbBytes == 0) { - if (ops->rewind(args) == -1) { - goto END_PACKET; - } - continue; - } else if (nbBytes < 3) { - etiLog.log(error, - "Error while reading file for packet header; " - "read %i out of 3 bytes\n", nbBytes); - break; - } - - length = header->packetLength * 24 + 24; - if (written + length > size) { - memcpy(data->packetData, header, 3); - ops->read(args, &data->packetData[3], length - 3); - data->packetLength = length; - continue; - } - if (data->enhancedPacketData != nullptr) { - if (data->enhancedPacketLength + length > (12 * 188)) { - memcpy(data->packetData, header, 3); - ops->read(args, &data->packetData[3], length - 3); - data->packetLength = length; - continue; - } - } - nbBytes = ops->read(args, dataBuffer + 3, length - 3); - if (nbBytes == -1) { - perror("Packet file"); - return -1; - } else if (nbBytes == 0) { - etiLog.log(info, - "Packet header read, but no data!\n"); - if (ops->rewind(args) == -1) { - goto END_PACKET; - } - continue; - } else if (nbBytes < length - 3) { - etiLog.log(error, "Error while reading packet file; " - "read %i out of %i bytes\n", nbBytes, length - 3); - break; - } - if (data->enhancedPacketData != nullptr) { - indexCol = data->enhancedPacketLength / 12; - indexRow = data->enhancedPacketLength % 12; // TODO Check if always 0 - for (int j = 0; j < length; ++j) { - data->enhancedPacketData[indexRow][indexCol] = dataBuffer[j]; - if (++indexRow == 12) { - indexRow = 0; - ++indexCol; - } - } - data->enhancedPacketLength += length; - if (data->enhancedPacketLength >= (12 * 188)) { - if (data->enhancedPacketLength > (12 * 188)) { - etiLog.log(error, - "Error, too much enhanced packet data!\n"); - } - ReedSolomon encoder(204, 188); - for (int j = 0; j < 12; ++j) { - encoder.encode(data->enhancedPacketData[j], 188); - } - data->enhancedPacketWaiting = 192; - } - } - written += length; - dataBuffer += length; - } - } -END_PACKET: - if (ops->read == dabInputFifoRead) { - dabInputFifoData* fifoData = (dabInputFifoData*)args; - dabInputFifoStats* fifoStats = (dabInputFifoStats*)&fifoData->stats; - fifoStats->frameRecords[fifoStats->frameCount].curSize = written; - fifoStats->frameRecords[fifoStats->frameCount].maxSize = size; - if (++fifoStats->frameCount == NB_RECORDS) { - etiLog.log(info, "Packet subchannel usage: (%i)", - fifoStats->id); - for (int i = 0; i < fifoStats->frameCount; ++i) { - etiLog.log(info, " %i/%i", - fifoStats->frameRecords[i].curSize, - fifoStats->frameRecords[i].maxSize); - } - etiLog.log(info, "\n"); - fifoStats->frameCount = 0; - } - } - while (written < size) { - memset(dataBuffer, 0, 22); - dataBuffer[22] = 0x60; - dataBuffer[23] = 0x4b; - dataBuffer += 24; - written += 24; - } - return written; -} - - -# endif -#endif diff --git a/src/dabInputPacketFile.h b/src/dabInputPacketFile.h deleted file mode 100644 index 77f33a6..0000000 --- a/src/dabInputPacketFile.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications - Research Center Canada) - */ -/* - This file is part of ODR-DabMux. - - ODR-DabMux 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 3 of the - License, or (at your option) any later version. - - ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef DAB_INPUT_PACKET_FILE_H -#define DAB_INPUT_PACKET_FILE_H - - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif -#include "dabInput.h" - - -#ifdef HAVE_FORMAT_PACKET -# ifdef HAVE_INPUT_FILE - - -extern struct dabInputOperations dabInputPacketFileOperations; - -int dabInputPacketFileRead(dabInputOperations* ops, void* args, void* buffer, - int size); - - -# endif -#endif - - -#endif // DAB_INPUT_PACKET_FILE_H diff --git a/src/dabInputRawFifo.cpp b/src/dabInputRawFifo.cpp deleted file mode 100644 index cc6268b..0000000 --- a/src/dabInputRawFifo.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/* - Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications - Research Center Canada) - */ -/* - This file is part of ODR-DabMux. - - ODR-DabMux 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 3 of the - License, or (at your option) any later version. - - ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "dabInputRawFifo.h" - -#include <unistd.h> -#include <stdio.h> -#include <fcntl.h> -#include <string.h> - -#ifndef _WIN32 -# define O_BINARY 0 -#endif - - -#ifdef HAVE_FORMAT_RAW -# ifdef HAVE_INPUT_FILE - - -struct dabInputOperations dabInputRawFifoOperations = { - dabInputRawFifoInit, - dabInputRawFifoOpen, - dabInputRawFifoSetbuf, - dabInputRawFifoRead, - nullptr, - nullptr, - dabInputRawFifoReadFrame, - dabInputSetbitrate, - dabInputRawFifoClose, - dabInputRawFifoClean, - dabInputRawFifoRewind -}; - - -int dabInputRawFifoInit(void** args) -{ - dabInputRawFifoData* data = new dabInputRawFifoData; - data->file = -1; - data->buffer = nullptr; - data->bufferSize = 0; - data->bufferOffset = 0; - - *args = data; - return 0; -} - - -int dabInputRawFifoOpen(void* args, const char* filename) -{ - dabInputRawFifoData* data = (dabInputRawFifoData*)args; - data->file = open(filename, O_RDONLY | O_BINARY | O_NONBLOCK); - if (data->file == -1) { - perror(filename); - return -1; - } -#ifdef _WIN32 -#else - int flags = fcntl(data->file, F_GETFL); - if (flags == -1) { - perror(filename); - return -1; - } - if (fcntl(data->file, F_SETFL, flags & ~O_NONBLOCK) == -1) { - perror(filename); - return -1; - } -#endif - - return 0; -} - - -int dabInputRawFifoSetbuf(void* args, int size) -{ - dabInputRawFifoData* data = (dabInputRawFifoData*)args; - - if (size <= 0) { - return size; - } - - if (data->bufferSize != (size_t)size) { - if (data->buffer != nullptr) { - delete[] data->buffer; - } - data->buffer = new uint8_t[size]; - data->bufferSize = size; - data->bufferOffset = 0; - } - - return 0; -} - - -int dabInputRawFifoRead(void* args, void* buffer, int size) -{ - dabInputRawFifoData* data = (dabInputRawFifoData*)args; - - return read(data->file, buffer, size); -} - - -int dabInputRawFifoReadFrame(dabInputOperations* ops, void* args, - void* buffer, int size) -{ - dabInputRawFifoData* data = (dabInputRawFifoData*)args; - int result; - - result = ops->read(args, data->buffer + data->bufferOffset, size - data->bufferOffset); - if (result == -1) { - etiLog.log(alert, "ERROR: Can't read fifo\n"); - perror(""); - return -1; - } - - if (result + data->bufferOffset < (size_t)size) { - data->bufferOffset += result; - - etiLog.log(info, "reach end of fifo -> rewinding\n"); - if (ops->rewind(args) == -1) { - etiLog.log(alert, "ERROR: Can't rewind fifo\n"); - return -1; - } - - result = ops->read(args, data->buffer + data->bufferOffset, size - data->bufferOffset); - if (result == -1) { - etiLog.log(alert, "ERROR: Can't read fifo\n"); - perror(""); - return -1; - } - - if (result < size) { - etiLog.log(alert, "ERROR: Not enought data in fifo\n"); - return 0; - } - } - - memcpy(buffer, data->buffer, size); - data->bufferOffset = 0; - - return size; -} - - -int dabInputRawFifoClose(void* args) -{ - dabInputRawFifoData* data = (dabInputRawFifoData*)args; - - if (data->file != -1) { - close(data->file); - data->file = -1; - } - return 0; -} - - -int dabInputRawFifoClean(void** args) -{ - dabInputRawFifoData* data = (dabInputRawFifoData*)*args; - if (data->buffer != nullptr) { - delete[] data->buffer; - } - delete data; - return 0; -} - - -int dabInputRawFifoRewind(void* args) -{ - dabInputRawFifoData* data = (dabInputRawFifoData*)args; - return lseek(data->file, 0, SEEK_SET); -} - - -# endif -#endif diff --git a/src/dabInputRawFifo.h b/src/dabInputRawFifo.h deleted file mode 100644 index 7d2a3a0..0000000 --- a/src/dabInputRawFifo.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications - Research Center Canada) - */ -/* - This file is part of ODR-DabMux. - - ODR-DabMux 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 3 of the - License, or (at your option) any later version. - - ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef DAB_INPUT_RAW_FIFO_H -#define DAB_INPUT_RAW_FIFO_H - - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "dabInput.h" - -#include <stdint.h> - - -#ifdef HAVE_FORMAT_RAW -# ifdef HAVE_INPUT_FILE - - -extern struct dabInputOperations dabInputRawFifoOperations; - -int dabInputRawFifoInit(void** args); -int dabInputRawFifoOpen(void* args, const char* filename); -int dabInputRawFifoSetbuf(void* args, int size); -int dabInputRawFifoRead(void* args, void* buffer, int size); -int dabInputRawFifoReadFrame(dabInputOperations* ops, void* args, - void* buffer, int size); -int dabInputRawFifoClose(void* args); -int dabInputRawFifoClean(void** args); -int dabInputRawFifoRewind(void* args); - - -struct dabInputRawFifoData { - int file; - uint8_t* buffer; - size_t bufferSize; - size_t bufferOffset; -}; - - -# endif -#endif - -#endif // DAB_INPUT_RAW_FIFO_H diff --git a/src/dabInputRawFile.cpp b/src/dabInputRawFile.cpp deleted file mode 100644 index be33a45..0000000 --- a/src/dabInputRawFile.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* - Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications - Research Center Canada) - */ -/* - This file is part of ODR-DabMux. - - ODR-DabMux 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 3 of the - License, or (at your option) any later version. - - ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "dabInputRawFile.h" -#include "dabInputFile.h" - - -#ifdef HAVE_FORMAT_RAW -# ifdef HAVE_INPUT_FILE - - -struct dabInputOperations dabInputRawFileOperations = { - dabInputFileInit, - dabInputFileOpen, - dabInputSetbuf, - dabInputFileRead, - nullptr, - nullptr, - dabInputRawFileRead, - dabInputSetbitrate, - dabInputFileClose, - dabInputFileClean, - dabInputFileRewind -}; - - -int dabInputRawFileRead(dabInputOperations* ops, void* args, void* buffer, - int size) -{ - int ret = ops->read(args, buffer, size); - if (ret == 0) { - etiLog.log(info, "reach end of raw file -> rewinding\n"); - ops->rewind(args); - ret = ops->read(args, buffer, size); - } - return ret; -} - - -# endif -#endif diff --git a/src/dabInputRawFile.h b/src/dabInputRawFile.h deleted file mode 100644 index 9a4a607..0000000 --- a/src/dabInputRawFile.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications - Research Center Canada) - */ -/* - This file is part of ODR-DabMux. - - ODR-DabMux 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 3 of the - License, or (at your option) any later version. - - ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef DAB_INPUT_RAW_FILE_H -#define DAB_INPUT_RAW_FILE_H - - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif -#include "dabInput.h" - - -#ifdef HAVE_FORMAT_RAW -# ifdef HAVE_INPUT_FILE - - -extern struct dabInputOperations dabInputRawFileOperations; - -int dabInputRawFileRead(dabInputOperations* ops, void* args, void* buffer, - int size); - - -# endif -#endif - -#endif // DAB_INPUT_RAW_FILE_H diff --git a/src/dabInputTest.cpp b/src/dabInputTest.cpp deleted file mode 100644 index fd4fc59..0000000 --- a/src/dabInputTest.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications - Research Center Canada) - */ -/* - This file is part of ODR-DabMux. - - ODR-DabMux 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 3 of the - License, or (at your option) any later version. - - ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "dabInputTest.h" - -#include <string.h> -#ifdef _WIN32 -#else -# include <arpa/inet.h> -#endif - - -#ifdef HAVE_FORMAT_RAW -# ifdef HAVE_INPUT_TEST - - -struct dabInputTestData { - unsigned long counter; -}; - - -struct dabInputOperations dabInputTestOperations = { - dabInputTestInit, - dabInputTestOpen, - NULL, - NULL, - NULL, - NULL, - dabInputTestRead, - dabInputTestSetbitrate, - dabInputTestClose, - dabInputTestClean, - NULL -}; - - -int dabInputTestInit(void** args) -{ - dabInputTestData* input = new dabInputTestData; - memset(input, 0, sizeof(*input)); - input->counter = 0; - *args = input; - return 0; -} - - -int dabInputTestOpen(void* args, const char* inputName) -{ - return 0; -} - - -int dabInputTestRead(dabInputOperations* ops, void* args, void* buffer, int size) -{ - dabInputTestData* input = (dabInputTestData*)args; - char* data = (char*)buffer; - - *((long*)buffer) = htonl(input->counter++); - for (int i = sizeof(input->counter); i < size; ++i) { - data[i] = i; - } - return size; -} - - -int dabInputTestSetbitrate(dabInputOperations* ops, void* args, int bitrate) -{ - return bitrate; -} - - -int dabInputTestClose(void* args) -{ - return 0; -} - - -int dabInputTestClean(void** args) -{ - dabInputTestData* input = (dabInputTestData*)(*args); - delete input; - return 0; -} - - -# endif -#endif diff --git a/src/dabInputTest.h b/src/dabInputTest.h deleted file mode 100644 index 34ebc05..0000000 --- a/src/dabInputTest.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications - Research Center Canada) - */ -/* - This file is part of ODR-DabMux. - - ODR-DabMux 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 3 of the - License, or (at your option) any later version. - - ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef DAB_INPUT_TEST_H -#define DAB_INPUT_TEST_H - - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif -#include "dabInput.h" - - -#ifdef HAVE_FORMAT_RAW -# ifdef HAVE_INPUT_TEST - - -extern struct dabInputOperations dabInputTestOperations; - -int dabInputTestInit(void** args); -int dabInputTestOpen(void* args, const char* inputName); -int dabInputTestRead(dabInputOperations* ops, void* args, void* buffer, int size); -int dabInputTestSetbitrate(dabInputOperations* ops, void* args, int bitrate); -int dabInputTestClose(void* args); -int dabInputTestClean(void** args); - - -# endif -#endif - - -#endif // DAB_INPUT_TEST_H diff --git a/src/dabInputUdp.cpp b/src/dabInputUdp.cpp deleted file mode 100644 index 0765599..0000000 --- a/src/dabInputUdp.cpp +++ /dev/null @@ -1,199 +0,0 @@ -/* - Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications - Research Center Canada) - */ -/* - This file is part of ODR-DabMux. - - ODR-DabMux 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 3 of the - License, or (at your option) any later version. - - ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "dabInputUdp.h" - -#include <string.h> -#include <limits.h> - - -#ifdef __MINGW32__ -# define bzero(s, n) memset(s, 0, n) -#endif - -#ifdef HAVE_FORMAT_RAW -# ifdef HAVE_INPUT_UDP - - -struct dabInputOperations dabInputUdpOperations = { - dabInputUdpInit, - dabInputUdpOpen, - dabInputSetbuf, - NULL, - NULL, - NULL, - dabInputUdpRead, - dabInputSetbitrate, - dabInputUdpClose, - dabInputUdpClean, - NULL -}; - - -int dabInputUdpInit(void** args) -{ - dabInputUdpData* input = new dabInputUdpData; - memset(&input->stats, 0, sizeof(input->stats)); - input->stats.id = dabInputFifoData::nb++; - input->socket = new UdpSocket(); - input->packet = new UdpPacket(2048); - *args = input; - - UdpSocket::init(); - return 0; -} - - -int dabInputUdpOpen(void* args, const char* inputName) -{ - int returnCode = 0; - char* address; - char* ptr; - long port; - dabInputUdpData* input = (dabInputUdpData*)args; - - // Skip the udp:// part if it is present - if (strncmp(inputName, "udp://", 6) == 0) { - address = strdup(inputName + 6); - } - else { - address = strdup(inputName); - } - - ptr = strchr(address, ':'); - if (ptr == NULL) { - etiLog.log(error, - "\"%s\" is an invalid format for udp address: " - "should be [udp://][address]:port - > aborting\n", address); - returnCode = -1; - goto udpopen_ptr_null_out; - } - *(ptr++) = 0; - port = strtol(ptr, (char **)NULL, 10); - if ((port == LONG_MIN) || (port == LONG_MAX)) { - etiLog.log(error, - "can't convert port number in udp address %s\n", - address); - returnCode = -1; - } - if (port == 0) { - etiLog.log(error, "can't use port number 0 in udp address\n"); - returnCode = -1; - } - if (input->socket->create(port) == -1) { - etiLog.log(error, "can't set port %i on Udp input (%s: %s)\n", - port, inetErrDesc, inetErrMsg); - returnCode = -1; - } - - if (*address != 0) { - if (input->socket->joinGroup(address) == -1) { - etiLog.log(error, - "can't join multicast group %s (%s: %s)\n", - address, inetErrDesc, inetErrMsg); - returnCode = -1; - } - } - - if (input->socket->setBlocking(false) == -1) { - etiLog.log(error, "can't set Udp input socket in blocking mode " - "(%s: %s)\n", inetErrDesc, inetErrMsg); - returnCode = -1; - } - -udpopen_ptr_null_out: - free(address); - etiLog.log(debug, "check return code of create\n"); - return returnCode; -} - - -int dabInputUdpRead(dabInputOperations* ops, void* args, void* buffer, int size) -{ - int nbBytes = 0; - uint8_t* data = reinterpret_cast<uint8_t*>(buffer); - - dabInputUdpData* input = (dabInputUdpData*)args; - dabInputFifoStats* stats = (dabInputFifoStats*)&input->stats; - - input->stats.frameRecords[input->stats.frameCount].curSize = 0; - input->stats.frameRecords[input->stats.frameCount].maxSize = size; - - if (input->packet->getLength() == 0) { - input->socket->receive(*input->packet); - } - - while (nbBytes < size) { - unsigned freeSize = size - nbBytes; - if (input->packet->getLength() > freeSize) { - // Not enought place in output - memcpy(&data[nbBytes], input->packet->getData(), freeSize); - nbBytes = size; - input->packet->setOffset(input->packet->getOffset() + freeSize); - } else { - unsigned length = input->packet->getLength(); - memcpy(&data[nbBytes], input->packet->getData(), length); - nbBytes += length; - input->packet->setOffset(0); - input->socket->receive(*input->packet); - if (input->packet->getLength() == 0) { - break; - } - } - } - input->stats.frameRecords[input->stats.frameCount].curSize = nbBytes; - bzero(&data[nbBytes], size - nbBytes); - - input->stats.frameRecords[input->stats.frameCount].curSize = nbBytes; - if (++stats->frameCount == NB_RECORDS) { - etiLog.log(info, "Data subchannel usage: (%i)", - stats->id); - for (int i = 0; i < stats->frameCount; ++i) { - etiLog.log(info, " %i/%i", - stats->frameRecords[i].curSize, - stats->frameRecords[i].maxSize); - } - etiLog.log(info, "\n"); - stats->frameCount = 0; - } - - return size; -} - - -int dabInputUdpClose(void* args) -{ - return 0; -} - - -int dabInputUdpClean(void** args) -{ - dabInputUdpData* input = (dabInputUdpData*)(*args); - delete input->socket; - delete input->packet; - delete input; - return 0; -} - - -# endif -#endif diff --git a/src/dabOutput/dabOutput.h b/src/dabOutput/dabOutput.h index eaa623f..c10d358 100644 --- a/src/dabOutput/dabOutput.h +++ b/src/dabOutput/dabOutput.h @@ -222,11 +222,6 @@ class TCPDataDispatcher; class DabOutputTcp : public DabOutput { public: - DabOutputTcp() {} - DabOutputTcp(const DabOutputTcp& other) = delete; - const DabOutputTcp& operator=(const DabOutputTcp& other) = delete; - ~DabOutputTcp(); - int Open(const char* name); int Write(void* buffer, int size); int Close(); @@ -238,7 +233,7 @@ class DabOutputTcp : public DabOutput private: std::string uri_; - TCPDataDispatcher* dispatcher_; + std::shared_ptr<TCPDataDispatcher> dispatcher_; }; // -------------- Simul ------------------ diff --git a/src/dabOutput/dabOutputTcp.cpp b/src/dabOutput/dabOutputTcp.cpp index 8696bec..2aab48a 100644 --- a/src/dabOutput/dabOutputTcp.cpp +++ b/src/dabOutput/dabOutputTcp.cpp @@ -95,6 +95,10 @@ class TCPConnection m_running = false; } } + + auto addr = m_sock.getRemoteAddress(); + etiLog.level(debug) << "Dropping TCP Connection from " << + addr.getHostAddress() << ":" << addr.getPort(); } }; @@ -121,22 +125,28 @@ class TCPDataDispatcher connection.queue.push(data); } - m_connections.remove_if([](TCPConnection& conn){ return conn.is_overloaded(); }); + m_connections.remove_if([](const TCPConnection& conn){ return conn.is_overloaded(); }); } private: void process(long) { - m_listener_socket.listen(); + try { + m_listener_socket.listen(); - const int timeout_ms = 1000; + const int timeout_ms = 1000; - while (m_running) { - // Add a new TCPConnection to the list, constructing it from the client socket - auto optional_sock = m_listener_socket.accept(timeout_ms); - if (optional_sock) { - m_connections.emplace(m_connections.begin(), std::move(*optional_sock)); + while (m_running) { + // Add a new TCPConnection to the list, constructing it from the client socket + auto sock = m_listener_socket.accept(timeout_ms); + if (sock.isValid()) { + m_connections.emplace(m_connections.begin(), move(sock)); + } } } + catch (std::runtime_error& e) { + etiLog.level(error) << "TCPDataDispatcher caught runtime error: " << e.what(); + m_running = false; + } } atomic<bool> m_running; @@ -145,14 +155,6 @@ class TCPDataDispatcher std::list<TCPConnection> m_connections; }; -DabOutputTcp::~DabOutputTcp() -{ - if (dispatcher_) { - delete dispatcher_; - dispatcher_ = nullptr; - } -} - static bool parse_uri(const char *uri, long *port, string& addr) { char* const hostport = strdup(uri); // the uri is actually an tuple host:port @@ -199,7 +201,7 @@ int DabOutputTcp::Open(const char* name) uri_ = name; if (success) { - dispatcher_ = new TCPDataDispatcher(); + dispatcher_ = make_shared<TCPDataDispatcher>(); try { dispatcher_->start(port, address); } diff --git a/src/input/File.cpp b/src/input/File.cpp new file mode 100644 index 0000000..5c61fd4 --- /dev/null +++ b/src/input/File.cpp @@ -0,0 +1,443 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + + Copyright (C) 2016 Matthias P. Braendli + http://www.opendigitalradio.org + + */ +/* + This file is part of ODR-DabMux. + + ODR-DabMux 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 3 of the + License, or (at your option) any later version. + + ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <sstream> +#include <errno.h> +#include <stdlib.h> +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> +#ifndef _WIN32 +# define O_BINARY 0 +#endif + +#include "input/File.h" +#include "mpeg.h" +#include "ReedSolomon.h" + +namespace Inputs { + +#ifdef _WIN32 +# pragma pack(push, 1) +#endif +struct packetHeader { + unsigned char addressHigh:2; + unsigned char last:1; + unsigned char first:1; + unsigned char continuityIndex:2; + unsigned char packetLength:2; + unsigned char addressLow; + unsigned char dataLength:7; + unsigned char command; +} +#ifdef _WIN32 +# pragma pack(pop) +#else +__attribute((packed)) +#endif +; + + +int FileBase::open(const std::string& name) +{ + m_fd = ::open(name.c_str(), O_RDONLY | O_BINARY); + if (m_fd == -1) { + std::stringstream ss; + ss << "Could not open input file " << name << ": " << + strerror(errno); + throw std::runtime_error(ss.str()); + } + return 0; +} + +int FileBase::setBitrate(int bitrate) +{ + if (bitrate <= 0) { + etiLog.log(error, "Invalid bitrate (%i)\n", bitrate); + return -1; + } + + return bitrate; +} + + +int FileBase::close() +{ + if (m_fd != -1) { + ::close(m_fd); + m_fd = -1; + } + return 0; +} + +int FileBase::rewind() +{ + return ::lseek(m_fd, 0, SEEK_SET); +} + +ssize_t FileBase::readFromFile(uint8_t* buffer, size_t size) +{ + ssize_t ret = read(m_fd, buffer, size); + + if (ret == -1) { + etiLog.log(alert, "ERROR: Can't read file\n"); + perror(""); + return -1; + } + + if (ret < (ssize_t)size) { + ssize_t sizeOut = ret; + etiLog.log(info, "reach end of file -> rewinding\n"); + if (rewind() == -1) { + etiLog.log(alert, "ERROR: Can't rewind file\n"); + return -1; + } + + ret = read(m_fd, buffer + sizeOut, size - sizeOut); + if (ret == -1) { + etiLog.log(alert, "ERROR: Can't read file\n"); + perror(""); + return -1; + } + + if (ret < (ssize_t)size) { + etiLog.log(alert, "ERROR: Not enough data in file\n"); + return -1; + } + } + + return size; +} + +int MPEGFile::readFrame(uint8_t* buffer, size_t size) +{ + int result; + bool do_rewind = false; +READ_SUBCHANNEL: + if (m_parity) { + result = readData(m_fd, buffer, size, 2); + m_parity = false; + return 0; + } else { + result = readMpegHeader(m_fd, buffer, size); + if (result > 0) { + result = readMpegFrame(m_fd, buffer, size); + if (result < 0 && getMpegFrequency(buffer) == 24000) { + m_parity = true; + result = size; + } + } + } + switch (result) { + case MPEG_BUFFER_UNDERFLOW: + etiLog.log(warn, "data underflow -> frame muted\n"); + goto MUTE_SUBCHANNEL; + case MPEG_BUFFER_OVERFLOW: + etiLog.log(warn, "bitrate too high -> frame muted\n"); + goto MUTE_SUBCHANNEL; + case MPEG_FILE_EMPTY: + if (do_rewind) { + etiLog.log(error, "file rewinded and still empty " + "-> frame muted\n"); + goto MUTE_SUBCHANNEL; + } + else { + etiLog.log(info, "reach end of file -> rewinding\n"); + rewind(); + goto READ_SUBCHANNEL; + } + case MPEG_FILE_ERROR: + etiLog.log(alert, "can't read file (%i) -> frame muted\n", errno); + perror(""); + goto MUTE_SUBCHANNEL; + case MPEG_SYNC_NOT_FOUND: + etiLog.log(alert, "mpeg sync not found, maybe is not a valid file " + "-> frame muted\n"); + goto MUTE_SUBCHANNEL; + case MPEG_INVALID_FRAME: + etiLog.log(alert, "file is not a valid mpeg file " + "-> frame muted\n"); + goto MUTE_SUBCHANNEL; + default: + if (result < 0) { + etiLog.log(alert, + "unknown error (code = %i) -> frame muted\n", + result); +MUTE_SUBCHANNEL: + memset(buffer, 0, size); + } + else { + if (result < (ssize_t)size) { + etiLog.log(warn, "bitrate too low from file " + "-> frame padded\n"); + memset((char*)buffer + result, 0, size - result); + } + + result = checkDabMpegFrame(buffer); + switch (result) { + case MPEG_FREQUENCY: + etiLog.log(error, "file has a frame with an invalid " + "frequency: %i, should be 48000 or 24000\n", + getMpegFrequency(buffer)); + break; + case MPEG_PADDING: + etiLog.log(warn, + "file has a frame with padding bit set\n"); + break; + case MPEG_COPYRIGHT: + result = 0; + break; + case MPEG_ORIGINAL: + result = 0; + break; + case MPEG_EMPHASIS: + etiLog.log(warn, + "file has a frame with emphasis bits set\n"); + break; + default: + if (result < 0) { + etiLog.log(alert, "mpeg file has an invalid DAB " + "mpeg frame (unknown reason: %i)\n", result); + } + break; + } + } + } + return result; +} + +int MPEGFile::setBitrate(int bitrate) +{ + if (bitrate == 0) { + uint8_t buffer[4]; + + if (readFrame(buffer, 4) == 0) { + bitrate = getMpegBitrate(buffer); + } + else { + bitrate = -1; + } + rewind(); + } + return bitrate; +} + +int RawFile::readFrame(uint8_t* buffer, size_t size) +{ + return readFromFile(buffer, size); +} + +PacketFile::PacketFile(bool enhancedPacketMode) +{ + m_enhancedPacketEnabled = enhancedPacketMode; +} + +int PacketFile::readFrame(uint8_t* buffer, size_t size) +{ + size_t written = 0; + int length; + packetHeader* header; + int indexRow; + int indexCol; + + while (written < size) { + if (m_enhancedPacketWaiting > 0) { + *buffer = 192 - m_enhancedPacketWaiting; + *buffer /= 22; + *buffer <<= 2; + *(buffer++) |= 0x03; + *(buffer++) = 0xfe; + indexCol = 188; + indexCol += (192 - m_enhancedPacketWaiting) / 12; + indexRow = 0; + indexRow += (192 - m_enhancedPacketWaiting) % 12; + for (int j = 0; j < 22; ++j) { + if (m_enhancedPacketWaiting == 0) { + *(buffer++) = 0; + } + else { + *(buffer++) = m_enhancedPacketData[indexRow][indexCol]; + if (++indexRow == 12) { + indexRow = 0; + ++indexCol; + } + --m_enhancedPacketWaiting; + } + } + written += 24; + if (m_enhancedPacketWaiting == 0) { + m_enhancedPacketLength = 0; + } + } + else if (m_packetLength != 0) { + header = (packetHeader*)(&m_packetData[0]); + if (written + m_packetLength > (unsigned)size) { + memset(buffer, 0, 22); + buffer[22] = 0x60; + buffer[23] = 0x4b; + length = 24; + } + else if (m_enhancedPacketEnabled) { + if (m_enhancedPacketLength + m_packetLength > (12 * 188)) { + memset(buffer, 0, 22); + buffer[22] = 0x60; + buffer[23] = 0x4b; + length = 24; + } + else { + std::copy(m_packetData.begin(), + m_packetData.begin() + m_packetLength, + buffer); + length = m_packetLength; + m_packetLength = 0; + } + } + else { + std::copy(m_packetData.begin(), + m_packetData.begin() + m_packetLength, + buffer); + length = m_packetLength; + m_packetLength = 0; + } + + if (m_enhancedPacketEnabled) { + indexCol = m_enhancedPacketLength / 12; + indexRow = m_enhancedPacketLength % 12; // TODO Check if always 0 + for (int j = 0; j < length; ++j) { + m_enhancedPacketData[indexRow][indexCol] = buffer[j]; + if (++indexRow == 12) { + indexRow = 0; + ++indexCol; + } + } + m_enhancedPacketLength += length; + if (m_enhancedPacketLength >= (12 * 188)) { + m_enhancedPacketLength = (12 * 188); + ReedSolomon encoder(204, 188); + for (int j = 0; j < 12; ++j) { + encoder.encode(&m_enhancedPacketData[j][0], 188); + } + m_enhancedPacketWaiting = 192; + } + } + written += length; + buffer += length; + } + else { + int nbBytes = readFromFile(buffer, 3); + header = (packetHeader*)buffer; + if (nbBytes == -1) { + if (errno == EAGAIN) goto END_PACKET; + perror("Packet file"); + return -1; + } + else if (nbBytes == 0) { + if (rewind() == -1) { + goto END_PACKET; + } + continue; + } + else if (nbBytes < 3) { + etiLog.log(error, + "Error while reading file for packet header; " + "read %i out of 3 bytes\n", nbBytes); + break; + } + + length = header->packetLength * 24 + 24; + if (written + length > size) { + memcpy(&m_packetData[0], header, 3); + readFromFile(&m_packetData[3], length - 3); + m_packetLength = length; + continue; + } + + if (m_enhancedPacketEnabled) { + if (m_enhancedPacketLength + length > (12 * 188)) { + memcpy(&m_packetData[0], header, 3); + readFromFile(&m_packetData[3], length - 3); + m_packetLength = length; + continue; + } + } + + nbBytes = readFromFile(buffer + 3, length - 3); + if (nbBytes == -1) { + perror("Packet file"); + return -1; + } + else if (nbBytes == 0) { + etiLog.log(info, + "Packet header read, but no data!\n"); + if (rewind() == -1) { + goto END_PACKET; + } + continue; + } + else if (nbBytes < length - 3) { + etiLog.log(error, "Error while reading packet file; " + "read %i out of %i bytes\n", nbBytes, length - 3); + break; + } + + if (m_enhancedPacketEnabled) { + indexCol = m_enhancedPacketLength / 12; + indexRow = m_enhancedPacketLength % 12; // TODO Check if always 0 + for (int j = 0; j < length; ++j) { + m_enhancedPacketData[indexRow][indexCol] = buffer[j]; + if (++indexRow == 12) { + indexRow = 0; + ++indexCol; + } + } + m_enhancedPacketLength += length; + if (m_enhancedPacketLength >= (12 * 188)) { + if (m_enhancedPacketLength > (12 * 188)) { + etiLog.log(error, + "Error, too much enhanced packet data!\n"); + } + ReedSolomon encoder(204, 188); + for (int j = 0; j < 12; ++j) { + encoder.encode(&m_enhancedPacketData[j][0], 188); + } + m_enhancedPacketWaiting = 192; + } + } + written += length; + buffer += length; + } + } +END_PACKET: + while (written < size) { + memset(buffer, 0, 22); + buffer[22] = 0x60; + buffer[23] = 0x4b; + buffer += 24; + written += 24; + } + return written; +} + +}; diff --git a/src/input/File.h b/src/input/File.h new file mode 100644 index 0000000..080d6b5 --- /dev/null +++ b/src/input/File.h @@ -0,0 +1,91 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + + Copyright (C) 2016 Matthias P. Braendli + http://www.opendigitalradio.org + + */ +/* + This file is part of ODR-DabMux. + + ODR-DabMux 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 3 of the + License, or (at your option) any later version. + + ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include <vector> +#include <array> +#include <string> +#include <stdint.h> +#include "input/inputs.h" +#include "ManagementServer.h" + +namespace Inputs { + +class FileBase : public InputBase { + public: + virtual int open(const std::string& name); + virtual int readFrame(uint8_t* buffer, size_t size) = 0; + virtual int setBitrate(int bitrate); + virtual int close(); + + /* Rewind the file + * Returns -1 on failure, 0 on success + */ + virtual int rewind(); + protected: + /* Read len bytes from the file into buf, and return + * the number of bytes read, or -1 in case of error. + */ + virtual ssize_t readFromFile(uint8_t* buf, size_t len); + + // We use unix open() instead of fopen() because + // we might want to do non-blocking I/O in the future + int m_fd = -1; +}; + +class MPEGFile : public FileBase { + public: + virtual int readFrame(uint8_t* buffer, size_t size); + virtual int setBitrate(int bitrate); + + private: + bool m_parity = false; +}; + +class RawFile : public FileBase { + public: + virtual int readFrame(uint8_t* buffer, size_t size); +}; + +class PacketFile : public FileBase { + public: + PacketFile(bool enhancedPacketMode); + virtual int readFrame(uint8_t* buffer, size_t size); + + protected: + std::array<uint8_t,96> m_packetData; + size_t m_packetLength; + + /* Enhanced packet mode enables FEC for MSC packet mode + * as described in EN 300 401 Clause 5.3.5 + */ + bool m_enhancedPacketEnabled = false; + std::array<std::array<uint8_t, 204>,12> m_enhancedPacketData; + size_t m_enhancedPacketWaiting; + size_t m_enhancedPacketLength; +}; + +}; diff --git a/src/dabInputPrbs.cpp b/src/input/Prbs.cpp index f34c427..7856a46 100644 --- a/src/dabInputPrbs.cpp +++ b/src/input/Prbs.cpp @@ -26,7 +26,7 @@ along with ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. */ -#include "dabInputPrbs.h" +#include "input/Prbs.h" #include <stdexcept> #include <sstream> @@ -34,59 +34,72 @@ #include <limits.h> #include <stdlib.h> #include <errno.h> +#include "utils.h" using namespace std; -int DabInputPrbs::open(const string name) +namespace Inputs { + +// ETS 300 799 Clause G.2.1 +// Preferred polynomial is G(x) = x^20 + x^17 + 1 +const uint32_t PRBS_DEFAULT_POLY = (1 << 20) | (1 << 17) | (1 << 0); + +int Prbs::open(const string& name) { - if (name[0] != ':') { - throw invalid_argument( - "Invalid PRBS address format. Must be prbs://:polynomial."); + if (name.substr(0, 7) != "prbs://") { + throw logic_error("Invalid PRBS name"); } - const string poly_str = name.substr(1); + const string& url_polynomial = name.substr(7); - long polynomial = strtol(poly_str.c_str(), (char **)NULL, 10); - if ((polynomial == LONG_MIN) || (polynomial == LONG_MAX)) { - stringstream ss; - ss << "Can't convert polynomial number " << poly_str; - throw invalid_argument(ss.str()); + if (url_polynomial.empty()) { + m_prbs.setup(PRBS_DEFAULT_POLY); } + else { + if (url_polynomial[0] != ':') { + throw invalid_argument( + "Invalid PRBS address format. " + "Must be prbs://:polynomial."); + } - if (polynomial == 0) { - throw invalid_argument("No polynomial given for PRBS input"); - } + const string poly_str = url_polynomial.substr(1); + + long polynomial = hexparse(poly_str); - m_prbs.setup(polynomial); + if (polynomial == 0) { + throw invalid_argument("No polynomial given for PRBS input"); + } + + m_prbs.setup(polynomial); + } rewind(); return 0; } -int DabInputPrbs::readFrame(void* buffer, int size) +int Prbs::readFrame(uint8_t* buffer, size_t size) { - unsigned char* cbuffer = reinterpret_cast<unsigned char*>(buffer); - - for (int i = 0; i < size; ++i) { - cbuffer[i] = m_prbs.step(); + for (size_t i = 0; i < size; ++i) { + buffer[i] = m_prbs.step(); } return size; } -int DabInputPrbs::setBitrate(int bitrate) +int Prbs::setBitrate(int bitrate) { return bitrate; } -int DabInputPrbs::close() +int Prbs::close() { return 0; } -int DabInputPrbs::rewind() +int Prbs::rewind() { m_prbs.rewind(); return 0; } +}; diff --git a/src/dabInputPrbs.h b/src/input/Prbs.h index 9cde7e2..3b2b7d4 100644 --- a/src/dabInputPrbs.h +++ b/src/input/Prbs.h @@ -28,19 +28,17 @@ #pragma once -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - #include <string> -#include "dabInput.h" +#include "input/inputs.h" #include "prbs.h" -class DabInputPrbs : public DabInputBase { +namespace Inputs { + +class Prbs : public InputBase { public: - virtual int open(const std::string name); - virtual int readFrame(void* buffer, int size); + virtual int open(const std::string& name); + virtual int readFrame(uint8_t* buffer, size_t size); virtual int setBitrate(int bitrate); virtual int close(); @@ -50,3 +48,5 @@ class DabInputPrbs : public DabInputBase { PrbsGenerator m_prbs; }; +}; + diff --git a/src/input/Udp.cpp b/src/input/Udp.cpp new file mode 100644 index 0000000..a238d9b --- /dev/null +++ b/src/input/Udp.cpp @@ -0,0 +1,134 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + + Copyright (C) 2016 + Matthias P. Braendli, matthias.braendli@mpb.li + + http://www.opendigitalradio.org + */ +/* + This file is part of ODR-DabMux. + + ODR-DabMux 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 3 of the + License, or (at your option) any later version. + + ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "input/Udp.h" + +#include <stdexcept> +#include <sstream> +#include <string.h> +#include <limits.h> +#include <stdlib.h> +#include <errno.h> +#include "utils.h" + +using namespace std; + +namespace Inputs { + +int Udp::open(const std::string& name) +{ + // Skip the udp:// part if it is present + const string endpoint = (name.substr(0, 6) == "udp://") ? + name.substr(6) : name; + + // The endpoint should be address:port + const auto colon_pos = endpoint.find_first_of(":"); + if (colon_pos == string::npos) { + stringstream ss; + ss << "'" << name << + " is an invalid format for udp address: " + "expected [udp://]address:port"; + throw invalid_argument(ss.str()); + } + + const auto address = endpoint.substr(0, colon_pos); + const auto port_str = endpoint.substr(colon_pos + 1); + + const long port = strtol(port_str.c_str(), nullptr, 10); + + if ((port == LONG_MIN or port == LONG_MAX) and errno == ERANGE) { + throw out_of_range("udp input: port out of range"); + } + else if (port == 0 and errno != 0) { + stringstream ss; + ss << "udp input port parse error: " << strerror(errno); + throw invalid_argument(ss.str()); + } + + if (port == 0) { + throw out_of_range("can't use port number 0 in udp address"); + } + + if (m_sock.reinit(port, address) == -1) { + stringstream ss; + ss << "Could not init UDP socket: " << inetErrMsg; + throw runtime_error(ss.str()); + } + + if (m_sock.setBlocking(false) == -1) { + stringstream ss; + ss << "Could not set non-blocking UDP socket: " << inetErrMsg; + throw runtime_error(ss.str()); + } + + return 0; +} + +int Udp::readFrame(uint8_t* buffer, size_t size) +{ + uint8_t* data = reinterpret_cast<uint8_t*>(buffer); + + // Regardless of buffer contents, try receiving data. + UdpPacket packet; + int ret = m_sock.receive(packet); + + if (ret == -1) { + stringstream ss; + ss << "Could not read from UDP socket: " << inetErrMsg; + throw runtime_error(ss.str()); + } + + std::copy(packet.getData(), packet.getData() + packet.getSize(), + back_inserter(m_buffer)); + + // Take data from the buffer if it contains enough data, + // in any case write the buffer + if (m_buffer.size() >= (size_t)size) { + std::copy(m_buffer.begin(), m_buffer.begin() + size, data); + } + else { + memset(data, 0x0, size); + } + + return size; +} + +int Udp::setBitrate(int bitrate) +{ + if (bitrate <= 0) { + etiLog.log(error, "Invalid bitrate (%i)\n", bitrate); + return -1; + } + + return bitrate; +} + +int Udp::close() +{ + return m_sock.close(); +} + +}; diff --git a/src/dabInputUdp.h b/src/input/Udp.h index ac9ddb0..379dbf3 100644 --- a/src/dabInputUdp.h +++ b/src/input/Udp.h @@ -1,6 +1,11 @@ /* Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) + + Copyright (C) 2016 + Matthias P. Braendli, matthias.braendli@mpb.li + + http://www.opendigitalradio.org */ /* This file is part of ODR-DabMux. @@ -19,41 +24,29 @@ along with ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef DAB_INPUT_UDP_H -#define DAB_INPUT_UDP_H - +#pragma once -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif -#include "dabInput.h" -#include "dabInputFifo.h" +#include <string> +#include <vector> +#include "input/inputs.h" #include "UdpSocket.h" +namespace Inputs { -#ifdef HAVE_FORMAT_RAW -# ifdef HAVE_INPUT_UDP - - -extern struct dabInputOperations dabInputUdpOperations; +class Udp : public InputBase { + public: + virtual int open(const std::string& name); + virtual int readFrame(uint8_t* buffer, size_t size); + virtual int setBitrate(int bitrate); + virtual int close(); + private: + UdpSocket m_sock; -struct dabInputUdpData { - UdpSocket* socket; - UdpPacket* packet; - dabInputFifoStats stats; + // The content of the UDP packets gets written into the + // buffer, and the UDP packet boundaries disappear there. + std::vector<uint8_t> m_buffer; }; +}; -int dabInputUdpInit(void** args); -int dabInputUdpOpen(void* args, const char* inputName); -int dabInputUdpRead(dabInputOperations* ops, void* args, void* buffer, int size); -int dabInputUdpClose(void* args); -int dabInputUdpClean(void** args); - - -# endif -#endif - - -#endif // DAB_INPUT_UDP_H diff --git a/src/dabInputZmq.cpp b/src/input/Zmq.cpp index 790a961..a5601fa 100644 --- a/src/dabInputZmq.cpp +++ b/src/input/Zmq.cpp @@ -2,7 +2,7 @@ Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2013, 2014 Matthias P. Braendli + Copyright (C) 2016 Matthias P. Braendli http://www.opendigitalradio.org ZeroMQ input. see www.zeromq.org for more info @@ -39,17 +39,8 @@ along with ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. */ -#include "dabInput.h" -#include "dabInputZmq.h" -#include "PcDebug.h" - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif +#include "input/Zmq.h" -#ifdef HAVE_INPUT_ZEROMQ - -#include "zmq.hpp" #include <cstdio> #include <cstdlib> #include <list> @@ -58,22 +49,28 @@ #include <string> #include <sstream> #include <limits.h> +#include "PcDebug.h" +#include "Log.h" #ifdef __MINGW32__ # define bzero(s, n) memset(s, 0, n) #endif +namespace Inputs { + using namespace std; int readkey(string& keyfile, char* key) { - int fd = open(keyfile.c_str(), O_RDONLY); - if (fd < 0) - return fd; - int ret = read(fd, key, CURVE_KEYLEN); - close(fd); - if (ret < 0) { - return ret; + FILE* fd = fopen(keyfile.c_str(), "r"); + if (fd == nullptr) { + return -1; + } + + int ret = fread(key, CURVE_KEYLEN, 1, fd); + fclose(fd); + if (ret == 0) { + return -1; } /* It needs to be zero-terminated */ @@ -89,7 +86,7 @@ int readkey(string& keyfile, char* key) * keys to the socket, and finally bind the socket * to the new address */ -void DabInputZmqBase::rebind() +void ZmqBase::rebind() { if (! m_zmq_sock_bound_to.empty()) { try { @@ -223,7 +220,7 @@ void DabInputZmqBase::rebind() } } -int DabInputZmqBase::open(const std::string inputUri) +int ZmqBase::open(const std::string& inputUri) { m_inputUri = inputUri; @@ -236,20 +233,20 @@ int DabInputZmqBase::open(const std::string inputUri) return 0; } -int DabInputZmqBase::close() +int ZmqBase::close() { m_zmq_sock.close(); return 0; } -int DabInputZmqBase::setBitrate(int bitrate) +int ZmqBase::setBitrate(int bitrate) { m_bitrate = bitrate; return bitrate; // TODO do a nice check here } // size corresponds to a frame size. It is constant for a given bitrate -int DabInputZmqBase::readFrame(void* buffer, int size) +int ZmqBase::readFrame(uint8_t* buffer, size_t size) { int rc; @@ -340,7 +337,7 @@ int DabInputZmqBase::readFrame(void* buffer, int size) /******** MPEG input *******/ // Read a MPEG frame from the socket, and push to list -int DabInputZmqMPEG::readFromSocket(size_t framesize) +int ZmqMPEG::readFromSocket(size_t framesize) { bool messageReceived = false; zmq::message_t msg; @@ -410,7 +407,7 @@ int DabInputZmqMPEG::readFromSocket(size_t framesize) // Read a AAC+ superframe from the socket, cut it into five frames, // and push to list -int DabInputZmqAAC::readFromSocket(size_t framesize) +int ZmqAAC::readFromSocket(size_t framesize) { bool messageReceived; zmq::message_t msg; @@ -496,7 +493,7 @@ int DabInputZmqAAC::readFromSocket(size_t framesize) /********* REMOTE CONTROL ***********/ -void DabInputZmqBase::set_parameter(const string& parameter, +void ZmqBase::set_parameter(const string& parameter, const string& value) { if (parameter == "buffer") { @@ -576,7 +573,7 @@ void DabInputZmqBase::set_parameter(const string& parameter, } } -const string DabInputZmqBase::get_parameter(const string& parameter) const +const string ZmqBase::get_parameter(const string& parameter) const { stringstream ss; if (parameter == "buffer") { @@ -615,5 +612,5 @@ const string DabInputZmqBase::get_parameter(const string& parameter) const } -#endif +}; diff --git a/src/dabInputZmq.h b/src/input/Zmq.h index fdd0f1b..8d729e0 100644 --- a/src/dabInputZmq.h +++ b/src/input/Zmq.h @@ -2,7 +2,7 @@ Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2013, 2014 Matthias P. Braendli + Copyright (C) 2016 Matthias P. Braendli http://www.opendigitalradio.org ZeroMQ input. see www.zeromq.org for more info @@ -41,48 +41,37 @@ along with ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef DAB_INPUT_ZMQ_H -#define DAB_INPUT_ZMQ_H - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#ifdef HAVE_INPUT_ZEROMQ +#pragma once #include <list> #include <string> #include <stdint.h> #include "zmq.hpp" -#include "dabInput.h" +#include "input/inputs.h" #include "ManagementServer.h" +namespace Inputs { + /* The frame_buffer contains DAB logical frames as defined in * TS 102 563, section 6. * Five elements of this buffer make one AAC superframe (120ms audio) */ -// Number of elements to prebuffer before starting the pipeline -#define INPUT_ZMQ_DEF_PREBUFFERING (5*4) // 480ms - -// Default frame_buffer size in number of elements -#define INPUT_ZMQ_DEF_BUFFER_SIZE (5*8) // 960ms - // Minimum frame_buffer size in number of elements // This is one AAC superframe, but you probably don't want to // go that low anyway. -#define INPUT_ZMQ_MIN_BUFFER_SIZE (5*1) // 120ms +const size_t INPUT_ZMQ_MIN_BUFFER_SIZE = 5*1; // 120ms // Maximum frame_buffer size in number of elements // One minute is clearly way over what everybody would // want. -#define INPUT_ZMQ_MAX_BUFFER_SIZE (5*500) // 60s +const size_t INPUT_ZMQ_MAX_BUFFER_SIZE = 5*500; // 60s /* The ZeroMQ Curve key is 40 bytes long in Z85 representation * * But we need to store it as zero-terminated string. */ -#define CURVE_KEYLEN 40 +const size_t CURVE_KEYLEN = 40; /* helper to invalidate a key */ #define INVALIDATE_KEY(k) memset(k, 0, CURVE_KEYLEN+1) @@ -156,9 +145,9 @@ struct zmq_frame_header_t #define ZMQ_FRAME_DATA(f) ( ((uint8_t*)f)+sizeof(zmq_frame_header_t) ) -class DabInputZmqBase : public DabInputBase, public RemoteControllable { +class ZmqBase : public InputBase, public RemoteControllable { public: - DabInputZmqBase(const std::string name, + ZmqBase(const std::string name, dab_input_zmq_config_t config) : RemoteControllable(name), m_zmq_context(1), @@ -191,8 +180,8 @@ class DabInputZmqBase : public DabInputBase, public RemoteControllable { INVALIDATE_KEY(m_curve_encoder_key); } - virtual int open(const std::string inputUri); - virtual int readFrame(void* buffer, int size); + virtual int open(const std::string& inputUri); + virtual int readFrame(uint8_t* buffer, size_t size); virtual int setBitrate(int bitrate); virtual int close(); @@ -238,11 +227,11 @@ class DabInputZmqBase : public DabInputBase, public RemoteControllable { size_t m_prebuf_current; }; -class DabInputZmqMPEG : public DabInputZmqBase { +class ZmqMPEG : public ZmqBase { public: - DabInputZmqMPEG(const std::string name, + ZmqMPEG(const std::string name, dab_input_zmq_config_t config) - : DabInputZmqBase(name, config) { + : ZmqBase(name, config) { RC_ADD_PARAMETER(buffer, "Size of the input buffer [mpeg frames]"); @@ -254,11 +243,11 @@ class DabInputZmqMPEG : public DabInputZmqBase { virtual int readFromSocket(size_t framesize); }; -class DabInputZmqAAC : public DabInputZmqBase { +class ZmqAAC : public ZmqBase { public: - DabInputZmqAAC(const std::string name, + ZmqAAC(const std::string name, dab_input_zmq_config_t config) - : DabInputZmqBase(name, config) { + : ZmqBase(name, config) { RC_ADD_PARAMETER(buffer, "Size of the input buffer [aac superframes]"); @@ -270,7 +259,6 @@ class DabInputZmqAAC : public DabInputZmqBase { virtual int readFromSocket(size_t framesize); }; -#endif // HAVE_INPUT_ZMQ +}; -#endif // DAB_INPUT_ZMQ_H diff --git a/src/dabInput.cpp b/src/input/inputs.h index 942e58d..bfb1fb6 100644 --- a/src/dabInput.cpp +++ b/src/input/inputs.h @@ -1,6 +1,11 @@ /* Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) + + Copyright (C) 2016 + Matthias P. Braendli, matthias.braendli@mpb.li + + http://www.opendigitalradio.org */ /* This file is part of ODR-DabMux. @@ -19,31 +24,29 @@ along with ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. */ -#include "dabInput.h" -#include "Log.h" +#pragma once -#include <string.h> +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include "Log.h" +#include "RemoteControl.h" +#include <string> -bool dabInputOperations::operator==(const dabInputOperations& ops) -{ - return memcmp(this, &ops, sizeof(*this)) == 0; -} +namespace Inputs { +/* New input object base */ +class InputBase { + public: + virtual int open(const std::string& name) = 0; + virtual int readFrame(uint8_t* buffer, size_t size) = 0; + virtual int setBitrate(int bitrate) = 0; + virtual int close() = 0; -int dabInputSetbuf(void* args, int size) -{ - return 0; -} + virtual ~InputBase() {} + protected: + InputBase() {} +}; +}; -int dabInputSetbitrate(dabInputOperations* ops, void* args, int bitrate) -{ - if (bitrate <= 0) { - etiLog.log(error, "Invalid bitrate (%i)\n", bitrate); - return -1; - } - if (ops->setbuf(args, bitrate * 3) == 0) { - return bitrate; - } - return -1; -} @@ -219,3 +219,29 @@ int readMpegFrame(int file, void* data, int size) } return framelength; } + +int checkDabMpegFrame(void* data) { + mpegHeader* header = (mpegHeader*)data; + unsigned long* headerData = (unsigned long*)data; + if ((*headerData & 0x0f0ffcff) == 0x0004fcff) return 0; + if ((*headerData & 0x0f0ffcff) == 0x0004f4ff) return 0; + if (getMpegFrequency(header) != 48000) { + if (getMpegFrequency(header) != 24000) { + return MPEG_FREQUENCY; + } + } + if (header->padding != 0) { + return MPEG_PADDING; + } + if (header->emphasis != 0) { + return MPEG_EMPHASIS; + } + if (header->copyright != 0) { + return MPEG_COPYRIGHT; + } + if (header->original != 0) { + return MPEG_ORIGINAL; + } + return -1; +} + @@ -75,6 +75,13 @@ ssize_t readData(int file, void* data, size_t size, unsigned int tries); int readMpegHeader(int file, void* data, int size); int readMpegFrame(int file, void* data, int size); +#define MPEG_FREQUENCY -2 +#define MPEG_PADDING -3 +#define MPEG_COPYRIGHT -4 +#define MPEG_ORIGINAL -5 +#define MPEG_EMPHASIS -6 +int checkDabMpegFrame(void* data); + #ifdef __cplusplus } #endif diff --git a/src/prbs.cpp b/src/prbs.cpp index 0ac3187..b0e3d6d 100644 --- a/src/prbs.cpp +++ b/src/prbs.cpp @@ -28,18 +28,18 @@ /* * Generate a parity check for a 32-bit word. */ -static unsigned long parity_check(unsigned long prbs_accum) +static uint32_t parity_check(uint32_t prbs_accum) { - unsigned long mask=1UL, parity=0UL; - int i; - for (i = 0; i < 32; ++i) { - parity ^= ((prbs_accum & mask) != 0UL); + uint32_t mask = 1; + uint32_t parity = 0; + for (int i = 0; i < 32; ++i) { + parity ^= ((prbs_accum & mask) != 0); mask <<= 1; } return parity; } -void PrbsGenerator::setup(long polynomial) +void PrbsGenerator::setup(uint32_t polynomial) { this->polynomial = polynomial; this->accum = 0; @@ -65,7 +65,7 @@ void PrbsGenerator::gen_prbs_table() { for (int i = 0; i < 4; ++i) { for (int j = 0; j < 256; ++j) { - unsigned long prbs_accum = ((unsigned long)j << (i * 8)); + uint32_t prbs_accum = ((uint32_t)j << (i * 8)); for (int k = 0; k < 8; ++k) { prbs_accum = (prbs_accum << 1) ^ parity_check(prbs_accum & polynomial); @@ -76,24 +76,23 @@ void PrbsGenerator::gen_prbs_table() } } -unsigned long PrbsGenerator::update_prbs() +uint32_t PrbsGenerator::update_prbs() { - unsigned char acc_lsb = 0; - int i; - for (i = 0; i < 4; ++i ) { + uint8_t acc_lsb = 0; + for (int i = 0; i < 4; ++i ) { acc_lsb ^= prbs_table [i] [ (accum >> (i * 8) ) & 0xff ]; } - return (accum << 8) ^ ((unsigned long)acc_lsb); + return (accum << 8) ^ ((uint32_t)acc_lsb); } void PrbsGenerator::gen_weight_table() { for (int i = 0; i < 256; ++i) { - unsigned char mask = 1U; - unsigned char ones_count = 0U; + uint8_t mask = 1; + uint8_t ones_count = 0; for (int j = 0; j < 8; ++j) { - ones_count += ((i & mask) != 0U); + ones_count += ((i & mask) != 0); mask = mask << 1; } weight[i] = ones_count; @@ -101,23 +100,23 @@ void PrbsGenerator::gen_weight_table() } size_t PrbsGenerator::error_count( - unsigned char *rx_data, - int rx_data_length) + uint8_t *rx_data, + size_t rx_data_length) { - unsigned long error_count = 0U; - unsigned long prbs_accum = 0U; + uint32_t error_count = 0; + uint32_t prbs_accum = 0; /* seed the PRBS accumulator */ - for (int i = 0; i < 4; ++i) { + for (int i = 0; i < 4; ++i) { prbs_accum = (prbs_accum << 8) ^ (rx_data[i] ^ polarity_mask); } /* check the received data */ - for (int i = 0; i < rx_data_length; ++i) { - unsigned char error_pattern = (unsigned char) - ((prbs_accum >> 24) - ^ (rx_data[i] ^ polarity_mask)); - if (error_pattern != 0U) { + for (size_t i = 0; i < rx_data_length; ++i) { + uint8_t error_pattern = + (prbs_accum >> 24) ^ (rx_data[i] ^ polarity_mask); + + if (error_pattern != 0) { error_count += weight[error_pattern]; } prbs_accum = update_prbs(); @@ -126,19 +125,19 @@ size_t PrbsGenerator::error_count( } void PrbsGenerator::gen_sequence( - unsigned char *tx_data, - int tx_data_length, - unsigned long polynomial) + uint8_t *tx_data, + size_t tx_data_length, + uint32_t polynomial) { - unsigned long prbs_accum = 0U; + uint32_t prbs_accum = 0; while (prbs_accum < polynomial) { prbs_accum <<= 1; prbs_accum |= 1; } - while (tx_data_length-- > 0) { + for (size_t i = 0; i < tx_data_length; i++) { prbs_accum = update_prbs(); - *(tx_data++) = (unsigned char)(prbs_accum & 0xff); + tx_data[i] = (uint8_t)(prbs_accum & 0xff); } } @@ -30,7 +30,7 @@ class PrbsGenerator { public: - void setup(long polynomial); + void setup(uint32_t polynomial); uint8_t step(void); @@ -42,30 +42,30 @@ class PrbsGenerator { void gen_prbs_table(void); /* Update a 32-bit PRBS generator eight bits at a time. */ - unsigned long update_prbs(void); + uint32_t update_prbs(void); /* Generate the weight table. */ void gen_weight_table(void); /* Count the number of errors in a block of received data. */ size_t error_count( - unsigned char *rx_data, - int rx_data_length); + uint8_t *rx_data, + size_t rx_data_length); void gen_sequence( - unsigned char *tx_data, - int tx_data_length, - unsigned long polynomial); + uint8_t *tx_data, + size_t tx_data_length, + uint32_t polynomial); // table of matrix products used to update a 32-bit PRBS generator - unsigned long prbs_table [4] [256]; + uint32_t prbs_table [4] [256]; // table of weights for 8-bit bytes - unsigned char weight[256]; + uint8_t weight[256]; // PRBS polynomial generator - unsigned long polynomial; + uint32_t polynomial; // PRBS generator polarity mask - unsigned char polarity_mask; + uint8_t polarity_mask; // PRBS accumulator - unsigned long accum; + uint32_t accum; }; diff --git a/src/utils.cpp b/src/utils.cpp index 0399467..4431407 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -103,42 +103,16 @@ void header_message() std::cerr << "Input URLs supported:" << std::endl << " prbs" << -#if defined(HAVE_INPUT_TEST) - " test" << -#endif -#if defined(HAVE_INPUT_UDP) " udp" << -#endif -#if defined(HAVE_INPUT_FIFO) - " fifo" << -#endif -#if defined(HAVE_INPUT_FILE) " file" << -#endif -#if defined(HAVE_INPUT_ZEROMQ) " zmq" << -#endif std::endl; std::cerr << "Inputs format supported:" << std::endl << -#if defined(HAVE_FORMAT_RAW) " raw" << -#endif -#if defined(HAVE_FORMAT_BRIDGE) - " bridge" << -#endif -#if defined(HAVE_FORMAT_MPEG) " mpeg" << -#endif -#if defined(HAVE_FORMAT_PACKET) " packet" << -#endif -#if defined(HAVE_FORMAT_DMB) - " dmb" << -#endif -#if defined(HAVE_FORMAT_EPM) " epm" << -#endif std::endl; std::cerr << "Output URLs supported:" << std::endl << @@ -465,3 +439,29 @@ void printEnsemble(const shared_ptr<dabEnsemble> ensemble) printLinking(ensemble); } +long hexparse(const std::string& input) +{ + long value = 0; + errno = 0; + + // Do not use strtol's base=0 because + // we do not want to accept octal. + if (input.find("0x") == 0) { + value = strtol(input.c_str() + 2, nullptr, 16); + } + else { + value = strtol(input.c_str(), nullptr, 10); + } + + if ((value == LONG_MIN or value == LONG_MAX) and errno == ERANGE) { + throw out_of_range("hexparse: value out of range"); + } + else if (value == 0 and errno != 0) { + stringstream ss; + ss << "hexparse: " << strerror(errno); + throw invalid_argument(ss.str()); + } + + return value; +} + diff --git a/src/utils.h b/src/utils.h index f65bba8..94712cd 100644 --- a/src/utils.h +++ b/src/utils.h @@ -26,9 +26,10 @@ You should have received a copy of the GNU General Public License along with ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef _UTILS_H -#define _UTILS_H +#pragma once +#include <string> +#include <vector> #include <cstdio> #include <memory> #include "MuxElements.h" @@ -78,5 +79,6 @@ void printEnsemble(const std::shared_ptr<dabEnsemble> ensemble); /* Print detailed component information */ void printComponent(DabComponent* component); -#endif + +long hexparse(const std::string& input); diff --git a/src/zmqinput-keygen.c b/src/zmqinput-keygen.c index 8bf61ac..ee0042e 100644 --- a/src/zmqinput-keygen.c +++ b/src/zmqinput-keygen.c @@ -25,6 +25,7 @@ #include <stdint.h> #include <stdlib.h> #include <zmq_utils.h> +#include <zmq.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> |