diff options
Diffstat (limited to 'src/inputs/InputMpegFile.cpp')
-rw-r--r-- | src/inputs/InputMpegFile.cpp | 184 |
1 files changed, 184 insertions, 0 deletions
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 + |