vlc的应用

转自:http://jeremiah.blog.51cto.com/539865/115910

vlc的应用之一:在命令行下的使用

   如果编译得到没有界面的vlc,双击运行后就没法手动选打文件或网络了。在这介绍几个vlc的命令行命令。

 
    1. vlc帮助
vlc --help
or
vlc --help --advanced
 
    2. vlc的debug log
vlc -vv --extraintf=logger
    运行的log将会保存在vlc-log.txt中。
 
    3. vlc打开文件
vlc -vv --extraintf=logger d:/01.avi
 
    4. 作为服务器通过rtp往客户端发送ts流
vlc -vvv --extraintf=logger d:/01.avi :sout=#duplicate{dst=rtp{dst=localhost,mux=ts,port=1234}}
 
    5. 作为客户端接收rtp流
vlc -vv --extraintf=logger rtp://@:1234
   
    Jeremiah最常用的就是这么多,如果还有其他需求,参考下面几个网址。
vlc的应用之二:vlc的ActiveX及cab
   2009-05-14补充:8. Activex的卸载;9. 让vlc自动安装Activex ;10. 关于vlc的Activex的说明。
    vlc自带了ActiveX控件--axvlc.dll,在编译完vlc之后的activex文件夹下。ActiveX是个好东西, axvlc.dll 可以 随意放到任何位置, 成功注册之后可以方便的应用在程序和网页之中。可以参考activex文件夹下的test.html和README.TXT。ActiveX控件的接口有第一版和第二版,第一版简单,功能少,已经不再维护建议用第二版本,功能多一点。(参考的[1])
    vlc-0.8.6i和vlc-0.9.4的ActiveX注册方法略有不同。
    做ActiveX的网页测试之前需要把Internet选项-->安全-->本地Intranet的安全级别调到最低。Jeremiah的网页测试环境是IE7,其他浏览器未进行测试。

    1. vlc-0.8.6iActiveX注册

    在E:下新建文件夹vlc-0.8.6iActiveX,拷贝vlc-0.8.6i目录下的plugins,libvlc.dll,activex/axvlc.dll到
vlc-0.8.6iActiveX/dlls目录下,拷贝activex/test.html到 vlc-0.8.6iActiveX下。新建文本文件install.bat内容如下:
regsvr32 dlls/axvlc.dll
    双击install.bat后会提示“dlls/axvlc.dll中的DllRegisterServer成功”。然后用打开test.html,文本框输入MRL就可以播放了。

    2. vlc-0.9.4的ActiveX注册
    0.9.4不光要告诉计算机vlc的axvlc.dll的位置,还要告诉注册表installdir的位置,也就是libvlc.dll的位置
   
在E:下新建文件夹vlc-0.9.4ActiveX,拷贝vlc-0.9.4目录下的plugins,libvlc.dll,libvlccore.dll,activex/axvlc.dll到 vlc-0.9.4ActiveX/dlls目录下,拷贝activex/test.html到 vlc-0.9.4ActiveX下。新建文本文件install.reg内容如下:
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE/SOFTWARE/VideoLAN/VLC]
"InstallDir"="E://vlc-0.9.4ActiveX//dlls"
    新建文本文件install.bat内容如下:

regsvr32 dlls/axvlc.dll

regedit /s install.reg
    双击install.bat后就可以用test.html进行测试了。

    3. 一点点小提示
    如果注册成功,但是test.html播放文件的时候会报错说decoder modules会找不到之类信息,那请将0.8.6i和0.9.4交替注册,可能会解决这个问题。(Jeremiah因为这个问题搞了一天,NND)(2009-05-14补充:直接看8吧,以前这个地方写的不大对。)
   
    4. 制作cab文件
    如果要类似与test.html作个播放器服务器,但是我们却不能手动操纵
客户端去下载注册vlc的ActiveX,解决方法就是自己制作cab文件。
    (1) 到
本日志的附件 (cabsdk.rar)或者 以下地址 去下载cabsdk.exe: [url]http://download.microsoft.com/download/platformsdk/cab/2.0/w98nt42kmexp/en-us/cabsdk.exe[/url]
    (2) 安装cabsdk.exe
    (3) 将axvlc.dll及vlc的安装文件拷贝到cabsdk安装路径/BIN/ 下。Jeremiah这里用的是vlc-0.8.6i-win32.exe。(关于如何制作vlc的安装文件,参考日志《windows平台下vlc编译之二:vlc-0.8.6i的编译》)
    (4) 在/BIN下新建文本文件axvlc.inf,内容如下:
; Version number and signature of INF file.
;
[version]
signature="$CHICAGO$"
AdvancedINF=2.0

[Add.Code]
vlc-0.8.6i-win32.exe
axvlc.dll=axvlc.dll

[axvlc.dll]
FileVersion=0,8,6,0
clsid={9BE31822-FDAD-461B-AD51-BE1D1C159921}
RegisterServer=no
hook=nsiinstaller

[vlc-0.8.6d-win32.exe]
FileVersion=0,8,6,0
file-win32-x86=thiscab

[nsiinstaller]
run=%EXTRACT_DIR%/vlc-0.8.6i-win32.exe
    注意:请根据安装文件的版本修改此文件。
    (5) 命令行到BIN目录下,执行以下命令生成cab文件:
CABARC.EXE N axvlc.cab axvlc.inf axvlc.dll vlc-0.8.6i-win32.exe
   
    5. cab文件的使用
    html页面下使用cab文件可以通过以下方式:
<OBJECT classid="clsid:9BE31822-FDAD-461B-AD51-BE1D1C159921"
                codebase="your/path/of/cabfile/axvlc.cab"
                         width="640" height="480" id="vlc" events="True">
< param name ="Src" value="" />
< param name ="ShowDisplay" value ="True" />
< param name ="AutoLoop" value ="False" />
< param name ="AutoPlay" value ="False" />
</OBJECT>
    这样web客户端无须手动注册axvlc.dll就可以使用了。

    6. 一点比较严重小问题
    由于vlc的安装文件一般是比较大,所以制作出来的cab文件也是很大的,在网络带宽不是很好的时候,光下载这个cab可能就很长很长时间,基本上可以说这样的方式是行不通的。所以
我们 需要根据自己的业务需求去精简vlc。Jeremiah将在下一篇日志介绍。

    7. C#下使用vlc的ActiveX
    vs2005新建一个windows应用程序,在左侧工具箱右键-->选择项-->com组件-->VideoLAN VLC ActiveX plugin v2,工具箱里面就添加了vlc的ActiveX控件,可以在窗体里面随便画了。
    调用函数如下:
private void button1_Click( object sender, EventArgs e)
{
         //输入参数
         string parameter = ":sout=#duplicate{dst=display} :no-overlay";
        
         //判断是否正在播放
         if ( this.axVLCPlugin21.playlist.isPlaying)
        {
                 //如果正在播放, 则停止
                 this.axVLCPlugin21.playlist.stop();
        }

         //清空播放列表
         this.axVLCPlugin21.playlist.clear();

         //添加播放列表
         this.axVLCPlugin21.playlist.add(textBox1.Text, null, parameter);

         //播放列表更新到新添加的播放项
         this.axVLCPlugin21.playlist.next();
        
         //播放
         this.axVLCPlugin21.playlist.play();
}
    其他函数调用参考activex/README.TXT。
    Jeremiah在附件里面提供了一个简单的调用程序(WindowsApplication1.rar), 不过需要注意的是,在用它测试0.9.4的ActiveX,当正常播放文件时点击X关闭窗口 产生异常,电脑会重新启动。在主窗体的
FormClosing 事件中让主线程睡了1000ms,并不能完全保证电脑不重启,所以请根据自己的情况进行本附件的调试。
 
    8. Activex的卸载
    卸载是安装的反向操作,知道怎么安装,卸载很简单。
    vlc-0.8.6i的Activex的卸载:新建uninstall.bat,内容如下:
regsvr32 dlls/axvlc.dll /u
    vlc-0.9.4的Activex的卸载:新建uninstall.reg,内容如下:
Windows Registry Editor Version 5.00

[-HKEY_LOCAL_MACHINE/SOFTWARE/VideoLAN]
    新建uninstall.bat,内容如下:
regsvr32 dlls/axvlc.dll /u

regedit /s uninstall.reg
    双击uninstall.bat,提示dlls/axvlc.dll中的DllUnregisterServer成功。就卸载完毕了。
 
     9. 让vlc安装的时候自动安装Activex
    4里面提到cab包的制作及5里面提到了cab包的使用。cab其实就是让客户自动下载vlc的安装文件,然后启动安装。但是安装过程中,出现这样一步:
    Activex plugin默认是没有被选中的,如何让它这一步默认是选中的,或者选中并且是灰色的(比如像Media Player这一项),不让客户改变呢?我们需要修改编译完的vlc的vlc.win32.nsi文件。然后用它重新制作vlc-0.9.4-win32.exe.
    具体修改过程如下:
    在vlc.win32.nsi文件中,找到:
Section /o $Name_Section04 SEC04
SectionIn 3
    修改为:
Section $Name_Section04 SEC04
SectionIn 1 2 3
    或者在1 2 3后面加入“空格RO”,表示这项是必须的不能去掉,就是选中并且是灰色的。$Name_Section04可以替换为"My ActiveX plugin (required)"等自己的名字。
    然后根据前面博客讲的制作vlc-0.9.4-win32.exe的过程执行一遍,然后再制作cab包就okay了。
 
    10. 关于vlc的Activex的说明
    根据我对vlc的Activex的使用,发现这个Activex做的真是不好,很多方法没有封装进来,如果扩展这个Activex,工作量不小。如果是做C/S程序, 强烈不建议用Activex来开发。除非是想简单做一下,快速开发等。做C/S播放器还是看我这篇博客:《 vlc的应用之三:动态调用vlc-0.9.4的libvlc.dll 》,开发过程虽然慢点,但是比较可控。 Activex只适合应用于B/S项目,只适合WEB开发,这是Jeremiah的一点忠告,但是只属于个人意见,仅供参考。
vlc的应用之三:动态调用vlc-0.9.4的libvlc.dll
    vlc-0.9.4提供的libvlc.dll是可以动态调用的,Jeremiah这一篇博客就介绍下如何用C#和WinForm框架调用libvlc.dll作个简易播放器。
 
    1. vs2005新建工程,将vlc-0.9.4的libvlc.dll,libvlccore.dll,plugins目录全部拷贝到工程目录下面/bin/Debug中
 
    2. 创建异常结构体
using System;
using System.Collections.Generic;
using System.Text;

namespace MyOwnPlayer
{
         //异常结构体
         public struct ExceptionStruct
        {
                 private int raised;
                 private int code;
                 private string message;
        }

         class MediaException
        {
        }
}
 
    3. CoreHandle和Core类
using System;
using System.Runtime.InteropServices;

namespace MyOwnPlayer
{
         class CoreHandle : SafeHandle
        {
                 //构造方法
                 public CoreHandle()
                        : base(IntPtr.Zero, true)
                {
                }

                 //重写的方法
                 public override bool IsInvalid
                {
                        get { return handle == IntPtr.Zero; }
                }

                 protected override bool ReleaseHandle()
                {
                         if (!IsInvalid)
                        {
                                libvlc_release( this);
                                handle = IntPtr.Zero;
                        }
                         return true;
                }

                 protected override void Dispose( bool disposing)
                {
                        ReleaseHandle();
                         base.Dispose(disposing);
                }

                 //Dll动态导入
                [DllImport( "libvlc")]
                 private static extern void libvlc_release(CoreHandle coreHandle);
        }
}
 
using System;
using System.Runtime.InteropServices;

namespace MyOwnPlayer
{
        class Core
        {
                //coreHandle字段和属性
                private CoreHandle coreHandle;
                public CoreHandle CoreHandle
                {
                        get { return coreHandle; }
                }
                
                //构造方法
                public Core(string[] argv, ref ExceptionStruct ex)
                {
                        coreHandle = libvlc_new(argv.Length, argv, ref ex);
                }

                //Dll动态导入
                [DllImport("libvlc")]
                private static extern CoreHandle libvlc_new(int argc, string[] args, ref ExceptionStruct ex);
        }
}
 
    3. MediaHandle和Media类,注意里面的非英文路径处理方法。
using System;
using System.Runtime.InteropServices;

namespace MyOwnPlayer
{
        class MediaHandle : SafeHandle
        {
                //构造方法
                public MediaHandle()
                        : base(IntPtr.Zero, true)
                {
                }

                //重写的方法
                public override bool IsInvalid
                {
                        get { return handle == IntPtr.Zero; }
                }

                protected override bool ReleaseHandle()
                {
                        if (!IsInvalid)
                        {
                                libvlc_media_release(this);
                                handle = IntPtr.Zero;
                        }
                        return true;
                }

                protected override void Dispose(bool disposing)
                {
                        ReleaseHandle();
                        base.Dispose(disposing);
                }

                //Dll动态导入
                [DllImport("libvlc")]
                private static extern void libvlc_media_release(MediaHandle mediaHandle);                
        }
}
 
using System;
using System.Text;
using System.Runtime.InteropServices;

namespace MyOwnPlayer
{
         class Media
        {
                 //mediaHandle字段和属性
                 private MediaHandle mediaHandle;
                 public MediaHandle MediaHandle
                {
                        get { return mediaHandle; }
                }

                 //构造方法                
                 public Media(CoreHandle coreHandle, String filename, ref ExceptionStruct ex)
                {
                         //c#为UTF-16编码, libvlc.dll为UTF-8编码, 需要转换.
                        UTF8Encoding utf8 = new UTF8Encoding();
                        mediaHandle = libvlc_media_new(coreHandle, utf8.GetBytes(filename), ref ex);
                }
                
                 //Dll动态导入
                [DllImport( "libvlc")]
                 private static extern MediaHandle libvlc_media_new
                        (CoreHandle coreHandle, [MarshalAs(UnmanagedType.LPArray)] byte[] link, ref ExceptionStruct ex);
                }
}
 
    5. MediaPlayerHandle和MediaPlayer类
using System;
using System.Runtime.InteropServices;

namespace MyOwnPlayer
{
         class MediaPlayerHandle : SafeHandle
        {
                 //构造方法
                 public MediaPlayerHandle()
                        : base(IntPtr.Zero, true)
                {
                }

                 //重写的方法
                 public override bool IsInvalid
                {
                        get { return handle == IntPtr.Zero; }
                }

                 protected override bool ReleaseHandle()
                {
                         if (!IsInvalid)
                        {
                                libvlc_media_player_release(this);                                 handle = IntPtr.Zero;
                        }
                         return true;
                }

                 protected override void Dispose( bool disposing)
                {
                        ReleaseHandle();
                         base.Dispose(disposing);
                }

                 //Dll动态导入
                [DllImport( "libvlc")]
                 private static extern void libvlc_media_player_release(MediaPlayerHandle mediaPlayerHandle);
        }
}
 
using System;
using System.Runtime.InteropServices;

namespace MyOwnPlayer
{
         class MediaPlayer
        {
                 //mediaPlayerHandle字段和属性
                 private MediaPlayerHandle mediaPlayerHandle;
                 public MediaPlayerHandle MediaPlayerHandle
                {
                        get { return mediaPlayerHandle; }
                }

                 //构造方法
                 public MediaPlayer(MediaHandle mediaHandle, ref ExceptionStruct ex)
                {
                        mediaPlayerHandle = libvlc_media_player_new_from_media(mediaHandle, ref ex);
                }

                 //设置父窗口
                 public void VedioSetParent(CoreHandle coreHandle, IntPtr hDT, ref ExceptionStruct ex)
                {
                        libvlc_video_set_parent(coreHandle, hDT, ref ex);
                }

                 //播放
                 public void Play( ref ExceptionStruct ex)
                {
                        libvlc_media_player_play(mediaPlayerHandle, ref ex);
                }

                 //停止
                 public void Stop( ref ExceptionStruct ex)
                {
                        libvlc_media_player_stop(mediaPlayerHandle, ref ex);
                }

                 //Dll动态导入
                [DllImport( "libvlc")]
                 private static extern MediaPlayerHandle libvlc_media_player_new_from_media(MediaHandle libvlc_media_handle, ref ExceptionStruct ex);

                [DllImport( "libvlc")]
                 private static extern void libvlc_video_set_parent(CoreHandle coreHandle, IntPtr hDT, ref ExceptionStruct ex);

                [DllImport( "libvlc")]
                 private static extern void libvlc_media_player_play(MediaPlayerHandle mediaPlayerHandle, ref ExceptionStruct ex);

                [DllImport( "libvlc")]
                 private static extern void libvlc_media_player_stop(MediaPlayerHandle mediaPlayerHandle, ref ExceptionStruct ex);
        }
}
 
    6. 基本工作做好了。下一步建立一个Form,里面画一个Panel(播放容器),画一个Textbox(播放地址),画一个Button(播放按钮),Button的点击事件为:
private void button1_Click(object sender, EventArgs e)
{
        
//要播放的文件的uri
        
string uri = this.textBox1.Text;

        
//进行播放的控件的句柄
        IntPtr hdl =
this.panel1.Handle;

        
//播放参数
        
string[] argv = new string[] { "-I", "--ignore-config" };

        
//vlc对象的创建
        ExceptionStruct ex =
new ExceptionStruct();
        Core core =
new Core(argv, ref ex);
        Media media =
new Media(core.CoreHandle, uri, ref ex);
        MediaPlayer player =
new MediaPlayer(media.MediaHandle, ref ex);

        
//垃圾回收
        GC.Collect();

        
//播放
        player.VedioSetParent(core.CoreHandle, hdl,
ref ex);
        player.Play(ref ex);

        
//继续回收垃圾等相关操作
        GC.Collect();
        GC.WaitForPendingFinalizers();
}
 
    7. 基本的播放功能就是这样实现的。其他接口请参考源码下面的/include/vlc/libvlc.h文件,里面有比较详细的对外接口的说明。
 
    8. 以上代码已经发送到附件中(MyOwnPlayer.rar),参考网址的楼主写的代码也在附件中(Marx_libvlc_wrapper(2).zip)。调试附件请注意第1步。
vlc的应用之四:vlc的Mozilla Plugin
    Jeremiah最近研究了下让vlc支持Mozilla的火狐浏览器,也就是类似于IE的Activex。现在将研究的结果共享一下。
 
    1. 测试的版本为vlc-0.9.4,当然编译的环境为旧版本的Cygwin(我的叫法,不是官方的叫法),具体的安装配置编译vlc-0.9.4,不明白的去看我的前几篇博客,里面详细的介绍了。
 
    2. 编译脚本为configure-vlc04.sh(附件提供)。
PATH=/usr/win32/bin:$PATH /
PKG_CONFIG_LIBDIR=/usr/win32/lib/pkgconfig /
CPPFLAGS="-I/usr/win32/include -I/usr/win32/include/ebml" /
LDFLAGS=-L/usr/win32/lib /
CC="gcc -mno-cygwin" CXX="g++ -mno-cygwin" /
./configure /
         --host=i686-pc-mingw32 /
         --disable-gtk /
         --enable-nls --enable-sdl --with-sdl-config-path=/usr/win32/bin /
         --enable-avcodec --enable-avformat --enable-swscale /
         --enable-faad --enable-flac --enable-theora /
         --with-wx-config-path=/usr/win32/bin /
         --with-freetype-config-path=/usr/win32/bin /
         --with-fribidi-config-path=/usr/win32/bin /
         --enable-live555 --with-live555-tree=/usr/win32/live.com /
         --enable-caca --with-caca-config-path=/usr/win32/bin /
         --with-xml2-config-path=/usr/win32/bin /
         --with-dvdnav-config-path=/usr/win32/bin /
         --disable-cddax --disable-vcdx --enable-goom /
         --enable-twolame --enable-dvdread /
         --enable-debug    --enable-dca /
         --enable-mozilla --with-mozilla-sdk-path=/usr/win32/gecko-sdk /
         --disable-mkv --disable-taglib
 
    3. 编译中出错及解决方法见[url]http://jeremiah.blog.51cto.com/539865/115322[/url]
 
    4. 编译完成后打包(make package-win32-base)。
 
    5. 将打包好的vlc-0.9.4文件夹下面的libvlc.dll,libvlccore.dll, plugins, mozilla/npvlc.dll拷贝到一个单独的目录下,比如E:/WorkBack/vlc-0.9.4/Mozilla Plugin/dlls。
 
     6. 新建注册表文件mozilla_plugin.reg(见附件),内容为:
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE/SOFTWARE/MozillaPlugins/@videolan.org/vlc,version=0.9.4]
"De.ion"="VLC Multimedia Plugin"
"Path"="E://WorkBack//vlc-0.9.4//Mozilla Plugin//dlls//npvlc.dll"
"Product"="VLC media player"
"Vendor"="VideoLAN"
"Version"="0.9.4"

[HKEY_LOCAL_MACHINE/SOFTWARE/VideoLAN/VLC]
"InstallDir"="E://WorkBack//vlc-0.9.4//Mozilla Plugin//dlls"
"Version"="0.9.4"
"Language"="2052"
 
    7. 运行这个注册表文件。
 
    8. 到打包好的vlc-0.9.4下面的activex目录中,用火狐打开test.html测试,done!
vlc的应用之五:动态调用libvlc.dll的补充
    最近Jeremiah在增加以前播放器的功能的时候,被一个中文路径转码问题恶心了两天,最后终于让我给解决了。在这跟大家分享这个转码的解决方法,以及用视频本次存储的接口实现。
 
    在看本篇日志之前,请先看我以前写的《vlc的应用之三:动态调用vlc-0.9.4的libvlc.dll 》
 
    补充一:libvlc_new(...)接口的中文路径转码处理
using System;
using System.Runtime.InteropServices;

namespace MyOwnPlayer
{
         class Core
        {
                 //coreHandle字段和属性    
                 private CoreHandle coreHandle;
                 public CoreHandle CoreHandle
                {
                        get { return coreHandle; }
                }

                 //构造方法    
                 public Core( string[] argv, ref ExceptionStruct ex)
                {
                         byte[][] argvbytes = new byte[argv.Length][];

                         for ( int i = 0; i < argv.Length; i++)
                        {
                                argvbytes[i] = Encoding.UTF8.GetBytes(argv[i]);
                        }

                        coreHandle = libvlc_new(argv.Length, ReturnIntPtr(argvbytes, argv.Length), ref ex);
                }

                 //转换函数
                 private IntPtr ReturnIntPtr( byte[][] data, int length)
                {
                        IntPtr[] dataIntPtrArr = new IntPtr[length];
                         for ( int i = 0; i < length; i++)
                        {
                                dataIntPtrArr[i] = Marshal.AllocHGlobal(data[i].Length * sizeof( byte));
                                Marshal.Copy(data[i], 0, dataIntPtrArr[i], data[i].Length);
                        }
                        IntPtr dataIntPtr = Marshal.AllocHGlobal(length * Marshal.SizeOf( typeof(IntPtr)));
                        Marshal.Copy(dataIntPtrArr, 0, dataIntPtr, length);
                         return dataIntPtr;
                }

                 //Dll动态导入    
                [DllImport( "libvlc")]
                 private static extern CoreHandle libvlc_new( int argc, IntPtr argv, ref ExceptionStruct ex);
        }
}
 
    补充二:本地存储。
    对libvlc_new的argv进行转码的主要目的就是为了进行本地存储,由于要将存储路径传入到argv中,所以要对中文的存储路径进行转码。下面的做法是将视频流默认存储为ts流,边播放边存储。
//avPath是本地存储路径,需要注意路径的/和/的问题。
argv = new string[] { "--sout=#duplicate{dst=display,dst=std{access=file,mux=ts,dst=" + avPath + "}}" };

//其他的就跟上一篇博客一样了。
core = new Core(argv, ref ex);
media = new Media(core.CoreHandle, link, ref ex);
player = new MediaPlayer(media.MediaHandle, ref ex);
player.Play( ref ex); //一面播放一面存储
   
    关于其他形式的argv,可以在vlc的存储里面获得。vlc -> 媒体 -> convert/save -> 转换/保存。根据选择不同的形式,在vlc界面的下半部分会有Generated stream output string。这个就是具体的argv。不过,请注意将:sout换成--sout。
 
参考网址:

写在这篇博客之后:

1. Jeremiah对vlc其实并不熟,我也不是vlc专家,视频服务器专家,呵呵,所以,有时候大家问我的问题,其实,我自己也很不明白,不能误导大家。但是我只要明白的,懂得的,都会毫不保留的跟大家交流。Jeremiah只是根据自己的业务需求来用vlc,当然,用vlc第一步就是要编译它。编译vlc花了我N多心血。其他的业务需求主要是借用vlc作一个自己的软解码器,播放网络H264流。所以,对vlc客户端的学习多一些,包括C#调用vlc接口,还有activex控件的相关内容。但是对vlc的服务器方面的应用掌握的不够多。Jeremiah略懂java,略懂C#,但是对C,C++,VC及控件等,非常不熟悉,所以,研习vlc代码,一直迟迟没有进行。
 
2. Jeremiah编译这几个版本的vlc,都是经过严格的测试,才发到博客上面的,而且,尽量的写的已经不能再详细的地步。所以,如果根据我的博客编译不成功,肯定是哪一步没有搞正确。如果每一步都搞正确了,最后还没有编译成功,我只能说RP到极点了。
 
3. 很多时候Google比Jeremiah好用许多。很多信息都会出现在官网的文档上。还有./configure -h和vlc -H这些命令也能提供很多资料,研习下这些资料,比Jeremiah直接告知,能学到更多的东西。
 
4. vlc研究群里面有N多高手,如果有问题得不到解决,去群里面忽悠忽悠吧。
 
5. vlc这个专题的文章,Jeremiah以后会继续发,但是由于本人能力有限,估计不会经常更新了。不过只要我学到了新的关于vlc的东西,我就会整理了发上来。也希望各位高手能能多多帮助我,多多提意见。
 
6. vlc的调用过程大体说一下,一般都是vlc界面或者activex或者自己写的程序->libvlc.dll->libcore.dll->plugins,所以,在进行相关调试的时候,这样的目录结构是不能变的,也就是libvlc.dll,libcore.dll,plugins目录是在一级目录下面,而不是一堆dll在一个目录下面。
 
7. 2009-03-11开通vlc中文论坛,地址为:http://bbs.dvbcn.com/vlc/
 
写得比较乱,先到此,以后想起什么,再补充。
vlc的应用之六:简单的视频点播系统(B/S)的实现
        前两天帮“猪小妹”考虑毕业设计的时候,想了想视频点播系统的该如何实现。在这写一下自己的想法和非常简单的实现方式,纯属娱乐,请勿拍砖。
 
        1. 大体的架构及流程
        实现视频点播系统,B/S架构,服务端至少应该是两个服务器:流媒体服务器,web服务器。客户端则就是web页面。当开启页面后则是客户端和服务器的第一次交互,通过http协议得到页面。里面会有流媒体地址的信息,浏览器里面点击显示视频组件,将流媒体的地址传给流媒体播放器,并启动播放器去请求视频。这是第二次交互。服务器端流媒体服务器发送流给客户端,页面上播放就okay了。
 
        2. 环境及所需软件
        Jeremiah的测试环境是xp sp2及IE8浏览器。IP地址:172.16.128.8. 与IP有关的地址,请根据个人情况自己改
        服务端:
        流媒体服务器先用个简单的:live555 Media Server(http://www.live555.com/mediaServer/windows/live555MediaServer.exe)
        Web服务器:Jeremiah以前学的JAVA,所以用Tomcat。IIS或者其他的Web服务器都可以。其实Jeremiah这个小系统用的是静态页面,所以如果是在本机测试的话,不用Web服务器也是okay的。模拟本地打开为Web浏览。
        客户端:vlc-0.9.4的Activex。需要把Activex注册好(参考http://jeremiah.blog.51cto.com/539865/115943
 
        3. 配置流媒体服务器
        下载完live555 Media Server之后放到d:/video下面,启动时会有以下信息:
"Play streams from this server using the URL
        rtsp://172.16.128.8/<filename>
where <filename> is a file present in the current directory."
并且后面还会有live555支持的视频格式。 本测试就用的mp3和ts格式。其他格式没有试验过。
        mp3好说,ts怎么得到呢?这时候vlc就出场了。vlc有转换保存功能,媒体->转换/保存->选择某个文件后点击转换/保存->流输出页面勾选本地播放,勾选文件并且浏览得到个文件名,注意后缀为ts而不是ps,方案封装选MPEG-TS,然后点击save。把你选择的视频播放一遍之后,ts格式的文件就生成好了。
        将生成好的ts文件和网上下载的mp3放到d:/video下面,本测试为01.ts及02.mp3。这样流媒体服务器就配置好了。
 
        4. web页面代码
        本web页面代码是vlc的Activex测试代码test.html上修改精简的。(没写注释,因为看着不难。)
vod.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
< html xmlns ="http://www.w3.org/1999/xhtml" >
< head >
< meta http-equiv ="Content-Type" content ="text/html; charset=UTF-8" />
< script >
var itemId = 0;
function getVLC(name)
{
        if (window.document[name])    
        {
                return window.document[name];
        }
        if (navigator.appName.indexOf("Microsoft Internet")==-1)
        {
                if (document.embeds && document.embeds[name])
                        return document.embeds[name];    
        }
        else
        {
                return document.getElementById(name);
        }
}

function doGo(mrl)
{
        var vlc = getVLC("vlc");
        itemId=vlc.playlist.add(mrl);
        vlc.playlist.playItem(itemId);
        document.getElementById("btn_stop").disabled = false;
}

function updateVolume(deltaVol)
{
        var vlc = getVLC("vlc");
        vlc.audio.volume += deltaVol;
}

function doPlay()
{
        vlc.playlist.playItem(itemId);
        
        document.getElementById("btn_stop").disabled = false;
        document.getElementById("btn_play").disabled = true;
}

function doStop()
{
        getVLC("vlc").playlist.stop();
        document.getElementById("btn_stop").disabled = true;
        document.getElementById("btn_play").disabled = false;
}
</script>
</head>
< body >
< div style ="margin: 50px" >
         < a title ="rtsp://172.16.128.8/01.ts" href ="#" onclick ="doGo(this.title);return false;" >01.ts </a>
         < span style ="margin: 20px;" />
         < a title ="rtsp://172.16.128.8/02.mp3" href ="#" onclick ="doGo(this.title);return false;" >02.mp3 </a>
         < span style ="margin: 20px;" />
</div>
< div >
        <object classid="clsid:9be31822-fdad-461b-ad51-be1d1c159921"
                width="640"
                height="480"
                id="vlc"
                events="true">
         < param name ="mrl" value="" />
         < param name ="showdisplay" value ="true" />
         < param name ="autoloop" value ="false" />
         < param name ="autoplay" value ="false" />
         < param name ="volume" value ="50" />
         < param name ="starttime" value ="0" />
        <embed pluginspage="http://www.videolan.org"
                     type="application/x-vlc-plugin"
                     version="videolan.vlcplugin.2"
                     width="640"
                     height="480"
                     name="vlc">
         </embed>
         </object>
</div>
< div >
< input type=button id ="btn_play" value =" 播放 " onClick ='doPlay();' disabled ="true" >
< input type=button id ="btn_stop" value ="停止" onClick ='doStop();' disabled ="true" >
< input type=button value ="静音切换" onclick ='getVLC("vlc").audio.togglemute();' >
< input type=button value ="减小音量" onclick ='updateVolume(-10)' >
< input type=button value ="增加音量" onclick ='updateVolume(+10)' >
</div>
</body>
</html>
将vod.html放置到Web服务器中。我就不多说了。so简单。
 
        5. 访问vod.html
        访问前请确保客户端Activex控件已注册成功。
        打开IE输入http://172.16.128.8:8080/vod/vod.html后访问到我们上面写的页面。然后点击01.ts超链接,在下面的vlc的Activex上就会显示视频了。这样,一个简单的点播系统就做好了。
请注意下面图片的视频上的地址。
 
        6. C/S架构的实现
        做成跟pplive类似的客户端,考虑与服务器的两次交流,第二次交流是没有问题的,关键在第一次交流上。如果客户端做成嵌入IE的方式,如C#的WebBrowser,则点击某个视频地址的信息模块,如超链接,无法将超链接的地址传给播放器组件了。Jeremiah考虑的解决的方法就是第一次与Web服务器的交流可以用xml来实现。客户端获取xml,然后解析,然后显示到某个组件里面,如C#的Listbox,这样点击这个组件就可以轻易的将视频地址传给播放器组件了。pplive的频道列表,估计就是用的这种方式。
vlc的应用之七:用vlc做单播,组播及点播服务器
    还是前两天帮“猪小妹”考虑毕业设计的时候,想了想vlc能不能作为vod的服务器,替代上一篇博客里面的live555 media server,因为live555 media server做的确实不是太好。查了些资料,在vlc群里面乱问了一通,终于解决了。好东西啊,大家共享。
    在这感谢vlc研究群“樱木”童鞋提供的帮助。
 
    1. 所需软件
    vlc-0.9.9或vlc-0.8.6i,主要测试的是比较新的0.9.9版本的。
    putty:一款集telnet,ssh远端登陆的非常好的软件。下载地址:http://wrc.gro.clinux.org/putty/putty.exe
 
    2. 命令行启动vlc,并打开后台信息显示,有助于观察后台信息
    开启cmd,并cd到vlc的目录,执行
vlc -vv --extraintf=logger
 
    3. 开启vlc的telnet服务
    vlc-0.9.9在界面上选择工具->界面->telnet控制台
    后台dos窗口会有反应,显示
[00000403] main interface debug: looking for interface module: 1 candidate
[00000403] main interface debug: creating VLM
[00000405] main vlm daemon debug: thread 5112 (vlm thread) created at priority 0
(../../src/input/vlm.c:112)
[00000405] main vlm daemon debug: thread started
[00000403] telnet interface: using the VLM interface plugin...
[00000403] main interface debug: net: listening to 127.0.0.1 port 4212
[00000403] telnet interface: telnet interface started on interface 127.0.0.1 421
2
[00000403] main interface debug: using interface module "telnet"
[00000403] main interface debug: TIMER module_Need() : 19.000 ms - Total 19.000
ms / 1 intvls (Avg 19.000 ms)
[00000403] main interface debug: thread 5136 (interface) created at priority 0 (
../../src/interface/interface.c:168)
[00000403] main interface debug: thread started
    注意观察main interface debug: net: listening to 127.0.0.1 port 4212这句话,说明vlc现在的telnet监听的是127.0.0.1这个地址和4212这个端口。如果没有显示ip的话,一般用127.0.0.1是没有问题的。127.0.0.1就表示的本机,与localhost是同一个意义。
 
    4. 启动putty.exe
    主机名称(或ip)输入:127.0.0.1
    端口:4212
    连接类型:选Telnet
    点打开。
    如果没有出现"Password:"字样,点打开就关闭了,那就说明没有telnet上。(这个时候可以在cmd里面输入telnet 127.0.0.1 4212,看结果应该是正在连接到127.0.0.1...不能打开到主机的连接, 在端口 4212: 连接失败,或者是与主机失去连接。不用cmd的telnet连接的主要原因是过会输入命令的时候看不到。)这个时候,请关闭防火墙,杀毒软件及一切相关软件,不过中毒了别找我哎。(*^__^*) 嘻嘻……继续继续。
    如果没有出现以上问题,在Password:后面输入"admin",没有明文回显。登录成功后会显示:Welcome, Master
 
    5. 架设点播服务vod
    分别输入:
new vod1 vod enabled
setup vod1 input d:/01.avi
    解释下:
    new了一个名字叫vod1的vod,设置vod1的input为d:/01.avi。
    验证:开启另一个vlc,打开rtsp://127.0.0.1/vod1。应该就可以播放了。127.0.0.1可以换成自己的ip。
 
    6. 架设组播服务器
    继续输入:
new ch1 broadcast enabled
setup ch1 input d:/02.avi [loop]
setup ch1 output #duplicate{dst=rtp{dst=226.0.0.6,mux=ts,port=1234}}
control ch1 play
    解释下:
    new了一个名字叫ch1的broadcast。设置ch1的input为d:/02.avi,loop可选,表示循环播放。设置ch1的output为#duplicate{dst=rtp{dst=226.0.0.6,mux=ts,port=1234}},表示rtp协议的ts流发送到组播地址为226.0.0.6,端口1234。控制ch1播放。
    扩充:
    1) output后面可以跟sout参数。具体可以参考vlc->媒体->流->流输出界面的已生成的流输出字符串。
    2) control ch1后面还可以加stop,pause,seek 百分比。表示停止,暂停和跳转到百分之几的位置。
    验证:开启一个vlc,打开rtp://226.0.0.6:1234。应该就可以播放了。
 
    7. 架设单播服务器
    第6步里面的output换成单播的地址就行了。其他的都一样的。注意不要new重名了。
 
    8. 保存刚才操作
    继续输入
save d:/01.cfg
    将刚才操作保存到了d:/01.cfg里面,除了control。可以通过记事本等文本编辑器查看一下里面的内容。
    如果重新开启了vlc,则可以输入
load d:/01.cfg
    将刚才保存的操作读入进来,继续操作或控制。
         
    通过这样的配置,一个vlc的实例可以提供多个服务,包括单播,组播和点播。确实强大啊。
    这样上一篇博客的流媒体服务器可以替换为vlc了。跟上一篇日志结合作个简单的流媒体服务的网站或者类似于pplive的客户端,就不是太有技术难度的事情了。
vlc的应用之八:MFC调用libvlc.dll
    本篇博客将简单介绍MFC调用libvlc.dll作一个简单的播放器,抛砖引玉,各位VC++达人继续深入研究,Jeremiah对VC++确实不太感兴趣,所以就不做太深入的研究了。
 
2009.10.29修改:加入clip_children属性设置。参考第1步。
2010.04.14修改:中文路径问题。参考第7步。
 
    环境:
        1) VC6 SP5
        2) vlc-0.9.9a

    0. 引言
    根据上一篇博客的研究,任何一个VC环境都可以调用MinGW/Gcc编译得到的libvlc.dll。VLC在编译打包之后(也就是执行完make package-win32-base),或者去官网下载zip包解压之后,或者是安装完VLC之后,在vlc-0.9.9a目录下有个sdk文件夹,里面又包含两个文件夹:include--头文件及lib--库。这些都是我们用MFC调用libvlc.dll所必须的。头文件没啥好说的,库里面的libvlc.dll.a及libvlccore.dll.a就是上一篇博客所说的静态库,我们分别手动改成libvlc.lib及libvlccore.lib就可以在VC环境中调用啦。下面简要说一下调用的过程,对各位VC++达人来说绝对是小菜一碟。
 
    1. 建立工程
    新建MFC AppWizard(exe)工程,名字为:MFCVLC。选择项目为Dialog based,点击完成。删除Dialog窗体上的所有的控件,包括“确定”、“取消”按钮及"TODO"静态文本。勾选窗口的clip_children属性,这样就会避免拖动、最大化最小化及全屏还原时找不到图像的缺陷。
   
    2. 画控件
    画四个控件,两个静态文本框,一个输入框,一个按钮。其中,第一个静态文本框修改Caption为“路径:”,第二个文本框为视频的显示区域,所以讲ID改为IDC_DISPLAY,Caption去掉。输入框关联一个变量,CString类型,命名为m_path。按钮的Caption改为“播放”,并为BN_CLICKED增加一个Function。在CMFCVLCdlg的构造方法中加入一下语句方便调试。
m_path = _T( "d:/01.avi"); // 输入常用的视频地址
 
   
    3. 拷贝vlc的相关库及头文件
    在资源管理器的MFCVLC工程目录下新建文件夹vlc,lib,将vlc-0.9.9a/sdk/include/vlc.h拷贝到MFCVLC工程目录下,将vlc-0.9.9a/sdk/include除了vlc.h之外的所有文件拷贝到vlc目录下,将vlc-0.9.9a/sdk/lib下的libvlc.dll.a及libvlccore.dll.a拷贝到lib下,并分别修改为libvlc.lib及libvlccore.lib。将vlc-0.9.9a目录下的libvlc.dll, libvlccore.dll, plugins目录拷贝到Debug目录下。如果有Cygwin环境,需要将stdint.h(/usr/include/stdint.h)这个头文件也拷贝到MFCVLC工程目录下。在VC6环境中FileView中新建文件夹及导入上述文件,最后入下图所示。
 
    4. 修改头文件
    1) 修改vlc.h,将所有的#include <***>改为 #include "***"
    2) 修改stdint.h,将所有的long long替换为__int64
    3) 修改libvlc_structures.h,#include <stdint.h>为#include "stdint.h"
 
 
    5. 编写代码
    在MFCVLCDlg.cpp中加入头文件导入。
#include "vlc.h"
 
    在button的onclick关联函数中加入代码:
void CMFCVLCDlg::OnButton1()    
{
   // TODO: Add your control notification handler code here
    char path[100];
    this->GetDlgItemText(IDC_EDIT1, path, 100);
    libvlc_exception_t ex;
    libvlc_exception_init(&ex);
     int vlc_argc = 0;
     char *vlc_argv[100];
    vlc_argv[vlc_argc++] = "--ignore-config";
    libvlc_instance_t *p_instance = libvlc_new(
          vlc_argc, vlc_argv, &ex);
    libvlc_media_t *p_media = libvlc_media_new(
          p_instance, path, &ex);
    libvlc_media_player_t *p_media_player    
        = libvlc_media_player_new_from_media(
            p_media, &ex);
    libvlc_drawable_t hwnd =    
        (libvlc_drawable_t) this->GetDlgItem(IDC_DISPLAY)->GetSafeHwnd();
    libvlc_media_player_set_drawable(p_media_player, hwnd, &ex);
    libvlc_media_player_play(p_media_player, &ex);
}

    6. 关联静态库及编译运行
    打开Project Setting,在link标签的Object/library modules:下输入 lib/libvlc.lib lib/libvlccore.lib
    build项目,应该没有错误。
    Execute Program就可以执行了。
 
    7. 两个BUG
    第6步执行的是Execute模式,如果是Debug模式,点击“播放”后,后台会显示加载的vlc的plugins的dll的信息,但是加载完最后一个dll的时候程序就Block住了。暂时不晓得为啥。经过更多的测试(win2003虚拟机里的vc6),发现Jeremiah的VC6可能真的有问题,debug的时候,打开Output窗口显示加载的dll的情况,就会block住。不打开Output窗口偶尔会set_drawable不成功,弹出新窗口。其他几位朋友测试则正常。
    上面的代码如果开带中文路径的地址会无法打开,因为传入的中文路径vlc识别不了。需要将路径也就是path变量从ANSIZ转换为UTF8代码。具体怎么转换,各位VC达人自己研究吧。
 
    8. 用VC6以上版本调试结果
    Jeremiah使用了vs2003及vs2005。
    1)  会两个重复定义的错误,解决方法是将stdint.h中注释掉:
#ifndef __intptr_t_defined
#define __intptr_t_defined
//typedef long intptr_t;
#endif
//typedef unsigned long uintptr_t;
    2) 发布Release版本会报内存错误。具体原因待查,应该是.lib不兼容的问题。不知道为啥Debug版就可以而Release版就不行。解决方法是用dll2lib.exe(附件提供)将0.9.9a的libvlc.dll及libvlccore.dll转换为相应的lib库,替换工程的lib/下面的相应的库,然后再次Release即可。

    Jeremiah对MFC只有一点点了解,所以上述的各个过程如果重复烦琐,及如何修复第7,8步讲的BUG及问题,请各位VC++达人指导Jeremiah。先谢过。本文附件中提供了MFCVLC的源码,只是需要把vlc-0.9.9a的libvlc.dll, libvlccore.dll, plugins目录拷贝到Debug目录下就可以编译执行。需要的自己下载添加调试。
vlc的应用之九:用vlc串流摄像头
    n就没有更新博客了,主要是Jeremiah最近对vlc研究的非常的少了,工作重点转移了,又增加了管理工作,让Jeremiah忙的晕头转向的。
 
    这篇博客是很久之前就想写的,今天终于提笔写了,心情还是比较爽的。废话不多说。
 
0. 环境搭建
Jeremiah这次主要是用的vlc-1.0.0(英文版)进行讲解。首先需要准备摄像头,Jeremiah用的是一个普通摄像头(以前钓MM用的,嘻嘻),驱动安装好后,在“我的电脑”中显示如下。
 
1. vlc播放摄像头
开启vlc-1.0.0,media->open capture device,进入Capture Device页面。这个也可以通过media->Advanced open file,选取此标签页。
video device name选择VIMICRO USB PC Camera (ZC0301PLH),如果没有,请先选择Refresh list刷新列表。
audio device name选择SoundMAX HD Audio,这个是Jeremiah的声卡。

之后可以勾选show more options,里面可是设置缓冲及看到MRL和Edit Options,这些信息都是很重要的。Advance Option按钮里面有一些详细设置,大家可以进去选择,其中video size是可以做调整的。下面会讲到。

之后点play,就可以播放了。
 
2. 用命令行开启vlc播放摄像头
命令行的最大好处就是,vlc命令后面的参数,就是我们在编程的时候调用libvlc_new的argv,将这些参数搞明白,我们就可以在编程的时候调用了。

开启cmd,切换到vlc目录下。

根据1中的MRL和Edit Options信息,设置vlc播放参数如下。
vlc dshow:// :dshow-vdev="VIMICRO USB PC Camera (ZC0301PLH)" :dshow-adev="SoundMAX HD Audio" :dshow-size=320*240
 
各个参数什么意思都是很明显的,如果不明白,就运行vlc -H,然后到vlc目录下面去找vlc-help.txt,里面是全部的参数的介绍。
 
3. 将vlc播放的摄像头信息存入文件中
播放成功之后,在达到我们的目的前,我们先做一个简单的验证工作,就是播放摄像头并存入文件。

根据以前stream到文件的参数,修改2的参数如下。
vlc dshow:// :dshow-vdev="VIMICRO USB PC Camera (ZC0301PLH)" :dshow-adev="SoundMAX HD udio" :dshow-size=320*240 :sout=#transcode{vcodec=h264,vb=800,scale=1,acodec=mp3,ab=128,channels=2,samplerate=44100}:std{access=file,mux=ts,dst=D:/01.ts}}
 
这里用到了转码,就是将摄像头的视频编码为h264,音频编码为MP3,然后封装为ts写入到d:/01.ts中。

这个不会显示摄像头,但是通过刷新d:/01.ts就会发现这个文件是在增大的,也就是有视频流在写入。
 
4. 将摄像头串流到网络中
根据3的参数做简单的修改就可以达到串流摄像头视频流到网络的目的了。修改3的参数如下。
vlc dshow:// :dshow-vdev="VIMICRO USB PC Camera (ZC0301PLH)" :dshow-adev="SoundMAX HD Audio" :dshow-size=320*240 :sout=#transcode{vcodec=h264,vb=800,scale=1,acodec=mp3,ab=128,channels=2,samplerate=44100}:duplicate{dst=display,dst=rtp{dst=127.0.0.1,mux=ts,port=1234}}
 
这里的duplicate大家应该都很熟悉了,因为在录像,vlm里面都讲过这个参数。参数的意思是,将摄像头的音视频流分别编码为MP3和h264之后封装为ts,然后通过rtp发送到127.0.0.1的1234端口上,同时显示出来。如果希望发送到其他网络地址或组播里面只需要改变127.0.0.1和1234为我们需要的地址和端口即可。

再开启一个vlc,播放这个ts over rtp流。
vlc rtp://@:1234 --rtp-caching=1500
 
成功后就可以看到了。切图如下:
 
左边的是摄像头的流服务,右边的是流的客户端,从下边的地址就能看的很清楚。
 
5. 遗留问题:
从图片可以看出,播放的视频颜色是不对的,是摄像头的问题还是vlc本身的问题还是参数设置的问题,现在不得而知,当然摄像头本身是没问题的,因为qq视频都很正常。希望谁研究出来告诉我一声。谢谢。
vlc的应用之十:vlc的远程控制

    VLC作为服务器,可以进行远程控制。再以前的博客中提到用telnet配置VLM(《vlc的应用之七:用vlc做单播,组播及点播服务器》),这也算是一种远程控制。这次介绍的远程控制主要包括以下两种,使用的是vlc-1.0.5。
1. http远程控制
2. vlc remote control (rc)

    1. vlc的http远程控制

    命令行执行以下命令。

      
      
  1. vlc -I http --http-host=localhost:8866 

    解释下:-I http就是启用http服务。--host-host=ip:port为启用的服务的ip地址及端口号。

    浏览器下输入http://localhost:8866,会显示如下界面。

    点击左上角的open按钮,打开input框。输入路径,点击play。出现视频画面。

    http模块在安装目录下面的http目录下面,通过解析index.html等,可以编写自己的web页面,并实现远程控制vlc的目的。在页面下方还有VLM的http配置,有兴趣的可以去好好研究下。

    注:如果要监听本机真实ip地址,让其他机器都能访问,则需要修改http目录下面的.host文件,配置相关private addresses。具体请根据自己ip地址进行配置。比如Jeremiah的ip地址为172.16.5.XXX,则只需要增加172.16.5.XXX/24,其他172.16.5段IP都可以访问了。

    2. vlc remote control

    命令行执行以下命令。

      
      
  1. vlc -I rc 

    出现vlc的rc后台。在里面输入help,打印出所有可以执行的命令。这些命令即为控制vlc的命令。如下图所示。

    输入add d:/video/01.avi,则开始播放视频。如下图所示。

    当然,我们也写程序远程控制vlc。主要思路就是建立一个socket,连接到vlc的rc服务,然后发送控制命令就可以了。

    1) 命令行运行以下命令。

      
      
  1. vlc -I rc --rc-host=localhost:8888 

    解释下:-I rc就是启动rc服务,--rc-host=ip:host就是监听的ip及端口号,一般ip设置为localhost。

    2) 编写程序client_vlc.c如下。

     
     
  1. /******************************************************************************  
  2. * Filename:        client_vlc.c   
  3. * Created on:      Apr 4, 2010    
  4. * Author:          jeremiah    
  5. * Description:     vlc的客户端程序,测试vlc远程控制  
  6. *    
  7. ******************************************************************************/ 
  8.  
  9. #include <stdio.h>  
  10. #include <stdlib.h>  
  11. #include <string.h>  
  12. #include <unistd.h>  
  13. #include <sys/socket.h>  
  14. #include <netinet/in.h>  
  15.  
  16. #define MAXLINE 4096  
  17. #define SERV_ADDR "127.0.0.1"  
  18. #define SERV_PORT 8888  
  19.  
  20. int main(int argc, char *argv[]) {  
  21.     struct sockaddr_in servaddr;  
  22.     char buf[MAXLINE];  
  23.     int sockfd;  
  24.     int read_size;  
  25.       
  26.     // 建立socket  
  27.     sockfd = socket(AF_INET, SOCK_STREAM, 0);  
  28.     bzero(&servaddr, sizeof(servaddr));  
  29.     servaddr.sin_family = AF_INET;  
  30.     inet_pton(AF_INET, SERV_ADDR, &servaddr.sin_addr);  
  31.     servaddr.sin_port = htons(SERV_PORT);  
  32.       
  33.     // 建立连接  
  34.     connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));  
  35.       
  36.     // 向vlc发请求 "add d:/video/01.avi"  
  37.     write(sockfd, "add d:/video/01.avi/r/n",   
  38.             strlen("add d:/video/01.avi/r/n") + 1);  
  39.       
  40.     // 打印vlc返回结果  
  41.     read_size = read(sockfd, buf, MAXLINE);  
  42.     printf("Response from vlc:/n");  
  43.     printf("%s/n", buf);  
  44.       
  45.     // 向vlc发请求 "is_playing"  
  46.     write(sockfd, "is_playing/r/n", strlen("is_playing/r/n"));  
  47.       
  48.     // 打印vlc返回结果  
  49.     read_size = read(sockfd, buf, MAXLINE);  
  50.     printf("Response from vlc:/n");  
  51.     printf("%s/n", buf);  
  52.       
  53.     // 关闭socket  
  54.     close(sockfd);  
  55.     return 0;  
  56. }  

    3) 编译上面的程序,本文主要在Cygwin里面编译使用。

     
     
  1. gcc -o client_vlc client_vlc.c 

    4)执行程序,查看结果。

 

    可以看到从服务器返回的字符串,显示添加成功,检查播放情况显示no error。关于其他的操作,还是参考上面的help的显示信息。

vlc的应用之十一:修改vlc的界面文字
   跟一个网友交流的时候,发现有这个需求,看着vlc的中文写的不爽,想要自己改改vlc界面的中文文字。经过几天的研究,找到了解决办法,记录在此。
 
    其实读取vlc的Makefile,在package-win32-common目标里面发现这几行代码:
# Copy the locales
                mkdir -p $(win32_destdir)/locale
                cat $(top_srcdir)/po/LINGUAS | while read i; do /
                    mkdir -p "$(win32_destdir)/locale/$${i}/LC_MESSAGES" ; /
                    cp "$(srcdir)/po/$${i}.gmo" /
                        "$(win32_destdir)/locale/$${i}/LC_MESSAGES/vlc.mo" /
                        || true ; /
                done
    可以看到其实locale文件夹下面的vlc.mo,是源码目录下面的po/zh_CN.gmo文件。
 
    读取源码下面对应的zh_CN.po文件发现,其实英文界面的每个相关的文字对应的中文,都是在这个po文件标示出来了。所以,如果要修改vlc的中文界面,修改这个zh_CN.po就可以了。但是要生成对应的gmo文件,却没有找到相关的命令。最后google了n天,找到了以下命令,在Cygwin下运行:
/usr/bin/msgfmt -c --statistics -o zh_CN.gmo zh_CN.po
 
    将生成好的zh_CN.gmo文件复制到vlc二进制目录的locale/zh_CN/LC_MESSAGES目录下,替换vlc.mo文件。然后重新启动vlc。
 
    Jeremiah修改了zh_CN.po文件的串流和vlc标题,具体的修改,去查找po文件的关键词,替换掉就okay了。效果图如下:
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值