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);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章