HRESULT FFmpegDecodeServices::SetInputMediaType(IMFMediaType* pMediaType) { std::lock_guard<decltype(_mutex)> lock(_mutex); if (pMediaType == NULL) { _inputMediaType.Reset(); _outputMediaType.Reset(); return S_OK; } HRESULT hr = CheckMediaType(pMediaType); if (FAILED(hr)) return hr; if (avcodec_find_decoder(ConvertGuidToCodecId(pMediaType)) == NULL) return E_ABORT; GUID majorType = GUID_NULL; pMediaType->GetGUID(MF_MT_MAJOR_TYPE, &majorType); if (majorType != MFMediaType_Video && majorType != MFMediaType_Audio) return MF_E_INVALID_CODEC_MERIT; hr = (majorType == MFMediaType_Video ? InitVideoDecoder(pMediaType) : InitAudioDecoder(pMediaType)); if (FAILED(hr)) return hr; MFCreateMediaType(&_inputMediaType); pMediaType->CopyAllItems(_inputMediaType.Get()); return S_OK; }
ErrorCode BasePinImpl::QueryAccept(MediaType* pmt) { ErrorCode hr = CheckMediaType(pmt); if (hr < 0) return 1; return hr; }
HRESULT CAMROutputPin::SetMediaType(const CMediaType *pmt) { // just set internal media type if (FAILED(CheckMediaType(pmt))) { return E_FAIL; } return CBaseOutputPin::SetMediaType(pmt); }
// Set the agree media type set up the necessary parameters HRESULT CScreenCaptureSourcePin::SetMediaType(const CMediaType *pMediaType) { CHECK_POINTER_RETURN_VALUE_IF_FAIL(pMediaType, E_POINTER); if (NULL == pMediaType->Format()) { return VFW_E_INVALIDMEDIATYPE; } HRESULT hr = E_FAIL; //CAutoLock cAutoLock(m_pFilter->pStateLock()); #ifdef _DEBUG DX_VERIFY(CheckMediaType(pMediaType)); if (FAILED(hr)) { return hr; } #endif { CAutoLock cAutoLock(m_pFilter->pStateLock()); COM_VERIFY(__super::SetMediaType(pMediaType)); if (SUCCEEDED(hr)) { VIDEOINFO *pvi = (VIDEOINFO*)m_mt.Format(); //ASSERT(m_iImageWidth == pvi->bmiHeader.biWidth); //ASSERT(m_iImageHeight == abs(pvi->bmiHeader.biHeight)); //ASSERT(m_nCurrentBitDepth == pvi->bmiHeader.biBitCount); //CAutoLock cAutoLock(&m_cStateLock); //if (m_pScreenCaptureImpl) //{ // SAFE_DELETE(m_pScreenCaptureImpl); //} FTLASSERT(pvi->bmiHeader.biHeight > 0); FTLASSERT(pvi->bmiHeader.biWidth > 0); m_nWidth = pvi->bmiHeader.biWidth; m_nHeight = FTL_ABS(pvi->bmiHeader.biHeight); m_nBitCount = pvi->bmiHeader.biBitCount; m_nAvgTimePerFrame = pvi->AvgTimePerFrame; //m_bmpInfo.bmiHeader.biWidth = pvi->bmiHeader.biWidth; //m_bmpInfo.bmiHeader.biHeight = pvi->bmiHeader.biHeight; //m_bmpInfo.bmiHeader.biBitCount = m_nBitCount; //m_bmpInfo.bmiHeader.biCompression = BI_RGB; //m_bmpInfo.bmiHeader.biPlanes = 1; //m_bmpInfo.bmiHeader.biSizeImage = GetBitmapSize(&pvi->bmiHeader); } } return NOERROR; }
STDMETHODIMP BasePin::ReceiveConnection(IPin * aPin, const AM_MEDIA_TYPE *aMediaType) { if (!aPin) return E_POINTER; if (!aMediaType) E_POINTER; CriticalSectionAutoEnter monitor(*mLock); if (IsConnected()) return VFW_E_ALREADY_CONNECTED; if (!IsStopped()) return VFW_E_NOT_STOPPED; HRESULT hr = CheckConnect(aPin); if (FAILED(hr)) { BreakConnect(); return hr; } // See if subclass supports the specified media type. const MediaType* mediaType = reinterpret_cast<const MediaType*>(aMediaType); hr = CheckMediaType(mediaType); if (FAILED(hr)) { BreakConnect(); return hr; } // Supported, set it. hr = SetMediaType(mediaType); if (FAILED(hr)) return hr; // Complete the connection. mConnectedPin = aPin; // Give the subclass one last chance to refuse the connection. hr = CompleteConnect(aPin); if (FAILED(hr)) { // Subclass refused connection, fail... mConnectedPin = NULL; BreakConnect(); return hr; } // It's all good, we're connected. return S_OK; }
//-------------------------------------------------------------------- // //-------------------------------------------------------------------- HRESULT DSFilterRenderStreamDSMediaSample::SetMediaType(const CMediaType *pmt) { /*NWStreamBlockDSMediaSample* streamBlock = NEW NWStreamBlockDSMediaSample(); streamBlock->init(); // Set the time streamBlock->setTime(0); // Add the streamblock to the stream mStream->writeBlock(streamBlock,false);*/ HRESULT hr = CheckMediaType(pmt); return hr; }
HRESULT CAMRInputPin::SetMediaType(const CMediaType* pmt) { // let the baseclass know if (FAILED(CheckMediaType(pmt))) { return E_FAIL; } HRESULT hr = CBasePin::SetMediaType(pmt); if (FAILED(hr)) { return hr; } return NOERROR; }
STDMETHODIMP BasePin::QueryAccept(const AM_MEDIA_TYPE *aMediaType) { if (!aMediaType) return E_POINTER; // Defer to subclasses CheckMediaType() function. Map all errors to S_FALSE, // so that we match the spec for QueryAccept(). if (FAILED(CheckMediaType((MediaType*)aMediaType))) return S_FALSE; return S_OK; }
// Attempt to connect this pin to |aPin| using given media type. HRESULT BasePin::AttemptConnection(IPin* aPin, const MediaType* aMediaType) { CriticalSectionAutoEnter monitor(*mLock); // Ensure we can connect to the other pin. Gives subclasses a chance // to prevent connection. HRESULT hr = CheckConnect(aPin); if (FAILED(hr)) { BreakConnect(); return hr; } // Ensure we can connect with this media type. This gives subclasses a // chance to abort the connection. hr = CheckMediaType(aMediaType); if (FAILED(hr)) return hr; hr = SetMediaType(aMediaType); if (FAILED(hr)) return hr; // Ask the other pin if it will accept a connection with our media type. hr = aPin->ReceiveConnection(static_cast<IPin*>(this), aMediaType); if (FAILED(hr)) return hr; // Looks good so far, give subclass one final chance to refuse connection... mConnectedPin = aPin; hr = CompleteConnect(aPin); if (FAILED(hr)) { // Subclass refused the connection, inform the other pin that we're // disconnecting, and break the connection. aPin->Disconnect(); BreakConnect(); mConnectedPin = NULL; mMediaType.Clear(); return VFW_E_TYPE_NOT_ACCEPTED; } // Otherwise, we're all good! return S_OK; }
////////////////////////////////////////////////////////////////////// // 入力ピンのメディアタイプチェック HRESULT ThroughEx::CheckInputType(const CMediaType *mtIn) { CheckPointer(mtIn,E_POINTER); // check this is a VIDEOINFOHEADER type if (*mtIn->FormatType() != FORMAT_VideoInfo) { return E_INVALIDARG; } // Can we transform this type if (CheckMediaType(mtIn)) { return NOERROR; } return E_FAIL; }
ErrorCode BasePinImpl::ReceiveConnection(IPin *pConnector, MediaType* pMediaType) { if (pConnector == NULL) { ASSERT(0); //return E_INVALIDARG; throw -1; } if (m_dir != PINDIR_INPUT) { ASSERT(0); return Error; } ErrorCode hr; hr = CheckConnect(pConnector); if (hr < 0) { BreakConnect(); return hr; } hr = CheckMediaType(pMediaType); if (hr < 0) { BreakConnect(); return hr; } // Is the order of these last two correct? SetMediaType(pMediaType); hr = CompleteConnect(pConnector); if (hr < 0) { // BreakConnect(); ?? return hr; } return 0; }
STDMETHODIMP CBasePin::QueryAccept( const AM_MEDIA_TYPE *pmt ) { CheckPointer(pmt,E_POINTER); ValidateReadPtr(pmt,sizeof(AM_MEDIA_TYPE)); /* The CheckMediaType method is valid to return error codes if the media type is horrible, an example might be E_INVALIDARG. What we do here is map all the error codes into either S_OK or S_FALSE regardless */ HRESULT hr = CheckMediaType((CMediaType*)pmt); if (FAILED(hr)) { return S_FALSE; } // note that the only defined success codes should be S_OK and S_FALSE... return hr; }
ErrorCode BasePinImpl::AttemptConnection(IPin *pReceivePin, MediaType* mt) { ErrorCode hr; //CheckConnect( Why Is this called here, it will be called multiple times if it's here? hr = CheckConnect(pReceivePin); if (hr < 0) { BreakConnect(); return hr; } hr = CheckMediaType(mt); if (hr < 0) { BreakConnect(); return hr; } hr = pReceivePin->ReceiveConnection(this, mt); if (hr < 0) return hr; hr = SetMediaType(mt); // ?? Have this here?? if (hr < 0) { BreakConnect(); return hr; } hr = CompleteConnect(pReceivePin); if (hr < 0) { Disconnect(); return hr; } return 0; }
HRESULT STDMETHODCALLTYPE CVCamStream::SetFormat(AM_MEDIA_TYPE *pmt) { // this is them saying you "must" use this type from now on...unless pmt is NULL that "means" reset...LODO handle it someday... if(!pmt) { return S_OK; // *sure* we reset..yeah...sure we did... } if(CheckMediaType((CMediaType *) pmt) != S_OK) { return E_FAIL; // just in case :P [FME...] } m_mt = *pmt; IPin* pin; ConnectedTo(&pin); if(pin) { IFilterGraph *pGraph = m_pParent->GetGraph(); pGraph->Reconnect(this); } return S_OK; }
// sets fps, size, (etc.) maybe, or maybe just saves it away for later use... HRESULT STDMETHODCALLTYPE CPushPinDesktop::SetFormat(AM_MEDIA_TYPE *pmt) { CAutoLock cAutoLock(m_pFilter->pStateLock()); // I *think* it can go back and forth, then. You can call GetStreamCaps to enumerate, then call // SetFormat, then later calls to GetMediaType/GetStreamCaps/EnumMediatypes will all "have" to just give this one // though theoretically they could also call EnumMediaTypes, then SetMediaType, and not call SetFormat // does flash call both? what order for flash/ffmpeg/vlc calling both? // LODO update msdn // "they" [can] call this...see msdn for SetFormat // NULL means reset to default type... if(pmt != NULL) { if(pmt->formattype != FORMAT_VideoInfo) // same as {CLSID_KsDataTypeHandlerVideo} return E_FAIL; // LODO I should do more here...http://msdn.microsoft.com/en-us/library/dd319788.aspx I guess [meh] // LODO should fail if we're already streaming... [?] VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *) pmt->pbFormat; if(CheckMediaType((CMediaType *) pmt) != S_OK) { return E_FAIL; // just in case :P [did skype get here once?] } // for FMLE's benefit, only accept a setFormat of our "final" width [force setting via registry I guess, otherwise it only shows 80x60 whoa!] // flash media live encoder uses setFormat to determine widths [?] and then only displays the smallest? oh man that is messed up if( pvi->bmiHeader.biWidth != getCaptureDesiredFinalWidth() || pvi->bmiHeader.biHeight != getCaptureDesiredFinalHeight()) { return E_INVALIDARG; } // ignore other things like cropping requests for now... // now save it away...for being able to re-offer it later. We could use SetMediaType but we're just being lazy and re-using m_mt for many things I guess m_mt = *pmt; // The frame rate at which your filter should produce data is determined by the AvgTimePerFrame field of VIDEOINFOHEADER if(pvi->AvgTimePerFrame) m_rtFrameLength = pvi->AvgTimePerFrame; // allow them to set whatever fps they request, i.e. if it's less than the max default. VLC command line can specify this, for instance... // also setup scaling here, as WFMLE and ffplay and VLC all get here... m_rScreen.right = m_rScreen.left + pvi->bmiHeader.biWidth; // allow them to set whatever "scaling size" they want [set m_rScreen is negotiated right here] m_rScreen.bottom = m_rScreen.top + pvi->bmiHeader.biHeight; } IPin* pin; ConnectedTo(&pin); if(pin) { IFilterGraph *pGraph = m_pParent->GetGraph(); HRESULT res = pGraph->Reconnect(this); if(res != S_OK) // LODO check first, and then just re-use the old one? return res; // else return early...not really sure how to handle this...since we already set m_mt...but it's a pretty rare case I think... // plus ours is a weird case... } else { // graph hasn't been built yet... // so we're ok with "whatever" format they pass us, we're just in the setup phase... } // success of some type if(pmt == NULL) { m_bFormatAlreadySet = false; } else { m_bFormatAlreadySet = true; } return S_OK; }
STDMETHODIMP CBasePin::ReceiveConnection( IPin * pConnector, // this is the pin who we will connect to const AM_MEDIA_TYPE *pmt // this is the media type we will exchange ) { CheckPointer(pConnector,E_POINTER); CheckPointer(pmt,E_POINTER); ValidateReadPtr(pConnector,sizeof(IPin)); ValidateReadPtr(pmt,sizeof(AM_MEDIA_TYPE)); CComAutoLock cObjectLock(m_pLock); #ifdef _DEBUG PIN_INFO PinInfo; if(!FAILED(pConnector->QueryPinInfo(&PinInfo))) { CEasyString PinName=PinInfo.achName; PrintSystemLog(0,"RecvPin:%s",(LPCTSTR)PinName); if(PinInfo.pFilter) { FILTER_INFO FilterInfo; if (!FAILED(PinInfo.pFilter->QueryFilterInfo(&FilterInfo))) { CLSID ClassID; PinInfo.pFilter->GetClassID(&ClassID); CEasyString FilterName=FilterInfo.achName; PrintSystemLog(0,"RecvPinFilter:%s",(LPCTSTR)FilterName); // The FILTER_INFO structure holds a pointer to the Filter Graph // Manager, with a reference count that must be released. if (FilterInfo.pGraph != NULL) { FilterInfo.pGraph->Release(); } } PinInfo.pFilter->Release(); } //MessageBox(NULL, (LPCTSTR)PinName, TEXT("Filter Name"), MB_OK); } #endif /* Are we already connected */ if (m_Connected) { return VFW_E_ALREADY_CONNECTED; } /* See if the filter is active */ if (!IsStopped() && !m_bCanReconnectWhenActive) { return VFW_E_NOT_STOPPED; } HRESULT hr = CheckConnect(pConnector); if (FAILED(hr)) { // Since the procedure is already returning an error code, there // is nothing else this function can do to report the error. EXECUTE_ASSERT( SUCCEEDED( BreakConnect() ) ); return hr; } /* Ask derived class if this media type is ok */ CMediaType * pcmt = (CMediaType*) pmt; hr = CheckMediaType(pcmt); if (hr != NOERROR) { // no -we don't support this media type // Since the procedure is already returning an error code, there // is nothing else this function can do to report the error. EXECUTE_ASSERT( SUCCEEDED( BreakConnect() ) ); // return a specific media type error if there is one // or map a general failure code to something more helpful // (in particular S_FALSE gets changed to an error code) if (SUCCEEDED(hr) || (hr == E_FAIL) || (hr == E_INVALIDARG)) { hr = VFW_E_TYPE_NOT_ACCEPTED; } return hr; } /* Complete the connection */ m_Connected = pConnector; m_Connected->AddRef(); hr = SetMediaType(pcmt); if (SUCCEEDED(hr)) { hr = CompleteConnect(pConnector); if (SUCCEEDED(hr)) { return NOERROR; } } DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("Failed to set the media type or failed to complete the connection."))); m_Connected->Release(); m_Connected = NULL; // Since the procedure is already returning an error code, there // is nothing else this function can do to report the error. EXECUTE_ASSERT( SUCCEEDED( BreakConnect() ) ); return hr; }
STDMETHODIMP TffdshowVideoInputPin::ReceiveConnection(IPin* pConnector, const AM_MEDIA_TYPE* pmt) { HRESULT hr; DPRINTF(_l("TffdshowVideoInputPin::ReceiveConnection")); CAutoLock cObjectLock(m_pLock); const CLSID &ref = GetCLSID(pConnector); if (ref == CLSID_MPC_MatroskaSplitter || ref == CLSID_GabestMatroskaSplitter) { connectedSplitter = MPC_matroska_splitter; } else if (ref == CLSID_HaaliMediaSplitter) { connectedSplitter = Haali_Media_splitter; } else if (ref == CLSID_MPC_MpegSourceFilter || ref == CLSID_MPC_MpegSplitterFilter) { connectedSplitter = MPC_mpegSplitters; } else if (ref == CLSID_DVBSourceFilter) { connectedSplitter = DVBSourceFilter; } else if (ref == CLSID_PBDA_DTFilter) { connectedSplitter = PBDA_DTFilter; } else if (ref == CLSID_NeuviewSource) { connectedSplitter = NeuviewSource; } #if 0 PIN_INFO pininfo; FILTER_INFO filterinfo; pConnector->QueryPinInfo(&pininfo); if (pininfo.pFilter) { pininfo.pFilter->QueryFilterInfo(&filterinfo); DPRINTF(_l("TffdshowVideoInputPin::ReceiveConnection filter=%s pin=%s"), filterinfo.achName, pininfo.achName); if (filterinfo.pGraph) { filterinfo.pGraph->Release(); } pininfo.pFilter->Release(); } DPRINTF(_l("CLSID 0x%x,0x%x,0x%x"), ref.Data1, ref.Data2, ref.Data3); for (int i = 0; i < 8; i++) { DPRINTF(_l(",0x%2x"), ref.Data4[i]); } #endif if (m_Connected) { CMediaType mt(*pmt); BITMAPINFOHEADER bih, bihCur; ExtractBIH(mt, &bih); ExtractBIH(m_mt, &bihCur); // HACK: for the intervideo filter, when it tries to change the pitch from 720 to 704... //if(bihCur.biWidth != bih.biWidth && bihCur.biHeight == bih.biHeight) // return S_OK; return (CheckMediaType(&mt) != S_OK || SetMediaType(&mt) != S_OK/* || !initVideo(mt)*/) ? VFW_E_TYPE_NOT_ACCEPTED : S_OK; // TODO: send ReceiveConnection downstream } else { hr = fv->deci->checkInputConnect(pConnector); if (hr != S_OK) { return hr; } } hr = TinputPin::ReceiveConnection(pConnector, pmt); return hr; }
HRESULT CWaveOutRenderer::CheckInputType(const CMediaType* mtIn) { return CheckMediaType(mtIn); }
HRESULT CMpcAudioRenderer::CheckInputType(const CMediaType *pmt) { return CheckMediaType(pmt); }
// given a specific media type, attempt a connection (includes // checking that the type is acceptable to this pin) HRESULT CBasePin::AttemptConnection( IPin* pReceivePin, // connect to this pin const CMediaType* pmt // using this type ) { // The caller should hold the filter lock becasue this function // uses m_Connected. The caller should also hold the filter lock // because this function calls SetMediaType(), IsStopped() and // CompleteConnect(). ASSERT(CritCheckIn(m_pLock)); // Check that the connection is valid -- need to do this for every // connect attempt since BreakConnect will undo it. HRESULT hr = CheckConnect(pReceivePin); if (FAILED(hr)) { DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("CheckConnect failed"))); // Since the procedure is already returning an error code, there // is nothing else this function can do to report the error. EXECUTE_ASSERT( SUCCEEDED( BreakConnect() ) ); return hr; } DisplayTypeInfo(pReceivePin, pmt); /* Check we will accept this media type */ hr = CheckMediaType(pmt); if (hr == NOERROR) { /* Make ourselves look connected otherwise ReceiveConnection may not be able to complete the connection */ m_Connected = pReceivePin; m_Connected->AddRef(); hr = SetMediaType(pmt); if (SUCCEEDED(hr)) { /* See if the other pin will accept this type */ hr = pReceivePin->ReceiveConnection((IPin *)this, pmt); if (SUCCEEDED(hr)) { /* Complete the connection */ hr = CompleteConnect(pReceivePin); if (SUCCEEDED(hr)) { return hr; } else { DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("Failed to complete connection"))); pReceivePin->Disconnect(); } } } } else { // we cannot use this media type // return a specific media type error if there is one // or map a general failure code to something more helpful // (in particular S_FALSE gets changed to an error code) if (SUCCEEDED(hr) || (hr == E_FAIL) || (hr == E_INVALIDARG)) { hr = VFW_E_TYPE_NOT_ACCEPTED; } } // BreakConnect and release any connection here in case CheckMediaType // failed, or if we set anything up during a call back during // ReceiveConnection. // Since the procedure is already returning an error code, there // is nothing else this function can do to report the error. EXECUTE_ASSERT( SUCCEEDED( BreakConnect() ) ); /* If failed then undo our state */ if (m_Connected) { m_Connected->Release(); m_Connected = NULL; } return hr; }