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; #ifdef _DEBUG odbgstream os; os << "webmvorbisdecoder::inpin::EOS" << endl; #endif if (m_bFlush) return S_FALSE; //? m_bEndOfStream = true; m_buffers.push_back(0); const BOOL b = SetEvent(m_hSamples); assert(b); return S_OK; }
void Inpin::OnCompletion() { Filter::Lock lock; HRESULT hr = lock.Seize(m_pFilter); assert(SUCCEEDED(hr)); while (!m_buffers.empty()) { IMediaSample* const pSample = m_buffers.front(); if (pSample == 0) //EOS notification break; //don't throw EOS notification away m_buffers.pop_front(); pSample->Release(); } typedef channels_t::iterator iter_t; iter_t i = m_channels.begin(); const iter_t j = m_channels.end(); while (i != j) { samples_t& ss = *i++; ss.clear(); } m_bDone = true; }
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 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; }
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; }
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::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 Outpin::GetCurrentPosition(LONGLONG* p) { if (p == 0) return E_POINTER; Filter::Lock lock; HRESULT hr = lock.Seize(m_pFilter); if (FAILED(hr)) return hr; LONGLONG& pos = *p; pos = m_pStream->GetCurrTime(); if (pos < 0) //means "use duration" { hr = GetDuration(&pos); if (FAILED(hr) || (pos < 0)) return E_FAIL; } return S_OK; }
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::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::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; }
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; }
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::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; //? }
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 Outpin::QueryAccept(const AM_MEDIA_TYPE* pmt_query) { if (pmt_query == 0) return E_INVALIDARG; const AM_MEDIA_TYPE& mt_query = *pmt_query; if (mt_query.majortype != MEDIATYPE_Video) return S_FALSE; if (mt_query.subtype == MEDIASUBTYPE_NV12) __noop; else if (mt_query.subtype == MEDIASUBTYPE_YV12) __noop; else if (mt_query.subtype == WebmTypes::MEDIASUBTYPE_I420) __noop; else if (mt_query.subtype == MEDIASUBTYPE_UYVY) __noop; else if (mt_query.subtype == MEDIASUBTYPE_YVYU) __noop; else if (mt_query.subtype == MEDIASUBTYPE_YUY2) __noop; else if (mt_query.subtype == MEDIASUBTYPE_YUYV) __noop; else return S_FALSE; Filter::Lock lock; const HRESULT hr = lock.Seize(m_pFilter); if (FAILED(hr)) return S_FALSE; const Inpin& inpin = m_pFilter->m_inpin; if (!bool(inpin.m_pPinConnection)) return S_FALSE; if (mt_query.formattype == FORMAT_None) return S_OK; if (mt_query.formattype == GUID_NULL) return S_OK; const AM_MEDIA_TYPE& mt_in = inpin.m_connection_mtv[0]; if (mt_query.formattype == FORMAT_VideoInfo) return QueryAcceptVideoInfo(mt_in, mt_query); if (mt_query.formattype == FORMAT_VideoInfo2) return QueryAcceptVideoInfo2(mt_in, mt_query); return S_FALSE; }
HRESULT Pin::EnumMediaTypes(IEnumMediaTypes** pp) { Filter::Lock lock; HRESULT hr = lock.Seize(m_pFilter); if (FAILED(hr)) return hr; //wodbgstream os; //os << "mkvsplit::pin[" << m_id << "]::EnumMediaTypes" << endl; return m_preferred_mtv.CreateEnum(this, pp); }
HRESULT Inpin::QueryInternalConnections( IPin** pa, ULONG* pn) { if (pn == 0) return E_POINTER; Filter::Lock lock; HRESULT hr = lock.Seize(m_pFilter); if (FAILED(hr)) return hr; const ULONG m = 1; //number of output pins ULONG& n = *pn; if (n == 0) { if (pa == 0) //query for required number { n = m; return S_OK; } return S_FALSE; //means "insufficient number of array elements" } if (n < m) { n = 0; return S_FALSE; //means "insufficient number of array elements" } if (pa == 0) { n = 0; return E_POINTER; } IPin*& pin = pa[0]; pin = &m_pFilter->m_outpin; pin->AddRef(); n = m; return S_OK; }
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; }
HRESULT Inpin::ReceiveConnection( IPin* pin, const AM_MEDIA_TYPE* pmt) { if (pin == 0) return E_INVALIDARG; if (pmt == 0) return E_INVALIDARG; Filter::Lock lock; HRESULT hr = lock.Seize(m_pFilter); if (FAILED(hr)) return hr; if (m_pFilter->m_state != State_Stopped) return VFW_E_NOT_STOPPED; if (bool(m_pPinConnection)) return VFW_E_ALREADY_CONNECTED; m_connection_mtv.Clear(); hr = QueryAccept(pmt); if (hr != S_OK) return VFW_E_TYPE_NOT_ACCEPTED; const AM_MEDIA_TYPE& mt = *pmt; hr = m_connection_mtv.Add(mt); if (FAILED(hr)) return hr; m_pPinConnection = pin; //TODO: init decompressor here? m_pFilter->m_outpin.OnInpinConnect(mt); return S_OK; }
HRESULT Outpin::GetPositions( LONGLONG* pCurrPos, LONGLONG* pStopPos) { Filter::Lock lock; HRESULT hr = lock.Seize(m_pFilter); if (FAILED(hr)) return hr; if (pCurrPos) hr = GetCurrentPosition(pCurrPos); if (pStopPos) hr = GetStopPosition(pStopPos); return S_OK; }
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; }
HRESULT Pin::ConnectionMediaType(AM_MEDIA_TYPE* p) { if (p == 0) return E_POINTER; Filter::Lock lock; HRESULT hr = lock.Seize(m_pFilter); if (FAILED(hr)) return hr; if (!bool(m_pPinConnection)) return VFW_E_NOT_CONNECTED; const CMediaTypes& mtv = m_connection_mtv; assert(mtv.Size() == 1); return mtv.Copy(0, *p); }
HRESULT Pin::ConnectedTo(IPin** pp) { if (pp == 0) return E_POINTER; IPin*& p = *pp; Filter::Lock lock; HRESULT hr = lock.Seize(m_pFilter); if (FAILED(hr)) return hr; p = m_pPinConnection; if (p == 0) return VFW_E_NOT_CONNECTED; p->AddRef(); return S_OK; }
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; }
HRESULT Pin::Disconnect() { Filter::Lock lock; HRESULT hr = lock.Seize(m_pFilter); if (FAILED(hr)) return hr; if (m_pFilter->m_state != State_Stopped) return VFW_E_NOT_STOPPED; if (!bool(m_pPinConnection)) return S_FALSE; hr = OnDisconnect(); assert(SUCCEEDED(hr)); m_pPinConnection = 0; m_connection_mtv.Clear(); return S_OK; }
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; }
HRESULT Pin::QueryPinInfo(PIN_INFO* p) { if (p == 0) return E_POINTER; Filter::Lock lock; HRESULT hr = lock.Seize(m_pFilter); if (FAILED(hr)) return hr; PIN_INFO& i = *p; i.pFilter = static_cast<IBaseFilter*>(m_pFilter); i.pFilter->AddRef(); i.dir = m_dir; hr = GetName(i); assert(SUCCEEDED(hr)); return S_OK; }
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; }
HRESULT Outpin::Connect(IPin* pin, const AM_MEDIA_TYPE* pmt) { if (pin == 0) return E_POINTER; GraphUtil::IMemInputPinPtr pInputPin; HRESULT hr = pin->QueryInterface(&pInputPin); if (hr != S_OK) return hr; Filter::Lock lock; hr = lock.Seize(m_pFilter); if (FAILED(hr)) return hr; if (m_pFilter->GetStateLocked() != State_Stopped) return VFW_E_NOT_STOPPED; if (bool(m_pPinConnection)) return VFW_E_ALREADY_CONNECTED; if (!bool(m_pFilter->m_inpin.m_pPinConnection)) return VFW_E_NO_TYPES; // VFW_E_NOT_CONNECTED? m_connection_mtv.Clear(); if (pmt) { hr = QueryAccept(pmt); if (hr != S_OK) return VFW_E_TYPE_NOT_ACCEPTED; if ((pmt->formattype == FORMAT_VideoInfo) || (pmt->formattype == FORMAT_VideoInfo2)) { hr = pin->ReceiveConnection(this, pmt); if (FAILED(hr)) return hr; m_connection_mtv.Add(*pmt); } else { // partial media type const ULONG n = m_preferred_mtv.Size(); LONG idx = -1; for (ULONG i = 0; i < n; ++i) { const AM_MEDIA_TYPE& mt = m_preferred_mtv[i]; if (pmt->subtype == mt.subtype) { idx = i; break; } } if (idx < 0) // weird return VFW_E_TYPE_NOT_ACCEPTED; const AM_MEDIA_TYPE& mt = m_preferred_mtv[idx]; hr = pin->ReceiveConnection(this, &mt); if (FAILED(hr)) return hr; m_connection_mtv.Add(mt); } } else { ULONG i = 0; const ULONG j = m_preferred_mtv.Size(); while (i < j) { const AM_MEDIA_TYPE& mt = m_preferred_mtv[i]; hr = pin->ReceiveConnection(this, &mt); if (SUCCEEDED(hr)) break; ++i; } if (i >= j) return VFW_E_NO_ACCEPTABLE_TYPES; const AM_MEDIA_TYPE& mt = m_preferred_mtv[i]; m_connection_mtv.Add(mt); } GraphUtil::IMemAllocatorPtr pAllocator; hr = pInputPin->GetAllocator(&pAllocator); if (FAILED(hr)) { // hr = CMemAllocator::CreateInstance(&m_sample_factory, &pAllocator); hr = CMediaSample::CreateAllocator(&pAllocator); if (FAILED(hr)) return VFW_E_NO_ALLOCATOR; } assert(bool(pAllocator)); ALLOCATOR_PROPERTIES props, actual; props.cBuffers = -1; // number of buffers props.cbBuffer = -1; // size of each buffer, excluding prefix props.cbAlign = -1; // applies to prefix, too props.cbPrefix = -1; // imediasample::getbuffer does NOT include prefix hr = pInputPin->GetAllocatorRequirements(&props); if (props.cBuffers <= 0) props.cBuffers = 1; LONG w, h; GetConnectionDimensions(w, h); const long cbBuffer = 2 * w * h; if (props.cbBuffer < cbBuffer) props.cbBuffer = cbBuffer; if (props.cbAlign <= 0) props.cbAlign = 1; if (props.cbPrefix < 0) props.cbPrefix = 0; hr = pAllocator->SetProperties(&props, &actual); if (FAILED(hr)) return hr; hr = pInputPin->NotifyAllocator(pAllocator, 0); // allow writes if (FAILED(hr) && (hr != E_NOTIMPL)) return hr; m_pPinConnection = pin; m_pAllocator = pAllocator; m_pInputPin = pInputPin; return S_OK; }