关键词不能为空

当前您在: 主页 > 英语 >

DirectShow从静止图像pin中捕捉图片

作者:高考题库网
来源:https://www.bjmy2z.cn/gaokao
2021-03-02 20:25
tags:

-

2021年3月2日发(作者:小玩意儿)




1.


关于视频捕捉(


About Video Capture in Dshow





1


视频捕捉


Graph


的构建



一个能 够捕捉音频或者视频的


graph


图都称之为捕捉


graph


图。捕捉


graph

图比一般的文件回放


graph


图要复杂许多,

< p>
dshow


提供了一个


Capture


Graph


Builder


COM


组件使得捕捉


graph


图的生成更加 简单。


C


apture


Graph


Builder


提供了一个


ICapt ureGraphBuilder2


接口,这个接口提供了一些方法用来构建和控制捕< /p>



graph




首先创建一个


Capture


Graph


Builder


对象和一个


graph


manger


对象,然后用


filte r


graph


manager



参数,调用


ICaptureGraphBuilder2:: SetFiltergraph


来初始化


Capture


Graph


Builder


。看下面的代码把



HRESULT InitCaptureGraphBuilder(


IGraphBuilder **ppGraph, // Receives the pointer.


ICaptureGraphBuilder2 **ppBuild // Receives the pointer.


)


{


if (!ppGraph || !ppBuild)


{


return E_POINTER;


}


IGraphBuilder *pGraph = NULL;


ICaptureGraphBuilder2 *pBuild = NULL;


// Create the Capture Graph Builder.


HRESULT hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,


CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void**)&pGraph);


if (SUCCEEDED(hr))


{




// Create the Filter Graph Manager.


hr = CoCreateInstance(CLSID_FilterGraph, 0, CLSCTX_INPROC_SERVER,


IID_IGraphBuilder, (void**)&pGraph);


if (SUCCEEDED(hr))


{


// Initialize the Capture Graph Builder.


pBuild->SetFiltergraph(pGraph);


// Return both interface pointers to the caller.


*ppBuild = pBuild;


*ppGraph = pGraph; // The caller must release both interfaces.


return S_OK;


}


Else


{


pBuild->Release();


}


}


return hr; // Failed


}



2.


Di recshow


中视频捕捉的


Filter



Pin


的种类



捕捉


Filter


一般都有两个或多个输出

< br>pin


,他们输出的媒体类型都一样,


比如预览


pin


和捕捉


pin



因此


根据媒体类型就不能很好的区别这些


pin


。此时就要根据


pin


的功能 来区别每个


pin


了,每个


pin


都有一个


GUID


,称为

< br>pin


的种类。



如果想仔细的 了解


pin


的种类,请看后面的相关内容


Working with Pin Categories


。对于大多数的应用


来说,


ICaptureGraphBuilder2


提供了一些函数可以自动确定


pin


的种类。



预览


pin


和捕捉


pin


视频捕捉


Filter


都提供了预览和捕捉的输出


pin


,预览


pin


用来将视频流在屏幕上显示,捕捉


p in


用来


将视频流写入文件。



预览


pin


和输出


p in


有下面的区别:



1

< p>
为了保证捕捉


pin


对视频桢流量,预览


pin


必要的时候可以停止。



2


经过捕捉


pin

< br>的视频桢都有时间戳,但是预览


pin


的视频流没有时间 戳。



预览


pin

的视频流之所以没有时间戳的原因在于


filter


图表管 理器在视频流里加一个很小的


latency




果捕捉时间被认为就是


render


时间的话,


视频


renderFilter

< p>
就认为视频流有一个小小的延迟,


如果此时


ren der


filter


试图连续播放的时候,

< br>就会丢桢。


去掉时间戳就保证了视频桢来了就可以播放,


不用等待,


也不丢桢。



Video Port pin


Video Port


是一个介于视频设备



TV


)和视频卡之间的硬件设备。同 过


Video Port


,视频数据可以直接

< br>发送到图像卡上,通过硬件的覆盖,视频可以直接在屏幕显示出来。


Video Port


就是连接两个设备的。



使用


Video Port


的最大好处 是,


不用


CPU


的任何工作,


视频流直接写入内存中。


如果捕捉设备使用了


V ideo


Port


,捕捉


Filte r


就用一个


video port pin

代替预览


pin




预览


pin


的种类


GUID



PIN_CATEGORY_PREVIEW


捕捉


pin


的种类


GUID



PIN_CATEGORY_CAPTURE



video port pin


的种 类


GUID



PIN_CATEGOR Y_VIDEOPORT


一个捕捉


filter


至少有一个


Capture pin


,另外,它可能有一个预览


pin


和一个


video port pin


,或者两者都没有,也许


filter


有很多的


capture pin


,和预览


pin

< p>
,每一个


pin


都代表一种媒体类型,因此一



filter


可以有一个视频

< p>
capture pin


,视频预览


pin


,音频捕捉


pin


,音频预览


pin




3.


预览视频(


Previewing Video





为了创建可以预览视频的


graph


,可以调用 下面的代码



ICaptureGraphBuilder2 *pBuild; // Capture Graph Builder


// Initialize pBuild (not shown).


IBaseFilter *pCap; // Video capture filter.


/* Initialize pCap and add it to the filter graph (not shown). */


hr = pBuild->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,


pCap, NULL, NULL);




4.


如何 捕捉视频流并保存到文件



Capture


video


to



File




1)



将视频流保存 到


AVI


文件



下面的图表显示了


graph






2


AVI


Mux


filter


接收从


capture


pin


过来的视频流,然后将其打包成


AVI


流。音频流也可以连接到


AVI


Mu


x


Filter


上,这样


mux


filter


就将视频流和视频流合成


AVI


流。


File


writer



AVI


流写入到文件中。


可以像下面这样构建


graph




IBaseFilter *pMux;


hr = pBuild->SetOutputFileName(


&MEDIASUBTYPE_Avi, // Specifies AVI for the target file.


L


&pMux, // Receives a pointer to the mux.


NULL); // (Optional) Receives a pointer to the file sink.


第一个参数表明文件的类型, 这里表明是


AVI


,第二个参数是制定文件的名称。对于


AVI


文件,


Set


OutputFileName


函数会创建一个


AVI


mux


Filter


和一个



File


writer


Filter


,并且 将两个


filter


添加到


grap< /p>


h


图中,在这个函数中,通过


File


Writer


Filter


请求< /p>


IFileSinkFilter


接口,然后调用


IFileSinkFilter::SetFile


Name


方法,设置文件的名称。然后将两个


filter


连接 起来。第三个参数返回一个指向



AVI

Mux


的指针,


同时,它也通过第四个参数返回一个


IFileSinkFilter


参数,如果你不需要这个参数,你可 以将这个参数设置



NULL




然后,你应该调用下面的函数将


capture


filter



AVI


Mux


连接起来。



hr = pBuild->RenderStream(


&PIN_CATEGORY_CAPTURE, // Pin category.


&MEDIATYPE_Video, // Media type.


pCap, // Capture filter.


NULL, // Intermediate filter (optional).


pMux); // Mux or file sink filter.


// Release the mux filter.


pMux->Release();


< br>5


个参数就是使用的上面函数返回的


pMux

< p>
指针。



当捕捉音频的时候,媒体类型要设置为< /p>


MEDIATYPE_Audio


,如果你从两个不同的设备捕捉 视频和音


频,你最好将音频设置成主流,这样可以防止两个数据流间

drift


,因为


avi


mux


filter


为同步音频,会调整


视频 的播放速度的。为了设置


master


流,调用


IConfigAviMux::SetMasterStream


方法,可 以采用如下的代


码:



IConfigAviMux *pConfigMux = NULL;


hr = pMux->QueryInterface(IID_IConfigAviMux, (void**)&pConfigMux);


if (SUCCEEDED(hr))


{


pConfigMux->SetMasterStream(1);


pConfigMux->Release();


}


S etMasterStream


的参数指的是数据流的数目,这个是由调用


RenderStream


的次序决定的。例如,如果


你调用


RenderStream


首先用于视频流,然后是音 频,那么视频流就是


0


,音频流就是


1




添加编码


filter


IBaseFilter *pEncoder; /* Create the encoder filter (not shown). */


// Add it to the filter graph.


pGraph->AddFilter(pEncoder, L


/* Call SetOutputFileName as shown previously. */


// Render the stream.


hr = pBuild->RenderStream(


&PIN_CATEGORY_CAPTURE,


&MEDIATYPE_Video,


pCap, pEncoder, pMux);


pEncoder->Release();


2)



将视频流保存 成


wmv


格式的文件



为了将视频流保存成并编码成


windows


media


video



WMV


)格式的文件,将


capture


pin


连到


WM


ASF



Writer


filter






3


构建


graph


图最简单的方法就是将在


I CaptureGraphBuilder2::SetOutputFileName


方法中指定


MEDIASUBTYPE_Asf



filter


。如下



IBaseFilter* pASFWriter = 0;


hr = pBuild->SetOutputFileName(


&MEDIASUBTYPE_Asf, // Create a Windows Media file.


L


&pASFWriter, // Receives a pointer to the filter.


NULL); // Receives an IFileSinkFilter interface pointer (optional).


参数


MEDIASUBTYPE_Asf


告诉


graph


builder


,要使用


wm


asf


writer


作为文件接收器 ,于是,


pbuil


d


就创建这个< /p>


filter



将其添加到


graph


图中,


然后调用


IFileSinkFilter::SetFileName


来设置输出文件的名字。


第三个参数用来返回一个


ASF


wr iter


指针,第四个参数用来返回文件的指针。


< p>
在将任何


pin


连接到


W M


ASF


Writer


之前,


一定要对


WM


ASF

< br>Writer


进行一下设置,


你可以同过


W


M


ASF


Writer



IConfigAsfWriter


接口指针来进行设置。



IConfigAsfWriter *pConfig = 0;


hr = pASFWriter->QueryInterface(IID_IConfigAsfWriter, (void**)&pCon


fig);


if (SUCCEEDED(hr))


{


// Configure the ASF Writer filter.


pConfig->Release();


}


然后调用


ICaptureGraphBuilder2::RenderStream



capture


Filter




ASF


writer


连接起来。



hr = pBuild->RenderStream(


&PIN_CATEGORY_CAPTURE, // Capture pin.


&MEDIATYPE_Video, // Video. Use MEDIATYPE_Audio for audio.


pCap, // Pointer to the capture filter.


0,


pASFWriter); // Pointer to the sink filter (ASF Writer).


3)



保存成自定义的文件格式



如果你想将文件保存成自己的格式,你必须有自己的



file


writer


。看下面的代码



IBaseFilter *pMux = 0;


IFileSinkFilter *pSink = 0;


hr = pBuild->SetOutputFileName(


&CLSID_MyCustomMuxFilter, //


自己开发的


Filter


L


4)



如何将视频流保存进多个文件



当你将 视频流保存进一个文件后,如果你想开始保存第二个文件,这时,你应该首先将


grap h


停止,


然后通过


IFileSink Filter::SetFileName


改变



File


Writer


的文件名称 。注意,


IFileSinkFilter


指针你可以在


Se


tOutputFileName


时通过 第四个参数返回的。



看看保存多个文件的代码吧



IBaseFilter *pMux;


同步的


synchronization


IFileSinkFilter *pSink


hr = pBuild->SetOutputFileName(&MEDIASUBTYPE_Avi, L



&pMux, &pSink);


if (SUCCEEDED(hr))


{


hr = pBuild->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,


pCap, NULL, pMux);


if (SUCCEEDED(hr))


{


pControl->Run();


/* Wait awhile, then stop the graph. */


pControl->Stop();


// Change the file name and run the graph again.


pSink->SetFileName(L


pControl->Run();


}


pMux->Release();


pSink->Release();


}


5)



组合视频的捕捉和预览



如果想组建一 个既可以预览视频,又可以将视频保存成文件的


graph


,只 需要两次调用


ICaptureGraph


Builder2: :RenderStream


即可。代码如下:



// Render the preview stream to the video renderer.


hr = pBuild->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,


pCap, NULL, NULL);


// Render the capture stream to the mux.


hr = pBuild->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,


pCap, NULL, pMux);


在上面的代码中,


graph


builder


其实隐藏了下面的细节。



1


如果


capture


Filter


既有


preview


pin


也有


captrue


pin


,那么


RenderStream


仅仅将两个


pin



render


filter


接起来。如下图





4


2


如果


caprture


Filter


只有一个


capture


pin


,那么


Capture


Graph


Builder


就采用一个


Smart


Tee


Filter


将视

< p>
频流分流,


graph


图如下




5





5.


如何控制


Capture Graph



Controlling Capture



Graph




Filter


图表管理器可以通过


IMediaContro l


接口控制整个


graph


的运行,停 止和暂停。但是当一个


graph


有捕捉和预览两个数据流的时 候,如果我们想单独的控制其中的一个数据流话,我们可以通过


ICaptureGra phBuilder2::ControlStream




下面讲一下如何来单独控制捕捉和预览数据流。



1


控制捕捉视频流



下面的代码,让捕捉数据流在


graph


开始运行


1


秒后开始,允运行


4

秒后结束。



// Control the video capture stream.


REFERENCE_TIME rtStart = 1000 0000, rtStop = 5000 0000;


const WORD wStartCookie = 1, wStopCookie = 2; // Arbitrary values.


hr = pBuild->ControlStream(


&PIN_CATEGORY_CAPTURE, // Pin category.


&MEDIATYPE_Video, // Media type.


pCap, // Capture filter.


&rtStart, &rtStop, // Start and stop times.


wStartCookie, wStopCookie // Values for the start and stop events.


);


pControl->Run();


第一个参数表明需 要控制的数据流,一般采用的是


pin


种类

GUID




第二个参数表明了媒体类型。



第三个 参数指明了捕捉的


filter


。如果想要控制


graph


图中的所有捕捉


filter


,第二个和第三个参数都要设置



NULL




第四和第五个参数表明了流开始和结束的时 间,这是一个相对于


graph


开始的时间。

< br>


只有你调用


IMediaControl::Run< /p>


以后,这个函数才有作用。如果


graph


正在运行,这个设置立即生效。



最后的两个参数用来设置当 数据流停止,开始能够得到的事件通知。对于任何一个运用此方法的数据


流,

< p>
graph


当流开始的时候,会发送


EC_STR EAM_CONTROL_STARTED


通知,在流结束的时候,要发送


EC_STREAM_CONTROL_STOPPED


通知。


wStartCookie



wStopCooki e


是作为第二个参数的。



看看事件通知处理过程吧



while (hr = pEvent->GetEvent(&evCode, ¶m1, ¶m2, 0), SUCCEEDE


D(hr))


{


switch (evCode)


{


case EC_STREAM_CONTROL_STARTED:


// param2 == wStartCookie


break;


case EC_STREAM_CONTROL_STOPPED:


// param2 == wStopCookie


break;


}


pEvent->FreeEventParams(evCode, param1, param2);


}


ControlStream


还定义了一些特定的值来表示开始和停止的时间。



MAXLONGLONG


从不开始,只有在

< br>graph


停止的时候才停止



NULL




立即开始和停止



例如,下面的代码立即停止捕捉流。



pBuild->ControlStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pCap,


0, 0, // Start and stop times.


wStartCookie, wStopCookie);


2


控制预览视频流


< br>只要给


ControlStream


第一个参数设置成< /p>


PIN_CATEGORY_PREVIEW


就可以控制预览


pin


,整个函数的使


用和控制捕捉流一样 ,但是唯一区别是在这里你没法设置开始和结束时间了,因为预览的视频流没有时间


戳, 因此你必须使用


NULL


或者


MAXL ONGLONG


。例子



Use NULL to start the preview stream:


pBuild->ControlStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pCap,


NULL, // Start now.


0, // (Don't care.)


wStartCookie, wStopCookie);


Use MAXLONGLONG to stop the preview stream:


pBuild->ControlStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pCap,


0, // (Don't care.)


MAXLONGLONG, // Stop now.


wStartCookie, wStopCookie);


3


关于数据流的控制



Pin


的缺省的行为是传递


sample



例如,


如果你对


PIN_ CATEGORY_CAPTURE


使用了


ControlSt ream



但是对于


PIN_CATE GORY_PREVIEW


没有使用该函数,因此,当你


run


graph


的时候,


preview


流会立即


运行起来,而


capture


流则要等到你设置的时间运行。




6.


如何配置一个视频捕捉设备




1


显示

< br>VFW


驱动的视频设备对话框



如果视频捕捉设备采用的仍然是


VFW


方式的驱动程序,则必须 支持下面三个对话框,用来设置视频


设备。



1


Video


Source



用来选择视频输入设备并且调整设备的设置,比如亮度和对比 度。



2Video


Format


用来设置桢的大小和位



3Video


Display


用来设置视频的显示参数


-


-


-


-


-


-


-


-



本文更新与2021-03-02 20:25,由作者提供,不代表本网站立场,转载请注明出处:https://www.bjmy2z.cn/gaokao/692829.html

DirectShow从静止图像pin中捕捉图片的相关文章

  • 爱心与尊严的高中作文题库

    1.关于爱心和尊严的作文八百字 我们不必怀疑富翁的捐助,毕竟普施爱心,善莫大焉,它是一 种美;我们也不必指责苛求受捐者的冷漠的拒绝,因为人总是有尊 严的,这也是一种美。

    小学作文
  • 爱心与尊严高中作文题库

    1.关于爱心和尊严的作文八百字 我们不必怀疑富翁的捐助,毕竟普施爱心,善莫大焉,它是一 种美;我们也不必指责苛求受捐者的冷漠的拒绝,因为人总是有尊 严的,这也是一种美。

    小学作文
  • 爱心与尊重的作文题库

    1.作文关爱与尊重议论文 如果说没有爱就没有教育的话,那么离开了尊重同样也谈不上教育。 因为每一位孩子都渴望得到他人的尊重,尤其是教师的尊重。可是在现实生活中,不时会有

    小学作文
  • 爱心责任100字作文题库

    1.有关爱心,坚持,责任的作文题库各三个 一则150字左右 (要事例) “胜不骄,败不馁”这句话我常听外婆说起。 这句名言的意思是说胜利了抄不骄傲,失败了不气馁。我真正体会到它

    小学作文
  • 爱心责任心的作文题库

    1.有关爱心,坚持,责任的作文题库各三个 一则150字左右 (要事例) “胜不骄,败不馁”这句话我常听外婆说起。 这句名言的意思是说胜利了抄不骄傲,失败了不气馁。我真正体会到它

    小学作文
  • 爱心责任作文题库

    1.有关爱心,坚持,责任的作文题库各三个 一则150字左右 (要事例) “胜不骄,败不馁”这句话我常听外婆说起。 这句名言的意思是说胜利了抄不骄傲,失败了不气馁。我真正体会到它

    小学作文