/* 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 . */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include #include #include "porting.h" #include "InputReader.h" #include "PcDebug.h" int InputFileReader::Open(std::string filename, bool loop) { filename_ = filename; loop_ = loop; 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_); // Also clears the EOF flag 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, "unknown!"); 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) { logger_.level(error) << "Reached end of file."; if (loop_) { if (Rewind() == 0) { if (fread(&frameSize, sizeof(frameSize), 1, inputfile_) != 1) { PDEBUG("Error after rewinding file!\n"); logger_.level(error) << "Error after rewinding file!"; return -1; } } else { PDEBUG("Impossible to rewind file!\n"); logger_.level(error) << "Impossible to rewind file!"; return -1; } } else { 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); size_t read_bytes = fread(buffer, 1, frameSize, inputfile_); if ( loop_ && streamtype_ == ETI_STREAM_TYPE_RAW && //implies frameSize == 6144 read_bytes == 0 && feof(inputfile_)) { // in case of an EOF from a RAW that we loop, rewind // otherwise, we won't tolerate it if (Rewind() == 0) { read_bytes = fread(buffer, 1, frameSize, inputfile_); } else { PDEBUG("Impossible to rewind file!\n"); logger_.level(error) << "Impossible to rewind file!"; return -1; } } 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 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; }