Example #1
0
HRESULT Inpin::NewSegment(
    REFERENCE_TIME st,
    REFERENCE_TIME sp,
    double r)
{
    Filter::Lock lock;

    HRESULT hr = lock.Seize(m_pFilter);

    if (FAILED(hr))
        return hr;

    if (!bool(m_pPinConnection))
        return VFW_E_NOT_CONNECTED;

    if (IPin* pPin = m_pFilter->m_outpin.m_pPinConnection)
    {
        lock.Release();

        const HRESULT hr = pPin->NewSegment(st, sp, r);
        return hr;
    }

    return S_OK;
}
Example #2
0
HRESULT Inpin::EndFlush()
{
    Filter::Lock lock;

    HRESULT hr = lock.Seize(m_pFilter);

    if (FAILED(hr))
        return hr;

    if (!bool(m_pPinConnection))
        return VFW_E_NOT_CONNECTED;

#if 0 //def _DEBUG
    odbgstream os;
    os << "vp8decoder::inpin::endflush" << endl;
#endif

    m_bFlush = false;
    m_bEndOfStream = false;

    if (IPin* pPin = m_pFilter->m_outpin.m_pPinConnection)
    {
        lock.Release();

        const HRESULT hr = pPin->EndFlush();
        return hr;
    }

    return S_OK;
}
HRESULT OutpinVideo::CheckCapabilities(DWORD* pdw)
{
    Filter::Lock lock;

    HRESULT hr = lock.Seize(m_pFilter);

    if (FAILED(hr))
        return hr;

    if (!bool(m_pPinConnection))
        return VFW_E_NOT_CONNECTED;

    const Inpin& inpin = m_pFilter->m_inpin;
    const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

    if (bool(pSeek))
    {
        lock.Release();
        return pSeek->CheckCapabilities(pdw);
    }

    if (pdw == 0)
        return E_POINTER;

    DWORD& dw = *pdw;

    const DWORD dwRequested = dw;

    if (dwRequested == 0)
        return E_INVALIDARG;

    return E_FAIL;
}
HRESULT OutpinVideo::GetPositions(
    LONGLONG* pCurrPos,
    LONGLONG* pStopPos)
{
    Filter::Lock lock;

    HRESULT hr = lock.Seize(m_pFilter);

    if (FAILED(hr))
        return hr;

    if (!bool(m_pPinConnection))
        return VFW_E_NOT_CONNECTED;

    const Inpin& inpin = m_pFilter->m_inpin;
    const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

    if (bool(pSeek))
    {
        lock.Release();
        return pSeek->GetPositions(pCurrPos, pStopPos);
    }

    return E_FAIL;
}
HRESULT OutpinVideo::GetAvailable(
    LONGLONG* pEarliest,
    LONGLONG* pLatest)
{
    Filter::Lock lock;

    HRESULT hr = lock.Seize(m_pFilter);

    if (FAILED(hr))
        return hr;

    if (!bool(m_pPinConnection))
        return VFW_E_NOT_CONNECTED;

    const Inpin& inpin = m_pFilter->m_inpin;
    const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

    if (bool(pSeek))
    {
        lock.Release();
        return pSeek->GetAvailable(pEarliest, pLatest);
    }

    return E_FAIL;
}
HRESULT OutpinVideo::GetDuration(LONGLONG* p)
{
    Filter::Lock lock;

    HRESULT hr = lock.Seize(m_pFilter);

    if (FAILED(hr))
        return hr;

    if (!bool(m_pPinConnection))
        return VFW_E_NOT_CONNECTED;

    const Inpin& inpin = m_pFilter->m_inpin;
    const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

    if (bool(pSeek))
    {
        lock.Release();
        return pSeek->GetDuration(p);
    }

    if (p == 0)
        return E_POINTER;

    return E_FAIL;
}
HRESULT OutpinVideo::GetCurrentPosition(LONGLONG* p)
{
    Filter::Lock lock;

    HRESULT hr = lock.Seize(m_pFilter);

    if (FAILED(hr))
        return hr;

    if (!bool(m_pPinConnection))
        return VFW_E_NOT_CONNECTED;

    const Inpin& inpin = m_pFilter->m_inpin;
#if 0
    const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

    if (bool(pSeek))
    {
        lock.Release();
        return pSeek->GetCurrentPosition(p);
    }

    if (p == 0)
        return E_POINTER;

    return E_FAIL;
#else
    if (p == 0)
        return E_POINTER;

    *p = inpin.m_start_reftime;

    return S_OK;
#endif
}
HRESULT OutpinVideo::SetTimeFormat(const GUID* p)
{
    Filter::Lock lock;

    HRESULT hr = lock.Seize(m_pFilter);

    if (FAILED(hr))
        return hr;

    if (!bool(m_pPinConnection))
        return VFW_E_NOT_CONNECTED;

    const Inpin& inpin = m_pFilter->m_inpin;
    const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

    if (bool(pSeek))
    {
        lock.Release();
        return pSeek->SetTimeFormat(p);
    }

    if (p == 0)
        return E_INVALIDARG;

    if (*p == TIME_FORMAT_MEDIA_TIME)
        return S_OK;

    return E_INVALIDARG;
}
HRESULT OutpinVideo::QueryPreferredFormat(GUID* p)
{
    Filter::Lock lock;

    HRESULT hr = lock.Seize(m_pFilter);

    if (FAILED(hr))
        return hr;

    if (!bool(m_pPinConnection))
        return VFW_E_NOT_CONNECTED;

    const Inpin& inpin = m_pFilter->m_inpin;
    const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

    if (bool(pSeek))
    {
        lock.Release();
        return pSeek->QueryPreferredFormat(p);
    }

    if (p == 0)
        return E_POINTER;

    *p = TIME_FORMAT_MEDIA_TIME;
    return S_OK;
}
Example #10
0
HRESULT OutpinVideo::IsFormatSupported(const GUID* p)
{
    Filter::Lock lock;

    HRESULT hr = lock.Seize(m_pFilter);

    if (FAILED(hr))
        return hr;

    if (!bool(m_pPinConnection))
        return VFW_E_NOT_CONNECTED;

    const Inpin& inpin = m_pFilter->m_inpin;
    const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

    if (bool(pSeek))
    {
        lock.Release();
        return pSeek->IsFormatSupported(p);
    }

    if (p == 0)
        return E_POINTER;

    const GUID& g = *p;

    if (g == TIME_FORMAT_MEDIA_TIME)
        return S_OK;

    return S_FALSE;
}
Example #11
0
HRESULT Inpin::BeginFlush()
{
    Filter::Lock lock;

    HRESULT hr = lock.Seize(m_pFilter);

    if (FAILED(hr))
        return hr;

    if (!bool(m_pPinConnection))
        return VFW_E_NOT_CONNECTED;

    //TODO:
    //if (m_bFlush)
    //    return S_FALSE;

#if 0 //def _DEBUG
    odbgstream os;
    os << "vp8decoder::inpin::beginflush" << endl;
#endif

    m_bFlush = true;

    if (IPin* pPin = m_pFilter->m_outpin.m_pPinConnection)
    {
        lock.Release();

        const HRESULT hr = pPin->BeginFlush();
        return hr;
    }

    return S_OK;
}
Example #12
0
HRESULT OutpinVideo::GetCapabilities(DWORD* pdw)
{
    Filter::Lock lock;

    HRESULT hr = lock.Seize(m_pFilter);

    if (FAILED(hr))
        return hr;

    if (!bool(m_pPinConnection))
        return VFW_E_NOT_CONNECTED;

    const Inpin& inpin = m_pFilter->m_inpin;
    const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

    if (bool(pSeek))
    {
        lock.Release();
        return pSeek->GetCapabilities(pdw);
    }

    if (pdw == 0)
        return E_POINTER;

    DWORD& dw = *pdw;
    dw = 0;

    return S_OK;  //?
}
Example #13
0
HRESULT Inpin::ReceiveCanBlock()
{
    Filter::Lock lock;

    const HRESULT hr = lock.Seize(m_pFilter);

    if (FAILED(hr))
        return S_OK;  //?

    if (IMemInputPin* pPin = m_pFilter->m_outpin.m_pInputPin)
    {
        lock.Release();
        return pPin->ReceiveCanBlock();
    }

    return S_FALSE;
}
Example #14
0
HRESULT OutpinVideo::ConvertTimeFormat(
    LONGLONG* ptgt,
    const GUID* ptgtfmt,
    LONGLONG src,
    const GUID* psrcfmt)
{
    Filter::Lock lock;

    HRESULT hr = lock.Seize(m_pFilter);

    if (FAILED(hr))
        return hr;

    if (!bool(m_pPinConnection))
        return VFW_E_NOT_CONNECTED;

    const Inpin& inpin = m_pFilter->m_inpin;
    const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

    if (bool(pSeek))
    {
        lock.Release();
        return pSeek->ConvertTimeFormat(ptgt, ptgtfmt, src, psrcfmt);
    }

    if (ptgt == 0)
        return E_POINTER;

    LONGLONG& tgt = *ptgt;

    const GUID& tgtfmt = ptgtfmt ? *ptgtfmt : TIME_FORMAT_MEDIA_TIME;
    const GUID& srcfmt = psrcfmt ? *psrcfmt : TIME_FORMAT_MEDIA_TIME;

    if (tgtfmt != TIME_FORMAT_MEDIA_TIME)
        return E_INVALIDARG;

    if (srcfmt != TIME_FORMAT_MEDIA_TIME)
        return E_INVALIDARG;

    tgt = src;
    return S_OK;
}
Example #15
0
HRESULT OutpinVideo::SetPositions(
    LONGLONG* pCurr_,
    DWORD dwCurr_,
    LONGLONG* pStop_,
    DWORD dwStop_)
{
    Filter::Lock lock;

    HRESULT hr = lock.Seize(m_pFilter);

    if (FAILED(hr))
        return hr;

    if (!bool(m_pPinConnection))
        return VFW_E_NOT_CONNECTED;

    const Inpin& inpin = m_pFilter->m_inpin;
    const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

    if (bool(pSeek))
    {
        lock.Release();

        LONGLONG curr;
        LONGLONG* const pCurr = pCurr_ ? pCurr_ : &curr;

        const DWORD dwCurr = pCurr_ ? dwCurr_ : AM_SEEKING_NoPositioning;

        LONGLONG stop;
        LONGLONG* const pStop = pStop_ ? pStop_ : &stop;

        const DWORD dwStop = pStop_ ? dwStop_ : AM_SEEKING_NoPositioning;

        return pSeek->SetPositions(pCurr, dwCurr, pStop, dwStop);
    }

    return E_FAIL;
}
Example #16
0
HRESULT OutpinVideo::SetRate(double r)
{
    Filter::Lock lock;

    HRESULT hr = lock.Seize(m_pFilter);

    if (FAILED(hr))
        return hr;

    if (!bool(m_pPinConnection))
        return VFW_E_NOT_CONNECTED;

    const Inpin& inpin = m_pFilter->m_inpin;
    const GraphUtil::IMediaSeekingPtr pSeek(inpin.m_pPinConnection);

    if (bool(pSeek))
    {
        lock.Release();
        return pSeek->SetRate(r);
    }

    return E_FAIL;
}
Example #17
0
HRESULT Inpin::EndOfStream()
{
    Filter::Lock lock;

    HRESULT hr = lock.Seize(m_pFilter);

    if (FAILED(hr))
        return hr;

    if (!bool(m_pPinConnection))
        return VFW_E_NOT_CONNECTED;

    m_bEndOfStream = true;

    if (IPin* pPin = m_pFilter->m_outpin.m_pPinConnection)
    {
        lock.Release();

#ifdef _DEBUG
        odbgstream os;
        os << "vp8decoder::inpin::EOS: calling pin->EOS" << endl;
#endif

        const HRESULT hr = pPin->EndOfStream();

#ifdef _DEBUG
        os << "vp8decoder::inpin::EOS: called pin->EOS; hr=0x"
           << hex << hr << dec
           << endl;
#endif

        return hr;
    }

    return S_OK;
}
Example #18
0
HRESULT Outpin::SetPositions(
    LONGLONG* pCurr,
    DWORD dwCurr_,
    LONGLONG* pStop,
    DWORD dwStop_)
{
    Filter::Lock lock;

    HRESULT hr = lock.Seize(m_pFilter);

    if (FAILED(hr))
        return hr;

#if 0 //def _DEBUG
    wodbgstream os;
    os << "\nwebmsource::Outpin[" << m_id << "]::SetPos(begin): pCurr="
       << dec << (pCurr ? *pCurr : -1)
       << " dwCurr=0x"
       << hex << dwCurr_
       << " pStop="
       << dec << (pStop ? *pStop : -1)
       << " dwStop=0x"
       << hex << dwStop_
       << "; STATE=" << m_pFilter->m_state
       << endl;
#endif

    if (m_connection == 0)
        return VFW_E_NOT_CONNECTED;

    const DWORD dwCurrPos = dwCurr_ & AM_SEEKING_PositioningBitsMask;
    const DWORD dwStopPos = dwStop_ & AM_SEEKING_PositioningBitsMask;

    if (dwCurrPos == AM_SEEKING_NoPositioning)
    {
        if (dwCurr_ & AM_SEEKING_ReturnTime)
        {
            if (pCurr == 0)
                return E_POINTER;

            *pCurr = m_pStream->GetCurrTime();

            if (*pCurr < 0)  //means "use duration"
            {
                hr = GetDuration(pCurr);

                if (FAILED(hr) || (*pCurr < 0))
                    *pCurr = 0;  //?
            }
        }

        if (dwStopPos == AM_SEEKING_NoPositioning)
        {
            if (dwStop_ & AM_SEEKING_ReturnTime)
            {
                if (pStop == 0)
                    return E_POINTER;

                *pStop = m_pStream->GetStopTime();

                if (*pStop < 0) //means "use duration"
                {
                    hr = GetDuration(pStop);

                    if (FAILED(hr) || (*pStop < 0))
                        *pStop = 0;  //?
                }
            }

            return S_FALSE;  //no position change
        }

        if (pStop == 0)
            return E_INVALIDARG;

        LONGLONG& tStop = *pStop;

        //It makes sense to be able to adjust this during stop.
        //However, if we're paused/running, then the thread is either
        //still sending frames, or it has already sent EOS.  In the
        //former case, it makes sense to be able to adjust where
        //the running thread will stop.  But in the latter case,
        //the thread has already terminated, and it wouldn't
        //make any sense to restart the thread because there
        //would be a large time gap.

        m_pStream->SetStopPosition(tStop, dwStop_);

        if (dwStop_ & AM_SEEKING_ReturnTime)
        {
            tStop = m_pStream->GetStopTime();

            if (tStop < 0)  //means "use duration"
            {
                hr = GetDuration(&tStop);

                if (FAILED(hr) || (tStop < 0))
                    tStop = 0;  //??
            }
        }

        //TODO: You're supposed to return S_FALSE if there has
        //been no change in position.  Does changing only the stop
        //position count has having changed the position?

        return S_OK;
    }

    //Check for errors first, before changing any state.

    if (pCurr == 0)
        return E_INVALIDARG;

    switch (dwCurrPos)
    {
        case AM_SEEKING_IncrementalPositioning:
        default:
            return E_INVALIDARG;  //applies only to stop pos

        case AM_SEEKING_AbsolutePositioning:
        case AM_SEEKING_RelativePositioning:
            break;
    }

    if (dwStopPos == AM_SEEKING_NoPositioning)
    {
        if (((dwStop_ & AM_SEEKING_ReturnTime) != 0) && (pStop == 0))
            return E_POINTER;
    }
    else if (pStop == 0)
        return E_INVALIDARG;

    assert(pCurr);  //vetted above
    LONGLONG& tCurr = *pCurr;

    if (tCurr == Filter::kNoSeek)
        return E_INVALIDARG;  //we need a nonce value

    if (m_pFilter->m_state != State_Stopped)
    {
#if 0 //def _DEBUG
        os << "webmsource::Outpin[" << m_id << "]::SetPos(cont'd): pCurr="
           << dec << (pCurr ? tCurr : -1)
           << " dwCurr=0x"
           << hex << dwCurr_
           << " pStop="
           << dec << (pStop ? *pStop : -1)
           << " dwStop=0x"
           << hex << dwStop_
           << "; BEGIN FLUSH: releasing filter lock; STATE="
           << m_pFilter->m_state
           << endl;
#endif

        lock.Release();

#if 0 //def _DEBUG
        os << "webmsource::Outpin[" << m_id << "]::SetPos(cont'd): pCurr="
           << dec << (pCurr ? tCurr : -1)
           << " dwCurr=0x"
           << hex << dwCurr_
           << " pStop="
           << dec << (pStop ? *pStop : -1)
           << " dwStop=0x"
           << hex << dwStop_
           << "; BEGIN FLUSH: released filter lock; "
           << "connection->calling BeginFlush"
           << endl;
#endif

        hr = m_connection->BeginFlush();

#if 0 //def _DEBUG
        os << "webmsource::Outpin[" << m_id << "]::SetPos(cont'd): pCurr="
           << dec << (pCurr ? tCurr : -1)
           << " dwCurr=0x"
           << hex << dwCurr_
           << " pStop="
           << dec << (pStop ? *pStop : -1)
           << " dwStop=0x"
           << hex << dwStop_
           << "; BEGIN FLUSH: released filter lock; "
           << "connection->called BeginFlush; "
           << "waiting for thread termination"
           << endl;
#endif

        assert(m_hThread);

        const DWORD dw = WaitForSingleObject(m_hThread, 5000);
        //assert(dw == WAIT_OBJECT_0);
        if (dw == WAIT_TIMEOUT)
            return VFW_E_TIMEOUT;

        const BOOL b = CloseHandle(m_hThread);
        assert(b);

        m_hThread = 0;

#if 0 //def _DEBUG
        os << "webmsource::Outpin[" << m_id << "]::SetPos(cont'd): pCurr="
           << dec << (pCurr ? tCurr : -1)
           << " dwCurr=0x"
           << hex << dwCurr_
           << " pStop="
           << dec << (pStop ? *pStop : -1)
           << " dwStop=0x"
           << hex << dwStop_
           << "; END FLUSH: calling connection->EndFlush"
           << endl;
#endif

        hr = m_connection->EndFlush();

#if 0 //def _DEBUG
        os << "webmsource::Outpin[" << m_id << "]::SetPos(cont'd): pCurr="
           << dec << (pCurr ? tCurr : -1)
           << " dwCurr=0x"
           << hex << dwCurr_
           << " pStop="
           << dec << (pStop ? *pStop : -1)
           << " dwStop=0x"
           << hex << dwStop_
           << "; END FLUSH: called connection->EndFlush; seizing filter lock"
           << endl;
#endif

        hr = lock.Seize(m_pFilter);
        assert(SUCCEEDED(hr));  //TODO

#if 0 //def _DEBUG
        os << "webmsource::Outpin[" << m_id << "]::SetPos(cont'd): pCurr="
           << dec << (pCurr ? tCurr : -1)
           << " dwCurr=0x"
           << hex << dwCurr_
           << " pStop="
           << dec << (pStop ? *pStop : -1)
           << " dwStop=0x"
           << hex << dwStop_
           << "; END FLUSH: seized filter lock"
           << endl;
#endif
    }


#if 0 //def _DEBUG
    os << "webmsource::Outpin[" << m_id << "]::SetPos(cont'd): pCurr="
       << dec << (pCurr ? tCurr : -1)
       << " pStop="
       << dec << (pStop ? *pStop : -1)
       << "; SET CURR POSN (begin)"
       << endl;
#endif

    m_pFilter->SetCurrPosition(tCurr, dwCurr_, this);

    if (dwStopPos == AM_SEEKING_NoPositioning)
    {
        //TODO: I still haven't figured what should happen to the
        //stop position if the user doesn't seek the stop time
        //too.  For now I assume that that user wants to play
        //the entire remainder of the stream starting from the
        //seek time.

        m_pStream->SetStopPositionEOS();
    }
    else
    {
        assert(pStop);  //vetted above
        m_pStream->SetStopPosition(*pStop, dwStop_);
    }

#if 0 //def _DEBUG
    os << "webmsource::Outpin[" << m_id << "]::SetPos(cont'd): pCurr="
       << dec << (pCurr ? tCurr : -1)
       << " pStop="
       << dec << (pStop ? *pStop : -1)
       << "; SET CURR POSN (end)"
       << endl;
#endif

    if (dwCurr_ & AM_SEEKING_ReturnTime)
    {
        tCurr = m_pStream->GetCurrTime();

        if (tCurr < 0)  //means "use duration"
        {
            hr = GetDuration(&tCurr);

            if (FAILED(hr) || (tCurr < 0))
                tCurr = 0;  //?
        }
    }

    if (dwStop_ & AM_SEEKING_ReturnTime)
    {
        assert(pStop);  //we checked this above
        *pStop = m_pStream->GetStopTime();

        if (*pStop < 0)  //means "use duration"
        {
            hr = GetDuration(pStop);

            if (FAILED(hr) || (*pStop < 0))
                *pStop = 0;  //?
        }
    }

    if (m_pFilter->m_state != State_Stopped)
        StartThread();

#if 0 //def _DEBUG
    os << "webmsource::Outpin[" << m_id << "]::SetPos(end): pCurr="
       << dec << (pCurr ? tCurr : -1)
       << " pStop="
       << dec << (pStop ? *pStop : -1)
       << "; DONE\n"
       << endl;
#endif

    return S_OK;
}
Example #19
0
HRESULT Outpin::PopulateSamples(OggTrack::samples_t& samples)
{
    for (;;)
    {
        assert(samples.empty());

        Filter::Lock lock;

        HRESULT hr = lock.Seize(m_pFilter);

        if (FAILED(hr))
            return hr;

        long count;

        hr = m_pTrack->GetPackets(count);

        if (FAILED(hr))  //TODO: handle underflow if req'd for ogg parsing
            return hr;

        if (hr != S_OK)      //EOS
            return S_FALSE;  //report EOS

        assert(count > 0);

        hr = lock.Release();
        assert(SUCCEEDED(hr));

        samples.reserve(count);

        for (long idx = 0; idx < count; ++idx)
        {
            IMediaSample* sample;

            hr = m_pAllocator->GetBuffer(&sample, 0, 0, 0);

            if (hr != S_OK)
                return E_FAIL;  //we're done

            samples.push_back(sample);
        }

        hr = lock.Seize(m_pFilter);

        if (FAILED(hr))
            return hr;

        hr = m_pTrack->PopulateSamples(samples);

        if (FAILED(hr))
            return hr;

        if (hr != 2)    //2 means "must parse more, and then re-try"
            return hr;  //have samples (0) or EOS (1), so we're done

        hr = lock.Release();
        assert(SUCCEEDED(hr));

        OggTrack::Clear(samples);
    }
}
HRESULT Inpin::BeginFlush()
{
#ifdef _DEBUG
    odbgstream os;
    os << "webmvorbisdecoder::inpin::beginflush(begin)" << endl;
#endif

    Filter::Lock lock;

    HRESULT hr = lock.Seize(m_pFilter);

    if (FAILED(hr))
        return hr;

    if (!bool(m_pPinConnection))
        return VFW_E_NOT_CONNECTED;

    //IPin::BeginFlush
    //In a flush operation, a filter discards whatever data it was processing.
    //It rejects new data until the flush is completed. The flush is
    //completed when the upstream pin calls the IPin::EndFlush method.
    //Flushing enables the filter graph to be more responsive when events
    //alter the normal data flow. For example, flushing occurs during a seek.
    //
    //When BeginFlush is called, the filter performs the following steps:
    //
    //(1) Passes the IPin::BeginFlush call downstream.
    //
    //(2) Sets an internal flag that causes all data-streaming methods to
    //    fail, such as IMemInputPin::Receive.
    //
    //(3) Returns from any blocked calls to the Receive method.
    //
    //
    //When the BeginFlush notification reaches a renderer filter,
    //the renderer frees any samples that it holds.
    //
    //After BeginFlush is called, the pin rejects all samples from upstream,
    //with a return value of S_FALSE, until the IPin::EndFlush method is
    //called.

    //IPin::EndOfStream
    //The IPin::BeginFlush method flushes any queued end-of-stream
    //notifications. This is intended for input pins only.

    m_bFlush = true;

    Outpin& outpin = m_pFilter->m_outpin;

    if (IPin* const pPin = outpin.m_pPinConnection)
    {
#ifdef _DEBUG
        os << "webmvorbisdecoder::inpin::beginflush:"
           << " flushing downstream filter"
           << endl;
#endif

        hr = pPin->BeginFlush();  //safe to do this here, while holding lock?

#ifdef _DEBUG
        os << "webmvorbisdecoder::inpin::beginflush:"
           << " called BeginFlush: hr=0x" << hex << hr << dec
           << "\nwebmvorbisdecoder::inpin::beginflush: waiting for thread"
           << "to terminate"
           << endl;
#endif

        const BOOL b = SetEvent(m_hSamples);  //to terminate thread
        assert(b);

        hr = lock.Release();
        assert(SUCCEEDED(hr));

        //The thread might not exist yet, if we have been connected but not
        //started.  In which case, attempting to stop the thread is benign.

        outpin.StopThread();
    }

#ifdef _DEBUG
    os << "webmvorbisdecoder::inpin::beginflush(end #2): thread terminated"
       << endl;
#endif

    return S_OK;
}
Example #21
0
HRESULT Inpin::Receive(IMediaSample* pInSample)
{
    if (pInSample == 0)
        return E_INVALIDARG;

//#define DEBUG_RECEIVE

#ifdef DEBUG_RECEIVE
    {
        __int64 start_reftime, stop_reftime;
        const HRESULT hr = pInSample->GetTime(&start_reftime, &stop_reftime);

        odbgstream os;
        os << "vp8dec::inpin::receive: ";

        os << std::fixed << std::setprecision(3);

        if (hr == S_OK)
            os << "start[ms]=" << double(start_reftime) / 10000
               << "; stop[ms]=" << double(stop_reftime) / 10000
               << "; dt[ms]=" << double(stop_reftime - start_reftime) / 10000;

        else if (hr == VFW_S_NO_STOP_TIME)
            os << "start[ms]=" << double(start_reftime) / 10000;

        os << endl;
    }
#endif

    Filter::Lock lock;

    HRESULT hr = lock.Seize(m_pFilter);

    if (FAILED(hr))
        return hr;

//#ifdef DEBUG_RECEIVE
//    wodbgstream os;
//    os << L"vp8dec::inpin::Receive: THREAD=0x"
//       << std::hex << GetCurrentThreadId() << std::dec
//       << endl;
//#endif

    if (!bool(m_pPinConnection))
        return VFW_E_NOT_CONNECTED;

    Outpin& outpin = m_pFilter->m_outpin;

    if (!bool(outpin.m_pPinConnection))
        return S_FALSE;

    if (!bool(outpin.m_pAllocator))  //should never happen
        return VFW_E_NO_ALLOCATOR;

    if (m_pFilter->m_state == State_Stopped)
        return VFW_E_NOT_RUNNING;

    if (m_bEndOfStream)
        return VFW_E_SAMPLE_REJECTED_EOS;

    if (m_bFlush)
        return S_FALSE;

    BYTE* buf;

    hr = pInSample->GetPointer(&buf);
    assert(SUCCEEDED(hr));
    assert(buf);

    const long len = pInSample->GetActualDataLength();
    assert(len >= 0);

    const vpx_codec_err_t err = vpx_codec_decode(&m_ctx, buf, len, 0, 0);

    if (err != VPX_CODEC_OK)
    {
        GraphUtil::IMediaEventSinkPtr pSink(m_pFilter->m_info.pGraph);

        if (bool(pSink))
        {
            lock.Release();

            hr = pSink->Notify(
                    EC_STREAM_ERROR_STOPPED,
                    VFW_E_SAMPLE_REJECTED,
                    err);
        }

        m_bEndOfStream = true;  //clear this when we stop and then start again
        return S_FALSE;
    }

    if (pInSample->IsPreroll() == S_OK)
        return S_OK;

    lock.Release();

    GraphUtil::IMediaSamplePtr pOutSample;

    hr = outpin.m_pAllocator->GetBuffer(&pOutSample, 0, 0, 0);

    if (FAILED(hr))
        return S_FALSE;

    assert(bool(pOutSample));

    hr = lock.Seize(m_pFilter);

    if (FAILED(hr))
        return hr;

    if (m_pFilter->m_state == State_Stopped)
        return VFW_E_NOT_RUNNING;

    if (!bool(outpin.m_pPinConnection))  //should never happen
        return S_FALSE;

    if (!bool(outpin.m_pInputPin))  //should never happen
        return S_FALSE;

    vpx_codec_iter_t iter = 0;

    vpx_image_t* const f = vpx_codec_get_frame(&m_ctx, &iter);

    if (f == 0)
        return S_OK;

    AM_MEDIA_TYPE* pmt;

    hr = pOutSample->GetMediaType(&pmt);

    if (SUCCEEDED(hr) && (pmt != 0))
    {
        assert(outpin.QueryAccept(pmt) == S_OK);
        outpin.m_connection_mtv.Clear();
        outpin.m_connection_mtv.Add(*pmt);

        MediaTypeUtil::Free(pmt);
        pmt = 0;
    }

    const AM_MEDIA_TYPE& mt = outpin.m_connection_mtv[0];
    assert(mt.formattype == FORMAT_VideoInfo);
    assert(mt.cbFormat >= sizeof(VIDEOINFOHEADER));
    assert(mt.pbFormat);

    const VIDEOINFOHEADER& vih = (VIDEOINFOHEADER&)(*mt.pbFormat);
    const BITMAPINFOHEADER& bmih = vih.bmiHeader;

    //Y

    const BYTE* pInY = f->planes[PLANE_Y];
    assert(pInY);

    unsigned int wIn = f->d_w;
    unsigned int hIn = f->d_h;

    BYTE* pOutBuf;

    hr = pOutSample->GetPointer(&pOutBuf);
    assert(SUCCEEDED(hr));
    assert(pOutBuf);

    BYTE* pOut = pOutBuf;

    const int strideInY = f->stride[PLANE_Y];

    LONG strideOut = bmih.biWidth;
    assert(strideOut);
    assert((strideOut % 2) == 0);  //?

    for (unsigned int y = 0; y < hIn; ++y)
    {
        memcpy(pOut, pInY, wIn);
        pInY += strideInY;
        pOut += strideOut;
    }

    strideOut /= 2;

    wIn = (wIn + 1) / 2;
    hIn = (hIn + 1) / 2;

    const BYTE* pInV = f->planes[PLANE_V];
    assert(pInV);

    const int strideInV = f->stride[PLANE_V];

    const BYTE* pInU = f->planes[PLANE_U];
    assert(pInU);

    const int strideInU = f->stride[PLANE_U];

    if (mt.subtype == MEDIASUBTYPE_YV12)
    {
        //V

        for (unsigned int y = 0; y < hIn; ++y)
        {
            memcpy(pOut, pInV, wIn);
            pInV += strideInV;
            pOut += strideOut;
        }

        //U

        for (unsigned int y = 0; y < hIn; ++y)
        {
            memcpy(pOut, pInU, wIn);
            pInU += strideInU;
            pOut += strideOut;
        }
    }
    else
    {
        //U

        for (unsigned int y = 0; y < hIn; ++y)
        {
            memcpy(pOut, pInU, wIn);
            pInU += strideInU;
            pOut += strideOut;
        }

        //V

        for (unsigned int y = 0; y < hIn; ++y)
        {
            memcpy(pOut, pInV, wIn);
            pInV += strideInV;
            pOut += strideOut;
        }
    }

    __int64 st, sp;

    hr = pInSample->GetTime(&st, &sp);

    if (FAILED(hr))
    {
        hr = pOutSample->SetTime(0, 0);
        assert(SUCCEEDED(hr));
    }
    else if (hr == S_OK)
    {
        hr = pOutSample->SetTime(&st, &sp);
        assert(SUCCEEDED(hr));
    }
    else
    {
        hr = pOutSample->SetTime(&st, 0);
        assert(SUCCEEDED(hr));
    }

    hr = pOutSample->SetSyncPoint(TRUE);
    assert(SUCCEEDED(hr));

    hr = pOutSample->SetPreroll(FALSE);
    assert(SUCCEEDED(hr));

    const ptrdiff_t lenOut_ = pOut - pOutBuf;
    const long lenOut = static_cast<long>(lenOut_);

    hr = pOutSample->SetActualDataLength(lenOut);
    assert(SUCCEEDED(hr));

    hr = pInSample->IsDiscontinuity();
    hr = pOutSample->SetDiscontinuity(hr == S_OK);

    hr = pOutSample->SetMediaTime(0, 0);

    lock.Release();

    return outpin.m_pInputPin->Receive(pOutSample);
}
HRESULT Inpin::Receive(IMediaSample* pInSample)
{
    if (pInSample == 0)
        return E_INVALIDARG;

    HRESULT hr;

//#define DEBUG_RECEIVE
#undef DEBUG_RECEIVE

#ifdef DEBUG_RECEIVE
    __int64 start_reftime_, stop_reftime_;
    hr = pInSample->GetTime(&start_reftime_, &stop_reftime_);
#endif

    Filter::Lock lock;

    hr = lock.Seize(m_pFilter);

    if (FAILED(hr))
        return hr;

//#ifdef DEBUG_RECEIVE
//    wodbgstream os;
//    os << L"vp8dec::inpin::Receive: THREAD=0x"
//       << std::hex << GetCurrentThreadId() << std::dec
//       << endl;
//#endif

    if (!bool(m_pPinConnection))
        return VFW_E_NOT_CONNECTED;

    Outpin& outpin = m_pFilter->m_outpin;

    if (!bool(outpin.m_pPinConnection))
        return S_FALSE;

    if (!bool(outpin.m_pAllocator))  //should never happen
        return VFW_E_NO_ALLOCATOR;

    if (m_pFilter->m_state == State_Stopped)
        return VFW_E_NOT_RUNNING;

    if (m_bEndOfStream)
        return VFW_E_SAMPLE_REJECTED_EOS;

    if (m_bFlush)
        return S_FALSE;

    if (m_bDone)
        return S_FALSE;

    if (m_first_reftime < 0)
    {
        LONGLONG sp;

        hr = pInSample->GetTime(&m_first_reftime, &sp);

        if (FAILED(hr))
            return S_OK;

        if (m_first_reftime < 0)
            return S_OK;

        m_start_reftime = m_first_reftime;
        m_samples = 0;

#ifdef DEBUG_RECEIVE
        odbgstream os;
        os << std::fixed << std::setprecision(3);

        os << "\nwebmvorbisdec::Inpin::Receive: RESET FIRST REFTIME;"
           << " st=" << m_start_reftime
           << " st[sec]=" << (double(m_start_reftime) / 10000000)
           << endl;
#endif

        const int status = vorbis_synthesis_restart(&m_dsp_state);
        status;
        assert(status == 0);  //success

        m_bDiscontinuity = true;
    }

#ifdef DEBUG_RECEIVE
    {
        odbgstream os;
        os << "webmvorbisdec::inpin::receive: ";

        os << std::fixed << std::setprecision(3);

        if (hr == S_OK)
            os << "start[sec]="
               << double(start_reftime_) / 10000000
               << "; stop[sec]="
               << double(stop_reftime_) / 10000000
               << "; dt[ms]="
               << double(stop_reftime_ - start_reftime_) / 10000;

        else if (hr == VFW_S_NO_STOP_TIME)
            os << "start[sec]=" << double(start_reftime_) / 10000000;

        os << endl;
    }
#endif

    Decode(pInSample);

    hr = lock.Release();
    assert(SUCCEEDED(hr));

    if (FAILED(hr))
        return hr;

    return PopulateSamples();
}