Qt+FFmpeg播放RTSP H264視頻流(3)- RTSP視頻流播放

Qt+FFmpeg播放RTSP H264視頻流(3)- RTSP視頻流播放

RTSP視頻播放器

通過上兩篇博客:Qt+FFmpeg播放RTSP H264視頻流(1)- 在Qt項目加入FFmpeg庫 Qt+FFmpeg播放RTSP H264視頻流(2)- FFmpeg自定義類封裝已經大概瞭解了FFmpeg的工作過程,本編接上兩篇完成一個簡單的RTSP播放器。大致界面如下,代碼下載地址:Qt工程完整代碼下載
視頻播放界面
播放邏輯如下:
視頻播放邏輯

RTSP_Player播放類

RTSP_Player.h

#ifndef RTSP_PLAYER_H
#define RTSP_PLAYER_H

#include “MyFFmpeg.h”
#include <QObject>

class RTSP_Player : public QObject
{
Q_OBJECT
public:
enum PlayerState {
FFmpegInitFail = 0,
FFmpegInitSucc,
FFmpegStoped
};

explicit RTSP_Player(MyFFmpeg *ffmpeg = nullptr, QObject *parent = nullptr);
void SetPlayerUrl(QString playerUrl);

signals:
void SigOpenUrlResult(int result);

public slots:
void PlayerStart();
void PlayerStop();

private:
volatile bool m_stopped; // 停止播放標識,爲true時停止播放,退出播放循環
QString m_playerUrl; // 播放url
MyFFmpeg *m_ffmpeg; // MyFFmepg指針
};

#endif // RTSP_PLAYER_H

RTSP_Player.cpp

#include "RTSP_Player.h"
#include <QThread>
RTSP_Player::RTSP_Player(MyFFmpeg *ffmpeg, QObject *parent)
QObject(parent)
, m_ffmpeg(ffmpeg)
{

}

void RTSP_Player::SetPlayerUrl(QString playerUrl)
{
this->m_playerUrl = playerUrl;
}

void RTSP_Player::PlayerStart()
{
if (m_ffmpeg == NULL){
emit SigOpenUrlResult(RTSP_Player::FFmpegInitFail);
return;
}

m_ffmpeg-&gt;MyFFmpegSetUrl(this-&gt;m_playerUrl);
if (m_ffmpeg-&gt;MyFFmpegInit() != 0) {
    emit SigOpenUrlResult(RTSP_Player::FFmpegInitFail);
    return;
}

emit SigOpenUrlResult(RTSP_Player::FFmpegInitSucc);

m_stopped = false;

while (1) {
    if (m_stopped){
        qDebug("--------------- stop ----------------");
        break;
    }

    if (!m_ffmpeg) {
        break;
    }

    if (m_ffmpeg-&gt;MyFFmpepReadFrame() &lt; 0) {
        qDebug("--------------- get frame fail, stop -----------");
        break;
    }
    
    QThread::msleep(0.02);
}

m_ffmpeg-&gt;MyFFmpegDestroy();
emit SigOpenUrlResult(RTSP_Player::FFmpegStoped);
qDebug("---------------- quit -----------------");

return;

}

void RTSP_Player::PlayerStop()
{
m_stopped = true;
}

FFmpegLibTestFrm UI界面類

FFmpegLibTestFrm.h

#ifndef FFMPEGLIBTESTFRM_H
#define FFMPEGLIBTESTFRM_H

#include <QMainWindow>
#include <QImage>
#include <QThread>
#include “RTSP_Player.h”

namespace Ui {
class FFmpegLibTestFrm;
}

class FFmpegLibTestFrm : public QMainWindow
{
Q_OBJECT

public:
explicit FFmpegLibTestFrm(QWidget *parent = 0);
~FFmpegLibTestFrm();

void MyFFmpegTest();

void PlayStart();
void PlayStop();
void PlayProcess();

protected:
void paintEvent(QPaintEvent *e);
void closeEvent(QCloseEvent *e);

private slots:
void SlotGetOneFrame(QImage img);
void SlotOpenUrlResult(int result);

void on_btnPlayer_clicked();

signals:
void SigPlayStart();

private:
QString m_playUrl;
MyFFmpeg *m_ffmpeg = nullptr;
RTSP_Player *m_player = nullptr;
QImage m_image;
QThread *m_playThread = nullptr;

private:
Ui::FFmpegLibTestFrm *ui;
};

#endif // FFMPEGLIBTESTFRM_H

#include "FFmpegLibTestFrm.h"
#include "ui_FFmpegLibTestFrm.h"
#include "MyHelper.h"
#include <QPainter>

extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavdevice/avdevice.h>
#include <libavformat/version.h>
#include <libavutil/time.h>
#include <libavutil/mathematics.h>
}

FFmpegLibTestFrm::FFmpegLibTestFrm(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::FFmpegLibTestFrm)
{
    ui->setupUi(this);

    m_ffmpeg = new MyFFmpeg;
    connect(m_ffmpeg, SIGNAL(MyFFmpegSigGetOneFrame(QImage)), this, SLOT(SlotGetOneFrame(QImage)));

    ui->labVideo->setStyleSheet("QLabel{border:2px solid green}");
    ui->labVideo->installEventFilter(this);
    ui->btnPlayer->setEnabled(true);
}

FFmpegLibTestFrm::~FFmpegLibTestFrm()
{
    delete ui;
}

void FFmpegLibTestFrm::MyFFmpegTest()
{
    MyFFmpeg *ffmpeg = new MyFFmpeg();

    QString rtspUrl = "rtsp://192.168.88.168:554/0";
    ffmpeg->MyFFmpegSetUrl(rtspUrl);
    if (ffmpeg->MyFFmpegInit() == 0) {
        int i;
        for (i = 0; i < 5; i++) {
            ffmpeg->MyFFmpepReadFrame();
        }
    } else {
        qDebug("MyFFmpegInit fail!\n");
    }

    delete ffmpeg;
}

void FFmpegLibTestFrm::PlayStop()
{
    if (m_player)
    {
        m_player->PlayerStop();
    }

    if (m_playThread)
    {
        m_playThread->quit();
        m_playThread->wait(1000);
        delete m_playThread;
        m_playThread = nullptr;
    }

    if (m_player)
    {
        delete m_player;
        m_player = nullptr;
    }
}

void FFmpegLibTestFrm::PlayStart()
{
    this->PlayStop();

    m_playThread = new QThread();
    m_player = new RTSP_Player(m_ffmpeg);
    m_player->SetPlayerUrl(m_playUrl);

    connect(this, SIGNAL(SigPlayStart()), m_player, SLOT(PlayerStart()));
    connect(m_player, SIGNAL(SigOpenUrlResult(int)), this, SLOT(SlotOpenUrlResult(int)));

    m_player->moveToThread(m_playThread);
    m_playThread->start();
}

void FFmpegLibTestFrm::PlayProcess()
{
    this->PlayStart();
    emit SigPlayStart();
}

void FFmpegLibTestFrm::SlotOpenUrlResult(int result)
{
    if (result == RTSP_Player::FFmpegInitFail)
    {
        this->PlayStop();

        QString rtspUrl = ui->txtRTSPURL->text().trimmed();
        QString errMsg = "打開" + rtspUrl + "失敗";
        MyHelper::ShowMessageBoxError(errMsg);
        ui->btnPlayer->setText("start");
    }
    else if (result == RTSP_Player::FFmpegInitSucc)
    {
        ui->btnPlayer->setText("stop");
    }
    else if (result == RTSP_Player::FFmpegStoped)
    {
        ui->btnPlayer->setText("start");
    }

    ui->btnPlayer->setEnabled(true);
}

void FFmpegLibTestFrm::SlotGetOneFrame(QImage image)
{
    m_image = image;
    this->update();
}

void FFmpegLibTestFrm::closeEvent(QCloseEvent *event)
{
    this->PlayStop();
}

void FFmpegLibTestFrm::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);

    if (m_image.size().width() <= 0)
        return;

    QImage img = m_image.scaled(ui->labVideo->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);

    int x = ui->labVideo->geometry().x();
    int y = ui->labVideo->geometry().y();
    painter.drawImage(QPoint(x, y), img);
}

void FFmpegLibTestFrm::on_btnPlayer_clicked()
{
    if (ui->btnPlayer->text().compare("start") == 0) {
        m_playUrl = ui->txtRTSPURL->text().trimmed();
        if (m_playUrl.length() <= (int)strlen("rtsp://")) {
            MyHelper::ShowMessageBoxError("請輸入rtsp播放地址!");
            return;
        }

        ui->btnPlayer->setEnabled(false);
        this->PlayProcess();
    } else if (ui->btnPlayer->text().compare("stop") == 0) {
        ui->btnPlayer->setEnabled(false);
        this->PlayStop();
    }
}


播放效果

RTSP簡單播放器

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章