#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),
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;
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()
#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)
threadUnlock();
bool finished = false;
ULLONG nowPTS, pktPTS;
+ int wait;
while (!finished)
{
threadCheckExit();
}
}
// 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;
}
}