diff options
Diffstat (limited to 'src/inputs')
-rw-r--r-- | src/inputs/Input.h | 121 | ||||
-rw-r--r-- | src/inputs/InputDabplusFile.cpp | 113 | ||||
-rw-r--r-- | src/inputs/InputFile.cpp | 67 | ||||
-rw-r--r-- | src/inputs/InputMpegFile.cpp | 184 | ||||
-rw-r--r-- | src/inputs/InputTest.cpp | 81 |
5 files changed, 566 insertions, 0 deletions
diff --git a/src/inputs/Input.h b/src/inputs/Input.h new file mode 100644 index 0000000..943b498 --- /dev/null +++ b/src/inputs/Input.h @@ -0,0 +1,121 @@ +/* + Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in + Right of Canada (Communications Research Center Canada) + + Copyright (C) 2013 Matthias P. Braendli + http://mpb.li + + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux 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-DabMux 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-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _INPUT_H_ +#define _INPUT_H_ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <vector> +#include <string> +#include <stdint.h> + +class InputBase { + + public: + virtual int Open(); + virtual int Lock(); // TODO get rid of lock/unlock + virtual int Unlock(); + + // ReadFrame must return exactly the right number of bytes + // for the format, which means it must fill the buffer to + // <size> bytes. + virtual int ReadFrame(void* buffer, int size); + + // TODO: ehm, where do we need this ? + virtual int SetBitrate(int bitrate); + + virtual int Close(); + virtual int Clean(); // TODO destructor + virtual int Rewind(); +}; + +/********************************************/ +/** TEST INPUT ***********************/ +/********************************************/ + +// Implement mostly everything, but don't do anything +class InputTest : InputBase { + public: + InputTest() : counter(0) {} + int Open(); + int Lock(); + int Unlock(); + int ReadFrame(void* buffer, int size); + int SetBitrate(int bitrate); + int Close(); + int Clean(); + int Rewind(); + + private: + unsigned long counter; +}; + + +/********************************************/ +/** FILE INPUTS ***********************/ +/********************************************/ + +#ifdef HAVE_INPUT_FILE + +// The InputFile is not used directly but defines some behaviour +// for Fifo, and also for different file types. +class InputFile : InputBase { + public: + InputFile(std::string fileName) : filename(fileName) {} + int Open(); + int Close(); + int Rewind(); + protected: + std::string filename; + int file; // the file descriptor +}; + +#ifdef HAVE_FORMAT_MPEG +class InputMpegFile : InputFile { + public: + InputMpegFile(std::string fileName) : filename(fileName) {} + int ReadFrame(void* buffer, int size); + private: + bool parity; +}; +#endif // HAVE_FORMAT_MPEG + +#ifdef HAVE_FORMAT_DABPLUS +class InputDabplusFile : InputFile { + public: + InputMpegFile(std::string fileName) : filename(fileName) {} + int ReadFrame(void* buffer, int size); + private: + int Read(void* buffer, int size); + std::vector<uint8_t> buffer; + size_t bufferIndex; +}; +#endif + +#endif + diff --git a/src/inputs/InputDabplusFile.cpp b/src/inputs/InputDabplusFile.cpp new file mode 100644 index 0000000..b55b3d9 --- /dev/null +++ b/src/inputs/InputDabplusFile.cpp @@ -0,0 +1,113 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + + Copyright (C) 2013 Matthias P. Braendli + http://mpb.li + + Base class for all file and fifo-based inputs. + + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux 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-DabMux 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-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "inputs/Input.h" + +#ifdef HAVE_FORMAT_DABPLUS +#ifdef HAVE_INPUT_FILE + +#include "mpeg.h" +#include "TcpLog.h" + +#include <string> +#include <vector> +#include <cstring> +#include <cstdlib> +#include <cstdio> +#include <stdint.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> + +#ifndef _WIN32 +# define O_BINARY 0 +#endif + +extern TcpLog etiLog; + +int InputDabplusFile::Read(void* buffer, int size) +{ + if (this->buffer.size() != size * 5) { + this->buffer.resize(size * 5); + this->bufferIndex = 0; + } + + if (this->bufferIndex + size > this->buffer.size()) { + int ret = read(this->file, &this->buffer[0], this->buffer.size()); + if (ret != this->buffer.size()) { + if (ret != 0) { + etiLog.print(TcpLog::CRIT, "ERROR: Incomplete DAB+ frame!\n"); + } + return 0; + } + this->bufferIndex = 0; + } + + memcpy(buffer, &this->buffer[this->bufferIndex], size); + this->bufferIndex += size; + + return size; +} + +int InputDabplusFile::ReadFrame(void* buffer, int size) +{ + int result; + uint8_t* dataOut = reinterpret_cast<uint8_t*>(buffer); + + result = Read(dataOut, size); + if (result == -1) { + etiLog.print(TcpLog::CRIT, "ERROR: Can't read file\n"); + perror(""); + return -1; + } + if (result < size) { + int sizeOut = result; + etiLog.print(TcpLog::NOTICE, "reach end of file -> rewinding\n"); + if (Rewind() == -1) { + etiLog.print(TcpLog::CRIT, "ERROR: Can't rewind file\n"); + return -1; + } + + result = Read(dataOut + sizeOut, size - sizeOut); + if (result == -1) { + etiLog.print(TcpLog::CRIT, "ERROR: Can't read file\n"); + perror(""); + return -1; + } + + if (result < size) { + etiLog.print(TcpLog::CRIT, "ERROR: Not enought data in file\n"); + return -1; + } + } + + return size; +} + +#endif +#endif + diff --git a/src/inputs/InputFile.cpp b/src/inputs/InputFile.cpp new file mode 100644 index 0000000..3701584 --- /dev/null +++ b/src/inputs/InputFile.cpp @@ -0,0 +1,67 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + + Copyright (C) 2013 Matthias P. Braendli + http://mpb.li + + Base class for all file and fifo-based inputs. + + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux 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-DabMux 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-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "inputs/InputFile.h" + +#include <string> +#include <cstdlib> +#include <cstdio> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> + +#ifndef _WIN32 +# define O_BINARY 0 +#endif + +#ifdef HAVE_INPUT_FILE + +int InputFile::Open() +{ + this->file = open(this->filename.c_str(), O_RDONLY | O_BINARY); + if (this->file == -1) { + perror(filename.c_str()); + return -1; + } + return 0; +} + +int InputFile::Rewind() +{ + return lseek(this->file, 0, SEEK_SET); +} + +int InputFile::Close() +{ + if (this->file != -1) { + close(this->file); + } + return 0; +} + +#endif + diff --git a/src/inputs/InputMpegFile.cpp b/src/inputs/InputMpegFile.cpp new file mode 100644 index 0000000..265b0ee --- /dev/null +++ b/src/inputs/InputMpegFile.cpp @@ -0,0 +1,184 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + + Copyright (C) 2013 Matthias P. Braendli + http://mpb.li + + Base class for all file and fifo-based inputs. + + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux 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-DabMux 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-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "inputs/Input.h" + +#ifdef HAVE_FORMAT_MPEG +#ifdef HAVE_INPUT_FILE + +#include "mpeg.h" +#include "TcpLog.h" + +#include <string> +#include <cstring> +#include <cstdlib> +#include <cstdio> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> + +#ifndef _WIN32 +# define O_BINARY 0 +#endif + +extern TcpLog etiLog; + +#define MPEG_FREQUENCY -2 +#define MPEG_PADDING -3 +#define MPEG_COPYRIGHT -4 +#define MPEG_ORIGINAL -5 +#define MPEG_EMPHASIS -6 + +int checkDabMpegFrame(void* data) +{ + mpegHeader* header = (mpegHeader*)data; + unsigned long* headerData = (unsigned long*)data; + if ((*headerData & 0x0f0ffcff) == 0x0004fcff) return 0; + if ((*headerData & 0x0f0ffcff) == 0x0004f4ff) return 0; + if (getMpegFrequency(header) != 48000) { + if (getMpegFrequency(header) != 24000) { + return MPEG_FREQUENCY; + } + } + if (header->padding != 0) { + return MPEG_PADDING; + } + if (header->copyright != 0) { + return MPEG_COPYRIGHT; + } + if (header->original != 0) { + return MPEG_ORIGINAL; + } + if (header->emphasis != 0) { + return MPEG_EMPHASIS; + } + return -1; +} + +int InputMpegFile::ReadFrame(void* buffer, int size) +{ + int result; + bool rewind = false; +READ_SUBCHANNEL: + if (this->parity) { + result = readData(this->file, buffer, size, 2); + this->parity = false; + return 0; + } + else { + result = readMpegHeader(this->file, buffer, size); + if (result > 0) { + result = readMpegFrame(this->file, buffer, size); + if (result < 0 && getMpegFrequency(buffer) == 24000) { + this->parity = true; + result = size; + } + } + } + + switch (result) { + case MPEG_BUFFER_UNDERFLOW: + etiLog.print(TcpLog::WARNING, "data underflow -> frame muted\n"); + goto MUTE_SUBCHANNEL; + case MPEG_BUFFER_OVERFLOW: + etiLog.print(TcpLog::WARNING, "bitrate too high -> frame muted\n"); + goto MUTE_SUBCHANNEL; + case MPEG_FILE_EMPTY: + if (rewind) { + etiLog.print(TcpLog::ERR, "file rewinded and still empty " + "-> frame muted\n"); + goto MUTE_SUBCHANNEL; + } else { + rewind = true; + etiLog.print(TcpLog::NOTICE, "reach end of file -> rewinding\n"); + lseek(this->file, 0, SEEK_SET); + goto READ_SUBCHANNEL; + } + case MPEG_FILE_ERROR: + etiLog.print(TcpLog::CRIT, "can't read file (%i) -> frame muted\n", errno); + perror(""); + goto MUTE_SUBCHANNEL; + case MPEG_SYNC_NOT_FOUND: + etiLog.print(TcpLog::CRIT, "mpeg sync not found, maybe is not a valid file " + "-> frame muted\n"); + goto MUTE_SUBCHANNEL; + case MPEG_INVALID_FRAME: + etiLog.print(TcpLog::CRIT, "file is not a valid mpeg file " + "-> frame muted\n"); + goto MUTE_SUBCHANNEL; + default: + if (result < 0) { + etiLog.print(TcpLog::CRIT, + "unknown error (code = %i) -> frame muted\n", + result); +MUTE_SUBCHANNEL: + memset(buffer, 0, size); + } + else { + if (result < size) { + etiLog.print(TcpLog::WARNING, "bitrate too low from file " + "-> frame padded\n"); + memset((char*)buffer + result, 0, size - result); + } + result = checkDabMpegFrame(buffer); + switch (result) { + case MPEG_FREQUENCY: + etiLog.print(TcpLog::ERR, "file has a frame with an invalid " + "frequency: %i, should be 48000 or 24000\n", + getMpegFrequency(buffer)); + break; + case MPEG_PADDING: + etiLog.print(TcpLog::WARNING, + "file has a frame with padding bit set\n"); + break; + case MPEG_COPYRIGHT: + etiLog.print(TcpLog::WARNING, + "file has a frame with copyright bit set\n"); + break; + case MPEG_ORIGINAL: + etiLog.print(TcpLog::WARNING, + "file has a frame with original bit set\n"); + break; + case MPEG_EMPHASIS: + etiLog.print(TcpLog::WARNING, + "file has a frame with emphasis bits set\n"); + break; + default: + if (result < 0) { + etiLog.print(TcpLog::CRIT, "mpeg file has an invalid DAB " + "mpeg frame (unknown reason: %i)\n", result); + } + break; + } + } + } + return result; +} + +#endif +#endif + diff --git a/src/inputs/InputTest.cpp b/src/inputs/InputTest.cpp new file mode 100644 index 0000000..becd8c7 --- /dev/null +++ b/src/inputs/InputTest.cpp @@ -0,0 +1,81 @@ +/* + Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + + Copyright (C) 2013 Matthias P. Braendli + http://mpb.li + + Test input that only returns frames consisting of a counter, and + padded with \0 + + */ +/* + This file is part of CRC-DabMux. + + CRC-DabMux 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-DabMux 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-DabMux. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "inputs/InputTest.h" + +#include <string.h> +#ifdef _WIN32 +#else +# include <arpa/inet.h> +#endif + + +int InputTest::Open() +{ + return 0; +} + +int InputTest::Lock() +{ + return 0; +} + +int InputTest::Unlock() +{ + return 0; +} + +int InputTest::ReadFrame(void* buffer, int size) +{ + char* data = (char*)buffer; + + *((long*)buffer) = htonl(counter++); + + for (int i = sizeof(counter); i < size; ++i) { + data[i] = i; + } + return size; +} + +int InputTest::SetBitrate(int bitrate) +{ + return bitrate; +} + + +int InputTest::Close() +{ + return 0; +} + + +int InputTest::Clean() +{ + return 0; +} + |