]> git.vomp.tv Git - vompclient.git/commitdiff
WIP: DVBSubtitles new timing loop, std::thread/cond and std::chrono
authorChris Tallon <chris@vomp.tv>
Tue, 3 Mar 2020 15:39:03 +0000 (15:39 +0000)
committerChris Tallon <chris@vomp.tv>
Tue, 3 Mar 2020 15:39:03 +0000 (15:39 +0000)
13 files changed:
boxstack.cc
demuxerts.cc
dvbsubtitles.cc
dvbsubtitles.h
main.cc
playerlivetv.cc
playerlivetv.h
playervideorec.cc
vdr.cc
vrecordinglist.h
vrecordinglistadvanced.h
vrecordinglistclassic.h
vvideorec.cc

index abfbb91ba7352141132541932c2def53c62f331b..f145525b8619de729842e95faa0f7554b0a719d2 100644 (file)
@@ -224,10 +224,10 @@ void BoxStack::redrawAllBoxes()
 
 void BoxStack::update(Boxx* toUpdate, Region* regionToUpdate)
 {
-  Log::getInstance()->log("BoxStack", Log::DEBUG, "Update called");
+//  Log::getInstance()->log("BoxStack", Log::DEBUG, "Update called");
   if (!initted) return; // it is allowed to call this before init
   boxLock.lock();
-  Log::getInstance()->log("BoxStack", Log::DEBUG, "Locked for update");
+//  Log::getInstance()->log("BoxStack", Log::DEBUG, "Locked for update");
 
   // Get the z index of the box
   int z = 0;
@@ -286,7 +286,7 @@ void BoxStack::update(Boxx* toUpdate, Region* regionToUpdate)
   }
 
   boxLock.unlock();
-  Log::getInstance()->log("BoxStack", Log::DEBUG, "Unlocked for update");
+//  Log::getInstance()->log("BoxStack", Log::DEBUG, "Unlocked for update");
 }
 
 void BoxStack::repaintRevealed(int x, Region r)
index 1466fffd8763d5031657b0d39b23ed062005a02a..7f2d4c14bb26124365024bac1821a5f2c0ab5c7e 100644 (file)
@@ -732,7 +732,7 @@ int DemuxerTS::processTS(UCHAR* buf)
   if (pid == subID && subActive && subPacket.getLength() == subLength)
   {
     parsePacketDetails(subPacket);
-Log::getInstance()->log("DEMUXERTS", Log::DEBUG, "SUBMITTING A SUBTITLE PACKET %d %x", subLength, subPacket.getSubstream());
+//Log::getInstance()->log("DEMUXERTS", Log::DEBUG, "SUBMITTING A SUBTITLE PACKET %d %x", subLength, subPacket.getSubstream());
     submitPacket(subPacket);
     subActive = false;
   }
index f90a8d6e009913534d152fbba7bb3433e1c01a8d..db440e91e937bbc54fab7250e920c06830cd183d 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright 2008 Mark Calderbank
+    Copyright 2008 Mark Calderbank, 2020 Chris Tallon
 
     This file is part of VOMP.
 
@@ -14,8 +14,7 @@
     GNU General Public License for more details.
 
     You should have received a copy of the GNU General Public License
-    along with VOMP; if not, write to the Free Software Foundation, Inc.,
-    51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+    along with VOMP.  If not, see <https://www.gnu.org/licenses/>.
 */
 /*  Sections of code and general methods adopted from VDR version 1.6.0
  *  dvbsubtitle.c (GPL version 2 or later)
 
 /*  Reference ETSI EN 300 743 V1.3.1 (2006-11) */
 
-#include "dvbsubtitles.h"
-#include "demuxer.h"
-#include "osdreceiver.h"
-#include "video.h"
-#include "log.h"
 
-// --- cTimeMs ---------------------------------------------------------------
-// Borrowed from the vdr tools
+#define DVBSDEBUG 0
 
-cTimeMs::cTimeMs(int Ms)
-{
-  initted = false;
 
-  if (Ms >= 0)
-     Set(Ms);
-  else
-  {
-     begin = 0;
-     isFirstCheck = false;
-  }
-}
+#ifdef DVBSDEBUG
 
-uint64_t cTimeMs::Now(void)
-{
-  struct timespec tp;
+// DBG
+#include <stdio.h>
+#include <string>
+#include <chrono>
+#include <iomanip>
 
-  if (getClockRealTime(&tp) == 0)
-    return (uint64_t(tp.tv_sec)) * 1000 + tp.tv_nsec / 1000000;
-  else
-    Log::getInstance()->log("SUBTITLES", Log::ERR, "cTimeMs: clock_gettime(CLOCK_REALTIME) failed");
-  return 0;
+std::string tp2str(const std::chrono::time_point<std::chrono::system_clock>& tp)
+{
+  auto tms = std::chrono::time_point_cast<std::chrono::milliseconds>(tp);
+  std::chrono::milliseconds e = tms.time_since_epoch();
+  long long c = e.count();
+  time_t tt = c / 1000;
+  int ttm = c % 1000;
+  auto stm = std::localtime(&tt);
+  std::stringstream ss;
+  ss << std::put_time(stm, "%T") << "." << std::setfill('0') << std::setw(3) << ttm;
+  return ss.str();
 }
 
-void cTimeMs::Set(int Ms)
-{
-  isFirstCheck = true; // Timer set, the first check can be done once
-  begin = Now() + Ms;
+#endif
 
-  if (Ms) initted = true;
-}
 
-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)
-{
-  if (!initted) return 0;
-  return Now() - begin;
-}
 
+#include "demuxer.h"
+#include "osdreceiver.h"
+#include "video.h"
+#include "log.h"
 
-//-------- End of cTimeMs borrowed from the vdr tools --------
+#include "dvbsubtitles.h"
 
 DVBSubtitleCLUT::DVBSubtitleCLUT()
 : version(0xFF),
@@ -545,22 +520,31 @@ DVBSubtitles::DVBSubtitles(OSDReceiver* tosd)
 : osd(tosd),
   pageOnDisplay(65536),
   running(false),
-  showing(false),
-  threadNudged(false),
-  SubtitleTimeout(0),
-  timeout_clear(false)
+  showing(false)
 {
 }
 
 void DVBSubtitles::put(const PESPacket& packet)
 {
+  // Player object play feed thread comes here, via the demuxer
+  // input_mutex only used in put() here, start(), stop() and threadMethod()
+  // So, roll old Thread::mutex/cond into input_mutex?
+
   input_mutex.lock();
   if (running)
   {
     if (packet.getPTS() != PESPacket::PTS_INVALID)
     {
       worklist.push_back(packet);
-      nudge();
+      signalRecalcWLTO = true;
+        Log::getInstance()->log("DVBSubs", Log::DEBUG, "Received packet: PTS: %llu, size: %u, type: %u", packet.getPTS(), packet.getSize(), packet.getPacketType());
+
+
+      dvbsCond.notify_one();
+    }
+    else
+    {
+        Log::getInstance()->log("DVBSubs", Log::DEBUG, "PUT DROPPING INVALID PACKET: PTS: %llu, size: %u, type: %u", packet.getPTS(), packet.getSize(), packet.getPacketType());
     }
   }
   input_mutex.unlock();
@@ -786,7 +770,7 @@ void DVBSubtitles::finishPage(const DVBSubtitlePage& page)
       DVBSubtitlePage::RegionMap::const_iterator region_iter;
       region_iter = page.regions.find(i->first);
       if (region_iter == page.regions.end()) continue;
-      Log::getInstance()->log("SUBTITLES", Log::DEBUG, "Clear region %d", i->first);
+      Log::getInstance()->log("DVBSubs", Log::DEBUG, "Clear region %d", i->first);
       if (!osdMenuShowing) osd->clearOSDArea(i->second.x, i->second.y,
            region_iter->second.getWidth(), region_iter->second.getHeight(),dds);
     }
@@ -797,55 +781,74 @@ void DVBSubtitles::finishPage(const DVBSubtitlePage& page)
     DVBSubtitlePage::RegionMap::const_iterator region_iter;
     region_iter = page.regions.find(i->first);
     if (region_iter == page.regions.end()) continue;
-    Log::getInstance()->log("SUBTITLES", Log::DEBUG, "Display region %d", i->first);
+    Log::getInstance()->log("DVBSubs", Log::DEBUG, "Display region %d", i->first);
     if (!osdMenuShowing) 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);
-  timeout_clear=false;
-  Log::getInstance()->log("SUBTITLES", Log::DEBUG, "SubtitleTimeout %d", page.timeout);
+
+  subtitleTimeoutPoint = std::chrono::system_clock::now() + std::chrono::seconds(page.timeout);
+  subtitleTimeoutPointActive = true;
+
+  Log::getInstance()->log("DVBSubs", Log::DEBUG, "SubtitleTimeout %d", page.timeout);
 }
 
-int DVBSubtitles::start()
+void DVBSubtitles::start()
 {
+  Log::getInstance()->log("DVBSubs", Log::DEBUG, "subs start");
+
+#ifdef DVBSDEBUG
+
+  DBG = fopen("dfifo", "a");
+
+  fprintf(DBG, "\033[H\033[2J");
+  fflush(DBG);
+
+#endif
+
   input_mutex.lock();
+
   dds=DVBSubtitleDisplayDefinition();
   running = true;
+
+  dvbsThread = std::thread([this] { threadMethod(); });
+
   input_mutex.unlock();
-  return threadStart();
 }
 
 void DVBSubtitles::stop()
 {
-  threadStop();
+  Log::getInstance()->log("DVBSubs", Log::DEBUG, "subs stop");
+
   input_mutex.lock();
-  running = false;
-  worklist.clear();
-  input_mutex.unlock();
-  output_mutex.lock();
-  PageMap::const_iterator pageEntry = pages.find(pageOnDisplay);
-  if (pageEntry != pages.end())
+  if (!running)
   {
-    const DVBSubtitlePage& page = pageEntry->second;
-    DVBSubtitlePage::DisplayMap::const_iterator i;
-    for (i = page.currentDisplay.begin(); i != page.currentDisplay.end(); ++i)
-    {
-      DVBSubtitlePage::RegionMap::const_iterator region_iter;
-      region_iter = page.regions.find(i->first);
-      if (region_iter == page.regions.end()) continue;
-      if (!osdMenuShowing) osd->clearOSDArea(i->second.x, i->second.y,
-           region_iter->second.getWidth(), region_iter->second.getHeight(),dds);
-    }
+    Log::getInstance()->log("DVBSubs", Log::ERR, "STOP called, already dead!");
+    input_mutex.unlock();
+    return;
   }
-  pages.clear();
-  pageOnDisplay = 65536;
-  output_mutex.unlock();
-  threadNudged = false;
+
+  running = false; // disables put()
+  signalStop = true;
+  dvbsCond.notify_one();
+  input_mutex.unlock();
+  dvbsThread.join();
+
+  worklist.clear();
+  input_mutex.unlock();
+
+  clearDisplayedPages();
+
+
+#ifdef DVBSDEBUG
+  fclose(DBG);
+#endif
 }
 
 void DVBSubtitles::show()
 {
+  Log::getInstance()->log("DVBSubs", Log::DEBUG, "subs show");
+
   output_mutex.lock();
   showing = true;
   output_mutex.unlock();
@@ -853,8 +856,16 @@ void DVBSubtitles::show()
 
 void DVBSubtitles::hide()
 {
-  output_mutex.lock();
+  Log::getInstance()->log("DVBSubs", Log::DEBUG, "subs hide");
+
   showing = false;
+  clearDisplayedPages();
+}
+
+void DVBSubtitles::clearDisplayedPages()
+{
+  output_mutex.lock();
+
   PageMap::const_iterator pageEntry = pages.find(pageOnDisplay);
   if (pageEntry != pages.end())
   {
@@ -871,26 +882,43 @@ void DVBSubtitles::hide()
   }
   pages.clear();
   pageOnDisplay = 65536;
+
   output_mutex.unlock();
 }
 
-void DVBSubtitles::nudge()
+void DVBSubtitles::pause()
 {
-#ifndef WIN32
-  pthread_mutex_lock(&threadCondMutex);
-  threadNudged = true;
-  pthread_cond_signal(&threadCond);
-  pthread_mutex_unlock(&threadCondMutex);
-#else
-  WaitForSingleObject(threadCondMutex, INFINITE);
-  threadNudged = true;
-  SetEvent(threadCond);
-  ReleaseMutex(threadCondMutex);
-#endif
+  Log::getInstance()->log("DVBSubs", Log::DEBUG, "subs pause");
+
+  input_mutex.lock();
+  if (!running)
+  {
+    Log::getInstance()->log("DVBSubs", Log::ERR, "pause called, already dead!");
+    input_mutex.unlock();
+    return;
+  }
+
+  signalPause = true;
+  dvbsCond.notify_one();
+  input_mutex.unlock();
 }
 
-#define SUBTITLE_TIMEOUT_MS 750 
-// How often do we check if subtitles have been timed out.
+void DVBSubtitles::unPause()
+{
+  Log::getInstance()->log("DVBSubs", Log::DEBUG, "subs pause");
+
+  input_mutex.lock();
+  if (!running)
+  {
+    Log::getInstance()->log("DVBSubs", Log::ERR, "pause called, already dead!");
+    input_mutex.unlock();
+    return;
+  }
+
+  signalRecalcWLTO = true;
+  dvbsCond.notify_one();
+  input_mutex.unlock();
+}
 
 #if WIN32
 // FIXME win pragma
@@ -899,6 +927,190 @@ void DVBSubtitles::nudge()
 
 void DVBSubtitles::threadMethod()
 {
+  std::unique_lock<std::mutex> ul(input_mutex);  // Lock here, force start() to return before this does anything
+
+  bool waitExpireST{};
+  bool waitExpireWL{};
+
+  std::chrono::time_point<std::chrono::system_clock> worklistTimeoutPoint;
+  bool worklistTimeoutPointActive{};
+
+  while(1)
+  {
+#ifdef DVBSDEBUG
+
+    // TEMP DEBUG - re-enable nowPTS below when this goes
+    ULLONG nowPTS = Video::getInstance()->getCurrentTimestamp();
+    fprintf(DBG, "\033[H\033[2J");
+    fprintf(DBG, "Now: %s %llu\n", tp2str(std::chrono::system_clock::now()).c_str(), Video::getInstance()->getCurrentTimestamp());
+    for (auto p : worklist)
+    {
+      fprintf(DBG, "packet PTS %llu SIZE %i\tTIME %s\n", p.getPTS(), p.getSize(),
+        tp2str(std::chrono::system_clock::now() + std::chrono::milliseconds(PTSDifference(p.getPTS(), nowPTS) / 90)).c_str());
+    }
+    fflush(DBG);
+
+#endif
+
+
+    if (signalStop)
+    {
+      Log::getInstance()->log("DVBSubs", Log::INFO, "Thread exiting");
+      signalStop = false;
+      return;
+    }
+    else if (signalPause)
+    {
+      signalPause = false;
+      subtitleTimeoutPointActive = false;
+      worklistTimeoutPointActive = false;
+    }
+    else if (signalRecalcWLTO) // once per incoming packet, and other times
+    {
+      signalRecalcWLTO = false;
+#ifndef DVBSDEBUG
+      ULLONG nowPTS = Video::getInstance()->getCurrentTimestamp();
+#endif
+
+      if (nowPTS == 0)
+      {
+        // Video is not started yet. DVBSub packet has come in. Don't set worklistTimeoutPoint,
+        // just store the packet and allow next signal to start things off
+        Log::getInstance()->log("DVBSubs", Log::DEBUG, "signalRecalcWLTO but Video PTS == 0");
+      }
+      else
+      {
+        worklistTimeoutPointActive = true;
+        Log::getInstance()->log("DVBSubs", Log::DEBUG, "Calc: Num packets available: %i", worklist.size());
+
+        ULLONG pktPTS = worklist.front().getPTS();
+        ULLONG diff = PTSDifference(pktPTS, nowPTS);
+        diff /= 90; // convert diff to ms (PTS difference is in 1/90000s)
+        if (diff < 60 * 1000)
+        {
+          worklistTimeoutPoint = std::chrono::system_clock::now() + std::chrono::milliseconds(diff);
+        }
+        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.
+
+          // FIXME check if this still works
+          worklistTimeoutPoint = std::chrono::system_clock::now();
+        }
+
+        Log::getInstance()->log("DVBSubs", Log::DEBUG, "Calc'd new worklistTimeoutPoint");
+      }
+    }
+    else if (waitExpireST) // do real work - subtitletimeout
+    {
+      Log::getInstance()->log("DVBSubs", Log::DEBUG, "Subtitle timeout occurred");
+      waitExpireST = false;
+      subtitleTimeoutPointActive = false;
+      output_mutex.lock();
+      if (showing && !osdMenuShowing) osd->clearOSD();
+      output_mutex.unlock();
+    }
+    else if (waitExpireWL) // do real work - worklist - could be multiple packets to do
+    {
+      Log::getInstance()->log("DVBSubs", Log::DEBUG, "Something to do");
+
+      waitExpireWL = false;
+      worklistTimeoutPointActive = false;
+
+      ULLONG nowPTS = Video::getInstance()->getCurrentTimestamp();
+
+      // Guaranteed to be at least one packet in the worklist
+      PESPacket packet = worklist.front();
+      ULLONG pktPTS = worklist.front().getPTS();
+
+      while(1)
+      {
+        worklist.pop_front();
+
+        output_mutex.lock();
+        if (showing) decodePacket(packet);
+        output_mutex.unlock();
+
+        // Repeat this loop only if there is another packet and it's the same PTS as this one
+        // Not sure this ever happens.
+        if (worklist.size() && (worklist.front().getPTS() == pktPTS))
+        {
+          packet = worklist.front();
+          continue;
+        }
+        else
+        {
+          break;
+        }
+      }
+
+      if (worklist.size())
+      {
+        signalRecalcWLTO = true;
+        continue; // restart the loop and force a recalc
+      }
+
+
+        /*
+
+
+        if (PTSDifference(nowPTS, pktPTS) < 2*90000     // need this? we should be here exactly on time
+         || PTSDifference(pktPTS, nowPTS) < 4000)
+        { // It is due for processing or discarding.
+          worklist.pop_front();
+
+          output_mutex.lock();
+          if (showing) decodePacket(packet);
+          output_mutex.unlock();
+        }
+        else if (PTSDifference(pktPTS, nowPTS) >= 60*90000)
+        { // Seems like a bad or very old entry. Get rid of it.
+          finished = false;
+          worklist.pop_front();
+        }
+*/
+
+
+      // Loop has exited. Either worklist is now empty or the next packet doesn't match the PTSDifference ranges
+    }
+    else
+    {
+      // Spurious?
+    }
+
+    // Either:
+    // 1. sleep until timeout
+    // 2. sleep until next worklist
+    // 3. sleep until signalled
+
+    if (!subtitleTimeoutPointActive && !worklistTimeoutPointActive)
+    {
+      Log::getInstance()->log("DVBSubs", Log::DEBUG, "No WL or STT. Infinite wait");
+      dvbsCond.wait(ul); // Wait until signalled
+    }
+    else if (subtitleTimeoutPointActive)
+    {
+      if (worklistTimeoutPointActive && (worklistTimeoutPoint < subtitleTimeoutPoint))
+      {
+        Log::getInstance()->log("DVBSubs", Log::DEBUG, "WaitFor: WL");
+        if (dvbsCond.wait_until(ul, worklistTimeoutPoint) == std::cv_status::timeout) waitExpireWL = true;
+      }
+      else
+      {
+        Log::getInstance()->log("DVBSubs", Log::DEBUG, "WaitFor: ST");
+        if (dvbsCond.wait_until(ul, subtitleTimeoutPoint) == std::cv_status::timeout) waitExpireST = true;
+      }
+    }
+    else
+    {
+      Log::getInstance()->log("DVBSubs", Log::DEBUG, "WaitFor: WL");
+      if (dvbsCond.wait_until(ul, worklistTimeoutPoint) == std::cv_status::timeout) waitExpireWL = true;
+    }
+  }
+/*
+
   struct timespec sleeptime;
   sleeptime.tv_sec = 0;
   sleeptime.tv_nsec = 0;
@@ -906,8 +1118,13 @@ void DVBSubtitles::threadMethod()
   timeout_clear=false;
   while (1)
   {
-    if (SubtitleTimeout.TimedOut())  // do we have a subtitle timeout
+    if (subtitleTimeoutPointActive && (subtitleTimeoutPoint < std::chrono::system_clock::now())) // do we have a subtitle timeout
     {
+      subtitleTimeoutPointActive = false;
+
+
+//    if (SubtitleTimeout.TimedOut())  // do we have a subtitle timeout
+//    {
       output_mutex.lock();
       if (showing && !osdMenuShowing) {
          if (!timeout_clear) {
@@ -919,7 +1136,15 @@ void DVBSubtitles::threadMethod()
     }
     else if (showing)                   // if not lets check when will we have it
     {
+      // Get milliseconds until the timeout
+      wakeup = std::chrono::duration_cast<std::chrono::milliseconds>(subtitleTimeoutPoint - std::chrono::system_clock::now()).count();
+              Log::getInstance()->log("DVBSubs", Log::DEBUG, "A1: %lu", wakeup);
+
+      //                 now - begin
        wakeup = -(SubtitleTimeout.Elapsed());
+
+              Log::getInstance()->log("DVBSubs", Log::DEBUG, "A2: %lu", wakeup);
+
        if (wakeup > 0 && sleeptime.tv_nsec == 0 && sleeptime.tv_sec == 0)
        // We are not done, we still have a Subtitle Timeout!
        {
@@ -928,18 +1153,23 @@ void DVBSubtitles::threadMethod()
          timeout_clear=false;
        }
     }
+
+
+    //if (dvbsThreadStop) return;
     threadCheckExit();
+
+
     threadLock();
     if (!threadNudged)
     { // We have done the current work and no more has arrived. Sleep.
       if (sleeptime.tv_sec == 0 && sleeptime.tv_nsec == 0)
       {
-        Log::getInstance()->log("SUBTITLES", Log::DEBUG, "Sleeping until nudged.");
+        Log::getInstance()->log("DVBSubs", Log::DEBUG, "Sleeping until nudged.");
         threadWaitForSignal();
       }
       else
       {
-        Log::getInstance()->log("SUBTITLES", Log::DEBUG, "Sleeping for %d and %d", sleeptime.tv_sec, sleeptime.tv_nsec);
+        Log::getInstance()->log("DVBSubs", Log::DEBUG, "Sleeping for %d and %d", sleeptime.tv_sec, sleeptime.tv_nsec);
         struct timespec targetTime;
 
                getClockRealTime(&targetTime);
@@ -1019,6 +1249,8 @@ void DVBSubtitles::threadMethod()
       }
     }
   }
+
+  */
 }
 
 void DVBSubtitles::setOSDMenuVisibility(bool visible)
index f3029f25aaed0f01519a68f1f0c4893a4a66b0c6..55bef1134c91f4130be4700e6430431a34d9619c 100644 (file)
     GNU General Public License for more details.
 
     You should have received a copy of the GNU General Public License
-    along with VOMP; if not, write to the Free Software Foundation, Inc.,
-    51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+    along with VOMP.  If not, see <https://www.gnu.org/licenses/>.
 */
 
 #ifndef DVBSUBTITLES_H
 #define DVBSUBTITLES_H
 
-#include "threadsystem.h"
-
-#include "bitmap.h"
-#include "demuxer.h"
-#ifndef WIN32
-#include <inttypes.h>
-#else
-typedef unsigned long long     uint64_t;
-#endif
 #include <ctime>
 #include <vector>
 #include <deque>
 #include <map>
+#include <chrono>
 #include <mutex>
+#include <thread>
+#include <condition_variable>
+#ifndef WIN32
+#include <inttypes.h>
+#else
+typedef unsigned long long uint64_t;
+#endif
 
-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);
-    bool initted;
-};
+#include "bitmap.h"
+#include "demuxer.h"
 
 class OSDReceiver;
 
@@ -122,17 +107,20 @@ public:
 
 };
 
-class DVBSubtitles : public Thread_TYPE
+class DVBSubtitles
 {
   public:
     DVBSubtitles(OSDReceiver* tosd = NULL);
     virtual ~DVBSubtitles() {}
     void put(const PESPacket& packet);
-    int  start();
+    void start();
     void stop();
     void show();
     void hide();
+    void pause();
+    void unPause();
     void setOSDMenuVisibility(bool visible);
+    bool isShowing() { return showing; }
 
   private:
     OSDReceiver* osd;
@@ -142,23 +130,27 @@ class DVBSubtitles : public Thread_TYPE
     UINT pageOnDisplay;
     bool decodePacket(const PESPacket&);
     void finishPage(const DVBSubtitlePage&);
+    void clearDisplayedPages();
     DVBSubtitleDisplayDefinition dds;
 
     bool osdMenuShowing;
     bool running;
     bool showing;
-    bool threadNudged;
-    cTimeMs SubtitleTimeout;
-    bool timeout_clear;
-    void nudge();
-    void lockInput();
-    void unlockInput();
-    void lockOutput();
-    void unlockOutput();
+    std::chrono::time_point<std::chrono::system_clock> subtitleTimeoutPoint;
+    bool subtitleTimeoutPointActive{};
     void threadMethod();
 
-    std::mutex input_mutex;
+    std::mutex input_mutex; // Also use as thread/cond/signal mutex, master loop etc.
     std::mutex output_mutex;
+
+    std::thread dvbsThread;
+    std::condition_variable dvbsCond;
+
+    bool signalRecalcWLTO{};
+    bool signalStop{};
+    bool signalPause{};
+
+    FILE* DBG;
 };
 
 #endif
diff --git a/main.cc b/main.cc
index b727db3be6b03ff16d9e45fd6540bff64267ed94..65975a2894e4fa2604b280cfe5327623ed08bbce 100644 (file)
--- a/main.cc
+++ b/main.cc
@@ -508,7 +508,7 @@ long long getTimeMS()
   return ts.tv_sec * 1000 + ts.tv_nsec / 1000000LL;
 }
 
-int getClockRealTime(struct timespec *tp)
+int getClockRealTime(struct timespec *tp) // FIXME - del if all goes chrono
 {
   return clock_gettime(CLOCK_REALTIME, tp);
 }
index 6e1e813e19a6be245118c4cdda650d7e5ce80e1a..62004b041270a159b5c5b04566d7ecd31bc40168 100644 (file)
@@ -702,6 +702,8 @@ void PlayerLiveTV::threadMethod()
       {
         logger->log("PlayerLiveTV", Log::DEBUG, "start new stream");
         
+        bool subsRestore = subtitles->isShowing();
+
         switchState(S_VIDEOSTARTUP);
         
         if (!checkError())
@@ -790,14 +792,27 @@ void PlayerLiveTV::threadMethod()
                        }
                }
 
-               if (selected >= 0) {
-                       demuxer->setSubID(chan->spids[selected].pid);
-                       if (command->getSubDefault()) {
-                               turnSubtitlesOn(true);
-                       } else {
-                               turnSubtitlesOn(false);
-                       }
-               }
+            if (selected >= 0)
+            {
+              demuxer->setSubID(chan->spids[selected].pid);
+
+              if (firstStart)
+              {
+                firstStart = false;
+
+                if (command->getSubDefault())
+                  turnSubtitlesOn(true);
+                else
+                  turnSubtitlesOn(false);
+              }
+              else
+              {
+                if (subsRestore)
+                  turnSubtitlesOn(true);
+                else
+                  turnSubtitlesOn(false);
+              }
+            }
 
                demuxer->setTID(chan->tpid);
                teletext->ResetDecoder();
index 028119d6e7d845c7f4a1ea4360941e334f4d64c7..75fe9865ef731149f56fc657d1d8da7943d6264f 100644 (file)
@@ -115,6 +115,7 @@ class PlayerLiveTV : public PlayerLive, public Thread_TYPE, public Callback, pub
     AFeed afeed;
     TFeed tfeed;
     ChannelList* chanList;
+    bool firstStart{true};
 
     std::queue<PLInstruction> instructions;
     const static UCHAR I_SETCHANNEL = 1;
index 73a25a76151a60631dd9a9e1bad78360b145a912..2f682478c34092f64f577d7a69374f77d53613de 100644 (file)
@@ -455,6 +455,7 @@ void PlayerVideoRec::switchState(UCHAR toState, ULONG jumpFrame)
 
           video->pause();
           audio->pause();
+          subtitles->pause();
           state = S_PAUSE_P;
           return;
         }
@@ -538,6 +539,7 @@ void PlayerVideoRec::switchState(UCHAR toState, ULONG jumpFrame)
         {
           video->unPause();
           audio->unPause();
+          subtitles->unPause();
 
           #ifdef VOMP_PLATFORM_RASPBERRY
           vfeed.start();
diff --git a/vdr.cc b/vdr.cc
index 11e9b565b21f6b229acad8f6c8ba1db87c43838f..bb97ca421a0778470d805706a74c4f7c52a9d1c0 100644 (file)
--- a/vdr.cc
+++ b/vdr.cc
@@ -366,7 +366,7 @@ void VDR::threadMethod()
     {
       if (lastKArecv < (timeNow - 5))
       {
-        logger->log("VDR", Log::DEBUG, "Sending KA packet");
+        //logger->log("VDR", Log::DEBUG, "Sending KA packet");
         if (!sendKA(timeNow))
         {
           logger->log("VDR", Log::DEBUG, "Could not send KA, calling connectionDied");
@@ -456,7 +456,7 @@ void VDR::threadMethod()
       {
         lastKAsent = 0;
         lastKArecv = KAreply;
-        logger->log("VDR", Log::DEBUG, "Rxd correct KA reply");
+        //logger->log("VDR", Log::DEBUG, "Rxd correct KA reply");
       }
     }
     else
index f9ec04efbad08b7e625490e75fdebf21b89b6016..67659ddb711054b1b75c89c6f2582792d5e1a5c8 100644 (file)
@@ -42,9 +42,12 @@ class VRecordingList : public TBBoxx
     VRecordingList();
     virtual ~VRecordingList();
 
+/*
 #ifndef WIN32
     using TBBoxx::draw; // Signal the compiler we are intentionally overriding the draw() virtual with different args
 #endif
+*/
+
     virtual void draw(bool doIndexPop = false)=0;
 
     int handleCommand(int command);
index f9dc189e064dedab13393dfa8724046d6bbe67e0..d629af102c4026add9cbde0d15f12a63b076ef66 100644 (file)
@@ -30,9 +30,12 @@ class VRecordingListAdvanced : public VRecordingList
     VRecordingListAdvanced();
     virtual ~VRecordingListAdvanced();
 
+/*
 #ifndef WIN32
     using TBBoxx::draw; // Signal the compiler we are intentionally overriding the draw() virtual with different args
 #endif
+*/
+
     void draw(bool doIndexPop = false);
 
     bool load();
index ebd91563dccef68563ea0efcb33656951607f3bd..f917b0f70ebea488f0650847f6e357702bacfc74 100644 (file)
@@ -28,9 +28,12 @@ class VRecordingListClassic : public VRecordingList
     VRecordingListClassic();
     virtual ~VRecordingListClassic();
 
+/*
 #ifndef WIN32
     using TBBoxx::draw; // Signal the compiler we are intentionally overriding the draw() virtual with different args
 #endif
+*/
+
     void draw(bool doIndexPop = false);
 
     bool load();
index e71fa0d37c2decb54a7604fe28e10a0d048df489..bd080d33ee1c30f21b7e039f121d7590fc7c750e 100644 (file)
@@ -768,8 +768,8 @@ void VVideoRec::doAudioSelector()
 
 void VVideoRec::doBar(int action_in)
 {
-  if (player->isSubtitlesOn()) clearOSD(); // remove dvbsubtitles
-  player->tellSubtitlesOSDVisible(true);
// if (player->isSubtitlesOn()) clearOSD(); // remove dvbsubtitles
// player->tellSubtitlesOSDVisible(true);
   barShowing = true;
 
   int action = action_in;