This repository has been archived by the owner on Jun 1, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 170
/
PlayerComponent.h
243 lines (199 loc) · 8.91 KB
/
PlayerComponent.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
#ifndef PLAYERCOMPONENT_H
#define PLAYERCOMPONENT_H
#include <QObject>
#include <QtCore/qglobal.h>
#include <QVariant>
#include <QSet>
#include <QQuickWindow>
#include <QTimer>
#include <QTextStream>
#include <functional>
#include "ComponentManager.h"
#include "CodecsComponent.h"
#include "QtHelper.h"
#include <mpv/client.h>
///////////////////////////////////////////////////////////////////////////////////////////////////
class PlayerComponent : public ComponentBase
{
Q_OBJECT
DEFINE_SINGLETON(PlayerComponent);
public:
const char* componentName() override { return "player"; }
bool componentExport() override { return true; }
bool componentInitialize() override;
void componentPostInitialize() override;
explicit PlayerComponent(QObject* parent = nullptr);
~PlayerComponent() override;
// Deprecated. Corresponds to stop() + queueMedia().
Q_INVOKABLE bool load(const QString& url, const QVariantMap& options, const QVariantMap& metadata, const QString& audioStream = QString(), const QString& subtitleStream = QString());
// Append a media item to the internal playlist. If nothing is played yet, the
// newly appended item will start playing immediately.
// options:
// - startMilliseconds: start playback at this time (in ms)
// - autoplay: if false, start playback paused; if true, start normally
Q_INVOKABLE void queueMedia(const QString& url, const QVariantMap& options, const QVariantMap &metadata, const QString& audioStream, const QString& subtitleStream);
// This clears all items queued with queueMedia().
// It explicitly excludes the currently playing item. The main use of this function
// is updating the next item that should be played (for the purpose of gapless audio).
// If you want to wipe everything, use stop().
Q_INVOKABLE void clearQueue();
Q_INVOKABLE virtual void seekTo(qint64 ms);
// Stop playback and clear all queued items.
Q_INVOKABLE virtual void stop();
// A full reload of the stream is imminent (stop() + load())
// Used for not resetting display mode with the next stop() call.
Q_INVOKABLE virtual void streamSwitch();
Q_INVOKABLE virtual void pause();
Q_INVOKABLE virtual void play();
// 0-100 volume 0=mute and 100=normal
// Ignored if no audio output active (e.g. when no file is playing).
Q_INVOKABLE virtual void setVolume(int volume);
// Returns 0 if no audio output active.
Q_INVOKABLE virtual int volume();
// Ignored if no audio output active.
Q_INVOKABLE virtual void setMuted(bool muted);
// Returns 0 if no audio output active.
Q_INVOKABLE virtual bool muted();
// Returns a QVariant of the following format:
// QVariantList (list of audio device entries)
// QVariantMap (an audio device entry)
// "name" -> QString (symbolic name/ID of the device)
// "description" -> QString (human readable description intended for display)
//
Q_INVOKABLE virtual QVariant getAudioDeviceList();
// Uses the "name" from the device list.
Q_INVOKABLE virtual void setAudioDevice(const QString& name);
Q_INVOKABLE virtual void setAudioStream(const QString& audioStream);
Q_INVOKABLE virtual void setSubtitleStream(const QString& subtitleStream);
Q_INVOKABLE virtual void setAudioDelay(qint64 milliseconds);
Q_INVOKABLE virtual void setSubtitleDelay(qint64 milliseconds);
// If enabled, hide the web view (whether it's OSD or not), and show video
// only. If no video is running, render a black background only.
Q_INVOKABLE virtual void setVideoOnlyMode(bool enable);
// Currently is meant to check for "vc1" and "mpeg2video". Will return whether
// it can be natively decoded. Will return true for all other codecs,
// including unknown codec names.
Q_INVOKABLE virtual bool checkCodecSupport(const QString& codec);
// Return list of currently installed codecs. Includes builtin codecs.
// Downloadable, but not yet installed codecs are excluded.
// May include codecs that do not work, like vc1_mmal on RPIs with no license.
// (checkCodecSupport() handles this specific case to a degree.)
Q_INVOKABLE virtual QList<CodecDriver> installedCodecDrivers();
// Return list of codecs supported for decoding. This specifically returns
// the format and not decoder implementation (e.g. "h264" not "h264_mmal").
Q_INVOKABLE virtual QStringList installedDecoderCodecs();
Q_INVOKABLE void userCommand(QString command);
// Set the region in which video should be rendered. This uses Qt pixel
// coordinates (x=0,y=0 is the top/left corner).
// If the aspect ratio mismatches, the video will be letterboxed or pillarboxed.
// The lower/right pixel border is always excluded.
// setVideoRectangle(-1, -1, -1 , -1) will revert to the default and
// automatically use the whole window. (Same if the rectangle is 0-sized.)
Q_INVOKABLE void setVideoRectangle(int x, int y, int w, int h);
QRect videoRectangle() { return m_videoRectangle; }
const mpv::qt::Handle getMpvHandle() const { return m_mpv; }
virtual void setWindow(QQuickWindow* window);
QString videoInformation() const;
static QStringList AudioCodecsAll() { return { "ac3", "dts", "eac3", "dts-hd", "truehd" }; };
static QStringList AudioCodecsSPDIF() { return { "ac3", "dts" }; };
enum class State {
finished,
canceled,
error,
paused,
playing,
buffering,
};
enum class MediaType {
Subtitle,
Audio,
};
public Q_SLOTS:
void setAudioConfiguration();
void updateAudioDeviceList();
void updateSubtitleSettings();
void updateVideoSettings();
private Q_SLOTS:
void handleMpvEvents();
void onRestoreDisplay();
void onRefreshRateChange();
void onCodecsLoadingDone(CodecsFetcher* sender);
void updateAudioDevice();
Q_SIGNALS:
// The following signals correspond to the State enum above.
void playing(); // playback is progressing (audio playing, pictures are moving)
void buffering(float percent); // temporary state during "playing", or during media loading
void paused(); // paused (covers all sub-states)
void finished(); // playback finished successfully
void canceled(); // playback was stopped (by user/via API)
void error(const QString& msg); // playback stopped due to external error
// To be phased out. Raised on finished() and canceled().
void stopped(); // playback finished successfully, or was stopped with stop()
void stateChanged(State newState, State oldState); // all state changes
// true if the video (or music) is actually playing
// false if nothing is loaded, playback is paused, during seeking, or media is being loaded
void videoPlaybackActive(bool active);
void windowVisible(bool visible);
// emitted as soon as the duration of the current file is known
void updateDuration(qint64 milliseconds);
// current position in ms should be triggered 2 times a second
// when position updates
void positionUpdate(quint64);
void onVideoRecangleChanged();
void onMpvEvents();
private:
// this is the function actually implemented in the backends. the variantmap contains
// a few known keys:
// * subtitleStreamIndex
// * subtitleStreamIdentifier
// * audioStreamIndex
// * audioStreamIdentifier
// * viewOffset
//
void loadWithOptions(const QVariantMap& options);
void setQtQuickWindow(QQuickWindow* window);
void updatePlaybackState();
void handleMpvEvent(mpv_event *event);
// Potentially switch the display refresh rate, and return true if the refresh rate
// was actually changed.
bool switchDisplayFrameRate();
void checkCurrentAudioDevice(const QSet<QString>& old_devs, const QSet<QString>& new_devs);
void appendAudioFormat(QTextStream& info, const QString& property) const;
void initializeCodecSupport();
PlaybackInfo getPlaybackInfo();
// Make the player prefer certain codecs over others.
void setPreferredCodecs(const QList<CodecDriver>& codecs);
// Determine the required codecs and possibly download them.
// Call resume() when done.
void startCodecsLoading(std::function<void()> resume);
void updateVideoAspectSettings();
QVariantList findStreamsForURL(const QString &url);
void reselectStream(const QString &streamSelection, MediaType target);
mpv::qt::Handle m_mpv;
State m_state;
bool m_paused;
bool m_playbackActive;
bool m_windowVisible;
bool m_videoPlaybackActive;
bool m_inPlayback;
bool m_playbackCanceled;
QString m_playbackError;
int m_bufferingPercentage;
int m_lastBufferingPercentage;
double m_lastPositionUpdate;
qint64 m_playbackAudioDelay;
QQuickWindow* m_window;
float m_mediaFrameRate;
QTimer m_restoreDisplayTimer;
QTimer m_reloadAudioTimer;
QSet<QString> m_audioDevices;
bool m_streamSwitchImminent;
QMap<QString, bool> m_codecSupport;
bool m_doAc3Transcoding;
QStringList m_passthroughCodecs;
QVariantMap m_serverMediaInfo;
QString m_currentSubtitleStream;
QString m_currentAudioStream;
QRect m_videoRectangle;
};
#endif // PLAYERCOMPONENT_H