本文来自于:http://blog.csdn.net/leixiaohua1020/article/details/42363079

最简单的基于libVLC的例子:最简单的基于libVLC的视频播放器

本文记录使用libVLC的开发的最简单的视频播放器示例。VLC Media Player是一款优秀的播放器,但是由于它的源代码编译的难度比较大,一直没有深入研究过它的开发方面的技术。此前触到了一些VLC开发方面的东西,因 此总结了一下libVLC的开发示例程序。

如何获取VLC的SDK

VLC开发所需的库文件可以有2种获取方法:

1.    自行编译
2.    直接从安装目录里面拷贝出来

第一种方法难度要大一些。尤其是在Windows下编译VLC是个比较麻烦的事情。一般情况下可以选择第二种方法获取VLC开发所需的文件。
开发VLC所需的文件的位置:

1.    动态链接库*.dll:安装目录下的libvlc.dll,libvlccore.dll以及plugins目录下的所有文件。
PS:VLC支持非常多的plugin。因此plugins目录的体积确实是非常大的。
2.    静态链接库*.lib:安装目录/sdk/lib
3.    头文件*.h:安装目录/sdk/include

新建一个VC工程后,把上述三类文件分别拷贝至新工程目录下,并且配置它们的路径之后,就可以使用libVLC进行开发了。

最简单的基于libVLC的视频播放器

使用libVLC开发一个播放器十分的容易。最简单的基于libVLC的视频播放器的流程图如下图所示。

流程图中包含了3个结构体:

libvlc_instance_t:代表一个libVLC的实例。
libvlc_media_t:代表一个可以播放的媒体。
libvlc_media_player_t:代表一个VLC媒体播放器(一个视频播放器播放一个视频)。注意VLC并不仅仅用于媒体播放。

创建或者以上3个结构体通过以下6个函数:

libvlc_new():创建libvlc_instance_t。
libvlc_media_new_path():创建libvlc_media_t。
libvlc_media_player_new_from_media():创建libvlc_media_player_t。
libvlc_media_player_release():释放libvlc_media_player_t
libvlc_media_release():释放libvlc_media_t。
libvlc_release():释放libvlc_instance_t。

可以已通过下面的函数控制媒体的播放或者暂停,这些函数都需要使用libvlc_media_player_t作为参数。这里处于简化的目的,只使用了播放和停止函数:

libvlc_media_player_play():播放。
libvlc_media_player_pause():暂停。
libvlc_media_player_stop():停止。

除了上述3个函数之外,还包括libvlc_media_player_set_position()等函数,这里不再一一记录。

几点注意事项

libvlc_media_t的创建

创 建libvlc_media_t有两种方法:libvlc_media_new_path()和 libvlc_media_new_location()。简单描述一下这两个函数的区别:libvlc_media_new_location()用于 打开协议,而libvlc_media_new_path()用于打开文件。因而传递给libvlc_media_new_path()的就是普通的文件 路径(绝对路径例如D:\xxx.flv,或者相对路径例如xxx.flv),而传递给libvlc_media_new_location()的就是协 议地址(例如"udp://….","http://")。但是这里有一点需要注意,在VLC中"文件"也属于一种广义上的"协议"。因此使用 libvlc_media_new_location()也可以打开文件,但是必须在文件路径前面加上"文件协议"的标记"file:///"。例如打开 "F:\movie\cuc_ieschool.flv"下的视频,实际使用的代码如下所示。

libvlc_media_new_location (inst, "file:///F:\\movie\\cuc_ieschool.flv");

此外,VLC还支持很多"神奇"的协议,比如输入"screen://"协议就可以进行屏幕录制,代码如下。

libvlc_media_new_location (inst, "screen://");

把libVLC的弹出窗口嵌入到程序中

在这里我只实践过Windows下把libVLC的弹出窗口嵌入到程序中。将窗口或者控件的句柄传递给libvlc_media_player_set_hwnd()函数即可。
这里有一点需要注意,如果把libVLC弹出窗口嵌入到程序中的话,"全屏"功能就不能使用了。

关于libVLC加载的问题

在 libVLC中可以通过 libvlc_media_player_get_length(),libvlc_video_get_width(),libvlc_video_get_height() 等函数获取到视频的时长,宽,高等信息。但是有一个很奇怪的现象:如果在调用完libvlc_media_player_play()之后立即调用上述3 个函数的话,返回的值都是0,只有"等待"一段时间(例如调用sleep())后再调用上述函数,才能得到正确的数值。对于这种现象,我觉得可能是 libVLC加载完成之后,才能通过上述几个函数获得正确的值(自己推测的,还没有深究)。

 #include <Windows.h>
 #include "vlc/vlc.h"
 int main(int argc, char* argv[])
 {
 libvlc_instance_t * inst;
 libvlc_media_player_t *mp;
 libvlc_media_t *m;

 libvlc_time_t length;
 int width;
 int height;
 int wait_time=;

 //libvlc_time_t length;

 /* Load the VLC engine */
 inst = libvlc_new (, NULL);

 //Create a new item
 //Method 1:
 //m = libvlc_media_new_location (inst, "file:///F:\\movie\\cuc_ieschool.flv");
 //Screen Capture
 //m = libvlc_media_new_location (inst, "screen://");
 //Method 2:
 m = libvlc_media_new_path (inst, "cuc_ieschool.flv");

 /* Create a media player playing environement */
 mp = libvlc_media_player_new_from_media (m);


 /* No need to keep the media now */
 libvlc_media_release (m);

 // play the media_player
 libvlc_media_player_play (mp);

 //wait until the tracks are created
 _sleep (wait_time);
 length = libvlc_media_player_get_length(mp);
 width = libvlc_video_get_width(mp);
 height = libvlc_video_get_height(mp);
 printf("Stream Duration: %ds\n",length/);
 printf("Resolution: %d x %d\n",width,height);
 //Let it play
 _sleep (length-wait_time);

 // Stop playing
 libvlc_media_player_stop (mp);

 // Free the media_player
 libvlc_media_player_release (mp);

 libvlc_release (inst);

 return ;
 }

最简单的基于libVLC的例子:最简单的基于libVLC的视频播放器(图形界面版)

本文记录使用libVLC开发的一个简单的图形界面的视频播放器。由于是示例程序,只包含了最简单的媒体播放方面的功能。其中有一些功能还不完善,有时间以后再做修改。

最简单的基于libVLC的视频播放器(图形界面版)

这 是使用libVLC基于MFC开发的一个示例播放器。实现了一个播放器的基本功能:播放,暂停/继续,停止,播放时间轴的显示,以及从任一点开始播放媒 体。并且支持将媒体文件拖拽至播放器进行播放。播放前将媒体文件的路径输入到"URL"栏中,然后单击"Start"即可开始播放。

播放时候的效果截图如下所示。

源代码比较长,不再详细记录。简单记录一下其中几个主要功能的实现机制。

视频的播放/暂停/继续/停止

播放

视频"播放"的源代码如下所示。简单来说,完成了以下视频播放的初始化工作:
(1)    输入的URL转换为UTF-8编码(后文详细记录)

(2)    将显示视频画面的控件的句柄提供给libVLC

(3)    初始化libVLC并开始播放

(4)    开启定时器,用于更新视频播放的进度(后文详细记录)

void CplayerGUIDlg::OnBnClickedStart()
{
CStringW cstr_url; #ifdef _UNICODE
m_url.GetWindowText(cstr_url);
#else
USES_CONVERSION;
CStringA cstr_urla;
m_url.GetWindowText(cstr_urla);
cstr_url.Format(L"%s",A2W(cstr_urla));
#endif std::string str_url;
UNICODE_to_UTF8(cstr_url, str_url);
const char *char_url=str_url.c_str(); if(strcmp(char_url,"")==){
AfxMessageBox(_T("Input URL is NULL!"));
return;
} HWND screen_hwnd=NULL;
screen_hwnd = this->GetDlgItem(IDC_SCREEN)->m_hWnd; if(playerstate!=STATE_PREPARE){
AfxMessageBox(_T("Media is playing now."));
return;
} /* Create a new item */
//m = libvlc_media_new_location (libvlc_inst, "http://mycool.movie.com/test.mov"); libvlc_m = libvlc_media_new_path (libvlc_inst, char_url); /* Create a media player playing environement */
libvlc_mp = libvlc_media_player_new_from_media (libvlc_m); /* No need to keep the media now */
libvlc_media_release (libvlc_m); //on windows
libvlc_media_player_set_hwnd (libvlc_mp,screen_hwnd); /* play the media_player */
int x=libvlc_media_player_play (libvlc_mp); //_sleep (30000); /* Let it play a bit */ playerstate=STATE_PLAY;
SetBtn(STATE_PLAY);
SetTimer(,,NULL);
}

暂停/继续

视频"暂停/继续"的源代码如下所示。其中调用了libvlc_media_player_set_pause()设定"暂停"或者是"继续"。

void CplayerGUIDlg::OnBnClickedPause()
{
if(playerstate==STATE_PLAY){
libvlc_media_player_set_pause(libvlc_mp,);
playerstate=STATE_PAUSE;
GetDlgItem(ID_PAUSE)->SetWindowText(_T("Resume"));
}else if(playerstate==STATE_PAUSE){
libvlc_media_player_set_pause(libvlc_mp,);
playerstate=STATE_PLAY;
GetDlgItem(ID_PAUSE)->SetWindowText(_T("Pause"));
}
}

停止

视频"停止"的源代码如下所示。其中调用了libvlc_media_player_stop()停止视频播放,并且调用libvlc_media_player_release()释放相应的libvlc_media_player_t结构体。

void CplayerGUIDlg::OnBnClickedStop()
{
if(libvlc_mp!=NULL){
libvlc_media_player_stop (libvlc_mp);
libvlc_media_player_release (libvlc_mp);
KillTimer();
} SystemClear();
}

视频播放进度杂时间轴的显示

随着视频的播放,需要在视频播放进度的时间轴上更新播放进度信息。在程序中使用了一个定时器完成这个功能。
在视频开始播放的时候,调用SetTimer()开启定时器。时间间隔设置为1000ms。

SetTimer(,,NULL);

在视频停止播放的时候,调用KillTimer()结束定时器。

KillTimer();

在定时器的消息响应函数中,调用libvlc_media_player_get_time()获取当前视频的播放进度,此外调用libvlc_media_player_get_length()获取视频的总时长。
经过计算之后,就可以把计算的结果设置到相应的编辑框(Edit Control)以及滑动控制条(Slider Control)上。

void CplayerGUIDlg::OnTimer(UINT_PTR nIDEvent)
{
if (nIDEvent == ){
CString curtimestr,durationstr;
int curtime;
int duration;
int tns, thh, tmm, tss;
int progress;
//ms
curtime = libvlc_media_player_get_time(libvlc_mp);
if(curtime!=){
//change to second
tns = curtime/;
thh = tns / ;
tmm = (tns % ) / ;
tss = (tns % );
curtimestr.Format(_T("%02d:%02d:%02d"),thh,tmm,tss);
m_curtime.SetWindowText(curtimestr);
}
duration = libvlc_media_player_get_length(libvlc_mp);
if(duration!=){
tns = duration/;
thh = tns / ;
tmm = (tns % ) / ;
tss = (tns % );
durationstr.Format(_T("%02d:%02d:%02d"),thh,tmm,tss);
m_duration.SetWindowText(durationstr); progress=curtime*/duration;
m_progress.SetPos(progress);
}
} //Stop in the end
if(libvlc_media_player_get_state(libvlc_mp)==libvlc_Ended)
OnBnClickedStop(); CDialogEx::OnTimer(nIDEvent);
}

视频播放点的调整

当鼠标拖动滑动控制条(Slider Control)控件上的滑块的时候,需要根据拖动的位置设置视频的播放进度。此时调用libvlc_media_player_set_position()设定视频的播放进度。消息响应函数中的代码如下所示。

void CplayerGUIDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
if (pScrollBar->GetSafeHwnd() == m_progress.GetSafeHwnd()){
float posf=0.0;
if(nSBCode==SB_THUMBPOSITION){
posf=(float)nPos/100.0;
libvlc_media_player_set_position(libvlc_mp,posf);
}
}
CDialogEx::OnHScroll(nSBCode, nPos, pScrollBar);
}

libVLC中输入中文文件路径问题

libVLC 使用英文作为输入路径的时候是没有问题的。但是当我们直接传递中文路径的时候,会出现libVLC将中文解析为乱码从而导致无法播放的问题。这个问题卡了 我一阵子时间。造成这一问题的原因在于VLC的输入文件路径是使用UTF-8编码的。因此我们需要将输入路径转码为UTF-8编码。转码之后这一问题即得 到了解决。

Unicode转码为UTF-8的函数代码如下所示。

void CplayerGUIDlg::UNICODE_to_UTF8(CStringW& unicodeString, std::string& str)
{
int stringLength = ::WideCharToMultiByte(CP_UTF8, NULL, unicodeString, wcslen(unicodeString), NULL, , NULL, NULL); char* buffer = new char[stringLength + ];
::WideCharToMultiByte(CP_UTF8, NULL, unicodeString, wcslen(unicodeString), buffer, stringLength, NULL, NULL);
buffer[stringLength] = '\0'; str = buffer; delete[] buffer;
}

最简单的基于libVLC的例子:最简单的基于libVLC的推流器

本文记录基于libVLC的最简单的推流器。该推流器可以将本地的视频文件转码后推送至目标流媒体服务器(也可以是一个组播地址)。

最简单的基于libVLC的推流器

该推流器的代码十分简单,只用到了几个函数:

libvlc_new():创建libvlc_instance_t。
libvlc_vlm_add_broadcast():增加一个广播(broadcast)。

libvlc_vlm_play_media():播放指定名称的广播(broadcast)。

libvlc_vlm_stop_media():停止指定名称的广播(broadcast)。

libvlc_vlm_release():释放ibvlc_instance_t。

本示例的输入视频文件为"cuc_ieschool.flv"。这个推流器实现了:

  • 输入视频转码为H.264
  • 音频转码为mp2
  • 封装格式设置为MPEG-TS
  • 以UDP的形式发送至组播地址"udp://233.233.233.233:6666"

在程序发送广播的同时,会弹出一个窗口显示当前正在发送的视频。

#include <Windows.h>
#include "vlc/vlc.h" int main(int argc, char **argv) {
libvlc_instance_t *vlc;
const char *url;
//Send File
//Transcode it. Video codec use x264. Audio codec use mpga.
//Mux it to mpegts format.
//And stream it to udp://233.233.233.233:6666
/*
const char *sout = "#transcode{vcodec=h264,fps=25,venc=x264{preset=ultrafast,"\
"profile=main,tune=zerolatency},vb=512,scale=0.5," \
"acodec=mpa,aenc=ffmpeg,ab=64,channels=2}" \
":standard{access=udp,mux=ts,dst=233.233.233.233:6666}";
*/
//Send and playing at same time
const char *sout = "#transcode{vcodec=h264,fps=25,venc=x264{preset=ultrafast,"\
"profile=baseline,tune=zerolatency},vb=512," \
"acodec=mpga,ab=64,channels=2}" \
":duplicate{dst=display,dst=standard{access=udp,mux=ts,dst=233.233.233.233:6666}}";
const char *media_name = "Lei's test"; //Screen Capture
//url = "screen://"; url = "cuc_ieschool.flv"; vlc = libvlc_new(, NULL);
libvlc_vlm_add_broadcast(vlc, media_name, url, sout, , NULL, true, false);
libvlc_vlm_play_media(vlc, media_name); //play 30s
_sleep(); libvlc_vlm_stop_media(vlc, media_name);
libvlc_vlm_release(vlc);
return ;
}

基于libVLC的视频播放器的更多相关文章

  1. 最简单的基于libVLC的例子:最简单的基于libVLC的视频播放器(图形界面版)

    ===================================================== 最简单的基于libVLC的例子文章列表: 最简单的基于libVLC的例子:最简单的基于lib ...

  2. 最简单的基于libVLC的例子:最简单的基于libVLC的推流器

    ===================================================== 最简单的基于libVLC的例子文章列表: 最简单的基于libVLC的例子:最简单的基于lib ...

  3. 基于VLC的视频播放器

    原文:基于VLC的视频播放器 最近在研究视频播放的功能,之前是使用VideoView.在网上看了一下,感觉不是很好,支持的格式比较少,现在网络视频的格式各种各样,感觉用VideoView播放起来局限性 ...

  4. 转:最简单的基于 DirectShow 的视频播放器

    50行代码实现的一个最简单的基于 DirectShow 的视频播放器 本文介绍一个最简单的基于 DirectShow 的视频播放器.该播放器对于初学者来说是十分有用的,它包含了使用 DirectSho ...

  5. Android开发学习之路--基于vitamio的视频播放器(二)

      终于把该忙的事情都忙得差不多了,接下来又可以开始good good study,day day up了.在Android开发学习之路–基于vitamio的视频播放器(一)中,主要讲了播放器的界面的 ...

  6. 50行代码实现的一个最简单的基于 DirectShow 的视频播放器

    本文介绍一个最简单的基于 DirectShow 的视频播放器.该播放器对于初学者来说是十分有用的,它包含了使用 DirectShow 播放视频所有必备的函数. 直接贴上代码,具体代码的含义都写在注释中 ...

  7. 基于VLC的视频播放器(转载)

    最近在研究视频播放的功能,之前是使用VideoView.在网上看了一下,感觉不是很好,支持的格式比较少,现在网络视频的格式各种各样,感觉用VideoView播放起来局限性很大. 找到了一个比较合适的播 ...

  8. 自定义基于 VLC 的视频播放器

    前言(蛋疼的背景故事) 前段时间,接了一个小项目,有个需求是要在系统待机一段时间以后,循环播放 MV(类似于 Windows 系统的屏幕保护). 听到这个需求,我首先想到的是 MediaPlayer ...

  9. GJM :自定义基于 VLC 的视频播放器 [转载]

    感谢您的阅读.喜欢的.有用的就请大哥大嫂们高抬贵手"推荐一下"吧!你的精神支持是博主强大的写作动力以及转载收藏动力.欢迎转载! 版权声明:本文原创发表于 [请点击连接前往] ,未经 ...

随机推荐

  1. 2019 gplt团体程序设计天梯赛总结

    分很菜… 以后写题一定记得把题意理清楚了再开始写. 模拟题还是大坑,代码还是写得不够多,代码量一大就写bug. 补题 l1-8 估值一亿的AI核心代码 补题链接:https://pintia.cn/p ...

  2. 一键安装LNMP(适合centos7)

    1.准备工作,下载源码包 wget https://cdn.mysql.com//Downloads/MySQL-5.7/mysql-5.7.22-linux-glibc2.12-x86_64.tar ...

  3. 50.常用的query查询方式

    主要知识点 match all match multi match range query term query terms query exist query         1.match all ...

  4. 2、Linux的关机方式

    shutdown 关机指令,你可以man shutdown 来看一下帮助文档.例如你可以运行如下命令关机: shutdown –h 10 ‘This server will shutdown afte ...

  5. Mysql学习总结(38)——21条MySql性能优化经验

    今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关于数据库的性能,这并不只是DBA才需要担心的事,而这更是我们程序员需要去关注的事情. 当我们去设计数据库表结构,对操作数 ...

  6. POJ 3608

    1.计算P上y坐标值最小的顶点(称为 yminP )和Q上y坐标值最大的顶点(称为 ymaxQ). 2.为多边形在 yminP 和 ymaxQ 处构造两条切线 LP 和 LQ 使得他们对应的多边形位于 ...

  7. Cocos2d-x3.3beta0创建动画的3种方式

    1.单独载入精灵对象 渲染效率低,浪费资源,不推荐用该方法.代码例如以下:注:代码仅仅需贴到HelloWorldScene.cpp中就可以. //First,单独渲染每个精灵帧 auto sprite ...

  8. jcaptcha进阶

    1.改动CaptchaServiceSingleton类.使用带參构造方法来创建DefaultManageableImageCaptchaService对象. watermark/2/text/aHR ...

  9. 自己定义隐式转换和显式转换c#简单样例

    自己定义隐式转换和显式转换c#简单样例 (出自朱朱家园http://blog.csdn.net/zhgl7688) 样例:对用户user中,usernamefirst name和last name进行 ...

  10. 【NOIP 2011】 Mayan游戏

    [题目链接] https://www.luogu.org/problemnew/show/P1312 [算法] 深度优先搜索 [代码] #include<bits/stdc++.h> us ...