Skip to content

Commit

Permalink
Add edi2eti converter application.
Browse files Browse the repository at this point in the history
  • Loading branch information
piratfm committed Jul 14, 2017
1 parent 2963d8b commit 6f100f5
Show file tree
Hide file tree
Showing 15 changed files with 2,287 additions and 5 deletions.
13 changes: 8 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,27 @@ LDFLAGS=-lm
#FEC_LDFLAGS:= -lfec


all: cleanapps ts2na na2ni ni2http
all: cleanapps ts2na na2ni ni2http edi2eti

edi2eti:
gcc -g $(CFLAGS) -Wall -o edi2eti network.c af_parser.c pf_parser.c tag_parser.c crc.c eti_assembler.c logging.c edi2eti.c -lfec -lzmq

ts2na:
gcc -g $(CFLAGS) -Wall -o ts2na ts2na.c
gcc -g $(CFLAGS) -Wall -o ts2na ts2na.c

ts2na_dreambox:
gcc -g $(CFLAGS) -Wall -o ts2na ts2na.c tune.c
gcc -g $(CFLAGS) -Wall -o ts2na ts2na.c tune.c

na2ni:
gcc -g $(CFLAGS) -Wall -o na2ni na2ni.c $(LDFLAGS) $(FEC_LDFLAGS)
gcc -g $(CFLAGS) -Wall -o na2ni na2ni.c $(LDFLAGS) $(FEC_LDFLAGS)

ni2http:
test -f ./libshout-2.2.2/src/.libs/libshout.a || { tar -xvzf libshout-2.2.2.tar.gz; cd libshout-2.2.2; ./configure --enable-shared=no --enable-static=yes; make; cd ..; }
gcc -g $(CFLAGS) -Wall -o ni2http ni2http.c wffigproc.c wfficproc.c wfbyteops.c wftables.c wffirecrc.c wfcrc.c parse_config.c $(LDFLAGS) -I./libshout-2.2.2/include ./libshout-2.2.2/src/.libs/libshout.a -lpthread $(FEC_LDFLAGS) $(ZMQ_LDFLAGS)

cleanapps:
rm -f *.o
rm -f ts2na na2ni ni2http
rm -f ts2na na2ni ni2http edi2eti

clean: cleanapps
if [ -f ./libshout-2.2.2/src/.libs/libshout.a ]; then cd libshout-2.2.2; make clean; cd ..; fi;
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,23 @@ na2ni - is ETI-NA to ETI-NI converter. This tool automatically detects E1-sync b

The output stream will be 6144-bytes aligned raw ETI-NI stream.

ETI edi2eti
===============
edi2eti - is EDI-AF or EDI-PF to ETI-NI converter. This tool automatically detects type of AF/PF packet type. Maximal deinterleaving depth is setted to 192ms to prevent high memory usage. Also it extracts ETI-LI content of the stream and incapsulate it into ETI-NI frames.
Tool is able to receive multicast data and save converted stream ETI-file or publish it by ZeroMQ protcol. This tool is written to convert microwave links (WiFi or raw packet stream) to tcp-zeromq stream useable by EasyDABv2 module.

usage: ./edi2eti [-o <outputfile|zeromq-uri>] [ip:port]

The output stream will be 6144-bytes aligned raw ETI-NI stream or local-port published ZeroMQ packet.

Sample of receiving multicast stream and convert it to ZeroMQ:

./edi2eti -o "zmq+tcp://*:18982" 232.20.10.1:12000

Sample of receiving multicast stream and save to file:

./edi2eti -o "out.eti" 232.20.10.1:12000

ETI ni2http
===============
ni2http - is ETI-NI to HTTP or ZeroMQ converter. This tool converts eti-stream to mp2/aac and relay it to icecast2 or ODR-DabMUX server.
Expand Down
171 changes: 171 additions & 0 deletions af_parser.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/*
* af_parser.c
*
* Created on: 27 янв. 2017
* Author: tipok
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <inttypes.h>
#include <unistd.h>
#include <ctype.h>

#include <fec.h>

#include "edi_parser.h"
#include "crc.h"
#include "logging.h"

#include "buffer_unpack.h"


edi_handler_t *initEDIHandle(int fmt, callback_t outCallback, void *priv_data)
{
edi_handler_t *h = calloc(1, sizeof(edi_handler_t));
h->eti_format = fmt;

h->afb.m_rs_handler = init_rs_char(8, 0x11d, 1, 1, 255 - 207, ((1 << 8) - 1) - 255);
h->write_cb = outCallback;
h->write_cb_priv = priv_data;
return h;
}

void closeEDIHandle(edi_handler_t *h)
{
int i;
msg_Log("EDI: stats: packets lost: %u/%u errors:%u/%u",
h->afb.PktLost, h->afb.PktCount, h->afb.errorsCorrected, h->afb.PktCount*h->afb.Plen);
if(h) {
free_rs_char(h->afb.m_rs_handler);

for(i=0;i<64;i++) {
if(h->eti.m_stc[i].mst) {
free(h->eti.m_stc[i].mst);
h->eti.m_stc[i].mst = NULL;
h->eti.m_stc[i].mst_size = 0;
}
}

if(h->pf._payload)
free(h->pf._payload);

free(h);
}
}




/*****************************************************************************
* AF HandleAFPacket
*****************************************************************************/
static int HandleAFPacket(edi_handler_t *h, uint8_t *edi_pkt, uint32_t pktsize)
{
if(pktsize < AFPACKET_HEADER_LEN || edi_pkt[0] != 'A' || edi_pkt[1] != 'F') {
msg_Log("EDI-AF: bad tag!");
return -1;
}

// read length from packet
uint32_t taglength = read_32b(edi_pkt + 2);
uint16_t seq = read_16b(edi_pkt + 6);
if (h->af.m_last_seq + 1 != seq) {
msg_Log("EDI-AF: Packet sequence error");
}
h->af.m_last_seq = seq;

bool has_crc = (edi_pkt[8] & 0x80) ? true : false;
uint8_t major_revision = (edi_pkt[8] & 0x70) >> 4;
uint8_t minor_revision = edi_pkt[8] & 0x0F;
if (major_revision != 1 || minor_revision != 0) {
msg_Log("EDI-AF: Packet has wrong revision %u.%u", major_revision, minor_revision);
return -1;
}
uint8_t pt = edi_pkt[9];
if (pt != 'T') {
// only support Tag
return 0;
}

const size_t crclength = 2;
if (pktsize < AFPACKET_HEADER_LEN + taglength + crclength) {
msg_Log("EDI-AF: packet too small: %u < %u", pktsize, AFPACKET_HEADER_LEN + taglength + crclength);
return 0;
}

if (!has_crc) {
msg_Log("EDI-AF: packet not supported, has no CRC");
return -1;
}
#if 0
uint16_t crc = 0xffff;
for (i = 0; i < AFPACKET_HEADER_LEN + taglength; i++) {
crc = crc16(crc, &edi_pkt[i], 1);
}
crc ^= 0xffff;

uint16_t packet_crc = read_16b(edi_pkt + AFPACKET_HEADER_LEN + taglength);

#endif
//msg_Dump(edi_pkt , pktsize);

//bool ok = checkCRC(edi_pkt, AFPACKET_HEADER_LEN + taglength + crclength);
bool ok = checkCRC(edi_pkt, AFPACKET_HEADER_LEN + taglength + crclength);

if (!ok) {
msg_Log("EDI-AF: Packet crc wrong pos:%u max:%u", AFPACKET_HEADER_LEN + taglength, pktsize);
return -1;
}


//msg_Dump(edi_pkt + AFPACKET_HEADER_LEN, taglength);
return decode_tagpacket(h, edi_pkt + AFPACKET_HEADER_LEN, taglength);
//utilized bytes: AFPACKET_HEADER_LEN + taglength + 2;
}


/*****************************************************************************
* HandleEDIPacket
*****************************************************************************/
int HandleEDIPacket(edi_handler_t *h, uint8_t *edi_pkt, size_t pktsize)
{
int ret = 0;

//msg_Dump((char *)edi_pkt, pktsize);

if(pktsize < 2) {
msg_Log("EDI: packet too small!");
goto edi_error;
}

if(edi_pkt[0]=='P' && edi_pkt[1]=='F') {

int used_bytes = 0;
do {
used_bytes = HandlePFPacket(h, edi_pkt+used_bytes, pktsize - used_bytes);
if(used_bytes > 0 && h->pf._valid) {
//returns bytes if we have AFpacked decoded.
int afBytes = pushPFTFrag(&h->pf, &h->afb);
if(afBytes > 0) {
ret = HandleAFPacket(h, h->afb.afPacket, afBytes);
if(ret > 0)
AssembleETIFrame(&h->eti, h->eti_format, h->write_cb, h->write_cb_priv);
}
}
} while (used_bytes > 0 && pktsize > used_bytes);
} else if(edi_pkt[0]=='A' && edi_pkt[1]=='F') {
ret = HandleAFPacket(h, edi_pkt, pktsize);
if(ret > 0)
AssembleETIFrame(&h->eti, h->eti_format, h->write_cb, h->write_cb_priv);
} else {
msg_Log("EDI: packet is unknown: %c%c", isprint(edi_pkt[0]) ? edi_pkt[0] : '.', isprint(edi_pkt[1]) ? edi_pkt[1] : '.');
}

return 0;
edi_error:
return -1;
}
41 changes: 41 additions & 0 deletions buffer_unpack.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@

#ifndef BUFFER_UNPACK_H_
#define BUFFER_UNPACK_H_

#include <stdint.h>
#include "crc.h"


/******************************************************************************
* small helper functions
******************************************************************************/
static inline uint16_t read_16b(const uint8_t *buf){
uint16_t value = ((uint16_t)buf[0]) << 8 | buf[1];
return value;
}

static inline uint32_t read_24b(const uint8_t *buf){
uint32_t value = ((uint32_t) buf[0]) << 16 | ((uint16_t)buf[1]) << 8 | buf[2];
return value;
}

static inline uint32_t read_32b(const uint8_t *buf){
uint32_t value = ((uint32_t)buf[0]) << 24 | ((uint32_t)buf[1]) << 16 | ((uint16_t)buf[2]) << 8 | buf[3];
return value;
}

static inline uint32_t unpack1bit(const uint8_t byte, int bitpos){
return (byte & 1 << (7-bitpos)) > (7-bitpos);
}

static inline bool checkCRC(const uint8_t *buf, size_t size)
{
const uint16_t crc_from_packet = read_16b(buf + size - 2);
uint16_t crc_calc = 0xffff;
crc_calc = crc16(crc_calc, buf, size - 2);
crc_calc ^= 0xffff;

return crc_from_packet == crc_calc;
}

#endif /* BUFFER_UNPACK_H_ */
Loading

0 comments on commit 6f100f5

Please sign in to comment.