diff --git a/mythtv/libs/libmythtv/recorders/dtvrecorder.cpp b/mythtv/libs/libmythtv/recorders/dtvrecorder.cpp
index 8d3c7b9579..40a608e0b3 100644
--- a/mythtv/libs/libmythtv/recorders/dtvrecorder.cpp
+++ b/mythtv/libs/libmythtv/recorders/dtvrecorder.cpp
@@ -21,6 +21,7 @@
 #include "atscstreamdata.h"
 #include "mpegstreamdata.h"
 #include "dvbstreamdata.h"
+#include "dvbtables.h"
 #include "dtvrecorder.h"
 #include "programinfo.h"
 #include "mythlogging.h"
@@ -77,6 +78,9 @@ DTVRecorder::DTVRecorder(TVRec *rec) :
     // record 'raw' mpts?
     _record_mpts(0),
     _record_mpts_only(false),
+    // EIT timing
+    _is_running(false),
+    _is_following(false),
     // statistics
     _use_pts(false),
     _packet_count(0),
@@ -1625,4 +1629,79 @@ RecordingQuality *DTVRecorder::GetRecordingQuality(const RecordingInfo *r) const
     return recq;
 }
 
+void DTVRecorder::HandleEIT(const DVBEventInformationTable *eit)
+{
+    DVBStreamData *dsd = dynamic_cast<DVBStreamData*>(_stream_data);
+    if (dsd &&
+        TableID::PF_EIT == eit->TableID() &&
+        eit->ServiceID() == (uint) dsd->DesiredProgram() &&
+        eit->OriginalNetworkID() == dsd->DesiredNetworkID() &&
+        eit->TSID() == dsd->DesiredTransportID())
+    {
+        for (uint i = 0; i < eit->EventCount(); i++)
+        {
+            QString programId, recordingProgId, recordingTitle;
+            desc_list_t list = MPEGDescriptor::Parse(
+                eit->Descriptors(i), eit->DescriptorsLength(i));
+            desc_list_t contentIds =
+                MPEGDescriptor::FindAll(list, DescriptorID::dvb_content_identifier);
+            for (uint j = 0; j < contentIds.size(); j++)
+            {
+                DVBContentIdentifierDescriptor desc(contentIds[j]);
+                if (desc.ContentEncoding() == 0 &&
+                    (desc.ContentType() == 0x01 || desc.ContentType() == 0x31))
+                {
+                    programId = desc.ContentId();
+                }
+            }
+
+            if (curRecording)
+            {
+                recordingProgId = curRecording->GetProgramID();
+                recordingTitle = curRecording->GetTitle();
+            }
+            // The programid in curRecording will have the default authority at the start
+            // so we have a match if they end the same.
+            bool isMatch = false;
+            if (!programId.isEmpty() && !recordingProgId.isEmpty())
+                isMatch = recordingProgId.endsWith(programId.toLower());
+            else
+            {
+                // Fall back to matching on the title.
+                desc_list_t shortEvents =
+                    MPEGDescriptor::FindAll(list, DescriptorID::short_event);
+                for (uint j = 0; j < shortEvents.size(); j++)
+                {
+                    ShortEventDescriptor sed(shortEvents[j]);
+                    // The title may include a subtitle that has been removed
+                    // by a fixup.
+                    if (sed.EventName().startsWith(recordingTitle))
+                    {
+                        isMatch = true;
+                        break;
+                    }
+                }
+            }
+
+            if (eit->Section() == 0)
+            {
+                LOG(VB_GENERAL, LOG_INFO, LOC + QString("Current is now %1").arg(programId));
+                _is_running = isMatch;
+            }
+            else if (eit->Section() == 1)
+            {
+                LOG(VB_GENERAL, LOG_INFO, LOC + QString("Following is now %1").arg(programId));
+                _is_following = isMatch;
+            }
+            if (curRecording)
+            {
+                LOG(VB_GENERAL, LOG_INFO,
+                    LOC + QString("Recording for %1 (%2) running=%3, following=%4")
+                    .arg(curRecording->GetTitle()).arg(recordingProgId)
+                    .arg(_is_running).arg(_is_following));
+            }
+        }
+    }
+}
+
 /* vim: set expandtab tabstop=4 shiftwidth=4: */
diff --git a/mythtv/libs/libmythtv/recorders/dtvrecorder.h b/mythtv/libs/libmythtv/recorders/dtvrecorder.h
index 6874edbd54..14849f58b5 100644
--- a/mythtv/libs/libmythtv/recorders/dtvrecorder.h
+++ b/mythtv/libs/libmythtv/recorders/dtvrecorder.h
@@ -33,6 +33,7 @@ class DTVRecorder :
     public ATSCMainStreamListener,
     public TSPacketListener,
     public TSPacketListenerAV,
+    public DVBEITStreamListener,
     public PSStreamListener
 {
   public:
@@ -93,6 +94,10 @@ class DTVRecorder :
     // Common audio/visual processing
     bool ProcessAVTSPacket(const TSPacket &tspacket);
 
+    // EIT timing information
+    bool IsRunning(void) { return _is_running; }
+    bool IsFollowing(void) { return _is_following; }
+
   protected:
     virtual void InitStreamData(void);
 
@@ -127,6 +132,9 @@ class DTVRecorder :
     virtual void SetCAMPMT(const ProgramMapTable*) {}
     virtual void UpdateCAMTimeOffset(void) {}
 
+    void HandleEIT(const DVBEventInformationTable*) override;
+    void HandleEIT(const PremiereContentInformationTable*) override {}
+
     // file handle for stream
     int _stream_fd;
 
@@ -181,6 +189,10 @@ class DTVRecorder :
     unsigned char _continuity_counter[0x1fff + 1];
     vector<TSPacket> _scratch;
 
+    // EIT timing
+    bool _is_running;
+    bool _is_following;
+
     // Statistics
     int           _minimum_recording_quality;
     bool          _use_pts; // vs use dts
diff --git a/mythtv/libs/libmythtv/recorders/dvbrecorder.cpp b/mythtv/libs/libmythtv/recorders/dvbrecorder.cpp
index fac5b4a76a..9e86c1e224 100644
--- a/mythtv/libs/libmythtv/recorders/dvbrecorder.cpp
+++ b/mythtv/libs/libmythtv/recorders/dvbrecorder.cpp
@@ -24,6 +24,7 @@
 // MythTV includes
 #include "dvbstreamhandler.h"
 #include "mpegstreamdata.h"
+#include "dvbstreamdata.h"
 #include "tsstreamdata.h"
 #include "dvbrecorder.h"
 #include "dvbchannel.h"
@@ -119,6 +120,10 @@ void DVBRecorder::run(void)
     if (_record_mpts_only)
         _stream_data->AddListeningPID(0x2000);
 
+    DVBStreamData *dsd = dynamic_cast<DVBStreamData*>(_stream_data);
+    if (dsd)
+        dsd->AddDVBEITListener(this);
+
     StartNewFile();
 
     _stream_data->AddAVListener(this);
@@ -126,6 +131,17 @@ void DVBRecorder::run(void)
     _stream_handler->AddListener(_stream_data, false, true,
                          (_record_mpts) ? ringBuffer->GetFilename() : QString());
 
+    QString recordingProgId = QString("?");
+    QString recordingTitle = QString("?");
+    if (curRecording)
+    {
+        recordingProgId = curRecording->GetProgramID();
+        recordingTitle = curRecording->GetTitle();
+    }
+    LOG(VB_GENERAL, LOG_INFO, LOC + QString("Recording %1 (%2) service %3 net %4 transport %5")
+        .arg(recordingTitle).arg(recordingProgId).arg(dsd->DesiredProgram())
+        .arg(dsd->DesiredNetworkID()).arg(dsd->DesiredTransportID()));
+
     while (IsRecordingRequested() && !IsErrored())
     {
         if (PauseAndWait())
@@ -158,6 +174,9 @@ void DVBRecorder::run(void)
     _stream_data->RemoveWritingListener(this);
     _stream_data->RemoveAVListener(this);
 
+    if (dsd)
+        dsd->RemoveDVBEITListener(this);
+
     Close();
 
     FinishRecording();
diff --git a/mythtv/libs/libmythtv/tv_rec.cpp b/mythtv/libs/libmythtv/tv_rec.cpp
index 421aff6823..52d5fb4fc3 100644
--- a/mythtv/libs/libmythtv/tv_rec.cpp
+++ b/mythtv/libs/libmythtv/tv_rec.cpp
@@ -116,6 +116,8 @@ TVRec::TVRec(int _inputid)
       // Current recording info
       curRecording(nullptr),
       overrecordseconds(0),
+      eitIsRunning(false),
+      eitIsFollowing(false),
       // Pseudo LiveTV recording
       pseudoLiveTVRecording(nullptr),
       nextLiveTVDir(""),            nextLiveTVDirLock(),
@@ -1347,6 +1349,22 @@ void TVRec::run(void)
         // Tell frontends about pending recordings
         HandlePendingRecordings();
 
+        bool isRunning = false;
+        bool isFollowing = false;
+        if (GetDTVRecorder())
+        {
+            isRunning = GetDTVRecorder()->IsRunning();
+            isFollowing = GetDTVRecorder()->IsFollowing();
+        }
+        if (isRunning && eitIsFollowing && ! eitIsRunning)
+        {
+            // Set a bookmark at the transition from Following to Present.
+            if (curRecording)
+                curRecording->SaveBookmark(GetFramesWritten());
+        }
+        eitIsRunning = isRunning;
+        eitIsFollowing = isFollowing;
+
         // If we are recording a program, check if the recording is
         // over or someone has asked us to finish the recording.
         // Add an extra 60 seconds to the recording end time if we
@@ -1354,9 +1372,20 @@ void TVRec::run(void)
         QDateTime recEnd = (!pendingRecordings.empty()) ?
             recordEndTime.addSecs(60) : recordEndTime;
         if ((GetState() == kState_RecordingOnly) &&
-            (MythDate::current() > recEnd ||
+            ((MythDate::current() > recEnd && !isRunning) ||
              HasFlags(kFlagFinishRecording)))
         {
+            QDateTime actualTime = QDateTime::currentDateTime();
+            QString title;
+            if (curRecording)
+                title = curRecording->GetTitle();
+            if (actualTime > recordEndTime.addSecs(10))
+                LOG(VB_GENERAL, LOG_INFO,
+                    QString("Extended end time of recording of %1 from %2 to %3")
+                        .arg(title)
+                        .arg(recordEndTime.toString("hh:mm:ss"))
+                        .arg(actualTime.toString("hh:mm:ss")));
+
             ChangeState(kState_None);
             ClearFlags(kFlagFinishRecording, __FILE__, __LINE__);
         }
diff --git a/mythtv/libs/libmythtv/tv_rec.h b/mythtv/libs/libmythtv/tv_rec.h
index 3d8321a339..0acd4536b8 100644
--- a/mythtv/libs/libmythtv/tv_rec.h
+++ b/mythtv/libs/libmythtv/tv_rec.h
@@ -410,6 +410,8 @@ class MTV_PUBLIC TVRec : public SignalMonitorListener, public QRunnable
     QDateTime    recordEndTime;
     QHash<QString,int> autoRunJobs; // RecordingInfo::MakeUniqueKey()->autoRun
     int          overrecordseconds;
+    bool         eitIsRunning;
+    bool         eitIsFollowing;
 
     // Pending recording info
     PendingMap   pendingRecordings;
