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-10-22 15:53:14

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

【流媒体开发】VLC Media Player - Android 平台源码编译 与 二次开发详解 (提供详细800M下载好的编译源码及eclipse可调试播放器源码下载)

作者 : 韩曙亮  博客地址 : http://blog.csdn.net/shulianghan/article/details/42707293 转载请注明出处 : http://blog.csdn.net/shulianghan VLC 二次开发 视频教程 : http://edu.csdn.net/course/detail/355 博客总结 : -- 本博客目的 : 让 Android 开发者通过看本博客能够掌握独立移植 VLC Media Player 核心框架到自己的 app 中,

android错误之MediaPlayer用法的Media Player called in state *

用到Media Player,遇到几个问题,记一下 用法就不说了,使用的时候最好参考一下mediaPlayer的这张图 第一个错误是Media Player called in state 8 这个是因为在调用start之前没有prepare,因为我是用了 mediaPlayer = MediaPlayer.create(context, R.raw.notice); 去初始化的播放器,这个接口说明 只要成功返回了播放器就不需要再去prepare了,但是我之后多次调用stop和start,就导致

Media Player Classic(Guliverkli2)源代码的下载与编译

Media Player Classic(Guliverkli2)是由匈牙利人Gabest开发,基于源代码开放协议(GPL:GNU通用公共许可证)的软件,暴风影音等不少播放器都是在它的基础上做出来的,在sourceforge.net上的项目叫做Guliverkli2,地址是:http://sourceforge.net/projects/guliverkli2/. 1.下载Guliverkli2 首先安装TortoiseSVN客户端,通过地址:https://guliverkli2.svn.so

android错误之MediaPlayer用法的Media Player called in state *,androidmediaplayer

用到Media Player,遇到几个问题,记一下 用法就不说了,使用的时候最好参考一下mediaPlayer的这张图 第一个错误是Media Player called in state 8 这个是因为在调用start之前没有prepare,因为我是用了 mediaPlayer = MediaPlayer.create(context, R.raw.notice); 去初始化的播放器,这个接口说明 只要成功返回了播放器就不需要再去prepare了,但是我之后多次调用stop和start,就导致

Swift - 使用Media Player播放本地视频,在线视频

Media Player框架用于播放本地视频.音频,也可以在线播放视频和音频. 1,播放器MPMovieControlStyle样式有如下几种: (1)None: 没有播放控制控件 (2)Embedded:嵌入式播放控件.没有Done按钮 (3)FullScreen:全屏播放,有播放进度.Done按钮和快进等控件    2,播放本地视频 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 im

Windows media player控件第二次播放时无法全屏

新建MFC工程,插入windows media player control,属性设置fullscreen为true,设置好URL参数. 添加CWMPPlayer4,CWMPControls3类. 控件绑定关联变量CWMPPlayer4 m_player并设CWMPControls3 m_control = m_player.get_controls(); 为了达到循环播放的目的,响应PlayStateChange消息,消息处理函数中是如下两句: m_control.play(); m_play

Winform Windows Media Player 简易播放器

新手上路,高手勿进! 窗体设计: 实现效果: 实现代码: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Data.SqlClient; using Sy

[Winform]Media Player com组件应用中遇到的问题

摘要 最近一个项目中,需要用到在客户端全屏循环播放视频,当时考虑使用开源的播放器,但控制起来不方便,然后考虑既然都是windows系统,那么可以考虑使用微软自带的Media Player播放器.所以在开发中,就在winform中嵌入了Media Player组件.下面就将开发中遇到的问题,做一个总结. 问题与解决办法 首先要搞清楚Media Player到底是x86的还是x86的.我电脑系统是x64的,可以尝试打开Media Player,在任务管理器中查看是不是x64的. 所以media pl