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->m_state != State_Stopped) return VFW_E_NOT_STOPPED; if (m_connection) return VFW_E_ALREADY_CONNECTED; m_connection_mtv.Clear(); if (pmt) { hr = QueryAccept(pmt); if (hr != S_OK) return VFW_E_TYPE_NOT_ACCEPTED; //The media type could me only a partial match, //so we need to fill it in before attemping //to use it. 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; //const AM_MEDIA_TYPE& mt = *pmt; //hr = m_pTrack->SetConnectionMediaType(mt); // //if (FAILED(hr)) // return VFW_E_TYPE_NOT_ACCEPTED; 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 0 if (SUCCEEDED(hr)) { hr = m_pTrack->SetConnectionMediaType(mt); if (SUCCEEDED(hr)) break; } #else if (SUCCEEDED(hr)) break; #endif ++i; } if (i >= j) return VFW_E_NO_ACCEPTABLE_TYPES; const AM_MEDIA_TYPE& mt = m_preferred_mtv[i]; m_connection_mtv.Add(mt); } hr = m_pTrack->SetConnectionMediaType(m_connection_mtv[0]); assert(SUCCEEDED(hr)); GraphUtil::IMemAllocatorPtr pAllocator; hr = pInputPin->GetAllocator(&pAllocator); if (FAILED(hr)) { 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); m_pTrack->UpdateAllocatorProperties(props); //modify props as req'd 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_pAllocator = pAllocator; m_connection = pin; //TODO: use com smartptr here m_connection->AddRef(); m_pInputPin = pInputPin; 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; }
HRESULT OutpinVideo::PostConnectStats(IPin* p) { IStreamPtr pStream; HRESULT hr = p->QueryInterface(&pStream); if (FAILED(hr)) return hr; const GraphUtil::IMemInputPinPtr pMemInput(p); if (bool(pMemInput)) { GraphUtil::IMemAllocatorPtr pAllocator; hr = pMemInput->GetAllocator(&pAllocator); if (FAILED(hr)) { hr = CMediaSample::CreateAllocator(&pAllocator); if (FAILED(hr)) return VFW_E_NO_ALLOCATOR; } assert(bool(pAllocator)); ALLOCATOR_PROPERTIES props; 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::getbuf does NOT include prefix hr = pMemInput->GetAllocatorRequirements(&props); if (props.cBuffers < 0) props.cBuffers = 0; if (props.cbBuffer < 0) props.cbBuffer = 0; if (props.cbAlign <= 0) props.cbAlign = 1; if (props.cbPrefix < 0) props.cbPrefix = 0; ALLOCATOR_PROPERTIES actual; hr = pAllocator->SetProperties(&props, &actual); if (FAILED(hr)) return hr; hr = pMemInput->NotifyAllocator(pAllocator, 0); //allow writes if (FAILED(hr) && (hr != E_NOTIMPL)) return hr; m_pAllocator = pAllocator; m_pInputPin = pMemInput; } m_pStream = pStream; return S_OK; }