📄 sdcreceive.cpp
字号:
/******************************************************************************\ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik * Copyright (c) 2001 * * Author(s): * Volker Fischer * * Description: * SDC data stream decoding (receiver) * ****************************************************************************** * * This program 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 2 of the License, or (at your option) any later * version. * * This program 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 * this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *\******************************************************************************/#include "SDC.h"/* Implementation *************************************************************/CSDCReceive::ERetStatus CSDCReceive::SDCParam(CVector<_BINARY>* pbiData, CParameter& Parameter){ /* Calculate length of data field in bytes (consistant to table 61 in (6.4.1)) */ const int iLengthDataFieldBytes = (int) ((_REAL) (Parameter.iNumSDCBitsPerSFrame - 20) / 8); /* 20 bits from AFS index and CRC */ const int iUsefulBitsSDC = 20 + iLengthDataFieldBytes * 8; /* CRC ------------------------------------------------------------------ */ /* Check the CRC of this data block */ CRCObject.Reset(16); (*pbiData).ResetBitAccess(); /* Special treatment of SDC data stream: The CRC (Cyclic Redundancy Check) field shall contain a 16-bit CRC calculated over the AFS index coded in an 8-bit field (4 msbs are 0) and the data field. 4 MSBs from AFS-index. Insert four "0" in the data-stream */ const _BYTE byFirstByte = (_BYTE) (*pbiData).Separate(4); CRCObject.AddByte(byFirstByte); /* "- 4": Four bits already used, "/ SIZEOF__BYTE": We add bytes, not bits, "- 2": 16 bits for CRC at the end */ const int iNumBytesForCRCCheck = (iUsefulBitsSDC - 4) / SIZEOF__BYTE - 2; for (int i = 0; i < iNumBytesForCRCCheck; i++) CRCObject.AddByte((_BYTE) (*pbiData).Separate(SIZEOF__BYTE)); if (CRCObject.CheckCRC((*pbiData).Separate(16)) == TRUE) { /* CRC-check successful, extract data from SDC-stream --------------- */ int iLengthOfBody; _BOOLEAN bError = FALSE; /* Reset separation function */ (*pbiData).ResetBitAccess(); /* AFS index */ /* Reconfiguration index (not used by this application) */ (*pbiData).Separate(4); /* Init bit count and total number of bits for body */ int iBitsConsumed = 4; /* 4 bits for AFS index */ const int iTotNumBitsWithoutCRC = iUsefulBitsSDC - 16; /* Length of the body, excluding the initial 4 bits ("- 4"), measured in bytes ("/ 8"). With this condition also the error code of the "Separate" function is checked! (implicitly) Check for: -end tag, -error, -no more data available */ while (((iLengthOfBody = (*pbiData).Separate(7)) != 0) && (bError == FALSE) && (iBitsConsumed < iTotNumBitsWithoutCRC)) { /* Version flag */ _BOOLEAN bVersionFlag; if ((*pbiData).Separate(1) == 0) bVersionFlag = FALSE; else bVersionFlag = TRUE; /* Data entity type */ /* First calculate number of bits for this entity ("+ 4" because of: "The body of the data entities shall be at least 4 bits long. The length of the body, excluding the initial 4 bits, shall be signalled by the header") */ const int iNumBitsEntity = iLengthOfBody * 8 + 4; /* Call the routine for the signalled type */ switch ((*pbiData).Separate(4)) { case 0: /* Type 0 */ bError = DataEntityType0(pbiData, iLengthOfBody, Parameter); break; case 1: /* Type 1 */ bError = DataEntityType1(pbiData, iLengthOfBody, Parameter); break; case 3: /* Type 3 */ bError = DataEntityType3(pbiData, iLengthOfBody, Parameter, bVersionFlag); break; case 4: /* Type 4 */ bError = DataEntityType4(pbiData, iLengthOfBody, Parameter, bVersionFlag); break; case 5: /* Type 5 */ bError = DataEntityType5(pbiData, iLengthOfBody, Parameter); break; case 7: /* Type 7 */ bError = DataEntityType7(pbiData, iLengthOfBody, Parameter, bVersionFlag); break; case 8: /* Type 8 */ bError = DataEntityType8(pbiData, iLengthOfBody, Parameter); break; case 9: /* Type 9 */ bError = DataEntityType9(pbiData, iLengthOfBody, Parameter); break; default: /* This type is not supported, delete all bits of this entity from the queue */ (*pbiData).Separate(iNumBitsEntity); } /* Count number of bits consumed (7 for length, 1 for version flag, 4 for type = 12 plus actual entitiy body data) */ iBitsConsumed += 12 + iNumBitsEntity; } /* If error was detected, return proper error code */ if (bError == TRUE) return SR_BAD_DATA; else return SR_OK; /* everything was ok */ } else { /* Data is corrupted, do not use it. Return error code */ return SR_BAD_CRC; }}/******************************************************************************\* Data entity Type 0 (Multiplex description data entity) *\******************************************************************************/_BOOLEAN CSDCReceive::DataEntityType0(CVector<_BINARY>* pbiData, const int iLengthOfBody, CParameter& Parameter){ CParameter::CMSCProtLev MSCPrLe; int iLenPartA; int iLenPartB; /* The receiver may determine the number of streams present in the multiplex by dividing the length field of the header by three (6.4.3.1) */ const int iNumStreams = iLengthOfBody / 3; /* Check number of streams for overflow */ if (iNumStreams > MAX_NUM_STREAMS) return TRUE; /* Get protection levels */ /* Protection level for part A */ MSCPrLe.iPartA = (*pbiData).Separate(2); /* Protection level for part B */ MSCPrLe.iPartB = (*pbiData).Separate(2); /* Reset hierarchical flag (hierarchical present or not) */ _BOOLEAN bWithHierarch = FALSE; /* Get stream parameters */ for (int i = 0; i < iNumStreams; i++) { /* In case of hirachical modulation stream 0 describes the protection level and length of hierarchical data */ if ((i == 0) && ((Parameter.eMSCCodingScheme == CParameter::CS_3_HMSYM) || (Parameter.eMSCCodingScheme == CParameter::CS_3_HMMIX))) { /* Protection level for hierarchical */ MSCPrLe.iHierarch = (*pbiData).Separate(2); bWithHierarch = TRUE; /* rfu: these 10 bits shall be reserved for future use by the stream description field and shall be set to zero until they are defined */ if ((*pbiData).Separate(10) != 0) return TRUE; /* Data length for hierarchical */ iLenPartB = (*pbiData).Separate(12); /* Set new parameters in global struct. Lenght of part A is zero with hierarchical modulation */ Parameter.SetStreamLen(i, 0, iLenPartB); } else { /* Data length for part A */ iLenPartA = (*pbiData).Separate(12); /* Data length for part B */ iLenPartB = (*pbiData).Separate(12); /* Set new parameters in global struct */ Parameter.SetStreamLen(i, iLenPartA, iLenPartB); } } /* Set new parameters in global struct */ Parameter.SetMSCProtLev(MSCPrLe, bWithHierarch); return FALSE;}/******************************************************************************\* Data entity Type 1 (Label data entity) *\******************************************************************************/_BOOLEAN CSDCReceive::DataEntityType1(CVector<_BINARY>* pbiData, const int iLengthOfBody, CParameter& Parameter){ /* Short ID (the short ID is the index of the service-array) */ const int iTempShortID = (*pbiData).Separate(2); /* rfu: these 2 bits are reserved for future use and shall be set to zero until they are defined */ if ((*pbiData).Separate(2) != 0) return TRUE; /* Get label string ----------------------------------------------------- */ /* Check the following restriction to the length of label: "label: this is a variable length field of up to 64 bytes defining the label" */ if (iLengthOfBody <= 64) { /* Reset label string */ Parameter.Service[iTempShortID].strLabel = ""; /* Get all characters from SDC-stream */ for (int i = 0; i < iLengthOfBody; i++) { /* Get character */ const char cNewChar = (*pbiData).Separate(8); /* Append new character */ Parameter.Service[iTempShortID].strLabel.append(&cNewChar, 1); } return FALSE; } else return TRUE; /* error */}/******************************************************************************\* Data entity Type 3 (Alternative frequency signalling) *\******************************************************************************/_BOOLEAN CSDCReceive::DataEntityType3(CVector<_BINARY>* pbiData, const int iLengthOfBody, CParameter& Parameter, const _BOOLEAN bVersion){ int i; _BOOLEAN bSyncMultplxFlag; _BOOLEAN bEnhanceFlag; _BOOLEAN bServRestrFlag; _BOOLEAN bRegionSchedFlag; int iServRestr; /* Init number of frequency count */ int iNumFreqTmp = iLengthOfBody; /* Init region ID and schedule ID with "not used" parameters */ int iRegionID = 0; int iScheduleID = 0; /* Synchronous Multiplex flag: this flag indicates whether the multiplex is broadcast synchronously */ switch ((*pbiData).Separate(1)) { case 0: /* 0 */ /* Multiplex is not synchronous (different content and/or channel parameters and/or multiplex parameters and/or signal timing in target area) */ bSyncMultplxFlag = FALSE; break; case 1: /* 1 */ /* Multiplex is synchronous (identical content and channel parameters and multiplex parameters and signal timing in target area) */ bSyncMultplxFlag = TRUE; break; } /* Layer flag: this flag indicates whether the frequencies given apply to the base layer of the DRM multiplex or to the enhancement layer */ switch ((*pbiData).Separate(1)) { case 0: /* 0 */ /* Base layer */ bEnhanceFlag = FALSE; break; case 1: /* 1 */ /* Enhancement layer */ bEnhanceFlag = TRUE; break; } /* Service Restriction flag: this flag indicates whether all or just some of the services of the tuned multiplex are available in the DRM multiplex on the frequencies */ switch ((*pbiData).Separate(1)) { case 0: /* 0 */ /* All services in the tuned multiplex are available on the frequencies given */ bServRestrFlag = FALSE; break; case 1: /* 1 */ /* A restricted set of services are available on the frequencies given */ bServRestrFlag = TRUE; break; } /* Region/Schedule flag: this field indicates whether the list of frequencies is restricted by region and/or schedule or not */ switch ((*pbiData).Separate(1)) { case 0: /* 0 */ /* No restriction */ bRegionSchedFlag = FALSE; break; case 1: /* 1 */ /* Region and/or schedule applies to this list of frequencies */ bRegionSchedFlag = TRUE; break; } /* Service Restriction field: this 8 bit field is only present if the Service Restriction flag is set to 1 */ if (bServRestrFlag == TRUE) { /* Short Id flags 4 bits. This field indicates, which services (identified by their Short Id) of the tuned DRM multiplex are carried in the DRM multiplex on the alternative frequencies by setting the corresponding bit to 1 */ iServRestr = (*pbiData).Separate(4); /* rfa 4 bits. This field (if present) is reserved for future additions and shall be set to zero until it is defined */ if ((*pbiData).Separate(4) != 0) return TRUE; /* Remove one byte from frequency count */ iNumFreqTmp--; } /* Region/Schedule field: this 8 bit field is only present if the Region/Schedule flag is set to 1 */ if (bRegionSchedFlag == TRUE) { /* Region Id 4 bits. This field indicates whether the region is unspecified (value 0) or whether the alternative frequencies are valid just in certain geographic areas, in which case it carries the Region Id (value 1 to 15). The region may be described by one or more "Alternative frequency signalling: Region definition data entity - type 7" with this Region Id */ iRegionID = (*pbiData).Separate(4); /* Schedule Id 4 bits. This field indicates whether the schedule is unspecified (value 0) or whether the alternative frequencies are valid just at certain times, in which case it carries the Schedule Id (value 1 to 15). The schedule is described by one or more "Alternative frequency signalling: Schedule definition data entity - type 4" with this Schedule Id */ iScheduleID = (*pbiData).Separate(4); /* Remove one byte from frequency count */ iNumFreqTmp--; } /* Check for error (length of body must be so long to include Service Restriction field and Region/Schedule field, also check that remaining number of bytes is devidable by 2 since we read 16 bits) */ if ((iNumFreqTmp < 0) || (iNumFreqTmp % 2 != 0)) return TRUE; /* n frequencies: this field carries n 16 bit fields. n is in the range 1 to 16. The number of frequencies, n, is determined from the length field of the header and the value of the Service Restriction flag and the Region/Schedule flag */ const int iNumFreq = iNumFreqTmp / 2; /* 16 bits are read */ CVector<int> veciFrequencies(iNumFreq); for (i = 0; i < iNumFreq; i++) { /* rfu 1 bit. This field is reserved for future use of the frequency value field and shall be set to zero until defined */ if ((*pbiData).Separate(1) != 0) return TRUE; /* Frequency value 15 bits. This field is coded as an unsigned integer and gives the frequency in kHz */ veciFrequencies[i] = (*pbiData).Separate(15); } /* Now, set data in global struct */ /* Enhancement layer is not supported */ if (bEnhanceFlag == FALSE) { /* Check the version flag */ if (bVersion != Parameter.AltFreqSign.bVersionFlag) { /* If version flag is wrong, reset everything and save flag */ Parameter.AltFreqSign.Reset(); Parameter.AltFreqSign.bVersionFlag = bVersion; } /* Create temporary object and reset for initialization */ CParameter::CAltFreqSign::CAltFreq AltFreq; AltFreq.Reset(); /* Set some parameters */ AltFreq.bIsSyncMultplx = bSyncMultplxFlag; AltFreq.iRegionID = iRegionID; AltFreq.iScheduleID = iScheduleID; /* Set Service Restriction */ if (bServRestrFlag == TRUE) { /* The first bit (msb) refers to Short Id 3, while the last bit (lsb) refers to Short Id 0 of the tuned DRM multiplex */ for (i = 0; i < MAX_NUM_SERVICES; i++) { /* Mask last bit (lsb) */ AltFreq.veciServRestrict[i] = iServRestr & 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -