QT实现一个视频播放器(vlc)

现在有一个需求,需要使用QT写界面,使用vlc进行视频的操作,显示在QLable上面。
借鉴了雷神大佬的博客,使用的环境是vs2015+Qt5.9.0。第一先介绍了vlc的下载和配置。二和三是雷神大佬的例子,用来测试。四介绍了完成需求的主要代码和流程。
源码下载地址

一、下载配置vlc

本文使用的vlc版本下载地址是: http://get.videolan.org/vlc/3.0.3/win32/ 下面的vlc-3.0.3-win32.7z
比如下载到:C:\Users\czf\Downloads\vlc-3.0.3-win32\vlc-3.0.3\

  • vs配置vlc的头文件位置(vs工程-设置-VC++目录-包含目录添加C:\Users\czf\Downloads\vlc-3.0.3-win32\vlc-3.0.3\sdk\include)
  • vs配置vlc的lib位置(vs工程-设置-VC++目录-库目录添加C:\Users\czf\Downloads\vlc-3.0.3-win32\vlc-3.0.3\sdk\lib)
  • 编译完工程后,需要把C:\Users\czf\Downloads\vlc-3.0.3-win32\vlc-3.0.3目录下的dll文件和plugins文件夹拷贝到和生成的exe同级目录(没有dll无法运行,没有plugins可能会崩溃)

二、测试例子:播放本地视频(最简单的基于libVLC的例子:最简单的基于libVLC的视频播放器)

demo

/**
 * 最简单的基于libVLC的播放器
 * Simplest libVLC Player
 *
 * 雷霄骅 Lei Xiaohua
 * [email protected]
 * 中国传媒大学/数字电视技术
 * Communication University of China / Digital TV Technology
 * http://blog.csdn.net/leixiaohua1020
 *
 * 本程序是一个最简单的基于libVLC的视频播放器。
 * 适合初学者学习libVLC。
 *
 * This example is the simplest Video Player based on libVLC.
 * Suitable for the beginner of 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:///C:\\Users\\czf\\Desktop\\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_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的推流器)

/**
 * 最简单的基于libVLC的推流器
 * Simplest libVLC Streamer
 *
 * 雷霄骅 Lei Xiaohua
 * [email protected]
 * 中国传媒大学/数字电视技术
 * Communication University of China / Digital TV Technology
 * http://blog.csdn.net/leixiaohua1020
 *
 * 本程序是一个最简单的基于libVLC的推流器。
 * 适合初学者学习libVLC。
 *
 * This example is the simplest Streamer based on libVLC.
 * Suitable for the beginner of libVLC.
 */
 
#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_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”

使用QT实现一个播放器

调用

int main(int argc, char *argv[])
{
	QApplication a(argc, argv);
	//CMediaPlayer::TestLocalPlayerVedio();
	//CMediaPlayer::TestRtmpPlayerVedio();
	testqt w;  //testqt是一个QMainWindow,上面有一个QLable
	w.show();
	// 获取w上面的qlable控件,传入handle,显示视频到QLabel
	QLabel* label = w.findChild<QLabel*>("lb");

	CMediaPlayer t;
	t.PlayVedio("", (HWND)label->winId());

	return a.exec();
}

实现

void CMediaPlayer::PlayVedio(const char *pstIp, HWND handle)
{
	char szPlayerUrl[255] = {0};
	sprintf_s(szPlayerUrl, "rtsp://admin:admin123%s", pstIp);

	libvlc_media_t *pMedia = libvlc_media_new_path(m_pInstant, "C:\\Users\\czf\\Desktop\\cuc_ieschool.flv"); //本地播放
	//libvlc_media_new_location(m_pInstant, szPlayerUrl);  //拉流播放
	if ( NULL == pMedia)
	{
		return;
	}

	libvlc_media_player_t *pPlayer = libvlc_media_player_new_from_media(pMedia);
	if (NULL == pPlayer)
	{
		return;
	}
	libvlc_media_player_set_hwnd(pPlayer, handle);
	int iRet = libvlc_media_player_play(pPlayer);
	if (0 != iRet)
	{
		libvlc_media_player_stop(pPlayer);
		libvlc_media_player_retain(pPlayer);
		return;
	}
}

流程介绍:
建立一个QT工程,只有一个QMainWindow,在QMainWindow添加一个QLable,读取该lable的Handle,传给vlc,vlc在该lable上进行视频显示。

参考博文

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

遇到的问题

1.问题描述:
解决方法:
2.问题描述:运行到libvlc_media_new_path崩溃
原因:m_pInstant = libvlc_new(0, NULL);为NULL
解决方法:把C:\Users\czf\Downloads\vlc-3.0.3-win32\vlc-3.0.3\文件夹下的plugins文件夹拷贝到exe同级目录下。
3.使用vlc会出现错误,typedef ssize_t (*libvlc_media_read_cb)(void *opaque, unsigned char *buf,size_t len);
解决方法:在文件中定义libvlc_media.h

typedef int ssize_t; //添加这一句
typedef ssize_t (*libvlc_media_read_cb)(void *opaque, unsigned char *buf, size_t len);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章