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 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 stoppeople 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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: libvlc是一个开源的跨平台多媒体框架,提供了许多功能,包括录制视频和音频的能力。 在使用libvlc进行录制的过程中,我们需要进行一些基本的操作。首先,我们需要创建一个libvlc实例,然后使用该实例来创建一个媒体对象。接下来,我们可以设置媒体对象的输入源,可以是摄像头、屏幕或者媒体文件。 一旦我们完成了设置,就可以开始录制了。我们可以调用libvlc_media_player_record_start函数来启动录制过程,该函数会将媒体流写入指定的文件或输出流中。我们还可以指定录制的格式、编码器和其他参数。 在录制过程中,我们可以使用libvlc_media_player_record_pause和libvlc_media_player_record_resume函数来暂停和恢复录制。我们还可以调用libvlc_media_player_record_stop函数来停止录制并释放相关资源。 值得注意的是,libvlc录制功能的可用性取决于所使用的平台和操作系统。一些平台可能不支持录制功能,或者只支持特定的输入源或格式。因此,在使用libvlc进行录制时,我们需要检查文档或参考相关示例代码,并根据需要进行适当的配置和调整。 总的来说,libvlc提供了一个简单而强大的录制功能,可以帮助开发者在跨平台环境中方便地进行视频和音频的录制操作。 ### 回答2: Libvlc是一个功能强大的多媒体框架,可以用于录制音频和视频。使用libvlc录制音频和视频非常简单。 首先,需要调用libvlc的初始化函数,创建一个libvlc实例。接下来,我们需要为录制配置一个媒体输出对象。通过设置输出格式、编码器、文件路径等参数,我们可以指定录制的详细信息和目的地。 在录制之前,我们还需要创建一个媒体对象,并设置其源。可以是一个本地文件、网络媒体流或者屏幕采集。然后,我们可以调用libvlc的录制函数,开始录制。 在录制过程中,可以根据需要进行一些操作,比如暂停、继续、停止等。可以通过调用相应的libvlc函数来实现这些功能。 最后,在录制完成之后,我们需要释放资源,关闭libvlc实例。 总结起来,使用libvlc录制音频和视频只需几个简单的步骤:初始化libvlc实例,配置录制参数,创建媒体对象并设置源,开始录制,根据需要进行一些操作,并在录制结束后释放资源。这样,我们就可以轻松地实现音频和视频的录制功能。 ### 回答3: libvlc是一个用C语言编写的开源多媒体框架,用于视频和音频的录制和播放。 在使用libvlc进行录制时,首先需要通过libvlc实例化一个播放器。然后,使用libvlc_media_new_path函数创建一个新的媒体文件。接下来,通过libvlc_media_player_set_media将媒体文件设置给播放器。然后,通过libvlc_media_player_play函数开始播放录制的内容。 在录制过程中,可以使用libvlc_video_set_format和libvlc_audio_set_format函数设置想要的视频和音频格式。还可以使用libvlc_video_set_callbacks和libvlc_audio_set_callbacks函数指定回调函数,用于处理视频和音频数据。通过回调函数,可以对录制的视频和音频进行处理,例如压缩或加密。 在录制完成后,可以使用libvlc_capture_stop函数停止录制。然后,通过libvlc_media_release和libvlc_instance_release函数释放资源。 总结来说,使用libvlc录制视频和音频需要实例化一个播放器、创建媒体文件、设置格式和回调函数,然后开始录制,最后停止录制并释放资源。libvlc提供了丰富的功能和灵活性,可以满足各种录制需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值