File indexing completed on 2024-04-28 15:40:27
0001 // SPDX-FileCopyrightText: 2021 Ömer Fadıl USTA <omerusta@gmail.com> 0002 // SPDX-FileCopyrightText: 2021-2022 Jesper K. Pedersen <jesper.pedersen@kdab.com> 0003 // SPDX-FileCopyrightText: 2021-2023 Johannes Zarl-Zierl <johannes@zarl-zierl.at> 0004 // 0005 // SPDX-License-Identifier: GPL-2.0-or-later 0006 0007 // QtAVWidgets/WidgetRenderer 1.13 is incompatible witch QT_DISABLE_DEPRECATED_BEFORE 5.15: 0008 #undef QT_DISABLE_DEPRECATED_BEFORE 0009 0010 #include "QtAVDisplay.h" 0011 #include "QtAVVideoToolBar.h" 0012 0013 #include <DB/ImageInfo.h> 0014 0015 #include <KLocalizedString> 0016 #include <QGuiApplication> 0017 #include <QMessageBox> 0018 #include <QPainterPath> 0019 #include <QScreen> 0020 #include <QVBoxLayout> 0021 #include <QtAV/AVPlayer.h> 0022 #include <QtAV/LibAVFilter.h> 0023 #include <QtAV/VideoRenderer.h> 0024 #include <QtAVWidgets/WidgetRenderer.h> 0025 #include <QtAVWidgets/global.h> 0026 0027 Viewer::QtAVDisplay::QtAVDisplay(QWidget *parent) 0028 : Viewer::VideoDisplay(parent) 0029 { 0030 m_renderer = new QtAV::WidgetRenderer(this, Qt::Widget); 0031 if (!m_renderer) { 0032 QMessageBox::critical(this, i18n("Failed to set up video playback"), i18n("Failed to set up video playback (renderer wasn't created)")); 0033 return; 0034 } 0035 0036 m_player = new QtAV::AVPlayer(this); 0037 0038 // I need this for the use case where we click on the slider after end of video playback. 0039 // If I don't disable asynchronous loading the seek will have no effect. 0040 // See VideoDisplay::seekToPosition 0041 m_player->setAsyncLoad(false); 0042 0043 m_videoWidget = m_renderer->widget(); 0044 if (!m_videoWidget) { 0045 QMessageBox::critical(this, i18n("Failed to set up video playback"), i18n("Failed to set up video playback (widget wasn't created)")); 0046 return; 0047 } 0048 QVBoxLayout *layout = new QVBoxLayout(this); 0049 layout->addWidget(m_videoWidget, 1); 0050 0051 m_player->setRenderer(m_renderer); 0052 0053 connect(m_player, &QtAV::AVPlayer::stopped, this, &QtAVDisplay::stopped); 0054 0055 m_toolBar = new QtAVVideoToolBar(m_player, this); 0056 layout->addWidget(m_toolBar); 0057 0058 connect(m_toolBar, &VideoToolBar::positionChanged, this, &QtAVDisplay::seekToPosition); 0059 connect(m_player, &QtAV::AVPlayer::positionChanged, this, &QtAVDisplay::displayPosition); 0060 connect(m_toolBar, &VideoToolBar::muted, m_player, [this](bool b) { m_player->audio()->setMute(b); }); 0061 0062 connect(m_toolBar, &VideoToolBar::volumeChanged, m_player, [this](int value) { m_player->audio()->setVolume(value / 100.0); }); 0063 m_toolBar->setVolume(100 * m_player->audio()->volume()); 0064 0065 m_rotateFilter = new QtAV::LibAVFilterVideo(m_player); 0066 } 0067 0068 bool Viewer::QtAVDisplay::setImageImpl(DB::ImageInfoPtr info, bool /*forward*/) 0069 { 0070 if (!m_videoWidget) 0071 return false; 0072 0073 rotate(m_info); 0074 0075 m_player->play(info->fileName().absolute()); 0076 m_toolBar->closePreview(); 0077 0078 return true; 0079 } 0080 0081 Viewer::QtAVDisplay::~QtAVDisplay() 0082 { 0083 stop(); 0084 } 0085 0086 void Viewer::QtAVDisplay::stop() 0087 { 0088 if (m_player) 0089 m_player->stop(); 0090 } 0091 0092 void Viewer::QtAVDisplay::playPause() 0093 { 0094 if (!m_player) 0095 return; 0096 m_player->togglePause(); 0097 } 0098 0099 QImage Viewer::QtAVDisplay::screenShoot() 0100 { 0101 return QGuiApplication::primaryScreen()->grabWindow(m_videoWidget->winId()).toImage(); 0102 } 0103 0104 void Viewer::QtAVDisplay::restart() 0105 { 0106 if (!m_player) 0107 return; 0108 0109 m_player->seek(m_player->startPosition()); 0110 m_player->play(); 0111 } 0112 0113 void Viewer::QtAVDisplay::relativeSeek(int msec) 0114 { 0115 seekToPosition(msec + m_player->position()); 0116 } 0117 0118 void Viewer::QtAVDisplay::seekToPosition(qint64 pos) 0119 { 0120 if (!m_player->isPlaying()) 0121 m_player->play(); 0122 m_player->setSeekType(QtAV::AccurateSeek); 0123 m_player->seek(pos); 0124 } 0125 0126 void Viewer::QtAVDisplay::rotate(const DB::ImageInfoPtr &info) 0127 { 0128 m_info = info; 0129 m_rotateFilter->uninstall(); 0130 if (info->angle() != 0) { 0131 m_rotateFilter->installTo(m_player); 0132 // See https://ffmpeg.org/ffmpeg-filters.html 0133 m_rotateFilter->setOptions(QString::fromUtf8("rotate=PI*%1/180").arg(info->angle())); 0134 } 0135 } 0136 0137 bool Viewer::QtAVDisplay::isPaused() const 0138 { 0139 if (!m_player) 0140 return false; 0141 0142 return m_player->isPaused(); 0143 } 0144 0145 bool Viewer::QtAVDisplay::isPlaying() const 0146 { 0147 if (!m_player) 0148 return false; 0149 0150 return m_player->isPlaying(); 0151 } 0152 0153 void Viewer::QtAVDisplay::displayPosition(qint64 pos) 0154 { 0155 if (m_player->isSeekable()) 0156 m_toolBar->setPosition(pos); 0157 } 0158 0159 // vi:expandtab:tabstop=4 shiftwidth=4: 0160 0161 #include "moc_QtAVDisplay.cpp"