[Windows Mobile] How to play audio/video C# or DirectShow.NET CF Part I
“DirectShow is a multimedia framework and API produced by Microsoft for software developers to perform various operations with media files or streams.” (c) Wikipedia
I`m not sure what earliest version of Windows Mobile that supports DirectShow, but i`m totally sure that Windows Mobile 5.0 and higher definitly suppor DirectShow.
So if you developing you application on C++ you have all headers and libs and it aint problem to use DirectShow, but if you developing on C# then welcome thats article exactly for you
So to make work we need to import required Interfaces and as DirectShow based on COM technologies we need to import CoCreateInstance function
[DllImport("ole32.dll")]
public static extern int CoCreateInstance(
[In] ref Guid rclsid,
[In] IntPtr pUnkOuter,
[In] uint dwClsContext,
[In] ref Guid riid,
[Out, MarshalAs(UnmanagedType.Interface)] out object pv);
In this post i will explain how to play video or audio files. So to play media files we need 2 interfaces:
IGraphBuilder and IMediaControl
to play any media file (if codecs and required filters installed) it will be enough to call method RenderFile of IGraphBuilder interface and method Run of IMediaControl interface… thats easy, isnt it?
[ComVisible(true), ComImport,
Guid("56A868A9-0AD4-11ce-B03A-0020AF0BA770"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IGraphBuilder
{
[PreserveSig]
int AddFilter(
[In] IntPtr pFilter,
[In, MarshalAs(UnmanagedType.LPWStr)] string pName);
[PreserveSig]
int RemoveFilter([In, MarshalAs(UnmanagedType.Interface)] object pFilter);
[PreserveSig]
int EnumFilters([Out, MarshalAs(UnmanagedType.Interface)] out object ppEnum);
[PreserveSig]
int FindFilterByName(
[In, MarshalAs(UnmanagedType.LPWStr)] string pName,
[Out, MarshalAs(UnmanagedType.Interface)] out object ppFilter);
[PreserveSig]
int ConnectDirect(
[In, MarshalAs(UnmanagedType.Interface)] object ppinOut,
[In, MarshalAs(UnmanagedType.Interface)] object ppinIn,
[In, MarshalAs(UnmanagedType.LPStruct)] IntPtr pmt);
[PreserveSig]
int Reconnect([In, MarshalAs(UnmanagedType.Interface)] object ppin);
[PreserveSig]
int Disconnect([In, MarshalAs(UnmanagedType.Interface)] object ppin);
[PreserveSig]
int SetDefaultSyncSource();
[PreserveSig]
int Connect(
[In, MarshalAs(UnmanagedType.Interface)] object ppinOut,
[In, MarshalAs(UnmanagedType.Interface)] object ppinIn);
[PreserveSig]
int Render([In, MarshalAs(UnmanagedType.Interface)] object ppinOut);
[PreserveSig]
int RenderFile(
[In, MarshalAs(UnmanagedType.LPWStr)] string lpcwstrFile,
[In, MarshalAs(UnmanagedType.LPWStr)] string lpcwstrPlayList);
[PreserveSig]
int AddSourceFilter(
[In, MarshalAs(UnmanagedType.LPWStr)] string lpcwstrFileName,
[In, MarshalAs(UnmanagedType.LPWStr)] string lpcwstrFilterName,
[Out] out IntPtr ppFilter);
[PreserveSig]
int SetLogFile(IntPtr hFile);
[PreserveSig]
int Abort();
[PreserveSig]
int ShouldOperationContinue();
}
[ComVisible(true), ComImport,
Guid("56A868B1-0AD4-11CE-B03A-0020AF0BA770"),
InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IMediaControl
{
[PreserveSig]
int Run();
[PreserveSig]
int Pause();
[PreserveSig]
int Stop();
[PreserveSig]
int GetState(
int msTimeout,
out int pfs);
[PreserveSig]
int RenderFile(string strFilename);
[PreserveSig]
int AddSourceFilter(
[In] string strFilename,
[Out, MarshalAs(UnmanagedType.IDispatch)] out object ppUnk);
[PreserveSig]
int get_FilterCollection(
[Out, MarshalAs(UnmanagedType.IDispatch)] out object ppUnk);
[PreserveSig]
int get_RegFilterCollection(
[Out, MarshalAs(UnmanagedType.IDispatch)] out object ppUnk);
[PreserveSig]
int StopWhenReady();
}
To make life more easier i created class CFilterGraph (simplified version of TFilterGraph from DSPack that in Delphi) so here is class that exports 4 methods:
renderFile, play, stop and pause.
using System;
namespace DirectShowNETCF
{
public class CFilterGraph: IDisposable
{
private IGraphBuilder graph = null;
private IMediaControl control = null;
public CFilterGraph()
{
object obj = null;
Guid clsid = CLSID_.FilterGraph;
Guid riid = IID_.IFilterGraph2;
PInvoke.CoCreateInstance(ref clsid, IntPtr.Zero, (uint)CLSCTX_.INPROC_SERVER, ref riid, out obj);
graph = (IGraphBuilder)obj;
control = (IMediaControl)graph;
obj = null;
}
public void Dispose()
{
stop();
System.Runtime.InteropServices.Marshal.ReleaseComObject(graph);
graph = null;
control = null;
}
public bool renderFile(string fileName)
{
return ((graph != null) && (graph.RenderFile(fileName, null) >= 0));
}
public bool play()
{
return ((control != null) && (control.Run() >= 0));
}
public bool stop()
{
return ((control != null) && (control.Stop() >= 0));
}
public bool pause()
{
return ((control != null) && (control.Pause() >= 0));
}
}
}
Thats all
enjoy and have fun, to play mediafiles use Player class from DirectShowNETCF
Filed under: Programming
December 16th, 2009 at 8:38 am
false means that its impossible to render clip for some reasons for example there not required codec exist
December 16th, 2009 at 6:24 am
I can play movie clip on my Omnia(i8000)
but i got error when i want to play third movie clip.
first and second movie clip is ok. but when i load the third like this:
player.renderFile(filename);
It returns FALSE.
October 20th, 2009 at 11:16 pm
DirectShowNetCF.Native.dll you should put on device/emulator by yourself
October 20th, 2009 at 10:48 pm
Tried to deploy on wm5 smartphone emulator, got error “can’t find Pinvooke DLL DirectShowNetCF.Native.dll
July 18th, 2009 at 10:02 am
I used the ILDASM to diassemble it and used ILASM to assemble back again with a strong key file and I am getting this error message.
System.MissingMethodException was unhandled
Message: File or assembly name ‘Interop.QuartzTypeLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=F47E5832F45865E5′, or one of its dependencies, was not found.
Can you please help?