DirectShowLib-使用覆盖文本保存视频
本文关键字:保存 视频 文本 覆盖 DirectShowLib- | 更新日期: 2023-09-27 18:22:41
如何在avi文件中保存处理后获得的图形。设法获得了带有覆盖文本的图片。我知道有一个方法SetOutputFileName(),但如何在这里使用它?
private Bitmap bitmapOverlay;
private IFilterGraph2 m_FilterGraph;
void GO()
{
SetupGraph("C:''Export.avi");
SetupBitmap();
IMediaControl mediaCtrl = m_FilterGraph as IMediaControl;
int hr = mediaCtrl.Run();
DsError.ThrowExceptionForHR( hr );
}
private void SetupGraph(string FileName)
{
int hr;
IBaseFilter ibfRenderer = null;
ISampleGrabber sampGrabber = null;
IBaseFilter capFilter = null;
IPin iPinInFilter = null;
IPin iPinOutFilter = null;
IPin iPinInDest = null;
// Get the graphbuilder object
m_FilterGraph = new FilterGraph() as IFilterGraph2;
// Get the SampleGrabber interface
sampGrabber = new SampleGrabber() as ISampleGrabber;
// Add the video source
hr = m_FilterGraph.AddSourceFilter(FileName, "Ds.NET FileFilter", out capFilter);
DsError.ThrowExceptionForHR( hr );
// Hopefully this will be the video pin
IPin iPinOutSource = DsFindPin.ByDirection(capFilter, PinDirection.Output, 0);
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 = m_FilterGraph.AddFilter( baseGrabFlt, "Ds.NET Grabber" );
DsError.ThrowExceptionForHR( hr );
hr = m_FilterGraph.Connect(iPinOutSource, iPinInFilter);
DsError.ThrowExceptionForHR( hr );
// Get the default video renderer
ibfRenderer = (IBaseFilter) new VideoRendererDefault();
// Add it to the graph
hr = m_FilterGraph.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 = m_FilterGraph.Connect(iPinOutFilter, iPinInDest);
DsError.ThrowExceptionForHR( hr );
SaveSizeInfo(sampGrabber);
}
处理视频-在每帧文本上绘制。cc.Save("C:''''Test''''img"+m_Count+".jpg")-因此可以使用叠加文本进行拍摄。如何将处理后的视频文件保存在avi文件中?
int ISampleGrabberCB.BufferCB( double SampleTime, IntPtr pBuffer, int BufferLen )
{
Graphics g;
String s;
float sLeft;
float sTop;
SizeF d;
g = Graphics.FromImage(bitmapOverlay);
g.Clear(System.Drawing.Color.Transparent);
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
// Prepare to put the specified string on the image
g.DrawRectangle(System.Drawing.Pens.Blue, 0, 0, m_videoWidth - 1, m_videoHeight - 1);
g.DrawRectangle(System.Drawing.Pens.Blue, 1, 1, m_videoWidth - 3, m_videoHeight - 3);
d = g.MeasureString(m_String, fontOverlay);
sLeft = (m_videoWidth - d.Width) / 2;
sTop = (m_videoHeight - d.Height ) / 2;
g.DrawString(m_String, fontOverlay, System.Drawing.Brushes.Red,
sLeft, sTop, System.Drawing.StringFormat.GenericTypographic);
g.Dispose();
Bitmap v;
v = new Bitmap(m_videoWidth, m_videoHeight, m_stride,
PixelFormat.Format32bppArgb, pBuffer);
v.RotateFlip(RotateFlipType.Rotate180FlipX);
g = Graphics.FromImage(v);
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
// draw the overlay bitmap over the video's bitmap
g.DrawImage(bitmapOverlay, 0, 0, bitmapOverlay.Width, bitmapOverlay.Height);
Bitmap cc = new Bitmap(v);
cc.Save("C:''Test''img" + m_Count + ".jpg");
g.Dispose();
v.Dispose();
m_Count++;
return 0;
}
通常它应该看起来像:
[File reader] -> [AVI Demuxer] -> (video pin) -> [Video decoder] -> [Sample grabber] -> [Video encoder] -> [AVI Muxer] -> [File writer]
|-> (audio pin) ->|
AVI文件是一个媒体容器,因此您需要将其多路分解以分离流,并在最后将(修改的)流多路复用回AVI容器。当你得到视频流时,它(通常)包含编码的视频。所以要修改它,你需要对它进行解码,然后在修改后将其编码回相同的格式。您不需要对音频流做任何操作,只需将其从解复用器直接引导到复用器即可。[文件写入器]过滤器允许您指定输出文件名。
我不知道什么是"Ds.NET FileFilter",也不知道它如何对视频进行解复用和解码,但似乎可以,因为你可以看到修改后的图片。AVI Muxer是一个标准的MS过滤器,我只是不记得它的名字。您需要选择一个视频编码器。我建议首先在GraphEditor中构建一个简单的图,它不修改图片,只需读取->demux->decod->encode->mux->write即可验证您是否拥有所需的一切,并且它们运行良好。只需尝试播放生成的AVI文件。