Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qaudiodecoder.cpp
Go to the documentation of this file.
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
6
7#include <QtMultimedia/private/qmultimediautils_p.h>
8#include <QtMultimedia/private/qplatformaudiodecoder_p.h>
9#include <QtMultimedia/private/qplatformmediaintegration_p.h>
10#include <QtCore/qcoreevent.h>
11#include <QtCore/qdebug.h>
12#include <QtCore/qfile.h>
13#include <QtCore/qmetaobject.h>
14#include <QtCore/qpointer.h>
15#include <QtCore/qtemporaryfile.h>
16#include <QtCore/qtimer.h>
17#include <QtCore/qurl.h>
18
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) : QObject{ *new QAudioDecoderPrivate, parent }
42{
43 Q_D(QAudioDecoder);
44
45 auto maybeDecoder = QPlatformMediaIntegration::instance()->createAudioDecoder(this);
46 if (maybeDecoder) {
47 d->decoder.reset(maybeDecoder.value());
48 } else {
49 qWarning() << "Failed to initialize QAudioDecoder" << maybeDecoder.error();
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 Q_D(const QAudioDecoder);
64
65 return bool(d->decoder);
66}
67
68/*!
69 \property QAudioDecoder::isDecoding
70 \brief \c true if the decoder is currently running and decoding audio data.
71*/
72bool QAudioDecoder::isDecoding() const
73{
74 Q_D(const QAudioDecoder);
75
76 return d->decoder && d->decoder->isDecoding();
77}
78
79/*!
80
81 Returns the current error state of the QAudioDecoder.
82*/
83QAudioDecoder::Error QAudioDecoder::error() const
84{
85 Q_D(const QAudioDecoder);
86 return d->decoder ? d->decoder->error() : NotSupportedError;
87}
88
89/*!
90 \property QAudioDecoder::error
91
92 Returns a human readable description of the current error, or
93 an empty string is there is no error.
94*/
95QString QAudioDecoder::errorString() const
96{
97 Q_D(const QAudioDecoder);
98 if (!d->decoder)
99 return tr("QAudioDecoder not supported.");
100 return d->decoder->errorString();
101}
102
103/*!
104 Starts decoding the audio resource.
105
106 As data gets decoded, the \l bufferReady() signal will be emitted
107 when enough data has been decoded. Calling \l read() will then return
108 an audio buffer without blocking.
109
110 If you call read() before a buffer is ready, an invalid buffer will
111 be returned, again without blocking.
112
113 \sa read()
114*/
115void QAudioDecoder::start()
116{
117 Q_D(QAudioDecoder);
118
119 if (!d->decoder)
120 return;
121
122 // Reset error conditions
123 d->decoder->clearError();
124 d->decoder->start();
125}
126
127/*!
128 Stop decoding audio. Calling \l start() again will resume decoding from the beginning.
129*/
130void QAudioDecoder::stop()
131{
132 Q_D(QAudioDecoder);
133
134 if (d->decoder)
135 d->decoder->stop();
136}
137
138/*!
139 Returns the current file name to decode.
140 If \l setSourceDevice was called, this will
141 be empty.
142*/
143QUrl QAudioDecoder::source() const
144{
145 Q_D(const QAudioDecoder);
146 return d->unresolvedUrl;
147}
148
149/*!
150 Sets the current audio file name to \a fileName.
151
152 When this property is set any current decoding is stopped,
153 and any audio buffers are discarded.
154
155 You can only specify either a source filename or
156 a source QIODevice. Setting one will unset the other.
157*/
158void QAudioDecoder::setSource(const QUrl &fileName)
159{
160 using namespace QtMultimediaPrivate;
161
162 Q_D(QAudioDecoder);
163
164 if (!d->decoder)
165 return;
166
167 d->decoder->clearError();
168 d->unresolvedUrl = fileName;
169 d->decoder->setSourceDevice(nullptr);
170 d->qrcFile.reset();
171
172 // Platform decoders generally can't read qrc resources directly; unless the platform
173 // decoder says otherwise, copy the resource to a real file first.
174 if (!fileName.isEmpty() && fileName.scheme() == u"qrc" && !d->decoder->canReadQrc()) {
175 QFile file(u':' + fileName.path());
176 if (!file.open(QFile::ReadOnly)) {
177 d->decoder->error(QAudioDecoder::ResourceError,
178 tr("Attempting to play invalid Qt resource"));
179 return;
180 }
181
182 auto qrcMedia = qCopyQrcToTemporaryFile(file, fileName);
183 if (!qrcMedia) {
184 d->decoder->error(QAudioDecoder::ResourceError, qrcMedia.error());
185 return;
186 }
187
188 d->qrcFile = std::move(qrcMedia->file);
189 d->decoder->setSource(qrcMedia->url);
190 return;
191 }
192
193 QUrl url = qMediaFromUserInput(fileName);
194 d->decoder->setSource(url);
195}
196
197/*!
198 Returns the current source QIODevice, if one was set.
199 If \l setSource() was called, this will be a nullptr.
200*/
201QIODevice *QAudioDecoder::sourceDevice() const
202{
203 Q_D(const QAudioDecoder);
204 return d->decoder ? d->decoder->sourceDevice() : nullptr;
205}
206
207/*!
208 Sets the current audio QIODevice to \a device.
209
210 When this property is set any current decoding is stopped,
211 and any audio buffers are discarded.
212
213 You can only specify either a source filename or
214 a source QIODevice. Setting one will unset the other.
215*/
216void QAudioDecoder::setSourceDevice(QIODevice *device)
217{
218 Q_D(QAudioDecoder);
219 if (d->decoder) {
220 d->unresolvedUrl = QUrl{};
221 d->decoder->setSourceDevice(device);
222 }
223}
224
225/*!
226 Returns the audio format the decoder is set to.
227
228 \note This may be different than the format of the decoded
229 samples, if the audio format was set to an invalid one.
230
231 \sa setAudioFormat(), formatChanged()
232*/
233QAudioFormat QAudioDecoder::audioFormat() const
234{
235 Q_D(const QAudioDecoder);
236 return d->decoder ? d->decoder->audioFormat() : QAudioFormat{};
237}
238
239/*!
240 Set the desired audio format for decoded samples to \a format.
241
242 This property can only be set while the decoder is stopped.
243 Setting this property at other times will be ignored.
244
245 If the decoder does not support this format, \l error() will
246 be set to \c FormatError.
247
248 If you do not specify a format, the format of the decoded
249 audio itself will be used. Otherwise, some format conversion
250 will be applied.
251
252 If you wish to reset the decoded format to that of the original
253 audio file, you can specify an invalid \a format.
254
255 \warning Setting a desired audio format is not yet supported
256 on the Android backend. It does work with the default FFMPEG
257 backend.
258*/
259void QAudioDecoder::setAudioFormat(const QAudioFormat &format)
260{
261 if (isDecoding())
262 return;
263
264 Q_D(QAudioDecoder);
265
266 if (d->decoder)
267 d->decoder->setAudioFormat(format);
268}
269
270/*!
271 Returns true if a buffer is available to be read,
272 and false otherwise. If there is no buffer available, calling
273 the \l read() function will return an invalid buffer.
274*/
275bool QAudioDecoder::bufferAvailable() const
276{
277 Q_D(const QAudioDecoder);
278 return d->decoder && d->decoder->bufferAvailable();
279}
280
281/*!
282 Returns position (in milliseconds) of the last buffer read from
283 the decoder or -1 if no buffers have been read.
284*/
285
286qint64 QAudioDecoder::position() const
287{
288 Q_D(const QAudioDecoder);
289 return d->decoder ? d->decoder->position() : -1;
290}
291
292/*!
293 Returns total duration (in milliseconds) of the audio stream or -1
294 if not available.
295*/
296
297qint64 QAudioDecoder::duration() const
298{
299 Q_D(const QAudioDecoder);
300 return d->decoder ? d->decoder->duration() : -1;
301}
302
303/*!
304 Read a buffer from the decoder, if one is available. Returns an invalid buffer
305 if there are no decoded buffers currently available, or on failure. In both cases
306 this function will not block.
307
308 You should either respond to the \l bufferReady() signal or check the
309 \l bufferAvailable() function before calling read() to make sure
310 you get useful data.
311*/
312
313QAudioBuffer QAudioDecoder::read() const
314{
315 Q_D(const QAudioDecoder);
316 return d->decoder ? d->decoder->read() : QAudioBuffer{};
317}
318
319// Enums
320/*!
321 \enum QAudioDecoder::Error
322
323 Defines a media player error condition.
324
325 \value NoError No error has occurred.
326 \value ResourceError A media resource couldn't be resolved.
327 \value FormatError The format of a media resource isn't supported.
328 \value AccessDeniedError There are not the appropriate permissions to play a media resource.
329 \value NotSupportedError QAudioDecoder is not supported on this platform
330*/
331
332// Signals
333/*!
334 \fn void QAudioDecoder::error(QAudioDecoder::Error error)
335
336 Signals that an \a error condition has occurred.
337
338 \sa errorString()
339*/
340
341/*!
342 \fn void QAudioDecoder::sourceChanged()
343
344 Signals that the current source of the decoder has changed.
345
346 \sa source(), sourceDevice()
347*/
348
349/*!
350 \fn void QAudioDecoder::formatChanged(const QAudioFormat &format)
351
352 Signals that the current audio format of the decoder has changed to \a format.
353
354 \sa audioFormat(), setAudioFormat()
355*/
356
357/*!
358 \fn void QAudioDecoder::bufferReady()
359
360 Signals that a new decoded audio buffer is available to be read.
361
362 \sa read(), bufferAvailable()
363*/
364
365/*!
366 \fn void QAudioDecoder::bufferAvailableChanged(bool available)
367
368 Signals the availability (if \a available is true) of a new buffer.
369
370 If \a available is false, there are no buffers available.
371
372 \sa bufferAvailable(), bufferReady()
373*/
374
375/*!
376 \fn void QAudioDecoder::finished()
377
378 Signals that the decoding has finished successfully.
379 If decoding fails, error signal is emitted instead.
380
381 \sa start(), stop(), error()
382*/
383
384/*!
385 \fn void QAudioDecoder::positionChanged(qint64 position)
386
387 Signals that the current \a position of the decoder has changed.
388
389 \sa durationChanged()
390*/
391
392/*!
393 \fn void QAudioDecoder::durationChanged(qint64 duration)
394
395 Signals that the estimated \a duration of the decoded data has changed.
396
397 \sa positionChanged()
398*/
399
400// Properties
401/*!
402 \property QAudioDecoder::source
403 \brief the active filename being decoded by the decoder object.
404*/
405
406/*!
407 \property QAudioDecoder::bufferAvailable
408 \brief whether there is a decoded audio buffer available
409*/
410
411QT_END_NAMESPACE
412
413#include "moc_qaudiodecoder.cpp"
Combined button and popup list for selecting options.