changed: Implement pause/unpause for the job queue of a certain priority and use...
authorarnova <arnova@void.org>
Sun, 10 Feb 2013 13:45:03 +0000 (14:45 +0100)
committerarnova <arnova@void.org>
Mon, 4 Mar 2013 09:18:47 +0000 (10:18 +0100)
xbmc/Application.cpp
xbmc/cores/amlplayer/AMLPlayer.cpp
xbmc/cores/omxplayer/OMXPlayer.cpp
xbmc/utils/JobManager.cpp
xbmc/utils/JobManager.h

index d6e663b..fc102c7 100644 (file)
@@ -4083,6 +4083,15 @@ bool CApplication::PlayFile(const CFileItem& item, bool bRestart)
   bool bResult;
   if (m_pPlayer)
   {
+    /* When playing video pause any low priority jobs, they will be unpaused  when playback stops.
+     * This should speed up player startup for files on internet filesystems (eg. webdav) and
+     * increase performance on low powered systems (Atom/ARM).
+     */
+    if (item.IsVideo())
+    {
+      CJobManager::GetInstance().Pause(CJob::PRIORITY_LOW); // Pause any low priority jobs
+    }
+
     // don't hold graphicscontext here since player
     // may wait on another thread, that requires gfx
     CSingleExit ex(g_graphicsContext);
@@ -4189,9 +4198,6 @@ void CApplication::OnPlayBackEnded()
   if(m_bPlaybackStarting)
     return;
 
-  if (CJobManager::GetInstance().IsPaused(kJobTypeMediaFlags))
-    CJobManager::GetInstance().UnPause(kJobTypeMediaFlags);
-
   // informs python script currently running playback has ended
   // (does nothing if python is not loaded)
 #ifdef HAS_PYTHON
@@ -4217,9 +4223,6 @@ void CApplication::OnPlayBackStarted()
   if(m_bPlaybackStarting)
     return;
 
-  if (!CJobManager::GetInstance().IsPaused(kJobTypeMediaFlags))
-    CJobManager::GetInstance().Pause(kJobTypeMediaFlags);
-
 #ifdef HAS_PYTHON
   // informs python script currently running playback has started
   // (does nothing if python is not loaded)
@@ -4253,9 +4256,6 @@ void CApplication::OnPlayBackStopped()
   if(m_bPlaybackStarting)
     return;
 
-  if (CJobManager::GetInstance().IsPaused(kJobTypeMediaFlags))
-    CJobManager::GetInstance().UnPause(kJobTypeMediaFlags);
-
   // informs python script currently running playback has ended
   // (does nothing if python is not loaded)
 #ifdef HAS_PYTHON
@@ -5105,6 +5105,12 @@ void CApplication::ProcessSlow()
   }
 #endif
 
+  // Resume low priority jobs when current item is not video
+  if (!CurrentFileItem().IsVideo())
+  {
+    CJobManager::GetInstance().UnPause(CJob::PRIORITY_LOW);
+  }
+
   // Store our file state for use on close()
   UpdateFileState();
 
index 94c9a82..6421340 100644 (file)
@@ -1306,9 +1306,7 @@ void CAMLPlayer::Process()
   CLog::Log(LOGNOTICE, "CAMLPlayer::Process");
   try
   {
-    CJobManager::GetInstance().Pause(kJobTypeMediaFlags);
-
-    if (CJobManager::GetInstance().IsProcessing(kJobTypeMediaFlags) > 0)
+    if (CJobManager::GetInstance().IsProcessing(CJob::PRIORITY_LOW))
     {
       if (!WaitForPausedThumbJobs(20000))
       {
@@ -1614,8 +1612,6 @@ void CAMLPlayer::Process()
 
   // reset ac3/dts passthough
   SetAudioPassThrough(AFORMAT_UNKNOWN);
-  // let thumbgen jobs resume.
-  CJobManager::GetInstance().UnPause(kJobTypeMediaFlags);
 
   if (m_log_level > 5)
     CLog::Log(LOGDEBUG, "CAMLPlayer::Process exit");
@@ -1721,7 +1717,7 @@ bool CAMLPlayer::WaitForPausedThumbJobs(int timeout_ms)
   // use m_bStop and Sleep so we can get canceled.
   while (!m_bStop && (timeout_ms > 0))
   {
-    if (CJobManager::GetInstance().IsProcessing(kJobTypeMediaFlags) > 0)
+    if (CJobManager::GetInstance().IsProcessing(CJob::PRIORITY_LOW))
     {
       Sleep(100);
       timeout_ms -= 100;
index 340bbb2..28c118c 100644 (file)
@@ -1043,11 +1043,8 @@ void COMXPlayer::Process()
   if (!CachePVRStream())
     SetCaching(CACHESTATE_FLUSH);
 
-  // stop thumb jobs
-  CJobManager::GetInstance().Pause(kJobTypeMediaFlags);
-
   /*
-  if (CJobManager::GetInstance().IsProcessing(kJobTypeMediaFlags) > 0)
+  if (CJobManager::GetInstance().IsProcessing(CJob::PRIORITY_LOW))
   {
     if (!WaitForPausedThumbJobs(20000))
     {
@@ -1273,9 +1270,6 @@ void COMXPlayer::Process()
     // check if in a cut or commercial break that should be automatically skipped
     CheckAutoSceneSkip();
   }
-
-  // let thumbgen jobs resume.
-  CJobManager::GetInstance().UnPause(kJobTypeMediaFlags);
 }
 
 bool COMXPlayer::CheckDelayedChannelEntry(void)
@@ -4154,7 +4148,7 @@ bool COMXPlayer::WaitForPausedThumbJobs(int timeout_ms)
   // use m_bStop and Sleep so we can get canceled.
   while (!m_bStop && (timeout_ms > 0))
   {
-    if (CJobManager::GetInstance().IsProcessing(kJobTypeMediaFlags) > 0)
+    if (CJobManager::GetInstance().IsProcessing(CJob::PRIORITY_LOW))
     {
       Sleep(100);
       timeout_ms -= 100;
index 3467646..9aaa06b 100644 (file)
@@ -168,6 +168,9 @@ CJobManager::CJobManager()
 {
   m_jobCounter = 0;
   m_running = true;
+  
+  for (unsigned int priority = CJob::PRIORITY_LOW; priority <= CJob::PRIORITY_HIGH; ++priority)
+    m_jobPause[priority] = false; // Set this priority to unpaused
 }
 
 void CJobManager::CancelJobs()
@@ -212,7 +215,7 @@ unsigned int CJobManager::AddJob(CJob *job, IJobCallback *callback, CJob::PRIORI
     m_jobCounter++;
 
   // create a work item for this job
-  CWorkItem work(job, m_jobCounter, callback);
+  CWorkItem work(job, m_jobCounter, priority, callback);
   m_jobQueue[priority].push_back(work);
 
   StartWorkers(priority);
@@ -264,6 +267,9 @@ CJob *CJobManager::PopJob()
   CSingleLock lock(m_section);
   for (int priority = CJob::PRIORITY_HIGH; priority >= CJob::PRIORITY_LOW; --priority)
   {
+    if (m_jobPause[priority]) // In case this priority is paused, skip it
+      continue;
+
     if (m_jobQueue[priority].size() && m_processing.size() < GetMaxWorkers(CJob::PRIORITY(priority)))
     {
       // skip adding any paused types
@@ -300,6 +306,36 @@ void CJobManager::UnPause(const std::string &pausedType)
     m_pausedTypes.erase(i);
 }
 
+void CJobManager::Pause(const CJob::PRIORITY &priority)
+{
+  CSingleLock lock(m_section);
+  m_jobPause[priority] = true;
+}
+
+void CJobManager::UnPause(const CJob::PRIORITY &priority)
+{
+  CSingleLock lock(m_section);
+  m_jobPause[priority] = false;
+}
+
+bool CJobManager::IsPaused(const CJob::PRIORITY &priority) const
+{
+  CSingleLock lock(m_section);
+  return m_jobPause[priority];
+}
+
+bool CJobManager::IsProcessing(const CJob::PRIORITY &priority) const
+{
+  CSingleLock lock(m_section);
+
+  for(Processing::const_iterator it = m_processing.begin(); it < m_processing.end(); it++)
+  {
+    if (priority == it->m_priority)
+      return true;
+  }
+  return false;
+}
+
 bool CJobManager::IsPaused(const std::string &pausedType)
 {
   CSingleLock lock(m_section);
index fee13d6..141806e 100644 (file)
@@ -165,11 +165,12 @@ class CJobManager
   class CWorkItem
   {
   public:
-    CWorkItem(CJob *job, unsigned int id, IJobCallback *callback)
+    CWorkItem(CJob *job, unsigned int id, CJob::PRIORITY priority, IJobCallback *callback)
     {
       m_job = job;
       m_id = id;
       m_callback = callback;
+      m_priority = priority;
     }
     bool operator==(unsigned int jobID) const
     {
@@ -191,6 +192,7 @@ class CJobManager
     CJob         *m_job;
     unsigned int  m_id;
     IJobCallback *m_callback;
+    CJob::PRIORITY m_priority;
   };
 
 public:
@@ -257,6 +259,37 @@ public:
    */
   int IsProcessing(const std::string &pausedType);
 
+  /*!
+   \brief Suspends queueing of the specified priority until unpaused
+   Useful to (for ex) stop queuing thumb jobs during video start/playback.
+   Does not affect currently processing jobs, use IsProcessing to see if any need to be waited on
+   \param priority only jobs of this priority will be affected
+   \sa UnPause(), IsPaused(), IsProcessing()
+   */
+  void Pause(const CJob::PRIORITY &priority);
+
+  /*!
+   \brief Resumes queueing of the specified priority
+   \param priority only jobs of this priority will be affected
+   \sa Pause(), IsPaused(), IsProcessing()
+   */
+  void UnPause(const CJob::PRIORITY &priority);
+
+  /*!
+   \brief Checks if jobs of specified priority are paused.
+   \param priority only jobs of this priority will be affected
+   \sa Pause(), UnPause(), IsProcessing()
+   */
+  bool IsPaused(const CJob::PRIORITY &priority) const;
+
+  /*!
+   \brief Checks to see if any jobs with specific priority are currently processing.
+   \param priority to search for
+   \return true if processing jobs, else returns false
+   \sa Pause(), UnPause(), IsPaused()
+   */
+  bool IsProcessing(const CJob::PRIORITY &priority) const;
+
 protected:
   friend class CJobWorker;
   friend class CJob;
@@ -319,6 +352,7 @@ private:
   typedef std::vector<CJobWorker*> Workers;
 
   JobQueue   m_jobQueue[CJob::PRIORITY_HIGH+1];
+  bool       m_jobPause[CJob::PRIORITY_HIGH+1];
   Processing m_processing;
   Workers    m_workers;