利用Directshow開發源Filter

來源:互聯網
上載者:User

摘要:
我們一般不推薦自己開發音頻或者視頻捕捉過濾器,因為diectshow對於音視頻的捕捉裝置以經提供了支援。所以,這篇文檔,對於某些使用者需要從特定裝置捕捉一些資料提供一些協助。這篇文檔主要包括以下內容。
1捕捉filter 對pin的要求
2如何完成一個預覽pin
3如何產生來源資料
1 對pin的要求Pin Requirements for Capture Filters
Pin的名字
你可以給你的filter起任何名字,如果你的pin的名字以~符號開頭,那麼當應用程式調用IGraphBuilder::RenderFile方法時,filter圖表管理器不會自動render這個pin的。例如,如果一個filter具有一個捕捉pin和預覽pin,相應的你給他們命名為”~Capture”和“Preview”。如果一個應用程式在graph中render這個filter ,那麼預覽pin就會自動和它預設的render相串連,但是,capture pin上卻不串連任何東西,這是一個合理的預設行為。這個也可以應用到那些傳輸不準備被rendered資料的pin,也可以應用到需要屬性設定的pin上。
註:名字中含有~符號的pin是可以手動串連的。
Pin的種類
一個捕捉filter通常用一個捕捉pin,也許還有一個預覽pin。一些捕捉filter除了這兩種pin之外還有其他的pin,用來傳遞其他的資料,例如控制資訊。每一個輸出pin都必須暴露IKsPropertySet介面,應用程式通過這些介面來判斷pin的種類,pin一般都會返回PIN_CATEGORY_CAPTURE or PIN_CATEGORY_PREVIEW。下面的例子示範了一個捕捉pin如何通過IKsPropertySet來返回pin的種類
// Set: Cannot set any properties.
HRESULT CMyCapturePin::Set(REFGUID guidPropSet, DWORD dwID,
void *pInstanceData, DWORD cbInstanceData, void *pPropData,
DWORD cbPropData)
{
return E_NOTIMPL;
}

// Get: Return the pin category (our only property).
HRESULT CMyCapturePin::Get(
REFGUID guidPropSet, // Which property set.
DWORD dwPropID, // Which property in that set.
void *pInstanceData, // Instance data (ignore).
DWORD cbInstanceData, // Size of the instance data (ignore).
void *pPropData, // Buffer to receive the property data.
DWORD cbPropData, // Size of the buffer.
DWORD *pcbReturned // Return the size of the property.
)
{
if (guidPropSet != AMPROPSETID_Pin)
return E_PROP_SET_UNSUPPORTED;
if (dwPropID != AMPROPERTY_PIN_CATEGORY)
return E_PROP_ID_UNSUPPORTED;
if (pPropData == NULL && pcbReturned == NULL)
return E_POINTER;
if (pcbReturned)
*pcbReturned = sizeof(GUID);
if (pPropData == NULL) // Caller just wants to know the size.
return S_OK;
if (cbPropData < sizeof(GUID)) // The buffer is too small.
return E_UNEXPECTED;
*(GUID *)pPropData = PIN_CATEGORY_CAPTURE;
return S_OK;
}

// QuerySupported: Query whether the pin supports the specified property.
HRESULT CMyCapturePin::QuerySupported(REFGUID guidPropSet, DWORD dwPropID,
DWORD *pTypeSupport)
{
if (guidPropSet != AMPROPSETID_Pin)
return E_PROP_SET_UNSUPPORTED;
if (dwPropID != AMPROPERTY_PIN_CATEGORY)
return E_PROP_ID_UNSUPPORTED;
if (pTypeSupport)
// We support getting this property, but not setting it.
*pTypeSupport = KSPROPERTY_SUPPORT_GET;
return S_OK;
}

2如何完成一個預覽pin Implementing a Preview Pin (Optional)
如果你的filter有一個預覽pin,預覽pin發送的資料是捕捉pin傳遞的資料的拷貝。預覽pin發送的資料不會降低捕捉pin的楨率,捕捉pin比預覽pin有優先權。
捕捉pin和預覽pin必鬚髮送一個相同格式的資料。這樣,他們串連都是通過同一種媒體資料類型,如果捕捉pin先串連,預覽pin應該提供相同的媒體類型,對於其他類型的資料媒體,則拒絕。如果預覽pin先串連,然後,如果捕捉pin以另一種媒體類型和其他pin串連,那麼預覽pin就應該用新的媒體類型重新串連,如果和filter的預覽pin串連的下遊filter拒絕新的資料類型,捕捉pin應該拒絕新的媒體類型。可以通過IPin::QueryAccept方法察看filter的預覽pin串連的下遊filter串連的資料媒體,然後通過IFilterGraph::Reconnect方法重新串連pin。
這條規則也適用於圖表管理器重新串連捕捉pin。
下面的代碼大體上描述了上面的過程
// Override CBasePin::CheckMediaType.
CCapturePin::CheckMediaType(CMediaType *pmt)
{
if (m_pMyPreviewPin->IsConnected())
{
// The preview pin is already connected, so query the pin it is
// connected to. If the other pin rejects it, so do we.
hr = m_pMyPreviewPin->GetConnected()->QueryAccept(pmt);
if (hr != S_OK)
{
// The preview pin cannot reconnect with this media type.
return E_INVALIDARG;
}
// The preview pin will reconnect when SetMediaType is called.
}
// Decide whether the capture pin accepts the format.
BOOL fAcceptThisType = ... // (Not shown.)
return (fAcceptThisType? S_OK : E_FAIL);
}

// Override CBasePin::SetMediaType.
CCapturePin::SetMediaType(CMediaType *pmt);
{
if (m_pMyPreviewPin->IsConnected())
{
// The preview pin is already connected, so it must reconnect.
if (m_pMyPreviewPin->GetConnected()->QueryAccept(pmt) == S_OK)
{
// The downstream pin will accept the new type, so it''s safe
// to reconnect.
m_pFilter->m_pGraph->Reconnect(m_pMyPreviewPin);
}
else
{
return VFW_E_INVALIDMEDIATYPE;
}
}
// Now do anything that the capture pin needs to set the type.
hr = MyInternalSetMediaType(pmt);

// And finally, call the base-class method.
return CBasePin::SetMediaType(pmt);
}

CPreviewPin::CheckMediaType(CMediaType *pmt)
{
if (m_pMyCapturePin->IsConnected())
{
// The preview pin must connect with the same type.
CMediaType cmt = m_pMyCapturePin->m_mt;
return (*pmt == cmt ? S_OK : VFW_E_INVALIDMEDIATYPE);
}
// Decide whether the preview pin accepts the format. You can use your
// knowledge of which types the capture pin will accept. Regardless,
// when the capture pin connects, the preview pin will reconnect.
return (fAcceptThisType? S_OK : E_FAIL);
}

3在源filter中產生資料 Producing Data in a Capture Filter
狀態改變
一個捕捉filter在運行時會產生資料流。當filter paused的時候,不要發送資料,並且此時,圖表管理器調用CBaseFilter::GetState方法會返回VFW_S_CANT_CUE,這個傳回值告訴圖表管理器,filter 正處於paused狀態,停止發送資料。下面的代碼顯示如何派生GetState方法
CMyVidcapFilter::GetState(DWORD dw, FILTER_STATE *pState)
{
CheckPointer(pState, E_POINTER);
*pState = m_State;
if (m_State == State_Paused)
return VFW_S_CANT_CUE;
else
return S_OK;
}
控制不同的資料流
一個捕捉filter應該支援IAMStreamControl介面,因此應用程式應該分別的開啟和關閉每一個pin,例如,一個應用程式可以只預覽而沒有捕捉,然後可以轉換到捕捉模式不用重新構建grap***表。你可以通過CBaseStreamControl類來實現這個介面
時間戳記
當一個filter捕捉了一個sample,將在每一個sample上標上一個目前時間的時間戳記。結束時間是開始時間加上期間。例如,如果一個filter每秒捕捉十個sample,and the stream time is 200,000,000 units when the filter captures the sample, the time stamps should be 200000000 and 201000000. (There are 10,000,000 units per second.)
可以通過IReferenceClock::GetTime方法獲得當前的參考時間,通過IMediaSample::SetTime給sample設定時間戳記。
相連的sample上的時間戳記必須是遞增的,即使filter pauses也是這樣,如果一個filter運行,停止,然後又運行,重新開始後產生的sample上的時間戳記必須比停止前的sample上的時間戳記要大一些。
預覽pin上的sample沒有時間戳記,但是,預覽pin一般比捕捉pin到達render pin稍晚,因此,render filter將預覽pin上的sample視作遲到的sample,為了趕上其他的時間進度,也許會丟失一些資料。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.