bool PSIPTable::HasSectionNumber(void) const { bool has_sn = false; switch (TableID()) { // MPEG case TableID::PAT: case TableID::CAT: case TableID::PMT: // ATSC case TableID::MGT: case TableID::TVCT: case TableID::CVCT: case TableID::RRT: case TableID::EIT: case TableID::ETT: case TableID::STT: case TableID::DET: case TableID::DST: has_sn = true; break; } return has_sn; }
QString VirtualChannelTable::toStringXML(uint indent_level) const { QString indent_0 = xml_indent(indent_level); QString indent_1 = xml_indent(indent_level + 1); QString indent_2 = xml_indent(indent_level + 2); QString section_name = QString("%1VirtualChannelSection") .arg((TableID::TVCT == TableID()) ? "Terrestrial" : "Cable"); QString mapid; if (TableID::CVCT == TableID()) { uint sctemapid = (pesdata()[3]<<8) | pesdata()[4]; mapid = QString(" mapid=\"0x%1\"").arg(sctemapid,4,16,QChar('0')); } QString str = QString("%1<%2 tsid=\"0x%3\" channel_count=\"%4\"" "\n%5global_descriptors_length=\"%6\"%7" "\n%8%9>\n") .arg(indent_0) .arg(section_name) .arg(TransportStreamID(),4,16,QChar('0')) .arg(ChannelCount()) .arg(indent_1) .arg(GlobalDescriptorsLength()) .arg(mapid) .arg(indent_1) .arg(PSIPTable::XMLValues(indent_level + 1)); vector<const unsigned char*> gdesc = MPEGDescriptor::Parse(GlobalDescriptors(), GlobalDescriptorsLength()); for (uint i = 0; i < gdesc.size(); i++) { str += MPEGDescriptor(gdesc[i], 300) .toStringXML(indent_level + 1) + "\n"; } for (uint i = 0; i < ChannelCount(); i++) str += ChannelStringXML(indent_level + 1, i) + "\n"; return str + indent_0 + QString("</%1>").arg(section_name); }
QString VirtualChannelTable::toString(void) const { QString str; str.append(QString("%1 Virtual Channel Section\n%2" " channel_count(%3) tsid(0x%4)") .arg((TableID::TVCT == TableID()) ? "Terrestrial":"Cable") .arg(PSIPTable::toString()) .arg(ChannelCount()) .arg(TransportStreamID(),4,16,QChar('0'))); if (TableID::CVCT == TableID()) { uint sctemapid = (pesdata()[3]<<8) | pesdata()[4]; str.append(QString(" mapid(0x%1)").arg(sctemapid,0,16)); } str.append("\n"); for (uint i = 0; i < ChannelCount(); i++) str.append(ChannelString(i)); if (0 != GlobalDescriptorsLength()) { str.append(QString("global descriptors length(%1) ") .arg(GlobalDescriptorsLength())); vector<const unsigned char*> desc = MPEGDescriptor::Parse(GlobalDescriptors(), GlobalDescriptorsLength()); str.append(QString("count: %1\n").arg(desc.size())); for (uint i = 0; i < desc.size(); i++) { str.append(QString(" %1\n") .arg(MPEGDescriptor(desc[i]).toString())); } } return str; }
bool PSIPTable::VerifyPSIP(bool verify_crc) const { if (verify_crc && (CalcCRC() != CRC())) { LOG(VB_SIPARSER, LOG_ERR, QString("PSIPTable: Failed CRC check 0x%1 != 0x%2 " "for StreamID = 0x%3") .arg(CRC(),0,16).arg(CalcCRC(),0,16).arg(StreamID(),0,16)); return false; } unsigned char *bufend = _fullbuffer + _allocSize; if ((_pesdata + 2) >= bufend) return false; // can't query length if (psipdata() >= bufend) return false; // data outside buffer if (TableID::PAT == TableID()) { uint pcnt = (SectionLength() - PSIP_OFFSET - 2) >> 2; bool ok = (psipdata() + (pcnt << 2) + 3 < bufend); if (!ok) { LOG(VB_SIPARSER, LOG_ERR, "PSIPTable: PAT: program list extends past end of buffer"); return false; } if ((Length() == 0xfff) && (TableIDExtension() == 0xffff) && (Section() == 0xff) && (LastSection() == 0xff)) { LOG(VB_SIPARSER, LOG_ERR, "PSIPTable: PAT: All values at maximums"); return false; } return true; }
bool PSIPTable::HasCRC(void) const { // default is false, but gets set to true for 0x80-0xfe at the end! bool has_crc = false; switch (TableID()) { // MPEG case TableID::PAT: case TableID::CAT: case TableID::PMT: has_crc = true; break; // case TableID::TSDT // DVB manditory case TableID::NIT: case TableID::SDT: case TableID::PF_EIT: has_crc = true; break; case TableID::TDT: has_crc = false; break; // DVB optional case TableID::NITo: case TableID::SDTo: case TableID::BAT: case TableID::PF_EITo: has_crc = true; break; case TableID::RST: case TableID::ST: has_crc = false; break; case TableID::TOT: has_crc = true; break; // case TableID::RNT: // case TableID::CT: // case TableID::RCT: // case TableID::CIT: // case TableID::MPEFEC: case TableID::DIT: has_crc = false; break; case TableID::SIT: has_crc = true; break; // SCTE case TableID::NITscte: case TableID::NTT: case TableID::SVCTscte: case TableID::STTscte: case TableID::SITscte: has_crc = true; break; case TableID::ADET: has_crc = false; break; // ATSC case TableID::MGT: case TableID::TVCT: case TableID::CVCT: case TableID::RRT: case TableID::EIT: case TableID::ETT: case TableID::STT: case TableID::DET: case TableID::DST: //case TableID::PIT: case TableID::NRT: case TableID::LTST: case TableID::DCCT: case TableID::DCCSCT: //case TableID::SITatsc: case TableID::AEIT: case TableID::AETT: case TableID::SVCT: has_crc = true; break; default: { // DVB Longterm EIT data if (TableID::SC_EITbeg <= TableID() && TableID() <= TableID::SC_EITendo) { has_crc = true; } // FIXME Dishnet Longterm EIT data, only on PID 0x300! Forces // table_id 0x80-0xfe to true, unless handled before or after! if (TableID::DN_EITbego <= TableID() && TableID() <= TableID::DN_EITendo) { has_crc = true; } // ATSC/DVB conditional access ECM/EMM, reset to false after Dishnet if (TableID::ECM0 <= TableID() && TableID() <= TableID::ECMend) { has_crc = false; } } break; } return has_crc; }