i developed in windows application in C#.NET4.0 with Directshow Lib,for recording video using webcam.during video recording i put an overlay text by grabing frame in BufferCB and put my overlay bitmap on frame.
This application with overlay is working fine. but after some days overlay text is not coming so i tried to identify the problem then i realise that BufferCB not getting call. SetCallback() function is returning 0 means not error in it.Then why BufferCB is not getting Call?
Edit
Button click code for starting recording,config samplegrabber get video size info etc.
private void button1_Click(object sender, EventArgs e)
{
jpg.RotateFlip(RotateFlipType.RotateNoneFlipY);
//jpgdata = jpg.LockBits(new Rectangle(0, 0, jpg.Width, jpg.Height), ImageLockMode.ReadWrite, jpg.PixelFormat);
AvailableAudioInputDevices = new List<DsDevice>();
DsDevice[] audioInputDevices = DsDevice.GetDevicesOfCat(FilterCategory.AudioInputDevice);
AvailableAudioInputDevices.AddRange(audioInputDevices);
AvailableVideoInputDevices = new List<DsDevice>();
DsDevice[] videoInputDevices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);
AvailableVideoInputDevices.AddRange(videoInputDevices);
Graph = (IFilterGraph2)new FilterGraph();
captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();
hr = captureGraph.SetFiltergraph(Graph);
DsError.ThrowExceptionForHR(hr);
hr = captureGraph.SetOutputFileName(MediaSubType.Asf, "qwe.wmv", out pMux, out pFilter);
DsError.ThrowExceptionForHR(hr);
hr = Graph.AddSourceFilterForMoniker(AvailableAudioInputDevices.First().Mon, null, AvailableAudioInputDevices.First().Name, out capFilter);
DsError.ThrowExceptionForHR(hr);
//ConfigProfileFromFile(pMux, "b.prx");
hr = captureGraph.RenderStream(PinCategory.Capture, MediaType.Audio, capFilter, null, pMux);
DsError.ThrowExceptionForHR(hr);
hr = Graph.AddSourceFilterForMoniker(AvailableVideoInputDevices.First().Mon, null, AvailableVideoInputDevices.First().Name, out capFilter);
DsError.ThrowExceptionForHR(hr);
#region code for init. preview window and sample grabber
mediaControl = (IMediaControl)Graph;
mediaEventEx = (IMediaEventEx)Graph;
mediaEventEx.SetNotifyWindow(pic.Handle, WM_GRAPHNOTIFY, IntPtr.Zero);
IBaseFilter vmr9preview = null;
vmr9preview = (IBaseFilter)new VideoMixingRenderer9();
hr = Graph.AddFilter(vmr9preview, "VMR9");
DsError.ThrowExceptionForHR(hr);
IVMRFilterConfig9 vmr9Config = (IVMRFilterConfig9)vmr9preview;
vmr9Config.SetRenderingMode(VMR9Mode.Windowless);
vmr9Config.SetNumberOfStreams(1);
vmr9Control = (IVMRWindowlessControl9)vmr9preview;
vmr9Control.SetVideoClippingWindow(pic.Handle);
vmr9Control.SetAspectRatioMode(VMR9AspectRatioMode.None);
var srcRect = new DsRect();
var dstRect = new DsRect(pic.ClientRectangle);
int arWidth, arHeight;
vmr9Control.GetNativeVideoSize(out srcRect.right, out srcRect.bottom, out arWidth, out arHeight);
vmr9Control.SetVideoPosition(srcRect, dstRect);
sampGrabber = new SampleGrabber() as ISampleGrabber;
#endregion
#region code for get video info and config sample grabber
IPin iPinOutSource = DsFindPin.ByDirection(capFilter, PinDirection.Output, 0);
// Configure the sample grabber
IBaseFilter baseGrabFlt = sampGrabber as IBaseFilter;
ConfigureSampleGrabber(sampGrabber);
iPinInFilter = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Input, 0);
iPinOutFilter = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Output, 0);
// Add the frame grabber to the graph
hr = Graph.AddFilter(baseGrabFlt, "Ds.NET Grabber");
DsError.ThrowExceptionForHR(hr);
hr = Graph.Connect(iPinOutSource, iPinInFilter);
DsError.ThrowExceptionForHR(hr);
// Get the default video renderer
ibfRenderer = (IBaseFilter)new VideoRendererDefault();
// Add it to the graph
hr = Graph.AddFilter(ibfRenderer, "Ds.NET VideoRendererDefault");
DsError.ThrowExceptionForHR(hr);
iPinInDest = DsFindPin.ByDirection(ibfRenderer, PinDirection.Input, 0);
// Connect the graph. Many other filters automatically get added here
hr = Graph.Connect(iPinOutFilter, iPinInDest);
DsError.ThrowExceptionForHR(hr);
SaveSizeInfo(sampGrabber);
hr = Graph.RemoveFilter(baseGrabFlt);
DsError.ThrowExceptionForHR(hr);
hr = Graph.Disconnect(iPinOutSource);
DsError.ThrowExceptionForHR(hr);
hr = Graph.RemoveFilter(ibfRenderer);
DsError.ThrowExceptionForHR(hr);
hr = Graph.Disconnect(iPinInDest);
DsError.ThrowExceptionForHR(hr);
#endregion
ConfigProfileFromFile(pMux, "b.prx");
hr = Graph.AddFilter(capFilter, "VMR9");
DsError.ThrowExceptionForHR(hr);
hr = Graph.AddFilter(baseGrabFlt, "Ds.NET Grabber");
DsError.ThrowExceptionForHR(hr);
hr = captureGraph.RenderStream(PinCategory.Preview, MediaType.Video, capFilter, null, vmr9preview);
DsError.ThrowExceptionForHR(hr);
hr = captureGraph.RenderStream(PinCategory.Capture, MediaType.Video, capFilter, null, pMux);
DsError.ThrowExceptionForHR(hr);
m_mediaCtrl = Graph as IMediaControl;
SetupBitmap();
m_mediaCtrl.Run();
//timer1.Start();
}
Config Sample Grabber method
private void ConfigureSampleGrabber(ISampleGrabber sampGrabber)
{
int hr;
AMMediaType media = new AMMediaType();
// Set the media type to Video/RBG24
media.majorType = MediaType.Video;
media.subType = MediaSubType.RGB24;
media.formatType = FormatType.VideoInfo;
hr = sampGrabber.SetMediaType(media);
DsError.ThrowExceptionForHR(hr);
DsUtils.FreeAMMediaType(media);
media = null;
// Configure the samplegrabber
hr = sampGrabber.SetCallback(this, 1);
DsError.ThrowExceptionForHR(hr);
}
BufferCB and SampleCB
int ISampleGrabberCB.SampleCB(double SampleTime, IMediaSample pSample)
{
Marshal.ReleaseComObject(pSample);
return 0;
}
[DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")]
static extern void CopyMemory(IntPtr Destination, IntPtr Source, int Length);
/// <summary> buffer callback, COULD BE FROM FOREIGN THREAD. </summary>
int ISampleGrabberCB.BufferCB(double SampleTime, IntPtr pBuffer, int BufferLen)
{
CopyMemory(pBuffer, bmpData.Scan0, bmpData.Stride*20);
return 0;
}