/* 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 . */ #include "inputs/Input.h" #ifdef HAVE_FORMAT_MPEG #ifdef HAVE_INPUT_FILE #include "mpeg.h" #include "TcpLog.h" #include #include #include #include #include #include #include #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 const char* InputMpegFile::GetName() { return m_name.c_str(); } 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::ReadSource(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