예제 #1
0
STDMETHODIMP FakeOutputPin::PushBuffer(byte *buffer,
                                       __int64 start, __int64 stop,
                                       unsigned int size, bool discont)
{
    IMediaSample *pSample = NULL;

    if (start != -1) {
        start /= 100;
        stop /= 100;
    }

    HRESULT hres = GetDeliveryBuffer(&pSample, NULL, NULL, 0);
    if (hres == S_OK && pSample)
    {
        BYTE *sample_buffer;
        pSample->GetPointer(&sample_buffer);
        if(sample_buffer)
        {
            memcpy (sample_buffer, buffer, size);
            pSample->SetActualDataLength(size);
        }
        pSample->SetDiscontinuity(discont);

        pSample->SetSyncPoint(TRUE);
        pSample->SetPreroll(FALSE);

        if (start != -1)
            pSample->SetTime(&start, &stop);

        hres = Deliver(pSample);
        pSample->Release();
    }

    return S_OK;
}
예제 #2
0
HRESULT CTSParserOutputPin::SendOut( DWORD nGroupFlag, const BYTE* pData, DWORD dwBytes, DWORD* dwUsedBytes )
{
    IMediaSample *pSample;
    BYTE *pSampleData;
    DWORD cbData;
	*dwUsedBytes = 0;

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

    pSample->GetPointer(&pSampleData);
    cbData = pSample->GetSize();
	if ( cbData < dwBytes )
	{
		dwBytes = cbData;
		ASSERT( 0 );
	}

	memcpy( pSampleData, pData, dwBytes );
	pSample->SetActualDataLength( dwBytes );
	*dwUsedBytes = dwBytes;

	hr = Deliver(pSample);
    pSample->Release();

	return S_OK;
}
예제 #3
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;
}
예제 #4
0
HRESULT OutputPin::Push(void *buf, long size)
{
    HRESULT hr;
    IMediaSample *pSample;
    VIDEOINFOHEADER *vi;
    AM_MEDIA_TYPE *pmt;
    BYTE *dst_buf;

    /**
     * Hold the critical section here as the pin might get disconnected
     * during the Deliver() method call.
     */
    m_pLock->Lock();

    hr = GetDeliveryBuffer(&pSample, NULL, NULL, 0);
    if (FAILED(hr))
        goto on_error;

    pSample->GetMediaType(&pmt);
    if (pmt) {
        mediaType.Set(*pmt);
        bufSize = pmt->lSampleSize;
    }

    pSample->GetPointer(&dst_buf);
    vi = (VIDEOINFOHEADER *)mediaType.pbFormat;
    if (vi->rcSource.right == vi->bmiHeader.biWidth) {
        assert(pSample->GetSize() >= size);
        memcpy(dst_buf, buf, size);
    } else {
        unsigned i, bpp;
        unsigned dststride, srcstride;
        BYTE *src_buf = (BYTE *)buf;

        bpp = size / abs(vi->bmiHeader.biHeight) / vi->rcSource.right;
        dststride = vi->bmiHeader.biWidth * bpp;
        srcstride = vi->rcSource.right * bpp;
        for (i = abs(vi->bmiHeader.biHeight); i > 0; i--) {
            memcpy(dst_buf, src_buf, srcstride);
            dst_buf += dststride;
            src_buf += srcstride;
        }
    }
    pSample->SetActualDataLength(size);

    hr = Deliver(pSample);

    pSample->Release();

on_error:
    m_pLock->Unlock();
    return hr;
}
예제 #5
0
HRESULT COutputPin::DeliverSample(GstBuffer *pBuffer)
{
    HRESULT hr = S_OK;
    IMediaSample *pSample = NULL;
    REFERENCE_TIME start = -1;
    REFERENCE_TIME stop = -1;

    hr = m_pAlloc->SetGstBuffer(pBuffer);
    if (FAILED(hr))
        return hr;

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

    // Set media time
    pSample->SetMediaTime(NULL, NULL);

    // Set time
    if (GST_BUFFER_TIMESTAMP_IS_VALID(pBuffer))
    {
        start = GST_BUFFER_TIMESTAMP(pBuffer) / 100;

        if (GST_BUFFER_DURATION_IS_VALID(pBuffer))
        {
            stop = (GST_BUFFER_TIMESTAMP(pBuffer) + GST_BUFFER_DURATION(pBuffer)) / 100;
        }
        else
        {
            stop = start + 1;
        }

        if (stop <= start) // Sometimes it may happen
            stop = start + 1;

        pSample->SetTime(&start, &stop);
    }
    else
    {
        pSample->SetTime(NULL, NULL);
    }

    if (GST_BUFFER_IS_DISCONT(pBuffer))
        pSample->SetDiscontinuity(TRUE);

    hr = Deliver(pSample);
    pSample->Release();
    if (FAILED(hr))
        return hr;

    return S_OK;
}
예제 #6
0
HRESULT CDXVADecoder::DisplayNextFrame()
{
	HRESULT					hr = S_FALSE;
	CComPtr<IMediaSample>	pSampleToDeliver;
	int						nPicIndex;

	nPicIndex = FindOldestFrame();
	if (nPicIndex != -1) {
		if (m_pPictureStore[nPicIndex].rtStart >= 0) {
			switch (m_nEngine) {
				case ENGINE_DXVA1 :
					// For DXVA1, query a media sample at the last time (only one in the allocator)
					hr = GetDeliveryBuffer (m_pPictureStore[nPicIndex].rtStart, m_pPictureStore[nPicIndex].rtStop, &pSampleToDeliver);
					SetTypeSpecificFlags(&m_pPictureStore[nPicIndex], pSampleToDeliver);
					if (SUCCEEDED (hr)) {
						hr = m_pAMVideoAccelerator->DisplayFrame(nPicIndex, pSampleToDeliver);
					}
					break;
				case ENGINE_DXVA2 :
					// For DXVA2 media sample is in the picture store
					m_pPictureStore[nPicIndex].pSample->SetTime (&m_pPictureStore[nPicIndex].rtStart, &m_pPictureStore[nPicIndex].rtStop);
					SetTypeSpecificFlags(&m_pPictureStore[nPicIndex], m_pPictureStore[nPicIndex].pSample);
					hr = m_pFilter->GetOutputPin()->Deliver(m_pPictureStore[nPicIndex].pSample);
					break;
			}

#if defined(_DEBUG) && 0
			static REFERENCE_TIME	rtLast = 0;
			TRACE ("Deliver : %10I64d - %10I64d   (Dur = %10I64d) {Delta = %10I64d}   Ind = %02d  Codec=%d  Ref=%d\n",
				   m_pPictureStore[nPicIndex].rtStart,
				   m_pPictureStore[nPicIndex].rtStop,
				   m_pPictureStore[nPicIndex].rtStop - m_pPictureStore[nPicIndex].rtStart,
				   m_pPictureStore[nPicIndex].rtStart - rtLast, nPicIndex,
				   m_pPictureStore[nPicIndex].nCodecSpecific,
				   m_pPictureStore[nPicIndex].bRefPicture);
			rtLast = m_pPictureStore[nPicIndex].rtStart;
#endif
		}
		m_bNeedChangeAspect = false;

		m_pPictureStore[nPicIndex].bDisplayed = true;
		if (!m_pPictureStore[nPicIndex].bRefPicture) {
			FreePictureSlot (nPicIndex);
		}
	}

	return hr;
}
예제 #7
0
HRESULT CDXVADecoder::GetFreeSurfaceIndex(int& nSurfaceIndex, IMediaSample** ppSampleToDeliver, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop)
{
    HRESULT hr = E_UNEXPECTED;
    int nPos = -1;
    DWORD dwMinDisplay = MAXDWORD;

    if (m_nFieldSurface != -1) {
        nSurfaceIndex = m_nFieldSurface;
        *ppSampleToDeliver = m_pFieldSample.Detach();
        return S_FALSE;
    }

    switch (m_nEngine) {
        case ENGINE_DXVA1:
            for (int i = 0; i < m_nPicEntryNumber; i++) {
                if (!m_pPictureStore[i].bInUse && m_pPictureStore[i].dwDisplayCount < dwMinDisplay) {
                    dwMinDisplay = m_pPictureStore[i].dwDisplayCount;
                    nPos  = i;
                }
            }

            if (nPos != -1) {
                nSurfaceIndex = nPos;
                return S_OK;
            }

            // Ho ho...
            ASSERT(FALSE);
            Flush();
            break;
        case ENGINE_DXVA2:
            CComPtr<IMediaSample> pNewSample;
            CComQIPtr<IMPCDXVA2Sample> pMPCDXVA2Sample;
            // TODO : test  IDirect3DDeviceManager9::TestDevice !!!
            if (SUCCEEDED(hr = GetDeliveryBuffer(rtStart, rtStop, &pNewSample))) {
                pMPCDXVA2Sample = pNewSample;
                nSurfaceIndex = pMPCDXVA2Sample ? pMPCDXVA2Sample->GetDXSurfaceId() : 0;
                *ppSampleToDeliver = pNewSample.Detach();
            }
            break;
    }

    return hr;
}
예제 #8
0
HRESULT CAMROutputPin::DeliverDataPacketAMR(DataPacketAMR &packet)
{
	IMediaSample *sample;
	HRESULT hr = GetDeliveryBuffer(&sample, NULL, NULL, 0);
	if (FAILED(hr)) {
		return E_FAIL;
	}

	// we should have enough space in there
	long lsize = sample->GetSize();
	ASSERT(lsize >= packet.size);

	BYTE *buf;
	sample->GetPointer(&buf);

	memcpy(buf, packet.buf, packet.size);
	sample->SetActualDataLength(packet.size);

	// sync point, discontinuity ?
	if (packet.sync_point) {
		sample->SetSyncPoint(TRUE);
	} else {
		sample->SetSyncPoint(FALSE);
	}

	if (packet.discontinuity) { 
		sample->SetDiscontinuity(TRUE); 
	} else { 
		sample->SetDiscontinuity(FALSE); 
	}

	// do we have a time stamp ?
	if (packet.has_time) { 
		sample->SetTime(&packet.rtStart, &packet.rtStop); 
	}

	// dorucime
	hr = Deliver(sample);	
	sample->Release();
	return hr;
}
예제 #9
0
HRESULT CLAVOutputPin::DeliverPacket(Packet *pPacket)
{
  HRESULT hr = S_OK;
  IMediaSample *pSample = nullptr;

  long nBytes = (long)pPacket->GetDataSize();

  if(nBytes == 0) {
    goto done;
  }

  CHECK_HR(hr = GetDeliveryBuffer(&pSample, nullptr, nullptr, 0));

  if (m_bPacketAllocator) {
    ILAVMediaSample *pLAVSample = nullptr;
    CHECK_HR(hr = pSample->QueryInterface(&pLAVSample));
    CHECK_HR(hr = pLAVSample->SetPacket(pPacket));
    SafeRelease(&pLAVSample);
  } else {
    // Resize buffer if it is too small
    // This can cause a playback hick-up, we should avoid this if possible by setting a big enough buffer size
    if(nBytes > pSample->GetSize()) {
      SafeRelease(&pSample);
      ALLOCATOR_PROPERTIES props, actual;
      CHECK_HR(hr = m_pAllocator->GetProperties(&props));
      // Give us 2 times the requested size, so we don't resize every time
      props.cbBuffer = nBytes*2;
      if(props.cBuffers > 1) {
        CHECK_HR(hr = __super::DeliverBeginFlush());
        CHECK_HR(hr = __super::DeliverEndFlush());
      }
      CHECK_HR(hr = m_pAllocator->Decommit());
      CHECK_HR(hr = m_pAllocator->SetProperties(&props, &actual));
      CHECK_HR(hr = m_pAllocator->Commit());
      CHECK_HR(hr = GetDeliveryBuffer(&pSample, nullptr, nullptr, 0));
    }

    // Fill the sample
    BYTE* pData = nullptr;
    if(FAILED(hr = pSample->GetPointer(&pData)) || !pData) goto done;

    memcpy(pData, pPacket->GetData(), nBytes);
  }

  if(pPacket->pmt) {
    DbgLog((LOG_TRACE, 10, L"::DeliverPacket() - sending new media type to decoder"));
    pSample->SetMediaType(pPacket->pmt);
    pPacket->bDiscontinuity = true;

    CAutoLock cAutoLock(m_pLock);
    CMediaType pmt = *(pPacket->pmt);
    m_mts.clear();
    m_mts.push_back(pmt);
    pPacket->pmt = nullptr;

    SetMediaType(&pmt);
  }

  bool fTimeValid = pPacket->rtStart != Packet::INVALID_TIME;

  // IBitRateInfo
  m_BitRate.nBytesSinceLastDeliverTime += nBytes;

  if (fTimeValid) {
    if (m_BitRate.rtLastDeliverTime == Packet::INVALID_TIME) {
      m_BitRate.rtLastDeliverTime = pPacket->rtStart;
      m_BitRate.nBytesSinceLastDeliverTime = 0;
    }

    if (m_BitRate.rtLastDeliverTime + 10000000 < pPacket->rtStart) {
      REFERENCE_TIME rtDiff = pPacket->rtStart - m_BitRate.rtLastDeliverTime;

      double dSecs, dBits;

      dSecs = rtDiff / 10000000.0;
      dBits = 8.0 * m_BitRate.nBytesSinceLastDeliverTime;
      m_BitRate.nCurrentBitRate = (DWORD)(dBits / dSecs);

      m_BitRate.rtTotalTimeDelivered += rtDiff;
      m_BitRate.nTotalBytesDelivered += m_BitRate.nBytesSinceLastDeliverTime;

      dSecs = m_BitRate.rtTotalTimeDelivered / 10000000.0;
      dBits = 8.0 * m_BitRate.nTotalBytesDelivered;
      m_BitRate.nAverageBitRate = (DWORD)(dBits / dSecs);

      m_BitRate.rtLastDeliverTime = pPacket->rtStart;
      m_BitRate.nBytesSinceLastDeliverTime = 0;
    }
  }

  CHECK_HR(hr = pSample->SetActualDataLength(nBytes));
  CHECK_HR(hr = pSample->SetTime(fTimeValid ? &pPacket->rtStart : nullptr, fTimeValid ? &pPacket->rtStop : nullptr));
  CHECK_HR(hr = pSample->SetMediaTime(nullptr, nullptr));
  CHECK_HR(hr = pSample->SetDiscontinuity(pPacket->bDiscontinuity));
  CHECK_HR(hr = pSample->SetSyncPoint(pPacket->bSyncPoint));
  CHECK_HR(hr = pSample->SetPreroll(fTimeValid && pPacket->rtStart < 0));
  // Deliver
  CHECK_HR(hr = Deliver(pSample));

done:
  if (!m_bPacketAllocator || !pSample)
    SAFE_DELETE(pPacket);
  SafeRelease(&pSample);
  return hr;
}
예제 #10
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;
}
예제 #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;
}
예제 #12
0
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);
예제 #13
0
HRESULT CLAVAudio::DeliverBitstream(AVCodecID codec, const BYTE *buffer, DWORD dwSize, DWORD dwFrameSize, REFERENCE_TIME rtStartInput, REFERENCE_TIME rtStopInput)
{
  HRESULT hr = S_OK;

  CMediaType mt = CreateBitstreamMediaType(codec, m_bsParser.m_dwSampleRate);
  WAVEFORMATEX* wfe = (WAVEFORMATEX*)mt.Format();

  if(FAILED(hr = ReconnectOutput(dwSize, mt))) {
    return hr;
  }

  IMediaSample *pOut;
  BYTE *pDataOut = NULL;
  if(FAILED(GetDeliveryBuffer(&pOut, &pDataOut))) {
    return E_FAIL;
  }

  REFERENCE_TIME rtStart = m_rtStart, rtStop = AV_NOPTS_VALUE;
  // TrueHD timings
  // Since the SPDIF muxer takes 24 frames and puts them into one IEC61937 frame, we use the cached timestamp from before.
  if (codec == AV_CODEC_ID_TRUEHD) {
    // long-term cache is valid
    if (m_rtBitstreamCache != AV_NOPTS_VALUE)
      rtStart = m_rtBitstreamCache;
    // Duration - stop time of the current frame is valid
    if (rtStopInput != AV_NOPTS_VALUE)
      rtStop = rtStopInput;
    else // no actual time of the current frame, use typical TrueHD frame size, 24 * 0.83333ms
      rtStop = rtStart + (REFERENCE_TIME)(200000 / m_dRate);
    m_rtStart = rtStop;
  } else {
    double dDuration = DBL_SECOND_MULT * (double)m_bsParser.m_dwSamples / m_bsParser.m_dwSampleRate / m_dRate;
    m_dStartOffset += fmod(dDuration, 1.0);

    // Add rounded duration to rtStop
    rtStop = rtStart + (REFERENCE_TIME)(dDuration + 0.5);
    // and unrounded to m_rtStart..
    m_rtStart += (REFERENCE_TIME)dDuration;
    // and accumulate error..
    if (m_dStartOffset > 0.5) {
      m_rtStart++;
      m_dStartOffset -= 1.0;
    }
  }

  REFERENCE_TIME rtJitter = rtStart - m_rtBitstreamCache;
  m_faJitter.Sample(rtJitter);

  REFERENCE_TIME rtJitterMin = m_faJitter.AbsMinimum();
  if (m_settings.AutoAVSync && abs(rtJitterMin) > m_JitterLimit && m_bHasVideo) {
    DbgLog((LOG_TRACE, 10, L"::Deliver(): corrected A/V sync by %I64d", rtJitterMin));
    m_rtStart -= rtJitterMin;
    m_faJitter.OffsetValues(-rtJitterMin);
    m_bDiscontinuity = TRUE;
  }

#ifdef DEBUG
  DbgLog((LOG_CUSTOM5, 20, L"Bitstream Delivery, rtStart(calc): %I64d, rtStart(input): %I64d, duration: %I64d, diff: %I64d", rtStart, m_rtBitstreamCache, rtStop-rtStart, rtJitter));

  if (m_faJitter.CurrentSample() == 0) {
    DbgLog((LOG_TRACE, 20, L"Jitter Stats: min: %I64d - max: %I64d - avg: %I64d", rtJitterMin, m_faJitter.AbsMaximum(), m_faJitter.Average()));
  }
#endif
  m_rtBitstreamCache = AV_NOPTS_VALUE;

  if(m_settings.AudioDelayEnabled) {
    REFERENCE_TIME rtDelay = (REFERENCE_TIME)((m_settings.AudioDelay * 10000i64) / m_dRate);
    rtStart += rtDelay;
    rtStop += rtDelay;
  }

  pOut->SetTime(&rtStart, &rtStop);
  pOut->SetMediaTime(NULL, NULL);

  pOut->SetPreroll(FALSE);
  pOut->SetDiscontinuity(m_bDiscontinuity);
  m_bDiscontinuity = FALSE;
  pOut->SetSyncPoint(TRUE);

  pOut->SetActualDataLength(dwSize);

  memcpy(pDataOut, buffer, dwSize);

  if(hr == S_OK) {
    hr = m_pOutput->GetConnected()->QueryAccept(&mt);
    if (hr == S_FALSE && m_nCodecId == AV_CODEC_ID_DTS && m_bDTSHD) {
      DbgLog((LOG_TRACE, 1, L"DTS-HD Media Type failed with %0#.8x, trying fallback to DTS core", hr));
      m_bForceDTSCore = TRUE;
      UpdateBitstreamContext();
      goto done;
    }
    DbgLog((LOG_TRACE, 1, L"Sending new Media Type (QueryAccept: %0#.8x)", hr));
    m_pOutput->SetMediaType(&mt);
    pOut->SetMediaType(&mt);
  }

  hr = m_pOutput->Deliver(pOut);
  if (FAILED(hr)) {
    DbgLog((LOG_ERROR, 10, L"::DeliverBitstream failed with code: %0#.8x", hr));
  }

done:
  SafeRelease(&pOut);
  return hr;
}
예제 #14
0
HRESULT CBaseSplitterOutputPin::DeliverPacket(CAutoPtr<Packet> p)
{
    HRESULT hr;

    long nBytes = (long)p->GetCount();

    if (nBytes == 0) {
        return S_OK;
    }

    m_brs.nBytesSinceLastDeliverTime += nBytes;

    if (p->rtStart != Packet::INVALID_TIME) {
        if (m_brs.rtLastDeliverTime == Packet::INVALID_TIME) {
            m_brs.rtLastDeliverTime = p->rtStart;
            m_brs.nBytesSinceLastDeliverTime = 0;
        }

        if (m_brs.rtLastDeliverTime + 10000000 < p->rtStart) {
            REFERENCE_TIME rtDiff = p->rtStart - m_brs.rtLastDeliverTime;

            double secs, bits;

            secs = (double)rtDiff / 10000000;
            bits = 8.0 * m_brs.nBytesSinceLastDeliverTime;
            m_brs.nCurrentBitRate = (DWORD)(bits / secs);

            m_brs.rtTotalTimeDelivered += rtDiff;
            m_brs.nTotalBytesDelivered += m_brs.nBytesSinceLastDeliverTime;

            secs = (double)m_brs.rtTotalTimeDelivered / 10000000;
            bits = 8.0 * m_brs.nTotalBytesDelivered;
            m_brs.nAverageBitRate = (DWORD)(bits / secs);

            m_brs.rtLastDeliverTime = p->rtStart;
            m_brs.nBytesSinceLastDeliverTime = 0;
            /*
                        TRACE(_T("[%d] c: %d kbps, a: %d kbps\n"),
                            p->TrackNumber,
                            (m_brs.nCurrentBitRate+500)/1000,
                            (m_brs.nAverageBitRate+500)/1000);
            */
        }

        double dRate = 1.0;
        if (SUCCEEDED((static_cast<CBaseSplitterFilter*>(m_pFilter))->GetRate(&dRate))) {
            p->rtStart = (REFERENCE_TIME)((double)p->rtStart / dRate);
            p->rtStop = (REFERENCE_TIME)((double)p->rtStop / dRate);
        }
    }

    do {
        CComPtr<IMediaSample> pSample;
        if (S_OK != (hr = GetDeliveryBuffer(&pSample, nullptr, nullptr, 0))) {
            break;
        }

        if (nBytes > pSample->GetSize()) {
            pSample.Release();

            ALLOCATOR_PROPERTIES props, actual;
            if (S_OK != (hr = m_pAllocator->GetProperties(&props))) {
                break;
            }
            props.cbBuffer = nBytes * 3 / 2;

            if (props.cBuffers > 1) {
                if (S_OK != (hr = __super::DeliverBeginFlush())) {
                    break;
                }
                if (S_OK != (hr = __super::DeliverEndFlush())) {
                    break;
                }
            }

            if (S_OK != (hr = m_pAllocator->Decommit())) {
                break;
            }
            if (S_OK != (hr = m_pAllocator->SetProperties(&props, &actual))) {
                break;
            }
            if (S_OK != (hr = m_pAllocator->Commit())) {
                break;
            }
            if (S_OK != (hr = GetDeliveryBuffer(&pSample, nullptr, nullptr, 0))) {
                break;
            }
        }

        if (p->pmt) {
            pSample->SetMediaType(p->pmt);
            p->bDiscontinuity = true;

            CAutoLock cAutoLock(m_pLock);
            m_mts.RemoveAll();
            m_mts.Add(*p->pmt);
        }

        bool fTimeValid = p->rtStart != Packet::INVALID_TIME;

#if defined(_DEBUG) && 0
        TRACE(_T("[%d]: d%d s%d p%d, b=%d, [%20I64d - %20I64d]\n"),
              p->TrackNumber,
              p->bDiscontinuity, p->bSyncPoint, fTimeValid && p->rtStart < 0,
              nBytes, p->rtStart, p->rtStop);
#endif

        ASSERT(!p->bSyncPoint || fTimeValid);

        BYTE* pData = nullptr;
        if (S_OK != (hr = pSample->GetPointer(&pData)) || !pData) {
            break;
        }
        memcpy(pData, p->GetData(), nBytes);
        if (S_OK != (hr = pSample->SetActualDataLength(nBytes))) {
            break;
        }
        if (S_OK != (hr = pSample->SetTime(fTimeValid ? &p->rtStart : nullptr, fTimeValid ? &p->rtStop : nullptr))) {
            break;
        }
        if (S_OK != (hr = pSample->SetMediaTime(nullptr, nullptr))) {
            break;
        }
        if (S_OK != (hr = pSample->SetDiscontinuity(p->bDiscontinuity))) {
            break;
        }
        if (S_OK != (hr = pSample->SetSyncPoint(p->bSyncPoint))) {
            break;
        }
        if (S_OK != (hr = pSample->SetPreroll(fTimeValid && p->rtStart < 0))) {
            break;
        }
        if (S_OK != (hr = Deliver(pSample))) {
            break;
        }
    } while (false);

    return hr;
}
예제 #15
0
파일: source.cpp 프로젝트: 9crk/EasyClient
//
// 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;
}
예제 #16
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;
}
예제 #17
0
HRESULT CLAVOutputPin::DeliverPacket(Packet *pPacket)
{
  HRESULT hr = S_OK;
  IMediaSample *pSample = NULL;

  long nBytes = (long)pPacket->GetDataSize();

  if(nBytes == 0) {
    goto done;
  }

  CHECK_HR(hr = GetDeliveryBuffer(&pSample, NULL, NULL, 0));

  if (m_bPacketAllocator) {
    ILAVMediaSample *pLAVSample = NULL;
    CHECK_HR(hr = pSample->QueryInterface(&pLAVSample));
    CHECK_HR(hr = pLAVSample->SetPacket(pPacket));
    SafeRelease(&pLAVSample);
  } else {
    // Resize buffer if it is too small
    // This can cause a playback hick-up, we should avoid this if possible by setting a big enough buffer size
    if(nBytes > pSample->GetSize()) {
      SafeRelease(&pSample);
      ALLOCATOR_PROPERTIES props, actual;
      CHECK_HR(hr = m_pAllocator->GetProperties(&props));
      // Give us 2 times the requested size, so we don't resize every time
      props.cbBuffer = nBytes*2;
      if(props.cBuffers > 1) {
        CHECK_HR(hr = __super::DeliverBeginFlush());
        CHECK_HR(hr = __super::DeliverEndFlush());
      }
      CHECK_HR(hr = m_pAllocator->Decommit());
      CHECK_HR(hr = m_pAllocator->SetProperties(&props, &actual));
      CHECK_HR(hr = m_pAllocator->Commit());
      CHECK_HR(hr = GetDeliveryBuffer(&pSample, NULL, NULL, 0));
    }

    // Fill the sample
    BYTE* pData = NULL;
    if(FAILED(hr = pSample->GetPointer(&pData)) || !pData) goto done;

    memcpy(pData, pPacket->GetData(), nBytes);
  }

  if(pPacket->pmt) {
    DbgLog((LOG_TRACE, 10, L"::DeliverPacket() - sending new media type to decoder"));
    pSample->SetMediaType(pPacket->pmt);
    pPacket->bDiscontinuity = true;

    CAutoLock cAutoLock(m_pLock);
    CMediaType pmt = *(pPacket->pmt);
    m_mts.clear();
    m_mts.push_back(pmt);
    pPacket->pmt = NULL;

    SetMediaType(&pmt);
  }

  bool fTimeValid = pPacket->rtStart != Packet::INVALID_TIME;

  CHECK_HR(hr = pSample->SetActualDataLength(nBytes));
  CHECK_HR(hr = pSample->SetTime(fTimeValid ? &pPacket->rtStart : NULL, fTimeValid ? &pPacket->rtStop : NULL));
  CHECK_HR(hr = pSample->SetMediaTime(NULL, NULL));
  CHECK_HR(hr = pSample->SetDiscontinuity(pPacket->bDiscontinuity));
  CHECK_HR(hr = pSample->SetSyncPoint(pPacket->bSyncPoint));
  CHECK_HR(hr = pSample->SetPreroll(fTimeValid && pPacket->rtStart < 0));
  // Deliver
  CHECK_HR(hr = Deliver(pSample));

done:
  if (!m_bPacketAllocator)
    SAFE_DELETE(pPacket);
  SafeRelease(&pSample);
  return hr;
}
예제 #18
0
GstFlowReturn VideoFakeSrcPin::PushBuffer(GstBuffer *buffer)
{
    IMediaSample *pSample = NULL;
    byte *data = GST_BUFFER_DATA (buffer);
    int attempts = 0;
    HRESULT hres;
    BYTE *sample_buffer;
    AM_MEDIA_TYPE *mediatype;

    StartUsingOutputPin();

    while (attempts < MAX_ATTEMPTS)
    {
        hres = GetDeliveryBuffer(&pSample, NULL, NULL, 0);
        if (SUCCEEDED (hres))
            break;
        attempts++;
        Sleep(100);
    }

    if (FAILED (hres))
    {
        StopUsingOutputPin();
        GST_WARNING ("Could not get sample for delivery to sink: %x", hres);
        return GST_FLOW_ERROR;
    }

    pSample->GetPointer(&sample_buffer);
    pSample->GetMediaType(&mediatype);
    if (mediatype)
        SetMediaType (mediatype);

    if(sample_buffer)
    {
        /* Copy to the destination stride.
         * This is not just a simple memcpy because of the different strides.
         * TODO: optimise for the same-stride case and avoid the copy entirely.
         */
        CopyToDestinationBuffer (data, sample_buffer);
    }

    pSample->SetDiscontinuity(FALSE); /* Decoded frame; unimportant */
    pSample->SetSyncPoint(TRUE); /* Decoded frame; always a valid syncpoint */
    pSample->SetPreroll(FALSE); /* For non-displayed frames.
                                 Not used in GStreamer */

    /* Disable synchronising on this sample. We instead let GStreamer handle
     * this at a higher level, inside BaseSink. */
    pSample->SetTime(NULL, NULL);

    while (attempts < MAX_ATTEMPTS)
    {
        hres = Deliver(pSample);
        if (SUCCEEDED (hres))
            break;
        attempts++;
        Sleep(100);
    }

    pSample->Release();

    StopUsingOutputPin();

    if (SUCCEEDED (hres))
        return GST_FLOW_OK;
    else {
        GST_WARNING_OBJECT (this, "Failed to deliver sample: %x", hres);
        if (hres == VFW_E_NOT_CONNECTED)
            return GST_FLOW_NOT_LINKED;
        else
            return GST_FLOW_ERROR;
    }
}
HRESULT CBaseSplitterOutputPin::DeliverPacket(CAutoPtr<Packet> p)
{
	HRESULT hr;

	long nBytes = (long)p->GetCount();

	if (nBytes == 0) {
		return S_OK;
	}

	DWORD nFlag = (static_cast<CBaseSplitterFilter*>(m_pFilter))->GetFlag();

	if (p->rtStart != INVALID_TIME && (nFlag & PACKET_PTS_DISCONTINUITY)) {
		// Filter invalid PTS value (if too different from previous packet)
		if (!IsDiscontinuous() && !((nFlag & PACKET_PTS_VALIDATE_POSITIVE) && p->rtStart < 0)) {
			REFERENCE_TIME rt = p->rtStart + m_rtOffset;
			if (_abs64(rt - m_rtPrev) > MAX_PTS_SHIFT) {
				m_rtOffset += m_rtPrev - rt;
				DbgLog((LOG_TRACE, 3, L"CBaseSplitterOutputPin::DeliverPacket() : Packet discontinuity detected, adjusting offset to %I64d", m_rtOffset));
			}
		}

		p->rtStart	+= m_rtOffset;
		p->rtStop	+= m_rtOffset;

		m_rtPrev	= p->rtStart;
	}

	m_brs.nBytesSinceLastDeliverTime += nBytes;

	if (p->rtStart != INVALID_TIME) {
		if (m_brs.rtLastDeliverTime == INVALID_TIME) {
			m_brs.rtLastDeliverTime = p->rtStart;
			m_brs.nBytesSinceLastDeliverTime = 0;
		}

		if (m_brs.rtLastDeliverTime + 10000000 < p->rtStart) {
			REFERENCE_TIME rtDiff = p->rtStart - m_brs.rtLastDeliverTime;

			double secs, bits;

			secs = (double)rtDiff / 10000000;
			bits = 8.0 * m_brs.nBytesSinceLastDeliverTime;
			m_brs.nCurrentBitRate = (DWORD)(bits / secs);

			m_brs.rtTotalTimeDelivered += rtDiff;
			m_brs.nTotalBytesDelivered += m_brs.nBytesSinceLastDeliverTime;

			secs = (double)m_brs.rtTotalTimeDelivered / 10000000;
			bits = 8.0 * m_brs.nTotalBytesDelivered;
			m_brs.nAverageBitRate = (DWORD)(bits / secs);

			m_brs.rtLastDeliverTime = p->rtStart;
			m_brs.nBytesSinceLastDeliverTime = 0;
			/*
						TRACE(_T("[%d] c: %d kbps, a: %d kbps\n"),
							p->TrackNumber,
							(m_brs.nCurrentBitRate+500)/1000,
							(m_brs.nAverageBitRate+500)/1000);
			*/
		}

		double dRate = 1.0;
		if (SUCCEEDED((static_cast<CBaseSplitterFilter*>(m_pFilter))->GetRate(&dRate))) {
			p->rtStart = (REFERENCE_TIME)((double)p->rtStart / dRate);
			p->rtStop = (REFERENCE_TIME)((double)p->rtStop / dRate);
		}
	}

	do {
		CComPtr<IMediaSample> pSample;
		if (S_OK != (hr = GetDeliveryBuffer(&pSample, NULL, NULL, 0))) {
			break;
		}

		if (nBytes > pSample->GetSize()) {
			pSample.Release();

			ALLOCATOR_PROPERTIES props, actual;
			if (S_OK != (hr = m_pAllocator->GetProperties(&props))) {
				break;
			}
			props.cbBuffer = nBytes*3/2;

			if (props.cBuffers > 1) {
				if (S_OK != (hr = __super::DeliverBeginFlush())) {
					break;
				}
				if (S_OK != (hr = __super::DeliverEndFlush())) {
					break;
				}
			}

			if (S_OK != (hr = m_pAllocator->Decommit())) {
				break;
			}
			if (S_OK != (hr = m_pAllocator->SetProperties(&props, &actual))) {
				break;
			}
			if (S_OK != (hr = m_pAllocator->Commit())) {
				break;
			}
			if (S_OK != (hr = GetDeliveryBuffer(&pSample, NULL, NULL, 0))) {
				break;
			}
		}

		if (p->pmt) {
			pSample->SetMediaType(p->pmt);
			p->bDiscontinuity = true;

			// CAutoLock cAutoLock(m_pLock); // this can cause the lock
			m_mts.RemoveAll();
			m_mts.Add(*p->pmt);
		}

		bool fTimeValid = p->rtStart != INVALID_TIME;

#if defined(_DEBUG) && 0
		TRACE(_T("[%d]: d%d s%d p%d, b=%d, [%20I64d - %20I64d]\n"),
			  p->TrackNumber,
			  p->bDiscontinuity, p->bSyncPoint, fTimeValid && p->rtStart < 0,
			  nBytes, p->rtStart, p->rtStop);
#endif

		ASSERT(!p->bSyncPoint || fTimeValid);

		BYTE* pData = NULL;
		if (S_OK != (hr = pSample->GetPointer(&pData)) || !pData) {
			break;
		}
		memcpy(pData, p->GetData(), nBytes);
		if (S_OK != (hr = pSample->SetActualDataLength(nBytes))) {
			break;
		}
		if (S_OK != (hr = pSample->SetTime(fTimeValid ? &p->rtStart : NULL, fTimeValid ? &p->rtStop : NULL))) {
			break;
		}
		if (S_OK != (hr = pSample->SetMediaTime(NULL, NULL))) {
			break;
		}
		if (S_OK != (hr = pSample->SetDiscontinuity(p->bDiscontinuity))) {
			break;
		}
		if (S_OK != (hr = pSample->SetSyncPoint(p->bSyncPoint))) {
			break;
		}
		if (S_OK != (hr = pSample->SetPreroll(fTimeValid && p->rtStart < 0))) {
			break;
		}
		if (S_OK != (hr = Deliver(pSample))) {
			break;
		}
	} while (false);

	return hr;
}
예제 #20
0
// the loop executed while running
HRESULT FCapturePin::DoBufferProcessingLoop(void) 
{
	Command com;

	OnThreadStartPlay();
	int32 LastFrame = -1;

	do 
	{
		while (!CheckRequest(&com)) 
		{
			// Wait for the next frame from the game thread 
			if ( !GCaptureSyncEvent->Wait(1000) )
			{
				FPlatformProcess::Sleep( 0.01f );
				continue;	// Reevaluate request
			}

			IMediaSample *pSample;
			int32 FrameNumber = FAVIWriter::GetInstance()->GetFrameNumber();
			if (FrameNumber > LastFrame)
			{
				UE_LOG(LogMovieCapture, Log, TEXT(" FrameNumber > LastFrame = %d > %d"), FrameNumber, LastFrame);
				HRESULT hr = GetDeliveryBuffer(&pSample,NULL,NULL,0);
				if (FAILED(hr)) 
				{
					if (pSample)
					{
						pSample->Release();
					}
				}
				else
				{
					LastFrame = FrameNumber;
					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)
						{
							UE_LOG(LogMovieCapture, Log, TEXT("Deliver() returned %08x; stopping"), hr);
							return S_OK;
						}
					}
				}
			}
			// Allow the game thread read more data
			GCaptureSyncEvent->Trigger();
		}

		// 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((uint32) E_UNEXPECTED);
		}
	} while (com != CMD_STOP);

	return S_FALSE;
}