Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / multimedia / DirectX

Media files conversion using C#

4.21/5 (14 votes)
28 Jul 20055 min read 10   12.3K  
Demonstrates building DirectShow filter graphs for file conversion.

Introduction

The GraphEdit utility, from the DirectShow SDK, is a popular tool to simulate the processing of media files on the Windows platform. Recently, DirectShowLib, an open-source .NET wrapper for DirectShow has been released. Version 1.0 of DirectShowLib wraps the most important interfaces and, already provides much more functionality than the interop assembly generated from the Quartz.dll. In this article, we'll present an application that builds filter graphs for the conversion of media files using C#. Hence, we'll show how to create applications in C# that provide some functionality that GraphEdit does.

Background

There are plenty of file formats for multimedia applications. The most popular ones are those in the MPEG family (MPEG-1/2, MPEG 4 (part 2 or 10)...), the Microsoft family (AVI, ASF, WMV,...), QuickTime family (QT, MOV,...) and RealMedia (RM, RAM,...). Each has its advantages and disadvantages. Moreover, some are covered by those silly little things called "software patents" (probably invented by fat, lazy middle managers in large corporations, who find it easier to dump work on their law department than actually developing products that their customers want ;-).

So for this application, I have decided to write a conversion utility that will convert many media files to the Windows Media Video (.wmv) format. Moreover, since Microsoft holds patents on the ASF format (from which .wmv is derived), I have code to convert to the open format initiative known as Matroska.

Using the code

This web site has many resources for using DirectShow from .NET. The ancestor of DirectShowLib was a project by .netmaster on this site. I have studied their code and you can look at them for things that I haven't explained in this article.

First, the command line to compile the application (provided in build.cmd and assuming that the C# compiler is accessible from the current path) refers to the DirectShowLib assembly. In the code, we start with:

C#
using DirectShowLib;

Then, we use the following variables to build the filter graph:

C#
// The main com object
FilterGraph fg = null;
// The graphbuilder interface ref
IGraphBuilder gb = null;
// The mediacontrol interface ref
IMediaControl mc = null;
// The mediaevent interface ref
IMediaEventEx me = null;

After some initial steps (common to all DirectShow applications in C#), we convert a media file to a .wmv file using the following code:

C#
// here we use the asf writer to create wmv files
WMAsfWriter asf_filter = new WMAsfWriter();
IFileSinkFilter fs = (IFileSinkFilter)asf_filter;
        
hr = fs.SetFileName( fileName + ".wmv", null );
DsError.ThrowExceptionForHR( hr );

hr = gb.AddFilter( (IBaseFilter)asf_filter, "WM Asf Writer" );
DsError.ThrowExceptionForHR( hr );
        
hr = gb.RenderFile( fileName + fExt, null );
DsError.ThrowExceptionForHR( hr );

hr = mc.Run();          
DsError.ThrowExceptionForHR( hr );

This code creates a WMAsfWriter object, and accesses its IFileSinkFilter interface to set its file name. Then it adds the filter to the graph using the GraphBuilder interface method AddFilter. After this, we use "Intelligent Connect" (done through the call to RenderFile) to let the DirectShow runtime build the rest of the graph. Then, when we call the method Run on the MediaControl interface, we are actually writing the file because the renderer filter in this graph is a file writer.

Points of Interest

From my earlier comments, you probably guessed that I am not a big fan of software patents. After having written the code for the conversion to .wmv files, I learned that Microsoft has patents on the file format on which it is based. So I looked for alternatives, and I realized that this field is replete with those "silly little things". So I decided to add support for conversion to the Matroska file format which is "patent-free", as far as I know.

Matroska support

The code to build a filter graph that will write .mkv files is similar to the code for writing .wmv files. Except that we don't create a WMAsfWriter but we create a FileWriter object (and, again, access its IFileSinkFilter interface to set its name). Then we use the following to add the Matroska Mux filter:

C#
// create an instance of the matroska multiplex filter and add it
// Matroska Mux Clsid = {1E1299A2-9D42-4F12-8791-D79E376F4143}
Guid guid = new Guid( "1E1299A2-9D42-4F12-8791-D79E376F4143" );
Type comtype = Type.GetTypeFromCLSID( guid );
IBaseFilter matroska_mux = (IBaseFilter)Activator.CreateInstance( comtype );

If you have installed support for Matroska to your system (download the codec pack from www.matroska.org if you don't consider codec packs "evil"), the CLSID for the Matroska Muxer will be included in your registry. Then you can create a type object and call Activator.CreateInstance to have an IBaseFilter object that can be added to the filter graph.

Using GraphBuilder.RenderFile will again try to build the rest of the graph from a source media file. This process doesn't always work as expected and you should consider the Matroska support as experimental and mainly used for illustrative purposes.

Limitations and known issues

I originally developed this application because I had some Real Media files that I wanted to convert to .wmv. I manually built the filter graph in the GraphEdit tool and rebuild it for every file. So I decided a little application that would do the same would be handy. Real Media files can be converted to Windows Media files without any problem if you have the Real Media Splitter installed on your system (with a Real Player or Real Alternative).

The Window Media file to Matroska file conversion seems to be working fairly well. But MPEG files don't convert to Matroska files with this application (and I didn't look into the problem). But you can convert MPEGs to WMVs and then convert it once more to a Matroska file. (This second conversion seems to hang on some files but the files are not corrupted and can be played in your favorite player. GraphEdit had the some difficulty on these files.) As mentioned, the Matroska support is experimental and mainly for illustrative purposes. So I don't promise that I'll support this functionality of the application.

Installing the codec pack for Matroska with its shell extension facility created problems on my system (and it seems to be a problem on other machines). But the default installation script doesn't include this functionality. Nevertheless, searching Google reveals that other people had problems after installing the Matroska codec pack on XP.

The timing on some Matroska files looks odd and I'll intent to look at this issue.

If the file is large, the conversion can take some time. I use the Task Manager application and check the CPU usage to find out when the conversion is over.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here