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