本文转自:http://blog.chinaunix.net/u2/63021/showart_492136.html
原文如下:
在播放媒体文件的过程中,有一个很有用的功能,就是在当前播放的位置抓取图,实现这种图片抓取功能的方法很多,我们这里只介绍常用的两种。
第1种方法最简单,它使用1BasicVideo::GetCurrentImage接口方法,代码如下。
heel SnapshotBitmap(IBasicVideo*pBa8icVideo, const char*OutFile)
if (pBasicVldeo)
{
long bitmapSize=0;
//首先获得图像大小
if(SUCCEEDED(pEasicVidee->GetcurrentImage(&bitmapSize,0)))
{
bool pass=false;
//分配图像帧内存
unsigned char*buffer=new unsigned char[bitmapSize];
//获取图像帧数据
if(SUCCEEDED(pBasicVideo->GetCurrentImage(&bitmapSize,(long*)buffer)))
{
BITMAPFILEHEADER hdr;
LPBITMAPINFOHEADER ipbi;
ipbi=(LPBITMAPINFOHEADER)buffer;
int nColors=1<<ipbi->biBitCount;
if(nColors>256)
//always is”BM”
hdr.bfType =((WORD)(‘M’<<8)|’B’);
hdr.bfSize =bitmapSize+sizeof(hdr);
hdr.bfReservedl =0;
hdr.bfReserved2 =0;
hdr.bfOffBits =(DWORD)
(sizeof(BITMAPFILEHEADER)+lpbi->biSize+nColors*sizeof(RGBQUAD));
CFile bitmapFile(outFile,CFile::modeReadWrite |
CFile::modeCreate | CFile::typeBinary);
//写入位图文件头
bitmapFile.Write{&hdr,sizeof【BITMApFILEHEADER));
//写入图像帧数据(包括BITMAPINFOHEADER信息)
bitmapFile.Write(buffer,bitmapSize);
bitmapFile.Close();
pas8=true;
}
delete[]burfer;
return Pass;
}
return false ;
值得注意的是,IBasieVideo接口应该从FilterGraphManager上获得,但真正实现在
RendererFilter上。如果我们使用的是传统的VideoRenderer,那么使用GetCurrentlmage 抓图将是不可靠的。因为如果VideoRenderer使用了DirectDraw加速,这个函数调用会失 败;而且调用这个函数,VideoRenderer必须处于暂停状态。但如果我们使用的是VMR, 则没有上述这些限制。
第2种方法比较复杂.它使用SampleGrabberFilter。它其实是一个Trans-In-Place
Filter,在SDK安装目录下的Samples\C++\DirectShow’Filters\Grabber提供了源代码。实际 上,SampleGrabber可以抓取任何类型的Sample。但在这里,我们只介绍使用它抓取视频 帧的方法。步骤如下:
(1)创建SampleGrabber,并将之加入到FilterGraph中。
//CreatetheSampleGrabber
IBaseFilter*pGrabberF=NULL;
hr=CoCreateInstanee(CLSID_SampleGrabber,NULL,CLSCTX_INPROC_SERVER,
IIDIBaseFilter,(void**)&pGrabberF);
if(FAILED(hr))
{
//Returnanerror
}
hr=pGraph->AddFilter(pGrabberF,L"SampleGrabber");
if(FAILED(hr)
{
//Returnanerror
}
ISampleGrabber*pGrabber=NULL;
pGrabberF->QueryInterface(IID_ISampleGrabber,(void**)&pGrabber);
(2)给SampleGrabber设置Pin上连接用的媒体类型。
如果我们想抓取24位的RGB图片,如下设置媒体类型:
AM_MEDIA_TYPEmt;
ZeroMemorY(&mt,sizeof(AM_MEDIA_TYPE));
mt.malOrtype=MEDIATYPEVideo;
mt.subtype=ME:DIASUBTYPERGB24;
hr=pGrabber->SetMediaType(&mt);
也可以根据当前显示器的配置来设置SampleGrabber接受的RGB类型,代码如下:
//Findthecurrentbitdepth
HDChdc=GetDC(NULL);
intiBitDepth=GetDeviceCaps(hdc,BITSPIXEL);
ReleaseDC(NULL,hdc);
//Setthemediatype
mt.maJortype=MEDIATYPEVideo;
switch(iBitDepth)
{
Case8:
mt.subtype=MEDIASUBTYPERGB8;
break;
case16:
mt.subtype=MEDIASUBTYPE_RGB555;
break;
case24:
mt.subtype=MEDIASUBTYPE_RGB24;
break;
case32:
mt.subtype=MEDIASUBTYPE_RGB32;
break;
default:
returnE_FAIL;
}
hr=pGrabber->SetMediaType(&mt);
(3)完成FilterGraph的构建。
因为SampleGrabber上已经设置了一个媒体类型,则其他Filter必须以这种媒
才能与SampleGrabber相连。我们可以使用DimctShow的“智能连接”机制,来
个FitlerGraph的创建过程,代码如下。
IBaseFiiter*pSrc;
hr=pGraph->AddSourceFilter(wszFileName,L"Source",&pSrc};
if(FAILED(hr))
{
//Returnanerrorcode
}
hr=ConnectFiiters(pGraph,pSrc,pGrabberF);
其中,ConnectFilters是我们在5.3节中介绍的自定义函数。
如果我们只是想抓图(不需要对视频预览),则SampleGrabber后面可以连接一个Null RendererFilter(它的CLSID为CLSIDNullRenderer)。如果要FilterGraph中的数据流以最快的速度传送,则FilterGraph不要使用参考时钟(调用IMediaFitter::SetSyncSource,参数为NULL)。
(4)运行FilterGraph。
SampleGrabber可以有如下两种工作模式:
缓冲模式将输入的Sample进行缓存后,再往下传送。
回调模式当有输入的Sample时,调用应用程序设置进来的回调函数。
因为回调模式会影响整个FilterGraph的效率,并且容易引起死锁,所以我们推荐使用缓冲模式。另外,我们可以设置ISampleGrabber::SetOneShot,使得SampleGrabber获取一个Sample以后,就让FilterGraph停止,代码如下:
//Setone-shotmodeandbuffering.
hr=pGrabber->SetOneShot(TRUE);
hr=pGrabber->SetBufferSamples(TRUE);
pControl->Run();//Runthegraph.
pEvent->WaitForCompletion(INFINITE,&evCode),//Waittillit’sdone.
(5)获取抓到的Sample数据。
缓冲模式下,我们可以调用ISampleGrabber::GetCurrentBuffer来获取Sample数据,代码如下:
//Findtherequiredbuffersize
longcbBuffer=0;
hr=pGrabber->GetCurrentBuffer(&cbBuffer,NULL);
char*pBuffer=newchar[cbBuffer];
if(!pBuffer)
//Outofmemory.Returnanerrorcode
}
hr=pGrabber->GetCurrentBuffer(&cbBuffer,(long*)pBuffer);
我们也可以将获取的数据使用GDI函数显示出来,代码如下:
AM_MEDIA_TYPEmt;
hr=pGrabber->GetConnectedMediaType(&rot);
if(FAILED(hr))
{
//Returnerr05code
}
//Examinetheformatblock
VIDEOINFOHEADER*pVih;
if((mt.formattype==FORMAT_VideoInfo)&&
(mt.cbFormat>=sizeof(VIDEOINFOHEADER))&&
(mt.pbFormat!=NULL))
pVih={vIDEOINFOHEADER*)mt·pbFormat;
}
else
{
//Wrongformat.Freetheformatblockandreturnanerror‘
FreeMedlaType(mt);
returnVFW_E_INVALIDMEDIATYPE;
//youcanusethemediatypetoaccesstheBITMAPINFOHEAFREinformation,
//Forexample,thefollowingcodedrawsthebitmapusingGDI
SetDIBitsToDevice(
hdc,0,0,
pVih->bmiHeader.biWidth,
pVih->bmiHeader.biHeight,
O,O,
0,
pVih->bmiHeader.biHeight,
pBuffer,
(BITMAPINFO*)&pVih->bmiHeader,
DIBRGBCOLORS
),
//Freetheformatblockwhenyouaredone:
FreeMediaType(mt);
分享到:
相关推荐
### DirectShow抓取图片的几种方法 #### 一、引言 DirectShow是Microsoft Windows操作系统中的一个组件,主要用于处理多媒体数据流,如音频和视频。它提供了强大的功能来捕获、压缩、播放以及编辑多媒体数据。本文...
实现摄像头抓取图片的基本步骤如下: 1. **初始化DirectShow**: 创建并初始化一个CoInitializeEx,以启动COM线程模型。 2. **创建过滤器图**: 使用IAMFilterGraph接口的AddSourceFilter方法添加视频捕获设备作为源...
在C# WinForm环境中,我们可以利用DirectShow库来实现视频采集和图片抓取功能。这个实例项目"DxSnap"提供了一个完整的解决方案,帮助开发者了解如何在Windows桌面应用程序中集成视频捕获和图像保存的能力。 首先,...
在Directshow中,图像抓取是指从视频流中捕获单帧图片并保存为图像文件的过程,这对于视频分析、监控系统或者视频处理应用是非常有用的。 首先,理解Directshow的基本架构至关重要。它由两部分组成:过滤器(Filter...
在这个主题中,我们将深入探讨如何利用DirectShow来实现视频采集与视频数据的抓取。 首先,理解DirectShow的基本结构至关重要。DirectShow由许多组件(filters)组成,每个组件负责特定的媒体处理任务,如捕获设备...
SampleGrabber是Directshow中一个非常重要的过滤器,它的主要功能是在视频流通过它的时候抓取一帧数据。这个过程通常用于捕获视频帧进行处理,例如分析、截图或者转码。下面我们将详细介绍如何实现这个功能。 首先...
### 基于Directshow的视频抓图在车牌识别系统中的应用 #### 一、Directshow原理 ##### 1.1 Directshow系统概述 Directshow是Microsoft提供的多媒体框架,用于在Windows平台上处理音频和视频流。它采用了一种称为...
这个压缩包“Get_Movie_Frame.zip”似乎包含了一个关于如何使用DirectShow从AVI视频文件中抓取帧的示例项目或教程,特别适用于Visual C++开发者。在本文中,我们将深入探讨DirectShow、AVI格式以及如何利用...
DirectShow是微软开发的一种多媒体框架,用于处理视频和音频流。在本文中,我们将深入探讨如何使用DirectShow在Visual Studio 2013环境下实现视频的实时显示,并进行抓图功能,同时允许用户自定义图像参数和视频格式...
用directshow写视频获取图片抓拍和显示程序,有分辨率设置,文字信息加入视频和抓拍的图片,设置文字信息的颜色和大小,这里给出单行,自己可以改成多行或者鼠标定点加入文字信息,其中也用到GDI+对多种图片格式的显示...
4. **跨滤镜**:如Sample Grabber,用于在数据流中抓取单个图像帧,这对于需要保存或处理单个图片的应用非常有用。 实现“自动检测电脑挂载的摄像头”功能,需要调用DirectShow的枚举设备接口,例如`...
在描述中提到的代码封装了DirectShow播放视频并进行图片抓取的功能。这意味着代码中可能包含了初始化DirectShow过滤器图形、创建播放器以及设置回调函数来捕获帧的关键步骤。通常,这个过程会涉及以下几个关键知识点...
总结起来,从摄像头抓取图片涉及的关键技术有C++编程、OpenCV或DirectShow库的使用、DIB位图的处理以及Win32 API的调用。对于想要深入学习这一领域的开发者,了解这些知识点并掌握其应用是至关重要的。通过编写和...
4. 实现拍照功能:当用户点击Button时,调用VideoCaptureDevice的Start方法开始捕获视频流,然后使用Snapshot方法抓取一帧图片,并保存为本地文件。以下是一个简单的事件处理函数: ```csharp private void ...
在这个场景中,我们将探讨如何利用DirectShow从视频流中连续抓取图像帧,并将它们保存为BMP格式的图片。 首先,我们要了解DirectShow的工作原理。DirectShow基于COM(Component Object Model)组件模型,它包含了一...
### 利用DirectShow技术实时捕捉视频流中的图像帧 #### 背景与意义 随着信息技术的发展,视频已经成为信息传播的重要载体之一。对于视频流的实时分析与处理成为研究的热点,特别是在视频分析领域中,如镜头分割、...
在DirectShow中,实现截图通常涉及到创建一个图像抓取滤镜,该滤镜可以捕获VMR9输出的帧数据并将其保存为图片文件。开发者只需稍微调整代码,就能实现在播放过程中动态捕获视频帧,生成静态图像,这对于视频分析、...
7. **图像抓拍**:在视频通信中,有时需要抓取远端的视频帧作为静态图片。DirectShow提供了抓图功能,通过调用特定接口,可以在任何时候捕获当前的视频帧。 8. **音视频同步**:为了提供良好的用户体验,视频和音频...
这个类可能包含了设置截图参数、启动截图、保存图片等功能。对于初学者来说,通过研究这个项目,不仅可以理解DirectShow的基本工作原理,还能学习到如何在C++中处理多媒体数据。 文件名"VMR9Teset"很可能是一个测试...
本教程将深入讲解如何使用DirectShow来实现USB摄像头的图像抓取。 首先,了解DirectShow的基本概念。DirectShow是基于COM(Component Object Model)组件模型的,它由一系列滤镜(Filter)组成,这些滤镜负责不同的...