ffpmeg笔记:(2)学习一个开源小demo:qt+sdl+ffmpeg,计算时间戳
创始人
2025-05-31 15:45:36
0

文章目录

  • 前言
  • 1.源码和编译方法
    • 1.1编译方法:
  • 2.源码简单介绍
    • 2.1 播放线程类 PlayThread
      • 2.1.1 计算当前播放进度时间
    • 2.2 主界面类 MainWindow
      • 2.2.1 在Qt widget中显示视频
      • 2.2.2 控制区域的自动隐藏和再现

前言

这个小demo实现了下面的功能:

1.打开文件。
2.播放。
3.暂停。
4.停止。
5.进度条显示,视频时长,当前进度时间。
6.控制面板隐藏和再现。

应该实现却没有实现的功能:

1.倍速播放
2.滑动进度条指定播放位置
3.音量调节

demo的效果:

https://www.bilibili.com/video/BV1Vv4y1j7sw/?spm_id_from=333.999.0.0&vd_source=f724775496aa565e12020e8529f8b274

1.源码和编译方法

原工程:https://gitee.com/tgtsml/QtPlayer
改动后工程:https://gitee.com/huangweide001/hwd-qt-demo/tree/master/QtPlayer-004

1.1编译方法:

我使用的版本是 Qt 5.14.1
1.使用qtCreator打开《QtSdlPlayer.pro》;
2.选择Qt的工具集 MinGW_64_bit;
3.构建项目,在工程目录下自动生成bin目录,用于存放exe文件。把下面的文件拷贝到本bin目录:

3.1 《3rdlib\ffmpeg-4.4-full_build-shared\bin*》
3.2 《3rdlib\SDL2\bin*》

4.在Qt中点击运行。

2.源码简单介绍

2.1 播放线程类 PlayThread

类PlayThread主要完成音视频的播放流程,相关的原理性介绍参考雷神的文章:最简单的基于FFMPEG+SDL的视频播放器 ver2 (采用SDL2.0)。
在播放流程的基础上,增加了几个发送信号的函数:

class PlayThread : public QThread
{Q_OBJECTvoid run() override;signals:void signal_updateDisplayImage(QImage img);	//	发送画面更新信号void signal_updateTotalTime(QTime time);	//	发送视频的长度void signal_updatePlayedTime(QTime time);	//	发送播放进度时间void signal_PlayedDone(void);				//	发送播放完毕信号
......
}    

这些信号对应主界面类MainWindow的槽函数。

2.1.1 计算当前播放进度时间

在这里插入图片描述
AVRational vedio_time_base= pFormatCtx->streams[videoindex]->time_base;
current_play_time = pFrame->pts * av_q2d(vedio_time_base);
在更新视频帧的位置加入计算当前进度时间的代码,单位为秒;因为一秒有约30个视频帧,不必每次更新视频帧时一起更新时间;所以做一下判断,只有秒数发生变化,才通知主界面更新当前进度时间。

                    ticks = pFrame->pts * av_q2d(vedio_time_base);		//计算当前时间戳//当进度秒数有变化时,发送信号通知界面if(old_sec != ticks){old_sec = ticks;qDebug()<

2.2 主界面类 MainWindow

类 MainWindow显示界面包括视频区域和控制区域,控制区域当鼠标移动时显示,鼠标停止动作3秒后隐藏。和PlayThread的信号对应的槽函数:

class MainWindow : public QMainWindow
{Q_OBJECT
public:MainWindow(QWidget *parent = nullptr);~MainWindow();void slot_updateCurrentImage(QImage img);void slot_updateTotalTime(QTime time);void slot_updatePlayedTime(QTime time);void slot_PlayedDone(void);
......
}    

2.2.1 在Qt widget中显示视频

本demo显示视频的方式是在视频解码时,生成一个QImage的对象,再把QImage通过信号和槽函数的方式传输。
在类PlayThread中生成QImage,并发送信号:

	sws_scale(img_convert_ctx, (const unsigned char* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx_Video->height, pFrameYUV->data, pFrameYUV->linesize);QImage tmpImg((uchar *)out_buffer_video, pCodecCtx_Video->width, pCodecCtx_Video->height,QImage::Format_RGB32);QImage image = tmpImg.copy(); //把图像复制一份 传递给界面显示emit signal_updateDisplayImage(image);  //发送界面刷新信号

在类MainWindow中的槽函数接收QImage:

void MainWindow::slot_updateCurrentImage(QImage img)
{m_currentImage = img;update();
}
void MainWindow::paintEvent(QPaintEvent *)
{QPainter painter(this);painter.setBrush(Qt::black);painter.drawRect(0, 0, this->width(), this->height());if (m_currentImage.size().width() <= 0){return;}QImage img = m_currentImage.scaled(this->size(), Qt::KeepAspectRatio);int x = this->width() - img.width();int y = this->height() - img.height();painter.drawImage(x/2.0, y/2.0, img);
}

2.2.2 控制区域的自动隐藏和再现

在类MainWindow的构造函数中,开启一个定时器,每次启动后,单次触发。

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);
......m_timerToHideControlBar = new QTimer(this);m_timerToHideControlBar->setSingleShot(true);	//	单次触发//	定时时间到,触发进度条隐藏的动作connect(m_timerToHideControlBar, &QTimer::timeout, [=](){ui->widget_playControlWgt->setVisible(false);});
}

鼠标按下或者移动时,显示进度条,并启动3秒的定时:

void MainWindow::restartControlBarHideTimer()
{if(! ui->widget_playControlWgt->isVisible() || m_timerToHideControlBar->isActive()){m_timerToHideControlBar->stop();ui->widget_playControlWgt->setVisible(true);}m_timerToHideControlBar->start(3000);
}
void MainWindow::mousePressEvent(QMouseEvent *event)
{restartControlBarHideTimer();QMainWindow::mousePressEvent(event);
}
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{restartControlBarHideTimer();QMainWindow::mouseMoveEvent(event);
}

相关内容

热门资讯

常熟人吃鱼的108种姿势:从科... 一条鲤鱼游出的千年文化密码 当苏州少年金耀星在天津全国烹饪大赛上,用迷你版果汁松鼠桂鱼斩获特金奖时,...
旅游还有哪些不开心的事 旅游中的“闹心”事儿,你遇到过几件? 旅游,本是一场逃离日常琐碎,奔赴诗和远方的美好旅程。然而,现...
陕西金延安端午文旅盛宴点燃文化... 又是一年端阳到,龙舟竞渡粽香飘。节日期间,陕西省延安市金延安旅游度假区将红色演艺与主题教育相结合,精...
去四川旅游攻略旅游团五日游要花... 标题:【我的四川五日游亲测报告:跟着本地导游乐乐玩转四川,花费竟如此实惠!】 四川旅游推荐!当地导游...
全球农创客训练营走进云南以“咖... 央广网北京6月2日消息(记者韩雪莹)据中央广播电视总台中国之声《新闻纵横》报道,一杯咖啡,可以让人头...
15道 旺销特色菜,创意融合 藜蒿炒腊肉 原料: 腊肉(肥三瘦七)300克,鄱阳湖藜蒿300克,韭菜段150克,盐、红辣椒段、蒜...
家里有个会做饭的男人太幸福了,... 姐妹们!你们知道家里有个会做饭的老公是什么体验吗?那就是——每天下班回家都能吃到热腾腾的饭菜,关键还...
原创 5... 姐妹们,今天给你们分享个我家每周必吃的省钱神菜—— 酸辣土豆丝!成本不到5块钱,10分钟出锅,每次炒...
原创 半... 朋友们,今天教你们一个偷懒都能被夸厨神的神仙做法! 只要电饭锅会煮饭,你就能做出甜到粘嘴唇的照烧五花...
原创 R... 曾经风头无两的韩国超级偶像Rain与他的妻子金泰熙已经携手走过七个年头,虽然外界对他们婚后生活的报道...
“龙腾端午·梧现精彩”非遗好市... 6月1日,由梧州市文化广电体育和旅游局主办的“龙腾端午·梧现精彩”非遗好市在梧州市西堤公园持续开展。...
上海海派旗袍文化节开幕,推出3... 静态展览,动态走秀,互动体验……6月1日,“旗韵绽芳华”——6·6上海海派旗袍文化节在张园拉开帷幕。...
华程国旅推出“欧洲循环巴士游” 英国当地时间5月27日下午,华程国旅集团TRIP2EU“欧洲循环巴士游”发布会伦敦站在伦敦千禧酒店举...
原创 6... “来来来,尝尝我们厂的窑鸡,特意给你加的菜!”何家劲笑容满面,将一整盘热腾腾的窑鸡推到黄日华面前。 ...
原创 以... #优质好文激励计划# “以前人人爱吃的小龙虾,为啥现在不火了?内行:4个原因很难改变” 家人们,谁...
吉木萨尔县第三届厦吉文化美食汇... 5月31日,为期3天的“百味醉天山 闽疆共飨宴”昌吉州旅游文化美食节系列活动之吉木萨尔县第三届厦吉文...
去四川旅游攻略当地团五天四晚要... 标题:去四川旅游攻略当地团五天四晚要花多少钱,驴友亲测!跟着乐乐玩转四川 四川旅游推荐!当地导游-乐...
上海迪士尼游客打架,属地部门:... 上海市公安局浦东分局官方微博6月1日消息,5月31日18时许,浦东公安分局接报警称迪士尼乐园内有人打...
“去中国要带空箱子!”在国外传... 随着“中国游”的便利性和吸引力不断上升,游在中国、购在中国成为越来越多国际游客的新选择 。 最近,“...
重庆家常美食菜谱,地道风味,轻... 重庆家常美味菜谱是一本介绍重庆地道美食的烹饪书籍,本书通过简单易懂的方式,呈现地道的重庆风味菜肴,读...