diff options
-rw-r--r-- | Makefile.am | 4 | ||||
-rw-r--r-- | README.md | 6 | ||||
-rw-r--r-- | src/mot-encoder.cpp (renamed from src/mot-encoder.c) | 265 |
3 files changed, 138 insertions, 137 deletions
diff --git a/Makefile.am b/Makefile.am index f698249..b807cd3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -60,9 +60,9 @@ dabplus_enc_SOURCES = src/dabplus-enc.cpp \ src/utils.h \ src/wavreader.c -mot_encoder_CFLAGS = $(GITVERSION_FLAGS) @MAGICKWAND_CFLAGS@ -Icontrib +mot_encoder_CXXFLAGS = $(GITVERSION_FLAGS) @MAGICKWAND_CFLAGS@ -Icontrib mot_encoder_LDADD = @MAGICKWAND_LDADD@ -mot_encoder_SOURCES = src/mot-encoder.c \ +mot_encoder_SOURCES = src/mot-encoder.cpp \ contrib/lib_crc.h \ contrib/lib_crc.c @@ -169,14 +169,14 @@ the specified folder, and generates the PAD data for the encoder. This is communicated through a fifo to the encoder. It also reads DLS from a file, and includes this information in the PAD. -*dabplus-enc-file-zmq* and *dabplus-enc-alsa-zmq* can insert the PAD data from -mot-encoder into the bitstream. +*dabplus-enc* can insert the PAD data from mot-encoder into the bitstream. The mp2 encoder [toolame-dab](https://github.com/Opendigitalradio/toolame-dab) can also read *mot-encoder* data. This is an ongoing development. Make sure you use the same pad length option for *mot-encoder* and the audio encoder. Only some pad lengths are supported, -please see *mot-encoder*'s help. +please see *mot-encoder*'s help. Only pad lengths 34, 42 and 58 seem to be +working with some receivers, 23 and 26 appear to be broken. Known Limitations ----------------- diff --git a/src/mot-encoder.c b/src/mot-encoder.cpp index 6f83eab..e227412 100644 --- a/src/mot-encoder.c +++ b/src/mot-encoder.cpp @@ -1,6 +1,8 @@ /* Copyright (C) 2014 CSP Innovazione nelle ICT s.c.a r.l. (http://rd.csp.it/) + Copyright (C) 2014 Matthias P. Braendli (http://opendigitalradio.org) + This program 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 @@ -14,17 +16,21 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. - MotEncoder.c + mot-encoder.c Generete PAD data for MOT Slideshow and DLS Authors: - Sergio Sagliocco <sergio.sagliocco@csp.it> + Sergio Sagliocco <sergio.sagliocco@csp.it> + Matthias P. Braendli <matthias@mpb.li> */ -#include <stdio.h> +#include <cstdio> #include <stdlib.h> +#include <stdint.h> #include <unistd.h> -#include <string.h> +#include <cstring> +#include <vector> +#include <deque> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> @@ -32,7 +38,9 @@ #include <wand/magick_wand.h> #include <getopt.h> +extern "C" { #include "lib_crc.h" +} #define MIN(a,b) (((a)<(b))?(a):(b)) #define MAX(a,b) (((a)>(b))?(a):(b)) @@ -40,9 +48,6 @@ #define MAXSEGLEN 8179 #define MAXDLS 129 -typedef unsigned char UCHAR; -typedef unsigned short int USHORT; - typedef struct { // MSC Data Group Header (extension field not supported) unsigned char extflag; // 1 bit @@ -92,12 +97,19 @@ void writeMotPAD(int output_fd, unsigned short int mscdgsize, unsigned short int padlen); -void create_dls_datagroup (char* text, int padlen, unsigned char*** p_dlsdg, int* p_numdg); +void create_dls_datagroup(char* text, int padlen); void writeDLS(int output_fd, const char* dls_file, int padlen); int get_xpadlengthmask(int padlen); #define ALLOWED_PADLEN "23, 26, 34, 42, 58" +// The toggle flag for the DLS +static uint8_t dls_toggle = 0; + +// The DLS data groups +std::deque<std::vector<uint8_t> > dlsdg; +static int dlsfd = 0; + void usage(char* name) { @@ -106,8 +118,6 @@ void usage(char* name) "Reads image data from the specified directory, and outputs PAD data\n" "on standard output\n" "Reads DLS from /tmp/dls.file\n\n" - "WARNING: This program has memory leaks! Do not attempt\n" - "to leave it running for long periods of time!\n\n" " http://opendigitalradio.org\n\n", #if defined(GITVERSION) GITVERSION @@ -137,7 +147,7 @@ int main(int argc, char *argv[]) struct dirent *pDirent; DIR *pDir; char imagepath[128]; - char dlstext[MAXDLS], dlstextprev[MAXDLS]; + char dlstext[MAXDLS]; int padlen=58; char* dir = NULL; @@ -351,7 +361,7 @@ void createMotHeader(size_t blobsize, int fidx, unsigned char* mothdr, int* moth MotHeaderCore[3] = (blobsize<<4 & 0x000000FF); sprintf(cntemp, "img%04d.jpg", fidx); - for (i = 0; i < sizeof(cntemp); i++) { + for (i = 0; i < strlen(cntemp); i++) { MotHeaderExt[8+i] = cntemp[i]; } *mothdrlen = 26; @@ -425,102 +435,13 @@ void packMscDG(unsigned char* b, MSCDG* msc, unsigned short int* bsize) } -void writeMotPAD(int output_fd, - unsigned char* mscdg, - unsigned short int mscdgsize, - unsigned short int padlen) -{ - - unsigned char pad[128]; - int xpadlengthmask, i, j,k, numseg, lastseglen; - unsigned short int crc; - - - xpadlengthmask = get_xpadlengthmask(padlen); - - // Write MSC Data Groups - int curseglen, non_ci_seglen; - for (i = 0; i < mscdgsize; i += curseglen) { - UCHAR* curseg; - UCHAR firstseg; - - curseg = &mscdg[i]; - //fprintf(stderr,"Segment offset %d\n",i); - - if (i == 0) { // First segment - firstseg = 1; - curseglen = padlen-10; - - non_ci_seglen = curseglen + 4 + 1 + 2; // size of first X-PAD = MSC-DG + DGLI-DG + End of CI list + 2x CI = size of subsequent non-CI X-PADs - } - else { - firstseg = 0; - curseglen = MIN(non_ci_seglen,mscdgsize-i); - } - - if (firstseg == 1) { - // FF-PAD Byte L (CI=1) - pad[padlen-1] = 0x02; - - // FF-PAD Byte L-1 (Variable size X_PAD) - pad[padlen-2] = 0x20; - - // Write Data Group Length Indicator - crc = 0xffff; - // CI for data group length indicator: data length=4, Application Type=1 - pad[padlen-3]=0x01; - // CI for data group length indicator: Application Type=12 (Start of MOT) - pad[padlen-4]=(xpadlengthmask<<5) | 12; - // End of CI list - pad[padlen-5]=0x00; - // RFA+HI Data group length - pad[padlen-6]=(mscdgsize & 0x3F00)>>8; - pad[padlen-7]=(mscdgsize & 0x00FF); - crc = update_crc_ccitt(crc, pad[padlen-6]); - crc = update_crc_ccitt(crc, pad[padlen-7]); - crc = ~crc; - // HI CRC - pad[padlen-8]=(crc & 0xFF00) >> 8; - // LO CRC - pad[padlen-9]=(crc & 0x00FF); - k=10; - } - else { - // FF-PAD Byte L (CI=0) - pad[padlen-1] = 0x00; - - // FF-PAD Byte L-1 (Variable size X_PAD) - pad[padlen-2] = 0x20; - k=3; - } - - for (j = 0; j < curseglen; j++) { - pad[padlen-k-j] = curseg[j]; - } - for (j = padlen-k-curseglen; j >= 0; j--) { - pad[j] = 0x00; - } - - write(output_fd, pad, padlen); - //fprintf(stderr,"MSC Data Group - Segment %d: ",i); - //for (j=0;j<padlen;j++) fprintf(stderr,"%02x ",pad[j]); - // fprintf(stderr,"\n"); - - } -} - void writeDLS(int output_fd, const char* dls_file, int padlen) { char dlstext[MAXDLS]; - static char dlstextprev[MAXDLS]; int dlslen; int i; - static unsigned char** dlsdg; - static int numdg = 0; - - static int dlsfd = 0; - if (dlsfd!=0) { + if (dlsfd != 0) { close(dlsfd); } @@ -532,34 +453,26 @@ void writeDLS(int output_fd, const char* dls_file, int padlen) { dlslen = read(dlsfd, dlstext, MAXDLS); dlstext[dlslen] = 0x00; - //if (strcmp(dlstext,dlstextprev)!=0) { - create_dls_datagroup(dlstext, padlen, &dlsdg, &numdg); - strcpy(dlstextprev, dlstext); - //} - for (i = 0; i < numdg; i++) { - write(output_fd, dlsdg[i], padlen); + create_dls_datagroup(dlstext, padlen); + for (i = 0; i < dlsdg.size(); i++) { + write(output_fd, &dlsdg[i].front(), dlsdg[i].size()); } } -void create_dls_datagroup (char* text, int padlen, UCHAR*** p_dlsdg, int* p_numdg) { - - UCHAR dlsseg[8][16]; // max 8 segments, each max 16 chars - UCHAR** dlsdg; // Array of datagroups composing dls text; - +void create_dls_datagroup(char* text, int padlen) { + int numdg = 0; // Number of data groups int numseg; // Number of DSL segments int lastseglen; // Length of the last segment - int numdg; // Number of data group int xpadlengthmask; int i, j, k, z, idx_start_crc, idx_stop_crc; - USHORT dlscrc; - static UCHAR toggle = 0; + uint16_t dlscrc; - if (toggle == 0) - toggle = 1; + if (dls_toggle == 0) + dls_toggle = 1; else - toggle = 0; + dls_toggle = 0; numseg = strlen(text) / 16; lastseglen = strlen(text) % 16; @@ -588,7 +501,6 @@ void create_dls_datagroup (char* text, int padlen, UCHAR*** p_dlsdg, int* p_numd } } - *p_numdg = numdg; fprintf(stderr, "PAD Length: %d\n", padlen); fprintf(stderr, "DLS text: %s\n", text); fprintf(stderr, "Number of DLS segments: %d\n", numseg); @@ -596,14 +508,14 @@ void create_dls_datagroup (char* text, int padlen, UCHAR*** p_dlsdg, int* p_numd xpadlengthmask = get_xpadlengthmask(padlen); - *p_dlsdg = (UCHAR**) malloc(numdg * sizeof(UCHAR*)); - dlsdg = *p_dlsdg; + dlsdg.resize(0); + dlsdg.resize(numdg); i = 0; for (z=0; z < numseg; z++) { char* curseg; int curseglen; - UCHAR firstseg, lastseg; + uint8_t firstseg, lastseg; curseg = &text[z * 16]; fprintf(stderr, "Segment number %d\n", z+1); @@ -630,7 +542,7 @@ void create_dls_datagroup (char* text, int padlen, UCHAR*** p_dlsdg, int* p_numd } if (curseglen <= padlen-9) { // Segment is composed of 1 data group - dlsdg[i] = (UCHAR*) malloc(padlen * sizeof(UCHAR)); + dlsdg[i].resize(padlen); // FF-PAD Byte L (CI=1) dlsdg[i][padlen-1]=0x02; @@ -646,7 +558,8 @@ void create_dls_datagroup (char* text, int padlen, UCHAR*** p_dlsdg, int* p_numd dlsdg[i][padlen-4]=0x00; // DLS Prefix (T=1,Only one segment,segment length-1) - dlsdg[i][padlen-5]=((toggle*8+firstseg*4+lastseg*2+0)<<4) | (curseglen-1); + dlsdg[i][padlen-5]=((dls_toggle*8+firstseg*4+lastseg*2+0)<<4) | + (curseglen-1); if (firstseg==1) { // DLS Prefix (Charset standard) @@ -675,8 +588,8 @@ void create_dls_datagroup (char* text, int padlen, UCHAR*** p_dlsdg, int* p_numd dlscrc = ~dlscrc; fprintf(stderr, "crc=%x ~crc=%x\n", ~dlscrc, dlscrc); - dlsdg[i][padlen-7-curseglen] = (dlscrc & 0xFF00) >> 8; // HI CRC - dlsdg[i][padlen-7-curseglen-1] = dlscrc & 0x00FF; // LO CRC + dlsdg[i][padlen-7-curseglen] = (dlscrc & 0xFF00) >> 8; // HI CRC + dlsdg[i][padlen-7-curseglen-1] = dlscrc & 0x00FF; // LO CRC // NULL PADDING for (j = padlen-7-curseglen-2; j >= 0; j--) { @@ -695,7 +608,7 @@ void create_dls_datagroup (char* text, int padlen, UCHAR*** p_dlsdg, int* p_numd // FIRST DG (NO CRC) dlscrc = 0xffff; - dlsdg[i] = (UCHAR*) malloc(padlen * sizeof(UCHAR)); + dlsdg[i].resize(padlen); // FF-PAD Byte L (CI=1) dlsdg[i][padlen-1]=0x02; @@ -711,7 +624,8 @@ void create_dls_datagroup (char* text, int padlen, UCHAR*** p_dlsdg, int* p_numd dlsdg[i][padlen-4]=0x00; // DLS Prefix (T=1,Only one segment,segment length-1) - dlsdg[i][padlen-5]=((toggle*8+firstseg*4+lastseg*2+0)<<4) | (curseglen-1); + dlsdg[i][padlen-5]=((dls_toggle*8+firstseg*4+lastseg*2+0)<<4) | + (curseglen-1); if (firstseg == 1) { @@ -746,14 +660,15 @@ void create_dls_datagroup (char* text, int padlen, UCHAR*** p_dlsdg, int* p_numd dlsdg[i][0]=0x00; fprintf(stderr, "First Data group: "); - for (j = 0; j < padlen; j++) + for (j = 0; j < padlen; j++) { fprintf(stderr, "%x ", dlsdg[i][j]); + } fprintf(stderr,"\n"); // SECOND DG (NO CI, NO PREFIX) i++; - dlsdg[i] = (UCHAR*) malloc(padlen*sizeof(UCHAR)); + dlsdg[i].resize(padlen); // FF-PAD Byte L (CI=0) dlsdg[i][padlen-1] = 0x00; @@ -780,8 +695,9 @@ void create_dls_datagroup (char* text, int padlen, UCHAR*** p_dlsdg, int* p_numd } fprintf(stderr, "Second Data group: "); - for (j = 0; j < padlen; j++) + for (j = 0; j < padlen; j++) { fprintf(stderr, "%x ", dlsdg[i][j]); + } fprintf(stderr, "\n"); fprintf(stderr, "**** crc=%x ~crc=%x\n", ~dlscrc, dlscrc); @@ -790,6 +706,91 @@ void create_dls_datagroup (char* text, int padlen, UCHAR*** p_dlsdg, int* p_numd } } +void writeMotPAD(int output_fd, + unsigned char* mscdg, + unsigned short int mscdgsize, + unsigned short int padlen) +{ + + unsigned char pad[128]; + int xpadlengthmask, i, j,k, numseg, lastseglen; + unsigned short int crc; + + xpadlengthmask = get_xpadlengthmask(padlen); + + // Write MSC Data Groups + int curseglen, non_ci_seglen; + for (i = 0; i < mscdgsize; i += curseglen) { + uint8_t* curseg; + uint8_t firstseg; + + curseg = &mscdg[i]; + //fprintf(stderr,"Segment offset %d\n",i); + + if (i == 0) { // First segment + firstseg = 1; + curseglen = padlen-10; + + // size of first X-PAD = MSC-DG + DGLI-DG + End of CI list + 2x CI = size of subsequent non-CI X-PADs + non_ci_seglen = curseglen + 4 + 1 + 2; + } + else { + firstseg = 0; + curseglen = MIN(non_ci_seglen,mscdgsize-i); + } + + if (firstseg == 1) { + // FF-PAD Byte L (CI=1) + pad[padlen-1] = 0x02; + + // FF-PAD Byte L-1 (Variable size X_PAD) + pad[padlen-2] = 0x20; + + // Write Data Group Length Indicator + crc = 0xffff; + // CI for data group length indicator: data length=4, Application Type=1 + pad[padlen-3]=0x01; + // CI for data group length indicator: Application Type=12 (Start of MOT) + pad[padlen-4]=(xpadlengthmask<<5) | 12; + // End of CI list + pad[padlen-5]=0x00; + // RFA+HI Data group length + pad[padlen-6]=(mscdgsize & 0x3F00)>>8; + pad[padlen-7]=(mscdgsize & 0x00FF); + crc = update_crc_ccitt(crc, pad[padlen-6]); + crc = update_crc_ccitt(crc, pad[padlen-7]); + crc = ~crc; + // HI CRC + pad[padlen-8]=(crc & 0xFF00) >> 8; + // LO CRC + pad[padlen-9]=(crc & 0x00FF); + k=10; + } + else { + // FF-PAD Byte L (CI=0) + pad[padlen-1] = 0x00; + + // FF-PAD Byte L-1 (Variable size X_PAD) + pad[padlen-2] = 0x20; + k=3; + } + + for (j = 0; j < curseglen; j++) { + pad[padlen-k-j] = curseg[j]; + } + for (j = padlen-k-curseglen; j >= 0; j--) { + pad[j] = 0x00; + } + + write(output_fd, pad, padlen); + //fprintf(stderr,"MSC Data Group - Segment %d: ",i); + //for (j=0;j<padlen;j++) fprintf(stderr,"%02x ",pad[j]); + // fprintf(stderr,"\n"); + + } +} + + int get_xpadlengthmask(int padlen) { int xpadlengthmask; |