From 8ecd0357866a42f18a2ccf8900a8d41423304063 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Fri, 28 Nov 2014 11:28:19 +0100 Subject: etisnoop: add support for streamed and framed ETI files --- Makefile | 4 +- etiinput.cpp | 197 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ etiinput.h | 49 +++++++++++++++ etisnoop.cpp | 44 ++++++++++--- 4 files changed, 283 insertions(+), 11 deletions(-) create mode 100644 etiinput.cpp create mode 100644 etiinput.h diff --git a/Makefile b/Makefile index c0a3a52..334077b 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ CC=g++ -SOURCES=etisnoop.cpp dabplussnoop.cpp lib_crc.c firecode.c faad_decoder.cpp wavfile.c -HEADERS=dabplussnoop.h lib_crc.h firecode.h faad_decoder.h wavfile.h +SOURCES=etisnoop.cpp dabplussnoop.cpp lib_crc.c firecode.c faad_decoder.cpp wavfile.c etiinput.cpp +HEADERS=dabplussnoop.h lib_crc.h firecode.h faad_decoder.h wavfile.h etiinput.h all: etisnoop diff --git a/etiinput.cpp b/etiinput.cpp new file mode 100644 index 0000000..ea3241f --- /dev/null +++ b/etiinput.cpp @@ -0,0 +1,197 @@ +/* + Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + Her Majesty the Queen in Right of Canada (Communications Research + Center Canada) + + Copyrigth (C) 2014 + Matthias P. Braendli, matthias.braendli@mpb.li + + Taken from ODR-DabMod + + Supported file formats: RAW, FRAMED, STREAMED + Supports re-sync to RAW ETI file + */ +/* + This file is part of ODR-DabMod. + + ODR-DabMod is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + ODR-DabMod is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ODR-DabMod. If not, see . + */ +#include "etiinput.h" +#include +#include +#include +#include +#include +#include +#include /* Definition of AT_* constants */ +#include + +int identify_eti_format(FILE* inputFile, int *streamType) +{ + *streamType = ETI_STREAM_TYPE_NONE; + + struct stat inputFileStat; + fstat(fileno(inputFile), &inputFileStat); + size_t inputfilelength_ = inputFileStat.st_size; + + int nbframes_; + + uint32_t sync; + uint32_t nbFrames; + uint16_t frameSize; + + char discard_buffer[6144]; + + if (fread(&sync, sizeof(sync), 1, inputFile) != 1) { + fprintf(stderr, "Unable to read sync in input file!\n"); + perror(""); + return -1; + } + if ((sync == 0x49c5f8ff) || (sync == 0xb63a07ff)) { + *streamType = ETI_STREAM_TYPE_RAW; + if (inputfilelength_ > 0) { + nbframes_ = inputfilelength_ / 6144; + } + else { + nbframes_ = ~0; + } + if (fseek(inputFile, -sizeof(sync), SEEK_CUR) != 0) { + // if the seek fails, consume the rest of the frame + if (fread(discard_buffer, 6144 - sizeof(sync), 1, inputFile) + != 1) { + fprintf(stderr, "Unable to read from input file!\n"); + perror(""); + return -1; + } + } + return 0; + } + + nbFrames = sync; + if (fread(&frameSize, sizeof(frameSize), 1, inputFile) != 1) { + fprintf(stderr, "Unable to read frame size in input file!\n"); + perror(""); + return -1; + } + sync >>= 16; + sync &= 0xffff; + sync |= ((uint32_t)frameSize) << 16; + + if ((sync == 0x49c5f8ff) || (sync == 0xb63a07ff)) { + *streamType = ETI_STREAM_TYPE_STREAMED; + frameSize = nbFrames & 0xffff; + if (inputfilelength_ > 0) { + nbframes_ = inputfilelength_ / (frameSize + 2); + } + else { + nbframes_ = ~0; + } + if (fseek(inputFile, -6, SEEK_CUR) != 0) { + // if the seek fails, consume the rest of the frame + if (fread(discard_buffer, frameSize - 4, 1, inputFile) + != 1) { + fprintf(stderr, "Unable to read from input file!\n"); + perror(""); + return -1; + } + } + return 0; + } + + if (fread(&sync, sizeof(sync), 1, inputFile) != 1) { + fprintf(stderr, "Unable to read nb frame in input file!\n"); + perror(""); + return -1; + } + if ((sync == 0x49c5f8ff) || (sync == 0xb63a07ff)) { + *streamType = ETI_STREAM_TYPE_FRAMED; + if (fseek(inputFile, -6, SEEK_CUR) != 0) { + // if the seek fails, consume the rest of the frame + if (fread(discard_buffer, frameSize - 4, 1, inputFile) + != 1) { + fprintf(stderr, "Unable to read from input file!\n"); + perror(""); + return -1; + } + } + nbframes_ = ~0; + return 0; + } + + // Search for the sync marker byte by byte + for (size_t i = 10; i < 6144 + 10; ++i) { + sync >>= 8; + sync &= 0xffffff; + if (fread((uint8_t*)&sync + 3, 1, 1, inputFile) != 1) { + fprintf(stderr, "Unable to read from input file!\n"); + perror(""); + return -1; + } + if ((sync == 0x49c5f8ff) || (sync == 0xb63a07ff)) { + *streamType = ETI_STREAM_TYPE_RAW; + if (inputfilelength_ > 0) { + nbframes_ = (inputfilelength_ - i) / 6144; + } + else { + nbframes_ = ~0; + } + if (fseek(inputFile, -sizeof(sync), SEEK_CUR) != 0) { + if (fread(discard_buffer, 6144 - sizeof(sync), 1, inputFile) + != 1) { + fprintf(stderr, "Unable to read from input file!\n"); + perror(""); + return -1; + } + } + return 0; + } + } + + fprintf(stderr, "Bad input file format!\n"); + return -1; +} + +int get_eti_frame(FILE* inputfile, int stream_type, void* buf) +{ + // Initialise buffer + memset(buf, 0x55, 6144); + + uint16_t frameSize; + if (stream_type == ETI_STREAM_TYPE_RAW) { + frameSize = 6144; + } + else { + if (fread(&frameSize, sizeof(frameSize), 1, inputfile) != 1) { + // EOF + return 0; + } + } + + if (frameSize > 6144) { // there might be a better limit + printf("Wrong frame size %u in ETI file!\n", frameSize); + return -1; + } + + int read_bytes = fread(buf, 1, frameSize, inputfile); + if (read_bytes != frameSize) { + // A short read of a frame (i.e. reading an incomplete frame) + // is not tolerated. Input files must not contain incomplete frames + printf("Incomplete frame in ETI file!\n"); + return -1; + } + + // We have added padding, so we always return 6144 bytes + return 6144; +} + diff --git a/etiinput.h b/etiinput.h new file mode 100644 index 0000000..d8b7691 --- /dev/null +++ b/etiinput.h @@ -0,0 +1,49 @@ +/* + Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + Her Majesty the Queen in Right of Canada (Communications Research + Center Canada) + + Copyrigth (C) 2014 + Matthias P. Braendli, matthias.braendli@mpb.li + + Taken from ODR-DabMod + + Supported file formats: RAW, FRAMED, STREAMED + Supports re-sync to RAW ETI file + */ +/* + This file is part of ODR-DabMod. + + ODR-DabMod is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + ODR-DabMod is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with ODR-DabMod. If not, see . + */ +#include + +#ifndef _ETIINPUT_H_ +#define _ETIINPUT_H_ + + +#define ETI_STREAM_TYPE_NONE 0 +#define ETI_STREAM_TYPE_RAW 1 +#define ETI_STREAM_TYPE_STREAMED 2 +#define ETI_STREAM_TYPE_FRAMED 3 + +/* Identify the stream type, and return 0 on success, -1 on failure */ +int identify_eti_format(FILE* inputfile, int *stream_type); + +/* Read the next ETI frame into buf, which must be at least 6144 bytes big + * Return number of bytes read, or zero if EOF */ +int get_eti_frame(FILE* inputfile, int stream_type, void* buf); + +#endif + diff --git a/etisnoop.cpp b/etisnoop.cpp index 4688ca9..1baea7d 100644 --- a/etisnoop.cpp +++ b/etisnoop.cpp @@ -40,6 +40,7 @@ #include "lib_crc.h" #include "dabplussnoop.h" +#include "etiinput.h" struct FIG { unsigned short int type; @@ -59,7 +60,7 @@ struct FIG0_13_shortAppInfo { using namespace std; struct eti_analyse_config_t { - int etifd; + FILE* etifd; bool ignore_error; std::map streams_to_decode; bool analyse_fic_carousel; @@ -170,15 +171,15 @@ int main(int argc, char *argv[]) } } - int etifd; + FILE* etifd; if (file_name == "-") { printf("Analysing stdin\n"); - etifd = STDIN_FILENO; + etifd = stdin; } else { - etifd = open(file_name.c_str(), O_RDONLY); - if (etifd == -1) { + etifd = fopen(file_name.c_str(), "r"); + if (etifd == NULL) { perror("File open failed"); return 1; } @@ -191,7 +192,7 @@ int main(int argc, char *argv[]) .analyse_fic_carousel = analyse_fic_carousel }; eti_analyse(config); - close(etifd); + fclose(etifd); } int eti_analyse(eti_analyse_config_t& config) @@ -206,10 +207,34 @@ int eti_analyse(eti_analyse_config_t& config) unsigned short int sad[64],stl[64]; char sdesc[256]; - while (1) { + bool running = true; - int ret = read(config.etifd, p, ETINIPACKETSIZE); - if (ret != ETINIPACKETSIZE) { + int stream_type = ETI_STREAM_TYPE_NONE; + if (identify_eti_format(config.etifd, &stream_type) == -1) { + printf("Could not identify stream type\n"); + + running = false; + } + else { + printf("Identified ETI type "); + if (stream_type == ETI_STREAM_TYPE_RAW) + printf("RAW\n"); + else if (stream_type == ETI_STREAM_TYPE_STREAMED) + printf("STREAMED\n"); + else if (stream_type == ETI_STREAM_TYPE_FRAMED) + printf("FRAMED\n"); + else + printf("?\n"); + } + + while (running) { + + int ret = get_eti_frame(config.etifd, stream_type, p); + if (ret == -1) { + fprintf(stderr, "ETI file read error\n"); + break; + } + else if (ret == 0) { fprintf(stderr, "End of ETI\n"); break; } @@ -226,6 +251,7 @@ int eti_analyse(eti_analyse_config_t& config) desc = "Error"; printbuf("ERR", 1, p, 1, desc); if (!config.ignore_error) { + printf("Aborting because of SYNC error\n"); break; } } -- cgit v1.2.3