/* Copyright (C) 2009 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) */ /* 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 "dabInputMpegFile.h" #include "dabInputFile.h" #include "mpeg.h" #include #include #include #ifdef HAVE_FORMAT_MPEG # ifdef HAVE_INPUT_FILE struct dabInputOperations dabInputMpegFileOperations = { dabInputFileInit, dabInputFileOpen, dabInputSetbuf, dabInputFileRead, NULL, NULL, dabInputMpegFileRead, dabInputMpegSetbitrate, dabInputFileClose, dabInputFileClean, dabInputFileRewind }; #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 dabInputMpegFileRead(dabInputOperations* ops, void* args, void* buffer, int size) { dabInputFileData* data = (dabInputFileData*)args; int result; bool rewind = false; READ_SUBCHANNEL: if (data->parity) { result = readData(data->file, buffer, size, 2); data->parity = false; return 0; } else { result = readMpegHeader(data->file, buffer, size); if (result > 0) { result = readMpegFrame(data->file, buffer, size); if (result < 0 && getMpegFrequency(buffer) == 24000) { data->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(data->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; } int dabInputMpegSetbitrate(dabInputOperations* ops, void* args, int bitrate) { //dabInputFileData* data = (dabInputFileData*)args; if (bitrate == 0) { char buffer[4]; if (ops->readFrame(ops, args, buffer, 4) == 0) { bitrate = getMpegBitrate(buffer); } else { bitrate = -1; } ops->rewind(args); } if (ops->setbuf(args, bitrate * 3) != 0) { bitrate = -1; } return bitrate; } # endif #endif