What can be do with DirectShow and C #
We would like-to-start by asking-there is no managed wrapper for DirectShow. The DirectShow SDK documentation contains a FAQ with this answer: "There is no current plans to implement a" Managed DirectShow "platform. You can use COM Interop to create DirectShow client applications in managed code, but creating filters that depend on the Common Language Runtime (CLR) is not recommended for performance reasons. "
Should we buy this answer like it would is "words from the Gospels"? I like the motto ' trust but verify '. One thing is sure, when we create a Graphbuilder object and run a stream through it, we end up creating a lot of threads a nd mixing native COM and managed code might not be a ideal mix for people who don ' t want to work more than what they has To get the job done.
So, we ' re not going to write filters in C #. But DirectShow client applications is an interesting possibility. The SDK already contains samples written in VB and there are no reason why we couldn ' t write similar applications in C #. So how does we go about it. There is a few samples at www.codeproject.com this use C # and DirectShow.
The easiest-to-write a DirectShow client application is simply to wrap the library "Quartz.dll" (with the Too L TlbImp from the. Net SDK or by adding a reference to in a VS project). That's the easiest and the methods we ' d like might is exposed this. So we have a couple of alternatives. There a library called "FSFWrap.dll" that adds some of the missing APIs or we can look at Dshownet (available on The CodeProject Web site).
The above remark means that DirectShow does not support managed code, so we do not use managed code to implement filter, but we can write DirectShow client program with the corresponding DLL. First look at a C + + version, the first programming environment to be configured, the previous blog has been introduced.
Playing a file using DirectShow in C + + is illustrated in the SDK documentation as:
#include <dshow.h>void main (void) {Igraphbuilder *pgraph = NULL; IMediaControl *pcontrol = NULL; Imediaevent *pevent = NULL; Initialize the COM library. HRESULT hr = CoInitialize (NULL); if (FAILED (HR)) {printf ("Error-could not initialize COM library"); Return }//Create the Filter Graph manager and query for interfaces. hr = CoCreateInstance (Clsid_filtergraph, NULL, Clsctx_inproc_server, Iid_igraphbuilder, (void * *) & Amp;pgraph); if (FAILED (HR)) {printf ("Error-could not create the Filter Graph Manager."); Return } hr = Pgraph->queryinterface (Iid_imediacontrol, (void * *) &pcontrol); hr = Pgraph->queryinterface (iid_imediaevent, (void * *) &pevent); Build the graph. Important:change this string to a file on your system. hr = Pgraph->renderfile (L "C:\\example.avi", NULL); if (SUCCEEDED (HR)) {//Run the graph. hr = Pcontrol->run (); if (SUCCEEDED (HR)) {//Wait for completion. Long Evcode; Pevent->waitforcompletion (INFINITE, &evcode); Note:do not use INFINITE in a real application, because it//can block indefinitely. }} pcontrol->release (); Pevent->release (); Pgraph->release (); CoUninitialize ();}
Here's the equivalent code in C # using Interop and Quartz.dll:
Using system;using quartztypelib;class playfile {public static void Main (string [] args) {Filgraphmanagerclass Graphclas s = null; Try args[0] ); Graphclass.run (); int evcode;graphclass.waitforcompletion (-1, out evcode); } catch (Exception) {} finally { graphclass = null;}} }
Using the previously mentioned CSC compiler, you can play the video file represented by the args[0] parameter. Http://www.cnblogs.com/stemon/p/4562581.html
Compile the command:
Csc/debug/t:exe/r:interop.quartztypelib.dll Test.cs
This will generate the corresponding EXE file, and then run the Test.exe under DOS and then follow the path of the video file as parameters, OK.
There is also a window version of this program where this code is called from a button on a form (the code can be found in The following). We passed the file name to play on the command line instead of hardcoding the name in the source as the the example from the S Dk. Also the first argument to WaitForCompletion is-1 because INFINITE are defined as 0XFFFFFFF.
The interop version uses the Filgraphmanagerclass to does all of the work.
. Net Master (at CodeProject) decided, the COM interfaces for DirectShow is sufficiantly simple-to-write wrappers for them using the IDL provided with the SDK. The advantage of this approach is so you has more control over which members of the interfaces so you can access. The disadvantages is the code can rather ugly and you has to think in term of native COM and managed code at the same Time. Here is a C # version using Dshownet from the. Net Master at CodeProject:
using system;using system.runtime.interopservices;using DShowNET;class playfile {public static void Main (string [] args) {Igraphbuilder graphbuilder = null; IMediaControl Mediactrl = null; Imediaevent mediaevt = null; Type comtype = null; Object comobj = null; try {comtype = Type.gettypefromclsid (clsid.filtergraph); Comobj = Activator.CreateInstance (ComType); Graphbuilder = (igraphbuilder) comobj; Comobj = null; Mediactrl = (IMediaControl) Graphbuilder; Mediaevt = (imediaevent) Graphbuilder; Graphbuilder.renderfile (args[0], NULL); Mediactrl.run (); int Evcode; Mediaevt.waitforcompletion (-1, out evcode); } catch (Exception) {} finally {if (comobj! = null) marshal.releasecomobject (comobj); Comobj = null; Mediactrl = null; MEDIAEVT = null; Graphbuilder = null; } }}
The call to Gettypefromclsid of the Type class, the call to CreateInstance of the Activator class and Releasecomojbect of The Marshall class is examples of what I meant by have to keep track of native COM and managed code. If the dshownet implementation give you access to what are need but not the plain Quartz interop. Then Dshownet is the the-go. At the time of writing this tutorial, there is a Beta version of an open source extension to the Dshownet library. The version 1.1 is now released, we'll show some uses of this new library in the following tutorials.
We ' ll stop here for our first look at DirectShow and C #.
The form code:
Using system;using system.drawing;using system.collections;using system.componentmodel;using System.Windows.Forms; Using system.data;using quartztypelib;namespace csplayer{///<summary>//Summary description for FORM1. </summary> public class Form1:System.Windows.Forms.Form {private System.Windows.Forms.Button button1; <summary>//Required designer variable. </summary> private System.ComponentModel.Container components = null; Public Form1 () {////Required-Windows Form Designer Support//InitializeComponent (); Todo:add any constructor code after InitializeComponent call//}///<summary>//clean Up any resources being used. </summary> protected override void Dispose (bool disposing) {if (disposing) {if (comp Onents = null) {components. Dispose (); }} base. Dispose (disposing); } #region Windows Form Designer generated code///<summary>//Required method for Designer support-do not Modify//The contents of this method with the Code editor. </summary> private void InitializeComponent () {this.button1 = new System.Windows.Forms.Button (); This. SuspendLayout (); Button1//this.button1.Location = new System.Drawing.Point (16, 16); This.button1.Name = "Button1"; This.button1.Size = new System.Drawing.Size (88, 32); This.button1.TabIndex = 0; This.button1.Text = "Play"; This.button1.Click + = new System.EventHandler (This.button1_click); Form1//this. AutoScaleBaseSize = new System.Drawing.Size (5, 13); This. ClientSize = new System.Drawing.Size (216, 86); This. Controls.AddRange (new system.windows.forms.control[] {th Is.button1}); This. Name = "Form1"; This. Text = "Form1"; This. ResumeLayout (FALSE); } #endregion///<summary>//The main entry point for the application. </summary> [STAThread] static void Main () {Application.Run (New Form1 ()); } private void Button1_Click (object sender, System.EventArgs e) {OpenFileDialog ofd = new OpenFileDialog (); if (OFD. ShowDialog () = = DialogResult.OK) {Filgraphmanagerclass graphclass = null; try {graphclass = new Filgraphmanagerclass (); Graphclass.renderfile (OFD. FileName); Graphclass.run (); int Evcode; Graphclass.waitforcompletion (-1, out evcode); } catch (Exception) {} finally {graphclass = null; } } } }}
The simplest example of DirectShow programming 2--