libvlc media player in C# (part 1)

原文 http://www.helyar.net/2009/libvlc-media-player-in-c/

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:

时间: 2024-09-17 04:24:35

libvlc media player in C# (part 1)的相关文章

libvlc media player in C# (part 2)

原文 http://www.helyar.net/2009/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

MFC使用window media player时遇到的问题

问题描述 MFC使用window media player时遇到的问题 MFC调用media player控件来播放视频,在xp和win7下都能播放,开始时怎么使用都没问题,但一段时间后在xp下切换视频时,调试到这一句m_player.put_url(strFilename)出现内存错误win7下完全没问题,请教大家帮忙解决一下,其中各个变量和指针都看过了,都没问题,调试了很久一直没解决 解决方案 出错的时候好像m_player这个对象不正确了.也可能media player控件本身挂了. 解决

如何在网页中嵌入Media player 播放流媒体文件

媒体|网页 Media Player两种版本播放器的嵌入代码,有相关说明(默认0为否,-1或1为是)不过代码还不全面,没有判断浏览器版本的参数程序代码: <object classid="clsid:22D6F312-B0F6-11D0-94AB-0080C74C7E95" id="MediaPlayer1" width="286" height="225"><param name="AudioSt

net 页面怎样内嵌media player视频窗口

页面 <script language=javascript defer> var volv=phx.settings.volume; setInterval("if(phx.playState==3){time.innerText=phx.controls.currentPositionString+'|'+ phx.currentMedia.durationString}",1000); setInterval("if(phx.playState==3){it

媒体播放器Media Player Classic

Media Player Classic Home Cinema,简称MPC-HC,是一款简洁的媒体播放器,Media Player Classic 的后续版本,有32位元和64位元版本.Media Player Classic 是由名为 "Gabest" 的程序员建立,现在他仍然有维护这个程序. Gabest 原先是以不公开源代码的方式开发 Media Player Classic,但后来他开放了 Media Player Classic 的源代码. 目前mpc-hc是一款开源软件,

Media Player Classic Home Cinema媒体播放器

Media Player Classic Home Cinema,简称MPC-HC,是一款简洁的媒体播放器,Media Player Classic 的后续版本,有32位元和64位元版本.Media Player Classic 是由名为 "Gabest" 的程序员建立,现在他仍然有维护这个程序. Gabest 原先是以不公开源代码的方式开发 Media Player Classic,但后来他开放了 Media Player Classic 的源代码. 目前mpc-hc是一款开源软件,

Windows Media Player界面的实现

一.简介 SYGUI是一个基于功能扩展的MFC界面库,我在以前的文章中介绍了如何使用该界面库来实现VC界面,在本文中将向大家介绍利用SYGUI4.0所提供的新功能来实现类似Windows Media Player的界面定制功能.这里所指的界面定制功能是指在不修改程序代码的情况下允许为程序设计各种具有不同外观风格的程序界面.例如本文所附的例子程序包含了如下图所示的三种不同的界面,三种界面可通过界面上的外观选择按钮进行动态切换: 图一 例子程序运行时的三种界面 当然,通过界面定制还可以为例子程序设计

Windows Media Player 12的新特性

我们已经介绍了一些 Windows 7 的新特性和新功能了,这次我们来看看 Windows Media Player 12 吧,Windows Media Player 仍然是 Windows 中的一个重要组件,本以为 Zune 会代替 Windows Media Player,题外话:Zune 软件的社会化功能确实挺有意思的,比如:Zune 的 Social Card,和 MixView 都很不错. Windows Media Player 12 的界面恐怕是最显著的变化了,与 Windows

WinCE 4.2下轻松调用Windows Media Player控件

小弟是个刚入门的菜鸟,现在大家都在做嵌入式开发了,所以我也来凑凑热闹.菜鸟就是菜鸟,这不,现在想在 WinCE4.2 下播放 wma.mp3 音乐,可是连个 Winodws Media Player 控件都不知道该怎么调用.大家可不要笑啊,以前我在 Winodws2000 平台下,感觉调用这个控件非常简单,可是在 WinCE4.2 平台下就没辙了.为什么呢?原因就是基于 WinCE4.2 平台的程序开发要在 Windows2000 等平台上做,可是在 Windows2000 平台上调出来的 Wi