Example #1
0
HRESULT CPushAudioPin::DoBufferProcessingLoop(void) {
	Command com;
	OnThreadStartPlay();
	do {
		while (!CheckRequest(&com)) {
			HRESULT hr;
			CAutoLock lock(&m_cSharedState);

			if( WaitForSingleObject( this->buffLockEvent, 500 ) == WAIT_OBJECT_0 ){
				if( this->buffData.size() != 0 ){
					if( this->buffLockEvent != NULL ){
						SetEvent(this->buffLockEvent);
					}
					IMediaSample *pSample;
					hr = GetDeliveryBuffer(&pSample,NULL,NULL,0);
					if (FAILED(hr)) {
						Sleep(1);
						continue;
					}
					hr = FillBuffer(pSample);
					if (hr == S_OK) {
						hr = Deliver(pSample);
						pSample->Release();

						if(hr != S_OK)
						{
							return S_OK;
						}
					} else if (hr == S_FALSE) {
						pSample->Release();
						DeliverEndOfStream();
						return S_OK;
					} else {
						pSample->Release();
						DeliverEndOfStream();
						m_pFilter->NotifyEvent(EC_ERRORABORT, hr, 0);
						return hr;
					}
				}else{
					if( this->buffLockEvent != NULL ){
						SetEvent(this->buffLockEvent);
					}
					Sleep(10);
				}
			}
		}
		// For all commands sent to us there must be a Reply call!
		if (com == CMD_RUN || com == CMD_PAUSE) {
			Reply(NOERROR);
		} else if (com != CMD_STOP) {
			Reply((DWORD) E_UNEXPECTED);
		}
	} while (com != CMD_STOP);
	return S_FALSE;
}
Example #2
0
int CBaseSplitterOutputPin::ThreadProcDelivery(int cnt)
{

	CAutoPtr<Packet> p;

	{
		CAutoLock cAutoLock(&m_queue);
		if((cnt = m_queue.GetCount()) > 0)
			p = m_queue.Remove();
	}

	if(S_OK == m_hrDeliver && cnt > 0)
	{
		ASSERT(!m_fFlushing);

		m_fFlushed = false;

		// flushing can still start here, to release a blocked deliver call

		HRESULT hr = p 
			? DeliverPacket(p) 
			: DeliverEndOfStream();

		m_eEndFlush.Wait(); // .. so we have to wait until it is done

		if(hr != S_OK && !m_fFlushed) // and only report the error in m_hrDeliver if we didn't flush the stream
		{
			// CAutoLock cAutoLock(&m_csQueueLock);
			m_hrDeliver = hr;
			cnt = 0;
		}
	}
	return cnt;
}
Example #3
0
void CDynamicSourceStream::FatalError(HRESULT hr)
{
    // Make sure the user is reporting a failure.
    ASSERT(FAILED(hr));

    m_bRunTimeError = TRUE;
    DeliverEndOfStream();
    m_pFilter->NotifyEvent(EC_ERRORABORT, hr, 0);
}
Example #4
0
DWORD CBaseSplitterOutputPin::ThreadProc()
{
	m_hrDeliver = S_OK;
	m_fFlushing = m_fFlushed = false;
	m_eEndFlush.Set();

	while(1)
	{
		Sleep(1);

		DWORD cmd;
		if(CheckRequest(&cmd))
		{
			m_hThread = NULL;
			cmd = GetRequest();
			Reply(S_OK);
			ASSERT(cmd == CMD_EXIT);
			return 0;
		}

		int cnt = 0;
		do
		{
			CAutoPtr<Packet> p;

			{
				CAutoLock cAutoLock(&m_queue);
				if((cnt = m_queue.GetCount()) > 0)
					p = m_queue.Remove();
			}

			if(S_OK == m_hrDeliver && cnt > 0)
			{
				ASSERT(!m_fFlushing);

				m_fFlushed = false;

				// flushing can still start here, to release a blocked deliver call

				HRESULT hr = p 
					? DeliverPacket(p) 
					: DeliverEndOfStream();

				m_eEndFlush.Wait(); // .. so we have to wait until it is done

				if(hr != S_OK && !m_fFlushed) // and only report the error in m_hrDeliver if we didn't flush the stream
				{
					// CAutoLock cAutoLock(&m_csQueueLock);
					m_hrDeliver = hr;
					break;
				}
			}
		}
		while(--cnt > 0);
	}
}
Example #5
0
STDMETHODIMP StreamOutputPin::EndOfStream(void)
{
	CAutoLock cAutoLock(this->m_pLock);

	this->m_pFilter->m_encoder->Stop(TRUE);

	DeliverEndOfStream();

	this->m_pFilter->NotifyEvent(EC_COMPLETE, S_OK, NULL);

	return S_OK;
}
Example #6
0
//----------------------------------------------------------------------------
//! @brief	  	サンプルをダウンストリームへ送り続ける処理
//! @return		エラーコード
//----------------------------------------------------------------------------
HRESULT CDemuxOutputPin::DoBufferProcessingLoop(void)
{
	Command com;
	HRESULT	hr;
	OnThreadStartPlay();
	do {
		while( !CheckRequest(&com) ) {
			// Virtual function user will override.
			IMediaSample *pSample;
			hr = RetrieveBuffer(&pSample);
			if( hr == S_OK ) {
				hr = Deliver(pSample);
				pSample->Release();
				if(hr != S_OK)
				{
					DbgLog((LOG_TRACE, 2, TEXT("Deliver() returned %08x; stopping"), hr));
					return S_OK;
				}
			} else if (hr == S_FALSE) {
				// derived class wants us to stop pushing data
				DeliverEndOfStream();
				return S_OK;
			} else {
				// derived class encountered an error
				DbgLog((LOG_ERROR, 1, TEXT("Error %08lX from FillBuffer!!!"), hr));
				DeliverEndOfStream();
				m_pFilter->NotifyEvent(EC_ERRORABORT, hr, 0);
				return hr;
			}
		}
		if( com == CMD_RUN || com == CMD_PAUSE ) {
			Reply(NOERROR);
		} else if( com != CMD_STOP ) {
			Reply((DWORD) E_UNEXPECTED);
			DbgLog((LOG_ERROR, 1, TEXT("Unexpected command!!!")));
		}
	} while( com != CMD_STOP );

	return S_FALSE;
}
Example #7
0
//
// DoBufferProcessingLoop
//
// Grabs a buffer and calls the users processing function.
// Overridable, so that different delivery styles can be catered for.
HRESULT CSourceStream::DoBufferProcessingLoop(void) {

    Command com;

    OnThreadStartPlay();

    do {
	while (!CheckRequest(&com)) {

	    IMediaSample *pSample;

	    HRESULT hr = GetDeliveryBuffer(&pSample,NULL,NULL,0);
	    if (FAILED(hr)) {
                Sleep(1);
		continue;	// go round again. Perhaps the error will go away
			    // or the allocator is decommited & we will be asked to
			    // exit soon.
	    }

	    // Virtual function user will override.
	    hr = FillBuffer(pSample);

	    if (hr == S_OK) {
		hr = Deliver(pSample);
                pSample->Release();

                // downstream filter returns S_FALSE if it wants us to
                // stop or an error if it's reporting an error.
                if(hr != S_OK)
                {
                  DbgLog((LOG_TRACE, 2, TEXT("Deliver() returned %08x; stopping"), hr));
                  return S_OK;
                }

	    } else if (hr == S_FALSE) {
                // derived class wants us to stop pushing data
		pSample->Release();
		DeliverEndOfStream();
		return S_OK;
	    } else {
                // derived class encountered an error
                pSample->Release();
		DbgLog((LOG_ERROR, 1, TEXT("Error %08lX from FillBuffer!!!"), hr));
                DeliverEndOfStream();
                m_pFilter->NotifyEvent(EC_ERRORABORT, hr, 0);
                return hr;
	    }

            // all paths release the sample
	}

        // For all commands sent to us there must be a Reply call!

	if (com == CMD_RUN || com == CMD_PAUSE) {
	    Reply(NOERROR);
	} else if (com != CMD_STOP) {
	    Reply((DWORD) E_UNEXPECTED);
	    DbgLog((LOG_ERROR, 1, TEXT("Unexpected command!!!")));
	}
    } while (com != CMD_STOP);

    return S_FALSE;
}
Example #8
0
HRESULT CAudioPin::DoBufferProcessingLoop(void)
{
  if (!m_bConnected) 
  {
    return S_OK;
    m_bThreadRunning = false;
  }
    
  Command com;
  OnThreadStartPlay();
  m_bThreadRunning = true;
  SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);

  do 
  {
    while (!CheckRequest(&com)) 
    {
      IMediaSample *pSample;
      HRESULT hr = GetDeliveryBuffer(&pSample,NULL,NULL,0);
      if (FAILED(hr)) 
      {
        Sleep(1);
        continue;	// go round again. Perhaps the error will go away
        // or the allocator is decommited & we will be asked to
        // exit soon.
      }

      // Virtual function user will override.
      hr = FillBuffer(pSample);

      if (hr == S_OK) 
      {
        // Some decoders seem to crash when we provide empty samples 
        if ((pSample->GetActualDataLength() > 0) && !m_pTsReaderFilter->IsStopping() && m_bConnected)
        {
          hr = Deliver(pSample); 
          m_sampleCount++ ;
        }
        else
        {
          m_bDiscontinuity = true;
        }
		
        pSample->Release();

        // downstream filter returns S_FALSE if it wants us to
        // stop or an error if it's reporting an error.
        if(hr != S_OK)
        {
          DbgLog((LOG_TRACE, 2, TEXT("Deliver() returned %08x; stopping"), hr));
          m_bThreadRunning = false;
          return S_OK;
        }
      } 
      else if (hr == S_FALSE) 
      {
        // derived class wants us to stop pushing data
        pSample->Release();
        DeliverEndOfStream();
        m_bThreadRunning = false;
        return S_OK;
      } 
      else 
      {
        // derived class encountered an error
        pSample->Release();
        DbgLog((LOG_ERROR, 1, TEXT("Error %08lX from FillBuffer!!!"), hr));
        DeliverEndOfStream();
        m_pFilter->NotifyEvent(EC_ERRORABORT, hr, 0);
        m_bThreadRunning = false;
        return hr;
      }
     // all paths release the sample
    }
    // For all commands sent to us there must be a Reply call!
	  if (com == CMD_RUN || com == CMD_PAUSE) 
    {
      Reply(NOERROR);
	  } 
    else if (com != CMD_STOP) 
    {
      Reply((DWORD) E_UNEXPECTED);
      DbgLog((LOG_ERROR, 1, TEXT("Unexpected command!!!")));
	  }
  } while (com != CMD_STOP);

  m_bThreadRunning = false;  
  return S_FALSE;
}
Example #9
0
// vlakno na output
DWORD CAMROutputPin::ThreadProc()
{
	while (true) {
		DWORD cmd = GetRequest();
		switch (cmd) {
			case CMD_EXIT:		Reply(0); return 0; break;
			case CMD_STOP:
				{
					Reply(0); 
				}
				break;
			case CMD_RUN:
				{
					Reply(0);
					if (!IsConnected()) {
						break;
					}

					// deliver packets
					DWORD	cmd2;
					BOOL	is_first = true;
					DataPacketAMR	*packet;
					HRESULT	hr;

					do {
						if (ev_abort.Check()) {
							break;
						}
						hr = NOERROR;
					
						HANDLE	events[] = { ev_can_read, ev_abort};
						DWORD	ret = WaitForMultipleObjects(2, events, FALSE, 10);

						if (ret == WAIT_OBJECT_0) {
							// look for new packet in queue
							{
								CAutoLock	lck(&lock_queue);
								packet = queue.RemoveHead();
								if (queue.IsEmpty()) {
									ev_can_read.Reset();
								}

								// allow buffering
								if (GetBufferTime_MS() < buffer_time_ms) {
									ev_can_write.Set();
								}
							}

							// bud dorucime End Of Stream, alebo packet
							if (packet->type == DataPacketAMR::PACKET_TYPE_EOS) {
								DeliverEndOfStream();
							} else if (packet->type == DataPacketAMR::PACKET_TYPE_NEW_SEGMENT) {
								hr = DeliverNewSegment(packet->rtStart, packet->rtStop, packet->rate);
							} else if (packet->type == DataPacketAMR::PACKET_TYPE_DATA) {
								hr = DeliverDataPacketAMR(*packet);
							}					

							delete packet;

							if (FAILED(hr)) {
								break;
							}
						}
					} while (!CheckRequest(&cmd2));
				}
				break;
			default:
				Reply(E_UNEXPECTED); 
				break;
		}
	}
	return 0;
}
Example #10
0
HRESULT CAudioPin::FillBuffer(IMediaSample *pSample)
{
  try
  {
    Packet* buffer = NULL;

    do
    {
      if (m_demux.m_bAudioWaitForSeek)
      {
        m_demux.m_bAudioWaitForSeek = false;
        m_bSeekDone = false;
      }

      if (!m_bSeekDone || m_pFilter->IsStopping() || m_bFlushing || m_demux.IsMediaChanging() || m_demux.m_bRebuildOngoing || 
        m_demux.m_eAudioClipSeen->Check())
      {
        Sleep(1);
        return ERROR_NO_DATA;
      }

      if (m_pCachedBuffer)
      {
        LogDebug("aud: cached fetch %6.3f clip: %d playlist: %d", m_pCachedBuffer->rtStart / 10000000.0, m_pCachedBuffer->nClipNumber, m_pCachedBuffer->nPlaylist);
        buffer = m_pCachedBuffer;
        m_pCachedBuffer = NULL;
      }
      else
        buffer = m_demux.GetAudio();

      if (m_demux.EndOfFile())
      {
        LogDebug("aud: set EOF");
        m_demux.m_eAudioClipSeen->Set();
        return S_FALSE;
      }

      if (!buffer)
      {
        if (m_bFirstSample)
          Sleep(10);
        else 
        {
          if (!m_bClipEndingNotified)
          {
            // Deliver end of stream notification to allow audio renderer to stop buffering.
            // This should only happen when the stream enters into paused state
            //LogDebug("aud: FillBuffer - DeliverEndOfStream");
            //DeliverEndOfStream();
            m_bClipEndingNotified = true;
          }
          else
            Sleep(10);

          return ERROR_NO_DATA;
        }
      }
      else
      {
        bool checkPlaybackState = false;
        REFERENCE_TIME rtStart = m_rtStart;

        //JoinAudioBuffers(buffer, &demux);
        
        {
          CAutoLock lock(m_section);

          if (m_demux.m_bAudioResetStreamPosition)
          {
            m_demux.m_bAudioResetStreamPosition = false;
            m_bZeroTimeStream = true;
          }

          if ((buffer->nNewSegment & NS_NEW_CLIP) == NS_NEW_CLIP)
          {
            LogDebug("aud: Playlist changed to %d - nNewSegment: %d offset: %6.3f rtStart: %6.3f rtPlaylistTime: %6.3f", 
              buffer->nPlaylist, buffer->nNewSegment, buffer->rtOffset / 10000000.0, buffer->rtStart / 10000000.0, buffer->rtPlaylistTime / 10000000.0);

            checkPlaybackState = true;
            m_bClipEndingNotified = false;

            m_demux.m_eAudioClipSeen->Set();
          }

          // Do not convert LPCM to PCM if audio decoder supports LPCM (LAV audio decoder style)
          if (!m_bUsePCM && buffer->pmt && buffer->pmt->subtype == MEDIASUBTYPE_PCM)
            buffer->pmt->subtype = MEDIASUBTYPE_BD_LPCM_AUDIO;

          if (buffer->pmt && m_mt != *buffer->pmt && !((buffer->nNewSegment & NS_NEW_CLIP)==NS_NEW_CLIP))
          {
            HRESULT hrAccept = S_FALSE;
            LogMediaType(buffer->pmt);

            if (m_pPinConnection && false) // TODO - DS audio renderer seems to be only one that supports this
              hrAccept = m_pPinConnection->DynamicQueryAccept(buffer->pmt);
            else if (m_pReceiver)
            {
              //LogDebug("aud: DynamicQueryAccept - not avail");
              GUID guid = buffer->pmt->subtype;
              if (buffer->pmt->subtype == MEDIASUBTYPE_PCM)
              {
                buffer->pmt->subtype = MEDIASUBTYPE_BD_LPCM_AUDIO;
                hrAccept = m_pReceiver->QueryAccept(buffer->pmt);
              }
              
              if (hrAccept != S_OK)
              {
                buffer->pmt->subtype = guid;
                hrAccept = m_pReceiver->QueryAccept(buffer->pmt);
                m_bUsePCM = true;
              }
              else
                m_bUsePCM = false;
            }

            if (hrAccept != S_OK)
            {
              CMediaType mt(*buffer->pmt);
              SetMediaType(&mt);

              LogDebug("aud: graph rebuilding required");

              m_demux.m_bAudioRequiresRebuild = true;
              checkPlaybackState = true;

              DeliverEndOfStream();
            }
            else
            {
              LogDebug("aud: format change accepted");
              CMediaType mt(*buffer->pmt);
              SetMediaType(&mt);
              pSample->SetMediaType(&mt);
              m_pCachedBuffer = buffer;

              return ERROR_NO_DATA;
            }
          }
        } // lock ends

        if (checkPlaybackState)
        {
          m_pCachedBuffer = buffer;
          LogDebug("aud: cached push  %6.3f clip: %d playlist: %d", m_pCachedBuffer->rtStart / 10000000.0, m_pCachedBuffer->nClipNumber, m_pCachedBuffer->nPlaylist);
          
          if (checkPlaybackState)
          {
            if (buffer->pmt && m_mt != *buffer->pmt && !((buffer->nNewSegment & NS_NEW_CLIP)==NS_NEW_CLIP))
            {
              CMediaType mt(*buffer->pmt);
              SetMediaType(&mt);
            }
          }
          m_pCachedBuffer->nNewSegment = 0;

          return ERROR_NO_DATA;
        }
  
        bool hasTimestamp = buffer->rtStart != Packet::INVALID_TIME;

        REFERENCE_TIME rtCorrectedStartTime = 0;
        REFERENCE_TIME rtCorrectedStopTime = 0;

        if (hasTimestamp && m_dRateSeeking == 1.0)
        {
          bool setPMT = false;

          if (m_bDiscontinuity || buffer->bDiscontinuity)
          {
            LogDebug("aud: set discontinuity");
            pSample->SetDiscontinuity(true);
            setPMT = true;
            m_bDiscontinuity = false;
          }

          if (buffer->pmt || setPMT)
          {
            LogDebug("aud: set PMT");
            pSample->SetMediaType(buffer->pmt);
            m_bDiscontinuity = false;          
          }

          if (hasTimestamp)
          {
            if (m_bZeroTimeStream)
            {
              m_rtStreamTimeOffset = buffer->rtStart - buffer->rtClipStartTime;
              m_bZeroTimeStream=false;
            }
            // Now we have the final timestamp, set timestamp in sample
            //REFERENCE_TIME refTime=(REFERENCE_TIME)cRefTimeStart;
            //refTime /= m_dRateSeeking; //the if rate===1.0 makes this redundant

            pSample->SetSyncPoint(true); // allow all packets to be seeking targets
            rtCorrectedStartTime = buffer->rtStart - m_rtStreamTimeOffset;//- m_rtStart;
            rtCorrectedStopTime = buffer->rtStop - m_rtStreamTimeOffset;// - m_rtStart;
            pSample->SetTime(&rtCorrectedStartTime, &rtCorrectedStopTime);
          }
          else
          {
            // Buffer has no timestamp
            pSample->SetTime(NULL, NULL);
            pSample->SetSyncPoint(false);
          }

          {
            CAutoLock lock(&m_csDeliver);

            if (!m_bFlushing)
            {
              ProcessAudioSample(buffer, pSample);
#ifdef LOG_AUDIO_PIN_SAMPLES
             LogDebug("aud: %6.3f corr %6.3f Playlist time %6.3f clip: %d playlist: %d", buffer->rtStart / 10000000.0, rtCorrectedStartTime / 10000000.0,
                buffer->rtPlaylistTime / 10000000.0, buffer->nClipNumber, buffer->nPlaylist);
#endif
            }
            else
            {
              LogDebug("aud: dropped sample as flush is active!");
              delete buffer;
              return ERROR_NO_DATA;
            }
          }

          m_bFirstSample = false;
          delete buffer;
        }
        else
        { // Buffer was not displayed because it was out of date, search for next.
          delete buffer;
          buffer = NULL;
        }
      }
    } while (!buffer);
    return NOERROR;
  }

  // Should we return something else than NOERROR when hitting an exception?
  catch (int e)
  {
    LogDebug("aud: FillBuffer exception %d", e);
  }
  catch (...)
  {
    LogDebug("aud: FillBuffer exception ...");
  }

  return NOERROR;
}
Example #11
0
HRESULT CMPVlcSourceStream::DoBufferProcessingLoop(void)
{
    Command com;
    HRESULT result = S_OK;
    BOOL bStop = false;

    OnThreadStartPlay();

    LogInfo("Starting grabber thread");

    if (m_exec)
    {
        LogInfo("Executing external command: %s %s", m_exec, m_exec_opt);
        ::ShellExecuteA(0, NULL, m_exec, m_exec_opt, NULL, SW_HIDE);
        Sleep(m_exec_wait);
    }

    //libvlc_vlm_seek_media(m_vlc, "vlc_ds_stream", 0);

    if (libvlc_vlm_play_media (m_vlc, "vlc_ds_stream") != 0)
    {
        LogError("libvlc_vlm_play_media failed");
        return S_FALSE;
    }

    OVERLAPPED o;
    o.hEvent = CreateEvent( NULL, FALSE, FALSE, NULL);
    o.Internal = o.InternalHigh = o.Offset = o.OffsetHigh = 0;

    ConnectNamedPipe(m_hPipe, &o);

    WaitForSingleObject(o.hEvent, 20000);
    BOOL fConnected = HasOverlappedIoCompleted(&o);

    SetThreadPriority(m_hThread, THREAD_PRIORITY_TIME_CRITICAL);

    if (!fConnected)
    {
        LogError("ConnectNamedPipe failed");
        CancelIo(m_hPipe);
        CloseHandle(o.hEvent);
        return S_FALSE;
    }
    else do
        {
            BOOL requestAvail = FALSE;
            while ((requestAvail = CheckRequest(&com)) == FALSE)
            {
                //LogDebug ("Command: %d", com);

                IMediaSample *pSample;

                HRESULT hr = GetDeliveryBuffer(&pSample,NULL,NULL,0);
                if (FAILED(hr))
                    continue;

                // fill buffer
                // ------------------------------------------------------------------------------------
                hr = S_OK;
                BYTE *pData;
                DWORD cbData;

                CheckPointer(pSample, E_POINTER);
                // Access the sample's data buffer
                pSample->GetPointer((BYTE **)&pData);
                cbData = pSample->GetSize();

                DWORD startRecvTime = GetTickCount();
                m_buffsize = 0;

                do
                {
                    DWORD cbBytesRead = 0;
                    ResetEvent(o.hEvent);
                    o.Internal = o.InternalHigh = o.Offset = o.OffsetHigh = 0;
                    BOOL fSuccess = ReadFile( m_hPipe,  pData + m_buffsize,  cbData - m_buffsize,  &cbBytesRead, &o);

                    if (GetLastError() == ERROR_IO_PENDING)
                    {
                        for (int n=0; n < 20; n++)
                        {
                            if ((requestAvail = CheckRequest(&com)) == TRUE)
                                break;
                            if (WaitForSingleObject(o.hEvent, 1000) == WAIT_OBJECT_0)
                                break;
                        }
                        fSuccess = GetOverlappedResult(m_hPipe, &o, &cbBytesRead, false);
                    }

                    if (!fSuccess || cbBytesRead == 0)
                    {
                        CancelIo(m_hPipe);
                        break;
                    }
                    m_buffsize += cbBytesRead;

                } while ( !requestAvail && m_buffsize < (cbData  * 3 / 4)
                          && abs((signed long)(GetTickCount() - startRecvTime)) < 100);

                // ------------------------------------------------------------------------------------

                if (m_buffsize != 0 && !(requestAvail && com == CMD_STOP))
                {
                    LogDebug("Posting %d / %d bytes", m_buffsize, pSample->GetSize());

                    REFERENCE_TIME rtStart = startRecvTime;
                    REFERENCE_TIME rtStop  = GetTickCount();

                    pSample->SetTime(&rtStart, &rtStop);
                    pSample->SetActualDataLength(m_buffsize);
                    pSample->SetSyncPoint(TRUE);

                    hr = Deliver(pSample);
                    // downstream filter returns S_FALSE if it wants us to
                    // stop or an error if it's reporting an error.
                    if(hr != S_OK)
                    {
                        LogInfo("Deliver() returned %08x; stopping", hr);
                        bStop = true;
                    }

                } else
                {
                    // FillBuffer returned false
                    bStop = true;
                    DeliverEndOfStream();
                }

                pSample->Release();

                if (bStop)
                    break;
            }

            if (requestAvail)
            {
                LogInfo("Received command: %d", com);
                if (com == CMD_RUN || com == CMD_PAUSE) {
                    Reply(NOERROR);
                } else if (com != CMD_STOP) {
                    Reply((DWORD) E_UNEXPECTED);
                    LogDebug("Unexpected command %d!!!", com);
                }
            }
        } while (com != CMD_STOP && bStop == false);

    //DeliverEndOfStream();
    LogDebug("end loop");

    HANDLE hSDThread = CreateThread(NULL, 0, &VlcStreamDiscardThread, LPVOID(m_hPipe), 0, 0);

    libvlc_vlm_stop_media(m_vlc, "vlc_ds_stream");
    LogDebug("libvlc_vlm_stop_media");

    if (WaitForSingleObject(hSDThread, 30000) == WAIT_TIMEOUT)
    {
        DWORD ec;
        LogError("Terminating StreamDiscardThread!");
        GetExitCodeThread(hSDThread, &ec);
        TerminateThread(hSDThread, ec);
    }
    DisconnectNamedPipe(m_hPipe);
    LogDebug("DoBufferProcessingLoop end");

    CloseHandle(o.hEvent);
    return result;
}
Example #12
0
//
// DoBufferProcessingLoop
//
// Grabs a buffer and calls the users processing function.
// Overridable, so that different delivery styles can be catered for.
HRESULT CDynamicSourceStream::DoBufferProcessingLoop(void)
{
    Command com;
    bool fOutputFormatChanged = false;

    OnThreadStartPlay();

    do
    {
        while(!CheckRequest(&com))
        {


            // CAutoUsingOutputPin::CAutoUsingOutputPin() only changes the value of hr
            // if an error occurs.
            HRESULT hr = S_OK;

            CAutoUsingOutputPin auopUsingOutputPin(this, &hr);
            if(FAILED(hr))
            {
                FatalError(hr);
                return hr;
            }

            if(m_fReconnectOutputPin)
            {
                hr = DynamicReconnect(NULL);

                m_fReconnectOutputPin = false;

                if(FAILED(hr))
                {
                    FatalError(hr);
                    return hr;
                }

                fOutputFormatChanged = true;
            }

            IMediaSample *pSample;

            hr = GetDeliveryBuffer(&pSample,NULL,NULL,0);
            if(FAILED(hr))
            {
                Sleep(1);
                continue;   // go round again. Perhaps the error will go away
                // or the allocator is decommited & we will be asked to
                // exit soon.
            }

            if(fOutputFormatChanged)
            {
                pSample->SetDiscontinuity(TRUE);
                fOutputFormatChanged = false;
            }

            // Virtual function user will override.
            hr = FillBuffer(pSample);

            if(hr == S_OK)
            {
                hr = Deliver(pSample);
                pSample->Release();

                // downstream filter returns S_FALSE if it wants us to
                // stop or an error if it's reporting an error.
                if(hr != S_OK)
                {
                    DbgLog((LOG_TRACE, 2, TEXT("Deliver() returned %08x; stopping"), hr));
                    return S_OK;
                }

            }
            else if(hr == S_FALSE)
            {
                // derived class wants us to stop pushing data
                pSample->Release();
                DeliverEndOfStream();
                return S_OK;
            }
            else
            {
                // derived class encountered an error
                pSample->Release();
                DbgLog((LOG_ERROR, 1, TEXT("Error %08lX from FillBuffer!!!"), hr));

                FatalError(hr);
                return hr;
            }
            // all paths release the sample
        }

        // For all commands sent to us there must be a Reply call!
        if(com == CMD_RUN || com == CMD_PAUSE)
        {
            Reply(NOERROR);
        }
        else if(com != CMD_STOP)
        {
            Reply((DWORD) E_UNEXPECTED);
            DbgLog((LOG_ERROR, 1, TEXT("Unexpected command!!!")));
        }



    } while(com != CMD_STOP);

    return S_FALSE;
}
Example #13
0
DWORD CLAVOutputPin::ThreadProc()
{
  std::string name = "CLAVOutputPin " + std::string(CBaseDemuxer::CStreamList::ToString(m_pinType));
  SetThreadName(-1, name.c_str());

  m_hrDeliver = S_OK;
  m_fFlushing = m_fFlushed = false;
  m_eEndFlush.Set();
  bool bFailFlush = false;

  while(1) {
    Sleep(1);

    DWORD cmd;
    if(CheckRequest(&cmd)) {
      cmd = GetRequest();
      Reply(S_OK);
      ASSERT(cmd == CMD_EXIT);
      return 0;
    }

    size_t cnt = 0;
    do {
      Packet *pPacket = NULL;

      // Get a packet from the queue (scoped for lock)
      {
        CAutoLock cAutoLock(&m_queue);
        if((cnt = m_queue.Size()) > 0) {
          pPacket = m_queue.Get();
        }
      }

      // We need to check cnt instead of pPacket, since it can be NULL for EndOfStream
      if(m_hrDeliver == S_OK && cnt > 0) {
        ASSERT(!m_fFlushing);
        m_fFlushed = false;

        // flushing can still start here, to release a blocked deliver call
        HRESULT hr = pPacket ? DeliverPacket(pPacket) : DeliverEndOfStream();

        // .. so, wait until flush finished
        m_eEndFlush.Wait();

        if(hr != S_OK && !m_fFlushed) {
          DbgLog((LOG_TRACE, 10, L"OutputPin::ThreadProc(): Delivery failed on %s pin, hr: %0#.8x", CBaseDemuxer::CStreamList::ToStringW(GetPinType()), hr));
          if (!bFailFlush && hr == S_FALSE) {
            DbgLog((LOG_TRACE, 10, L"OutputPin::ThreadProc(): Trying to revive it by flushing..."));
            GetConnected()->BeginFlush();
            GetConnected()->EndFlush();
            bFailFlush = true;
          } else {
            m_hrDeliver = hr;
          }
          break;
        }
      } else if (pPacket) {
        // in case of stream switches or other events, we may end up here
        SAFE_DELETE(pPacket);
      }
    } while(cnt > 1 && m_hrDeliver == S_OK);
  }
  return 0;
}
Example #14
0
DWORD CBaseSplitterOutputPin::ThreadProc()
{
    SetThreadName(DWORD(-1), "CBaseSplitterOutputPin");
    m_hrDeliver = S_OK;
    m_fFlushing = m_fFlushed = false;
    m_eEndFlush.Set();

    // fix for Microsoft DTV-DVD Video Decoder - video freeze after STOP/PLAY
    bool iHaaliRenderConnect = false;
    CComPtr<IPin> pPinTo = this, pTmp;
    while (pPinTo && SUCCEEDED(pPinTo->ConnectedTo(&pTmp)) && (pPinTo = pTmp)) {
        pTmp = nullptr;
        CComPtr<IBaseFilter> pBF = GetFilterFromPin(pPinTo);
        if (GetCLSID(pBF) == CLSID_DXR) { // Haali Renderer
            iHaaliRenderConnect = true;
            break;
        }
        pPinTo = GetFirstPin(pBF, PINDIR_OUTPUT);
    }
    if (IsConnected() && !iHaaliRenderConnect) {
        GetConnected()->BeginFlush();
        GetConnected()->EndFlush();
    }

    for (;;) {
        Sleep(1);

        DWORD cmd;
        if (CheckRequest(&cmd)) {
            m_hThread = nullptr;
            cmd = GetRequest();
            Reply(S_OK);
            ASSERT(cmd == CMD_EXIT);
            return 0;
        }

        int cnt = 0;
        do {
            CAutoPtr<Packet> p;

            {
                CAutoLock cAutoLock(&m_queue);
                if ((cnt = m_queue.GetCount()) > 0) {
                    p = m_queue.Remove();
                }
            }

            if (S_OK == m_hrDeliver && cnt > 0) {
                ASSERT(!m_fFlushing);

                m_fFlushed = false;

                // flushing can still start here, to release a blocked deliver call

                HRESULT hr = p
                             ? DeliverPacket(p)
                             : DeliverEndOfStream();

                m_eEndFlush.Wait(); // .. so we have to wait until it is done

                if (hr != S_OK && !m_fFlushed) { // and only report the error in m_hrDeliver if we didn't flush the stream
                    // CAutoLock cAutoLock(&m_csQueueLock);
                    m_hrDeliver = hr;
                    break;
                }
            }
        } while (--cnt > 0);
    }
}
Example #15
0
HRESULT CVideoPin::FillBuffer(IMediaSample* pSample)
{
  try
  {
    Packet* buffer = NULL;

    do
    {
      if (m_pFilter->IsStopping() || m_demux.IsMediaChanging() || m_bFlushing || !m_bSeekDone || m_demux.m_bRebuildOngoing)
      {
        Sleep(1);
        return ERROR_NO_DATA;
      }

      if (m_demux.EndOfFile())
      {
        LogDebug("vid: set EOF");
        return S_FALSE;
      }

      if (m_demux.m_bVideoClipSeen || m_demux.m_bAudioRequiresRebuild && !m_demux.m_bVideoClipSeen && !m_demux.m_eAudioClipSeen->Check())
      {
        CheckPlaybackState();
        return ERROR_NO_DATA;
      }

      if (m_pCachedBuffer)
      {
        LogDebug("vid: cached fetch %6.3f clip: %d playlist: %d", m_pCachedBuffer->rtStart / 10000000.0, m_pCachedBuffer->nClipNumber, m_pCachedBuffer->nPlaylist);
        buffer = m_pCachedBuffer;
        m_pCachedBuffer = NULL;
        buffer->bDiscontinuity = true;
        
        if (m_bProvidePMT)
        {
          CMediaType mt(*buffer->pmt);
          SetMediaType(&mt);
          pSample->SetMediaType(&mt);
          m_bProvidePMT = false;
        }
      }
      else
        buffer = m_demux.GetVideo();

      if (!buffer)
      {
        if (m_bFirstSample)
          Sleep(10);
        else 
        {
          if (!m_bClipEndingNotified)
          {
            // Deliver end of stream notification to flush the video decoder.
            // This should only happen when the stream enters into paused state
            LogDebug("vid: FillBuffer - DeliverEndOfStream");
            DeliverEndOfStream();
            m_bClipEndingNotified = true;
          }
          else
            Sleep(10);
		  
          return ERROR_NO_DATA;
        }
      }
      else
      {
        bool checkPlaybackState = false;

        {
          CAutoLock lock(m_section);

          if (buffer->nNewSegment > 0)
          {
            if ((buffer->nNewSegment & NS_NEW_CLIP) == NS_NEW_CLIP)
            {
              LogDebug("vid: Playlist changed to %d - nNewSegment: %d offset: %6.3f rtStart: %6.3f rtPlaylistTime: %6.3f", 
                buffer->nPlaylist, buffer->nNewSegment, buffer->rtOffset / 10000000.0, buffer->rtStart / 10000000.0, buffer->rtPlaylistTime / 10000000.0);
            
              m_demux.m_bVideoClipSeen = true;
 
              m_bInitDuration = true;
              checkPlaybackState = true;
              m_bClipEndingNotified = false;

              if (buffer->bResuming || buffer->nNewSegment & NS_INTERRUPTED)
              {
                m_bDoFakeSeek = true;
                m_rtStreamOffset = buffer->rtPlaylistTime;
                m_bZeroTimeStream = true;
                m_demux.m_bAudioResetStreamPosition = true;
              }
              else
                m_rtStreamOffset = 0;

              // LAV video decoder requires an end of stream notification to be able to provide complete video frames
              // to downstream filters in a case where we are waiting for the audio pin to see the clip boundary as
              // we cannot provide yet the next clip's PMT downstream since audio stream could require a rebuild
              if (m_currentDecoder == CLSID_LAVVideo && (buffer->nNewSegment & NS_NEW_PLAYLIST))
              {
                LogDebug("DeliverEndOFStream LAV Only for audio pin wait (%d,%d)", buffer->nPlaylist, buffer->nClipNumber);
                DeliverEndOfStream();
              }
            }
            if ((buffer->nNewSegment & NS_STREAM_RESET) == NS_STREAM_RESET)
              m_bInitDuration = true;
          }

          if (buffer->pmt)
          {
            GUID subtype = subtype = buffer->pmt->subtype;

            if (buffer->pmt->subtype == FOURCCMap('1CVW') && m_VC1Override != GUID_NULL)
            {
              buffer->pmt->subtype = m_VC1Override;
              LogDebug("vid: FillBuffer - force VC-1 GUID");
            }

            if (!CompareMediaTypes(buffer->pmt, &m_mt))
            {
              LogMediaType(buffer->pmt);
            
              HRESULT hrAccept = S_FALSE;
              m_bProvidePMT = true;

              if (m_pReceiver && CheckVideoFormat(&buffer->pmt->subtype, &m_currentDecoder))
              {
                // Currently no other video decoders than LAV seems to be compatible with
                // the dynamic format changes
                if (m_currentDecoder == CLSID_LAVVideo)
                hrAccept = m_pReceiver->QueryAccept(buffer->pmt);
              }

              if (hrAccept != S_OK)
              {
                CMediaType mt(*buffer->pmt);
                SetMediaType(&mt);

                LogDebug("vid: graph rebuilding required");

                m_demux.m_bVideoRequiresRebuild = true;
                m_bZeroTimeStream = true;
                checkPlaybackState = true;

                //LogDebug("DeliverEndOFStream for rebuild (%d,%d)", buffer->nPlaylist, buffer->nClipNumber);
                //DeliverEndOfStream();
              }
              else
              {
                LogDebug("vid: format change accepted");
                CMediaType mt(*buffer->pmt);
                SetMediaType(&mt);
                pSample->SetMediaType(&mt);

                buffer->nNewSegment = 0;
                m_pCachedBuffer = buffer;
				
                //if (m_currentDecoder == CLSID_LAVVideo)
                //{
                //  LogDebug("DeliverEndOFStream LAV Only (%d,%d)", buffer->nPlaylist, buffer->nClipNumber);
                //  DeliverEndOfStream();
                //}

                return ERROR_NO_DATA;
              }
            } // comparemediatypes
          }
        } // lock ends

        m_rtTitleDuration = buffer->rtTitleDuration;

        if (checkPlaybackState)
        {
          buffer->nNewSegment = 0;
          m_pCachedBuffer = buffer;

          CheckPlaybackState();

          LogDebug("vid: cached push  %6.3f clip: %d playlist: %d", m_pCachedBuffer->rtStart / 10000000.0, m_pCachedBuffer->nClipNumber, m_pCachedBuffer->nPlaylist);

          return ERROR_NO_DATA;
        }

        bool hasTimestamp = buffer->rtStart != Packet::INVALID_TIME;
        REFERENCE_TIME rtCorrectedStartTime = 0;
        REFERENCE_TIME rtCorrectedStopTime = 0;

        if (hasTimestamp)
        {
          if (m_bZeroTimeStream)
          {
            m_rtStreamTimeOffset = buffer->rtStart - buffer->rtClipStartTime;
            m_bZeroTimeStream = false;
          }

          if (m_bDiscontinuity || buffer->bDiscontinuity)
          {
            LogDebug("vid: set discontinuity");
            pSample->SetDiscontinuity(true);
            pSample->SetMediaType(buffer->pmt);
            m_bDiscontinuity = false;
          }

          rtCorrectedStartTime = buffer->rtStart - m_rtStreamTimeOffset;
          rtCorrectedStopTime = buffer->rtStop - m_rtStreamTimeOffset;

          pSample->SetTime(&rtCorrectedStartTime, &rtCorrectedStopTime);

          if (m_bInitDuration)
          {
            m_pFilter->SetTitleDuration(m_rtTitleDuration);
            m_pFilter->ResetPlaybackOffset(buffer->rtPlaylistTime - rtCorrectedStartTime);
            m_bInitDuration = false;
          }

          m_pFilter->OnPlaybackPositionChange();
        }
        else // Buffer has no timestamp
          pSample->SetTime(NULL, NULL);

        pSample->SetSyncPoint(buffer->bSyncPoint);

        {
          CAutoLock lock(&m_csDeliver);

          if (!m_bFlushing)
          {
            BYTE* pSampleBuffer;
            pSample->SetActualDataLength(buffer->GetDataSize());
            pSample->GetPointer(&pSampleBuffer);
            memcpy(pSampleBuffer, buffer->GetData(), buffer->GetDataSize());

            m_bFirstSample = false;

#ifdef LOG_VIDEO_PIN_SAMPLES
            LogDebug("vid: %6.3f corr %6.3f playlist time %6.3f clip: %d playlist: %d size: %d", buffer->rtStart / 10000000.0, rtCorrectedStartTime / 10000000.0, 
              buffer->rtPlaylistTime / 10000000.0, buffer->nClipNumber, buffer->nPlaylist, buffer->GetCount());
#endif
          }
          else
          {
            LogDebug("vid: dropped sample as flush is active!");
            return ERROR_NO_DATA;
          }
        }

        //static int iFrameNumber = 0;
        //LogMediaSample(pSample, iFrameNumber++);

        delete buffer;
      }
    } while (!buffer);
    return NOERROR;
  }

  catch(...)
  {
    LogDebug("vid: FillBuffer exception");
  }

  return S_OK;
}
HRESULT CMPIptvSourceStream::DoBufferProcessingLoop(void) 
{
  Command com;

  OnThreadStartPlay();

  WSADATA wsaData;
  WSAStartup(MAKEWORD(2, 2), &wsaData);

#ifdef logging
  LogDebug("Starting grabber thread");
#endif
  sockaddr_in addr;
  memset(&addr, 0, sizeof(addr));
  addr.sin_family = AF_INET;
  if (localip) {
    addr.sin_addr.s_addr = inet_addr(localip);
  } else {
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
  }
  addr.sin_port = htons((u_short)port);

  ip_mreq imr; 
  imr.imr_multiaddr.s_addr = inet_addr(ip);
  if (localip) {
    imr.imr_interface.s_addr = inet_addr(localip);
  } else {
    imr.imr_interface.s_addr = INADDR_ANY;
  }
  unsigned long nonblocking = 1;

  if((m_socket = socket(AF_INET, SOCK_DGRAM, 0)) >= 0)
  {
    /*		u_long argp = 1;
    ioctlsocket(m_socket, FIONBIO, &argp);
    */
    DWORD dw = TRUE;
    int dwLen = sizeof(dw);
    if(setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (const char*)&dw, sizeof(dw)) < 0)
    {
      closesocket(m_socket);
      m_socket = -1;
    }

    if(setsockopt(m_socket, SOL_SOCKET, SO_BROADCAST, (const char*)&dw, sizeof(dw)) < 0)
    {
      closesocket(m_socket);
      m_socket = -1;
    }

    getsockopt(m_socket, SOL_SOCKET, SO_RCVBUF, (char *)&dw, &dwLen);
#ifdef logging
    LogDebug("Socket receive buffer is: %d (%d)", dw, dwLen);

    LogDebug("Trying to set receive buffer to %d", IPTV_SOCKET_BUFFER_SIZE);
#endif
    dw = IPTV_SOCKET_BUFFER_SIZE;
    if(setsockopt(m_socket, SOL_SOCKET, SO_RCVBUF, (const char*)&dw, sizeof(dw)) < 0)
    {
      closesocket(m_socket);
      m_socket = -1;
    }

    dwLen = sizeof(dw);
    getsockopt(m_socket, SOL_SOCKET, SO_RCVBUF, (char *)&dw, &dwLen);
#ifdef logging
    LogDebug("New socket receive buffer is: %d (%d)", dw, dwLen);
#endif
    if (ioctlsocket(m_socket, FIONBIO, &nonblocking) != 0) {
      closesocket(m_socket);
      m_socket = -1;
    }

    if(bind(m_socket, (struct sockaddr*)&addr, sizeof(addr)) < 0)
    {
      closesocket(m_socket);
      m_socket = -1;
    }

    if(IN_MULTICAST(htonl(imr.imr_multiaddr.s_addr)))
    {
      int ret = setsockopt(m_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char*)&imr, sizeof(imr));
      if(ret < 0) ret = ::WSAGetLastError();
      ret = ret;
    }
  }

  SetThreadPriority(m_hThread, THREAD_PRIORITY_TIME_CRITICAL);

  int fromlen = sizeof(addr);

  m_buffsize = 0;
  timeval tv; //Will be used for select() below
  tv.tv_sec = 0;
  tv.tv_usec = 100000; //100 msec
  do 
  {
    BOOL requestAvail;
    while ((requestAvail = CheckRequest(&com)) == FALSE) 
    {
      DWORD startRecvTime;
      startRecvTime = GetTickCount();
#ifdef FILL_DIRECTLY_INTO_BUFFER
      IMediaSample *pSample;
      char *pData;
      long cbData;

      HRESULT hr = GetDeliveryBuffer(&pSample,NULL,NULL,0);
      if (FAILED(hr))
        continue;	
      CheckPointer(pSample, E_POINTER);
    // Access the sample's data buffer
      pSample->GetPointer((BYTE **)&pData);
      cbData = pSample->GetSize();
#endif
      do 
      {
        //Try to read the complete remaining buffer size
        //But stop reading after 100ms have passed (slow streams like internet radio)
#ifdef FILL_DIRECTLY_INTO_BUFFER
        int len = recvfrom(m_socket, &pData[m_buffsize], cbData - m_buffsize, 0, (SOCKADDR*)&addr, &fromlen);
#else
        int len = recvfrom(m_socket, &m_buffer[m_buffsize], IPTV_BUFFER_SIZE - m_buffsize, 0, (SOCKADDR*)&addr, &fromlen);
#endif
        if(len <= 0)
        {
          //Wait until there's something in the receive buffer
          fd_set myFDsocket;
          myFDsocket.fd_count = 1;
          myFDsocket.fd_array[0] = m_socket;
          int selectRet = select(0, &myFDsocket, NULL, NULL, &tv);
#ifdef logging
          LogDebug("select return code: %d", selectRet);
#endif
          continue; //On error or nothing read just repeat the loop
        }
#ifdef logging
        LogDebug("Read %d bytes at pos %d of %d", len, m_buffsize, IPTV_BUFFER_SIZE); 
#endif
        m_buffsize += len;
#ifdef FILL_DIRECTLY_INTO_BUFFER
      } while ((requestAvail = CheckRequest(&com)) == FALSE && m_buffsize < (cbData           * 3 / 4) && abs((signed long)(GetTickCount() - startRecvTime)) < 100);
#else
      } while ((requestAvail = CheckRequest(&com)) == FALSE && m_buffsize < (IPTV_BUFFER_SIZE * 3 / 4) && abs((signed long)(GetTickCount() - startRecvTime)) < 100);
#endif
      if (requestAvail) break;
#ifndef FILL_DIRECTLY_INTO_BUFFER
      if (m_buffsize == 0) continue; //100ms passed but no buffer received
      IMediaSample *pSample;
      HRESULT hr = GetDeliveryBuffer(&pSample,NULL,NULL,0);
      if (FAILED(hr))
      {
        continue;	
        // go round again. Perhaps the error will go away
        // or the allocator is decommited & we will be asked to
        // exit soon.
      }
#endif
      // fill buffer
      hr = FillBuffer(pSample);

      if (hr == S_OK) 
      {
        hr = Deliver(pSample);
        pSample->Release();

        // downstream filter returns S_FALSE if it wants us to
        // stop or an error if it's reporting an error.
        if(hr != S_OK)
        {
#ifdef logging
          LogDebug("Deliver() returned %08x; stopping", hr);
#endif
          if(m_socket >= 0) {closesocket(m_socket); m_socket = -1;}
          WSACleanup();
          return S_OK;
        }

      } else if (hr == S_FALSE) {
        // derived class wants us to stop pushing data
        pSample->Release();
        DeliverEndOfStream();
        if(m_socket >= 0) {closesocket(m_socket); m_socket = -1;}
        WSACleanup();
        return S_OK;
      } else {
        // derived class encountered an error
        pSample->Release();
#ifdef logging
        LogDebug("Error %08lX from FillBuffer!!!", hr);
#endif
        DeliverEndOfStream();
        m_pFilter->NotifyEvent(EC_ERRORABORT, hr, 0);
        if(m_socket >= 0) {closesocket(m_socket); m_socket = -1;}
        WSACleanup();
        return hr;
      }

      // all paths release the sample
    }

    // For all commands sent to us there must be a Reply call!

    if (com == CMD_RUN || com == CMD_PAUSE) {
      Reply(NOERROR);
    } else if (com != CMD_STOP) {
      Reply((DWORD) E_UNEXPECTED);
#ifdef logging
      LogDebug("Unexpected command %d!!!", com);
#endif
    }
  } while (com != CMD_STOP);
DWORD CAVIOutputPin::ThreadProc()
{
    CAVIScanner* scanner = m_pSplitter->GetAVIScanner();
    bool bFirst = true;
    REFERENCE_TIME tStart = 0;
    REFERENCE_TIME tStop = 0;
    REFERENCE_TIME duration = 0;
    bool bDeliverEOS = true;
    DWORD req = 0;
    HRESULT hr = S_OK;
    REFERENCE_TIME tSeekStart = 0;
    REFERENCE_TIME tSeekStop = 0;

     double dRate;
    m_pSplitter->GetSeekingParams(&tSeekStart, &tSeekStop, &dRate);
    DeliverNewSegment(tSeekStart, tSeekStop, dRate);
    int startPos = GetIndexStartPosEntry(tSeekStart);
    for (int i = startPos; i < m_pIndex->size(); i++)
    {
        const INDEXENTRY& entry = (*m_pIndex)[i];
        if (!entry.dwChunkLength)
            continue;
        CComPtr<IMediaSample> pSample;
        hr = GetNewSample(&pSample, entry.dwChunkLength);
        
        // Break out without calling EndOfStream if we're asked to
	    // do something different
	    if (CheckRequest(&req)) 
        {
            bDeliverEOS = false;          
            break;
        }


        if (bFirst)
        {
            bFirst = false;
            pSample->SetDiscontinuity(TRUE);
           

        }
        if (entry.dwFlags & AVIIF_INDEX)
            pSample->SetSyncPoint(TRUE);
        tStart = GetCurTime(i) - tSeekStart;
        tStop = GetCurTime(i+1)- tSeekStart;
       
        pSample->SetTime(&tStart,&tStop);
        if (tStart < 0 && tStop <= 0)
            pSample->SetPreroll(TRUE);

        BYTE* pbData = 0;
        pSample->GetPointer(&pbData);
        scanner->ReadData(entry.chunkOffset, entry.dwChunkLength, pbData);   
        hr = Deliver(pSample);
        if (FAILED(hr) || hr == S_FALSE)
        {
            while(true)
            {
                if (CheckRequest(&req)) 
                {
                    bDeliverEOS = false;          
                    break;
                }
                Sleep(100);
            }           
        }
    }
    if (bDeliverEOS)
        DeliverEndOfStream();

    req =GetRequest();
    Reply(S_OK);
    return 0;
}