• 632阅读
  • 1回复

Qt音视频开发18-不同视频打开无缝切换 [复制链接]

上一主题 下一主题
离线liudianwu
 

只看楼主 倒序阅读 楼主  发表于: 2023-02-28


## 一、前言
在轮询视频的时候,通常都是需要将之前的视频全部关闭,然后打开下一组视频,在这个切换的过程中,如果是按照常规的做法,比如先关闭再打开新的视频,肯定会出现空白黑屏之类的过度空白区间,如何避免这个问题实现无感知的无缝切换,是个需要稍微懂点脑筋的问题,有一个比较好的做法就是,准备双倍的通道或者后台解码线程,在收到需要切换指令的时候,先后台打开解码线程,直到打开完成能够正常出图像,此时再去关闭之前的解码线程,这样就相当于无缝对接上了,不会说是中间等待打开解码到能正常出图像的过程空白。但是这样又存在一个问题,那就是轮询间隔时间不是非常准确,会有个1-2s的偏差,基本上这个偏差也能接受就是,所以如果是60s的轮询间隔,你可以在58s的时候就开始打开另外一组的解码线程,2s后全部正常出图像后就关联到视频控件上显示,把之前的解码线程关闭并销毁。这样处理下来,既保证了切换过程无感知,又保证了不会过度开销占用CPU,也就切换的期间刚好有双倍的解码线程,只要内存足够,这点性能牺牲还是值得的。

## 二、效果图




## 三、体验地址
1. 国内站点:[https://gitee.com/feiyangqingyun](https://gitee.com/feiyangqingyun)
2. 国际站点:[https://github.com/feiyangqingyun](https://github.com/feiyangqingyun)
3. 个人作品:[https://blog.csdn.net/feiyangqingyun/article/details/97565652](https://blog.csdn.net/feiyangqingyun/article/details/97565652)
4. 体验地址:[https://pan.baidu.com/s/1d7TH_GEYl5nOecuNlWJJ7g](https://pan.baidu.com/s/1d7TH_GEYl5nOecuNlWJJ7g) 提取码:01jf 文件名:bin_video_demo/bin_linux_video。

## 四、相关代码
```cpp
#include "frmdemovideochange.h"
#include "ui_frmdemovideochange.h"
#include "quihelper.h"
#include "videourl.h"
#include "videohelper.h"
#include "videowidgetx.h"

frmDemoVideoChange::frmDemoVideoChange(QWidget *parent) : QWidget(parent), ui(new Ui::frmDemoVideoChange)
{
    ui->setupUi(this);
    this->initForm();
}

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

void frmDemoVideoChange::showEvent(QShowEvent *)
{
    static bool isLoad = false;
    if (!isLoad) {
        isLoad = true;
        on_btnChange_clicked();
    }
}

void frmDemoVideoChange::initForm()
{
    ui->cboxUrl->addItems(VideoUrl::getUrls(VideoUrl::HttpVideo | VideoUrl::Other));
    ui->cboxUrl2->addItems(VideoUrl::getUrls(VideoUrl::HttpVideo | VideoUrl::Other));
    ui->cboxUrl->lineEdit()->setText(AppConfig::VideoChangeUrl1);
    ui->cboxUrl2->lineEdit()->setText(AppConfig::VideoChangeUrl2);

    //实例化视频控件(这里放两个用于交替无缝切换)
    videoWidget1 = new VideoWidget;
    videoWidget2 = new VideoWidget;
    this->initVideo(videoWidget1);
    this->initVideo(videoWidget2);

    currentIndex = 1;
    videoWidget1->setVisible(true);
}

void frmDemoVideoChange::initVideo(VideoWidget *videoWidget)
{
    //设置窗体参数
    WidgetPara widgetPara = videoWidget->getWidgetPara();
    widgetPara.fillColor = "#110F11";
    widgetPara.scaleMode = ScaleMode_Aspect;
    videoWidget->setWidgetPara(widgetPara);

    //设置解码内核
    VideoPara videoPara = videoWidget->getVideoPara();
    VideoHelper::initVideoCore(videoPara);
    videoWidget->setVideoPara(videoPara);

    //加入到布局并关联打开成功信号
    videoWidget->setVisible(false);
    ui->gridLayout->addWidget(videoWidget);
    connect(videoWidget, SIGNAL(sig_receivePlayStart(int)), this, SLOT(receivePlayStart(int)));
}

void frmDemoVideoChange::receivePlayStart(int time)
{
    ui->btnChange->setEnabled(true);
    if (currentIndex == 0) {
        videoWidget2->setVisible(false);
        videoWidget1->setVisible(true);
        videoWidget2->stop();
    } else if (currentIndex == 1) {
        videoWidget1->setVisible(false);
        videoWidget2->setVisible(true);
        videoWidget1->stop();
    }
}

void frmDemoVideoChange::on_btnChange_clicked()
{
    ui->btnChange->setEnabled(false);
    currentIndex = (currentIndex == 0 ? 1 : 0);
    AppConfig::VideoChangeUrl1 = ui->cboxUrl->currentText();
    AppConfig::VideoChangeUrl2 = ui->cboxUrl2->currentText();
    AppConfig::writeConfig();

    //先后台默默的打开不显示(等待打开成功后再显示)
    if (currentIndex == 0) {
        videoWidget1->open(AppConfig::VideoChangeUrl1);
    } else if (currentIndex == 1) {
        videoWidget2->open(AppConfig::VideoChangeUrl2);
    }
}
```
4条评分好评度+1贡献值+1金钱+10威望+1
20091001753 好评度 +1 - 2023-03-01
20091001753 贡献值 +1 - 2023-03-01
20091001753 威望 +1 - 2023-03-01
20091001753 金钱 +10 - 2023-03-01
欢迎关注微信公众号:Qt实战/Qt入门和进阶(各种开源作品、经验整理、项目实战技巧,专注Qt/C++软件开发,视频监控、物联网、工业控制、嵌入式软件、国产化系统应用软件开发) QQ:517216493  WX:feiyangqingyun  QQ群:751439350
离线tanyue.esec

只看该作者 1楼 发表于: 2023-03-03


试试看去
快速回复
限100 字节
 
上一个 下一个