Exemple #1
0
STDMETHODIMP CStreamSwitcherAllocator::GetBuffer(
    IMediaSample** ppBuffer,
    REFERENCE_TIME* pStartTime, REFERENCE_TIME* pEndTime,
    DWORD dwFlags)
{
    HRESULT hr = VFW_E_NOT_COMMITTED;

    if (!m_bCommitted) {
        return hr;
    }
    /*
    TRACE(_T("CStreamSwitcherAllocator::GetBuffer m_pPin->m_evBlock.Wait() + %x\n"), this);
        m_pPin->m_evBlock.Wait();
    TRACE(_T("CStreamSwitcherAllocator::GetBuffer m_pPin->m_evBlock.Wait() - %x\n"), this);
    */
    if (m_fMediaTypeChanged) {
        if (!m_pPin || !m_pPin->m_pFilter) {
            return hr;
        }

        CStreamSwitcherOutputPin* pOut = (static_cast<CStreamSwitcherFilter*>(m_pPin->m_pFilter))->GetOutputPin();
        if (!pOut || !pOut->CurrentAllocator()) {
            return hr;
        }

        ALLOCATOR_PROPERTIES Properties, Actual;
        if (FAILED(pOut->CurrentAllocator()->GetProperties(&Actual))) {
            return hr;
        }
        if (FAILED(GetProperties(&Properties))) {
            return hr;
        }

        if (!m_bCommitted || Properties.cbBuffer < Actual.cbBuffer) {
            Properties.cbBuffer = Actual.cbBuffer;
            if (FAILED(Decommit())) {
                return hr;
            }
            if (FAILED(SetProperties(&Properties, &Actual))) {
                return hr;
            }
            if (FAILED(Commit())) {
                return hr;
            }
            ASSERT(Actual.cbBuffer >= Properties.cbBuffer);
            if (Actual.cbBuffer < Properties.cbBuffer) {
                return hr;
            }
        }
    }

    hr = CMemAllocator::GetBuffer(ppBuffer, pStartTime, pEndTime, dwFlags);

    if (m_fMediaTypeChanged && SUCCEEDED(hr)) {
        (*ppBuffer)->SetMediaType(&m_mt);
        m_fMediaTypeChanged = false;
    }

    return hr;
}
STDMETHODIMP CStreamSwitcherInputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
{
	if(!IsConnected())
		return S_OK;

	CAutoLock cAutoLock(&m_csReceive);

	CStreamSwitcherFilter* pSSF = (CStreamSwitcherFilter*)m_pFilter;

	CStreamSwitcherOutputPin* pOut = pSSF->GetOutputPin();
    if(!pOut || !pOut->IsConnected())
		return VFW_E_NOT_CONNECTED;

	return pSSF->DeliverNewSegment(tStart, tStop, dRate);
}
STDMETHODIMP CStreamSwitcherInputPin::EndFlush()
{
	CAutoLock cAutoLock(&((CStreamSwitcherFilter*)m_pFilter)->m_csState);

	HRESULT hr;

	CStreamSwitcherFilter* pSSF = (CStreamSwitcherFilter*)m_pFilter;

	CStreamSwitcherOutputPin* pOut = pSSF->GetOutputPin();
    if(!IsConnected() || !pOut || !pOut->IsConnected())
		return VFW_E_NOT_CONNECTED;

    if(FAILED(hr = __super::EndFlush())) 
		return hr;

	return IsActive() ? pSSF->DeliverEndFlush() : Block(true), S_OK;
}
Exemple #4
0
STDMETHODIMP CStreamSwitcherInputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
{
	SetThreadName((DWORD)-1, "CStreamSwitcherInputPin");

	if(!IsConnected())
		return S_OK;

	CAutoLock cAutoLock(&m_csReceive);

	CStreamSwitcherFilter* pSSF = static_cast<CStreamSwitcherFilter*>(m_pFilter);

	CStreamSwitcherOutputPin* pOut = pSSF->GetOutputPin();
    if(!pOut || !pOut->IsConnected())
		return VFW_E_NOT_CONNECTED;

	return pSSF->DeliverNewSegment(tStart, tStop, dRate);
}
Exemple #5
0
STDMETHODIMP CStreamSwitcherInputPin::BeginFlush()
{
    CAutoLock cAutoLock(&(static_cast<CStreamSwitcherFilter*>(m_pFilter))->m_csState);

	HRESULT hr;

	CStreamSwitcherFilter* pSSF = static_cast<CStreamSwitcherFilter*>(m_pFilter);

	CStreamSwitcherOutputPin* pOut = pSSF->GetOutputPin();
    if(!IsConnected() || !pOut || !pOut->IsConnected())
		return VFW_E_NOT_CONNECTED;

    if(FAILED(hr = __super::BeginFlush())) 
		return hr;

	return IsActive() ? pSSF->DeliverBeginFlush() : Block(false), S_OK;
}
Exemple #6
0
STDMETHODIMP CStreamSwitcherInputPin::EndOfStream()
{
    CAutoLock cAutoLock(&m_csReceive);

    CStreamSwitcherFilter* pSSF = static_cast<CStreamSwitcherFilter*>(m_pFilter);

    CStreamSwitcherOutputPin* pOut = pSSF->GetOutputPin();
    if (!IsConnected() || !pOut || !pOut->IsConnected()) {
        return VFW_E_NOT_CONNECTED;
    }

    if (m_hNotifyEvent) {
        SetEvent(m_hNotifyEvent), m_hNotifyEvent = nullptr;
        return S_OK;
    }

    return IsActive() ? pSSF->DeliverEndOfStream() : S_OK;
}
Exemple #7
0
HRESULT CStreamSwitcherInputPin::QueryAcceptDownstream(const AM_MEDIA_TYPE* pmt)
{
    HRESULT hr = S_OK;

    CStreamSwitcherOutputPin* pOut = (static_cast<CStreamSwitcherFilter*>(m_pFilter))->GetOutputPin();

    if (pOut && pOut->IsConnected()) {
        if (CComPtr<IPinConnection> pPC = pOut->CurrentPinConnection()) {
            hr = pPC->DynamicQueryAccept(pmt);
            if (hr == S_OK) {
                return S_OK;
            }
        }

        hr = pOut->GetConnected()->QueryAccept(pmt);
    }

    return hr;
}
Exemple #8
0
STDMETHODIMP CStreamSwitcherInputPin::Receive(IMediaSample* pSample)
{
    AM_MEDIA_TYPE* pmt = nullptr;
    if (SUCCEEDED(pSample->GetMediaType(&pmt)) && pmt) {
        const CMediaType mt(*pmt);
        DeleteMediaType(pmt), pmt = nullptr;
        SetMediaType(&mt);
    }

    // DAMN!!!!!! this doesn't work if the stream we are blocking
    // shares the same thread with another stream, mpeg splitters
    // are usually like that. Our nicely built up multithreaded
    // strategy is useless because of this, ARRRRRRGHHHHHH.

#ifdef BLOCKSTREAM
    if (m_fCanBlock) {
        m_evBlock.Wait();
    }
#endif

    if (!IsActive()) {
#ifdef BLOCKSTREAM
        if (m_fCanBlock) {
            return S_FALSE;
        }
#endif

        TRACE(_T("&^$#@ : a stupid fix for this stupid problem\n"));
        //Sleep(32);
        return E_FAIL; // a stupid fix for this stupid problem
    }

    CAutoLock cAutoLock(&m_csReceive);

    CStreamSwitcherOutputPin* pOut = (static_cast<CStreamSwitcherFilter*>(m_pFilter))->GetOutputPin();
    ASSERT(pOut->GetConnected());

    HRESULT hr = __super::Receive(pSample);
    if (S_OK != hr) {
        return hr;
    }

    if (m_SampleProps.dwStreamId != AM_STREAM_MEDIA) {
        return pOut->Deliver(pSample);
    }

    //

    ALLOCATOR_PROPERTIES props, actual;
    hr = m_pAllocator->GetProperties(&props);
    hr = pOut->CurrentAllocator()->GetProperties(&actual);

    REFERENCE_TIME rtStart = 0, rtStop = 0;
    if (S_OK == pSample->GetTime(&rtStart, &rtStop)) {
        //
    }

    long cbBuffer = pSample->GetActualDataLength();

    CMediaType mtOut = m_mt;
    mtOut = (static_cast<CStreamSwitcherFilter*>(m_pFilter))->CreateNewOutputMediaType(mtOut, cbBuffer);

    bool fTypeChanged = false;

    if (mtOut != pOut->CurrentMediaType() || cbBuffer > actual.cbBuffer) {
        fTypeChanged = true;

        m_SampleProps.dwSampleFlags |= AM_SAMPLE_TYPECHANGED/*|AM_SAMPLE_DATADISCONTINUITY|AM_SAMPLE_TIMEDISCONTINUITY*/;

        /*
                if (CComQIPtr<IPinConnection> pPC = pOut->CurrentPinConnection())
                {
                    HANDLE hEOS = CreateEvent(nullptr, FALSE, FALSE, nullptr);
                    hr = pPC->NotifyEndOfStream(hEOS);
                    hr = pOut->DeliverEndOfStream();
                    WaitForSingleObject(hEOS, 3000);
                    CloseHandle(hEOS);
                    hr = pOut->DeliverBeginFlush();
                    hr = pOut->DeliverEndFlush();
                }
        */

        if (props.cBuffers < 8 && mtOut.majortype == MEDIATYPE_Audio) {
            props.cBuffers = 8;
        }

        props.cbBuffer = cbBuffer;

        if (actual.cbAlign != props.cbAlign
                || actual.cbPrefix != props.cbPrefix
                || actual.cBuffers < props.cBuffers
                || actual.cbBuffer < props.cbBuffer) {
            hr = pOut->DeliverBeginFlush();
            hr = pOut->DeliverEndFlush();
            hr = pOut->CurrentAllocator()->Decommit();
            hr = pOut->CurrentAllocator()->SetProperties(&props, &actual);
            hr = pOut->CurrentAllocator()->Commit();
        }
    }

    CComPtr<IMediaSample> pOutSample;
    if (FAILED(InitializeOutputSample(pSample, &pOutSample))) {
        return E_FAIL;
    }

    pmt = nullptr;
    if (SUCCEEDED(pOutSample->GetMediaType(&pmt)) && pmt) {
        const CMediaType mt(*pmt);
        DeleteMediaType(pmt), pmt = nullptr;
        // TODO
        ASSERT(0);
    }

    if (fTypeChanged) {
        pOut->SetMediaType(&mtOut);
        (static_cast<CStreamSwitcherFilter*>(m_pFilter))->OnNewOutputMediaType(m_mt, mtOut);
        pOutSample->SetMediaType(&mtOut);
    }

    // Transform

    hr = (static_cast<CStreamSwitcherFilter*>(m_pFilter))->Transform(pSample, pOutSample);

    //

    if (S_OK == hr) {
        hr = pOut->Deliver(pOutSample);
        m_bSampleSkipped = FALSE;
        /*
                if (FAILED(hr))
                {
                    ASSERT(0);
                }
        */
    } else if (S_FALSE == hr) {
        hr = S_OK;
        pOutSample = nullptr;
        m_bSampleSkipped = TRUE;

        if (!m_bQualityChanged) {
            m_pFilter->NotifyEvent(EC_QUALITY_CHANGE, 0, 0);
            m_bQualityChanged = TRUE;
        }
    }

    return hr;
}
Exemple #9
0
HRESULT CStreamSwitcherInputPin::InitializeOutputSample(IMediaSample* pInSample, IMediaSample** ppOutSample)
{
    if (!pInSample || !ppOutSample) {
        return E_POINTER;
    }

    CStreamSwitcherOutputPin* pOut = (static_cast<CStreamSwitcherFilter*>(m_pFilter))->GetOutputPin();
    ASSERT(pOut->GetConnected());

    CComPtr<IMediaSample> pOutSample;

    DWORD dwFlags = m_bSampleSkipped ? AM_GBF_PREVFRAMESKIPPED : 0;

    if (!(m_SampleProps.dwSampleFlags & AM_SAMPLE_SPLICEPOINT)) {
        dwFlags |= AM_GBF_NOTASYNCPOINT;
    }

    HRESULT hr = pOut->GetDeliveryBuffer(&pOutSample
                                         , m_SampleProps.dwSampleFlags & AM_SAMPLE_TIMEVALID ? &m_SampleProps.tStart : nullptr
                                         , m_SampleProps.dwSampleFlags & AM_SAMPLE_STOPVALID ? &m_SampleProps.tStop : nullptr
                                         , dwFlags);

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

    if (!pOutSample) {
        return E_FAIL;
    }

    if (CComQIPtr<IMediaSample2> pOutSample2 = pOutSample) {
        AM_SAMPLE2_PROPERTIES OutProps;
        EXECUTE_ASSERT(SUCCEEDED(pOutSample2->GetProperties(FIELD_OFFSET(AM_SAMPLE2_PROPERTIES, tStart), (PBYTE)&OutProps)));
        OutProps.dwTypeSpecificFlags = m_SampleProps.dwTypeSpecificFlags;
        OutProps.dwSampleFlags =
            (OutProps.dwSampleFlags & AM_SAMPLE_TYPECHANGED) |
            (m_SampleProps.dwSampleFlags & ~AM_SAMPLE_TYPECHANGED);

        OutProps.tStart = m_SampleProps.tStart;
        OutProps.tStop  = m_SampleProps.tStop;
        OutProps.cbData = FIELD_OFFSET(AM_SAMPLE2_PROPERTIES, dwStreamId);

        hr = pOutSample2->SetProperties(FIELD_OFFSET(AM_SAMPLE2_PROPERTIES, dwStreamId), (PBYTE)&OutProps);
        if (m_SampleProps.dwSampleFlags & AM_SAMPLE_DATADISCONTINUITY) {
            m_bSampleSkipped = FALSE;
        }
    } else {
        if (m_SampleProps.dwSampleFlags & AM_SAMPLE_TIMEVALID) {
            pOutSample->SetTime(&m_SampleProps.tStart, &m_SampleProps.tStop);
        }

        if (m_SampleProps.dwSampleFlags & AM_SAMPLE_SPLICEPOINT) {
            pOutSample->SetSyncPoint(TRUE);
        }

        if (m_SampleProps.dwSampleFlags & AM_SAMPLE_DATADISCONTINUITY) {
            pOutSample->SetDiscontinuity(TRUE);
            m_bSampleSkipped = FALSE;
        }

        LONGLONG MediaStart, MediaEnd;
        if (pInSample->GetMediaTime(&MediaStart, &MediaEnd) == NOERROR) {
            pOutSample->SetMediaTime(&MediaStart, &MediaEnd);
        }
    }

    *ppOutSample = pOutSample.Detach();

    return S_OK;
}