Qt/C++编写音视频实时通话/画中画/设备热插拔/本地摄像头和桌面

360影视 动漫周边 2025-05-16 16:39 2

摘要:#include "frmconfig.h"#include "frmmain.h"#include "ui_frmmain.h"#include "qthelper.h"#include "apphelper.h"#include "osdgraph.h"#

近期有客户提需求,需要在嵌入式板子上和电脑之间音视频通话,要求用Qt开发,可以用第三方的编解码组件,能少用就尽量少用,以便后期移植起来方便。如果换成5年前的知识储备,估计会采用纯网络通信收发图片和声音数据方式实现,比如用qcamera打开摄像头,转成图片,base64编码发送,接收到收到后base64解码成图片绘制,声音用qaudioinput采集后pcm数据直接tcp发送,收到后直接发给qaudiooutput设备播放即可。这种能不能实现效果呢,也是可以的,就是体验不大好友好,比如画面的流畅度要低不少,估计只能做到20fps,而且双方只能用私有协议通信,外部如果要取流比如在网页查看通话的视频,无法实现。

按照现在的知识储备,方案就很多了,最佳方案就是用推拉流,实时性极好,局域网可以做到0.2s内,而且音视频通话都是实时的,可以连续7*24小时运行,而且可以拓展成一对多通话,多一个人员加入只需要多一路拉流就行,非常的方便,悬浮画面还可以设置各种位置,使用下来的效果非常的棒。所以随着知识储备的增加,以前无法解决的疑难杂症,现在只需要分分钟就搞定。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

#include "frmconfig.h"#include "frmmain.h"#include "ui_frmmain.h"#include "qthelper.h"#include "apphelper.h"#include "osdgraph.h"#include "ffmpegthread.h"#include "ffmpegthreadcheck.h"frmMain::frmMain(QWidget *parent) : QWidget(parent), ui(new Ui::frmMain){ui->setupUi(this);this->initForm;this->installEventFilter(this);QMetaObject::invokeMethod(this, "formChanged", Qt::QueuedConnection);}frmMain::~frmMain{delete ui;}void frmMain::savePos{AppConfig::FormMax = this->isMaximized;if (!AppConfig::FormMax) {AppConfig::FormGeometry = this->geometry;}AppConfig::writeConfig;}bool frmMain::eventFilter(QObject *watched, QEvent *event){//尺寸发生变化或者窗体移动位置记住窗体位置int type = event->type;if (type == QEvent::Resize || type == QEvent::Move) {QMetaObject::invokeMethod(this, "savePos", Qt::QueuedConnection);} else if (type == QEvent::Close) {audioInput->stop(false);audioOutput->stop(false);exit(0);}//尺寸发生变化重新调整小预览窗体的位置if (this->isVisible && type == QEvent::Resize) {this->formChanged;}return QWidget::eventFilter(watched, event);}void frmMain::initForm{//初始化输入输出视频控件AppHelper::initVideoWidget(ui->videoInput);AppHelper::initVideoWidget(ui->videoOutput);//初始化输入输出音频线程audioInput = new FFmpegThread(this);audioOutput = new FFmpegThread(this);checkInput = new FFmpegThreadCheck(audioInput, this);AppHelper::initAudioThread(audioInput, ui->levelInput);AppHelper::initAudioThread(audioOutput, ui->levelOutput);//输入打开成功后立即推流connect(audioInput, SIGNAL(receivePlayStart(int)), this, SLOT(receivePlayStart(int)));connect(ui->videoInput, SIGNAL(sig_receivePlayStart(int)), this, SLOT(receivePlayStart(int)));ui->ckInput->setChecked(AppConfig::MuteInput ? Qt::Checked : Qt::Unchecked);ui->ckOutput->setChecked(AppConfig::MuteOutput ? Qt::Checked : Qt::Unchecked);if (AppConfig::StartServer) {on_btnStart_clicked;}}void frmMain::clearLevel{ui->levelInput->setLevel(0);ui->levelOutput->setLevel(0);}void frmMain::formChanged{AppHelper::changeWidget(ui->videoInput, ui->videoOutput, ui->gridLayout, NULL);}void frmMain::receivePlayStart(int time){QObject *obj = sender;if (obj == ui->videoInput) {#ifdef betaversionOsdGraph::testOsd(ui->videoInput);#endifui->videoInput->recordStart(AppConfig::VideoPush);} else if (obj == audioInput) {audioInput->recordStart(AppConfig::AudioPush);}}void frmMain::on_btnStart_clicked{if (ui->btnStart->text == "启动服务") {if (AppConfig::VideoUrl == "video=" || AppConfig::AudioUrl == "audio=") {QtHelper::showMessageBoxError("请先打开系统设置, 选择对应的视音频设备");//return;}ui->videoInput->open(AppConfig::VideoUrl);ui->videoOutput->open(AppConfig::VideoPull);audioInput->setMediaUrl(AppConfig::AudioUrl);audioOutput->setMediaUrl(AppConfig::AudioPull);audioInput->play;audioOutput->play;checkInput->start;ui->btnStart->setText("停止服务");} else {ui->videoInput->stop;ui->videoOutput->stop;audioInput->stop;audioOutput->stop;checkInput->stop;ui->btnStart->setText("启动服务");QMetaObject::invokeMethod(this, "clearLevel", Qt::QueuedConnection);}AppConfig::StartServer = (ui->btnStart->text == "停止服务");AppConfig::writeConfig;}void frmMain::on_btnConfig_clicked{static frmConfig *config = NULL;if (!config) {config = new frmConfig;connect(config, SIGNAL(formChanged), this, SLOT(formChanged));}config->show;config->activateWindow;}void frmMain::on_ckInput_stateChanged(int arg1){bool muted = (arg1 != 0);audioInput->setMuted(muted);AppConfig::MuteInput = muted;AppConfig::writeConfig;}void frmMain::on_ckOutput_stateChanged(int arg1){bool muted = (arg1 != 0);audioOutput->setMuted(muted);AppConfig::MuteOutput = muted;AppConfig::writeConfig;}

来源:Qt自定义控件

相关推荐