DirectShowLib - 使用叠加文本保存视频

时间:2014-09-18 09:36:43

标签: c# directshow

如何保存在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;
        }

1 个答案:

答案 0 :(得分:0)

通常情况应该如下:

[File reader] -> [AVI Demuxer] -> (video pin) -> [Video decoder] -> [Sample grabber] -> [Video encoder] -> [AVI Muxer] -> [File writer]
                      |->                                             (audio pin)                             ->|

AVI文件是一个媒体容器,因此您需要将其解复用为单独的流,最后将多路复用(已修改)的流解复用回AVI容器。获得视频流时(通常)包含编码视频。因此,要修改它,您需要对其进行解码,然后在修改后将其编码回相同的格式。你不需要对音频流做任何事情,只需将它从解复用器直接转到muxer。 [文件编写器]过滤器允许您指定输出文件名。

我不知道" Ds.NET FileFilter"以及它如何解复,然后解码视频,但似乎可以,因为你可以看到你修改过的图片。 AVI Muxer是标准的MS滤波器,我只是不记得它的名字。您需要选择视频编码器。我建议先在GraphEditor中构建一个简单的图形,它不会修改图片,只需读取> demux-> decod-> encode-> mux-> write来验证你有你需要的一切,他们工作正常。只是尝试播放生成的AVI文件。