diff options
Diffstat (limited to 'src/dabInputPacketFile.cpp')
-rw-r--r-- | src/dabInputPacketFile.cpp | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/src/dabInputPacketFile.cpp b/src/dabInputPacketFile.cpp new file mode 100644 index 0000000..65b5ebe --- /dev/null +++ b/src/dabInputPacketFile.cpp @@ -0,0 +1,263 @@ +/* + Copyright (C) 2009, 2011 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 <http://www.gnu.org/licenses/>. + */ + +#include "dabInputPacketFile.h" +#include "dabInputFile.h" +#include "dabInputFifo.h" +#include "ReedSolomon.h" + +#ifdef HAVE_FORMAT_PACKET +# ifdef HAVE_INPUT_FILE + + +#include <string.h> +#include <stdio.h> +#include <errno.h> + + +#ifdef _WIN32 +# pragma pack(push, 1) +#endif +struct packetHeader { + unsigned char addressHigh:2; + unsigned char last:1; + unsigned char first:1; + unsigned char continuityIndex:2; + unsigned char packetLength:2; + unsigned char addressLow; + unsigned char dataLength:7; + unsigned char command; +} +#ifdef _WIN32 +# pragma pack(pop) +#else +__attribute((packed)) +#endif +; + + +struct dabInputOperations dabInputPacketFileOperations = { + dabInputFileInit, + dabInputFileOpen, + dabInputSetbuf, + dabInputFileRead, + NULL, + NULL, + dabInputPacketFileRead, + dabInputSetbitrate, + dabInputFileClose, + dabInputFileClean, + dabInputFileRewind +}; + + +int dabInputPacketFileRead(dabInputOperations* ops, void* args, void* buffer, + int size) +{ + dabInputFileData* data = (dabInputFileData*)args; + unsigned char* dataBuffer = (unsigned char*)buffer; + int written = 0; + int length; + packetHeader* header; + int indexRow; + int indexCol; + + while (written < size) { + if (data->enhancedPacketWaiting > 0) { + *dataBuffer = 192 - data->enhancedPacketWaiting; + *dataBuffer /= 22; + *dataBuffer <<= 2; + *(dataBuffer++) |= 0x03; + *(dataBuffer++) = 0xfe; + indexCol = 188; + indexCol += (192 - data->enhancedPacketWaiting) / 12; + indexRow = 0; + indexRow += (192 - data->enhancedPacketWaiting) % 12; + for (int j = 0; j < 22; ++j) { + if (data->enhancedPacketWaiting == 0) { + *(dataBuffer++) = 0; + } else { + *(dataBuffer++) = data->enhancedPacketData[indexRow][indexCol]; + if (++indexRow == 12) { + indexRow = 0; + ++indexCol; + } + --data->enhancedPacketWaiting; + } + } + written += 24; + if (data->enhancedPacketWaiting == 0) { + data->enhancedPacketLength = 0; + } + } else if (data->packetLength != 0) { + header = (packetHeader*)data->packetData; + if (written + data->packetLength > (unsigned)size) { + memset(dataBuffer, 0, 22); + dataBuffer[22] = 0x60; + dataBuffer[23] = 0x4b; + length = 24; + } else if (data->enhancedPacketData != NULL) { + if (data->enhancedPacketLength + data->packetLength + > (12 * 188)) { + memset(dataBuffer, 0, 22); + dataBuffer[22] = 0x60; + dataBuffer[23] = 0x4b; + length = 24; + } else { + memcpy(dataBuffer, data->packetData, data->packetLength); + length = data->packetLength; + data->packetLength = 0; + } + } else { + memcpy(dataBuffer, data->packetData, data->packetLength); + length = data->packetLength; + data->packetLength = 0; + } + if (data->enhancedPacketData != NULL) { + indexCol = data->enhancedPacketLength / 12; + indexRow = data->enhancedPacketLength % 12; // TODO Check if always 0 + for (int j = 0; j < length; ++j) { + data->enhancedPacketData[indexRow][indexCol] = dataBuffer[j]; + if (++indexRow == 12) { + indexRow = 0; + ++indexCol; + } + } + data->enhancedPacketLength += length; + if (data->enhancedPacketLength >= (12 * 188)) { + data->enhancedPacketLength = (12 * 188); + ReedSolomon encoder(204, 188); + for (int j = 0; j < 12; ++j) { + encoder.encode(data->enhancedPacketData[j], 188); + } + data->enhancedPacketWaiting = 192; + } + } + written += length; + dataBuffer += length; + } else { + int nbBytes = ops->read(args, dataBuffer, 3); + header = (packetHeader*)dataBuffer; + if (nbBytes == -1) { + if (errno == EAGAIN) goto END_PACKET; + perror("Packet file"); + return -1; + } else if (nbBytes == 0) { + if (ops->rewind(args) == -1) { + goto END_PACKET; + } + continue; + } else if (nbBytes < 3) { + etiLog.print(TcpLog::ERR, + "Error while reading file for packet header; " + "read %i out of 3 bytes\n", nbBytes); + break; + } + + length = header->packetLength * 24 + 24; + if (written + length > size) { + memcpy(data->packetData, header, 3); + ops->read(args, &data->packetData[3], length - 3); + data->packetLength = length; + continue; + } + if (data->enhancedPacketData != NULL) { + if (data->enhancedPacketLength + length > (12 * 188)) { + memcpy(data->packetData, header, 3); + ops->read(args, &data->packetData[3], length - 3); + data->packetLength = length; + continue; + } + } + nbBytes = ops->read(args, dataBuffer + 3, length - 3); + if (nbBytes == -1) { + perror("Packet file"); + return -1; + } else if (nbBytes == 0) { + etiLog.print(TcpLog::NOTICE, + "Packet header read, but no data!\n"); + if (ops->rewind(args) == -1) { + goto END_PACKET; + } + continue; + } else if (nbBytes < length - 3) { + etiLog.print(TcpLog::ERR, "Error while reading packet file; " + "read %i out of %i bytes\n", nbBytes, length - 3); + break; + } + if (data->enhancedPacketData != NULL) { + indexCol = data->enhancedPacketLength / 12; + indexRow = data->enhancedPacketLength % 12; // TODO Check if always 0 + for (int j = 0; j < length; ++j) { + data->enhancedPacketData[indexRow][indexCol] = dataBuffer[j]; + if (++indexRow == 12) { + indexRow = 0; + ++indexCol; + } + } + data->enhancedPacketLength += length; + if (data->enhancedPacketLength >= (12 * 188)) { + if (data->enhancedPacketLength > (12 * 188)) { + etiLog.print(TcpLog::ERR, + "Error, too much enhanced packet data!\n"); + } + ReedSolomon encoder(204, 188); + for (int j = 0; j < 12; ++j) { + encoder.encode(data->enhancedPacketData[j], 188); + } + data->enhancedPacketWaiting = 192; + } + } + written += length; + dataBuffer += length; + } + } +END_PACKET: + if (ops->read == dabInputFifoRead) { + dabInputFifoData* fifoData = (dabInputFifoData*)args; + dabInputFifoStats* fifoStats = (dabInputFifoStats*)&fifoData->stats; + fifoStats->frameRecords[fifoStats->frameCount].curSize = written; + fifoStats->frameRecords[fifoStats->frameCount].maxSize = size; + if (++fifoStats->frameCount == NB_RECORDS) { + etiLog.print(TcpLog::INFO, "Packet subchannel usage: (%i)", + fifoStats->id); + for (int i = 0; i < fifoStats->frameCount; ++i) { + etiLog.print(TcpLog::INFO, " %i/%i", + fifoStats->frameRecords[i].curSize, + fifoStats->frameRecords[i].maxSize); + } + etiLog.print(TcpLog::INFO, "\n"); + fifoStats->frameCount = 0; + } + } + while (written < size) { + memset(dataBuffer, 0, 22); + dataBuffer[22] = 0x60; + dataBuffer[23] = 0x4b; + dataBuffer += 24; + written += 24; + } + return written; +} + + +# endif +#endif |