From 4326ebc113287dbad10a193bab94544c643e051a Mon Sep 17 00:00:00 2001 From: Marten Richter Date: Mon, 8 Oct 2012 08:10:08 +0200 Subject: [PATCH] Subtitle timeout patch, provided by JTE --- dvbsubtitles.cc | 103 ++++++++++++++++++++++++++++++++++++++++++++---- dvbsubtitles.h | 16 ++++++++ 2 files changed, 112 insertions(+), 7 deletions(-) diff --git a/dvbsubtitles.cc b/dvbsubtitles.cc index b0da569..5210d7e 100644 --- a/dvbsubtitles.cc +++ b/dvbsubtitles.cc @@ -32,6 +32,64 @@ #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; } } diff --git a/dvbsubtitles.h b/dvbsubtitles.h index db65750..1fb4452 100644 --- a/dvbsubtitles.h +++ b/dvbsubtitles.h @@ -25,11 +25,27 @@ #include "bitmap.h" #include "demuxer.h" +#include "inttypes.h" #include #include #include #include +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 -- 2.39.2