feat: 新增视频推流(待优化)

pull/14/head
cbwu 6 months ago
parent 2eb9906370
commit 945bca9356

@ -1,7 +1,8 @@
#include "networkDetection.h" #include "networkDetection.h"
#include <QDateTime> #include <QDateTime>
networkDetection::networkDetection(QObject *parent,int id) : QObject(parent),m_id(id){ networkDetection::networkDetection(QObject *parent, int id)
: QObject(parent), m_id(id) {
flagRun = true; flagRun = true;
CmdListChanged = false; CmdListChanged = false;
m_process = new QProcess(this); m_process = new QProcess(this);
@ -10,7 +11,7 @@ networkDetection::~networkDetection() { delete m_process; }
void networkDetection::dowork(int id, QStringList cmdlist) { void networkDetection::dowork(int id, QStringList cmdlist) {
m_cmd = cmdlist; m_cmd = cmdlist;
if(id != m_id) if (id != m_id)
return; return;
QString result; QString result;
while (flagRun) { while (flagRun) {
@ -18,15 +19,17 @@ void networkDetection::dowork(int id, QStringList cmdlist) {
// if(id == 1) // if(id == 1)
// { // {
// QDateTime time = QDateTime::currentDateTime(); // QDateTime time = QDateTime::currentDateTime();
// QString str = time .toString("start yyyy-MM-dd hh:mm:ss\n");//格式化时间 .toString("yyyy-MM-dd hh:mm:ss");//格式化时间 // QString str = time .toString("start yyyy-MM-dd
// qDebug()<< str; // hh:mm:ss\n");//格式化时间 .toString("yyyy-MM-dd
// hh:mm:ss");//格式化时间 qDebug()<< str;
// } // }
m_process->waitForFinished(); // 等待指令执行完毕 m_process->waitForFinished(); // 等待指令执行完毕
// if(id == 1) // if(id == 1)
// { // {
// QDateTime time = QDateTime::currentDateTime(); // QDateTime time = QDateTime::currentDateTime();
// QString str = time .toString("end yyyy-MM-dd hh:mm:ss\n");//格式化时间 .toString("yyyy-MM-dd hh:mm:ss");//格式化时间 // QString str = time .toString("end yyyy-MM-dd
// qDebug()<< str; // hh:mm:ss\n");//格式化时间 .toString("yyyy-MM-dd
// hh:mm:ss");//格式化时间 qDebug()<< str;
// } // }
result = QString::fromLocal8Bit(m_process->readAll()); // 获取指令执行结果 result = QString::fromLocal8Bit(m_process->readAll()); // 获取指令执行结果
// qDebug() << result; // qDebug() << result;
@ -34,20 +37,20 @@ void networkDetection::dowork(int id, QStringList cmdlist) {
{ {
// qDebug() << "在线"; // qDebug() << "在线";
QString delay = selectTTL(result); QString delay = selectTTL(result);
emit resultReady(m_id, "在线",delay); emit resultReady(m_id, "在线", delay);
} else { } else {
// qDebug() << "离线"; // qDebug() << "离线";
emit resultReady(m_id, "离线","通信异常"); emit resultReady(m_id, "离线", "通信异常");
} }
//QThread::sleep(0.001); // 加sleep降低CPU占用率 QThread::sleep(3); // 加sleep降低CPU占用率
} }
} }
void networkDetection::stopwork(int id) { void networkDetection::stopwork(int id) {
if(id == m_id){ if (id == m_id) {
flagRun = false; flagRun = false;
} }
} }
void networkDetection::DyChangeCmdList(QStringList changeCmdList) { void networkDetection::DyChangeCmdList(QStringList changeCmdList) {
@ -56,9 +59,9 @@ void networkDetection::DyChangeCmdList(QStringList changeCmdList) {
CmdListChanged = true; CmdListChanged = true;
} }
//查找延迟 // 查找延迟
QString networkDetection::selectTTL(QString str) { QString networkDetection::selectTTL(QString str) {
str = str.remove(0,str.indexOf("平均 = ")+5); str = str.remove(0, str.indexOf("平均 = ") + 5);
str = str.left(str.indexOf("ms")+2); str = str.left(str.indexOf("ms") + 2);
return "通信正常\n"+str; return "通信正常\n" + str;
} }

@ -166,6 +166,8 @@ void ModelCameraDlg::on_pushButton_5_clicked() {
QString str = ui->pushButton_5->text(); QString str = ui->pushButton_5->text();
if (str == "播放视频") { if (str == "播放视频") {
QString ip = ui->videoIPLineEdit->text(); QString ip = ui->videoIPLineEdit->text();
ui->cameraVideoWidget->setPushStreamIP(
QStringLiteral("rtmp://182.92.130.23/app/stream999"));
ui->cameraVideoWidget->play(ip); ui->cameraVideoWidget->play(ip);
ui->pushButton_5->setText("暂停播放"); ui->pushButton_5->setText("暂停播放");
} else { } else {

@ -1,9 +1,12 @@
SOURCES += \ SOURCES += \
$$PWD/cffmpeg_decode.cpp \ $$PWD/cffmpeg_decode.cpp \
$$PWD/ffmpegpushstream.cpp \
$$PWD/ffmpegvideodlg.cpp $$PWD/ffmpegvideodlg.cpp
HEADERS += \ HEADERS += \
$$PWD/cffmpeg_decode.h \ $$PWD/cffmpeg_decode.h \
$$PWD/ffmpeginclude.h \
$$PWD/ffmpegpushstream.h \
$$PWD/ffmpegvideodlg.h \ $$PWD/ffmpegvideodlg.h \
FORMS += \ FORMS += \

@ -38,7 +38,7 @@ bool Cffmpeg_decode::open_input_file() {
// 设置缓存大小1080p可将值调大 // 设置缓存大小1080p可将值调大
av_dict_set(&avdic, "buffer_size", "2048000", 0); av_dict_set(&avdic, "buffer_size", "2048000", 0);
// 以udp方式打开如果以tcp方式打开将udp替换为tcp // 以udp方式打开如果以tcp方式打开将udp替换为tcp
av_dict_set(&avdic, "rtsp_transport", "udp", 0); av_dict_set(&avdic, "rtsp_transport", "tcp", 0);
// 设置超时断开连接时间,单位微秒//listen_timeout // 设置超时断开连接时间,单位微秒//listen_timeout
// av_dict_set(&avdic, "listen_timeout", "200000", 0); // av_dict_set(&avdic, "listen_timeout", "200000", 0);
av_dict_set(&avdic, "stimeout", "200000", 0); av_dict_set(&avdic, "stimeout", "200000", 0);
@ -122,6 +122,13 @@ bool Cffmpeg_decode::open_input_file() {
qDebug() << "Fill arrays failed.\n"; qDebug() << "Fill arrays failed.\n";
return 0; return 0;
} }
// 推流初始化
if (bPushStreamFlag) {
emit sendInitPushStream_Signal(inputFormatCtx);
}
// 裸流保存
if (!openSave()) { if (!openSave()) {
return false; return false;
}; };
@ -136,7 +143,11 @@ void Cffmpeg_decode::run() {
IsstopPlay = true; IsstopPlay = true;
return; return;
} }
if (bRecordTime) {
startTime = av_gettime();
qDebug() << "*******StartTime:" << QString::number(startTime);
bRecordTime = false;
}
// 读取数据包 // 读取数据包
while (av_read_frame(inputFormatCtx, inputPacket) >= 0) { while (av_read_frame(inputFormatCtx, inputPacket) >= 0) {
if (IsstopPlay) { if (IsstopPlay) {
@ -145,6 +156,13 @@ void Cffmpeg_decode::run() {
} }
if (inputPacket->stream_index == videoStreamIndex) { if (inputPacket->stream_index == videoStreamIndex) {
// 推流
if (bPushStreamFlag) {
// av_packet_clone(inputPacket);
AVPacket *outputPacket = av_packet_clone(inputPacket);
emit sendStreamData_Signal(outputPacket, frm_cnt);
}
// 保存裸流 // 保存裸流
if (m_formatContextSave) { if (m_formatContextSave) {
// 由于保存的m_formatContextSave只创建了一个视频流而读取到的图像的流索引不一定为0可能会出现错误【Invalid // 由于保存的m_formatContextSave只创建了一个视频流而读取到的图像的流索引不一定为0可能会出现错误【Invalid
@ -154,6 +172,7 @@ void Cffmpeg_decode::run() {
av_write_frame(m_formatContextSave, av_write_frame(m_formatContextSave,
inputPacket); // 将数据包写入输出媒体文件 inputPacket); // 将数据包写入输出媒体文件
} }
// 解码数据包 // 解码数据包
if (avcodec_send_packet(decoderCtx, inputPacket) >= 0) { if (avcodec_send_packet(decoderCtx, inputPacket) >= 0) {
int ret; int ret;
@ -178,10 +197,10 @@ void Cffmpeg_decode::run() {
QImage::Format_RGB32); QImage::Format_RGB32);
emit sendQImage(img); emit sendQImage(img);
QThread::msleep(28); QThread::msleep(28);
} }
} }
av_packet_unref(inputPacket); av_packet_unref(inputPacket);
frm_cnt++;
} }
if (IsstopPlay) { if (IsstopPlay) {
if (m_formatContextSave) { if (m_formatContextSave) {
@ -269,7 +288,7 @@ bool Cffmpeg_decode::openSave() {
ret = avcodec_parameters_from_context(m_videoStreamOut->codecpar, decoderCtx); ret = avcodec_parameters_from_context(m_videoStreamOut->codecpar, decoderCtx);
if (ret < 0) { if (ret < 0) {
// free(); // free();
qWarning() << "DecodeVideo Error"; qWarning() << "avcodec_parameters_from_context Failed";
return false; return false;
} }

@ -1,6 +1,7 @@
#ifndef CFFMPEG_DECODE_H #ifndef CFFMPEG_DECODE_H
#define CFFMPEG_DECODE_H #define CFFMPEG_DECODE_H
#include "ffmpeginclude.h"
#include <QDateTime> #include <QDateTime>
#include <QDebug> #include <QDebug>
#include <QDir> #include <QDir>
@ -10,23 +11,6 @@
#include <QThread> #include <QThread>
#include <QWidget> #include <QWidget>
extern "C" {
#include "libavcodec/avcodec.h"
#include <libavutil/channel_layout.h>
#include <libavutil/common.h>
#include <libavutil/frame.h>
#include <libavutil/imgutils.h>
#include <libavutil/mem.h>
#include <libavutil/opt.h>
#include <libavutil/parseutils.h>
#include <libavutil/samplefmt.h>
#include <libswscale/swscale.h>
#include <libavformat/avformat.h>
}
// class Cffmpeg_decode: public QThread // class Cffmpeg_decode: public QThread
class Cffmpeg_decode : public QObject { class Cffmpeg_decode : public QObject {
Q_OBJECT Q_OBJECT
@ -37,7 +21,6 @@ public:
public: public:
bool open_input_file(); bool open_input_file();
bool IsstopPlay = false;
void stop(); void stop();
/** /**
* @brief * @brief
@ -51,6 +34,12 @@ public slots:
signals: signals:
void sendQImage(QImage); void sendQImage(QImage);
void sendConnectFail(int); void sendConnectFail(int);
void sendInitPushStream_Signal(AVFormatContext *inputFormatCtx);
void sendStreamData_Signal(AVPacket *pkt, int frm_cnt);
public:
bool IsstopPlay = false;
bool bPushStreamFlag = false;
private: private:
AVFormatContext *inputFormatCtx = NULL; // AVFormatContext *inputFormatCtx = NULL; //
@ -72,11 +61,13 @@ private:
unsigned char *out_buffer = nullptr; unsigned char *out_buffer = nullptr;
int videoStreamIndex = -1; int videoStreamIndex = -1;
int videoStreamIndexOut = -1;
int numBytes = -1; int numBytes = -1;
int frm_cnt = 0;
QString _url; QString _url;
QString saveFileDirPath; QString saveFileDirPath;
bool bRecordTime = true;
long long startTime;
/******** 保存裸流使用 ******************/ /******** 保存裸流使用 ******************/
AVFormatContext *m_formatContextSave = nullptr; // 封装上下文 AVFormatContext *m_formatContextSave = nullptr; // 封装上下文
QString m_strCodecName; // 编解码器名称 QString m_strCodecName; // 编解码器名称

@ -0,0 +1,20 @@
#ifndef FFMPEGINCLUDE_H
#define FFMPEGINCLUDE_H
extern "C" {
#include "libavcodec/avcodec.h"
#include <libavformat/avformat.h>
#include <libavutil/channel_layout.h>
#include <libavutil/common.h>
#include <libavutil/frame.h>
#include <libavutil/imgutils.h>
#include <libavutil/mem.h>
#include <libavutil/opt.h>
#include <libavutil/parseutils.h>
#include <libavutil/samplefmt.h>
#include <libavutil/time.h>
#include <libswscale/swscale.h>
}
#endif // FFMPEGINCLUDE_H

@ -0,0 +1,128 @@
#include "ffmpegpushstream.h"
FFmpegPushStream::FFmpegPushStream(QObject *parent) : QObject{parent} {}
/**
* @brief
* @param url
*/
void FFmpegPushStream::setRemoteIP(QString url) { pushStreamIP = url; }
int FFmpegPushStream::openNetworkStream(AVFormatContext *inputFormatCtx) {
if (pushStreamIP.isEmpty())
return -1;
int ret;
// 初始化网络输出流
// const char *output_url = "rtsp://182.92.130.23/app/stream999";
ret = avformat_alloc_output_context2(&outputFormatCtx, NULL, "flv",
pushStreamIP.toUtf8().constData());
if (ret < 0) {
qDebug() << "Could not create output context.";
return -1;
}
// 复制流信息
for (unsigned int i = 0; i < inputFormatCtx->nb_streams; ++i) {
if (inputFormatCtx->streams[i]->codecpar->codec_type ==
AVMEDIA_TYPE_VIDEO) {
AVStream *inputStream = inputFormatCtx->streams[i];
AVStream *outputStream = avformat_new_stream(outputFormatCtx, nullptr);
if (!outputStream) {
qDebug() << "Failed allocating output stream.\n";
return -1;
}
// 复制编解码器参数
ret = avcodec_parameters_copy(outputStream->codecpar,
inputStream->codecpar);
if (ret < 0) {
// free();
qWarning() << "avcodec_parameters_from_context Failed";
return -1;
}
// outputStream->codecpar = inputStream->codecpar;
// outputStream->codecpar->codec_tag = 0;
// outputStream->time_base.num = 1;
break;
}
}
// 打开输出文件
if (!(outputFormatCtx->flags & AVFMT_NOFILE)) {
if (avio_open(&outputFormatCtx->pb, pushStreamIP.toUtf8().constData(),
AVIO_FLAG_WRITE) < 0) {
qDebug() << "Could not open output file.\n";
return -1;
}
}
// 写入头文件
if (avformat_write_header(outputFormatCtx, NULL) < 0) {
qDebug() << "Error occurred when opening output file.\n";
return -1;
}
mInitStatus = true;
this->inputFormatCtx = inputFormatCtx;
return 1;
}
int FFmpegPushStream::pushStream(AVPacket *pkt, int frm_cnt) {
if (!mInitStatus)
return -1;
if (pkt->dts <= 0)
return -1;
int inputStreamIndex = pkt->stream_index;
int outputStreamIndex = 0;
// 没有pts的视频数据如未解码的H.264裸流需要重新计算其pts。
if (pkt->pts == AV_NOPTS_VALUE) {
AVRational time_base = inputFormatCtx->streams[inputStreamIndex]->time_base;
// Duration between 2 frames (us)
int64_t calc_duration =
(double)AV_TIME_BASE /
av_q2d(inputFormatCtx->streams[inputStreamIndex]->r_frame_rate);
// Reset Parameters
pkt->pts = (double)(frm_cnt * calc_duration) /
(double)(av_q2d(time_base) * AV_TIME_BASE);
pkt->dts = pkt->pts;
pkt->duration =
(double)calc_duration / (double)(av_q2d(time_base) * AV_TIME_BASE);
}
// 计算延时后,重新指定时间戳
AVRational istream_base =
inputFormatCtx->streams[inputStreamIndex]->time_base;
AVRational ostream_base =
outputFormatCtx->streams[outputStreamIndex]->time_base;
pkt->pts =
av_rescale_q_rnd(pkt->pts, istream_base, ostream_base,
(AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
pkt->dts =
av_rescale_q_rnd(pkt->dts, istream_base, ostream_base,
(AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
pkt->pts = pkt->pts < 0 ? 0 : pkt->pts;
pkt->dts = pkt->dts < 0 ? 0 : pkt->dts;
pkt->duration =
(int64_t)av_rescale_q(pkt->duration, istream_base, ostream_base);
pkt->pos = -1;
if (pkt->pts < pkt->dts) {
return 1;
}
// 视频帧推送速度
auto pts_time = av_rescale_q(pkt->dts, ostream_base, AVRational{1, 1000});
auto now_time = av_gettime() / 1000;
if (pts_time > now_time) {
qDebug() << "****************sleep time:"
<< QString::number(pts_time - now_time);
av_usleep(static_cast<std::uint32_t>(pts_time - now_time));
}
// 向推流服务器推送流数据
pkt->stream_index = 0;
int ret = av_interleaved_write_frame(outputFormatCtx, pkt);
if (ret < 0) {
return ret;
}
// 数据包写入成功现在可以释放pkt
av_packet_unref(pkt);
}

@ -0,0 +1,32 @@
#ifndef FFMPEGPUSHSTREAM_H
#define FFMPEGPUSHSTREAM_H
#include "ffmpeginclude.h"
#include <QDebug>
#include <QObject>
class FFmpegPushStream : public QObject {
Q_OBJECT
public:
explicit FFmpegPushStream(QObject *parent = nullptr);
/**
* @brief
* @param url
*/
void setRemoteIP(QString url);
signals:
private:
AVFormatContext *inputFormatCtx = nullptr; //
AVFormatContext *outputFormatCtx = NULL; //
AVCodecContext *encoderCtx = nullptr; //
const AVCodec *encoder = nullptr; // 编码器
int videoIndex = -1;
QString pushStreamIP; // 推流地址
bool mInitStatus = false;
public slots:
int pushStream(AVPacket *pkt, int frm_cnt);
int openNetworkStream(AVFormatContext *inputFormatCtx);
};
#endif // FFMPEGPUSHSTREAM_H

@ -5,23 +5,22 @@
ffmpegvideoDlg::ffmpegvideoDlg(QWidget *parent) ffmpegvideoDlg::ffmpegvideoDlg(QWidget *parent)
: QWidget(parent), ui(new Ui::ffmpegvideoDlg) { : QWidget(parent), ui(new Ui::ffmpegvideoDlg) {
ui->setupUi(this); ui->setupUi(this);
// iniWindow(); ffmpegPushStream = nullptr;
pushStreamThread = nullptr;
} }
ffmpegvideoDlg::~ffmpegvideoDlg() { ffmpegvideoDlg::~ffmpegvideoDlg() {
stop(); stop();
delete ui; delete ui;
} if (ffmpegPushStream != nullptr)
ffmpegPushStream->deleteLater();
// 暂未使用 if (pushStreamThread != nullptr) {
void ffmpegvideoDlg::iniWindow() { pushStreamThread->quit();
QString VideoFilePath = QDir::currentPath() + "./Video"; pushStreamThread->wait();
QDir VideoDir(VideoFilePath); pushStreamThread->deleteLater();
if (!VideoDir.exists()) {
VideoDir.mkdir(VideoFilePath);
qDebug() << "文件夹创建成功";
} }
} }
void ffmpegvideoDlg::setVedioSaveFileDirPath(QString saveDirPath) { void ffmpegvideoDlg::setVedioSaveFileDirPath(QString saveDirPath) {
videoSaveDirPath = saveDirPath; videoSaveDirPath = saveDirPath;
} }
@ -32,6 +31,8 @@ void ffmpegvideoDlg::play(QString url) {
ffmpeg = new Cffmpeg_decode; ffmpeg = new Cffmpeg_decode;
ffmpeg->setSaveFileDirPath(videoSaveDirPath); ffmpeg->setSaveFileDirPath(videoSaveDirPath);
ffmpeg->IsstopPlay = false; ffmpeg->IsstopPlay = false;
if (!pushStreamIP.isEmpty()) // 推流
startPushStream(m_PlayStatus);
ffmpeg->moveToThread(&workerThread); ffmpeg->moveToThread(&workerThread);
connect(&workerThread, &QThread::finished, ffmpeg, connect(&workerThread, &QThread::finished, ffmpeg,
@ -46,16 +47,19 @@ void ffmpegvideoDlg::play(QString url) {
SLOT(showMessagBox(int))); // 发送错误信息提示 SLOT(showMessagBox(int))); // 发送错误信息提示
workerThread.start(); workerThread.start();
emit this->setUrlSign(url);// 设置URL emit this->setUrlSign(url); // 设置URL
emit this->operate(); // 启用线程信号 emit this->operate(); // 启用线程信号
} }
} }
void ffmpegvideoDlg::stop() { void ffmpegvideoDlg::stop() {
if (m_PlayStatus) { if (m_PlayStatus) {
ffmpeg->stop(); ffmpeg->stop();
m_PlayStatus = false; m_PlayStatus = false;
ffmpeg->IsstopPlay = true; // 线程结束标志 ffmpeg->IsstopPlay = true; // 线程结束标志
workerThread.quit(); // 线程退出时自动delete线程里的类 if (!pushStreamIP.isEmpty()) // 停止推流
startPushStream(m_PlayStatus);
workerThread.quit(); // 线程退出时自动delete线程里的类
workerThread.wait(); workerThread.wait();
img.fill(Qt::black); img.fill(Qt::black);
} }
@ -108,3 +112,30 @@ void ffmpegvideoDlg::showMessagBox(int type) {
bool ffmpegvideoDlg::Isplay(bool IsstopPlay) { bool ffmpegvideoDlg::Isplay(bool IsstopPlay) {
return ffmpeg->IsstopPlay = IsstopPlay; return ffmpeg->IsstopPlay = IsstopPlay;
} }
void ffmpegvideoDlg::startPushStream(bool bPush) {
if (bPush) {
if (ffmpegPushStream == nullptr) {
ffmpegPushStream = new FFmpegPushStream;
ffmpegPushStream->setRemoteIP(pushStreamIP); // 设置推流地址
}
if (pushStreamThread == nullptr) {
pushStreamThread = new QThread;
pushStreamThread->start();
ffmpegPushStream->moveToThread(pushStreamThread);
}
connect(ffmpeg, &Cffmpeg_decode::sendInitPushStream_Signal,
ffmpegPushStream, &FFmpegPushStream::openNetworkStream);
connect(ffmpeg, &Cffmpeg_decode::sendStreamData_Signal, ffmpegPushStream,
&FFmpegPushStream::pushStream);
ffmpeg->bPushStreamFlag = true;
} else {
if (ffmpeg)
ffmpeg->bPushStreamFlag = false;
}
}
void ffmpegvideoDlg::setPushStreamIP(QString pushStreamURL) {
pushStreamIP = pushStreamURL;
}

@ -2,6 +2,8 @@
#define FFMPEGVIDEODLG_H #define FFMPEGVIDEODLG_H
#include "cffmpeg_decode.h" #include "cffmpeg_decode.h"
#include "ffmpeginclude.h"
#include "ffmpegpushstream.h"
#include <QDebug> #include <QDebug>
#include <QDir> #include <QDir>
#include <QImage> #include <QImage>
@ -10,23 +12,6 @@
#include <QThread> #include <QThread>
#include <QWidget> #include <QWidget>
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavutil/channel_layout.h>
#include <libavutil/common.h>
#include <libavutil/frame.h>
#include <libavutil/imgutils.h>
#include <libavutil/mem.h>
#include <libavutil/opt.h>
#include <libavutil/parseutils.h>
#include <libavutil/samplefmt.h>
#include <libswscale/swscale.h>
#include <libavformat/avformat.h>
}
namespace Ui { namespace Ui {
class ffmpegvideoDlg; class ffmpegvideoDlg;
} }
@ -38,18 +23,19 @@ public:
explicit ffmpegvideoDlg(QWidget *parent = nullptr); explicit ffmpegvideoDlg(QWidget *parent = nullptr);
~ffmpegvideoDlg(); ~ffmpegvideoDlg();
private:
Ui::ffmpegvideoDlg *ui;
public:
void iniWindow();
void setVedioSaveFileDirPath(QString saveDirPath); void setVedioSaveFileDirPath(QString saveDirPath);
void play(QString); void play(QString);
void stop(); void stop();
bool Isplay(bool IsstopPlay); bool Isplay(bool IsstopPlay);
bool m_PlayStatus = false; void startPushStream(bool bPush);
void setPushStreamIP(QString pushStreamURL);
private:
Ui::ffmpegvideoDlg *ui;
public:
bool m_PlayStatus = false;
double m_setVideoAreaWidth; double m_setVideoAreaWidth;
double m_setVideoAreaHeight; double m_setVideoAreaHeight;
double m_ax; double m_ax;
@ -71,6 +57,9 @@ private:
QThread workerThread; QThread workerThread;
QImage img; QImage img;
QString videoSaveDirPath; QString videoSaveDirPath;
QThread *pushStreamThread;
FFmpegPushStream *ffmpegPushStream;
QString pushStreamIP;
}; };
#endif // FFMPEGVIDEODLG_H #endif // FFMPEGVIDEODLG_H

Loading…
Cancel
Save