1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qtmultimediaglobal_p.h"
5#include "qaudiodecoder.h"
6
7#include "private/qplatformaudiodecoder_p.h"
8
9#include <private/qplatformmediaintegration_p.h>
10#include <private/qobject_p.h>
11
12#include <QtCore/qcoreevent.h>
13#include <QtCore/qmetaobject.h>
14#include <QtCore/qtimer.h>
15#include <QtCore/qurl.h>
16#include <QtCore/qdebug.h>
17#include <QtCore/qpointer.h>
18
19QT_BEGIN_NAMESPACE
20
21/*!
22 \class QAudioDecoder
23 \brief The QAudioDecoder class implements decoding audio.
24 \inmodule QtMultimedia
25 \ingroup multimedia
26 \ingroup multimedia_audio
27
28 \preliminary
29
30 The QAudioDecoder class is a high level class for decoding
31 audio media files. It is similar to the QMediaPlayer class except
32 that audio is provided back through this API rather than routed
33 directly to audio hardware.
34
35 \sa QAudioBuffer
36*/
37
38/*!
39 Construct an QAudioDecoder instance with \a parent.
40*/
41QAudioDecoder::QAudioDecoder(QObject *parent)
42 : QObject(parent)
43{
44 auto maybeDecoder = QPlatformMediaIntegration::instance()->createAudioDecoder(this);
45 if (maybeDecoder) {
46 decoder = maybeDecoder.value();
47 } else {
48 qWarning() << "Failed to initialize QAudioDecoder" << maybeDecoder.error();
49 }
50}
51
52
53/*!
54 Destroys the audio decoder object.
55*/
56QAudioDecoder::~QAudioDecoder() = default;
57
58/*!
59 Returns true is audio decoding is supported on this platform.
60*/
61bool QAudioDecoder::isSupported() const
62{
63 return bool(decoder);
64}
65
66/*!
67 \property QAudioDecoder::isDecoding
68 \brief \c true if the decoder is currently running and decoding audio data.
69*/
70bool QAudioDecoder::isDecoding() const
71{
72 return decoder && decoder->isDecoding();
73}
74
75/*!
76
77 Returns the current error state of the QAudioDecoder.
78*/
79QAudioDecoder::Error QAudioDecoder::error() const
80{
81 return decoder ? decoder->error() : NotSupportedError;
82}
83
84/*!
85 \property QAudioDecoder::error
86
87 Returns a human readable description of the current error, or
88 an empty string is there is no error.
89*/
90QString QAudioDecoder::errorString() const
91{
92 if (!decoder)
93 return tr(s: "QAudioDecoder not supported.");
94 return decoder->errorString();
95}
96
97/*!
98 Starts decoding the audio resource.
99
100 As data gets decoded, the \l bufferReady() signal will be emitted
101 when enough data has been decoded. Calling \l read() will then return
102 an audio buffer without blocking.
103
104 If you call read() before a buffer is ready, an invalid buffer will
105 be returned, again without blocking.
106
107 \sa read()
108*/
109void QAudioDecoder::start()
110{
111 if (!decoder)
112 return;
113
114 // Reset error conditions
115 decoder->clearError();
116 decoder->start();
117}
118
119/*!
120 Stop decoding audio. Calling \l start() again will resume decoding from the beginning.
121*/
122void QAudioDecoder::stop()
123{
124 if (decoder)
125 decoder->stop();
126}
127
128/*!
129 Returns the current file name to decode.
130 If \l setSourceDevice was called, this will
131 be empty.
132*/
133QUrl QAudioDecoder::source() const
134{
135 return decoder ? decoder->source() : QString{};
136}
137
138/*!
139 Sets the current audio file name to \a fileName.
140
141 When this property is set any current decoding is stopped,
142 and any audio buffers are discarded.
143
144 You can only specify either a source filename or
145 a source QIODevice. Setting one will unset the other.
146*/
147void QAudioDecoder::setSource(const QUrl &fileName)
148{
149 if (!decoder)
150 return;
151
152 decoder->clearError();
153 decoder->setSource(fileName);
154}
155
156/*!
157 Returns the current source QIODevice, if one was set.
158 If \l setSource() was called, this will be a nullptr.
159*/
160QIODevice *QAudioDecoder::sourceDevice() const
161{
162 return decoder ? decoder->sourceDevice() : nullptr;
163}
164
165/*!
166 Sets the current audio QIODevice to \a device.
167
168 When this property is set any current decoding is stopped,
169 and any audio buffers are discarded.
170
171 You can only specify either a source filename or
172 a source QIODevice. Setting one will unset the other.
173*/
174void QAudioDecoder::setSourceDevice(QIODevice *device)
175{
176 if (decoder)
177 decoder->setSourceDevice(device);
178}
179
180/*!
181 Returns the audio format the decoder is set to.
182
183 \note This may be different than the format of the decoded
184 samples, if the audio format was set to an invalid one.
185
186 \sa setAudioFormat(), formatChanged()
187*/
188QAudioFormat QAudioDecoder::audioFormat() const
189{
190 return decoder ? decoder->audioFormat() : QAudioFormat{};
191}
192
193/*!
194 Set the desired audio format for decoded samples to \a format.
195
196 This property can only be set while the decoder is stopped.
197 Setting this property at other times will be ignored.
198
199 If the decoder does not support this format, \l error() will
200 be set to \c FormatError.
201
202 If you do not specify a format, the format of the decoded
203 audio itself will be used. Otherwise, some format conversion
204 will be applied.
205
206 If you wish to reset the decoded format to that of the original
207 audio file, you can specify an invalid \a format.
208
209 \warning Setting a desired audio format is not yet supported
210 on the Android backend. It does work with the default FFMPEG
211 backend.
212*/
213void QAudioDecoder::setAudioFormat(const QAudioFormat &format)
214{
215 if (isDecoding())
216 return;
217
218 if (decoder)
219 decoder->setAudioFormat(format);
220}
221
222/*!
223 Returns true if a buffer is available to be read,
224 and false otherwise. If there is no buffer available, calling
225 the \l read() function will return an invalid buffer.
226*/
227bool QAudioDecoder::bufferAvailable() const
228{
229 return decoder && decoder->bufferAvailable();
230}
231
232/*!
233 Returns position (in milliseconds) of the last buffer read from
234 the decoder or -1 if no buffers have been read.
235*/
236
237qint64 QAudioDecoder::position() const
238{
239 return decoder ? decoder->position() : -1;
240}
241
242/*!
243 Returns total duration (in milliseconds) of the audio stream or -1
244 if not available.
245*/
246
247qint64 QAudioDecoder::duration() const
248{
249 return decoder ? decoder->duration() : -1;
250}
251
252/*!
253 Read a buffer from the decoder, if one is available. Returns an invalid buffer
254 if there are no decoded buffers currently available, or on failure. In both cases
255 this function will not block.
256
257 You should either respond to the \l bufferReady() signal or check the
258 \l bufferAvailable() function before calling read() to make sure
259 you get useful data.
260*/
261
262QAudioBuffer QAudioDecoder::read() const
263{
264 return decoder ? decoder->read() : QAudioBuffer{};
265}
266
267// Enums
268/*!
269 \enum QAudioDecoder::Error
270
271 Defines a media player error condition.
272
273 \value NoError No error has occurred.
274 \value ResourceError A media resource couldn't be resolved.
275 \value FormatError The format of a media resource isn't supported.
276 \value AccessDeniedError There are not the appropriate permissions to play a media resource.
277 \value NotSupportedError QAudioDecoder is not supported on this platform
278*/
279
280// Signals
281/*!
282 \fn void QAudioDecoder::error(QAudioDecoder::Error error)
283
284 Signals that an \a error condition has occurred.
285
286 \sa errorString()
287*/
288
289/*!
290 \fn void QAudioDecoder::sourceChanged()
291
292 Signals that the current source of the decoder has changed.
293
294 \sa source(), sourceDevice()
295*/
296
297/*!
298 \fn void QAudioDecoder::formatChanged(const QAudioFormat &format)
299
300 Signals that the current audio format of the decoder has changed to \a format.
301
302 \sa audioFormat(), setAudioFormat()
303*/
304
305/*!
306 \fn void QAudioDecoder::bufferReady()
307
308 Signals that a new decoded audio buffer is available to be read.
309
310 \sa read(), bufferAvailable()
311*/
312
313/*!
314 \fn void QAudioDecoder::bufferAvailableChanged(bool available)
315
316 Signals the availability (if \a available is true) of a new buffer.
317
318 If \a available is false, there are no buffers available.
319
320 \sa bufferAvailable(), bufferReady()
321*/
322
323/*!
324 \fn void QAudioDecoder::finished()
325
326 Signals that the decoding has finished successfully.
327 If decoding fails, error signal is emitted instead.
328
329 \sa start(), stop(), error()
330*/
331
332/*!
333 \fn void QAudioDecoder::positionChanged(qint64 position)
334
335 Signals that the current \a position of the decoder has changed.
336
337 \sa durationChanged()
338*/
339
340/*!
341 \fn void QAudioDecoder::durationChanged(qint64 duration)
342
343 Signals that the estimated \a duration of the decoded data has changed.
344
345 \sa positionChanged()
346*/
347
348
349// Properties
350/*!
351 \property QAudioDecoder::source
352 \brief the active filename being decoded by the decoder object.
353*/
354
355/*!
356 \property QAudioDecoder::bufferAvailable
357 \brief whether there is a decoded audio buffer available
358*/
359
360QT_END_NAMESPACE
361
362#include "moc_qaudiodecoder.cpp"
363

source code of qtmultimedia/src/multimedia/audio/qaudiodecoder.cpp