libvlc media player in C# (part 1)

There seems to be a massive misconception about using VLC inside an application and many, many large wrapper libraries have been written. These are often harder to use than libvlc itself, buggy or just downright don’t work (at least not in what will be “the latest” version of VLC at the time you want to write anything).

Using the libvlc documentation directly and the libvlc example I wrote a simple wrapper class that performs the basics needed to play, pause and stop media. Because it is libvlc, things like resizing the video, toggling full screen by double clicking the video output or streaming media from a source device or network are handled automatically.

This code was all written and tested with VLC 0.98a but because it is taken from the documentation and example, it should work for all versions 0.9x and later with only minor changes. Because it is so simple, these changes should be easy to make. Most of the time, these changes will just be slight function name changes and no new re-structuring is needed.

The first thing to note is that there is no version of libvlc for Windows x64. All developers should set their CPU type to x86, even if they have a 32bit machine. If you set it to “Any CPU” then 64bit users will not be able to load libvlc.dll and will crash out. If you are compiling from the command line, this should look something like csc /platform:x86 foobar.cs

The second thing to note, which trips up a lot of users, is that you must specify VLC’s plugin directory. This may make distribution a nightmare, as the plugin directory is a large directory full of DLLs. It may be possible to narrow down these DLLs to just the ones your application actually needs but I don’t know if videolan have any advice about or licensing for redistribution of these.

libvlc is made up of several modules. For the sake of simplicity in this example, I will use 1 static class to contain every exported C function and split them up visually by module with #region.

The nicest thing about VLC, as far as interop with C# goes, is that all memory management is handled internally by libvlc and functions are provided for doing anything that you would need to do to their members. This means that using an IntPtr is suitable for almost everything. You just need to make sure that you pass the correct IntPtr into each function but another layer of C# encapsulating this would easily be able to make sure of that, as discussed in part 2. The only structure that you need to define is an exception, which is very simple. You then simply always pass in references to these structs with ref ex.

The code listing for the wrapper class is as follows:

using System;
using System.Runtime.InteropServices;
 
namespace MyLibVLC
{
  // http://www.videolan.org/developers/vlc/doc/doxygen/html/group__libvlc.html
 
  [StructLayout(LayoutKind.Sequential, Pack = 1)]
  struct libvlc_exception_t
  {
    public int b_raised;
    public int i_code;
    [MarshalAs(UnmanagedType.LPStr)]
    public string psz_message;
  }
 
  static class LibVlc
  {
    #region core
    [DllImport("libvlc")]
    public static extern IntPtr libvlc_new(int argc, [MarshalAs(UnmanagedType.LPArray,
      ArraySubType = UnmanagedType.LPStr)] string[] argv, ref libvlc_exception_t ex);
 
    [DllImport("libvlc")]
    public static extern void libvlc_release(IntPtr instance);
    #endregion
 
    #region media
    [DllImport("libvlc")]
    public static extern IntPtr libvlc_media_new(IntPtr p_instance,
      [MarshalAs(UnmanagedType.LPStr)] string psz_mrl, ref libvlc_exception_t p_e);
 
    [DllImport("libvlc")]
    public static extern void libvlc_media_release(IntPtr p_meta_desc);
    #endregion
 
    #region media player
    [DllImport("libvlc")]
    public static extern IntPtr libvlc_media_player_new_from_media(IntPtr media,
      ref libvlc_exception_t ex);
 
    [DllImport("libvlc")]
    public static extern void libvlc_media_player_release(IntPtr player);
 
    [DllImport("libvlc")]
    public static extern void libvlc_media_player_set_drawable(IntPtr player, IntPtr drawable,
      ref libvlc_exception_t p_e);
 
    [DllImport("libvlc")]
    public static extern void libvlc_media_player_play(IntPtr player, ref libvlc_exception_t ex);
 
    [DllImport("libvlc")]
    public static extern void libvlc_media_player_pause(IntPtr player, ref libvlc_exception_t ex);
 
    [DllImport("libvlc")]
    public static extern void libvlc_media_player_stop(IntPtr player, ref libvlc_exception_t ex);
    #endregion
 
    #region exception
    [DllImport("libvlc")]
    public static extern void libvlc_exception_init(ref libvlc_exception_t p_exception);
 
    [DllImport("libvlc")]
    public static extern int libvlc_exception_raised(ref libvlc_exception_t p_exception);
 
    [DllImport("libvlc")]
    public static extern string libvlc_exception_get_message(ref libvlc_exception_t p_exception);
    #endregion
  }
}

For a sample application to use this simple wrapper, I just created a new Windows form and added a play button, stop button and a panel for viewing the video. In this example, the stop button also cleans everything up so you should make sure to press it before closing the form.

At one point during this code, libvlc can optionally be given a HWND to draw to. If you don’t give it one, it pops up a new player. However, people seem to be confused over how simple this is to do in C# and have been making large amounts of interop calls to the Win32 API to get handles. This is not necessary, as System.Windows.Forms.Control.Handle allows you go get the window handle (HWND) to any component that inherits from the Control class. This includes the Form class and the Panel class (and even the Button class) so all you actually need to pass it is this.Handle (for the handle to the form itself) or panel.Handle (for a Panel called panel). If you want it to start fullscreen, add the command line argument “-f” rather than using the Win32 function GetDesktopWindow().

Because I will be using this to display PAL video, which is interlaced at 576i, I have added some deinterlacing options to the command line. These are --vout-filter=deinterlace and --deinterlace-mode=blend.

Without further ado, here is the code listing for the partial windows form class:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
 
using System.Runtime.InteropServices;
 
namespace MyLibVLC
{
  public partial class Form1 : Form
  {
    IntPtr instance, player;
 
    public Form1()
    {
      InitializeComponent();
    }
 
    private void Play_Click(object sender, EventArgs e)
    {
      libvlc_exception_t ex = new libvlc_exception_t();
      LibVlc.libvlc_exception_init(ref ex);
 
      string[] args = new string[] {
        "-I", "dummy", "--ignore-config",
        @"--plugin-path=C:\Program Files (x86)\VideoLAN\VLC\plugins",
        "--vout-filter=deinterlace", "--deinterlace-mode=blend"
      };
 
      instance = LibVlc.libvlc_new(args.Length, args, ref ex);
      Raise(ref ex);
 
      IntPtr media = LibVlc.libvlc_media_new(instance, @"C:\foobar.mpg", ref ex);
      Raise(ref ex);
 
      player = LibVlc.libvlc_media_player_new_from_media(media, ref ex);
      Raise(ref ex);
 
      LibVlc.libvlc_media_release(media);
 
      // panel1 may be any component including a System.Windows.Forms.Form but
      // this example uses a System.Windows.Forms.Panel
      LibVlc.libvlc_media_player_set_drawable(player, panel1.Handle, ref ex);
      Raise(ref ex);
 
      LibVlc.libvlc_media_player_play(player, ref ex);
      Raise(ref ex);
    }
 
    private void Stop_Click(object sender, EventArgs e)
    {
      libvlc_exception_t ex = new libvlc_exception_t();
      LibVlc.libvlc_exception_init(ref ex);
 
      LibVlc.libvlc_media_player_stop(player, ref ex);
      Raise(ref ex);
 
      LibVlc.libvlc_media_player_release(player);
      LibVlc.libvlc_release(instance);
    }
 
    static void Raise(ref libvlc_exception_t ex)
    {
      if (LibVlc.libvlc_exception_raised(ref ex) != 0)
        MessageBox.Show(LibVlc.libvlc_exception_get_message(ref ex));
    }
  }
}

Note that this section of code is deprecated and the code from part 2 should be used instead.

Adding a pause button is similar to the stop button but without the cleanup.

Here is an example slightly further on down the line but using the same code:
Example of LibVLC

See part 2 for more.

Tags: , ,

45 Responses to “libvlc media player in C# (part 1)”

  1. Daniel says:

    Hi,

    I’m trying to get the Movie Lenght.

    Therefor I used a wrapper for

    libvlc_media_player_get_length ( libvlc_media_player_t * ,
    libvlc_exception_t *
    )

    like this:

    [DllImport("libvlc")]
    public static extern Int64 libvlc_media_player_get_time(IntPtr player, libvlc_exception_t ex);

    But that with the Int64 don’t work. Do you have a solution to get the lenght?

  2. Daniel says:

    Sorry I was wrong. It works fine.

  3. Yasir says:

    How can i play udp stream this way?

     string[] args = new string[] {
                    "-I", "dummy", "--ignore-config",
                    @"--plugin-path=C:\Program Files\VideoLAN\VLC\plugins",
                    "--vout-filter=deinterlace", "--deinterlace-mode=blend","udp://"+txtIP.Text+":"+txtPort.Text
                };

    this way? because i use write

    udp://ip address:port instead of filename it does not work.

  4. George Helyar says:

    I am not a VLC support forum. Please use the proper support channels. You could start with the Wiki.

    All I can say is that the plugin-path argument is the most important so make sure you get it absolutely correct.

    You should try running vlc.exe with the same command line arguments to test them first.

  5. Muhammad says:

    Hi

    can you plz send me solution for this example

    thanx

  6. George Helyar says:

    Hi Muhammad, you can download the project/solution at the bottom of “part 2″.

  7. rekna says:

    could you update for vlc 1.1.1?

  8. Hi George,

    I appreciate you for awesome code and explanation. I tried your code in Win 7 and VS2008. It is compiling fine but not playing the video. I used some .avi video and .mpg video. I would appreciate you for giving me an advice because I have to include VLS player for one of my project here.

    Thanks,
    Binu

  9. George Helyar says:

    Hi Binu,

    I don’t know why it isn’t playing. There are three things I can suggest to start with.

    Firstly, try a different version of VLC and compile against that. “Part 2″ of this post is more up to date.

    Secondly, try waiting a few minutes after you hit play. Occasionally it takes some time to play the first video after compiling for me, I don’t know why. It could be something similar to when VLC itself says “rebuilding font cache”, but without the popup telling you what it’s doing. This seems to be quite rare but it has caught me out a few times where I thought I had done something to break it, and just waiting for it eventually started it. After the first time it tends to load instantly the next time you run it.

    Finally, check if any errors are being thrown anywhere. The code here does not have much error handling and if something is going wrong it may not tell you. In the debugger you can check if handles are 0, for example.

  10. Yes now it is working. I reinstalled the VLC.

    Thanks a lot George!! I appreciate once again your great advice and work.

    Binu

  11. Sam E says:

    Hello George,
    i’m using VS2008 so how do u reference the plugin folder ? Do you do it through right-click -> Proporties->Refernece Paths or do you copy the folder to system32 ?

    Thank You

  12. George Helyar says:

    You do not reference the plugin directory inside Visual Studio itself, but rather change the args string when initialising the instance of libvlc. Pass the appropriate path in the constructor. You can clearly see where the plugins path is in the sample code.

  13. jehad drubi says:

    really great stuff George. i am trying to get live stream from camera with ip address . can vlc do that in csharp

  14. George Helyar says:

    I suspect libvlc can stream from a camera with IP address (particularly if VLC itself can) but I don’t have a camera to test it with, so you should probably ask on the libvlc forum.

  15. jiga says:

    Can this play youtube video directly from link??

    The actual vlc player can do this, but i am not sure if libvlc supports it.

  16. [...] Firstly, libvlc is great! , almost – all streaming types – are supported. However, it is written in C language and also finding a good wrapper for C# is very hard. After litte research and try, we decided to use helyar’s libvlc wrapper. [...]

  17. villecoder says:

    Really great information and an excellent introduction to how to use libvlc from .NET. Really, this is the first post I’ve seen that had some simple, easy to follow, non-complicated advice on how to use Interop to interface with the library. This will go a long way to help me with my project. Thank you!

  18. Moon1337 says:

    I can’t find libvlc.dll anywhere, why isn’t this file on http://www.videolan.org ?
    When I try your code I get a System.DllNotFoundException …

  19. George Helyar says:

    moon, you need both libvlc.dll and libvlccore.dll. You also need many of the dlls from VLC’s plugin directory, as these are what provide codec support, interlace support, etc. These all need to be from the same version of VLC too. This means that you need almost the entire VLC installation to get all the dlls, so just install or extract the latest version of VLC, take the two main dlls from there and change the plugin-path argument in your libvlc initialisation call to point to the plugin directory inside the VLC directory you just created when installing or extracting.

    You may be able to distribute a subset of the DLLs in the plugin directory but distribution is not covered here.

  20. Aneesh says:

    I’ve created a media payer using libvlc.dll. While playing the video it is not displaying the context menu with this vlc control. I need to display the context menus when playing the video. If it is not playing it is displaying the context menus when right clicking the mouse. Please help me..

  21. George Helyar says:

    The context menu is part of the VLC client, not the libvlc library. Write your own.

  22. Aneesh says:

    Hi George,

    Thanks for your replay. I’m using C# winform to create this application. I’ve already set the ContextMenuStrip with the axvlc plugin. Axvlc plugin has the property ContextMenuStrip to set the ContextMenuStrip. Actually I’m using multiple axvlc plugin in a form.ContextMenuStrip is working fine when video stops. It is not working while the video is playing. Please help.

    Thanks,
    Aneesh

  23. Bayaraa says:

    Hi Helyar, i need VLC media player in my c# application. But i can’t use it. My computer CPU type 64bit and my application must work in 64bit. How do i use VLC ? Can you give me some VLC examples for 64bit if it possible.

  24. George Helyar says:

    @Bayaraa
    Read the post again.

    There is no 64 bit libvlc. If you want to use libvlc, you need to set your C# project to 32 bit (which will still allow it to be run on 64 bit windows). This also means that any other DLLs you link to in the same binary must also be 32 bit.

  25. Bill Boykin says:

    Hi George, excellant post on embedding VLC. I’ve used VLC in the past but when I needed to use the ActiveX control, it’s always failed by trying to write to protected memory and shutting down the IDE (C# Visual Studio). So I’ve tried out your tutorial and it works great so I’m going to pursue this approach to my applications. I haven’t done the research yet but I’d like to get your input on the following Question :
    The tutorial works with the respective version of VLC install (vlc-1.1.2-win32.exe). When I try out other “versions” it does not run. Would you give me some insight as to what I should be looking for to make the code compatible with other version?
    Thanks George !

  26. Bill Boykin says:

    George, what is your opinion on VLC versus MPlayer ? (www.mplayerhq.hu) Which one is the best for handling the most possible video streams, cameras, video file types?

  27. George Helyar says:

    Hi Bill. The problem of VLC versions is answered in several of the comments in part 2 of this post. It’s mostly just a matter of grabbing the two libvlc dlls from the appropriate version and compiling against them. There may be some minor changes between versions but it’s usually just a few function names, if anything.

    This can lead to a problem of distribution, as you either need the target machine to have the appropriate version of VLC installed or you need to ship the dlls, including codec plugin dlls, with your application.

    MPlayer is a decent player but has a slightly different purpose. VLC is designed to just work out of the box so that you don’t have to install codecs. If you know specifically which codecs you will be using in advance (e.g. from a set of networked security cameras) or have control over the target computers, you may not need the flexibility that VLC offers. If you want a player that will play everything and also has very good streaming capabilities, VLC may be better. I would certainly say that VLC is the best player available for Windows, at least. libvlc is also a very nicely designed API.

  28. Jason Fullen says:

    I understand that the source code from part two is supposed to just run and work when I try to debug in visual studio 2010. However, when I tried to run your code I got an exception when the Form1 constructor tried to initialize the VlcInstance object. I ran the debugger and traced the exception to the following lines of code:

    class VlcInstance : IDisposable
    {
    internal IntPtr Handle;

    public VlcInstance(string[] args)
    {
    Handle = LibVlc.libvlc_new(args.Length, args);
    if (Handle == IntPtr.Zero) throw new VlcException(); //This is the fail spot.
    }

    public void Dispose()
    {
    LibVlc.libvlc_release(Handle);
    }
    }

    The Handle is coming back initialized to zero or else the exception would not be thrown. Is there something I am doing wrong? I checked the path for the libvlc.dll and (since I am using windows 7) it is correct. I am not sure what else could be wrong with this code. I really liked the simplicity of this wrapper and would really like to use it in my application. Any help is much appreciated.

  29. George Helyar says:

    Hi Jason, this has been asked in several comments in part 2 so please read them if you need further information.

    The two libvlc dlls must be the same version as your VLC. Go to your copy of VLC (as on the path used in the constructor), copy libvlc.dll and libvlccore.dll to your project, recompile and run your project.

  30. Luke says:

    Are there any pros and cons of using this technique vs the active x assembly?

    Here’s an example of the active x plugin being used in wpf:

    http://miteshsureja.blogspot.com/2011/11/creating-simple-video-player-using-vlc.html

  31. George Helyar says:

    Hi Luke,

    The ActiveX plugin adds a control to your Visual Studio designer interface but that’s the only reason I can think of to use it in .net. With the code in this post, you can just do the same thing by attaching libvlc to the window handle of a Panel control or something similar. Some other languages may prefer to use the ActiveX plugin if they can’t interface with C libraries directly, but these are likely variants on old style Visual Basic.

    The cons of the ActiveX control include increased dependencies, potential security risks (as with all ActiveX), likely slower development, less testing from videolan and a smaller feature set than the full libvlc library, etc.

    The VLC ActiveX documentation suggests using the ActiveX plugin for web browser plugins, but it’s a very obscure plugin to rely on when Adobe Flash and HTML 5 both have built in video playback support for modern browsers.

  32. Zainab says:

    Hi i am new at streaming and and i have little concept of C#
    i need to do streaming in C#, i heard of a wrapper for vlc in java, VLCJ ,
    but i prefer to use vlc for streaming in C#.
    can you please guide me how should i start.

  33. Allan says:

    Hi,
    I was developing an audio player with 3 players in C# using VLC Plugins, I have multiple sound card, I need to assign individual sound card to each player, can any one help me for that. Thanks in advance.

  34. Tony says:

    Hi, I wish to play a jpg or other image files for a set duration. How can I do this?

  35. Jason says:

    Use “–text-renderer=tdummy” in the args commands for libvlc_new call

  36. Bill Boykin says:

    Hi George, It’s been some time since I studied your article and practised with your solution to get VLC to work in a windows C# application form. Intuitive and to the point.

    Well, the need did come up where I needed to apply your solution and wanted to say thank you for your guidance.

    I consider myself fortunate to have read and practised with your VLC solution. Big souts to you George and much thanks!

  37. AzaleaMay says:

    Dear George,
    I want to capture a live streaming video in VLC into a C# application. Do you have some suggestions on the same. I am just getting started and I can do will all the help that I get, in terms of documentations and earlier attempts, etc. Thanks a lot!

  38. George Helyar says:

    Hi AzaleaMay,

    Do you have this working in the normal VLC player? Is it RSTP? UDP? DirectShow? etc?

  39. kamlesh delat says:

    can it’s possible work’s on mono project ?

  40. George Helyar says:

    It should work on mono but I haven’t tested. You should certainly be able to do it yourself with simple interop calls.

    One platform difference is that a different function is called when setting the drawable control to render on.
    libvlc_media_player_set_hwnd on Windows, libvlc_media_player_set_xwindow on Linux, etc.

    Check the documentation for details.

  41. Jose Carlos says:

    Hi.
    I need to use a different Audio Card, not the windows default device, how Can I do this?

    Regards

  42. Sid says:

    Hello,

    Can i use the same library with windows phone 8.1 as i am developing an application for playing Video files of all format.

    If any one knows about any other library supported for windows phone please let me know and will be a great help for me.

    Thanks in advance.

  43. George Helyar says:

    Hi Sid,

    As far as I know, libvlc will not work on Windows Phone 8.1. The RT versions of Windows are for the ARM CPU architecture, and libvlc does not have Windows builds for ARM.

    However, there is a rumour that VLC for Windows Phone 8.1 is coming soon.

    You may also be able to build it yourself from source, as ARM is already supported on other operating systems, but if that were the case I suspect there would already be a binary available.

    I do not have a Windows Phone to test any of this.

    Currently, to play videos on Windows Phone 8.1, you should be using Media Foundation.

  44. Sid says:

    Hello George,

    Many thanks for your quick response.

    Currently i am Using Windows phone 8.1 Media element to play videos but the problem is MediaElement only support few video format only supported by windows phone OS which i am able to play successfully and Same format i can play with MediaFoudation.

    So i m seeking a library or codec supported for windows phone 8.x which can play Formats like MKV and FLV.

    Thanks

  45. George Helyar says:

    Hi Sid,

    MKV and FLV are both container formats, not stream codecs. For example, both MKV and FLV files may contain H.264 video streams that can already be played by MF. In this case, you just need to be able to open the container format and get the stream, perhaps with libavformat.

    I have no experience with Media Foundation. However, if you do have a stream format that can’t be played you should be able to either decode (to YUV video or PCM audio) with an external library and then play the decoded streams with MF, or implement a custom decoder in MFT.

    If ffmpeg will work on Windows RT, it may do most of this for you. You can also look at mkvtoolnix etc.

    If you need to interact with these external programs, you can usually do this via their standard input and output streams to avoid having to save temporary files to disk.

Leave a Reply