現在有一個需求,需要使用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);