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

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

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