aboutsummaryrefslogtreecommitdiffstats
path: root/src/inputs
diff options
context:
space:
mode:
Diffstat (limited to 'src/inputs')
-rw-r--r--src/inputs/Input.h121
-rw-r--r--src/inputs/InputDabplusFile.cpp113
-rw-r--r--src/inputs/InputFile.cpp67
-rw-r--r--src/inputs/InputMpegFile.cpp184
-rw-r--r--src/inputs/InputTest.cpp81
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;
+}
+