码迷,mamicode.com
首页 > 其他好文 > 详细

转:基于libVLC的视频播放器

时间:2015-05-17 18:37:03      阅读:202      评论:0      收藏:0      [点我收藏+]

标签:

本文来自于: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"下的视频,实际使用的代码如下所示。

[cpp] view plaincopy技术分享技术分享技术分享

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

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

[cpp] view plaincopy技术分享技术分享技术分享

  1. 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=5000;??

? ??

? ?????//libvlc_time_t?length;??

? ??

? ?????/*?Load?the?VLC?engine?*/??

? ?????inst?=?libvlc_new?(0,?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/1000);??

? ?????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?0;??

? ?}??

?

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

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

?技术分享

?

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

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

技术分享

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

技术分享

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

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

播放

视频"播放"的源代码如下所示。简单来说,完成了以下视频播放的初始化工作:
(1)????输入的URL转换为UTF-8编码(后文详细记录)
(2)????将显示视频画面的控件的句柄提供给libVLC
(3)????初始化libVLC并开始播放
(4)????开启定时器,用于更新视频播放的进度(后文详细记录)

[cpp] view plaincopy技术分享技术分享技术分享

  1. void?CplayerGUIDlg::OnBnClickedStart()??
  2. {??
  3. ????CStringW?cstr_url;??
  4. ??
  5. #ifdef?_UNICODE??
  6. ????m_url.GetWindowText(cstr_url);??
  7. #else??
  8. ????USES_CONVERSION;??
  9. ????CStringA?cstr_urla;??
  10. ????m_url.GetWindowText(cstr_urla);??
  11. ????cstr_url.Format(L"%s",A2W(cstr_urla));??
  12. #endif??
  13. ??
  14. ????std::string?str_url;??
  15. ????UNICODE_to_UTF8(cstr_url,?str_url);??
  16. ????const?char?*char_url=str_url.c_str();??
  17. ??
  18. ????if(strcmp(char_url,"")==0){??
  19. ????????AfxMessageBox(_T("Input?URL?is?NULL!"));??
  20. ????????return;??
  21. ????}??
  22. ??????
  23. ????HWND?screen_hwnd=NULL;??
  24. ????screen_hwnd?=?this->GetDlgItem(IDC_SCREEN)->m_hWnd;???
  25. ??
  26. ????if(playerstate!=STATE_PREPARE){??
  27. ????????AfxMessageBox(_T("Media?is?playing?now."));??
  28. ????????return;??
  29. ????}??
  30. ??
  31. ??
  32. ?????/*?Create?a?new?item?*/??
  33. ?????//m?=?libvlc_media_new_location?(libvlc_inst,?"http://mycool.movie.com/test.mov");??
  34. ??
  35. ?????libvlc_m?=?libvlc_media_new_path?(libvlc_inst,?char_url);??
  36. ??
  37. ?????/*?Create?a?media?player?playing?environement?*/??
  38. ?????libvlc_mp?=?libvlc_media_player_new_from_media?(libvlc_m);??
  39. ???????
  40. ?????/*?No?need?to?keep?the?media?now?*/??
  41. ?????libvlc_media_release?(libvlc_m);??
  42. ???
  43. ????//on?windows??
  44. ?????libvlc_media_player_set_hwnd?(libvlc_mp,screen_hwnd);??
  45. ???
  46. ?????/*?play?the?media_player?*/??
  47. ?????int?x=libvlc_media_player_play?(libvlc_mp);??
  48. ??????
  49. ?????//_sleep?(30000);?/*?Let?it?play?a?bit?*/??
  50. ??????
  51. ??
  52. ????playerstate=STATE_PLAY;??
  53. ????SetBtn(STATE_PLAY);??
  54. ????SetTimer(1,1000,NULL);??
  55. }??

?

暂停/继续

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

[cpp] view plaincopy技术分享技术分享技术分享

  1. void?CplayerGUIDlg::OnBnClickedPause()??
  2. {??
  3. ????if(playerstate==STATE_PLAY){??
  4. ????????libvlc_media_player_set_pause(libvlc_mp,1);??
  5. ????????playerstate=STATE_PAUSE;??
  6. ????????GetDlgItem(ID_PAUSE)->SetWindowText(_T("Resume"));??
  7. ????}else?if(playerstate==STATE_PAUSE){??
  8. ????????libvlc_media_player_set_pause(libvlc_mp,0);??
  9. ????????playerstate=STATE_PLAY;??
  10. ????????GetDlgItem(ID_PAUSE)->SetWindowText(_T("Pause"));??
  11. ????}??
  12. }??

?

停止

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

[cpp] view plaincopy技术分享技术分享技术分享

  1. void?CplayerGUIDlg::OnBnClickedStop()??
  2. {??
  3. ????if(libvlc_mp!=NULL){??
  4. ????????libvlc_media_player_stop?(libvlc_mp);??
  5. ????????libvlc_media_player_release?(libvlc_mp);??
  6. ????????KillTimer(1);??
  7. ????}??
  8. ??????
  9. ????SystemClear();??
  10. }??

?

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

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

[cpp] view plaincopy技术分享技术分享技术分享

  1. SetTimer(1,1000,NULL);??

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

[cpp] view plaincopy技术分享技术分享技术分享

  1. KillTimer(1);??

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

[cpp] view plaincopy技术分享技术分享技术分享

  1. void?CplayerGUIDlg::OnTimer(UINT_PTR?nIDEvent)??
  2. {??
  3. ????if?(nIDEvent?==?1){??
  4. ????????CString?curtimestr,durationstr;??
  5. ????????int?curtime;??
  6. ????????int?duration;??
  7. ????????int?tns,?thh,?tmm,?tss;??
  8. ????????int?progress;??
  9. ????????//ms??
  10. ????????curtime?=?libvlc_media_player_get_time(libvlc_mp);??
  11. ????????if(curtime!=0){??
  12. ????????????//change?to?second??
  13. ????????????tns?=?curtime/1000;??
  14. ????????????thh??=?tns?/?3600;??
  15. ????????????tmm??=?(tns?%?3600)?/?60;??
  16. ????????????tss??=?(tns?%?60);??
  17. ????????????curtimestr.Format(_T("%02d:%02d:%02d"),thh,tmm,tss);??
  18. ????????????m_curtime.SetWindowText(curtimestr);??
  19. ????????}??
  20. ????????duration??=?libvlc_media_player_get_length(libvlc_mp);??
  21. ????????if(duration!=0){??
  22. ????????????tns?=?duration/1000;??
  23. ????????????thh??=?tns?/?3600;??
  24. ????????????tmm??=?(tns?%?3600)?/?60;??
  25. ????????????tss??=?(tns?%?60);??
  26. ????????????durationstr.Format(_T("%02d:%02d:%02d"),thh,tmm,tss);??
  27. ????????????m_duration.SetWindowText(durationstr);??
  28. ??
  29. ????????????progress=curtime*100/duration;??
  30. ????????????m_progress.SetPos(progress);??
  31. ????????}??
  32. ????}??
  33. ??
  34. ????//Stop?in?the?end??
  35. ????if(libvlc_media_player_get_state(libvlc_mp)==libvlc_Ended)??
  36. ????????OnBnClickedStop();??
  37. ??
  38. ??
  39. ????CDialogEx::OnTimer(nIDEvent);??
  40. }??

?

视频播放点的调整

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

[cpp] view plaincopy技术分享技术分享技术分享

  1. void?CplayerGUIDlg::OnHScroll(UINT?nSBCode,?UINT?nPos,?CScrollBar*?pScrollBar)??
  2. {??
  3. ????if?(pScrollBar->GetSafeHwnd()?==?m_progress.GetSafeHwnd()){??
  4. ????????float?posf=0.0;??
  5. ????????if(nSBCode==SB_THUMBPOSITION){??
  6. ????????????posf=(float)nPos/100.0;??
  7. ????????????libvlc_media_player_set_position(libvlc_mp,posf);??
  8. ????????}??
  9. ????}??
  10. ????CDialogEx::OnHScroll(nSBCode,?nPos,?pScrollBar);??
  11. }??

?

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

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

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

[cpp] view plaincopy技术分享技术分享技术分享

  1. void?CplayerGUIDlg::UNICODE_to_UTF8(CStringW&?unicodeString,?std::string&?str)??
  2. {??
  3. ????int?stringLength?=?::WideCharToMultiByte(CP_UTF8,?NULL,?unicodeString,?wcslen(unicodeString),?NULL,?0,?NULL,?NULL);??
  4. ??
  5. ????char*?buffer?=?new?char[stringLength?+?1];??
  6. ????::WideCharToMultiByte(CP_UTF8,?NULL,?unicodeString,?wcslen(unicodeString),?buffer,?stringLength,?NULL,?NULL);??
  7. ????buffer[stringLength]?=?‘\0‘;??
  8. ??
  9. ????str?=?buffer;??
  10. ??
  11. ????delete[]?buffer;??
  12. }??

?

最简单的基于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(0,?NULL);??

? ????libvlc_vlm_add_broadcast(vlc,?media_name,?url,?sout,?0,?NULL,?true,?false);??

? ????libvlc_vlm_play_media(vlc,?media_name);??

? ??????

? ????//play?30s??

? ????_sleep(30000);???

? ??

? ????libvlc_vlm_stop_media(vlc,?media_name);??

? ????libvlc_vlm_release(vlc);??

? ????return?0;??

? }??

转:基于libVLC的视频播放器

标签:

原文地址:http://www.cnblogs.com/xkfz007/p/4510105.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!