Использование 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);
}
2 ответа
Я думаю, что ваш график не настроен должным образом, и сэмплы никогда не проходят через сэмплер. На первый взгляд, я думаю, что образец граббер никогда не рендерится. Подключите выходной контактный образец граббера к нулевому рендереру, и все должно работать.
Образец Grabber не даст правильный MediaType для каждого взятого образца, поэтому не стесняйтесь запрашивать его у образца здесь. Вместо этого получите входной контакт захвата или выходной вывод камеры и вызовите IPin.ConnectionMediaType(), чтобы узнать правильный тип мультимедиа этого потока.