diff options
Diffstat (limited to 'src/InputFileReader.cpp')
-rw-r--r-- | src/InputFileReader.cpp | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/src/InputFileReader.cpp b/src/InputFileReader.cpp new file mode 100644 index 0000000..1be1ad7 --- /dev/null +++ b/src/InputFileReader.cpp @@ -0,0 +1,266 @@ +/* + Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + Her Majesty the Queen in Right of Canada (Communications Research + Center Canada) + + Copyrigth (C) 2013 + Matthias P. Braendli, matthias.braendli@mpb.li + + + Input module for reading the ETI data from file or pipe. + + Supported formats: RAW, FRAMED, STREAMED + Supports re-sync to RAW ETI + */ +/* + This file is part of CRC-DADMOD. + + CRC-DADMOD 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-DADMOD 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-DADMOD. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <string> +#include <cstdio> +#include <cstring> +#include <errno.h> +#include <stdint.h> +#include <sys/stat.h> +#include "porting.h" +#include "InputReader.h" +#include "PcDebug.h" + +int InputFileReader::Open(std::string filename) +{ + filename_ = filename; + inputfile_ = fopen(filename_.c_str(), "r"); + if (inputfile_ == NULL) { + fprintf(stderr, "Unable to open input file!\n"); + logger_.level(error) << "Unable to open input file!"; + perror(filename_.c_str()); + return -1; + } + + return IdentifyType(); +} + +int InputFileReader::Rewind() +{ + rewind(inputfile_); + return IdentifyType(); +} + +int InputFileReader::IdentifyType() +{ + EtiStreamType streamType = ETI_STREAM_TYPE_NONE; + + struct stat inputFileStat; + fstat(fileno(inputfile_), &inputFileStat); + inputfilelength_ = inputFileStat.st_size; + + 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"); + logger_.level(error) << "Unable to read sync in input file!"; + perror(filename_.c_str()); + 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"); + logger_.level(error) << "Unable to read from input file!"; + perror(filename_.c_str()); + return -1; + } + } + this->streamtype_ = streamType; + return 0; + } + + nbFrames = sync; + if (fread(&frameSize, sizeof(frameSize), 1, inputfile_) != 1) { + fprintf(stderr, "Unable to read frame size in input file!\n"); + logger_.level(error) << "Unable to read frame size in input file!"; + perror(filename_.c_str()); + 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"); + logger_.level(error) << "Unable to read from input file!"; + perror(filename_.c_str()); + return -1; + } + } + this->streamtype_ = streamType; + return 0; + } + + if (fread(&sync, sizeof(sync), 1, inputfile_) != 1) { + fprintf(stderr, "Unable to read nb frame in input file!\n"); + logger_.level(error) << "Unable to read nb frame in input file!"; + perror(filename_.c_str()); + 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"); + logger_.level(error) << "Unable to read from input file!"; + perror(filename_.c_str()); + return -1; + } + } + this->streamtype_ = streamType; + 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"); + logger_.level(error) << "Unable to read from input file!"; + perror(filename_.c_str()); + 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"); + logger_.level(error) << "Unable to read from input file!"; + perror(filename_.c_str()); + return -1; + } + } + this->streamtype_ = streamType; + return 0; + } + } + + fprintf(stderr, "Bad input file format!\n"); + logger_.level(error) << "Bad input file format!"; + return -1; +} + +void InputFileReader::PrintInfo() +{ + fprintf(stderr, "Input file format: "); + switch (streamtype_) { + case ETI_STREAM_TYPE_RAW: + fprintf(stderr, "raw"); + break; + case ETI_STREAM_TYPE_STREAMED: + fprintf(stderr, "streamed"); + break; + case ETI_STREAM_TYPE_FRAMED: + fprintf(stderr, "framed"); + break; + default: + fprintf(stderr, "unkown!"); + break; + } + fprintf(stderr, "\n"); + fprintf(stderr, "Input file length: %zu\n", inputfilelength_); + if (~nbframes_ != 0) { + fprintf(stderr, "Input file nb frames: %lu\n", nbframes_); + } + else { + fprintf(stderr, "Input file nb frames: endless\n"); + } +} + +int InputFileReader::GetNextFrame(void* buffer) +{ + uint16_t frameSize; + + if (streamtype_ == ETI_STREAM_TYPE_RAW) { + frameSize = 6144; + } + else { + if (fread(&frameSize, sizeof(frameSize), 1, inputfile_) != 1) { + PDEBUG("End of file!\n"); + logger_.level(error) << "Reached end of file!"; + return 0; + } + } + if (frameSize > 6144) { // there might be a better limit + logger_.level(error) << "Wrong frame size " << frameSize << " in ETI file!"; + fprintf(stderr, "Wrong frame size %u in ETI file!\n", frameSize); + return -1; + } + + PDEBUG("Frame size: %u\n", frameSize); + + if (fread(buffer, frameSize, 1, inputfile_) != 1) { + // A short read of a frame (i.e. reading an incomplete frame) + // is not tolerated. Input files must not contain incomplete frames + fprintf(stderr, + "Unable to read a complete frame of %u data bytes from input file!\n", + frameSize); + + perror(filename_.c_str()); + logger_.level(error) << "Unable to read from input file!"; + return -1; + } + + memset(&((uint8_t*)buffer)[frameSize], 0x55, 6144 - frameSize); + + return 6144; +} |