目前BPlay1.0的主要功能(视频播放)已经基本实现,但是开启/暂停按钮和进度条还是无法控制视频的播放进度,本节将这两个功能收尾掉。
1、按钮联动
在 BPlay1.0系列(5:自定义按钮控件) 里面,我们基本实现了按钮消息的获取和状态位图的功能,关键代码是这个鼠标释放事件回调:Bbutton::mouseReleaseEvent,我们需要在里面新增一个视频开启/暂停的方法(LinkFfmpeg())即可:
/********************************
* void Bbutton::mouseReleaseEvent(QMouseEvent *e)
* 功能:鼠标释放事件回调
* *****************************/
void Bbutton::mouseReleaseEvent(QMouseEvent *e)
{
BLOG("Bbutton::mouseReleaseEvent");
QPixmap Pix;
QString Image;
Status = !Status;
Image = Status ? BbuttonImage1 : BbuttonImage2;
bool ret = Pix.load(Image);
if (!ret) {
BLOG( "Load Image1 fail");
return;
}
this->setIcon(Pix); /* 设置图标 */
/* 联动视频开启/暂停 */
LinkFfmpeg();
return;
}
LinkFfmpeg()里面主要是根据按钮的状态来控制解封装和解码线程的开启与暂停,实现如下:
/********************************
* void Bbutton::LinkFfmpeg()
* 功能:开启/暂停视频
* *****************************/
void Bbutton::LinkFfmpeg()
{
if (Status) {
Bffmpeg::GetInstance()->StartPlay();
} else {
Bffmpeg::GetInstance()->StopPlay();
}
return;
}
/********************************
* void Bffmpeg::StartPlay()
* 功能:开始播放媒体文件
* *****************************/
void Bffmpeg::StartPlay()
{
this->start();
Bvideo::GetInstance()->start();
Baudio::GetInstance()->start();
return;
}
/********************************
* void Bffmpeg::StopPlay()
* 功能:暂停播放媒体文件
* *****************************/
void Bffmpeg::StopPlay()
{
ffmpegrun = false;
Bvideo::GetInstance()->stop();
Baudio::GetInstance()->stop();
return;
}
2、进度条
进度条条主要有两个功能,一是根据显示当前视频播放的进度,二是修改视频播放的进度。显示播放进度是通过在主窗口添加了一个定时器实时更新视频的Pts:
/********************************
* MainWindow::MainWindow(QWidget *parent)
* 功能:主窗口构造函数
* *****************************/
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
/* 开始/停止播放按钮 */
OnOffBbutton = new Bbutton(":/Image/on.png", ":/Image/off.png");
OnOffBbutton->setParent(this);
OnOffBbutton->move(50, 530);
ui->BPlaySlider->setValue(0);
ui->MediaAllTime->setText("00:00");
ui->MediaPlayTime->setText("00:00");
/* 进度条刷新 */
connect(&UpdateTimer, &QTimer::timeout, [=](){
int TimeAll = (int)Bffmpeg::GetInstance()->GetTimeAll();
int Pts = (int)Bffmpeg::GetInstance()->GetAudioPts();
ui->MediaAllTime->setText(QString("%1:%2:%3").arg(TimeAll / 3600).arg((TimeAll % 3600) / 60).arg(TimeAll % 60));
ui->MediaPlayTime->setText(QString("%1:%2:%3").arg(Pts / 3600).arg((Pts % 3600) / 60).arg(Pts % 60));
if (!BPlaySliderPress) {
ui->BPlaySlider->setMaximum(TimeAll);
ui->BPlaySlider->setValue(Pts);
}
});
UpdateTimer.start(100);
}
修改视频播放的进度则是重写进度块按下释放的回调,根据最终进度条的位置来跳转媒体帧:
/********************************
* void MainWindow::on_BPlaySlider_sliderPressed()
* 功能:滑动条点击回调函数
* *****************************/
void MainWindow::on_BPlaySlider_sliderPressed()
{
BPlaySliderPress = true;
return;
}
/********************************
* void MainWindow::on_BPlaySlider_sliderPressed()
* 功能:滑动条释放回调函数
* *****************************/
void MainWindow::on_BPlaySlider_sliderReleased()
{
BPlaySliderPress = false;
Bffmpeg::GetInstance()->ResetTime(ui->BPlaySlider->value());
return;
}
/********************************
* double Bffmpeg::GetTimeAll()
* 功能:重设视频播放时间(进度)
* *****************************/
void Bffmpeg::ResetTime(int Time)
{
StopPlay();
Bffmpeg::GetInstance()->GetAudioQue().que.clear();
Bffmpeg::GetInstance()->GetVideoQue().que.clear();
QMutexLocker locker(&ffmpegMutex);
if (!FormatContext)
{
BLOG("FormatContext NULL");
return;
}
/* 根据滑动条重设视频播放点 */
av_seek_frame(FormatContext, -1, (int64_t)Time * AV_TIME_BASE, AVSEEK_FLAG_ANY);
StartPlay();
return;
}
最终效果如下: