一、简单说明
本文讲解利用MFC调用vlc(2.0.0)的动态库实现简单的播放器,实现播放、暂停、停止、音量控制、进度控制,支持中文路径等。
VLC 中文路径转码问题<转>
最近用MFC编写调用libVLC的程序时碰到中文路径不能打开的问题,愤闷了两天终于给解决了,在这里贴出来希望给那些遇到转码问题的人一点帮助。
主要问题是编码方式不对,现在程序主要是用Unicode码,我遇到的libVLC默认为UTF8,这就在遇到中文是需要转为UTF8。我遇到的主要是CString转为const char *或char *。VC++提供强制转码貌似是行不通的,这里写了个函数供参考(因为是转Unicode,所以支持所有语言,还有确保你的项目编码方式是Use Multi-Byte Character Set(不是宽字节编码))。
char* UniToUTF8(CString strUnicode)
{
USES_CONVERSION;
LPWSTR pwStr=new wchar_t[strUnicode.GetLength()+1];
wcscpy(pwStr,T2W((LPCTSTR)strUnicode));
int ilen = WideCharToMultiByte(CP_UTF8, 0, pwStr, -1, NULL, 0, NULL, NULL); //获取长度
char *szUtf8Temp=new char[ilen + 1];
memset(szUtf8Temp, 0, ilen +1);
WideCharToMultiByte (CP_UTF8, 0, pwStr, -1, szUtf8Temp, ilen, NULL,NULL); //UTF转码
detele pwStr;
return szUtf8Temp;
}
这函数也可以用在其他需要转码的地方。
注:szUtf8Temp用完记得释放空间
二、所需环境说明
VC6.0 VLC的版本为2.0.0
三、搭建MFC调用libvlc的环境
1.新建立一个VC的工程,暂时取名为VLCDemo
2.首先将VLC的目录下的vlc/sdk\include\vlc.h复制到工程目录下,然后新建立vlc和lib两个文件夹
3.将include目录下的除vlc.h中所有文件拷贝到vlc下,同事将vlc\lib下的两个libvlc.lib和libvlccore.lib复制到lib文件夹下。
4、将vlc目录下的livvlc.dll和libvlccore.dll以及plugins目录到复制到Debug目录下
5.网上下载stdint.h复制主目录下。
推荐地址为:http://download.csdn.net/detail/yigebing52/5747815
6.在项目中添加libvlc.lib和libvlccore.lib的引用。
6.在C**DLG.cpp中加入vlc.h的包含
7点击编译按钮,按照提示将<**>修改为“”就可以了。
这时环境就以及搭建好了。
四。绘制界面,开始增加功能
整体界面图如下图
按钮的作用从上到下依次为:显示当前播放的文件路径,浏览文件按钮,测试按钮(用于测试函数用法),播放、停止。
其中显示文件路径的Edit框ID为IDC_VIDEO_PATH,关联一个成员变量。浏览按钮ID为IDC_SELECT_VIDEO,其他几个按钮ID分别为IDC_BTN_TEST,
IDC_PLAYTIME,IDC_VOLUME,IDC_PLAY,IDC_PAUSE,IDC_STOP。中间播放界面为一个文本框,修改其ID为IDC_STATIC_PIC。
五,一步一步实现功能。
1.绘制播放窗口为黑色
正在窗口绘制函数OnPaint()中加入如下代码:
CBrush *oldBursh, brNew;
HWND hWnd = GetDlgItem(IDC_STATIC_PIC)->GetSafeHwnd();
brNew.CreateSolidBrush(RGB(0, 0, 0));
HDC hDC = ::GetDC(hWnd);
CDC *pDC = CDC::FromHandle(hDC);
oldBursh = pDC->SelectObject(&brNew);
CRect rect2;
::GetClientRect(hWnd, &rect2);
pDC->Rectangle(rect2);
pDC->SelectObject(oldBursh);
2.浏览播放文件按钮功能函数。
void CVLCDemoDlg::OnSelectVideo()
{
// TODO: Add your control notification handler code here
TCHAR BASED_CODE szFilter[] = _T("Video Files All Files (*.*)|*.*||");
CFileDialog fileDlg (TRUE, _T("Video file"), _T(""), OFN_FILEMUSTEXIST, szFilter, this);
if(fileDlg.DoModal() == IDOK)
{
m_VideoPath = fileDlg.GetPathName();
m_bNew = true;
}
UpdateData(FALSE);
}
3.播放按钮的函数实现
首先需要在VLCDemoDlg.h添加几个变量。
bool m_bNew;----------表明当前文件是否为新文件
libvlc_instance_t* m_vlcInst;-------vlc的入口变量
libvlc_media_player_t* m_vlcMplay;
libvlc_media_t* m_vlcMedia;
libvlc_time_t m_TotalTime;---文件总的时间
UINT_PTR m_playerTimer;----定时器变量
在初始化函数OnInitDialog添加
SetWindowText("VLC SDK demo");
char *vlc_argv[100];
int vlc_argc = 0;
vlc_argv[vlc_argc++] = "--ignore-config";
m_vlcInst = libvlc_new (vlc_argc, vlc_argv);
m_SliderPlayer.SetRange(0, 1000);
m_SliderPlayer.SetPos(0);
m_SliderVolume.SetRange(0,100);
m_SliderVolume.SetPos(100);
在cpp中构造函数中初始化上面几个变量
m_vlcInst = NULL;
m_vlcMedia = NULL;
m_vlcMplay = NULL;
m_bNew = true;
在cpp文件中添加如下函数
void CVLCDemoDlg::OnPlay()
{
UpdateData(true);
if (m_VideoPath == "")
{
return;
}
if(m_bNew == true)
{
if(m_vlcMplay != NULL)
{
libvlc_media_player_release(m_vlcMplay);
}
m_vlcMedia = libvlc_media_new_path (m_vlcInst, EncodeToUTF8(m_VideoPath.GetBuffer(0)));
m_vlcMplay = libvlc_media_player_new_from_media (m_vlcMedia);
HWND hwnd = GetDlgItem(IDC_STATIC_PIC)->GetSafeHwnd();
libvlc_media_player_set_hwnd (m_vlcMplay, hwnd);
m_bNew = false;
}
libvlc_media_player_play (m_vlcMplay);
m_TotalTime = libvlc_media_player_get_length(m_vlcMplay);
m_playerTimer = SetTimer(100,1*100,NULL);
}
这个程序支持中文路径的视频文件,上面讲assi转化为utf-8即可。
char* EncodeToUTF8(const char* mbcsStr)
{
wchar_t* wideStr;
char* utf8Str;
int charLen;
charLen = MultiByteToWideChar(CP_UTF8, 0, mbcsStr, -1, NULL, 0);
wideStr = (wchar_t*) malloc(sizeof(wchar_t)*charLen);
MultiByteToWideChar(CP_ACP, 0, mbcsStr, -1, wideStr, charLen);
charLen = WideCharToMultiByte(CP_UTF8, 0, wideStr, -1, NULL, 0, NULL, NULL);
utf8Str = (char*) malloc(charLen);
WideCharToMultiByte(CP_UTF8, 0, wideStr, -1, utf8Str, charLen, NULL, NULL);
free(wideStr);
return utf8Str;
}
此时在就能播放视频文件了。
3.暂停
void CVLCDemoDlg::OnPause()
{
if(m_vlcMplay != NULL)
libvlc_media_player_pause(m_vlcMplay);
}
4.停止
void CVLCDemoDlg::OnStop()
{
// TODO: Add your control notification handler code here
if (m_vlcMplay == NULL)
{
return;
}
libvlc_media_player_stop(m_vlcMplay);
m_bNew = true;
m_vlcMplay = NULL;
//libvlc_exception_clear(&m_vlcEx);
if (m_vlcMedia != NULL)
{
libvlc_media_release(m_vlcMedia);
}
if (m_vlcMplay != NULL)
{
libvlc_media_player_release(m_vlcMplay);
}
KillTimer(100);
m_SliderPlayer.SetPos(0);
OnPaint();
}
5.播放时进度条跟着时间变化而走动
通过一个定时器实现的。
void CVLCDemoDlg::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if (nIDEvent == 100)
{
libvlc_time_t m_CurTime = libvlc_media_player_get_time(m_vlcMplay);
//float fPos = libvlc_media_player_get_position(m_vlcMplay, &m_vlcEx);
m_TotalTime = libvlc_media_player_get_length(m_vlcMplay);
int m_npos = m_CurTime*1000/m_TotalTime;
m_SliderPlayer.SetPos(m_npos);
}
if(libvlc_Ended == libvlc_media_player_get_state(m_vlcMplay))//获取播放状态的函数,如果是结束就发送stop命令,更改状态。
OnStop();
CDialog::OnTimer(nIDEvent);
}
6.屏蔽回车键和退出键。
BOOL CVLCDemoDlg::PreTranslateMessage(MSG* pMsg)
{
if (pMsg->message == WM_KEYDOWN) {
if (pMsg->wParam == VK_ESCAPE || pMsg->wParam == VK_RETURN)
{
//SetFullScreen();
return TRUE;
}
}
return CDialog::PreTranslateMessage(pMsg);
}
7.拖动进度条 修改播放进度。
void CVLCDemoDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
if (pScrollBar->GetSafeHwnd() == m_SliderPlayer.GetSafeHwnd())
{
if (m_vlcMplay != NULL)
{
libvlc_time_t m_CurTime;
m_TotalTime = libvlc_media_player_get_length(m_vlcMplay);
double pos = m_SliderPlayer.GetPos()/1000.0;
m_CurTime = m_TotalTime * pos;
libvlc_media_player_set_time(m_vlcMplay,m_CurTime);
}
}
else if (pScrollBar->GetSafeHwnd() == m_SliderVolume.GetSafeHwnd())
{
if (m_vlcMplay != NULL)
{
int iVolume = m_SliderVolume.GetPos();
libvlc_audio_set_volume(m_vlcMplay,iVolume);//取值范围为0-100
}
}
else
{
CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
}
}
六。程序工程文件下载地址。
http://www.pudn.com/downloads559/sourcecode/windows/multimedia/detail2305271.html
完。。。。