aboutsummaryrefslogtreecommitdiffstats
path: root/src/DabMux.cpp
diff options
context:
space:
mode:
authorMatthias P. Braendli (think) <matthias@mpb.li>2012-08-23 20:20:30 +0200
committerMatthias P. Braendli (think) <matthias@mpb.li>2012-08-23 20:20:30 +0200
commit3b9073ec178d1ebd8563d94ebbb9b95726e31835 (patch)
tree895ed780d41501089e1464efd20482ab9a0e4c1c /src/DabMux.cpp
parent37f3f44cc1c0f5cf3a9b3f0ffc32f638b281994e (diff)
downloaddabmux-3b9073ec178d1ebd8563d94ebbb9b95726e31835.tar.gz
dabmux-3b9073ec178d1ebd8563d94ebbb9b95726e31835.tar.bz2
dabmux-3b9073ec178d1ebd8563d94ebbb9b95726e31835.zip
crc-dabmux: configuration file support for ensemble definitionr5
Diffstat (limited to 'src/DabMux.cpp')
-rw-r--r--src/DabMux.cpp1896
1 files changed, 48 insertions, 1848 deletions
diff --git a/src/DabMux.cpp b/src/DabMux.cpp
index 3f5f87c..8a065a0 100644
--- a/src/DabMux.cpp
+++ b/src/DabMux.cpp
@@ -1,6 +1,6 @@
/*
Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- 2011 Her Majesty the Queen in Right of Canada (Communications
+ 2011, 2012 Her Majesty the Queen in Right of Canada (Communications
Research Center Canada)
Includes modifications
@@ -21,23 +21,28 @@
You should have received a copy of the GNU General Public License
along with CRC-DabMux. If not, see <http://www.gnu.org/licenses/>.
- */
-
+*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
-#include <stdio.h>
+#include <cstdio>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <iomanip>
-#include <cstdio>
#include <cstring>
+#include <string>
#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <signal.h>
+
+// for basename
+#include <libgen.h>
-using namespace std;
#include <vector>
#include <set>
#include <functional>
@@ -72,11 +77,6 @@ typedef DWORD32 uint32_t;
# include <linux/netdevice.h>
#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <signal.h>
-
#ifdef _WIN32
# pragma warning ( disable : 4103 )
# include "Eti.h"
@@ -84,6 +84,7 @@ typedef DWORD32 uint32_t;
#else
# include "Eti.h"
#endif
+
#include "dabInputFile.h"
#include "dabInputFifo.h"
#include "dabInputMpegFile.h"
@@ -110,579 +111,13 @@ typedef DWORD32 uint32_t;
#include "InetAddress.h"
#include "dabUtils.h"
#include "PcDebug.h"
+#include "DabMux.h"
+#include "MuxElements.h"
+#include "utils.h"
+#include "ParserCmdline.h"
+#include "ParserConfigfile.h"
-
-// DAB Mode
-#define DEFAULT_DAB_MODE 2
-
-// Taille de la trame de donnee, sous-canal 3, nb de paquets de 64bits,
-// STL3 * 8 = x kbytes par trame ETI
-
-// Data bitrate in kbits/s. Must be 64 kb/s multiple.
-#define DEFAULT_DATA_BITRATE 384
-#define DEFAULT_PACKET_BITRATE 32
-
-// Etiquettes des sous-canaux et de l'ensemble, 16 characteres incluant les
-// espaces
-#define DEFAULT_ENSEMBLE_LABEL "CRC-Dr.Radio"
-#define DEFAULT_ENSEMBLE_SHORT_LABEL 0xe000
-#define DEFAULT_ENSEMBLE_ID 0xc000
-#define DEFAULT_ENSEMBLE_ECC 0xa1
-
-//Numeros des sous-canaux
-#define DEFAULT_SERVICE_ID 50
-#define DEFAULT_PACKET_ADDRESS 0
-
-
-struct dabOutput {
- const char* outputProto;
- const char* outputName;
- void* data;
- dabOutputOperations operations;
-};
-
-
-struct dabLabel {
- char text[16];
- uint16_t flag;
-};
-
-
-struct dabService;
-struct dabComponent;
-struct dabSubchannel;
-struct dabEnsemble {
- uint16_t id;
- uint8_t ecc;
- dabLabel label;
- uint8_t mode;
- vector<dabService*> services;
- vector<dabComponent*> components;
- vector<dabSubchannel*> subchannels;
-};
-
-
-struct dabProtectionShort {
- unsigned char tableSwitch;
- unsigned char tableIndex;
-};
-
-
-struct dabProtectionLong {
- unsigned char option;
-};
-
-
-struct dabProtection {
- unsigned char level;
- unsigned char form;
- union {
- dabProtectionShort shortForm;
- dabProtectionLong longForm;
- };
-};
-
-
-struct dabSubchannel {
- const char* inputProto;
- const char* inputName;
- void* data;
- dabInputOperations operations;
- unsigned char id;
- unsigned char type;
- uint16_t startAddress;
- uint16_t bitrate;
- dabProtection protection;
-};
-
-
-class SubchannelId : public std::binary_function <dabSubchannel*, int, bool> {
-public:
- bool operator()(const dabSubchannel* subchannel, const int id) const {
- return subchannel->id == id;
- }
-};
-
-
-vector<dabSubchannel*>::iterator getSubchannel(
- vector<dabSubchannel*>& subchannels, int id)
-{
- return find_if(
- subchannels.begin(),
- subchannels.end(),
- bind2nd(SubchannelId(), id)
- );
-}
-
-
-struct dabAudioComponent {
-};
-
-
-struct dabDataComponent {
-};
-
-
-struct dabFidcComponent {
-};
-
-
-struct dabPacketComponent {
- uint16_t id;
- uint16_t address;
- uint16_t appType;
- bool datagroup;
-};
-
-
-struct dabComponent {
- dabLabel label;
- uint32_t serviceId;
- uint8_t subchId;
- uint8_t type;
- uint8_t SCIdS;
- union {
- dabAudioComponent audio;
- dabDataComponent data;
- dabFidcComponent fidc;
- dabPacketComponent packet;
- };
-
- bool isPacketComponent(vector<dabSubchannel*>& subchannels)
- {
- if (subchId > 63) {
- etiLog.printHeader(TcpLog::ERR,
- "You must define subchannel id in the "
- "packet component before defining packet ");
- return false;
- }
- if (getSubchannel(subchannels, subchId) == subchannels.end()) {
- etiLog.printHeader(TcpLog::ERR,
- "Invalid subchannel id in the packet component "
- "for defining packet ");
- return false;
- }
- if ((*getSubchannel(subchannels, subchId))->type != 3) {
- etiLog.printHeader(TcpLog::ERR,
- "Invalid component type for defining packet ");
- return false;
- }
- return true;
- }
-};
-
-
-vector<dabComponent*>::iterator getComponent(
- vector<dabComponent*>& components,
- uint32_t serviceId,
- vector<dabComponent*>::iterator current)
-{
- if (current == components.end()) {
- current = components.begin();
- } else {
- ++current;
- }
-
- while (current != components.end()) {
- if ((*current)->serviceId == serviceId) {
- return current;
- }
- ++current;
- }
-
- return components.end();
-}
-
-
-vector<dabComponent*>::iterator getComponent(
- vector<dabComponent*>& components,
- uint32_t serviceId) {
- return getComponent(components, serviceId, components.end());
-}
-
-
-struct dabService {
- dabLabel label;
- uint32_t id;
- unsigned char pty;
- unsigned char language;
- bool program;
-
- unsigned char getType(dabEnsemble* ensemble)
- {
- vector<dabSubchannel*>::iterator subchannel;
- vector<dabComponent*>::iterator component =
- getComponent(ensemble->components, id);
- if (component == ensemble->components.end()) {
- return 4;
- }
- subchannel = getSubchannel(ensemble->subchannels, (*component)->subchId);
- if (subchannel == ensemble->subchannels.end()) {
- return 8;
- }
-
- return (*subchannel)->type;
- }
- unsigned char nbComponent(vector<dabComponent*>& components)
- {
- int nb = 0;
- vector<dabComponent*>::iterator current;
-
- for (current = components.begin(); current != components.end();
- ++current) {
- if ((*current)->serviceId == id) {
- ++nb;
- }
- }
- return nb;
- }
-};
-
-
-vector<dabService*>::iterator getService(
- dabComponent* component,
- vector<dabService*>& services)
-{
- vector<dabService*>::iterator service;
-
- for (service = services.begin(); service != services.end(); ++service) {
- if ((*service)->id == component->serviceId) {
- break;
- }
- }
-
- return service;
-}
-
-
-/******************************************************************************
- ***************** Definitions des stuctures des FIGs **********************
- ******************************************************************************/
-struct FIGtype0 {
- uint8_t Length:5;
- uint8_t FIGtypeNumber:3;
- uint8_t Extension:5;
- uint8_t PD:1;
- uint8_t OE:1;
- uint8_t CN:1;
-} PACKED;
-
-
-struct FIGtype0_0 {
- uint8_t Length:5;
- uint8_t FIGtypeNumber:3;
- uint8_t Extension:5;
- uint8_t PD:1;
- uint8_t OE:1;
- uint8_t CN:1;
-
- uint16_t EId;
- uint8_t CIFcnt_hight:5;
- uint8_t Al:1;
- uint8_t Change:2;
- uint8_t CIFcnt_low:8;
-} PACKED;
-
-
-struct FIGtype0_2 {
- uint8_t Length:5;
- uint8_t FIGtypeNumber:3;
- uint8_t Extension:5;
- uint8_t PD:1;
- uint8_t OE:1;
- uint8_t CN:1;
-} PACKED;
-
-
-struct FIGtype0_2_Service {
- uint16_t SId;
- uint8_t NbServiceComp:4;
- uint8_t CAId:3;
- uint8_t Local_flag:1;
-} PACKED;
-
-
-struct FIGtype0_2_Service_data {
- uint32_t SId;
- uint8_t NbServiceComp:4;
- uint8_t CAId:3;
- uint8_t Local_flag:1;
-} PACKED;
-
-
-struct FIGtype0_2_audio_component {
- uint8_t ASCTy:6;
- uint8_t TMid:2;
- uint8_t CA_flag:1;
- uint8_t PS:1;
- uint8_t SubChId:6;
-} PACKED;
-
-
-struct FIGtype0_2_data_component {
- uint8_t DSCTy:6;
- uint8_t TMid:2;
- uint8_t CA_flag:1;
- uint8_t PS:1;
- uint8_t SubChId:6;
-} PACKED;
-
-
-struct FIGtype0_2_packet_component {
- uint8_t SCId_high:6;
- uint8_t TMid:2;
- uint8_t CA_flag:1;
- uint8_t PS:1;
- uint8_t SCId_low:6;
- void setSCId(uint16_t SCId) {
- SCId_high = SCId >> 6;
- SCId_low = SCId & 0x3f;
- }
-} PACKED;
-
-
-struct FIGtype0_3_header {
- uint8_t Length:5;
- uint8_t FIGtypeNumber:3;
- uint8_t Extension:5;
- uint8_t PD:1;
- uint8_t OE:1;
- uint8_t CN:1;
-} PACKED;
-
-
-/* Warning: When bit SCCA_flag is unset(0), the multiplexer R&S does not send
- * the SCCA field. But, in the Factum ETI analyzer, if this field is not there,
- * it is an error.
- */
-struct FIGtype0_3_data {
- uint8_t SCId_high;
- uint8_t SCCA_flag:1;
- uint8_t rfa:3;
- uint8_t SCId_low:4;
- uint8_t DSCTy:6;
- uint8_t rfu:1;
- uint8_t DG_flag:1;
- uint8_t Packet_address_high:2;
- uint8_t SubChId:6;
- uint8_t Packet_address_low;
- uint16_t SCCA;
- void setSCId(uint16_t SCId) {
- SCId_high = SCId >> 4;
- SCId_low = SCId & 0xf;
- }
- void setPacketAddress(uint16_t address) {
- Packet_address_high = address >> 8;
- Packet_address_low = address & 0xff;
- }
-} PACKED;
-
-
-struct FIGtype0_8_short {
- uint8_t SCIdS:4;
- uint8_t rfa_1:3;
- uint8_t ext:1;
- uint8_t Id:6;
- uint8_t MscFic:1;
- uint8_t LS:1;
- uint8_t rfa_2;
-} PACKED;
-
-
-struct FIGtype0_8_long {
- uint8_t SCIdS:4;
- uint8_t rfa_1:3;
- uint8_t ext:1;
- uint8_t SCId_high:4;
- uint8_t rfa:3;
- uint8_t LS:1;
- uint8_t SCId_low;
- uint8_t rfa_2;
- void setSCId(uint16_t id) {
- SCId_high = id >> 8;
- SCId_low = id & 0xff;
- }
- uint16_t getSCid() {
- return (SCId_high << 8) | SCId_low;
- }
-} PACKED;
-
-
-struct FIGtype0_9 {
- uint8_t Length:5;
- uint8_t FIGtypeNumber:3;
- uint8_t Extension:5;
- uint8_t PD:1;
- uint8_t OE:1;
- uint8_t CN:1;
-
- uint8_t ensembleLto:6;
- uint8_t lto:1;
- uint8_t ext:1;
- uint8_t ensembleEcc;
- uint8_t tableId;
-} PACKED;
-
-
-struct FIGtype0_10 {
- uint8_t Length:5;
- uint8_t FIGtypeNumber:3;
- uint8_t Extension:5;
- uint8_t PD:1;
- uint8_t OE:1;
- uint8_t CN:1;
-
- uint8_t MJD_high:7;
- uint8_t RFU:1;
- uint8_t MJD_med;
- uint8_t Hours_high:3;
- uint8_t UTC:1;
- uint8_t ConfInd:1;
- uint8_t LSI:1;
- uint8_t MJD_low:2;
- uint8_t Minutes:6;
- uint8_t Hours_low:2;
- void setMJD(uint32_t date) {
- MJD_high = (date >> 10) & 0x7f;
- MJD_med = (date >> 2) & 0xff;
- MJD_low = date & 0x03;
- }
- void setHours(uint16_t hours) {
- Hours_high = (hours >> 2) & 0x07;
- Hours_low = hours & 0x03;
- }
-} PACKED;
-
-
-struct FIGtype0_17_programme {
- uint16_t SId;
- uint8_t NFC:2;
- uint8_t Rfa:2;
- uint8_t CC:1;
- uint8_t L:1;
- uint8_t PS:1;
- uint8_t SD:1;
-} PACKED;
-
-
-struct FIGtype0_1 {
- uint8_t Length:5;
- uint8_t FIGtypeNumber:3;
- uint8_t Extension:5;
- uint8_t PD:1;
- uint8_t OE:1;
- uint8_t CN:1;
-} PACKED;
-
-
-struct FIG_01_SubChannel_ShortF {
- uint8_t StartAdress_high:2;
- uint8_t SubChId:6;
- uint8_t StartAdress_low:8;
- uint8_t TableIndex:6;
- uint8_t TableSwitch:1;
- uint8_t Short_Long_form:1;
-} PACKED;
-
-
-struct FIG_01_SubChannel_LongF {
- uint8_t StartAdress_high:2;
- uint8_t SubChId:6;
- uint8_t StartAdress_low:8;
- uint8_t Sub_ChannelSize_high:2;
- uint8_t ProtectionLevel:2;
- uint8_t Option:3;
- uint8_t Short_Long_form:1;
- uint8_t Sub_ChannelSize_low:8;
-} PACKED;
-
-
-struct FIG0_13_shortAppInfo {
- uint16_t SId;
- uint8_t No:4;
- uint8_t SCIdS:4;
-} PACKED;
-
-
-struct FIG0_13_longAppInfo {
- uint32_t SId;
- uint8_t No:4;
- uint8_t SCIdS:4;
-} PACKED;
-
-
-struct FIG0_13_app {
- uint8_t typeHigh;
- uint8_t length:5;
- uint8_t typeLow:3;
- void setType(uint16_t type) {
- typeHigh = type >> 3;
- typeLow = type & 0x1f;
- }
-} PACKED;
-
-
-struct FIGtype1_0 {
- uint8_t Length:5;
- uint8_t FIGtypeNumber:3;
- uint8_t Extension:3;
- uint8_t OE:1;
- uint8_t Charset:4;
-
- uint16_t EId;
-} PACKED;
-
-
-struct FIGtype1_1 {
- uint8_t Length:5;
- uint8_t FIGtypeNumber:3;
- uint8_t Extension:3;
- uint8_t OE:1;
- uint8_t Charset:4;
-
- uint16_t Sld;
-} PACKED;
-
-
-struct FIGtype1_5 {
- uint8_t Length:5;
- uint8_t FIGtypeNumber:3;
- uint8_t Extension:3;
- uint8_t OE:1;
- uint8_t Charset:4;
- uint32_t SId;
-} PACKED;
-
-
-struct FIGtype1_4_programme {
- uint8_t Length:5;
- uint8_t FIGtypeNumber:3;
- uint8_t Extension:3;
- uint8_t OE:1;
- uint8_t Charset:4;
- uint8_t SCIdS:4;
- uint8_t rfa:3;
- uint8_t PD:1;
- uint16_t SId;
-} PACKED;
-
-
-struct FIGtype1_4_data {
- uint8_t Length:5;
- uint8_t FIGtypeNumber:3;
- uint8_t Extension:3;
- uint8_t OE:1;
- uint8_t Charset:4;
- uint8_t SCIdS:4;
- uint8_t rfa:3;
- uint8_t PD:1;
- uint32_t SId;
-} PACKED;
-
-
-#ifdef _WIN32
-# pragma pack(pop)
-#endif
+using namespace std;
static unsigned char Padding_FIB[] = {
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -700,17 +135,6 @@ const unsigned short Bit_Rate_SpecifiedTable[16] = {
};
-const unsigned short Sub_Channel_SizeTable[64] = {
- 16, 21, 24, 29, 35, 24, 29, 35,
- 42, 52, 29, 35, 42, 52, 32, 42,
- 48, 58, 70, 40, 52, 58, 70, 84,
- 48, 58, 70, 84, 104, 58, 70, 84,
- 104, 64, 84, 96, 116, 140, 80, 104,
- 116, 140, 168, 96, 116, 140, 168, 208,
- 116, 140, 168, 208, 232, 128, 168, 192,
- 232, 280, 160, 208, 280, 192, 280, 416
-};
-
const unsigned char ProtectionLevelTable[64] = {
4, 3, 2, 1, 0, 4, 3, 2,
@@ -736,250 +160,6 @@ const unsigned short BitRateTable[64] = {
};
-unsigned short getSizeByte(dabSubchannel* subchannel)
-{
- return subchannel->bitrate * 3;
-}
-
-
-unsigned short getSizeWord(dabSubchannel* subchannel)
-{
- return (subchannel->bitrate * 3) >> 2;
-}
-
-
-unsigned short getSizeDWord(dabSubchannel* subchannel)
-{
- return (subchannel->bitrate * 3) >> 3;
-}
-
-
-unsigned short getSizeCu(dabSubchannel* subchannel)
-{
- if (subchannel->protection.form == 0) {
- return Sub_Channel_SizeTable[subchannel->
- protection.shortForm.tableIndex];
- } else {
- dabProtectionLong* protection =
- &subchannel->protection.longForm;
- switch (protection->option) {
- case 0:
- switch (subchannel->protection.level) {
- case 0:
- return (subchannel->bitrate * 12) >> 3;
- break;
- case 1:
- return subchannel->bitrate;
- break;
- case 2:
- return (subchannel->bitrate * 6) >> 3;
- break;
- case 3:
- return (subchannel->bitrate >> 1);
- break;
- default: // Should not happens
- etiLog.print(TcpLog::ERR, "Bad protection level on "
- "subchannel\n");
- return 0;
- }
- break;
- case 1:
- switch (subchannel->protection.level) {
- case 0:
- return (subchannel->bitrate * 27) >> 5;
- break;
- case 1:
- return (subchannel->bitrate * 21) >> 5;
- break;
- case 2:
- return (subchannel->bitrate * 18) >> 5;
- break;
- case 3:
- return (subchannel->bitrate * 15) >> 5;
- break;
- default: // Should not happens
- etiLog.print(TcpLog::ERR,
- "Bad protection level on subchannel\n");
- return 0;
- }
- break;
- default:
- etiLog.print(TcpLog::ERR, "Invalid protection option\n");
- return 0;
- }
- }
- return 0;
-}
-
-
-time_t getDabTime()
-{
- static time_t oldTime = 0;
- static int offset = 0;
- if (oldTime == 0) {
- oldTime = time(NULL);
- } else {
- offset+= 24;
- if (offset >= 1000) {
- offset -= 1000;
- ++oldTime;
- }
- }
- return oldTime;
-}
-
-
-void printUsage(char *name, FILE* out = stderr)
-{
- fprintf(out, "NAME\n");
- fprintf(out, " %s - A software DAB multiplexer\n", name);
- fprintf(out, "\nSYNOPSYS\n");
- fprintf(out, " %s"
- " [ensemble]"
- " [subchannel1 subchannel2 ...]"
- " [service1 component1 [component2 ...] service2 ...]"
- " [output1 ...]"
- " [-h]"
- " [-m mode]"
- " [-n nbFrames]"
- " [-o]"
- " [-s]"
- " [-V]"
- " [-z]"
- "\n",
- name);
- fprintf(out, "\n Where ensemble ="
- " [-i ensembleId]"
- " [-L label]"
- " [-l sLabel]"
- "\n");
- fprintf(out, "\n Where subchannel ="
- " -(A | B | D | E | F | M | P | T) inputName"
- " [-b bitrate]"
- " [-i subchannelId]"
- " [-k]"
- " [-p protection]"
- "\n");
- fprintf(out, "\n Where service ="
- " -S"
- " [-g language]"
- " [-i serviceId]"
- " [-L label]"
- " [-l sLabel]"
- " [-y PTy]"
- "\n");
- fprintf(out, "\n Where component ="
- " -C"
- " [-a address]"
- " [-d]"
- " [-f figType]"
- " [-i subchannelId]"
- " [-L label]"
- " [-l sLabel]"
- " [-t type]"
- "\n");
- fprintf(out, "\nDESCRIPTION\n");
- fprintf(out,
- " %s is a software multiplexer that generates an ETI stream from\n"
- " audio and data streams. Because of its software based architecture,\n"
- " many typical DAB services can be generated and multiplexed on a single\n"
- " PC platform with live or pre-recorded sources.\n"
- "\n"
- " A DAB multiplex configuration is composed of one ensemble. An ensemble\n"
- " is the entity that receivers tune to and process. An ensemble contains\n"
- " several services. A service is the listener-selectable output. Each\n"
- " service contains one mandatory service component which is called pri-\n"
- " mary component. An audio primary component define a program service\n"
- " while a data primary component define a data service. Service can con-\n"
- " tain additional components which are called secondary components. Maxi-\n"
- " mum total number of components is 12 for program services and 11 for\n"
- " data services. A service component is a link to one subchannel (of Fast\n"
- " Information Data Channel). A subchannel is the physical space used\n"
- " within the common interleaved frame.\n"
- "\n"
- " __________________________________________________\n"
- " | CRC-Ensemble | ENSEMBLE\n"
- " |__________________________________________________|\n"
- " | | |\n"
- " | | |\n"
- " _______V______ _______V______ _______V______\n"
- " | CRC-Service1 | | CRC-Service2 | | CRC-Service3 | SERVICES\n"
- " |______________| |______________| |______________|\n"
- " | | | | |______ |\n"
- " | | | | | |\n"
- " __V__ __V__ __V__ __V__ __V__ __V__\n"
- " | SC1 | | SC2 | | SC3 | | SC4 | | SC5 | | SC6 | SERVICE\n"
- " |_____| |_____| |_____| |_____| |_____| |_____| COMPONENTS\n"
- " | | _____| | | ____|\n"
- " | | | | | |\n"
- " __V________V__V______________V________V___V_______ COMMON\n"
- " | SubCh1 | SubCh9 | ... | SubCh3 | SubCh60 | ... | INTERLEAVED\n"
- " |________|________|_______|________|_________|_____| FRAME\n"
- " Figure 1: An example of a DAB multiplex configuration\n",
- name);
-
- fprintf(out, "\nGENERAL OPTIONS\n");
- fprintf(out, " -h : get this help\n");
- fprintf(out, " -m : DAB mode (default: 2)\n");
- fprintf(out, " -n nbFrames : number of frames to produce\n");
- fprintf(out, " -o : turn on TCP log on port 12222\n");
- fprintf(out, " -r : throttle the output rate to one ETI frame every 24ms\n");
- fprintf(out, " -V : print version information and "
- "exit\n");
- fprintf(out, " -z : write SCCA field for Factum ETI"
- " analyzer\n");
- fprintf(out, "\nINPUT OPTIONS\n");
- fprintf(out, " -A : set audio service\n");
- fprintf(out, " -B : set CRC-Bridge data service\n");
- fprintf(out, " -D : set data service\n");
- fprintf(out, " -E : set enhanced packet service\n");
- fprintf(out, " -F : set DAB+ service\n");
- fprintf(out, " -M : set DMB service\n");
- fprintf(out, " -P : set packet service\n");
- fprintf(out, " -T : set test service\n");
- fprintf(out, " inputName<n> : name of file for audio and "
- "packet service and Udp input address for data service "
- "([address]:port)\n");
- fprintf(out, " -a : packet address (default: 0x%x "
- "(%i))\n", DEFAULT_PACKET_ADDRESS, DEFAULT_PACKET_ADDRESS);
- fprintf(out, " -b bitrate<n> : bitrate (in kbits/s) of the "
- "subchannel (default: audio 1st frame, data %i, packet %i)\n",
- DEFAULT_DATA_BITRATE, DEFAULT_PACKET_BITRATE);
- fprintf(out, " -c : set the extendend country code ECC "
- "(default: %u (0x%2x)\n", DEFAULT_ENSEMBLE_ECC, DEFAULT_ENSEMBLE_ECC);
- fprintf(out, " -d : turn on datagroups in packet "
- "mode\n");
- fprintf(out, " -f figType : user application type in FIG "
- "0/13 for packet mode\n");
- fprintf(out, " -g language : Primary service component "
- "language: english=9, french=15\n");
- fprintf(out, " -i id<n> : service|subchannel|"
- "serviceComponent id <n> (default: <n>)\n");
- fprintf(out, " -k : set non-blocking file input "
- "(audio and packet only)\n");
- fprintf(out, " -L label<n> : label of service <n>"
- " (default: CRC-Audio<n>)\n");
- fprintf(out, " -l sLabel<n> : short label flag of service <n>"
- " (default: 0xf040)\n");
- fprintf(out, " -p protection<n> : protection level (default: 3)\n");
- fprintf(out, " -s : enable TIST, synchronized on 1PPS at level 2. This also transmits time using the MNSC.\n");
- fprintf(out, " -t type : audio/data service component type"
- " (default: 0)\n");
- fprintf(out, " audio: foreground=0, "
- "background=1, multi-channel=2\n");
- fprintf(out, " data: unspecified=0, TMC=1, "
- "EWS=2, ITTS=3, paging=4, TDC=5, DMB=24, IP=59, MOT=60, "
- "proprietary=61\n");
- fprintf(out, " -y PTy : Primary service component program"
- " type international code\n");
- fprintf(out, "\nOUTPUT OPTIONS\n");
- fprintf(out, " -O output : name of the output in format "
- "scheme://[address][:port][/name]\n"
- " where scheme is (raw|udp|tcp|file|fifo|simul)\n"
- );
-}
-
-
bool running = true;
void signalHandler(int signum)
@@ -1021,259 +201,10 @@ void signalHandler(int signum)
}
-void printEnsemble(dabEnsemble* ensemble)
-{
- char label[17];
- memcpy(label, ensemble->label.text, 16);
- label[16] = 0;
-
- etiLog.printHeader(TcpLog::INFO, "Ensemble\n");
- etiLog.printHeader(TcpLog::INFO, " id: 0x%lx (%lu)\n",
- ensemble->id, ensemble->id);
- etiLog.printHeader(TcpLog::INFO, " ecc: 0x%x (%u)\n",
- ensemble->ecc, ensemble->ecc);
- etiLog.printHeader(TcpLog::INFO, " label: %s\n", label);
- etiLog.printHeader(TcpLog::INFO, " short label: ");
- for (int i = 0; i < 32; ++i) {
- if (ensemble->label.flag & 0x8000 >> i) {
- etiLog.printHeader(TcpLog::INFO, "%c", ensemble->label.text[i]);
- }
- }
- etiLog.printHeader(TcpLog::INFO, " (0x%x)\n", ensemble->label.flag);
- etiLog.printHeader(TcpLog::INFO, " mode: %u\n", ensemble->mode);
-}
-
-
-void printSubchannels(vector<dabSubchannel*>& subchannels)
-{
- vector<dabSubchannel*>::iterator subchannel;
- int index = 0;
-
- for (subchannel = subchannels.begin(); subchannel != subchannels.end();
- ++subchannel) {
- dabProtection* protection = &(*subchannel)->protection;
- etiLog.printHeader(TcpLog::INFO, "Subchannel %i\n", index);
- etiLog.printHeader(TcpLog::INFO, " input\n");
- etiLog.printHeader(TcpLog::INFO, " protocol: %s\n",
- (*subchannel)->inputProto);
- etiLog.printHeader(TcpLog::INFO, " name: %s\n",
- (*subchannel)->inputName);
- etiLog.printHeader(TcpLog::INFO, " type: ");
- switch ((*subchannel)->type) {
- case 0:
- etiLog.printHeader(TcpLog::INFO, "audio\n");
- break;
- case 1:
- etiLog.printHeader(TcpLog::INFO, "data\n");
- break;
- case 2:
- etiLog.printHeader(TcpLog::INFO, "fidc\n");
- break;
- case 3:
- etiLog.printHeader(TcpLog::INFO, "packet\n");
- break;
- default:
- etiLog.printHeader(TcpLog::INFO, "Unknown data type "
- "(service->type)\n");
- break;
- }
- etiLog.printHeader(TcpLog::INFO, " id: %i\n",
- (*subchannel)->id);
- etiLog.printHeader(TcpLog::INFO, " bitrate: %i\n",
- (*subchannel)->bitrate);
- etiLog.printHeader(TcpLog::INFO, " protection: ");
- if (protection->form == 0) {
- etiLog.printHeader(TcpLog::INFO, "UEP %i\n", protection->level + 1);
- } else {
- etiLog.printHeader(TcpLog::INFO, "EEP %i-%c\n",
- protection->level + 1,
- protection->longForm.option == 0 ? 'A' : 'B');
- }
- if (protection->form == 0) {
- etiLog.printHeader(TcpLog::INFO,
- " form: short\n switch: %i\n index: %i\n",
- protection->shortForm.tableSwitch,
- protection->shortForm.tableIndex);
- } else {
- etiLog.printHeader(TcpLog::INFO,
- " form: long\n option: %i\n level: %i\n",
- protection->longForm.option,
- (*subchannel)->protection.level);
- }
- etiLog.printHeader(TcpLog::INFO, " SAD: %i\n",
- (*subchannel)->startAddress);
- etiLog.printHeader(TcpLog::INFO, " size (CU): %i\n",
- getSizeCu(*subchannel));
- ++index;
- }
-}
-
-
-void printComponent(dabComponent* component)
-{
- char label[17];
- memcpy(label, component->label.text, 16);
- label[16] = 0;
- if (label[0] == 0) {
- sprintf(label, "<none>");
- }
-
- etiLog.printHeader(TcpLog::INFO, " service id: %i\n",
- component->serviceId);
- etiLog.printHeader(TcpLog::INFO, " subchannel id: %i\n",
- component->subchId);
- etiLog.printHeader(TcpLog::INFO, " label: %s\n",
- label);
- etiLog.printHeader(TcpLog::INFO, " short label: ");
- for (int i = 0; i < 32; ++i) {
- if (component->label.flag & 0x8000 >> i) {
- etiLog.printHeader(TcpLog::INFO, "%c", component->label.text[i]);
- }
- }
- etiLog.printHeader(TcpLog::INFO, " (0x%x)\n", component->label.flag);
- etiLog.printHeader(TcpLog::INFO, " service component type: 0x%x (%u)\n",
- component->type, component->type);
- etiLog.printHeader(TcpLog::INFO, " (packet) id: %u\n",
- component->packet.id);
- etiLog.printHeader(TcpLog::INFO, " (packet) address: %u\n",
- component->packet.address);
- etiLog.printHeader(TcpLog::INFO, " (packet) app type: %u\n",
- component->packet.appType);
- etiLog.printHeader(TcpLog::INFO, " (packet) datagroup: %u\n",
- component->packet.datagroup);
-}
-
-
-void printComponents(vector<dabComponent*>& components)
-{
- vector<dabComponent*>::const_iterator current;
- unsigned int index = 0;
-
- for (current = components.begin(); current != components.end(); ++current) {
- etiLog.printHeader(TcpLog::INFO, "Component %i\n", index);
- printComponent(*current);
- ++index;
- }
-}
-
-
-void printServices(vector<dabService*>& services)
-{
- vector<dabService*>::const_iterator current;
- int index = 0;
-
- for (current = services.begin(); current != services.end(); ++current) {
- char label[17];
- memcpy(label, (*current)->label.text, 16);
- label[16] = 0;
-
- etiLog.printHeader(TcpLog::INFO, "Service %i\n", index);
- etiLog.printHeader(TcpLog::INFO, " label: %s\n", label);
- etiLog.printHeader(TcpLog::INFO, " short label: ");
- for (int i = 0; i < 32; ++i) {
- if ((*current)->label.flag & 0x8000 >> i) {
- etiLog.printHeader(TcpLog::INFO, "%c", (*current)->label.text[i]);
- }
- }
- etiLog.printHeader(TcpLog::INFO, " (0x%x)\n", (*current)->label.flag);
- etiLog.printHeader(TcpLog::INFO, " id: 0x%lx (%lu)\n",
- (*current)->id, (*current)->id);
- etiLog.printHeader(TcpLog::INFO, " pty: 0x%x (%u)\n",
- (*current)->pty, (*current)->pty);
- etiLog.printHeader(TcpLog::INFO, " language: 0x%x (%u)\n",
- (*current)->language, (*current)->language);
- ++index;
- }
-}
-
-
-void printOutputs(vector<dabOutput*>& outputs)
-{
- vector<dabOutput*>::const_iterator output;
- int index = 0;
-
- for (output = outputs.begin(); output != outputs.end(); ++output) {
- etiLog.printHeader(TcpLog::INFO, "Output %i\n", index);
- etiLog.printHeader(TcpLog::INFO, " protocol: %s\n",
- (*output)->outputProto);
- etiLog.printHeader(TcpLog::INFO, " name: %s\n",
- (*output)->outputName);
- ++index;
- }
-}
-
-
int main(int argc, char *argv[])
{
- etiLog.printHeader(TcpLog::INFO,
- "Welcome to %s %s, compiled at %s, %s\n\n",
- PACKAGE_NAME, PACKAGE_VERSION, __DATE__, __TIME__);
- etiLog.printHeader(TcpLog::INFO,
- "Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011\n"
- "Her Majesty the Queen in Right of Canada,\n"
- "(Communications Research Centre Canada) All rights reserved.\n\n");
- etiLog.printHeader(TcpLog::INFO, "Input URLs supported:");
-#if defined(HAVE_INPUT_PRBS)
- etiLog.printHeader(TcpLog::INFO, " prbs");
-#endif
-#if defined(HAVE_INPUT_TEST)
- etiLog.printHeader(TcpLog::INFO, " test");
-#endif
-#if defined(HAVE_INPUT_SLIP)
- etiLog.printHeader(TcpLog::INFO, " slip");
-#endif
-#if defined(HAVE_INPUT_UDP)
- etiLog.printHeader(TcpLog::INFO, " udp");
-#endif
-#if defined(HAVE_INPUT_FIFO)
- etiLog.printHeader(TcpLog::INFO, " fifo");
-#endif
-#if defined(HAVE_INPUT_FILE)
- etiLog.printHeader(TcpLog::INFO, " file");
-#endif
- etiLog.printHeader(TcpLog::INFO, "\n");
- etiLog.printHeader(TcpLog::INFO, "Inputs format supported:");
-#if defined(HAVE_FORMAT_RAW)
- etiLog.printHeader(TcpLog::INFO, " raw");
-#endif
-#if defined(HAVE_FORMAT_BRIDGE)
- etiLog.printHeader(TcpLog::INFO, " bridge");
-#endif
-#if defined(HAVE_FORMAT_MPEG)
- etiLog.printHeader(TcpLog::INFO, " mpeg");
-#endif
-#if defined(HAVE_FORMAT_PACKET)
- etiLog.printHeader(TcpLog::INFO, " packet");
-#endif
-#if defined(HAVE_FORMAT_DMB)
- etiLog.printHeader(TcpLog::INFO, " dmb");
-#endif
-#if defined(HAVE_FORMAT_EPM)
- etiLog.printHeader(TcpLog::INFO, " epm");
-#endif
- etiLog.printHeader(TcpLog::INFO, "\n");
-
- etiLog.printHeader(TcpLog::INFO, "Output URLs supported:");
-#if defined(HAVE_OUTPUT_FILE)
- etiLog.printHeader(TcpLog::INFO, " file");
-#endif
-#if defined(HAVE_OUTPUT_FIFO)
- etiLog.printHeader(TcpLog::INFO, " fifo");
-#endif
-#if defined(HAVE_OUTPUT_UDP)
- etiLog.printHeader(TcpLog::INFO, " udp");
-#endif
-#if defined(HAVE_OUTPUT_TCP)
- etiLog.printHeader(TcpLog::INFO, " tcp");
-#endif
-#if defined(HAVE_OUTPUT_RAW)
- etiLog.printHeader(TcpLog::INFO, " raw");
-#endif
-#if defined(HAVE_OUTPUT_SIMUL)
- etiLog.printHeader(TcpLog::INFO, " simul");
-#endif
- etiLog.printHeader(TcpLog::INFO, "\n\n");
+ header_message();
/* for (int signum = 1; signum < 16; ++signum) {
signal(signum, signalHandler);
@@ -1389,778 +320,46 @@ int main(int argc, char *argv[])
bool MNSC_increment_time = false;
- char* progName = strrchr(argv[0], '/');
- if (progName == NULL) {
- progName = argv[0];
- } else {
- ++progName;
- }
-
-
- while (1) {
- int c = getopt(argc, argv,
- "A:B:CD:E:F:L:M:O:P:STVa:b:c:de:f:g:hi:kl:m:n:op:rst:y:z");
- if (c == -1) {
- break;
- }
- switch (c) {
- case 'O':
- outputs.push_back(new dabOutput);
- output = outputs.end() - 1;
-
- memset(*output, 0, sizeof(dabOutput));
- (*output)->outputProto = NULL;
- (*output)->outputName = NULL;
- (*output)->data = NULL;
- (*output)->operations = dabOutputDefaultOperations;
-
- char* proto;
-
- proto = strstr(optarg, "://");
- if (proto == NULL) {
- etiLog.printHeader(TcpLog::ERR,
- "No protocol defined for output\n");
- returnCode = -1;
- goto EXIT;
- } else {
- (*output)->outputProto = optarg;
- (*output)->outputName = proto + 3;
- *proto = 0;
- }
- subchannel = ensemble->subchannels.end();
- protection = NULL;
- component = ensemble->components.end();
- service = ensemble->services.end();
- break;
- case 'S':
- ensemble->services.push_back(new dabService);
-
- subchannel = ensemble->subchannels.end();
- protection = NULL;
- component = ensemble->components.end();
- service = ensemble->services.end() - 1;
- output = outputs.end();
-
- memset((*service)->label.text, 0, 16);
- sprintf((*service)->label.text, "CRC-Service%i",
- (int)ensemble->services.size());
- (*service)->label.flag = 0xe01f;
- (*service)->id = DEFAULT_SERVICE_ID + ensemble->services.size();
- (*service)->pty = 0;
- (*service)->language = 0;
- currentFrame = 0; // Will be used temporaly for SCIdS
-
- break;
- case 'C':
- if (service == ensemble->services.end()) {
- etiLog.printHeader(TcpLog::ERR, "You must define a service"
- " before using option -%c\n", c);
- printUsage(progName);
- returnCode = -1;
- goto EXIT;
- }
-
- ensemble->components.push_back(new dabComponent);
-
- component = ensemble->components.end() - 1;
- subchannel = ensemble->subchannels.end();
- protection = NULL;
- output = outputs.end();
+ /* TODO Okay, this is clearly not the nicest way to handle the two
+ * ways of defining the ensemble, but it works.
+ */
+ if (strncmp(basename(argv[0]), "CRC-DabMux-cfg", 16) == 0) {
+ try {
- memset(*component, 0, sizeof(dabComponent));
- memset((*component)->label.text, 0, 16);
- (*component)->label.flag = 0xffff;
- (*component)->serviceId = (*service)->id;
- (*component)->subchId = (*(ensemble->subchannels.end() - 1))->id;
- (*component)->SCIdS = currentFrame++;
- break;
- case 'A':
- case 'B':
- case 'D':
- case 'E':
- case 'F':
- case 'M':
- case 'P':
- case 'T':
- if (optarg == NULL && c != 'T') {
- etiLog.printHeader(TcpLog::ERR,
- "Missing parameter for option -%c\n", c);
- printUsage(progName);
- returnCode = -1;
+ if (argc != 2) {
+ printUsageConfigfile(argv[0]);
goto EXIT;
}
- ensemble->subchannels.push_back(new dabSubchannel);
-
- subchannel = ensemble->subchannels.end() - 1;
- protection = &(*subchannel)->protection;
- component = ensemble->components.end();
- service = ensemble->services.end();
- output = outputs.end();
-
- if (c != 'T') {
- (*subchannel)->inputName = optarg;
- } else {
- (*subchannel)->inputName = NULL;
- }
- if (0) {
-#if defined(HAVE_INPUT_FILE) && defined(HAVE_FORMAT_MPEG)
- } else if (c == 'A') {
- (*subchannel)->inputProto = "file";
- (*subchannel)->type = 0;
- (*subchannel)->bitrate = 0;
- (*subchannel)->operations = dabInputMpegFileOperations;
-#endif // defined(HAVE_INPUT_FILE) && defined(HAVE_FORMAT_MPEG)
-#if defined(HAVE_FORMAT_DABPLUS)
- } else if (c == 'F') {
- (*subchannel)->type = 0;
- (*subchannel)->bitrate = 32;
-
- char* proto;
-
- proto = strstr(optarg, "://");
- if (proto == NULL) {
- (*subchannel)->inputProto = "file";
- } else {
- (*subchannel)->inputProto = optarg;
- (*subchannel)->inputName = proto + 3;
- *proto = 0;
- }
-
- if (0) {
-#if defined(HAVE_INPUT_FILE)
- } else if (strcmp((*subchannel)->inputProto, "file") == 0) {
- (*subchannel)->operations = dabInputDabplusFileOperations;
-#endif // defined(HAVE_INPUT_FILE)
- } else {
- etiLog.printHeader(TcpLog::ERR,
- "Invalid protocol for DAB+ input (%s)\n",
- (*subchannel)->inputProto);
- printUsage(progName);
- returnCode = -1;
- goto EXIT;
- }
-#endif // defined(HAVE_FORMAT_DABPLUS)
- } else if (c == 'B') {
- char* proto;
-
- proto = strstr(optarg, "://");
- if (proto == NULL) {
- (*subchannel)->inputProto = "udp";
- } else {
- (*subchannel)->inputProto = optarg;
- (*subchannel)->inputName = proto + 3;
- *proto = 0;
- }
- if (0) {
-#if defined(HAVE_FORMAT_BRIDGE)
-#if defined(HAVE_INPUT_UDP)
- } else if (strcmp((*subchannel)->inputProto, "udp") == 0) {
- (*subchannel)->operations = dabInputBridgeUdpOperations;
-#endif // defined(HAVE_INPUT_UDP)
-#if defined(HAVE_INPUT_SLIP)
- } else if (strcmp((*subchannel)->inputProto, "slip") == 0) {
- (*subchannel)->operations = dabInputSlipOperations;
-#endif // defined(HAVE_INPUT_SLIP)
-#endif // defined(HAVE_FORMAT_BRIDGE)
- }
- } else if (c == 'D') {
- char* proto;
-
- proto = strstr(optarg, "://");
- if (proto == NULL) {
- (*subchannel)->inputProto = "udp";
- } else {
- (*subchannel)->inputProto = optarg;
- (*subchannel)->inputName = proto + 3;
- *proto = 0;
- }
- if (0) {
-#if defined(HAVE_INPUT_UDP)
- } else if (strcmp((*subchannel)->inputProto, "udp") == 0) {
- (*subchannel)->operations = dabInputUdpOperations;
-#endif
-#if defined(HAVE_INPUT_PRBS) && defined(HAVE_FORMAT_RAW)
- } else if (strcmp((*subchannel)->inputProto, "prbs") == 0) {
- (*subchannel)->operations = dabInputPrbsOperations;
-#endif
-#if defined(HAVE_INPUT_FILE) && defined(HAVE_FORMAT_RAW)
- } else if (strcmp((*subchannel)->inputProto, "file") == 0) {
- (*subchannel)->operations = dabInputRawFileOperations;
-#endif
- } else if (strcmp((*subchannel)->inputProto, "fifo") == 0) {
- (*subchannel)->operations = dabInputRawFifoOperations;
- } else {
- etiLog.printHeader(TcpLog::ERR,
- "Invalid protocol for data input (%s)\n",
- (*subchannel)->inputProto);
- printUsage(progName);
- returnCode = -1;
- goto EXIT;
- }
+ string conf_file = argv[1];
- (*subchannel)->type = 1;
- (*subchannel)->bitrate = DEFAULT_DATA_BITRATE;
-#if defined(HAVE_INPUT_TEST) && defined(HAVE_FORMAT_RAW)
- } else if (c == 'T') {
- (*subchannel)->inputProto = "test";
- (*subchannel)->type = 1;
- (*subchannel)->bitrate = DEFAULT_DATA_BITRATE;
- (*subchannel)->operations = dabInputTestOperations;
-#endif // defined(HAVE_INPUT_TEST)) && defined(HAVE_FORMAT_RAW)
-#ifdef HAVE_FORMAT_PACKET
- } else if (c == 'P') {
- (*subchannel)->inputProto = "file";
- (*subchannel)->type = 3;
- (*subchannel)->bitrate = DEFAULT_PACKET_BITRATE;
-#ifdef HAVE_INPUT_FILE
- (*subchannel)->operations = dabInputPacketFileOperations;
-#elif defined(HAVE_INPUT_FIFO)
- (*subchannel)->operations = dabInputFifoOperations;
-#else
-# pragma error("Must defined at least one packet input")
-#endif // defined(HAVE_INPUT_FILE)
-#ifdef HAVE_FORMAT_EPM
- } else if (c == 'E') {
- (*subchannel)->inputProto = "file";
- (*subchannel)->type = 3;
- (*subchannel)->bitrate = DEFAULT_PACKET_BITRATE;
- (*subchannel)->operations = dabInputEnhancedPacketFileOperations;
-#endif // defined(HAVE_FORMAT_EPM)
-#endif // defined(HAVE_FORMAT_PACKET)
-#ifdef HAVE_FORMAT_DMB
- } else if (c == 'M') {
- char* proto;
-
- proto = strstr(optarg, "://");
- if (proto == NULL) {
- (*subchannel)->inputProto = "udp";
- } else {
- (*subchannel)->inputProto = optarg;
- (*subchannel)->inputName = proto + 3;
- *proto = 0;
- }
- if (strcmp((*subchannel)->inputProto, "udp") == 0) {
- (*subchannel)->operations = dabInputDmbUdpOperations;
- } else if (strcmp((*subchannel)->inputProto, "file") == 0) {
- (*subchannel)->operations = dabInputDmbFileOperations;
- } else {
- etiLog.printHeader(TcpLog::ERR,
- "Invalid protocol for DMB input (%s)\n",
- (*subchannel)->inputProto);
- printUsage(progName);
- returnCode = -1;
- goto EXIT;
- }
+ parse_configfile(conf_file, outputs, ensemble, &enableTist, &FICL,
+ &factumAnalyzer, &limit);
- (*subchannel)->type = 1;
- (*subchannel)->bitrate = DEFAULT_DATA_BITRATE;
-#endif
- } else {
- etiLog.printHeader(TcpLog::ERR,
- "Service '%c' not yet coded!\n", c);
- returnCode = -1;
- goto EXIT;
- }
- (*subchannel)->operations.init(&(*subchannel)->data);
- for (int i = 0; i < 64; ++i) { // Find first free subchannel
- subchannel = getSubchannel(ensemble->subchannels, i);
- if (subchannel == ensemble->subchannels.end()) {
- subchannel = ensemble->subchannels.end() - 1;
- (*subchannel)->id = i;
- break;
- }
- }
- (*subchannel)->startAddress = 0;
+ printSubchannels(ensemble->subchannels);
+ cerr << endl;
+ printServices(ensemble->services);
+ cerr << endl;
+ printComponents(ensemble->components);
+ cerr << endl;
+ printOutputs(outputs);
- if (c == 'A') {
- protection->form = 0;
- protection->level = 2;
- protection->shortForm.tableSwitch = 0;
- protection->shortForm.tableIndex = 0;
- } else {
- protection->level = 2;
- protection->form = 1;
- protection->longForm.option = 0;
- }
- break;
- case 'L':
- if (optarg == NULL) {
- etiLog.printHeader(TcpLog::ERR,
- "Missing parameter for option -L\n");
- printUsage(progName);
- returnCode = -1;
- goto EXIT;
- }
- if (service == ensemble->services.end()) {
- memset(ensemble->label.text, 0, 16);
- strncpy(ensemble->label.text, optarg, 16);
- ensemble->label.flag = 0xff00;
- } else if (component != ensemble->components.end()) {
- memset((*component)->label.text, 0, 16);
- strncpy((*component)->label.text, optarg, 16);
- (*component)->label.flag = 0xff00;
- } else { // Service
- memset((*service)->label.text, 0, 16);
- strncpy((*service)->label.text, optarg, 16);
- (*service)->label.flag = 0xff00;
- }
- // TODO Check strlen before doing short label
- // TODO Check if short label already set
- break;
- case 'V':
- goto EXIT;
- case 'l':
- if (optarg == NULL) {
- etiLog.printHeader(TcpLog::ERR,
- "Missing parameter for option -l\n");
- printUsage(progName);
- returnCode = -1;
- goto EXIT;
- }
- if (service == ensemble->services.end()) {
- char* end;
- ensemble->label.flag = strtoul(optarg, &end, 0);
- if (*end != 0) {
- end = optarg;
- ensemble->label.flag = 0;
- for (int i = 0; i < 32; ++i) {
- if (*end == ensemble->label.text[i]) {
- ensemble->label.flag |= 0x8000 >> i;
- if (*(++end) == 0) {
- break;
- }
- }
- }
- if (*end != 0) {
- etiLog.printHeader(TcpLog::ERR,
- "Error at '%c' in ensemble short label '%s'!\n"
- "Not in label '%s'!\n",
- *end, optarg, ensemble->label.text);
- returnCode = -1;
- goto EXIT;
- }
- }
- int count = 0;
- for (int i = 0; i < 16; ++i) {
- if (ensemble->label.flag & (1 << i)) {
- ++count;
- }
- }
- if (count > 8) {
- etiLog.printHeader(TcpLog::ERR,
- "Ensemble short label too long!\n"
- "Must be < 8 characters.\n");
- returnCode = -1;
- goto EXIT;
- }
- } else if (component != ensemble->components.end()) {
- char* end;
- (*component)->label.flag = strtoul(optarg, &end, 0);
- if (*end != 0) {
- end = optarg;
- (*component)->label.flag = 0;
- for (int i = 0; i < 32; ++i) {
- if (*end == (*component)->label.text[i]) {
- (*component)->label.flag |= 0x8000 >> i;
- if (*(++end) == 0) {
- break;
- }
- }
- }
- if (*end != 0) {
- etiLog.printHeader(TcpLog::ERR,
- "Error at '%c' in component short label '%s'!\n"
- "Not in label '%s'!\n",
- *end, optarg, (*component)->label.text);
- returnCode = -1;
- goto EXIT;
- }
- }
- int count = 0;
- for (int i = 0; i < 16; ++i) {
- if ((*component)->label.flag & (1 << i)) {
- ++count;
- }
- }
- if (count > 8) {
- etiLog.printHeader(TcpLog::ERR,
- "Service '%s' short label too long!\n"
- "Must be < 8 characters.\n", (*component)->label.text);
- returnCode = -1;
- goto EXIT;
- }
- } else {
- char* end;
- (*service)->label.flag = strtoul(optarg, &end, 0);
- if (*end != 0) {
- end = optarg;
- (*service)->label.flag = 0;
- for (int i = 0; i < 32; ++i) {
- if (*end == (*service)->label.text[i]) {
- (*service)->label.flag |= 0x8000 >> i;
- if (*(++end) == 0) {
- break;
- }
- }
- }
- if (*end != 0) {
- etiLog.printHeader(TcpLog::ERR,
- "Error at '%c' in service short label '%s'!\n"
- "Not in label '%s'!\n",
- *end, optarg, (*service)->label.text);
- returnCode = -1;
- goto EXIT;
- }
- }
- int count = 0;
- for (int i = 0; i < 16; ++i) {
- if ((*service)->label.flag & (1 << i)) {
- ++count;
- }
- }
- if (count > 8) {
- etiLog.printHeader(TcpLog::ERR,
- "Service '%s' short label too long!\n"
- "Must be < 8 characters.\n", (*service)->label.text);
- returnCode = -1;
- goto EXIT;
- }
- }
- break;
- case 'i':
- if (optarg == NULL) {
- etiLog.printHeader(TcpLog::ERR,
- "Missing parameter for option -i\n");
- printUsage(progName);
- returnCode = -1;
- goto EXIT;
- }
- if (component != ensemble->components.end()) {
- (*component)->subchId = strtoul(optarg, NULL, 0);
- } else if (subchannel != ensemble->subchannels.end()) {
- (*subchannel)->id = strtoul(optarg, NULL, 0);
- } else if (service != ensemble->services.end()) {
- (*service)->id = strtoul(optarg, NULL, 0);
- if ((*service)->id == 0) {
- etiLog.printHeader(TcpLog::ERR,
- "Service id 0 is invalid\n");
- returnCode = -1;
- goto EXIT;
- }
- } else {
- ensemble->id = strtoul(optarg, NULL, 0);
- }
- break;
- case 'b':
- if (optarg == NULL) {
- etiLog.printHeader(TcpLog::ERR,
- "Missing parameter for option -b\n");
- printUsage(progName);
- returnCode = -1;
- goto EXIT;
- }
- if (subchannel == ensemble->subchannels.end()) {
- etiLog.printHeader(TcpLog::ERR,
- "You must define a subchannel first!\n");
- printUsage(progName);
- returnCode = -1;
- goto EXIT;
- }
- (*subchannel)->bitrate = strtoul(optarg, NULL, 0);
- if (((*subchannel)->bitrate & 0x7) != 0) {
- (*subchannel)->bitrate += 8;
- (*subchannel)->bitrate &= ~0x7;
- etiLog.printHeader(TcpLog::WARNING,
- "bitrate must be multiple of 8 -> ceiling to %i\n",
- (*subchannel)->bitrate);
- }
- break;
- case 'c':
- if (optarg == NULL) {
- etiLog.printHeader(TcpLog::ERR,
- "Missing parameter for option -c\n");
- printUsage(progName);
- returnCode = -1;
- goto EXIT;
- }
- ensemble->ecc = strtoul(optarg, NULL, 0);
- break;
-#if defined(HAVE_INPUT_FIFO) && defined(HAVE_INPUT_FILE)
- case 'k':
- if (subchannel == ensemble->subchannels.end()) {
- etiLog.printHeader(TcpLog::ERR,
- "You must define a subchannel first!\n");
- printUsage(progName);
- returnCode = -1;
- goto EXIT;
- }
- switch ((*subchannel)->type) {
-#ifdef HAVE_FORMAT_PACKET
- case 3:
- (*subchannel)->operations.clean(&(*subchannel)->data);
- if ((*subchannel)->operations == dabInputPacketFileOperations) {
- (*subchannel)->operations = dabInputFifoOperations;
-#ifdef HAVE_FORMAT_EPM
- } else if ((*subchannel)->operations == dabInputEnhancedPacketFileOperations) {
- (*subchannel)->operations = dabInputEnhancedFifoOperations;
-#endif // defined(HAVE_FORMAT_EPM)
- } else {
- etiLog.printHeader(TcpLog::ERR,
- "Error, wrong packet subchannel operations!\n");
- returnCode = -1;
- goto EXIT;
- }
- (*subchannel)->operations.init(&(*subchannel)->data);
- (*subchannel)->inputProto = "fifo";
- break;
-#endif // defined(HAVE_FORMAT_PACKET)
-#ifdef HAVE_FORMAT_MPEG
- case 0:
- (*subchannel)->operations.clean(&(*subchannel)->data);
- if ((*subchannel)->operations == dabInputMpegFileOperations) {
- (*subchannel)->operations = dabInputMpegFifoOperations;
- } else if ((*subchannel)->operations ==
- dabInputDabplusFileOperations) {
- (*subchannel)->operations = dabInputDabplusFifoOperations;
- } else {
- etiLog.printHeader(TcpLog::ERR,
- "Error, wrong audio subchannel operations!\n");
- returnCode = -1;
- goto EXIT;
- }
- (*subchannel)->operations.init(&(*subchannel)->data);
- (*subchannel)->inputProto = "fifo";
- break;
-#endif // defined(HAVE_FORMAT_MPEG)
- default:
- etiLog.printHeader(TcpLog::ERR,
- "sorry, non-blocking input file is "
- "only valid with audio or packet services\n");
- returnCode = -1;
- goto EXIT;
- }
- break;
-#endif // defined(HAVE_INPUT_FIFO) && defined(HAVE_INPUT_FILE)
- case 'p':
- int level;
- if (optarg == NULL) {
- etiLog.printHeader(TcpLog::ERR,
- "Missing parameter for option -P\n");
- printUsage(progName);
- returnCode = -1;
- goto EXIT;
- }
- if (subchannel == ensemble->subchannels.end()) {
- etiLog.printHeader(TcpLog::ERR,
- "You must define a subchannel first!\n");
- printUsage(progName);
- returnCode = -1;
- goto EXIT;
- }
- level = strtoul(optarg, NULL, 0) - 1;
- if (protection->form == 0) {
- if ((level < 0) || (level > 4)) {
- etiLog.printHeader(TcpLog::ERR,
- "protection level must be between "
- "1 to 5 inclusively (current = %i)\n", level);
- returnCode = -1;
- goto EXIT;
- }
- } else {
- if ((level < 0) || (level > 3)) {
- etiLog.printHeader(TcpLog::ERR,
- "protection level must be between "
- "1 to 4 inclusively (current = %i)\n", level);
- returnCode = -1;
- goto EXIT;
- }
- }
- protection->level = level;
- break;
- case 'm':
- if (optarg) {
- ensemble->mode = strtoul(optarg, NULL, 0);
- if ((ensemble->mode < 1) || (ensemble->mode > 4)) {
- etiLog.printHeader(TcpLog::ERR,
- "Mode must be between 1-4\n");
- returnCode = -1;
- goto EXIT;
- }
- if (ensemble->mode == 4)
- ensemble->mode = 0;
- if (ensemble->mode == 3) {
- FICL = 32;
- } else {
- FICL = 24;
- }
- } else {
- etiLog.printHeader(TcpLog::ERR,
- "Missing parameter for option -m\n");
- printUsage(progName);
- returnCode = -1;
- goto EXIT;
- }
- break;
- case 'n':
- if (optarg) {
- limit = strtoul(optarg, NULL, 0);
- } else {
- etiLog.printHeader(TcpLog::ERR,
- "Missing parameter for option -n\n");
- printUsage(progName);
- returnCode = -1;
- goto EXIT;
- }
- break;
- case 'o':
- etiLog.open("createETI", 0, 12222);
- break;
- case 't':
- if (optarg == NULL) {
- etiLog.printHeader(TcpLog::ERR,
- "Missing parameter for option -t\n");
- printUsage(progName);
- returnCode = -1;
- goto EXIT;
- }
- if (component == ensemble->components.end()) {
- etiLog.printHeader(TcpLog::ERR,
- "You must define a component before setting "
- "service type!\n");
- printUsage(progName);
- returnCode = -1;
- goto EXIT;
- }
- (*component)->type = strtoul(optarg, NULL, 0);
- break;
- case 'a':
- if (component == ensemble->components.end()) {
- etiLog.printHeader(TcpLog::ERR,
- "You must define a component before setting "
- "packet address!\n");
- printUsage(progName);
- returnCode = -1;
- goto EXIT;
- }
- if (!(*component)->isPacketComponent(ensemble->subchannels)) {
- etiLog.printHeader(TcpLog::ERR, "address\n");
- printUsage(progName);
- returnCode = -1;
- goto EXIT;
- }
- (*component)->packet.address = strtoul(optarg, NULL, 0);
- break;
- case 'd':
- if (component == ensemble->components.end()) {
- etiLog.printHeader(TcpLog::ERR,
- "You must define a component before setting "
- "datagroup!\n");
- printUsage(progName);
- returnCode = -1;
- goto EXIT;
- }
- if (!(*component)->isPacketComponent(ensemble->subchannels)) {
- etiLog.printHeader(TcpLog::ERR, "datagroup\n");
- printUsage(progName);
- returnCode = -1;
- goto EXIT;
- }
- (*component)->packet.datagroup = true;
- break;
- case 'f':
- if (component == ensemble->components.end()) {
- etiLog.printHeader(TcpLog::ERR,
- "You must define a component first!\n");
- printUsage(progName);
- returnCode = -1;
- goto EXIT;
- }
- if (!(*component)->isPacketComponent(ensemble->subchannels)) {
- etiLog.printHeader(TcpLog::ERR, "application type\n");
- printUsage(progName);
- returnCode = -1;
- goto EXIT;
- }
- (*component)->packet.appType = strtoul(optarg, NULL, 0);
- break;
- case 'g':
- if (service == ensemble->services.end()) {
- etiLog.printHeader(TcpLog::ERR, "You must define a service"
- " before using option -%c\n", c);
- printUsage(progName);
- returnCode = -1;
- goto EXIT;
- }
- (*service)->language = strtoul(optarg, NULL, 0);
- break;
- case 's':
- {
- /*
- struct timeval tv;
- gettimeofday(&tv, NULL);
- unsigned _8ms = (tv.tv_usec / 1000) / 8;
- unsigned _1ms = (tv.tv_usec - (_8ms * 8000)) / 1000;
- unsigned _4us = 20;
- unsigned _488ns = 0;
- unsigned _61ns = 0;
- timestamp = (((((((_8ms << 3) | _1ms) << 8) | _4us) << 3) | _488ns) << 8) | _61ns;
- */
- enableTist = true;
- }
- break;
- case 'y':
- if (service == ensemble->services.end()) {
- etiLog.printHeader(TcpLog::ERR, "You must define a service"
- " before using option -%c\n", c);
- printUsage(progName);
- returnCode = -1;
- goto EXIT;
- }
- (*service)->pty = strtoul(optarg, NULL, 0);
- break;
- case 'z':
- factumAnalyzer = true;
- break;
- case 'r':
- etiLog.printHeader(TcpLog::INFO,
- "Enabling throttled output using simul, one frame every 24ms\n");
- outputs.push_back(new dabOutput);
- output = outputs.end() - 1;
-
- memset(*output, 0, sizeof(dabOutput));
- (*output)->outputProto = "simul";
- (*output)->outputName = "";
- (*output)->data = NULL;
- (*output)->operations = dabOutputDefaultOperations;
-
- subchannel = ensemble->subchannels.end();
- protection = NULL;
- component = ensemble->components.end();
- service = ensemble->services.end();
- break;
- case '?':
- returnCode = -1;
- case 'h':
- printUsage(progName, stdout);
- goto EXIT;
- default:
- etiLog.printHeader(TcpLog::ERR, "Option '%c' not coded yet\n", c);
- returnCode = -1;
+ }
+ catch (runtime_error &e) {
+ etiLog.printHeader(TcpLog::ERR, "Configuration file parsing error: %s\n",
+ e.what());
goto EXIT;
}
}
- if (optind < argc) {
- etiLog.printHeader(TcpLog::ERR, "Too much parameters:");
- while (optind < argc) {
- etiLog.printHeader(TcpLog::ERR, " %s", argv[optind++]);
+ else {
+ if (!parse_cmdline(argv, argc, outputs, ensemble, &enableTist, &FICL,
+ &factumAnalyzer, &limit)) {
+ goto EXIT;
}
- etiLog.printHeader(TcpLog::ERR, "\n");
- printUsage(progName);
- returnCode = -1;
- goto EXIT;
}
+
+
if (outputs.size() == 0) {
etiLog.printHeader(TcpLog::WARNING, "no output defined\n");
@@ -2211,7 +410,8 @@ int main(int argc, char *argv[])
component = getComponent(ensemble->components, (*service)->id);
if (component == ensemble->components.end()) {
etiLog.printHeader(TcpLog::ERR,
- "Service %u includes no component!\n");
+ "Service id 0x%x (%u) includes no component!\n",
+ (*service)->id, (*service)->id);
returnCode = -1;
goto EXIT;
}