PonyPlayer
framecontroller.hpp
浏览该文件的文档.
1//
2// Created by ColorsWind on 2022/5/5.
3//
4
5#pragma once
6
7#include <QObject>
8#include <utility>
9#include "playback.hpp"
10
16class FrameController : public QObject {
17Q_OBJECT
18private:
19 QThread *m_affinityThread = nullptr;
20 Demuxer *m_demuxer = nullptr;
21 Playback *m_playback = nullptr;
22public:
23 explicit FrameController([[maybe_unused]] QObject *parent) : QObject(nullptr) {
24 m_affinityThread = new QThread;
25 m_affinityThread->setObjectName(PonyPlayer::FRAME);
26 this->moveToThread(m_affinityThread);
27 connect(m_affinityThread, &QThread::started, this, &FrameController::initOnThread);
28 m_affinityThread->start();
29 }
30
31private slots:
32
33 void initOnThread() {
34 this->m_demuxer = new Demuxer{this};
35 this->m_playback = new Playback{m_demuxer, this};
36 connect(m_playback, &Playback::setPicture, this, &FrameController::setPicture, Qt::DirectConnection);
38 Qt::DirectConnection);
40 // WARNING: BLOCKING_QUEUED_CONNECTION!!!
41 connect(this, &FrameController::signalDecoderSeek, m_demuxer, &Demuxer::seek, Qt::BlockingQueuedConnection);
42 connect(m_demuxer, &Demuxer::openFileResult, this, [this](PonyPlayer::OpenFileResultType result) {
44 m_playback->setDesiredFormat(m_demuxer->getInputFormat());
45 m_demuxer->setOutputFormat(m_playback->getDeviceFormat());
46 m_demuxer->start();
47 m_playback->clearCacheFrame();
48 m_playback->showFrame();
49 }
50 emit openFileResult(result);
51 });
52 connect(m_playback, &Playback::resourcesEnd, this, &FrameController::resourcesEnd, Qt::DirectConnection);
54 connect(this, &FrameController::signalSetTrack, this, [this](int i) {
55 qreal pos = m_playback->getPreferablePos();
56 m_playback->stop();
57 m_demuxer->pause();
59 m_playback->setDesiredFormat(m_demuxer->getInputFormat());
60 m_demuxer->setOutputFormat(m_playback->getDeviceFormat());
61 seek(pos);
62 });
63 connect(this, &FrameController::signalBackward, this, [this] {
64 qreal pos = m_playback->getPreferablePos();
65 m_playback->stop();
66 m_demuxer->pause();
67 m_demuxer->backward();
68 seek(pos);
69 m_demuxer->start();
70 });
71 connect(this, &FrameController::signalForward, this, [this] {
72 qreal pos = m_playback->getPreferablePos();
73 m_playback->stop();
74 m_demuxer->pause();
75 m_demuxer->forward();
76 seek(pos);
77 m_demuxer->start();
78 });
79 connect(m_playback, &Playback::requestResynchronization, this, [this](bool enableAudio, bool updateAudioFormat) {
80 if (!m_demuxer->isFileOpen()) return;
81 bool isPlay = m_playback->isPlaying();
82 qreal pos = m_playback->getPreferablePos();
83 m_playback->stop();
84 m_demuxer->pause();
85 if (updateAudioFormat) {
86 m_playback->setDesiredFormat(m_demuxer->getInputFormat());
87 m_demuxer->setOutputFormat(m_playback->getDeviceFormat());
88 }
89 m_demuxer->setEnableAudio(enableAudio);
90 seek(pos);
91 m_demuxer->start();
92 if (isPlay) { m_playback->start(); }
93 }, Qt::QueuedConnection);
94 connect(m_playback, &Playback::signalAudioOutputDevicesListChanged, this,
96 connect(m_playback, &Playback::signalDeviceSwitched, this, [this] {
98 });
99 }
100
101public:
102
103 ~FrameController() override {
104 m_affinityThread->quit();
105 }
106
107 void setTrack(int i) {
108 emit signalSetTrack(i);
109 }
110
111 void setSelectedAudioOutputDevice(QString deviceName) {
112 m_playback->setSelectedAudioOutputDevice(std::move(deviceName));
113 }
114
116
117 PONY_THREAD_SAFE void backward() {
118 emit signalBackward();
119 }
120
121 PONY_THREAD_SAFE void forward() {
122 emit signalForward();
123 }
124
125 PONY_THREAD_SAFE qreal getPreferablePos() {
126 return m_playback->getPreferablePos();
127 }
128
133 qreal getAudioDuration() { return m_demuxer->audioDuration(); }
134
139 qreal getVideoDuration() { return m_demuxer->videoDuration(); }
140
145 QStringList getTracks() { return m_demuxer->getTracks(); }
146
147 qreal getPitch() { return m_playback ? m_playback->getPitch() : 1.0; }
148
149 bool hasVideo() { return m_demuxer->hasVideo(); }
150
151 void setVolume(qreal volume) { m_playback->setVolume(volume); }
152
153 void setPitch(qreal pitch) { m_playback->setPitch(pitch); }
154
155 void setSpeed(qreal speed) { m_playback->setSpeed(speed); }
156
157 QStringList getAudioDeviceList() { return m_playback ? m_playback->getAudioDeviceList() : QStringList(); }
158
159public slots:
160
161 void openFile(const QString &path) {
162 qDebug() << "Open file" << path;
163 emit signalDecoderOpenFile(path.toStdString());
164 }
165
166
167 void pause() {
168 qDebug() << "Pausing";
169 m_playback->pause();
170 }
171
172 void stop() {
173 qDebug() << "Stopping";
174 m_demuxer->close();
175 m_demuxer->flush();
176 m_playback->stop();
177 }
178
179 void close() {
180 qDebug() << "Closing";
181 m_demuxer->close();
182 m_playback->stop();
183 }
184
185 void start() {
186 qDebug() << "Starting";
187 m_demuxer->start();
188 m_playback->start();
189 }
190
191 void seek(qreal seekPos) {
192 qDebug() << "Start seek for" << seekPos;
193 m_playback->stop();
194 m_demuxer->pause(); // blocking, make sure pic and sample request can be blocked
195
196 // WARNING: must make sure everything (especially PTS) has been properly updated
197 // otherwise, the video thread will be BLOCKING for a long time.
198 emit signalDecoderSeek(seekPos); // blocking connection
199 m_demuxer->flush();
200 m_demuxer->start();
201
202 bool backward = m_demuxer->isBackward();
203 // time-consuming job
204 // use audio frame pts may be more accurate, but it is not available in rewinding.
205 qreal startPoint;
206 if (backward) {
207 // if rewinding, there is no need to skip frame. (dispatcher guarantee)
208 if (m_demuxer->hasVideo()) {
209 startPoint = m_demuxer->frontPicture();
210 } else {
211 startPoint = seekPos;
212 }
213 } else {
214 if (m_demuxer->hasVideo()) {
215 m_demuxer->skipPicture([seekPos](qreal framePos) { return framePos < seekPos; });
216 }
217 m_demuxer->skipSample(
218 [seekPos, &startPoint](qreal framePos) { return startPoint = framePos, framePos < seekPos; });
219
220 }
221
222 emit signalPositionChangedBySeek(); // block
223 m_playback->setStartPoint(startPoint);
224 m_playback->showFrame();
225
226 qDebug() << "End seek for" << seekPos;
227 }
228
229signals:
230
231 void signalDecoderOpenFile(std::string path);
232
233 void signalDecoderSeek(qreal pos);
234
236
237 void signalSetTrack(int i);
238
240
242
244
246
248
250
251 void playbackStateChanged(bool isPlaying);
252
254
256
257
258};
259
Definition: demuxer.hpp:14
PONY_THREAD_SAFE int skipSample(const std::function< bool(qreal)> &predicate)
Definition: demuxer.hpp:73
PONY_THREAD_SAFE int skipPicture(const std::function< bool(qreal)> &predicate)
Definition: demuxer.hpp:53
qreal frontPicture()
Definition: demuxer.hpp:48
void close()
Definition: demuxer.hpp:265
PONY_THREAD_SAFE void start()
Definition: demuxer.hpp:148
void forward()
Definition: demuxer.hpp:259
qreal videoDuration()
Definition: demuxer.hpp:88
PonyAudioFormat getInputFormat()
Definition: demuxer.hpp:158
void seek(qreal secs)
Definition: demuxer.hpp:193
void openFileResult(PonyPlayer::OpenFileResultType result, QPrivateSignal)
PONY_THREAD_SAFE bool isFileOpen()
Definition: demuxer.hpp:131
PONY_THREAD_SAFE bool isBackward()
Definition: demuxer.hpp:108
void setTrack(int i)
Definition: demuxer.hpp:285
void openFile(const std::string &fn)
Definition: demuxer.hpp:210
QStringList getTracks()
Definition: demuxer.hpp:95
void backward()
Definition: demuxer.hpp:246
void setOutputFormat(PonyAudioFormat format)
Definition: demuxer.hpp:172
PONY_THREAD_SAFE void pause()
Definition: demuxer.hpp:126
void setEnableAudio(bool enable)
Definition: demuxer.hpp:154
PONY_THREAD_SAFE bool hasVideo()
Definition: demuxer.hpp:114
qreal audioDuration()
Definition: demuxer.hpp:81
将解码拿到的帧传递给输出.
Definition: framecontroller.hpp:16
void setVolume(qreal volume)
Definition: framecontroller.hpp:151
void pause()
Definition: framecontroller.hpp:167
void setPitch(qreal pitch)
Definition: framecontroller.hpp:153
void stop()
Definition: framecontroller.hpp:172
void playbackStateChanged(bool isPlaying)
QStringList getTracks()
Definition: framecontroller.hpp:145
bool hasVideo()
Definition: framecontroller.hpp:149
qreal getPitch()
Definition: framecontroller.hpp:147
qreal getVideoDuration()
Definition: framecontroller.hpp:139
PONY_THREAD_SAFE void backward()
Definition: framecontroller.hpp:117
void signalDecoderOpenFile(std::string path)
void openFile(const QString &path)
Definition: framecontroller.hpp:161
FrameController(QObject *parent)
Definition: framecontroller.hpp:23
void signalDecoderSetTrack(int i)
void openFileResult(PonyPlayer::OpenFileResultType result)
void signalSetTrack(int i)
void setSpeed(qreal speed)
Definition: framecontroller.hpp:155
void setSelectedAudioOutputDevice(QString deviceName)
Definition: framecontroller.hpp:111
void close()
Definition: framecontroller.hpp:179
void signalPositionChangedBySeek()
void signalDecoderSeek(qreal pos)
void signalAudioOutputDevicesChanged()
qreal getAudioDuration()
Definition: framecontroller.hpp:133
void setPicture(VideoFrameRef pic)
void setTrack(int i)
Definition: framecontroller.hpp:107
void seek(qreal seekPos)
Definition: framecontroller.hpp:191
void signalDeviceSwitched()
void signalBackward()
void start()
Definition: framecontroller.hpp:185
QStringList getAudioDeviceList()
Definition: framecontroller.hpp:157
~FrameController() override
Definition: framecontroller.hpp:103
QString getSelectedAudioOutputDevice()
Definition: framecontroller.hpp:115
PONY_THREAD_SAFE qreal getPreferablePos()
Definition: framecontroller.hpp:125
PONY_THREAD_SAFE void forward()
Definition: framecontroller.hpp:121
void signalForward()
负责输出视频和音频(不含视频预览).
Definition: playback.hpp:22
void pause()
Definition: playback.hpp:259
bool isPlaying()
Definition: playback.hpp:225
void start()
Definition: playback.hpp:243
void setSpeed(qreal speed)
Definition: playback.hpp:201
void signalDeviceSwitched()
qreal getPitch()
Definition: playback.hpp:283
QString getSelectedAudioOutputDevice()
Definition: playback.hpp:209
void stop()
Definition: playback.hpp:270
void stateChanged(bool isPlaying)
PONY_THREAD_SAFE qreal getPreferablePos()
Definition: playback.hpp:162
void clearCacheFrame()
Definition: playback.hpp:217
QStringList getAudioDeviceList()
Definition: playback.hpp:281
void setPitch(qreal pitch)
Definition: playback.hpp:197
void resourcesEnd()
void setDesiredFormat(const PonyAudioFormat &format)
Definition: playback.hpp:180
void setSelectedAudioOutputDevice(QString deviceName)
Definition: playback.hpp:205
void requestResynchronization(bool enableAudio, bool updateAudioFormat)
void setPicture(VideoFrameRef pic)
PonyAudioFormat getDeviceFormat()
Definition: playback.hpp:166
void setVolume(qreal volume)
Definition: playback.hpp:192
void signalAudioOutputDevicesListChanged()
void showFrame()
Definition: playback.hpp:213
void setStartPoint(qreal startPoint)
Definition: playback.hpp:233
Definition: frame.hpp:47
OpenFileResultType
Definition: dispatcher.hpp:32
@ FAILED
打开文件失败
Definition: dispatcher.hpp:33
constexpr PonyThread FRAME
Definition: ponyplayer.h:50