您好我正在尝试使用ISampleGrabberCB::SampleCB
在我的表单中显示图像之前从实时预览中获取图像。
我希望能够将每个新帧转换为要处理的位图(例如扫描+添加水印类型图像)。
目前我正尝试以下列方式进行此操作:
int ISampleGrabberCB.SampleCB(double SampleTime, IMediaSample sample)
{
int hr;
IntPtr buffer;
AMMediaType mediaType;
VideoInfoHeader videoInfo;
int frameWidth;
int frameHeight;
int stride;
int bufferLength;
hr = sample.GetPointer(out buffer);
DsError.ThrowExceptionForHR(hr);
hr = sample.GetMediaType(out mediaType);
DsError.ThrowExceptionForHR(hr);
bufferLength = sample.GetSize();
try
{
videoInfo = new VideoInfoHeader();
Marshal.PtrToStructure(mediaType.formatPtr, videoInfo);
frameWidth = videoInfo.BmiHeader.Width;
frameHeight = videoInfo.BmiHeader.Height;
stride = frameWidth * (videoInfo.BmiHeader.BitCount / 8);
CopyMemory(imageBuffer, buffer, bufferLength);
Bitmap bitmapOfFrame = new Bitmap(frameWidth, frameHeight, stride, PixelFormat.Format24bppRgb, buffer);
bitmapOfFrame.Save("C:\\Users\\...\\...\\...\\....jpg");
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
return 0;
}
理论上,这应该得到媒体类型,然后用于获取图像的宽度,高度和步幅,然后用于创建位图。然后从IMediaSample的指针获取缓冲区。
然而,这似乎不起作用(我假设这是因为位图永远不会保存)。那么我如何将每个新帧转换为位图呢?
设置引脚的附加功能:
public void setupGraphForSampleGrabber(DsDevice webcamDevice, Control displayBox)
{
int hr;
ISampleGrabber sampleGrabber = null;
IPin capturePin = null;
IPin samplePin = null;
IPin renderPin = null;
IBaseFilter captureFilter;
filtergraph = new FilterGraph() as IFilterGraph2;
try
{
//Add the webcam
hr = filtergraph.AddSourceFilterForMoniker(webcamDevice.Mon, null, webcamDevice.Name, out captureFilter);
DsError.ThrowExceptionForHR(hr);
//Get the still pin
stillPin = DsFindPin.ByCategory(captureFilter, PinCategory.Still, 0);
if (stillPin == null)
{
stillPin = DsFindPin.ByCategory(captureFilter, PinCategory.Preview, 0);
}
if (stillPin == null)
{
IPin outputPin = null;
IPin inputPin = null;
//As there is still no still pin set this to null
videoControl = null;
// Add a splitter
IBaseFilter smartTee = (IBaseFilter)new SmartTee();
try
{
hr = filtergraph.AddFilter(smartTee, "SmartTee");
DsError.ThrowExceptionForHR(hr);
//Obtain the capture pin from the webcam and the input pin from the spliter and assign them to the outputPin and inputPin respectivly
outputPin = DsFindPin.ByCategory(captureFilter, PinCategory.Capture, 0);
inputPin = DsFindPin.ByDirection(smartTee, PinDirection.Input, 0);
//Then connect both of them to the graph
hr = filtergraph.Connect(outputPin, inputPin);
DsError.ThrowExceptionForHR(hr);
//Set the capture and still pins so we can use them with the rest of the program
stillPin = DsFindPin.ByName(smartTee, "Preview");
capturePin = DsFindPin.ByName(smartTee, "Capture");
setParameters(outputPin);
}
//Release all the com objects to avoid problems as the program is to be used for extended periods
finally
{
if (outputPin != null)
{
Marshal.ReleaseComObject(outputPin);
}
if (outputPin != inputPin)
{
Marshal.ReleaseComObject(inputPin);
}
if (outputPin != smartTee)
{
Marshal.ReleaseComObject(smartTee);
}
}
}
else
{
videoControl = captureFilter as IAMVideoControl;
capturePin = DsFindPin.ByCategory(captureFilter, PinCategory.Capture, 0);
setParameters(stillPin);
}
//Get interface
sampleGrabber = new SampleGrabber() as ISampleGrabber;
//Configure the samplegrabber
IBaseFilter baseFilter = sampleGrabber as IBaseFilter;
configureSampleGrabber(sampleGrabber);
samplePin = DsFindPin.ByDirection(baseFilter, PinDirection.Input, 0);
//Video Renderer
IBaseFilter render = new VideoRendererDefault() as IBaseFilter;
hr = filtergraph.AddFilter(render, "Renderer");
DsError.ThrowExceptionForHR(hr);
renderPin = DsFindPin.ByDirection(render, PinDirection.Input, 0);
//Add samplegrabber to graph
hr = filtergraph.AddFilter(baseFilter, "SampleGrabber");
DsError.ThrowExceptionForHR(hr);
if (videoControl == null)
{
//Connect still pin to samplegrabber
hr = filtergraph.Connect(stillPin, samplePin);
DsError.ThrowExceptionForHR(hr);
//Connect capture pin to render
hr = filtergraph.Connect(capturePin, renderPin);
DsError.ThrowExceptionForHR(hr);
}
else
{
//Connect capture pin to render
hr = filtergraph.Connect(capturePin, renderPin);
DsError.ThrowExceptionForHR(hr);
//Connect still pin to samplegrabber
hr = filtergraph.Connect(stillPin, samplePin);
DsError.ThrowExceptionForHR(hr);
}
//Get video properties
saveVideoInfo(sampleGrabber);
ConfigureVideoLocation(displayBox);
//Run Graph
IMediaControl mediaControl = filtergraph as IMediaControl;
hr = mediaControl.Run();
DsError.ThrowExceptionForHR(hr);
}
finally
{
if (sampleGrabber != null)
{
Marshal.ReleaseComObject(sampleGrabber);
sampleGrabber = null;
}
if (capturePin != null)
{
Marshal.ReleaseComObject(capturePin);
capturePin = null;
}
if (renderPin != null)
{
Marshal.ReleaseComObject(renderPin);
renderPin = null;
}
if (samplePin != null)
{
Marshal.ReleaseComObject(samplePin);
samplePin = null;
}
}
}
此外,我像这样配置我的samplegrabber:
public void configureSampleGrabber(ISampleGrabber sampleGrabber)
{
int hr;
AMMediaType mediaType = new AMMediaType();
//Set the values for media type and format
mediaType.majorType = MediaType.Video;
mediaType.subType = MediaSubType.RGB24;
mediaType.formatType = FormatType.VideoInfo;
hr = sampleGrabber.SetMediaType(mediaType);
DsError.ThrowExceptionForHR(hr);
DsUtils.FreeAMMediaType(mediaType);
mediaType = null;
//Configure
hr = sampleGrabber.SetCallback(this, 0);
DsError.ThrowExceptionForHR(hr);
}
答案 0 :(得分:1)
Sample Grabber不会为每个抓取的样本提供正确的MediaType,因此请不要在此处从样本中请求它。而是获取抓取器的输入引脚或相机的输出引脚,并调用IPin.ConnectionMediaType()以了解此流的正确媒体类型。
答案 1 :(得分:1)
我认为您的图表设置不正确,样本永远不会通过样本采集器。乍一看,我认为样本采集器从未被渲染过。将样本采集器输出引脚连接到空渲染器,事情应该可行。