HRESULT SMPortOutputQueue::Flush(SMThread& Thread, DWORD dwTimeout /*= DEFAULT_FLUSH_TIMEOUT*/)
{
    HRESULT hr = S_OK;

    // Verify that the queue has been initialized
    CHECK_INITIALIZED(Flush);

    SMTimer Timer;
    bool bDone = false;
    while (!bDone && Thread.IsPermittedToRun() && m_Port.IsOpen())
    {
        // Need atomic access to queue
        SMSingleLock SingleLock(&m_QueueMutex);
        SingleLock.Lock();
        bDone = m_Queue.empty();
        SingleLock.Unlock();

        // Sleep for a while, even if the queue is now empty (in order to allow
        // for the last message removed to be fully transmitted).
        ::Sleep(100);
        if (!bDone && (Timer.ElapsedSeconds() >= dwTimeout))
        {
            bDone = true;
            hr = E_FAIL;
            SM_LOG_NAME(hr, 1, "SMPortOutputQueue::Flush(): Timed-out waiting for queue to become empty!");
        }
    }

    return hr;
}
Example #2
0
void CVideoReferenceClock::RefreshChanged()
{
  CSingleLock SingleLock(m_CritSection);
  if (m_pVideoSync)
  {
    m_pVideoSync->RefreshChanged();
  }
}
Example #3
0
void CVideoReferenceClock::UpdateRefreshrate()
{
  CSingleLock SingleLock(m_CritSection);
  m_RefreshRate = m_pVideoSync->GetFps();
  m_ClockSpeed = 1.0;

  CLog::Log(LOGDEBUG, "CVideoReferenceClock: Detected refreshrate: %.3f hertz", m_RefreshRate);
}
Example #4
0
void CVideoReferenceClock::Process()
{
  bool SetupSuccess = false;
  int64_t Now;

  while(!m_bStop)
  {
    m_pVideoSync = g_Windowing.GetVideoSync(this);

    if (m_pVideoSync)
    {
      SetupSuccess = m_pVideoSync->Setup(CBUpdateClock);
      UpdateRefreshrate();
    }

    CSingleLock SingleLock(m_CritSection);
    Now = CurrentHostCounter();
    m_CurrTime = Now + m_ClockOffset; //add the clock offset from the previous time we stopped
    m_LastIntTime = m_CurrTime;
    m_CurrTimeFract = 0.0;
    m_ClockSpeed = 1.0;
    m_TotalMissedVblanks = 0;
    m_MissedVblanks = 0;

    if (SetupSuccess)
    {
      m_UseVblank = true;          //tell other threads we're using vblank as clock
      m_VblankTime = Now;          //initialize the timestamp of the last vblank
      SingleLock.Leave();

      //run the clock
      m_pVideoSync->Run(m_bStop);
    }
    else
    {
      SingleLock.Leave();
      CLog::Log(LOGDEBUG, "CVideoReferenceClock: Setup failed, falling back to CurrentHostCounter()");
    }

    SingleLock.Enter();
    m_UseVblank = false;                       //we're back to using the systemclock
    Now = CurrentHostCounter();                //set the clockoffset between the vblank clock and systemclock
    m_ClockOffset = m_CurrTime - Now;
    SingleLock.Leave();

    //clean up the vblank clock
    if (m_pVideoSync)
    {
      m_pVideoSync->Cleanup();
      m_pVideoSync.reset();
    }

    if (!SetupSuccess)
      break;
  }
}
Example #5
0
double CVideoReferenceClock::GetSpeed()
{
  CSingleLock SingleLock(m_CritSection);

  //dvdplayer needs to know the speed for the resampler
  if (m_UseVblank)
    return m_ClockSpeed;
  else
    return 1.0;
}
void CVideoReferenceClock::Process()
{
  bool SetupSuccess = false;
  int64_t Now;

  while(!m_bStop)
  {
    m_pVideoSync = CServiceBroker::GetWinSystem()->GetVideoSync(this);

    if (m_pVideoSync)
    {
      SetupSuccess = m_pVideoSync->Setup(CBUpdateClock);
      UpdateRefreshrate();
    }

    CSingleLock SingleLock(m_CritSection);
    Now = CurrentHostCounter();
    m_CurrTime = Now;
    m_LastIntTime = m_CurrTime;
    m_CurrTimeFract = 0.0;
    m_ClockSpeed = 1.0;
    m_TotalMissedVblanks = 0;
    m_MissedVblanks = 0;

    if (SetupSuccess)
    {
      m_UseVblank = true;          //tell other threads we're using vblank as clock
      m_VblankTime = Now;          //initialize the timestamp of the last vblank
      SingleLock.Leave();

      m_vsyncStopEvent.Reset();
      //run the clock
      m_pVideoSync->Run(m_vsyncStopEvent);
    }
    else
    {
      SingleLock.Leave();
      CLog::Log(LOGDEBUG, "CVideoReferenceClock: Setup failed, falling back to CurrentHostCounter()");
    }

    SingleLock.Enter();
    m_UseVblank = false;                       //we're back to using the systemclock
    SingleLock.Leave();

    //clean up the vblank clock
    if (m_pVideoSync)
    {
      m_pVideoSync->Cleanup();
      m_pVideoSync.reset();
    }

    if (!SetupSuccess)
      break;
  }
}
Example #7
0
//this is called from CDVDClock::WaitAbsoluteClock, which is called from CXBMCRenderManager::WaitPresentTime
//it waits until a certain timestamp has passed, used for displaying videoframes at the correct moment
int64_t CVideoReferenceClock::Wait(int64_t Target)
{
  int64_t       Now;
  int           SleepTime;

  CSingleLock SingleLock(m_CritSection);

  if (m_UseVblank) //when true the vblank is used as clock source
  {
    while (m_CurrTime < Target)
    {
      //calculate how long to sleep before we should have gotten a signal that a vblank happened
      Now = CurrentHostCounter();
      int64_t NextVblank = TimeOfNextVblank();
      SleepTime = (int)((NextVblank - Now) * 1000 / m_SystemFrequency);

      int64_t CurrTime = m_CurrTime; //save current value of the clock

      bool Late = false;
      if (SleepTime <= 0) //if sleeptime is 0 or lower, the vblank clock is already late in updating
      {
        Late = true;
      }
      else
      {
        m_VblankEvent.Reset();
        SingleLock.Leave();
        if (!m_VblankEvent.WaitMSec(SleepTime)) //if this returns false, it means the vblank event was not set within
          Late = true;                          //the required time
        SingleLock.Enter();
      }

      //if the vblank clock was late with its update, we update the clock ourselves
      if (Late && CurrTime == m_CurrTime)
        UpdateClock(1, false); //update the clock by 1 vblank

    }
    return m_CurrTime;
  }
  else
  {
    int64_t ClockOffset = m_ClockOffset;
    SingleLock.Leave();
    Now = CurrentHostCounter();
    //sleep until the timestamp has passed
    SleepTime = (int)((Target - (Now + ClockOffset)) * 1000 / m_SystemFrequency);
    if (SleepTime > 0)
      Sleep(SleepTime);

    Now = CurrentHostCounter();
    return Now + ClockOffset;
  }
}
Example #8
0
void CVideoReferenceClock::SetSpeed(double Speed)
{
  CSingleLock SingleLock(m_CritSection);
  //dvdplayer can change the speed to fit the rereshrate
  if (m_UseVblank)
  {
    if (Speed != m_ClockSpeed)
    {
      m_ClockSpeed = Speed;
      CLog::Log(LOGDEBUG, "CVideoReferenceClock: Clock speed %f%%", GetSpeed() * 100.0);
    }
  }
}
//for the codec information screen
bool CVideoReferenceClock::GetClockInfo(int& MissedVblanks, double& ClockSpeed, double& RefreshRate) const
{
  CSingleLock SingleLock(m_CritSection);

  if (m_UseVblank)
  {
    MissedVblanks = m_TotalMissedVblanks;
    ClockSpeed = m_ClockSpeed;
    RefreshRate = m_RefreshRate;
    return true;
  }
  return false;
}
Example #10
0
//dvdplayer needs to know the refreshrate for matching the fps of the video playing to it
double CVideoReferenceClock::GetRefreshRate(double* interval /*= NULL*/)
{
  CSingleLock SingleLock(m_CritSection);

  if (m_UseVblank)
  {
    if (interval)
      *interval = m_ClockSpeed / m_RefreshRate;

    return m_RefreshRate;
  }
  else
    return -1;
}
Example #11
0
//called from dvdclock to get the time
int64_t CVideoReferenceClock::GetTime(bool interpolated /* = true*/)
{
  CSingleLock SingleLock(m_CritSection);

  //when using vblank, get the time from that, otherwise use the systemclock
  if (m_UseVblank)
  {
    int64_t  NextVblank;
    int64_t  Now;

    Now = CurrentHostCounter();        //get current system time
    NextVblank = TimeOfNextVblank();   //get time when the next vblank should happen

    while(Now >= NextVblank)  //keep looping until the next vblank is in the future
    {
      UpdateClock(1, false);           //update clock when next vblank should have happened already
      NextVblank = TimeOfNextVblank(); //get time when the next vblank should happen
    }

    if (interpolated)
    {
      //interpolate from the last time the clock was updated
      double elapsed = (double)(Now - m_VblankTime) * m_ClockSpeed * m_fineadjust;
      //don't interpolate more than 2 vblank periods
      elapsed = std::min(elapsed, UpdateInterval() * 2.0);

      //make sure the clock doesn't go backwards
      int64_t intTime = m_CurrTime + (int64_t)elapsed;
      if (intTime > m_LastIntTime)
        m_LastIntTime = intTime;

      return m_LastIntTime;
    }
    else
    {
      return m_CurrTime;
    }
  }
  else
  {
    return CurrentHostCounter() + m_ClockOffset;
  }
}
HRESULT SMPortOutputQueue::Push(SMString& Data)
{
    HRESULT hr = S_OK;

    // Verify that the queue has been initialized
    CHECK_INITIALIZED(Push);

    // Trace message if enabled
    if (m_bMessageTrace)
    {
        SM_LOG_NAME(S_OK, 1, "SMPortOutputQueue::Push(): " << Data.Data());
    }

    // Protect access to the queue from multiple threads
    SMSingleLock SingleLock(&m_QueueMutex, true);

    // Push a copy of the object into the output queue
    m_Queue.push(new SMString(Data));

    // Signal write thread that we added to the queue
    m_AddedToQueue.Set();

    return hr;
}
HRESULT SMPortOutputQueue::Thread(SMThread& Thread)
{
    SM_LOG(S_OK, 1, "SMPortOutputQueue::Thread(): thread running...");

    HRESULT hr = S_OK;
    // While thread is alive, receive data from port, push message onto queue
    // and signal that data has been made available.
    while (Thread.IsPermittedToRun() && m_Port.IsOpen())
    {
        SM_TRY

        // Wait for event signaling that data is available to publish
        SMMultiLock MultiLock(&m_AddedToQueue, &Thread.GetStopEvent());
        MultiLock.Lock();
        bool bQueueEmpty = false;
        while(Thread.IsPermittedToRun() && !bQueueEmpty)
        {
             // Need atomic access to queue
            SMSingleLock SingleLock(&m_QueueMutex);
            SingleLock.Lock();
            if (!m_Queue.empty())
            {
                bQueueEmpty = false;
                SMString* pData = m_Queue.front();
                m_Queue.pop();
                SingleLock.Unlock();

                if (pData != NULL)
                {
                    hr = m_Port.Send(pData->Data(), pData->GetLength());

                    if (hr == 0x8007006d || hr == 0x800700e8)  // broken pipe
                    {
                        SM_LOG(hr, 1, "Broken pipe, stop output queue thread");
                        m_Port.Close();
                        m_bInitialized = false;
                        break;  // get out of  while (bQueueEmpty)
                    }

                    // Trace message if enabled
                    if (m_bMessageTrace)
                    {
                        SM_LOG_NAME(S_OK, 1, "SMPortOutputQueue::Pop(): " << pData->Data());
                    }
                }

                // Delete the message
                if (pData != NULL)
                    delete pData;
            }
            else 
            {
                SingleLock.Unlock();
                bQueueEmpty = true;
                // Delay on errors, incoming data to avoid consuming too much CPU
                Thread.Sleep(100);
            }
        }

        // Catch any exceptions here so we can try to continue running
        SM_CATCH_ALL_DEFAULT_NO_HR
    }

    SM_LOG_NAME(S_OK, 1, "SMPortOutputQueue::Thread(): Write thread exiting...");

    return S_OK;
}
Example #14
0
void CVideoReferenceClock::Process()
{
  bool SetupSuccess = false;
  int64_t Now;

  while(!m_bStop)
  {
    //set up the vblank clock
#if defined(HAVE_X11)
  std::string gpuvendor = g_Windowing.GetRenderVendor();
  std::transform(gpuvendor.begin(), gpuvendor.end(), gpuvendor.begin(), ::tolower);
  if ((gpuvendor.compare(0, 5, "intel") == 0 ||
       gpuvendor.compare(0, 5, "x.org") == 0)) // AMD
    m_pVideoSync = new CVideoSyncDRM();
#if defined(HAS_GLX)
  else
    m_pVideoSync = new CVideoSyncGLX();
#endif
#elif defined(TARGET_DARWIN_OSX)
    m_pVideoSync = new CVideoSyncOsx();
#elif defined(TARGET_DARWIN_IOS)
    m_pVideoSync = new CVideoSyncIos();
#elif defined(TARGET_RASPBERRY_PI)
    m_pVideoSync = new CVideoSyncPi();
#elif defined(TARGET_ANDROID)
    m_pVideoSync = new CVideoSyncAndroid();
#endif

    if (m_pVideoSync)
    {
      SetupSuccess = m_pVideoSync->Setup(CBUpdateClock);
      UpdateRefreshrate();
    }

    CSingleLock SingleLock(m_CritSection);
    Now = CurrentHostCounter();
    m_CurrTime = Now + m_ClockOffset; //add the clock offset from the previous time we stopped
    m_LastIntTime = m_CurrTime;
    m_CurrTimeFract = 0.0;
    m_ClockSpeed = 1.0;
    m_TotalMissedVblanks = 0;
    m_fineadjust = 1.0;
    m_MissedVblanks = 0;

    if (SetupSuccess)
    {
      m_UseVblank = true;          //tell other threads we're using vblank as clock
      m_VblankTime = Now;          //initialize the timestamp of the last vblank
      SingleLock.Leave();

      //run the clock
      m_pVideoSync->Run(m_bStop);
    }
    else
    {
      SingleLock.Leave();
      CLog::Log(LOGDEBUG, "CVideoReferenceClock: Setup failed, falling back to CurrentHostCounter()");
    }

    SingleLock.Enter();
    m_UseVblank = false;                       //we're back to using the systemclock
    Now = CurrentHostCounter();                //set the clockoffset between the vblank clock and systemclock
    m_ClockOffset = m_CurrTime - Now;
    SingleLock.Leave();

    //clean up the vblank clock
    if (m_pVideoSync)
    {
      m_pVideoSync->Cleanup();
      delete m_pVideoSync;
      m_pVideoSync = NULL;
    }

    if (!SetupSuccess)
      break;
  }
}
Example #15
0
void CVideoReferenceClock::SetFineAdjust(double fineadjust)
{
  CSingleLock SingleLock(m_CritSection);
  m_fineadjust = fineadjust;
}
Example #16
0
BOOL DownLoad(LPCSTR URL, LPCSTR Path, BOOL& quit, CSocketList& list, CMutex& mutex)
{
try{
	CHttpSocket HttpSocket;
	CFile DownloadFile;
	CString strServer,strObject;
	unsigned short nPort;
	DWORD dwServiceType;
	long nLength;
	const char *pRequestHeader = NULL;
	SOCKET tmpS = 0;
	if(!AfxParseURL(URL,dwServiceType,strServer,strObject,nPort))
	{
		return FALSE;
	}
	try{
		pRequestHeader = HttpSocket.FormatRequestHeader((LPTSTR)(LPCTSTR)strServer,(LPTSTR)(LPCTSTR)strObject,nLength, nPort);	
		if(!HttpSocket.Socket())
			throw 0;
		tmpS = HttpSocket.GetSocket();

		CSingleLock SingleLock(&mutex);
		SingleLock.Lock();
		if(SingleLock.IsLocked())
			list.AddTail(tmpS);
		SingleLock.Unlock();
		
		if(quit){
			return FALSE;
		}
//		HttpSocket.SetTimeout(20000,0);
		if(!HttpSocket.Connect((LPTSTR)(LPCTSTR)strServer,nPort))
			throw 1;
		if(quit)
			return FALSE;
		if(!HttpSocket.SendRequest())
			throw 1;
		if(quit)
			return FALSE;
		int nLineSize = 0;
		char szLine[256];
		while(nLineSize != -1){
			nLineSize = HttpSocket.GetResponseLine(szLine,256);
			if(quit)
				return FALSE;
		}
		char szValue[30];
		BOOL bContLen = TRUE;
		int nFileSize = -1;
		if(HttpSocket.GetField("Content-Length",szValue,30)==-1)
			bContLen = FALSE;
		else
			nFileSize = atoi(szValue);
		if(quit)
			return FALSE;
		int nCompletedSize = 0;
		if(!DownloadFile.Open(Path, CFile::modeCreate|CFile::modeWrite))
			throw 2;
		char pData[1024];
		int nReceSize = 0;
		BOOL first = TRUE;
		while(!quit){
			nReceSize = HttpSocket.Receive(pData,1024);
			if(quit)
				return FALSE;
			if(nReceSize == 0)
				break;
			if(nReceSize == -1)
				throw 3;
			if(first&&!bContLen){
				char* temp = strstr(pData,"\r\n");
				if(!temp)
					throw 3;
				DownloadFile.Write(temp+2,nReceSize-(temp+2-pData));
			}
			else
				DownloadFile.Write(pData,nReceSize);
			nCompletedSize += nReceSize;
			first = FALSE;
			if(bContLen && nCompletedSize>=nFileSize)
				break;
		}
		if(!bContLen && !quit){
			long len =(long) DownloadFile.GetLength();
			DownloadFile.SetLength(len-7);
		}
		DownloadFile.Close();
		SingleLock.Lock();
		if(SingleLock.IsLocked()){
			POSITION pos = list.Find(tmpS);
			if(pos)
				list.RemoveAt(pos);
		}
		SingleLock.Unlock();
		
		HttpSocket.CloseSocket();
	}
	catch(int err){
		POSITION pos;
		CSingleLock SingleLock(&mutex);
		switch(err){
		case 3:
			DownloadFile.Close();
		case 2:
		case 1:
			SingleLock.Lock();
			if(SingleLock.IsLocked()){
				pos = list.Find(tmpS);
				if(pos)
					list.RemoveAt(pos);
			}
			SingleLock.Unlock();
			HttpSocket.CloseSocket();
			break;
		}
		return FALSE;
	}
	return !quit;
}
catch(...){
#ifdef _DEBUG
	Tips("BOOL DownLoad(LPCSTR URL, LPCSTR Path, BOOL& quit, CSocketList& list)");
#endif
}
	return FALSE;
}