嗨,我試圖使用ISampleGrabberCB::SampleCB
從我的窗體內顯示之前,它們的實時預覽中獲取圖像。使用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);
}
您繼續保存到相同的文件,這可能會導致併發寫入。 – Matthias
這仍然不會留下文件的名稱?目前它不保存任何內容。除此之外,這是轉換圖像的正確方式嗎? – legohead