1.通过vlc实现rtsp视频流播放
核心代码:
if (libvlc_NothingSpecial != libvlc_state) {
qDebug()<<"Media is playing now"<<endl;
return;
}
libvlc_inst = libvlc_new(NULL,NULL);
// libvlc_new(sizeof (vlc_args) / sizeof (vlc_args[0]),vlc_args);
if(NULL == libvlc_inst){
qDebug()<<"error: libvlc_new error" <<endl;
return;
}
// 网络路径 libvlc_media_new_location
if (QFile::exists(libvlc_url)) {
libvlc_m = libvlc_media_new_path(libvlc_inst,libvlc_url.toStdString().c_str());
}
else {
libvlc_m = libvlc_media_new_location(libvlc_inst,libvlc_url.toStdString().c_str());
}
if(NULL == libvlc_m){
qDebug()<<"error:libvlc_media_new_location"<<endl;
return;
}
libvlc_mp = libvlc_media_player_new_from_media(libvlc_m);
if (libvlc_mainWindow) {
libvlc_WId = libvlc_mainWindow->winId();
libvlc_media_player_set_hwnd(libvlc_mp,(void*)libvlc_WId);
libvlc_video_set_mouse_input(libvlc_mp, false);
libvlc_video_set_key_input(libvlc_mp, false);
}
Sleep(3);
libvlc_media_player_play(libvlc_mp);
libvlc_state = libvlc_media_player_get_state(libvlc_mp);
2.通过ffmpeg实现rtsp视频流播放
QFFmpeg::QFFmpeg(QObject *parent) :
QObject(parent) {
m_is_init_succeed = true;
m_is_play = true;
m_is_play_by_timer = true;
video_stream_index = -1;
av_register_all();//注册库中所有可用的文件格式和解码器
avformat_network_init();//初始化网络流格式,使用RTSP网络流时必须先执行
pAVFormatContext = avformat_alloc_context();//申请一个AVFormatContext结构的内存,并进行简单初始化
pAVFrame = av_frame_alloc();
m_timer = new QTimer();
m_check_get_image_index = 0;
m_is_get_image = false;
m_timer->setInterval(1000);
connect(m_timer, SIGNAL(timeout()), this, SLOT(OnTimerOut()));
}
QFFmpeg::~QFFmpeg() {
if (m_timer) {
delete m_timer;
m_timer = nullptr;
}
Free();
}
bool QFFmpeg::Init() {
if (m_timer && m_timer->isActive()) {
m_timer->stop();
}
m_timer->start();
//打开视频流
int result = avformat_open_input(&pAVFormatContext, m_url.toStdString().c_str(), nullptr, nullptr);
if (result < 0) {
#ifdef _DEBUG
qDebug() << "avformat_open_input : Open video stream failed!";
#endif
m_is_init_succeed = false;
return false;
}
//获取视频流信息
result = avformat_find_stream_info(pAVFormatContext, nullptr);
if (result < 0) {
#ifdef _DEBUG
qDebug() << "avformat_find_stream_info : Get video stream info failed!";
#endif
m_is_init_succeed = false;
return false;
}
//获取视频流索引
video_stream_index = -1;
for (uint i = 0; i < pAVFormatContext->nb_streams; i++) {
if (pAVFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
video_stream_index = i;
break;
}
}
if (video_stream_index == -1) {
#ifdef _DEBUG
qDebug() << "Get video stream index failed!";
#endif
avformat_close_input(&pAVFormatContext);
m_is_init_succeed = false;
return false;
}
m_is_init_succeed = true;
//获取视频流的分辨率大小
pAVCodecContext = pAVFormatContext->streams[video_stream_index]->codec;
videoWidth = pAVCodecContext->width;
videoHeight = pAVCodecContext->height;
avpicture_alloc(&pAVPicture, AV_PIX_FMT_RGB24, videoWidth, videoHeight);
// 获取视频流解码器 (真正的编解码器,其中有编解码需要调用的函数)
AVCodec *pAVCodec = avcodec_find_decoder(pAVCodecContext->codec_id);
if (!pAVCodec) {
avcodec_close(pAVCodecContext);
avformat_close_input(&pAVFormatContext);
}
pSwsContext = sws_getContext(videoWidth,videoHeight,AV_PIX_FMT_YUV420P,videoWidth,videoHeight,AV_PIX_FMT_RGB24,SWS_BICUBIC,0,0,0);
//打开对应解码器
result = avcodec_open2(pAVCodecContext, pAVCodec, nullptr);
if (result < 0) {
#ifdef _DEBUG
qDebug() << "avcodec_open2 : Open AVCodec decoder failed!";
#endif
avcodec_close(pAVCodecContext);
avformat_close_input(&pAVFormatContext);
return false;
}
#ifdef _DEBUG
qDebug() << "Init video stream Ok!";
#endif
return true;
}
void QFFmpeg::Play()
{
//一帧一帧读取视频
while (true) {
// Sleep(300);
if (!m_is_play || !m_is_init_succeed || !m_is_play_by_timer) {
continue;
}
if (av_read_frame(pAVFormatContext, &pAVPacket) >= 0) {
if(pAVPacket.stream_index==video_stream_index){
int frameFinished=0;
avcodec_decode_video2(pAVCodecContext, pAVFrame, &frameFinished, &pAVPacket);
// qDebug() << "start decode "<<QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss") << " is finish:" << frameFinished;
if (frameFinished){
mutex.lock();
sws_scale(pSwsContext,(const uint8_t* const *)pAVFrame->data,pAVFrame->linesize,0,videoHeight,pAVPicture.data,pAVPicture.linesize);
//发送获取一帧图像信号
QImage image(pAVPicture.data[0], videoWidth, videoHeight, QImage::Format_RGB888);
qDebug() << "emit One Image ";
emit SetImage(image);
m_is_get_image = true;
mutex.unlock();
}
}
}
av_free_packet(&pAVPacket);//释放资源,否则内存会一直上升
}
}
欢迎留言或交流。 QQ:1123601333 WX:clauszheng