1 /******************************************************************************
2     QtAV:  Multimedia framework based on Qt and FFmpeg
3     Copyright (C) 2012-2017 Wang Bin <wbsecg1@gmail.com>
4 
5 *   This file is part of QtAV (from 2013)
6 
7     This library is free software; you can redistribute it and/or
8     modify it under the terms of the GNU Lesser General Public
9     License as published by the Free Software Foundation; either
10     version 2.1 of the License, or (at your option) any later version.
11 
12     This library is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15     Lesser General Public License for more details.
16 
17     You should have received a copy of the GNU Lesser General Public
18     License along with this library; if not, write to the Free Software
19     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20 ******************************************************************************/
21 
22 #ifndef QTAV_QML_AVPLAYER_H
23 #define QTAV_QML_AVPLAYER_H
24 
25 #include <QtCore/QObject>
26 #include <QtCore/QStringList> //5.0
27 #include <QtQml/QQmlParserStatus>
28 #include <QtQml/QQmlListProperty>
29 #include <QmlAV/MediaMetaData.h>
30 #include <QmlAV/QuickFilter.h>
31 #include <QtAV/AVError.h>
32 #include <QtAV/VideoCapture.h>
33 
34 namespace QtAV {
35 class AVPlayer;
36 }
37 using namespace QtAV;
38 class QmlAVPlayer : public QObject, public QQmlParserStatus
39 {
40     Q_OBJECT
41     Q_INTERFACES(QQmlParserStatus)
42     Q_PROPERTY(qreal volume READ volume WRITE setVolume NOTIFY volumeChanged)
43     Q_PROPERTY(Status status READ status NOTIFY statusChanged)
44     Q_PROPERTY(Error error READ error NOTIFY errorChanged)
45     Q_PROPERTY(int duration READ duration NOTIFY durationChanged)
46     Q_PROPERTY(int position READ position NOTIFY positionChanged)
47     Q_PROPERTY(bool muted READ isMuted WRITE setMuted NOTIFY mutedChanged)
48     Q_PROPERTY(bool hasAudio READ hasAudio NOTIFY hasAudioChanged)
49     Q_PROPERTY(bool hasVideo READ hasVideo NOTIFY hasVideoChanged)
50     Q_PROPERTY(PlaybackState playbackState READ playbackState NOTIFY playbackStateChanged)
51     Q_PROPERTY(bool autoPlay READ autoPlay WRITE setAutoPlay NOTIFY autoPlayChanged)
52     Q_PROPERTY(bool autoLoad READ isAutoLoad WRITE setAutoLoad NOTIFY autoLoadChanged)
53     Q_PROPERTY(qreal playbackRate READ playbackRate WRITE setPlaybackRate NOTIFY playbackRateChanged)
54     Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
55     Q_PROPERTY(int loops READ loopCount WRITE setLoopCount NOTIFY loopCountChanged)
56     Q_PROPERTY(qreal bufferProgress READ bufferProgress NOTIFY bufferProgressChanged)
57     Q_PROPERTY(bool seekable READ isSeekable NOTIFY seekableChanged)
58     Q_PROPERTY(MediaMetaData *metaData READ metaData CONSTANT)
59     Q_PROPERTY(QObject *mediaObject READ mediaObject  NOTIFY mediaObjectChanged SCRIPTABLE false DESIGNABLE false)
60     Q_PROPERTY(QString errorString READ errorString NOTIFY errorChanged)
61     Q_ENUMS(Loop)
62     Q_ENUMS(PlaybackState)
63     Q_ENUMS(Status)
64     Q_ENUMS(Error)
65     Q_ENUMS(ChannelLayout)
66     Q_ENUMS(BufferMode)
67     // not supported by QtMultimedia
68     Q_ENUMS(PositionValue)
69     Q_ENUMS(MediaEndAction)
70     Q_PROPERTY(int startPosition READ startPosition WRITE setStartPosition NOTIFY startPositionChanged)
71     Q_PROPERTY(int stopPosition READ stopPosition WRITE setStopPosition NOTIFY stopPositionChanged)
72     Q_PROPERTY(bool fastSeek READ isFastSeek WRITE setFastSeek NOTIFY fastSeekChanged)
73     Q_PROPERTY(int timeout READ timeout WRITE setTimeout NOTIFY timeoutChanged)
74     Q_PROPERTY(bool abortOnTimeout READ abortOnTimeout WRITE setAbortOnTimeout NOTIFY abortOnTimeoutChanged)
75     Q_PROPERTY(ChannelLayout channelLayout READ channelLayout WRITE setChannelLayout NOTIFY channelLayoutChanged)
76     Q_PROPERTY(QStringList videoCodecs READ videoCodecs)
77     Q_PROPERTY(QStringList videoCodecPriority READ videoCodecPriority WRITE setVideoCodecPriority NOTIFY videoCodecPriorityChanged)
78     Q_PROPERTY(QVariantMap videoCodecOptions READ videoCodecOptions WRITE setVideoCodecOptions NOTIFY videoCodecOptionsChanged)
79     Q_PROPERTY(QVariantMap avFormatOptions READ avFormatOptions WRITE setAVFormatOptions NOTIFY avFormatOptionsChanged)
80     Q_PROPERTY(bool useWallclockAsTimestamps READ useWallclockAsTimestamps WRITE setWallclockAsTimestamps NOTIFY useWallclockAsTimestampsChanged)
81     Q_PROPERTY(QtAV::VideoCapture *videoCapture READ videoCapture CONSTANT)
82     Q_PROPERTY(int audioTrack READ audioTrack WRITE setAudioTrack NOTIFY audioTrackChanged)
83     Q_PROPERTY(int videoTrack READ videoTrack WRITE setVideoTrack NOTIFY videoTrackChanged)
84     Q_PROPERTY(int bufferSize READ bufferSize WRITE setBufferSize NOTIFY bufferSizeChanged)
85     Q_PROPERTY(BufferMode bufferMode READ bufferMode WRITE setBufferMode NOTIFY bufferModeChanged)
86     Q_PROPERTY(qreal frameRate READ frameRate WRITE setFrameRate NOTIFY frameRateChanged)
87     Q_PROPERTY(QUrl externalAudio READ externalAudio WRITE setExternalAudio NOTIFY externalAudioChanged)
88     Q_PROPERTY(QVariantList internalAudioTracks READ internalAudioTracks NOTIFY internalAudioTracksChanged)
89     Q_PROPERTY(QVariantList internalVideoTracks READ internalVideoTracks NOTIFY internalVideoTracksChanged)
90     Q_PROPERTY(QVariantList externalAudioTracks READ externalAudioTracks NOTIFY externalAudioTracksChanged)
91     Q_PROPERTY(QVariantList internalSubtitleTracks READ internalSubtitleTracks NOTIFY internalSubtitleTracksChanged)
92     // internal subtitle, e.g. mkv embedded subtitles
93     Q_PROPERTY(int internalSubtitleTrack READ internalSubtitleTrack WRITE setInternalSubtitleTrack NOTIFY internalSubtitleTrackChanged)
94     Q_PROPERTY(MediaEndAction mediaEndAction READ mediaEndAction WRITE setMediaEndAction NOTIFY mediaEndActionChanged)
95 
96     Q_PROPERTY(QQmlListProperty<QuickAudioFilter> audioFilters READ audioFilters)
97     Q_PROPERTY(QQmlListProperty<QuickVideoFilter> videoFilters READ videoFilters)
98     // TODO: startPosition/stopPosition
99     Q_PROPERTY(QStringList audioBackends READ audioBackends WRITE setAudioBackends NOTIFY audioBackendsChanged)
100     Q_PROPERTY(QStringList supportedAudioBackends READ supportedAudioBackends)
101 public:
102     enum Loop { Infinite = -1 };
103     // use (1<<31)-1
104     enum PositionValue { PositionMax = int(~0)^(1<<(sizeof(int)*8-1))};
105     enum PlaybackState {
106         StoppedState,
107         PlayingState,
108         PausedState
109     };
110     enum Status {
111         UnknownStatus = QtAV::UnknownMediaStatus, // e.g. user status after interrupt
112         NoMedia = QtAV::NoMedia,
113         Loading = QtAV::LoadingMedia, // when source is set
114         Loaded = QtAV::LoadedMedia, // if auto load and source is set. player is stopped state
115         Stalled = QtAV::StalledMedia,
116         Buffering = QtAV::BufferingMedia,
117         Buffered = QtAV::BufferedMedia, // when playing
118         EndOfMedia = QtAV::EndOfMedia,
119         InvalidMedia = QtAV::InvalidMedia
120     };
121     enum Error {
122         NoError,
123         ResourceError,
124         FormatError,
125         NetworkError,
126         AccessDenied,
127         ServiceMissing
128     };
129     // currently supported channels<3.
130     enum ChannelLayout {
131         ChannelLayoutAuto, //the same as source if channels<=2. otherwise resamples to stereo
132         Left,
133         Right,
134         Mono,
135         Stereo
136     };
137     enum BufferMode
138     {
139        BufferTime    = QtAV::BufferTime,
140        BufferBytes   = QtAV::BufferBytes,
141        BufferPackets = QtAV::BufferPackets
142     };
143     enum MediaEndAction {
144         MediaEndAction_Default, /// stop playback (if loop end) and clear video renderer
145         MediaEndAction_KeepDisplay = 1, /// stop playback but video renderer keeps the last frame
146         MediaEndAction_Pause = 1 << 1 /// pause playback. Currently AVPlayer repeat mode will not work if this flag is set
147     };
148 
149     explicit QmlAVPlayer(QObject *parent = 0);
150     //derived
151     virtual void classBegin();
152     virtual void componentComplete();
153 
154     // add QtAV::AVPlayer::isAudioAvailable()?
155     bool hasAudio() const;
156     bool hasVideo() const;
157 
158     QUrl source() const;
159     /*!
160      * \brief setSource
161      * If url is changed and auto load is true, current playback will stop.
162      */
163     void setSource(const QUrl& url);
164 
165     // 0,1: play once. MediaPlayer.Infinite: forever.
166     // >1: play loopCount() - 1 times. different from Qt
167     int loopCount() const;
168     void setLoopCount(int c);
169 
170     QObject* videoOut();
171     void setVideoOut(QObject* out);
172     qreal volume() const;
173     void setVolume(qreal value);
174     bool isMuted() const;
175     void setMuted(bool m);
176     int duration() const;
177     int position() const;
178     bool isSeekable() const;
179 
180     int startPosition() const;
181     void setStartPosition(int value);
182     int stopPosition() const;
183     /*!
184      * \brief setStopPosition
185      * You can use MediaPlayer.PositionMax to play until the end of stream.
186      */
187     void setStopPosition(int value);
188     bool isFastSeek() const;
189     void setFastSeek(bool value);
190 
191     qreal bufferProgress() const;
192 
193     Status status() const;
194     Error error() const;
195     QString errorString() const;
196     PlaybackState playbackState() const;
197     void setPlaybackState(PlaybackState playbackState);
198     qreal playbackRate() const;
199     void setPlaybackRate(qreal s);
200     Q_INVOKABLE void play(const QUrl& url);
201     AVPlayer *player();
202 
203     bool isAutoLoad() const;
204     void setAutoLoad(bool autoLoad);
205 
206     bool autoPlay() const;
207     void setAutoPlay(bool autoplay);
208 
209     MediaMetaData *metaData() const;
210     QObject *mediaObject() const;
211     QtAV::VideoCapture *videoCapture() const;
212 
213     // "FFmpeg", "CUDA", "DXVA", "VAAPI" etc
214     QStringList videoCodecs() const;
215     QStringList videoCodecPriority() const;
216     void setVideoCodecPriority(const QStringList& p);
217     QVariantMap videoCodecOptions() const;
218     void setVideoCodecOptions(const QVariantMap& value);
219     QVariantMap avFormatOptions() const;
220     void setAVFormatOptions(const QVariantMap& value);
221 
222     bool useWallclockAsTimestamps() const;
223     void setWallclockAsTimestamps(bool use_wallclock_as_timestamps);
224 
225     void setAudioChannels(int channels);
226     int audioChannels() const;
227     void setChannelLayout(ChannelLayout channel);
228     ChannelLayout channelLayout() const;
229 
230     void setTimeout(int value); // ms
231     int timeout() const;
232     void setAbortOnTimeout(bool value);
233     bool abortOnTimeout() const;
234 
235     /*!
236      * \brief audioTrack
237      * The audio stream number in current media or external audio.
238      * Value can be: 0, 1, 2.... 0 means the 1st audio stream in current media or external audio
239      */
240     int audioTrack() const;
241     void setAudioTrack(int value);
242     QVariantList internalAudioTracks() const;
243     /*!
244      * \brief videoTrack
245      * The video stream number in current media.
246      * Value can be: 0, 1, 2.... 0 means the 1st video stream in current media
247      */
248     int videoTrack() const;
249     void setVideoTrack(int value);
250     QVariantList internalVideoTracks() const;
251 
252     int bufferSize() const;
253     void setBufferSize(int value);
254 
255     BufferMode bufferMode() const;
256     void setBufferMode(BufferMode value);
257 
258     qreal frameRate() const;
259     void setFrameRate(qreal value);
260 
261     MediaEndAction mediaEndAction() const;
262     void setMediaEndAction(MediaEndAction value);
263     /*!
264      * \brief externalAudio
265      * If externalAudio url is valid, player will use audioTrack of external audio as audio source.
266      * Set an invalid url to disable external audio
267      * \return external audio url or an invalid url if use internal audio tracks
268      */
269     QUrl externalAudio() const;
270     void setExternalAudio(const QUrl& url);
271     QVariantList externalAudioTracks() const;
272 
273     int internalSubtitleTrack() const;
274     void setInternalSubtitleTrack(int value);
275     QVariantList internalSubtitleTracks() const;
276 
277     QQmlListProperty<QuickAudioFilter> audioFilters();
278     QQmlListProperty<QuickVideoFilter> videoFilters();
279 
280     QStringList supportedAudioBackends() const;
281     QStringList audioBackends() const;
282     void setAudioBackends(const QStringList& value);
283 
284 public Q_SLOTS:
285     void play();
286     void pause();
287     void stop();
288     void stepForward();
289     void stepBackward();
290     void seek(int offset);
291     void seekForward();
292     void seekBackward();
293 
294 Q_SIGNALS:
295     void volumeChanged();
296     void mutedChanged();
297     // TODO: signal from QtAV::AVPlayer
298     void hasAudioChanged();
299     void hasVideoChanged();
300     void durationChanged();
301     void positionChanged();
302     void sourceChanged();
303     void autoLoadChanged();
304     void loopCountChanged();
305     void videoOutChanged();
306     void playbackStateChanged();
307     void autoPlayChanged();
308     void playbackRateChanged();
309     void paused();
310     void stopped();
311     void playing();
312     void startPositionChanged();
313     void stopPositionChanged();
314     void seekableChanged();
315     void seekFinished(); //WARNING: position() now is not the seek finished video timestamp
316     void fastSeekChanged();
317     void bufferProgressChanged();
318     void videoCodecPriorityChanged();
319     void videoCodecOptionsChanged();
320     void avFormatOptionsChanged();
321     void useWallclockAsTimestampsChanged();
322     void channelLayoutChanged();
323     void timeoutChanged();
324     void abortOnTimeoutChanged();
325     void audioTrackChanged();
326     void internalAudioTracksChanged();
327     void videoTrackChanged();
328     void internalVideoTracksChanged();
329     void externalAudioChanged();
330     void externalAudioTracksChanged();
331     void internalSubtitleTrackChanged();
332     void internalSubtitleTracksChanged();
333     void bufferSizeChanged();
334     void bufferModeChanged();
335     void frameRateChanged();
336     void mediaEndActionChanged();
337 
338     void errorChanged();
339     void error(Error error, const QString &errorString);
340     void statusChanged();
341     void mediaObjectChanged();
342     void audioBackendsChanged();
343 private Q_SLOTS:
344     // connect to signals from player
345     void _q_error(const QtAV::AVError& e);
346     void _q_statusChanged();
347     void _q_started();
348     void _q_stopped();
349     void _q_paused(bool);
350 
351 private Q_SLOTS:
352     void applyVolume();
353     void applyChannelLayout();
354 
355 private:
356     static void af_append(QQmlListProperty<QuickAudioFilter> *property, QuickAudioFilter *value);
357     static int af_count(QQmlListProperty<QuickAudioFilter> *property);
358     static QuickAudioFilter *af_at(QQmlListProperty<QuickAudioFilter> *property, int index);
359     static void af_clear(QQmlListProperty<QuickAudioFilter> *property);
360     static void vf_append(QQmlListProperty<QuickVideoFilter> *property, QuickVideoFilter *value);
361     static int vf_count(QQmlListProperty<QuickVideoFilter> *property);
362     static QuickVideoFilter *vf_at(QQmlListProperty<QuickVideoFilter> *property, int index);
363     static void vf_clear(QQmlListProperty<QuickVideoFilter> *property);
364 
365     Q_DISABLE_COPY(QmlAVPlayer)
366 
367     bool mUseWallclockAsTimestamps;
368     bool m_complete;
369     bool m_mute;
370     bool mAutoPlay;
371     bool mAutoLoad;
372     bool mHasAudio, mHasVideo;
373     bool m_fastSeek;
374     bool m_loading;
375     int mLoopCount;
376     int mStart, mStop;
377     qreal mPlaybackRate;
378     qreal mVolume;
379     PlaybackState mPlaybackState;
380     Error mError;
381     QString mErrorString;
382     QtAV::AVPlayer *mpPlayer;
383     QUrl mSource;
384     QStringList mVideoCodecs;
385     ChannelLayout mChannelLayout;
386     int m_timeout;
387     bool m_abort_timeout;
388     int m_audio_track;
389     int m_video_track;
390     QUrl m_audio;
391     int m_sub_track;
392 
393     QScopedPointer<MediaMetaData> m_metaData;
394     QVariantMap vcodec_opt;
395     QVariantMap avfmt_opt;
396 
397     QList<QuickAudioFilter*> m_afilters;
398     QList<QuickVideoFilter*> m_vfilters;
399     QStringList m_ao;
400 };
401 
402 #endif // QTAV_QML_AVPLAYER_H
403