原文 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:

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

  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 play ...

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

    作者 : 韩曙亮  博客地址 : http://blog.csdn.net/shulianghan/article/details/42707293 转载请注明出处 : http://blog.csd ...

  3. 用VLC Media Player搭建简单的流媒体服务器

    VLC可以作为播放器使用,也可以搭建服务器. 在经历了Helix Server和Darwin Streaming Server+Perl的失败之后,终于找到了一个搭建流媒体简单好用的方法. 这个网址中 ...

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

    用到Media Player,遇到几个问题,记一下 用法就不说了,使用的时候最好参考一下mediaPlayer的这张图 第一个错误是Media Player called in state 8 这个是 ...

  5. win7自带windows media player 已停止工作

    解决方法如下: 在计算机开始,菜单找到控制面板 ,然后打开程序和功能,选择打开或关闭window功能,媒体功能.再取消windows Media Center Windows MediaPlayer选 ...

  6. 转:Media Player Classic - HC 源代码分析

    VC2010 编译 Media Player Classic - Home Cinema (mpc-hc) Media Player Classic - Home Cinema (mpc-hc)播放器 ...

  7. Media Player 把光盘中的内容拷贝出来的方法

    http://jingyan.baidu.com/article/cb5d610529f0c1005c2fe0b4.html  这个链接是通过Media  Player 把光盘中的内容拷贝出来的方法h ...

  8. 20 Free Open Source Web Media Player Apps

    free Media Players (Free MP3, Video, and Music Player ...) are cool because they let web developers ...

  9. Windows Media Player安装了却不能播放网页上的视频

    前段时间遇到Windows Media Player安装了却不能播放网页上的视频的问题,在网上查找资料时,发现大部分资料都没能解决我这个问题.偶尔试了网上一牛人的方法,后来竟然解决了.现在再找那个网页 ...

随机推荐

  1. 相关Python分割操作

    刚论坛python文本 http://bbs.byr.cn/#!article/Python/1693 攻克了一个关于python分片的问题. 问题: uesrList = ['1','2','3', ...

  2. R语言做文本挖掘 Part4文本分类

    Part4文本分类 Part3文本聚类提到过.与聚类分类的简单差异. 那么,我们需要理清训练集的分类,有明白分类的文本:測试集,能够就用训练集来替代.预測集,就是未分类的文本.是分类方法最后的应用实现 ...

  3. jQuery EasyUI实现全部关闭tabs

    有时,当我们打开很多tabs当标签,要关闭一个接一个,它只能被关停 显然太麻烦,能够在选项卡的最右边加入一个button 实现关闭所有. 代码例如以下: <!DOCTYPE HTML PUBLI ...

  4. ZOJ 2760 How Many Shortest Path(Dijistra + ISAP 最大流)

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1760 题意:给定一个带权有向图 G=(V, E)和源点 s.汇点 t ...

  5. android4.4组件分析--service组件-bindService源代码分析

    6.1.1.    bindService 由于有前面分析startService的代码实现过程,则对于bindService的代码分析就不用那么具体介绍,在介绍流程的同一时候更关注一些细节上的部分. ...

  6. 阿里巴巴2014研发project师实习生面试经历

    java研发project师的初面是在上周三进行的,终于结果到了晚上才出,而没有通过的则是一结束网上就更新了状态.之后阿里通知这周三,也就是今天进行二面. 凑巧的是今早被舍友吵醒,中午那个困啊,但没时 ...

  7. LeetCode :: Insertion Sort List [具体分析]

    Sort a linked list using insertion sort. 仍然是一个很简洁的题目,让我们用插入排序给链表排序:这里说到插入排序.能够来回想一下, 最主要的入门排序算法.就是插入 ...

  8. 【C语言】reverse_string(char * string)(递归)

    递归reverse_string(char * string)性能. 逆转 原始字符串 更改 相反,打印出的. /* 编写一个函数reverse_string(char * string)(递归实现) ...

  9. 《生活在Linux中》之:prefer function to alias in Bash

    在Bash环境中,定义了alias替换有时会产生不是想要的替换:e.g:;而定义function则能够避免这样的缺陷.

  10. debian(wheezy) chrome beta 38.0.2x.xxx Shockwave Flash was crashed 该解决方案崩溃.

    版本号chrome beta升级到38.0.2x.xxx什么时候, flash他挂了. 调试 ./libpepflashplayer.so: /lib/x86_64-linux-gnu/libc.so ...