libvlc media player in C# (part 2)

I gave some simplified VLC media player code in part 1 to show how easy it was to do and how most wrapper libraries make a mountain out of a mole hill. In that entry, I briefly touched on using some classes to make it easier and safer to implement actual programs with this.

The first thing to do is write a wrapper for the exceptions, so that they are handled nicely in C#. For a program using the library, exceptions should be completely transparent and should be handled in the normal try/catch blocks without having to do anything like initialise them or check them.

Another thing to do is to move all of the initialisation functions into constructors and all of the release functions into destuctors or use the System.IDisposable interface.

Here is the code listing for the 4 classes used (VlcInstance, VlcMedia, VlcMediaPlayer and VlcException). Note that the first 3 of these are very similar and that the main difference is that the media player class has some extra functions for doing things like playing and pausing the content.

class VlcInstance : IDisposable
{
    internal IntPtr Handle;
 
    public VlcInstance(string[] args)
    {
        VlcException ex = new VlcException();
        Handle = LibVlc.libvlc_new(args.Length, args, ref ex.Ex);
        if (ex.IsRaised) throw ex;
    }
 
    public void Dispose()
    {
        LibVlc.libvlc_release(Handle);
    }
}
 
class VlcMedia : IDisposable
{
    internal IntPtr Handle;
 
    public VlcMedia(VlcInstance instance, string url)
    {
        VlcException ex = new VlcException();
        Handle = LibVlc.libvlc_media_new(instance.Handle, url, ref ex.Ex);
        if (ex.IsRaised) throw ex;
    }
 
    public void Dispose()
    {
        LibVlc.libvlc_media_release(Handle);
    }
}
 
class VlcMediaPlayer : IDisposable
{
    internal IntPtr Handle;
    private IntPtr drawable;
    private bool playing, paused;
 
    public VlcMediaPlayer(VlcMedia media)
    {
        VlcException ex = new VlcException();
        Handle = LibVlc.libvlc_media_player_new_from_media(media.Handle, ref ex.Ex);
        if (ex.IsRaised) throw ex;
    }
 
    public void Dispose()
    {
        LibVlc.libvlc_media_player_release(Handle);
    }
 
    public IntPtr Drawable
    {
        get
        {
            return drawable;
        }
        set
        {
            VlcException ex = new VlcException();
            LibVlc.libvlc_media_player_set_drawable(Handle, value, ref ex.Ex);
            if (ex.IsRaised) throw ex;
            drawable = value;
        }
    }
 
    public bool IsPlaying { get { return playing && !paused; } }
 
    public bool IsPaused { get { return playing && paused; } }
 
    public bool IsStopped { get { return !playing; } }
 
    public void Play()
    {
        VlcException ex = new VlcException();
        LibVlc.libvlc_media_player_play(Handle, ref ex.Ex);
        if (ex.IsRaised) throw ex;
 
        playing = true;
        paused = false;
    }
 
    public void Pause()
    {
        VlcException ex = new VlcException();
        LibVlc.libvlc_media_player_pause(Handle, ref ex.Ex);
        if (ex.IsRaised) throw ex;
 
        if (playing)
            paused ^= true;
    }
 
    public void Stop()
    {
        VlcException ex = new VlcException();
        LibVlc.libvlc_media_player_stop(Handle, ref ex.Ex);
        if (ex.IsRaised) throw ex;
 
        playing = false;
        paused = false;
    }
}
 
class VlcException : Exception
{
    internal libvlc_exception_t Ex;
 
    public VlcException() : base()
    {
        Ex = new libvlc_exception_t();
        LibVlc.libvlc_exception_init(ref Ex);
    }
 
    public bool IsRaised { get { return LibVlc.libvlc_exception_raised(ref Ex) != 0; } }
 
    public override string Message { get { return LibVlc.libvlc_exception_get_message(ref Ex); } }
}

Using these classes is even easier than before, can use proper exception handling (removed for brevity) and cleans up better at the end. In this example, I have added an OpenFileDialog, which is where the file is loaded.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
 
namespace MyLibVLC
{
    public partial class Form1 : Form
    {
        VlcInstance instance;
        VlcMediaPlayer player;
 
        public Form1()
        {
            InitializeComponent();
 
            openFileDialog1.FileName = "";
            openFileDialog1.Filter = "MPEG|*.mpg|AVI|*.avi|All|*.*";
 
            string[] args = new string[] {
                "-I", "dummy", "--ignore-config",
                @"--plugin-path=C:\Program Files (x86)\VideoLAN\VLC\plugins",
                "--vout-filter=deinterlace", "--deinterlace-mode=blend"
            };
 
            instance = new VlcInstance(args);
            player = null;
        }
 
        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            if(player != null) player.Dispose();
            instance.Dispose();
        }
 
        private void Open_Click(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() != DialogResult.OK)
                return;
 
            using (VlcMedia media = new VlcMedia(instance, openFileDialog1.FileName))
            {
                if (player != null) player.Dispose();
                player = new VlcMediaPlayer(media);
            }
 
            player.Drawable = panel1.Handle;
        }
 
        private void Play_Click(object sender, EventArgs e)
        {
            player.Play();
        }
 
        private void Pause_Click(object sender, EventArgs e)
        {
            player.Pause();
        }
 
        private void Stop_Click(object sender, EventArgs e)
        {
            player.Stop();
        }
    }
}

Update:

I have just corrected a minor bug (the wrong release function being called on the player handle) and uploaded the full Visual Studio 2005 project. You can download the full project here (or see 1.1.2 version below). It comes with the libvlc.dll and libvlccore.dll for VLC 1.0.1 in the bin\x86\Debug directory so if you have a version other than this, just overwrite those files.

Update for VLC 1.1.2:

You can now download the VLC 1.1.2 compatible version. There were some changes to the way libvlc handles exceptions that needed to be corrected. Other than that, there were a couple of minor function name changes.

Please use these posts as a starting point to use your own code though. These posts are intended to stop people from being reliant on the already existing, large, overcomplicated and quickly outdated libraries. They are not intended to be just another library for people to blindly use without understanding how it works. You can use this to learn how to write your own native interop code on a well designed library then adapt it for your own changes and keep it up to date with whichever version of VLC you want. This also means you never have to use the terrible code on pinvoke.net for other libraries, as you can write your own from the original documentation and it will almost always be better.

Bugfix: VlcException should use Marshal.PtrToStringAnsi not Marshal.PtrToStringAuto

Tags: , ,

128 Responses to “libvlc media player in C# (part 2)”

  1. Dennis says:

    George,

    Thank you for these articles. I learned a lot about wrapping native DLL’s for use in C# from your example (which is so much easier than I anticipated!). And, I have directly applied your VLC example (plus a few addition wrapped functions) for embedded video features in our project.

  2. Mike says:

    Gooood article!!!

    But … i’ve a couple of questions …

    how can i implement a method to play a byte array instead of video files on disk?

    It’s necessary to have vlc installed on my pc in order to use this libs and wrapper?

    Tnx ;)

  3. George Helyar says:

    Hi Mike,

    Playing from memory can apparently be achieved with imem_access but I have yet to see this done at all. Here are some threads:
    http://forum.videolan.org/viewtopic.php?f=32&t=75919
    http://forum.videolan.org/viewtopic.php?f=32&t=85451
    http://forum.videolan.org/viewtopic.php?f=32&t=86533

    This is something I would like to do but right now it seems that it isn’t possible.

    In the meantime, I am just writing to a temporary file (.mpg or .ts – something that can be written to while you’re playing it) playing that file and then deleting it afterwards.

    Regarding distribution, read part 1 of this. You need at least the plugin dlls for anything you’re using (e.g. deinterlacing or specific codecs) and since that’s most of the VLC installation anyway, unless you can cut it down to only the bare minimum dlls and ship them with your application it may be easier to just install the full VLC. It is certainly useful to have the full VLC installation on your development system.

  4. elestigio says:

    Greetings colleagues, I need help to implement a method that allows me to view videos in fullscreen from the principal from either through the event using the buttons as objects of iteration of the application.

  5. kzhustler says:

    Hi George,

    Great vlc wrapper. I want to use the wrapper with an external tv tuner. How can i add this with dshow?

    Thanks, be well.

    bye

  6. George Helyar says:

    Because VLC is specifically designed not to require DirectShow filters, this is not a simple task. Everything I could find points to using Sensoray.

    If your tuner offers other connection methods, you may be able to use these instead. For example, I believe the SiliconDust HDHomeRun can use UDP, which libvlc can connect to as described in previous comments for networked security cameras (in fact the HDHomeRun specifically lists VLC compatibility as a feature). Other similar products (EyeTV etc) may offer similar functionality, particularly if they offer non-Windows clients.

    I just samba share my MythTV (live) recording directory and play the mpg in VLC while it is recording.

  7. ryandaniels says:

    Hey, thanks for this tutorial, I was beginning to think about not using libvlc until I found this. I had to change some of the sample code; I got an error (stack was imbalanced), and my research led me to add some extra arguments into the “[DllImport("libvlc")]” lines.

    Anyways, after I did this, it worked, I was able to play a video, however, when I closed it, it threw some exceptions (Including access violation), and I found that this occured when the form Disposed. I also found that if I slowed it down a bit (via debugging), the crash doesn’t occur. All I have to do is put a breakpoint on base.Dispose(), and that stops it from crashing.

    I assume you might already know why this is happening (given more experience with libvlc), so I thought I pose this question. For myself, as well as any other readers.

    Thanks!

  8. George Helyar says:

    Hi Ryan, it sounds like it just isn’t being cleaned up properly before it disposes e.g. it’s still trying to draw to a component handle that no longer exists, as set in VlcMediaPlayer.Drawable. Stop the video and make sure all the release functions are called in the right order, before the form closes.

  9. Yosua says:

    hi george. Im yosua an im a newbie in C#. I have an assigment that requires me to stream a video from a different computer. LAN system i mean. For example 1 server has 10 client and that 10 client play a different videos. My job is to display what video their playin in a mini 10 screen from server computer. The video on the server has to be real time, i mean no lag and play smoothly. Can i do it using this VLC?reply my message please. My email is yosua160891@yahoo.com. It’s a very important assignment.sorry if my english is bad because im indonesian. tq before.

  10. George Helyar says:

    Hi Yosua, any academic assignment of this complexity will have given you the resources you need to complete it. In general if you need to look for external resources, you’ve misunderstood the assignment, so check with whoever gave you the assignment.

    If this is a commercial or personal project then yes, you can stream video in VLC but only on certain protocols. In fact VLC is the “VideoLAN Client”, while there is also a VideoLAN Server for streaming, although it is now mostly integrated into VLC. As far as streaming smoothly, 1 server encoding 10 different videos in real time is probably going to have performance problems no matter what you do, unless the videos are very low resolution or the server has a lot of hardware acceleration.

    This article is purely a simple guide on how to use libvlc directly from a .net project without relying on someone else’s wrapper. Streaming servers are out of scope here. The first thing you should check out is How to Stream with VLC on the VideoLAN wiki. VLC itself even has options such as “Display Locally” when streaming.

  11. Yosua says:

    thank you for your guidance George, So the feature is quite impossible to make. i’m very thankful to you, maybe sometime i ask you more about this project or another project. Could you give me your email George?Thank you for your help.

  12. Yosua says:

    And my another question George. If i just streaming 1 videos from another computer it is possible to write a code in C# using libvlc or not? Because i don’t familiar with API code and from what i see from your code its just tellin me how to make a media player using libvlc. I’ve been searching for a code to streaming a video on LAN but after 4 days i still not found it. Thank you before.

  13. skymania says:

    Has anybody have any success streaming a file with this wrapper ?

  14. Fadi says:

    Hi George,
    Thanks for the nice post, it does indeed put hope in one’s ability to create a wrapper from scratch!

    I am running into a strange scenario where if I run two instances of the application (I am doing this outside of VS environment to minimize problems) once i play an http stream on one window, the other http stream on the other window stops.
    I must hit stop/start to make it work but then as you might exect, the other running stream/playback will freeze.

    Any hints or ideas on how to fix this. Thanks
    FK

  15. George Helyar says:

    Hi FK,

    It should just work but unfortunately I don’t know why it doesn’t. Other comments here have viewed multiple simultaneous streams even within the same application. You should only need a new VlcMediaPlayer for each simultaneous stream.

    The first thing to check is probably that multiple instances of the normal VLC client can play your streams correctly.

    Hope that helps, George

  16. David Roux says:

    Getting this if run using .net 4.0 -> Unable to load DLL ‘libvlc’: The specified module could not be found. (Exception from HRESULT: 0x8007007E)

    .net 2.0 all runs 100%… any ideas how i can run this in .net 4?

  17. Mon Vin says:

    HI,

    I want use more function of libvlc, such as : duration, currentposition, audiotrack or audiochannel, nextplay, volumn,… How can I do that ?

    Hope the helps…

  18. Anu says:

    Hi

    I am getting the below error while running the application

    An unhandled exception of type ‘System.EntryPointNotFoundException’ occurred in MyLibVLC.exe

    Additional information: Unable to find an entry point named ‘libvlc_media_new’ in DLL ‘libvlc’.

    Thanks
    Anu

  19. Nice says:

    Hi Helyar. I need vlc player in c#. i m playing movie in my windows application. I need playing speed 2x, 3x 4x 6x 8x 16x,32x .. etc. how to playing speed in c#????? I need help please

  20. George Helyar says:

    Try libvlc_media_player_set_rate.

    If you’re unsure how to use the function, read both pages of this post. That’s what the purpose of it is, and you can apply it to any function..

  21. Dan says:

    George,

    Thanks a big heap for the simple article. I was able to use the examples to get my unattended remote play out server working with one exception. If I play a file for a certain duration say 30 minute, but it turns out to end after 15 minutes, the player still says it is playing and freezes on the last frame and will stay there until my timer says it should be done. I thought I could check for being stopped or set a stopped event, but that doesn’t work. I tried the command line parameter –play-and-exit, without success either. I didn’t see any functions on the VLC page you referenced in the previous post (or maybe I didn’t know what to look for). Any advice?

    Thanks.

  22. Nice says:

    Hi Helyar. I need forward example code. Please send me source code.

  23. Samsung says:

    HI Helyar,
    Thanks for great post.
    I am tring to stream on http like the command line “C:\Users\Public\Videos\Sample Videos\Wildlife.wmv”:
    sout=#transcode{vcodec=h264,acodec=mp3,ab=128,channels=2,samplerate=44100}:http{dst=:8090/go.mpg}
    does using your code….but I couldnt able to do.
    Could you please tell me where i can give my vlc parameters to start streaming?

    Thanks.

  24. Konzertheld says:

    Thanks, that helped a lot, understanding and using. The only trouble that remains is when I have German umlauts in my file path. It is a VLC issue, do you have any idea how to work around that? I tried URL encoding, did not help. I also tried passing an ISO-8859-1 byte array instead of a string to libvlc_media_new_location or (libvlc_media_new_file, what I’m usually using), also did not help. When I pass such a file, just nothing happens, it seems to be played and no error occurs but it is not played. When I rename the file so there are no more umlauts it works fine. Would be great if you could help me with that…

  25. George Helyar says:

    Hi Konzertheld, please take a look at this thread and see if it works:
    http://forum.videolan.org/viewtopic.php?f=32&t=53714

    The method converts the UTF-16 string to a UTF-8 byte array with System.Text.Encoding.UTF8.GetBytes and passes it as a byte array instead of a string to the libvlc function.

    Another alternative may be to set the charset of the string to UTF8 when importing the function from the dll, but I have not tested this.

  26. Konzertheld says:

    Aaaah, it’s UTF-8. That’s mostly what I already tried except I didn’t tried the correct charset. Awesome. Thank you! I totally agree with you it is unnecessary to build a huge framework around libvlc. The one I used before was so complex I didn’t know where to start looking for an error that occured somewhen… now it’s easy and transparent.

  27. ravi says:

    how can i implement frame by frame using this vlc library?

  28. jinzhexiu999 says:

    Hi Helyar. I need vlc player in c#. i m playing movie in my windows application.
    I need playing speed 2x, 3x 4x
    I want to know how to implement fast forward wih using vlc_media_player_set_rate, vlc_media_player_get_rate fuctnion

Leave a Reply