/*
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
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;
}
int InputMpegFile::ReadFrame(void* buffer, int size)
{
return ReadFrameFromBuffer(buffer, size);
}
#endif
#endif