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;
}
}
}
さらに、サンプルグラバーを次のように構成します。
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);
}