avplayerwidget.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. #include "avplayerwidget.h"
  2. #include "avopenglwidget.h"
  3. #include "av_player.h"
  4. #include "vframe.h"
  5. AVPlayerWidget::AVPlayerWidget(QWidget *parent)
  6. : QWidget{parent}
  7. , m_player(new AVPlayer)
  8. , m_openglWidget(new AVOpenGLWidget(this))
  9. , m_isPlaying(false)
  10. , m_isPaused(false)
  11. {
  12. // 设置尺寸策略,确保能够正确填充空间
  13. setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
  14. setupUI();
  15. connectSignals();
  16. // 设置默认音量
  17. m_player->setVolume(50);
  18. m_volumeSlider->setValue(50);
  19. // 设置默认测试URL
  20. m_urlEdit->setText("rtmp://106.55.186.74:1935/stream/V1/");
  21. }
  22. AVPlayerWidget::~AVPlayerWidget()
  23. {
  24. if (m_player) {
  25. m_player->clearPlayer();
  26. }
  27. }
  28. void AVPlayerWidget::setupUI()
  29. {
  30. m_mainLayout = new QVBoxLayout(this);
  31. m_mainLayout->setContentsMargins(5, 5, 5, 5); // 减少主布局边距
  32. m_mainLayout->setSpacing(5); // 减少组件间距
  33. // 添加OpenGL视频渲染组件
  34. m_mainLayout->addWidget(m_openglWidget, 1);
  35. // 创建控制面板容器
  36. QWidget *controlWidget = new QWidget(this);
  37. controlWidget->setFixedHeight(60); // 设置控制面板固定高度
  38. controlWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
  39. m_controlLayout = new QHBoxLayout(controlWidget);
  40. m_controlLayout->setContentsMargins(5, 5, 5, 5); // 减少控制面板内边距
  41. m_controlLayout->setSpacing(5); // 减少控件间距
  42. // URL输入框
  43. m_urlEdit = new QLineEdit(this);
  44. m_urlEdit->setPlaceholderText("输入视频文件路径或URL");
  45. m_urlEdit->setFixedHeight(30); // 固定高度适应控制面板
  46. m_urlEdit->setFont(QFont("Arial", 9));
  47. m_controlLayout->addWidget(m_urlEdit, 2);
  48. // 测试播放按钮
  49. m_testPlayButton = new QPushButton("测试播放", this);
  50. m_testPlayButton->setFixedSize(70, 30); // 固定尺寸
  51. m_testPlayButton->setFont(QFont("Arial", 9, QFont::Bold));
  52. m_controlLayout->addWidget(m_testPlayButton);
  53. // 播放控制按钮
  54. m_playButton = new QPushButton("播放", this);
  55. m_playButton->setFixedSize(50, 30); // 固定尺寸
  56. m_playButton->setFont(QFont("Arial", 9, QFont::Bold));
  57. m_pauseButton = new QPushButton("暂停", this);
  58. m_pauseButton->setFixedSize(50, 30); // 固定尺寸
  59. m_pauseButton->setFont(QFont("Arial", 9, QFont::Bold));
  60. m_stopButton = new QPushButton("停止", this);
  61. m_stopButton->setFixedSize(50, 30); // 固定尺寸
  62. m_stopButton->setFont(QFont("Arial", 9, QFont::Bold));
  63. m_controlLayout->addWidget(m_playButton);
  64. m_controlLayout->addWidget(m_pauseButton);
  65. m_controlLayout->addWidget(m_stopButton);
  66. // 音量控制
  67. QLabel *volumeLabel = new QLabel("音量:", this);
  68. volumeLabel->setFont(QFont("Arial", 9));
  69. m_volumeSlider = new QSlider(Qt::Horizontal, this);
  70. m_volumeSlider->setRange(0, 100);
  71. m_volumeSlider->setValue(50);
  72. m_volumeSlider->setFixedSize(100, 20); // 固定尺寸
  73. m_controlLayout->addWidget(volumeLabel);
  74. m_controlLayout->addWidget(m_volumeSlider);
  75. // 时间显示
  76. m_timeLabel = new QLabel("00:00 / 00:00", this);
  77. m_timeLabel->setFont(QFont("Arial", 9));
  78. m_timeLabel->setFixedWidth(80);
  79. m_controlLayout->addWidget(m_timeLabel);
  80. m_mainLayout->addWidget(controlWidget, 0); // 拉伸因子为0,不占用额外空间
  81. // 设置初始状态
  82. m_pauseButton->setEnabled(false);
  83. m_stopButton->setEnabled(false);
  84. controlWidget->hide();
  85. }
  86. void AVPlayerWidget::connectSignals()
  87. {
  88. // 连接AVPlayer信号
  89. connect(m_player, &AVPlayer::frameChanged, this, &AVPlayerWidget::onFrameChanged, Qt::QueuedConnection);
  90. connect(m_player, &AVPlayer::AVDurationChanged, this, &AVPlayerWidget::durationChangedSlot);
  91. connect(m_player, &AVPlayer::AVPtsChanged, this, &AVPlayerWidget::ptsChangedSlot);
  92. connect(m_player, &AVPlayer::AVTerminate, this, &AVPlayerWidget::terminateSlot, Qt::QueuedConnection);
  93. // 连接UI控件信号
  94. connect(m_playButton, &QPushButton::clicked, this, &AVPlayerWidget::onPlayButtonClicked);
  95. connect(m_pauseButton, &QPushButton::clicked, this, &AVPlayerWidget::onPauseButtonClicked);
  96. connect(m_stopButton, &QPushButton::clicked, this, &AVPlayerWidget::onStopButtonClicked);
  97. connect(m_testPlayButton, &QPushButton::clicked, this, &AVPlayerWidget::onTestPlayButtonClicked);
  98. connect(m_volumeSlider, &QSlider::valueChanged, this, &AVPlayerWidget::onVolumeChanged);
  99. }
  100. void AVPlayerWidget::play(const QString &url)
  101. {
  102. if (!m_player->play(url)) {
  103. // 提示反馈?
  104. return;
  105. }
  106. m_isPlaying = true;
  107. m_isPaused = false;
  108. m_playButton->setEnabled(false);
  109. m_pauseButton->setEnabled(true);
  110. m_stopButton->setEnabled(true);
  111. emit playStateChanged(true);
  112. }
  113. void AVPlayerWidget::stop()
  114. {
  115. m_player->clearPlayer();
  116. m_isPlaying = false;
  117. m_isPaused = false;
  118. m_playButton->setEnabled(true);
  119. m_pauseButton->setEnabled(false);
  120. m_stopButton->setEnabled(false);
  121. m_openglWidget->clearFrame();
  122. emit playStateChanged(false);
  123. }
  124. void AVPlayerWidget::pause()
  125. {
  126. if (m_isPlaying && !m_isPaused) {
  127. m_player->pause(true);
  128. m_isPaused = true;
  129. m_playButton->setText("继续");
  130. m_playButton->setEnabled(true);
  131. m_pauseButton->setEnabled(false);
  132. }
  133. }
  134. void AVPlayerWidget::resume()
  135. {
  136. if (m_isPlaying && m_isPaused) {
  137. m_player->pause(false);
  138. m_isPaused = false;
  139. m_playButton->setText("播放");
  140. m_playButton->setEnabled(false);
  141. m_pauseButton->setEnabled(true);
  142. }
  143. }
  144. void AVPlayerWidget::onPlayButtonClicked()
  145. {
  146. if (m_isPaused) {
  147. resume();
  148. } else {
  149. QString url = m_urlEdit->text().trimmed();
  150. if (!url.isEmpty()) {
  151. play(url);
  152. }
  153. }
  154. }
  155. void AVPlayerWidget::onPauseButtonClicked()
  156. {
  157. pause();
  158. }
  159. void AVPlayerWidget::onStopButtonClicked()
  160. {
  161. stop();
  162. }
  163. void AVPlayerWidget::onTestPlayButtonClicked()
  164. {
  165. // 使用默认测试视频
  166. QString testUrl = "C:/Users/zhuizhu/Videos/2.mp4";
  167. m_urlEdit->setText(testUrl);
  168. play(testUrl);
  169. }
  170. void AVPlayerWidget::onVolumeChanged(int volume)
  171. {
  172. m_player->setVolume(volume);
  173. }
  174. void AVPlayerWidget::onFrameChanged(QSharedPointer<VideoFrame> frame)
  175. {
  176. m_openglWidget->onShowYUV(frame);
  177. // 注意:这里不要释放avFrame,因为Render方法会处理
  178. }
  179. void AVPlayerWidget::ptsChangedSlot(unsigned int pts)
  180. {
  181. // 更新时间显示
  182. int seconds = pts / 1000;
  183. int minutes = seconds / 60;
  184. seconds = seconds % 60;
  185. QString timeStr = QString("%1:%2").arg(minutes, 2, 10, QChar('0')).arg(seconds, 2, 10, QChar('0'));
  186. // 这里可以更新时间标签的当前时间部分
  187. }
  188. void AVPlayerWidget::durationChangedSlot(unsigned int duration)
  189. {
  190. // 更新总时长显示
  191. int seconds = duration / 1000;
  192. int minutes = seconds / 60;
  193. seconds = seconds % 60;
  194. QString durationStr = QString("%1:%2").arg(minutes, 2, 10, QChar('0')).arg(seconds, 2, 10, QChar('0'));
  195. m_timeLabel->setText(QString("00:00 / %1").arg(durationStr));
  196. }
  197. void AVPlayerWidget::terminateSlot()
  198. {
  199. stop();
  200. }
  201. // 兼容旧接口实现
  202. void AVPlayerWidget::stopPlay()
  203. {
  204. stop();
  205. }
  206. void AVPlayerWidget::setPlayRoomId(const QString &id)
  207. {
  208. // 以当前URL为基准,去掉最后一节后拼接房间ID,避免硬编码服务器地址
  209. QString base = m_urlEdit->text().trimmed();
  210. if (base.isEmpty()) {
  211. base = "rtmp://106.55.186.74:1935/stream/V1/";
  212. }
  213. // rtmp://106.55.186.74:1935/stream/V1/0198da41-cdb6-78e3-879d-2ea32d58f73f
  214. int lastSlash = base.lastIndexOf('/');
  215. QString streamBase = lastSlash > 0 ? base.left(lastSlash) : base;
  216. QString url = streamBase + "/" + id;
  217. qDebug() << "setPlayRoomId" << url;
  218. m_urlEdit->setText(url);
  219. }
  220. void AVPlayerWidget::startPlay()
  221. {
  222. const QString url = m_urlEdit->text().trimmed();
  223. if (!url.isEmpty()) {
  224. qDebug() << "startPlay" << url;
  225. play(url);
  226. }
  227. }