diff options
| author | Matthias P. Braendli (think) <matthias@mpb.li> | 2012-08-23 20:20:30 +0200 | 
|---|---|---|
| committer | Matthias P. Braendli (think) <matthias@mpb.li> | 2012-08-23 20:20:30 +0200 | 
| commit | 3b9073ec178d1ebd8563d94ebbb9b95726e31835 (patch) | |
| tree | 895ed780d41501089e1464efd20482ab9a0e4c1c /src/utils.cpp | |
| parent | 37f3f44cc1c0f5cf3a9b3f0ffc32f638b281994e (diff) | |
| download | dabmux-3b9073ec178d1ebd8563d94ebbb9b95726e31835.tar.gz dabmux-3b9073ec178d1ebd8563d94ebbb9b95726e31835.tar.bz2 dabmux-3b9073ec178d1ebd8563d94ebbb9b95726e31835.zip | |
crc-dabmux: configuration file support for ensemble definitionr5
Diffstat (limited to 'src/utils.cpp')
| -rw-r--r-- | src/utils.cpp | 457 | 
1 files changed, 457 insertions, 0 deletions
| diff --git a/src/utils.cpp b/src/utils.cpp new file mode 100644 index 0000000..270e7f5 --- /dev/null +++ b/src/utils.cpp @@ -0,0 +1,457 @@ +/* +   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +   2011, 2012 Her Majesty the Queen in Right of Canada (Communications +   Research Center Canada) + +   Includes modifications +   2012, Matthias P. Braendli, matthias.braendli@mpb.li +   */ +/* +   This file is part of CRC-DabMux. + +   CRC-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. + +   CRC-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 CRC-DabMux.  If not, see <http://www.gnu.org/licenses/>. +*/ +#include <cstring> +#include "DabMux.h" +#include "utils.h" + + +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 header_message()  +{ +    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, 2012\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"); + +} + +void printUsage(char *name, FILE* out) +{ +    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" +           ); +} + +void printUsageConfigfile(char *name, FILE* out) +{ +    fprintf(out, "NAME\n"); +    fprintf(out, "  %s - A software DAB multiplexer\n", name); +    fprintf(out, "\nSYNOPSYS\n"); +    fprintf(out, "  %s configfile\n\n", name); +    fprintf(out, "See doc/example.config for an example format for the configuration file"); +} + +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; +    } +} + +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 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 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 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 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); +} + + + | 
