Ticket #11739: eit_ett_staleness_fix_20151120.patch

File eit_ett_staleness_fix_20151120.patch, 8.1 KB (added by carlpny <carlpny@…>, 4 years ago)

Proposed bug fix for EIT/ETT mismatched.

  • mythtv/libs/libmythtv/eithelper.cpp

    From 60b8e825bb5bcbb6bd56063a62f14df91d541f1f Mon Sep 17 00:00:00 2001
    From: carlpny
    Date: Fri, 20 Nov 2015 00:07:26 -0800
    Subject: [PATCH 1/2] Fix for EIT and ETT mismatch.
    
    ---
     mythtv/libs/libmythtv/eithelper.cpp | 56 +++++++++++++++++++++++++++----------
     mythtv/libs/libmythtv/eithelper.h   | 45 ++++++++++++++++++++++-------
     2 files changed, 77 insertions(+), 24 deletions(-)
    
    diff --git a/mythtv/libs/libmythtv/eithelper.cpp b/mythtv/libs/libmythtv/eithelper.cpp
    index ab14a71..04035ca 100644
    a b void EITHelper::AddEIT(uint atsc_major, uint atsc_minor, 
    159159                     eit->title(i).GetBestMatch(languagePreferences),
    160160                     eit->Descriptors(i), eit->DescriptorsLength(i));
    161161
     162        // Look to see if there has been a recent ett message with the same event id.
    162163        EventIDToETT::iterator it = etts.find(eit->EventID(i));
    163 
     164        QString ett_text = QString::null;
     165        bool found_matching_ett = false;
    164166        if (it != etts.end())
    165167        {
    166             CompleteEvent(atsc_major, atsc_minor, ev, *it);
     168            // Don't use an ett description if it was scanned long in the past.
     169            if (!it->IsStale()) {
     170              ett_text = it->ett_text;
     171              found_matching_ett = true;
     172            }
    167173            etts.erase(it);
    168174        }
    169         else if (!ev.etm)
     175
     176        // Create an event immediately if a matching ett description was found,
     177        // or if item is false, indicating that no ett description should be
     178        // expected.
     179        if (found_matching_ett || !ev.etm)
    170180        {
    171             CompleteEvent(atsc_major, atsc_minor, ev, QString::null);
     181            CompleteEvent(atsc_major, atsc_minor, ev, ett_text);
    172182        }
    173183        else
    174184        {
    175185            unsigned char *tmp = new unsigned char[ev.desc_length];
    176186            memcpy(tmp, eit->Descriptors(i), ev.desc_length);
    177187            ev.desc = tmp;
    178             events[eit->EventID(i)] = ev;
     188            events.insert(eit->EventID(i), ev);
    179189        }
    180190    }
    181191}
    void EITHelper::AddETT(uint atsc_major, uint atsc_minor, 
    184194                       const ExtendedTextTable *ett)
    185195{
    186196    uint atsc_key = (atsc_major << 16) | atsc_minor;
    187     // Try to complete an Event
     197    // Try to match up the ett with an eit event.
    188198    ATSCSRCToEvents::iterator eits_it = incomplete_events.find(atsc_key);
    189199    if (eits_it != incomplete_events.end())
    190200    {
    191201        EventIDToATSCEvent::iterator it = (*eits_it).find(ett->EventID());
    192202        if (it != (*eits_it).end())
    193203        {
    194             CompleteEvent(
    195                 atsc_major, atsc_minor, *it,
    196                 ett->ExtendedTextMessage().GetBestMatch(languagePreferences));
     204            bool completed_event = false;
     205            // Only consider eit events from the recent past.
     206            if (!it->IsStale()) {
     207              completed_event = true;
     208              CompleteEvent(
     209                  atsc_major, atsc_minor, *it,
     210                  ett->ExtendedTextMessage().GetBestMatch(languagePreferences));
     211            }
    197212
    198213            if ((*it).desc)
    199214                delete [] (*it).desc;
    200215
    201216            (*eits_it).erase(it);
    202217
    203             return;
     218            if (completed_event) return;
    204219        }
    205220    }
    206221
    207     // Couldn't find matching EIT. If not yet in unmatched ETT map, insert it.
     222    // Report if an unmatched ett was previously noted and overwrite it.
     223    // See also https://code.mythtv.org/trac/ticket/11739
    208224    EventIDToETT &elist = unmatched_etts[atsc_key];
    209     if (elist.find(ett->EventID()) == elist.end())
     225    EventIDToETT::iterator existing_unmatched_ett_it =
     226        elist.find(ett->EventID());
     227    const QString next_ett_text = ett->ExtendedTextMessage()
     228        .GetBestMatch(languagePreferences);
     229    if (existing_unmatched_ett_it != elist.end() &&
     230        existing_unmatched_ett_it->ett_text != next_ett_text)
    210231    {
    211         elist[ett->EventID()] = ett->ExtendedTextMessage()
    212             .GetBestMatch(languagePreferences);
     232       LOG(VB_EIT, LOG_INFO, LOC +
     233           QString("Overwriting previously unmatched ett. stale: %1 major: %2 "
     234                   "minor: %3 old ett: %4  new ett: %5")
     235               .arg(existing_unmatched_ett_it->IsStale())
     236               .arg(atsc_major)
     237               .arg(atsc_minor)
     238               .arg(existing_unmatched_ett_it->ett_text)
     239               .arg(next_ett_text));
    213240    }
     241    elist.insert(ett->EventID(), ATSCEtt(next_ett_text));
    214242}
    215243
    216244static void parse_dvb_event_descriptors(desc_list_t list, uint fix,
  • mythtv/libs/libmythtv/eithelper.h

    diff --git a/mythtv/libs/libmythtv/eithelper.h b/mythtv/libs/libmythtv/eithelper.h
    index a60e5d5..903235e 100644
    a b  
    1717
    1818class MSqlQuery;
    1919
     20// An entry from the EIT table containing event details.
    2021class ATSCEvent
    2122{
    2223  public:
    23     /// This empty constructor is needed for the QMap<> to work, it is
    24     /// not intended to be used to initialize an ATSC Event.
    25     /// Since we immediately initialize the value inserted into the
    26     /// QMap this is safe in that use.
    27     ATSCEvent() : start_time(0), length(0), etm(0), desc_length(0), desc(NULL) {}
    28     /// This is the only valid constructor for ATSCEvent.
    2924    ATSCEvent(uint a, uint b, uint c, QString d,
    3025              const unsigned char *e, uint f)
    31         : start_time(a), length(b), etm(c), desc_length(f), title(d), desc(e)
    32     {
     26        : start_time(a), length(b), etm(c), desc_length(f), title(d), desc(e),
     27          scan_time(time(NULL)) {}
     28
     29    bool IsStale() const {
     30      // The minimum recommended repetition time for EIT events according to
     31      // http://atsc.org/wp-content/uploads/2015/03/Program-and-system-information-protocol-implementation-guidelines-for-broadcaster.pdf
     32      // is one minute. Consider any EIT event seen > 2 minutes in the past as stale.
     33      return scan_time + 2 * 60 < time(NULL);
    3334    }
    3435
    35   public:
    3636    uint32_t start_time;
    3737    uint32_t length;
    3838    uint32_t etm;
    3939    uint32_t desc_length;
    4040    QString  title;
    4141    const unsigned char *desc;
     42
     43  private:
     44    // The time the event was created.
     45    time_t scan_time;
    4246};
    4347
     48// An entry from the ETT table containing description text for an event.
     49class ATSCEtt
     50{
     51  public:
     52    explicit ATSCEtt(QString text) : ett_text(text), scan_time(time(NULL)) {}
     53
     54    bool IsStale() const {
     55      // The minimum recommended repetition time for ETT events according to
     56      // http://atsc.org/wp-content/uploads/2015/03/Program-and-system-information-protocol-implementation-guidelines-for-broadcaster.pdf
     57      // is one minute. Consider any ETT event seen > 2 minutes in the past as stale.
     58      return scan_time + 2 * 60 < time(NULL);
     59    }
     60
     61    QString ett_text;
     62
     63  private:
     64    // The time the ETT was created.
     65    time_t scan_time;
     66};
     67
     68
    4469typedef QMap<uint,ATSCEvent>               EventIDToATSCEvent;
    45 typedef QMap<uint,QString>                 EventIDToETT;
     70typedef QMap<uint,ATSCEtt>                 EventIDToETT;
    4671typedef QMap<uint,EventIDToATSCEvent>      ATSCSRCToEvents;
    4772typedef QMap<uint,EventIDToETT>            ATSCSRCToETTs;
    4873typedef QMap<unsigned long long,uint>      ServiceToChanID;
  • mythtv/libs/libmythtv/eithelper.cpp

    -- 
    2.5.0
    
    
    From ed9ccf18022f7d241209c25639408a582fed6a9e Mon Sep 17 00:00:00 2001
    From: carlpny <carlpny@gmail.com>
    Date: Fri, 20 Nov 2015 09:33:36 -0800
    Subject: [PATCH 2/2] Change LOG to DEBUG.
    
    ---
     mythtv/libs/libmythtv/eithelper.cpp | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/mythtv/libs/libmythtv/eithelper.cpp b/mythtv/libs/libmythtv/eithelper.cpp
    index 04035ca..58ea61f 100644
    a b void EITHelper::AddETT(uint atsc_major, uint atsc_minor, 
    229229    if (existing_unmatched_ett_it != elist.end() &&
    230230        existing_unmatched_ett_it->ett_text != next_ett_text)
    231231    {
    232        LOG(VB_EIT, LOG_INFO, LOC +
     232       LOG(VB_EIT, LOG_DEBUG, LOC +
    233233           QString("Overwriting previously unmatched ett. stale: %1 major: %2 "
    234234                   "minor: %3 old ett: %4  new ett: %5")
    235235               .arg(existing_unmatched_ett_it->IsStale())