]> git.vomp.tv Git - vompclient.git/commitdiff
Subtitle timeout patch, provided by JTE
authorMarten Richter <marten.richter@freenet.de>
Mon, 8 Oct 2012 06:10:08 +0000 (08:10 +0200)
committerMarten Richter <marten.richter@freenet.de>
Mon, 8 Oct 2012 06:10:08 +0000 (08:10 +0200)
dvbsubtitles.cc
dvbsubtitles.h

index b0da569e0299d22e3abaa597851042f117453438..5210d7e2d32da103666f91b1725075cafbe000a5 100644 (file)
 #include "video.h"
 #include "log.h"
 
+// --- cTimeMs ---------------------------------------------------------------
+// Borrowed from the vdr tools
+
+cTimeMs::cTimeMs(int Ms)
+{
+  if (Ms >= 0)
+     Set(Ms);
+  else
+     begin = 0;
+     isFirstCheck = false;
+}
+
+uint64_t cTimeMs::Now(void)
+{
+  struct timespec tp;
+#ifndef WIN32
+  if (clock_gettime(CLOCK_REALTIME, &tp) == 0)
+    return (uint64_t(tp.tv_sec)) * 1000 + tp.tv_nsec / 1000000;
+  else
+    Log::getInstance()->log("SUBTITLES", Log::DEBUG, "cTimeMs: clock_gettime(CLOCK_REALTIME) failed");
+
+#else
+  SYSTEMTIME systime;
+   __int64  filetime;
+   __int64  test;
+  GetSystemTime(&systime);
+  SystemTimeToFileTime(&systime,(FILETIME*)&filetime);
+  tp.tv_sec=(filetime-WINDOWS_TIME_BASE_OFFSET)/(10*1000*1000);
+  tp.tv_nsec=((filetime-WINDOWS_TIME_BASE_OFFSET)%(10*1000*1000))*100;
+  return (uint64_t(tp.tv_sec)) * 1000 + tp.tv_nsec / 1000000;
+#endif
+}
+
+void cTimeMs::Set(int Ms)
+{
+  isFirstCheck = true; // Timer set, the first check can be done once
+  begin = Now() + Ms;
+}
+
+bool cTimeMs::TimedOut(void)
+{
+  if (isFirstCheck && (Now() >= begin))
+  {
+    isFirstCheck = false; // Timer timed out & the first check is done
+    return true;
+  }
+  else
+    return false;
+}
+
+uint64_t cTimeMs::Elapsed(void)
+{
+  return Now() - begin;
+}
+
+cTimeMs SubtitleTimeout;
+//-------- End of cTimeMs borrowed from the vdr tools --------
+
 DVBSubtitleCLUT::DVBSubtitleCLUT()
 : version(0xFF),
   palette2(2),
@@ -167,9 +225,10 @@ DVBSubtitlePage::DVBSubtitlePage()
 void DVBSubtitlePage::setState(UCHAR s)
 {
   state = s;
-  if (state == 1)
+  if (state == 1) // Acquisition point - page refresh
     serviceAcquired = true;
-  if (state == 2) // Mode change
+    regions.clear();
+  if (state == 2) // Mode change - new epoch
   {
     serviceAcquired = true;
     dirty = true;
@@ -749,6 +808,9 @@ void DVBSubtitles::finishPage(const DVBSubtitlePage& page)
     Log::getInstance()->log("SUBTITLES", Log::DEBUG, "Display region %d", i->first);
     osd->drawOSDBitmap(i->second.x, i->second.y, region_iter->second,dds);
   }
+// after displaying regions set the page timeout timer
+  SubtitleTimeout.Set(page.timeout * 1000);
+  Log::getInstance()->log("SUBTITLES", Log::DEBUG, "SubtitleTimeout %d", page.timeout);
 }
 
 void DVBSubtitles::lockInput()
@@ -869,13 +931,34 @@ void DVBSubtitles::nudge()
 #endif
 }
 
+#define SUBTITLE_TIMEOUT_MS 750 
+// How often do we check if subtitles have been timed out.
+
 void DVBSubtitles::threadMethod()
 {
   struct timespec sleeptime;
   sleeptime.tv_sec = 0;
   sleeptime.tv_nsec = 0;
+  uint64_t wakeup = 0;
   while (1)
   {
+    if (SubtitleTimeout.TimedOut())  // do we have a subtitle timeout
+    {
+      lockOutput();
+      if(showing)
+       osd->clearOSD();      // if we have the timeout, lets clear the OSD
+      unlockOutput();
+    }
+    else                    // if not lets check when will we have it
+    {
+       wakeup = -(SubtitleTimeout.Elapsed());
+       if (wakeup > 0 && sleeptime.tv_nsec == 0 && sleeptime.tv_sec == 0)
+       // We are not done, we still have a Subtitle Timeout!
+       {
+         sleeptime.tv_sec = (int)(wakeup / 1000);
+         sleeptime.tv_nsec = (long)(wakeup % 1000) * 10000L / 1000L * 100000L;
+       }
+    }
     threadCheckExit();
     threadLock();
     if (!threadNudged)
@@ -914,6 +997,7 @@ void DVBSubtitles::threadMethod()
     threadUnlock();
     bool finished = false;
     ULLONG nowPTS, pktPTS;
+    int wait;
     while (!finished)
     {
       threadCheckExit();
@@ -952,19 +1036,24 @@ void DVBSubtitles::threadMethod()
       }
     }
     // Calculate how long to sleep for
+    wait = SUBTITLE_TIMEOUT_MS; // Max sleep while checking subtitle timeout 
     sleeptime.tv_sec = 0;
     sleeptime.tv_nsec = 0;
     if (pktPTS != PESPacket::PTS_INVALID)
     { // A future action exists
       nowPTS = Video::getInstance()->getCurrentTimestamp();
       ULLONG diff = PTSDifference(pktPTS, nowPTS);
-      sleeptime.tv_sec = diff / 90000;
-      sleeptime.tv_nsec = (long)(diff % 90000) * 10000L / 90000L * 100000L;
-      if (sleeptime.tv_sec > 60)
-      { // We have a problem. An action so far in the future should have
+      diff /= 90; // convert diff in ms as PTS difference in 1/90000s
+      if (diff < 60 * 1000)
+      {
+        if (diff < (ULLONG)wait)
+          wait = (int)diff;
+        sleeptime.tv_nsec = (long)(wait % 1000) * 10000L / 1000L * 100000L;
+      }
+      else
+        { // We have a problem. An action so far in the future should have
         // been culled. Probably the action is already due and PTSDifference
         // wrapped around. Therefore we sleep for a minimal time instead.
-        sleeptime.tv_sec = 0;
         sleeptime.tv_nsec = 1;
       }
     }
index db6575006e174d927f475424fd5fc0325066c1c1..1fb44527978690e5401e67f7f7700b829950c10d 100644 (file)
 
 #include "bitmap.h"
 #include "demuxer.h"
+#include "inttypes.h"
 #include <ctime>
 #include <vector>
 #include <deque>
 #include <map>
 
+class cTimeMs {
+  private:
+    uint64_t begin;
+    bool isFirstCheck;
+  public:
+    cTimeMs(int Ms = 0);
+        ///< Creates a timer with ms resolution and an initial timeout of Ms.
+        ///< If Ms is negative the timer is not initialized with the current
+        ///< time.
+    static uint64_t Now(void);
+    void Set(int Ms = 0);
+    bool TimedOut(void);
+    uint64_t Elapsed(void);
+};
+
 class OSDReceiver;
 
 class DVBSubtitleCLUT