分享
 
 
 

利用Directshow开发源Filter

王朝vc·作者佚名  2006-12-17
窄屏简体版  字體: |||超大  

利用Directshow开发源Filter

利用Directshow开发源Filter 摘要:

我们一般不推荐自己开发音频或者视频捕捉过滤器,因为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,例如,一个应用程序可以只预览而没有捕捉,然后可以转换到捕捉模式不用重新构建graph图表。你可以通过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,为了赶上其他的时间进度,也许会丢失一些数据。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有