diff --git a/mythtv/libs/libmythtv/mpeg/mpegstreamdata.cpp b/mythtv/libs/libmythtv/mpeg/mpegstreamdata.cpp
index 1072d49..d4d2b65 100644
--- a/mythtv/libs/libmythtv/mpeg/mpegstreamdata.cpp
+++ b/mythtv/libs/libmythtv/mpeg/mpegstreamdata.cpp
@@ -15,7 +15,7 @@ void init_sections(sections_t &sect, uint last_section)
     uint endz = last_section >> 3;
     if (endz)
         sect.resize(endz, 0x00);
-    sect.resize(33 - endz, 0xff);
+    sect.resize(32, 0xff);
     sect[endz] = init_bits[last_section & 0x7];
 
 #if 0
@@ -668,6 +668,12 @@ void MPEGStreamData::HandleTSTables(const TSPacket* tspacket)
         DONE_WITH_PES_PACKET();
     }
 
+    if (!psip->VerifyPSIP(!_have_CRC_bug))
+    {
+        VERBOSE(VB_RECORD, "PSIP table is invalid");
+        DONE_WITH_PES_PACKET();
+    }
+
     // Don't decode redundant packets,
     // but if it is a desired PAT or PMT emit a "heartbeat" signal.
     if (IsRedundant(tspacket->PID(), *psip))
@@ -691,6 +697,7 @@ void MPEGStreamData::HandleTSTables(const TSPacket* tspacket)
     }
 
     HandleTables(tspacket->PID(), *psip);
+
     DONE_WITH_PES_PACKET();
 }
 #undef DONE_WITH_PES_PACKET
diff --git a/mythtv/libs/libmythtv/mpeg/mpegtables.cpp b/mythtv/libs/libmythtv/mpeg/mpegtables.cpp
index 1efe738..c4722a5 100644
--- a/mythtv/libs/libmythtv/mpeg/mpegtables.cpp
+++ b/mythtv/libs/libmythtv/mpeg/mpegtables.cpp
@@ -65,6 +65,176 @@ uint StreamID::Normalize(uint stream_id, const desc_list_t &desc)
     return stream_id;
 }
 
+bool PSIPTable::HasCRC(void) const
+{
+    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;
+
+        // 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;
+            }
+
+            // Dishnet Longterm EIT data
+            if (TableID::DN_EITbego <= TableID() &&
+                TableID() <= TableID::DN_EITendo)
+            {
+                has_crc = true;
+            }
+        }
+        break;
+    }
+
+    return has_crc;
+}
+
+bool PSIPTable::VerifyPSIP(bool verify_crc) const
+{
+    if (verify_crc && (CalcCRC() != CRC()))
+    {
+        VERBOSE(VB_SIPARSER,
+                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;
+        return (psipdata() + (pcnt << 2) + 3 < bufend);
+    }
+
+    if (TableID::PMT == TableID())
+    {
+        if (psipdata() + 3 >= bufend)
+        {
+            VERBOSE(VB_SIPARSER, "can't query program info length");
+            return false; // can't query program info length
+        }
+
+        if (psipdata() + Length() - 9 > bufend)
+        {
+            VERBOSE(VB_SIPARSER, "reported length to large");
+            return false; // reported length to large
+        }
+
+        uint proginfolen = ((psipdata()[2]<<8) | psipdata()[3]) & 0x0fff;
+        const unsigned char *proginfo = psipdata() + 4;
+        const unsigned char *cpos = proginfo + proginfolen;
+        if (cpos > bufend)
+        {
+            VERBOSE(VB_SIPARSER, "program info extends past end of buffer");
+            return false;
+        }
+
+        vector<unsigned char*> _ptrs;
+        const unsigned char *pos = cpos;
+        uint i = 0;
+        for (; pos < psipdata() + Length() - 9; i++)
+        {
+            const unsigned char *ptr = pos;
+            if (pos + 4 > bufend)
+            {
+                VERBOSE(VB_SIPARSER, QString("stream info %1 extends past "
+                                             "end of buffer").arg(i));
+                return false;
+            }
+            pos += 5 + ((ptr[3] << 8) | ptr[4]) & 0x0fff;
+        }
+        if (pos > bufend)
+        {
+            VERBOSE(VB_SIPARSER, QString("last stream info %1 extends past "
+                                         "end of buffer").arg(i));
+            return false;
+        }
+
+        return true;
+    }
+
+    return true;
+}
+
 ProgramAssociationTable* ProgramAssociationTable::CreateBlank(bool small)
 {
     (void) small; // currently always a small packet..
diff --git a/mythtv/libs/libmythtv/mpeg/mpegtables.h b/mythtv/libs/libmythtv/mpeg/mpegtables.h
index 0db147d..1065895 100644
--- a/mythtv/libs/libmythtv/mpeg/mpegtables.h
+++ b/mythtv/libs/libmythtv/mpeg/mpegtables.h
@@ -228,11 +228,72 @@ class TableID
         DIT      = 0x7e, // always on pid 0x1e
         SIT      = 0x7f, // always on pid 0x1f
 
+        // DVB Conditional Access
+        DVBCAbeg = 0x80,
+        DVBCAend = 0x8f,
+
         // Dishnet Longterm EIT data
         DN_EITbego = 0x80, // always on pid 0x300
         DN_EITendo = 0xfe, // always on pid 0x300
 
-        // ATSC
+        // ARIB
+        ARIBbeg  = 0x80,
+        ARIBend  = 0x8f,
+
+        // SCTE
+        PIM      = 0xC0, // Program Information Message (57 2003) PMT PID
+        PNM      = 0xC1, // Program Name Message (57 2003) PMT PID
+        NIM      = 0xC2, // Network Information Message (57 2003)
+                         // on Network PID (per PAT)
+        NITscte  = 0xC2, // Network Information Table (NIT) (65 2002) on 0x1FFC
+        NTM      = 0xC3, // Network Text Message (57 2003) on 0x1FFC
+                         // (terrestrial only, Map Name Table only) or
+                         // Network PID (per PAT)
+        NTT      = 0xC3, // Network Text Table (NTT) (65 2002) on 0x1FFC
+        VCM      = 0xC4, // Virtual Channel Message (57 2003) on 0x1FFC
+                         // (terrestrial only) or Network PID (per PAT)
+        SVCTscte = 0xC4, // Short Virtual Channel Table (65 2002) on 0x1FFC
+        STM      = 0xC5, // System Time Message (57 2003)
+                         // on Network PID (per PAT)
+        STTscte  = 0xC5, // System Time Table (STT) (65 2002) on 0x1FFC
+        SM       = 0xC6, // subtitle_message (27 2003)
+        MGTscte  = 0xC7, // Master Guide Table (57 2003) on 0x1ffc
+        LVCT     = 0xC9, // Long-form Virtual Channel Table (57 2003) on 0x1ffc
+        RRTscte  = 0xCA, // Region Rating Table (57 2003) on 0x1ffc
+
+        CEA      = 0xD8, // Cable Emergency Alert (18 2002)
+        ADET     = 0xD9, // Aggregate Data Event Table (80 2002)
+
+        // ATSC Conditional Access (A/70)
+        ECM0     = 0x80,
+        ECM1     = 0x81,
+        ECMbeg   = 0x82, // ECM begin private data
+        ECMend   = 0x8f, // ECM end private data
+
+        // ATSC main
+        MGT      = 0xC7, // Master Guide Table A/65 on 0x1ffb
+        TVCT     = 0xC8, // Terrestrial Virtual Channel Table A/65 on 0x1ffb
+        CVCT     = 0xC9, // Cable Virtual Channel Table A/65 on 0x1ffb
+        RRT      = 0xCA, // Region Rating Table A/65 on 0x1ffb
+        EIT      = 0xCB, // Event Information Table A/65 (per MGT)
+        ETT      = 0xCC, // Extended Text Table A/65 (per MGT)
+        STT      = 0xCD, // System Time Table A/65
+        DET      = 0xCE, // Data Event Table A/90 (per MGT)
+        DST      = 0xCF, // Data Service Table A/90
+
+        PIT      = 0xD0, // Program ID Table ???
+        NRT      = 0xD1, // Network Resources Table A/90
+        LTST     = 0xD2, // Long Term Service Table A/90
+        DCCT     = 0xD3, // Directed Channel Change Table A/57 on 0x1ffb
+        DCCSCT   = 0xD4, // DCC Selection Code Table A/57 on 0x1ffb
+        SITatsc  = 0xD5, // Selection Information Table (EIA-775.2 2000)
+        AEIT     = 0xD6, // Aggregate Event Information Table A/81
+        AETT     = 0xD7, // Aggregate Extended Text Table A/81
+        SVCT     = 0xDA, // Satellite VCT A/81
+
+        SRM      = 0xE0, // System Renewability Message (ATSC TSG-717r0)
+
+        // Unknown
         STUFFING = 0x80,
         CAPTION  = 0x86,
         CENSOR   = 0x87,
@@ -241,17 +302,6 @@ class TableID
         SRVLOC   = 0xA1,
         TSS      = 0xA2,
         CMPNAME  = 0xA3,
-
-        MGT      = 0xC7, // always on pid 0x1ffb
-        TVCT     = 0xC8,
-        CVCT     = 0xC9,
-        RRT      = 0xCA,
-        EIT      = 0xCB,
-        ETT      = 0xCC,
-        STT      = 0xCD,
-
-        DCCT     = 0xD3,
-        DCCSCT   = 0xD4,
     };
 };
 
@@ -358,6 +408,10 @@ class PSIPTable : public PESPacket
     // only for real ATSC PSIP tables, not similar MPEG2 tables
     void SetProtocolVersion(int ver) { pesdata()[8] = ver; }
 
+    bool HasCRC(void) const;
+
+    bool VerifyPSIP(bool verify_crc) const;
+
     const QString toString(void) const;
 
     static const uint PSIP_OFFSET = 8; // general PSIP header offset
@@ -625,7 +679,7 @@ class ConditionalAccessTable : public PSIPTable
     // for (i = 0; i < N; i++)      8.0      64
     //   { descriptor() }
     uint DescriptorsLength(void) const
-        { return SectionLength() - PSIP_OFFSET - (HasCRC() ? 4 : 0); }
+        { return SectionLength() - PSIP_OFFSET; }
     const unsigned char *Descriptors(void) const { return psipdata(); }
 
     // CRC_32 32 rpchof
diff --git a/mythtv/libs/libmythtv/mpeg/pespacket.h b/mythtv/libs/libmythtv/mpeg/pespacket.h
index f5a0c71..1198b1b 100644
--- a/mythtv/libs/libmythtv/mpeg/pespacket.h
+++ b/mythtv/libs/libmythtv/mpeg/pespacket.h
@@ -182,7 +182,7 @@ class PESPacket
     /// 1 bit  Additional Copy Info field is present
     bool HasACI()             const { return (_pesdata[4] & 0x4) >> 2; }
     /// 1 bit  Cyclic Redundancy Check present
-    bool HasCRC()             const { return (_pesdata[4] & 0x2) >> 1; }
+    virtual bool HasCRC()     const { return (_pesdata[4] & 0x2) >> 1; }
     /// 1 bit  Extension flags are present
     bool HasExtensionFlags()  const { return _pesdata[4] & 0x1; }
 
@@ -249,7 +249,7 @@ class PESPacket
 
     unsigned char *_pesdata;    ///< Pointer to PES data in full buffer
     unsigned char *_fullbuffer; ///< Pointer to allocated data
-  private:
+
     uint _psiOffset;    ///< AFCOffset + StartOfFieldPointer
     uint _ccLast;       ///< Continuity counter of last inserted TS Packet
     uint _pesdataSize;  ///< Number of data bytes (TS header + PES data)

