61阅读

vlc播放器-基于VLC的播放器开发

发布时间:2018-03-19 所属栏目:Windows系列

一 : 基于VLC的播放器开发

VLC的C++封装

因为工作需要,研究了一段时间的播放器开发,如果从头开始做,可以学习下FFmpeg(http://www.ffmpeg.org/),很多播放器都是基于FFmpeg开发的,但是这样工作量和难度都比较大,如果想很快能拿出一个播放器来用的,可以研究下开源的播放器,参考下射手播放器作者的文章:媒体播放器三大底层架构。[www.61k.com)

对比下现有的主流播放器:媒体播放器列表,VLC是在各个方面都表现很突出的一款。VLC 是一款免费、自由、开源的跨平台多媒体播放器及框架,可播放大多数多媒体文件,DVD、音频 CD、VCD 以及各类流媒体协议。VLC官网:http://www.videolan.org/。

VLC是在Linux下用C语言开发的,如果想用其接口,可以将C的接口用C++封装一下,这样使用方便的很多,在CodeProject上搜到一个C++的封装,在他的基础上加了点函数,使用了最新的VLC版本(2.1.0),用MFC做成了如下的样子:

小红帽播放器 基于VLC的播放器开发

主要实现功能:

1、打开:加载音视频文件(同时开始播放)。

2、播放/暂停:播放暂停文件播放。

3、停止:停止播放。

4、快进:快进5秒。

5、快退:后退5秒。

6、音量:音量调节(0--100)。

7、播放进度控制:使用进度条控制。

基本上实现的功能和CodeProject上那个demo差不多,我修改后可以播放网络流媒体,将加载的文件名修改为流媒体地址就可以了。播放上面双语字幕的文件时貌似不能正常显示中文,VLC播放器本身也有这个问题,不过可以设置修改。其他更多的功能还有待研究,VLC的接口注释都很详细,按照它的接口应该可以实现更多的功能,有问题也可以直接在VideoLan的论坛上发帖问:

VLC的C#封装

如果播放器客户端使用的是.Net开发的,如何使用VLC?可以有以下几种方法:

1、ActiveX控件:可以将上述MFC的播放器封装成ActiveX控件提供给C#调用。鉴于业余时间有限,现在这部分工作还没做。

2、使用.Net的PInvoke技术将VLC的C接口封装成C#接口,这方面网上的文章也很多,具体可参考以下文章:

libvlc media player in C# (part 1)
http://www.helyar.net/2009/libvlc-media-player-in-c/

libvlc media player in C# (part 2)
http://www.helyar.net/2009/libvlc-media-player-in-c-part-2/

VideoLan DotNet for WinForm, WPF & Silverlight 5
https://vlcdotnet.codeplex.com/

nVLC
http://www.codeproject.com/Articles/109639/nVLC

c#万能视频播放器

这里还有一个Android下的VLC播放器开发:

源码下载

基于VLC的MFC播放器下载:http://download.csdn.net/detail/luxiaoxun/6671339

二 : VLC播放器终于支持Surface RT/Surface 2

IT之家讯在Win8.1《VLC》修正版推出后两天,VLC再次迎来更新,最终添加对Windows RT系统的支持,这意味着Surface RT和Surface 2平板用户,还有基于Windows RT系统的诺基亚Lumia2520用户将首次用上这款流行的播放器应用。[www.61k.com]

VLC VLC播放器终于支持Surface RT/Surface 2

该消息由开发者Thomas Nigro宣布,目前VLC将是Windows通用应用,支持Windows 8.1、Windows10、Windows RT和Windows Phone 8.1,本次更新会在Windows商店,大家请记得检查更新。

开发者Thomas Nigro也表示共享通用应用程序代码意味着,从现在开始,所有的Windows版本的更新将会加快,并同步推出。

Win8.1/Windows RT版VLC下载,点此链接。

(via:Windows Central)

扩展:surfacert和surface2 / vlc播放器官方下载 / vlc播放器

三 : vlc播放器架构

vlc播放器架构
2014播放器简述

包含内容
? 播放器的基本原理介绍 ? sk_media播放器介绍 ? vlc播放器基本架构介绍

一.播放器的基本原理介绍
? ? ? ? ? 一般情况下,播放一个音视频分为4个步骤: 1). acess 访问 2). demux 解复用 3). decode 解码 4). output 输出

acess :访问
? 可以理解为接收、获取、得到数据资源, 包括解析访问源(url)、使用http协议(ftp、 rtsp协议......)建立连接、获取数据等。

demux :解复用
? 就是把通常合在一起的音频和视频分离(还 有可能的字幕),通过分析数据包头来判断 是什么数据文件,需要用什么解码格式。

为什么需要demux
? 其实之所以需要demux,是因为音视频在 制作的时候实际上都是独立编码的,得到 的是分开的数据,为了传输方便必须要用 某种方式合起来,这就有了各种封装 格式, 也就有了demux。

decode 解码
? 包括音频和视频的解码,或者软件解码和硬 件解码。

output 输出
? 分为音频和视频的输出(aout和vout)

例如: 播放一个UDP组播的MPEG TS流

?

access部分负责从网络接收组播流, 放到播放器的内存缓冲区中,access模块 关注IP协议,如是否IPv6、组播地址、组播 协议、 端口等信息;如果检测出来是RTP 协议(RTP协议在UDP头部简单得加上了 固定12个字节的信息),还要分析RTP头 部信息。(对于VLC播放器,这部分可以参 看VLC源码 /modules/access/udp.c )。

? 而demux部分首先要解析TS流的信息。TS 格式是MPEG2协议的一部分,一般,TS通 常是固定188字节的一个packet,一个TS流 可以包含多个program(节目),一个 program又可以包含多个视频、音频、和文 字信息的ES流;每个ES流会有不同的PID 标示。而又为了可以分析这 些ES流,TS有 一些固定的PID用来间隔发送program和es 流信息的表格:PAT和PMT表。 ? 对于VLC播放器,使用库libdvbpsi来解析和 编码TS流.(调用代码可以参见VLC源码 /modules/demux/ts.c。)

? demux分解出来的音频和视频流分别送往音频解 码器和视频解码器。因为原始的音视频都是占用 大量空间,而且冗余度较高的数据,通常在制作 的时候就会进行 某种压缩。这就是我们熟知的音 视频编码格式,包括MPEG1(VCD)、MPEG2 (DVD)、MPEG4、H.264、rmvb等等。音视频 解码器的作用就是把这些压缩了的数据还原成原 始的音视频数据。(VLC解码MPEG2使用了一个 独立的库libmpeg2,调用它的源文件是 codec/libmpeg2.c。VLC关于编解码的模块都放 在/modules/codec目录下,其中包括著名的庞大 的 ffmpeg。)

? output模块,视频解码器输出的是一张一张 的类似位图格式的图像,但是要让人从屏 幕看得到,还需要一个视频输出的模块。 音频也

是一样,需要将pcm等数据转化为声 音

二.sk_media播放器介绍
? sk_media播放器使用开源软件vlc_2.1.0(后 面介绍)。 ? sk_media播放器的解码部分,mp3(mpga)格 式用软件解码,其它格式使用硬件解码, 以便加快解码速度。 ? sk_media播放器以插件的形式提供接口 (sk_media.h)给浏览器和应用,以达到平 台无关性。 ? sk_media.h是公司提供的统一的播放器对 外接口。

1.sk_media播放器使用流程图及 部分接口

?

2.简单的sk_media播放器demo
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? } static int main_media_test () { int ret; sk_media_t skplayer_service_data; char *url=NULL; int res; sk_media_init(NULL); ret = sk_media_create_player(&skplayer_service_data,NULL); url="http://192.168.11.193/HEAAC_128K_3sec.mp4"; sk_media_player_set_file(skplayer_service_data,0,2,url,url); ret = sk_media_player_start(skplayer_service_data, 0, 1, 0); Sleep(10); sk_media_player_stop(skplayer_service_data); sk_media_destroy_player(skplayer_service_data,NULL); sk_media_term(NULL);

三.vlc播放器基本架构介绍
? vlc(Video Lan Client)设计框架结构。vlc是一个完整的多 媒体框架 (如DirectShow或GStreamer的),最大特点 是可以根据需要动态加载许多插件模块,支持大量的音视 频传输、封装和编码格式。框架核心就是用程序将各模块 连接起来,对输入媒体数据 经过各模块处理后输出。

1.VLC 源代码结构

2.module功能模块目录树 VLC建立在很多独立的功能模块上面的,象 很多媒体播放器系统框 架一样,每个模块 实现一个新的功能

3.src模块目录介绍
? LibVLC是VLC的重要部分。它是一个提供接口的 库,比如给VLC提供功能接口:流的接入,音频和 视频输出,插件管理,线程系统。LibVLC源码位 于src/及其子目录: ? Interface/:包含与用户交互的代码如按键和设备弹 出。 ? Playlist/:管理播放列表的交互,如停止、播放、 暂停 、下一个,或者随机播放。 ? Input/:打开一个输入组件,读包,解析它们并且 将被还原的基本流传递给解码器。

? Video_output/:初始化video显示器,从解码器得 到所有的图片和子图片(如subtitles)。随意将它们 转换为其它格式(如:YUV到RGB)并且播放。 ? Audio_output/:初始化音频mixer(混合器)。如:发 现正确的播放频率,然后重新制作从解码器接收 过来的音频帧。 ? Stream_output/:类似Audio_output。 ? Misc/:被libvlc其它部分使用的杂项,如线程系统, 消息队列,CPU探测,对象查询系统,或者特定 平台代码。关于block_t结构 的一些功能也在其中 (block.c),包括队列的存放、删除等。(如果做本 地缓存可以考虑在block.c里处理)

4.vlc常用名词
? 容器 比较常见的容器格式包括AVI(.avi)、MPEG (.mpg, .mpeg)、QuickTim

e(.mov)、RealMedia (.rm)、MP4(.mp4)、Matroska(.mkv)、Ogg Media(.ogg)等

视频格式
? 常见的有:MPEG-1/2/4,divx,h.263, H.264 / MPEG-4 AVC, wmv, mov,

音频格式
? MPEG 1/2/3, AAC (MPEG4 part3), AC3 A/52 (Dolby Digital),WMA ,FLAC, Real Audio 2 , AMR (3GPP)

视频输出
? DirectX、X11、XVideo、SDL、 FrameBuffer、ASCII

访问输入
? UDP/RTP Unicast(单播),UDP/RTP Multicast(组播), ? TCP/RTP Unicast,DCCP/RTP Unicast, ? HTTP / FTP, MPEG encoder,Video acquisition(视频 采集) ? DVB,File

控制界面
? Gtk、QT4、Web、Telnet、Command line、 Lgui

字幕
? 文件内字幕,外挂字幕

5.数据处理流程框架
? VLC由一个运行核(libvlc)和很多功能模块组 成,很多功能都由模块提供. ? 在目前vlc设计框架的基础上,将vlc中使用 的demux模块, decoder模块, out模块, 置换 成目前硬件平台支持的硬件demux, decoder, out模块,从而使用硬件解码。 demux, decoder 探测部分使用开源的 ffmpeg 中的库文件。

vlc播放器的数据处理流程框图
access GUI页面 (qt4) 播放列表 playlist 本地文件 demux 解析容器 (Analysis container) decoder 硬件解码器 out 硬件视频 输出

网络文件(网 络下载协议) 消息管理 键盘鼠标 外设

探测解码器 Demux (软件或硬件)

软件解码器

硬件音频 输出

ffmpeg库,其 他插件库 外挂字幕等 subtitle

播放列表playlist
? 对gui 页面提供统一接口,使用vlc 统一接 口。

Access
? 网络或本地文件下载,移植vlc 支持的网络 下载协议。--http、tcp/udp、RTSP/RTP

demux
? 先按照给出的文件流类型,选择容器解析和 demux解析。若无文件流类型,则使用探测的方 式尝试。解析容器,使用软件ffmpeg提供的或其 他插件提供等。对于音视频加扰的流,使用软件 demux解码器可能会产生ca解扰问题,考虑使用 硬件demux,不在讨论范围内。 ? 软件解码依赖ffmpeg提供库或其他开放的源代码 解码器。针对ts 流的格式的文件,vlc使用软件 libdvbpsi 开源库。 ? 如果使用硬件demux, 对于decoder模块,hdi需要 提供独立操作的接口。

decoder
? 根据判断硬件支持情况,选择使用软硬件 解码器,视频都使用硬件解码器,有些独 立的音频播放可以使用软件解码器(mpeg audio layer 1/2/3 (mpga))。对于加扰的视 频需另外增加处理。 ? 软件解码依赖ffmpeg提供库或其他开放的 源代码解码器。 ? 如果使用软件decoder, 对于【www.61k.comout输出模块, hdi需要提供独立的音视频接口。

output
? 音视频模块,提供独立的可操作接口

subtitle 外挂字幕
? 软件解析后,直接发送至输出接口。

6.vlc调用内部接口运行过程

附:直接调用vlc上api播放音视频demo
? ? ? ? ? ? ? ? ? static void test_media_local(const char** argv,

int argc) { libvlc_media_t *md1, *md2, *md3, *md4; libvlc_instance_t *vlc; libvlc_media_t *md; libvlc_media_player_t *mp; const char * file0 = test_default_sample0;//file vlc = libvlc_new (argc, argv); md = libvlc_media_new_path (vlc, file0);

?
? ? ?

mp = libvlc_media_player_new_from_media (md);
libvlc_media_player_play (mp); sleep(100); }

1.首先程序调用libvlc_new(lib\core.c)接口,实现创建一个VLC运行实 例libvlc_instance_t,该实例在程序运行过程中唯一。 2.在libvlc_new接口中,调用了libvlc_InternalInit函数实现具体的初始化 工作. 3.libvlc_InternalInit(\src\libvlc.c)函数中,首先通过system_Init函数完 成传入参数对系统的相关初始化,接着通过module_InitBank (\src\modules\bank.c)函数初始化module_bank结构体,并创建了 main模块,然后通过module_InitStatic载入静态模块,通过 module_LoadPlugins(\src\modules\bank.c)函数载入动态模块. 4.调用libvlc_media_new_path接口,载入播放节目单. 5.在获取流时,通过调用stream_UrlNew(src\input\stream.c)函数完成 对access、demux和path的解析。最后调用stream_AccessNew (\src\input\stream.c)函数,创建stream_t结构体对象,并初始化对 象中所有函数指针;

6.再调用stream_Seek(\include\vlc_stream.h)内联函数,设置起始位 置 7.调用stream_Size(\include\vlc_stream.h)获得大小; 8.调用stream_Read(\include\vlc_stream.h),读取到缓冲区; 9.libvlc_media_player_play播放通过input_Create创建线程运行空间, input_Start中创建线程Run(\src\input\input.c) 10.Run线程是整个VLC作为流媒体服务器的核心。其主要分为如下几个 步骤:Init、MainLoop和End。其中MainLoop是一个无限循环,是完 成流媒体的整个发布过程: a.首先调用Init(\src\input\input.c)函数,初始化相关统计参数; b.其次再调用input_EsOutNew(\src\input\es_out.c)函数,初始化 es_out_t结构体对象和es_out_sys_t结构体对象,并设置相关函数指 针; c.再调用InputSourceInit(\src\input\input.c)函数,初始化 input_thread_t对象中的input_source_t对象,主要有access_t、 stream_t、demux_t三个结构体对象;

d.再调用MainLoop(\src\input\input.c)函数,完成读取、解复用、解码、 复用和传输; e.MainLoop函数为无限循环,直到input_thread_t对象存在b_die、 b_error、b_eof时为止。在该函数中,存在如下行代码: i_ret=p_input->input.p_demux->pf_demux(p_input->input.p_demux); 它就是流媒体服务器运行的起点,所有的后续操作都会在该函数中继续 衍生。 f.p f_demux调用的是(\modules\demux\ps)中的Demux函数,在该函 数中主要完成如下操作: 1).PS流中数据包重新同步 2).再调用ps_pkt_read(\modules\demux\ps.c)函数,最终调用 stream_Block函数,这个函数内部会根据实际情况,调用stream_t模 块中的pf_read

或pf_block函数,函数结果会返回一个读取的buffer; 3).根据数据包的i_code的值,做不同的处理,对于音视频数据流,调用 es_out_Send(\include\vlc_es_out.h)函数处理;

4.)es_out_Send一个抽象层函数,其通过函数指针,实际调用的是 EsOutSend(\src\input\es_out.c)函数; 5.)EsOutSend函数最终会调用input_DecoderDecode (\src\input\decoder.c)函数; 6.)input_DecoderDecode函数会将数据发送到音视频队列fifo; 7.)DecoderProcess里分别处理音视频的解码,硬件解码也可以在这里将 数据注入到硬件(hdi)接口中。 pf_demux函数为流媒体所有操作的起点,通过该处衍生了很多其他模块 的处理

VLC运行过程
? 在PC上运行时,vlc(exe)先被动态加载,然后主线程就 变成了接口 ? 线程并且在src/interface/interface.c中开始。 ? 它执行下列步骤:
? ? ? ? ? ? 1.cpu探测? 2.消息接口初始化; 3.命令行选项解析组件 4.创建播放列表 5.仓库初始化 6.加载所有内置和动态组件

? 7.打开接口 ? 8.安装信号处理器:SIGHUP,SIGINT和SIGQUIT(捕获一个,忽略后来 的并退出)。 ? 9.派生音频输出线程; ? 10.派生视频输出线程; ? 11.主循环:事件管理;

7.VLC组件结构和加载
? ? ? ? ? ? ? ? ? ? ? ? ? ? 组件位于modules\子目录,在运行时被加载。每一个组件提供不同的特征适应特定的文件的环境。 组件中的插件被位于src\misc\modules.c和include\modules*.h中的函数动态加载和卸载。组件的 API描述如下,共3种: (1)组件描述宏:声明组件具有哪种优先级的能力(接口,demux2等等),还有GUI组件的实现参数, 特定组件的配置变量,快捷方式,子组件等等; (2)Open(vlc_objeet_t*p_object): (3)Close(vlc_objeet_t*p_object): eg: vlc_module_begin () set_shortname( "Matroska" ) set_description( N_("Matroska stream demuxer" ) ) set_capability( "demux", 50 ) set_callbacks( Open, Close ) set_category( CAT_INPUT ) set_subcategory( SUBCAT_INPUT_DEMUX ) vlc_module_end ()

说明: 1.vlc注册模块用的是一套标准模板,组件名“Matroska",_("")可以用来创建需 要翻译的字符串,类型"demux"。 set_capability的50参数表示该插件的优先级,越大越可能被使用,如果是0 的话就不会自动使用,只能手动强制使用。如果VLC需要装载某一类型的功 能模块(如解码器),VLC将装载所有的具有该能力的模块,按照匹配分数降序 排列,然后调用Open()函数,如果返回VLC_SUCCESS,结束。 set_callbacks( Open, Close ),这个很关键,其实是告诉vlc开始播放的时候 调用Open,结束播放的时候调用Close。 2.消息映射宏 vlc_module_begin(); ………………….. vlc_module_end(); 3.配置分类包括: CAT_INTERFACE CAT_AUDIO CAT_VIDEO CAT_INPUT CAT_SOUT CAT_ADVANCED CAT_PLAYLIST

?

同时,也

可以使用某一个子类进行配置。所有的配置分类和子类的定义,参考 include/vlc_config_cat.h include/vlc_configuration.h (2)static int Open ( vlc_object_t * ); VLC运行核尝试打开模块的时候,将调用该函数,进行模块装载。 在Open函数里面,设置各种结构,设备或I/O。可以正常打开的函数将返回 VLC_SUCCESS。否则,将认为装载失败。 Open函数里面还进行私有数据的分配(如有),对私有结构进行设置。如果打开失败, 需要用户自己清理结构里面的资源。 被VLC调用初始化这个组件,它被组件描述宏赋值给了结构体module_t中的pf_activate 函数指针,被Module_Need调用; Open里面主要的工作就是设置另外几个回调函数以及绑定上面定义的私有数据结构, 设置回调函数(如control)、绑定私有数据等: p_demux->pf_demux = Demux; p_demux->pf_control = Control;

? ? ? ? ?

? ? ?

? (3)static int Close ( vlc_object_t * ) VLC运行核尝试关闭或卸载模块的时候,调用 Close函数。 在关闭函数里面,将清理一些数据结构,I/O或设 备。同时,关闭函数也释放一些私有数据。 Close比较简单,主要工作是释放自己的私有数据 被VLC调用负初始化这个组件,保证消耗Open分 配的所有资源。它被组件描述宏赋值给了结构体 module_t中的pf_deactivate函数指针,被 Module_Unneed调用。 (4)用LibVLC写的组件能够直接被编译进VLC, 因为有的OS不支持动态加载代码。被静态编译进 VLC的组件叫做内置组件。

? (5)模块类型 ? 根据模块的能力的类别不同,需要实现的函数或 方法也不一样,用户可以在相应的模块分类里面 找到更多的信息。下面是一些主要的模块类别清 单: ? Access/获取 ? Demux/解复 ? Access_Demux / 获取并解复 ? Decoder/解码 ? Interface/用户界面 ? Videofilter / 视频滤波 ? Audi ofilter /音频滤波 ? Audio output /语音输出

8.vlc组建仓库功能函数
? 在启动的时候,VLC创建一个包含所有插件接口 (.so和内置插件)的仓库,每一个插件都会被检查 其实现的功能(见vlc_modules.h) ? 管理这些插件的API如下: ? Module_InitBank:创建组件仓库,然后调用 module_LoadMain将主程序信息导入组件银行。 ? Module_LoadMain:将主程序信息导入组件仓库。 ? Module_LoadBulltins:加载所有内置组件。 ? Module_Loadplugins:加载所有动态组件。

? Module_EndBank:清空组件仓库。 ? Module_ReSetBank:通过卸载所有无用的 动态(插件)组件,重置组件仓库。 ? Module_EndBank:卸载所有动态(插件)组件, 清空模仓库。 ? Module_Need:得到能力最符合要求的组件。 ? Module_Unneed:减少一个组件的引用计数, 必须被Module_Need的同一个线程调用。

9.数据访问模块(access)
? access数据访问的输入和输

出函数实现VLC大部分的基本 IO功能。这些通常是一些协议如 (http,ftp,...)或一些设备访 问如网络摄像头,图像采集卡。 ? set_capability( "access", 60 ) set_category( CAT_INPUT ) set_subcategory( SUBCAT_INPUT_ACCESS ) 结构定义: ? ssize_t (*pf_read) ( access_t *, uint8_t *, size_t ); ? block_t *(*pf_block)( access_t * ); ? int (*pf_seek) ( access_t *, uint64_t ); ? int (*pf_control)( access_t *, int i_query, va_list args);

? 如果采用的协议返回未知大小的数据块, Block类型比较合适。 ? 如果能够控制给采用的协议的数据大小, Read类型比较合适. ? 实现的函数 ? 除了实现Open() 和Close()函数以外,还需 要实现几个主要的数据访问类模块的函数。 在include/vlc_access.h定义了下面几个函 数: ? Seek, pf_seek 指针指向的函数。 ? Control, pf_control 指针指向的函数。

? Seek ? 原型:int (*pf_seek) ( access_t *, uint64_t ); ? 数据位置定位函数可以根据请求随时调用。该函 数的参数为模块指针和请求的位置。 ? 注意:如果制定的协议或设备不支持数据位置定位 功能,该可以为空。如果函数正常工作,需要将 p_access->info.b_eof设置为false. ? 返回值: ? 如果函数运行成功,返回VLC_SUCCESS,否则, 返回VLC_EGENERIC.

? ? ? ? ?

? ? ? ? ? ? ? ? ?

Control 原型:int (*pf_control)( access_t *, int i_query, va_list arhttp://www.61k.comgs); 控制函数非常简单,运行核将使用下面的参数对模块进行查询: 指向模块结构的指针。 i_query参数可以有几种类型,args,根据i_query的类型,通过列表 输入一些子参数。 返回值: 如果运行成功,返回VLC_SUCCESS.否则,返回VLC_EGENERIC. 控制查询类型 下面的标记必须设置为true. ACCESS_CAN_SEEK, ACCESS_CAN_FASTSEEK, ACCESS_CAN_PAUSE, ACCESS_CAN_CONTROL_PACE, ACCESS_GET_PTS_DELAY

? Read 原型:ssize_t (*pf_read) ( access_t *, uint8_t *, size_t ); ? 返回值: 如果还没有数据,返回 -1;如果数据已经读取完 毕,返回0;否则,返回实际读取到的数据大小。 ? Block 原型: block_t *(*pf_block)( access_t * ); 返回原始大小的数据块,如果没有数据或到数据 末尾,将返回NULL。没有数据和已经到达数据末 尾的区别是,在到达数据末尾的时候,p_access>info.b_eof应该为true.

VLC线程分析

vlc线程管理
? VLC是一个密集的多线程应用。由于解码器 必须预先清空,播放工序也必须预先做好 流程(比如说解码器和输出必须被分开使用, 否则无法保证在要求的时间里播放文件), 因此VLC不采用单线程方法。目前不支持单 线程的客户端,多线程的解码器通常就意 味着更多的开销(各线程共享内存的问题等), 进程间的通信也会比较复杂。

? VLC的线程结构基于pthreads线程模型。为 了可移植的目的,没

有直接使用pthreads函 数,而是做了一系列类似的包裹函数: ? vlc_thread_create,vlc_thread_exit, vlc_thread_join,vlc_mutex_init, vlc_mutex_lock,vlc_mutex_unlock, vlc_mutex_destroy,vlc_cond_init,

? vlc_cond_signal,vlc_cond_broadcast, vlc_cond_wait,vlc_cond_destroy和类似 结构:vlc_thread_t,vlc_mutex_t,and vlc_co nd_t。

vlc线程同步
? VLC的另一个关键特征就是解码和播放是异步的:解码由一 个解码器线程工作,播放由音频输出线程或者视频输出线 程工作。这个设计的主要目的是不会阻塞任何解码器线程, 能够及时播放正确的音频帧或者视频帧。这样实现也导致 产生了在接口,输入,解码器和输出之间的一个复杂的通 讯结构。 ? 虽然当前接口并不允许,但是让若干个输入和视频输出线 程在同一时刻读取多个文件是可行的(这是VLC未来改进 的主要方向)。现在的客户端就是用这种思想实现的,这 就意味着如果没有用到全局锁的话那么一个不能重入的库 是不能被使用的(尤其是liba52库)。

? VLC输出的流里包含时间戳,被传递给解码器, 所有有时间戳标记的流也均被记录,这样输出层 可以正确及时的播放这些流。(时间mtime_t是一 个有符号的64-bit整形变量,单位是百万分之一秒, 是从1970年7月1日以来的绝对时间。) ? 当前时间能够被mdate()函数恢复。一个线程可以 被阻塞到mwait(mtime_t date)等到一个确定的时 间才被执行。也可以用msleep(mtime_t delay)休 眠一段时间。如果有重要的事情要处理的话,那 么应该在正常时间到来之前被唤醒。

vlc消息接口
? 由于printf()函数不是线程安全的,因此在调用printf()函数时一个线程 的执行将会受到干扰,当这个线程被另一个函数所调用时就会其状态 被破坏而退出程序。所以VLC构造了自己的线程安全的消息接口。 ? VLC的线程安全的消息接口有两种实现方式:如果在config.h里定义了 INTF_MSG_QUEUE的话,每一个类似printf()的函数将会把排队的消 息放到链表里,这个链表将会在事件循环中被线程接口用红色标记的 方式打印出来。如果INTF_MSG_QUEUE没被定义的话,调用线程将 会获得一个print lock(用来防止在同一时刻有两个printf操作被执行)同 时直接打印出消息(默认操作)。 ? 以下为VLC线程安全消息的API: ? QueueMsg:添加一条消息到消息队列,如果消息队列满了,先打印所 有的消息; ? SKMSG_DBG:skmedia里打印所有在消息队列里的消息,特别的,消息 队列必须被提前加锁,因为该函数不检查锁。

一些常见的音视频问题
? ? ? ? ? ? ? ? ? ? 1.无效的视频源,无法访问 (SK_MEDIA_EVT_INVALID_BAD_CONTENT)。 2.不支持的编解码格式. (SK_MEDIA_EVT_INVALID_AUDIO_FORMAT或者 SK_ME

DIA_EVT_INVALID_VIDEO_FORMAT) 3.内存不足。(out of memory) 4.音频卡顿。 5.视频卡 6.音视频没播放完就停止。 7.音视频不同步。 8.获取不到总时间

? ? ? ? ? ?

9.时间显示不正确,seek时跳转位置不对。 10.死锁 11.多音轨时切换不出来 12.字幕显示问题 13. 开启速度太慢问题。(plugins.dat) 14.插件库太大,没法烧机问题.


四 : Win10 Mobile版VLC视频播放器内测中 批量截图曝光

在今年5月底,61阅读曾报道 Win10 UWP版《VLC》封闭内测中,像Win32版本一样强悍的消息,并且可能将优先推出Win10 Mobile版。现在外媒已经曝光了Win10 Mobile版《VLC》应用的大量截图。

Windows 10 Mobile版VLC视频播放器相比之前WP8.1版本,最大改变就是界面UI全面更新,核心功能升级,包括UPnP和浏览网络共享,支持HTTPS、自适应流媒体传输、更好的硬件解码,并且支持尽可能多的桌面解码。

不过根据外媒消息,目前Win10 Mobile版VLC视频播放器还存在一些Bug,仍在封闭测试中,希望正式版尽快登陆Windows10应用商店。

下面是Win10手机版VLC曝光截图:

本文标题:vlc播放器-基于VLC的播放器开发
本文地址: http://www.61k.com/1158757.html

61阅读| 精彩专题| 最新文章| 热门文章| 苏ICP备13036349号-1