1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29
30#include <QtCore/QString>
31#include <QtTest/QtTest>
32
33#include "qaudiodecoder.h"
34#include "mockaudiodecoderservice.h"
35#include "mockmediaserviceprovider.h"
36
37class tst_QAudioDecoder : public QObject
38{
39 Q_OBJECT
40
41public:
42 tst_QAudioDecoder();
43
44private Q_SLOTS:
45 void init();
46 void ctors();
47 void read();
48 void stop();
49 void format();
50 void source();
51 void readAll();
52 void nullControl();
53 void nullService();
54
55private:
56 MockAudioDecoderService *mockAudioDecoderService;
57 MockMediaServiceProvider *mockProvider;
58};
59
60tst_QAudioDecoder::tst_QAudioDecoder()
61{
62}
63
64void tst_QAudioDecoder::init()
65{
66 mockAudioDecoderService = new MockAudioDecoderService(this);
67 mockProvider = new MockMediaServiceProvider(mockAudioDecoderService);
68
69 QMediaServiceProvider::setDefaultServiceProvider(mockProvider);
70}
71
72void tst_QAudioDecoder::ctors()
73{
74 QAudioDecoder d;
75 QVERIFY(d.state() == QAudioDecoder::StoppedState);
76 QVERIFY(d.bufferAvailable() == false);
77 QCOMPARE(d.sourceFilename(), QString(""));
78
79 d.setSourceFilename("");
80 QVERIFY(d.state() == QAudioDecoder::StoppedState);
81 QVERIFY(d.bufferAvailable() == false);
82 QCOMPARE(d.sourceFilename(), QString(""));
83}
84
85void tst_QAudioDecoder::read()
86{
87 QAudioDecoder d;
88 QVERIFY(d.state() == QAudioDecoder::StoppedState);
89 QVERIFY(d.bufferAvailable() == false);
90
91 QSignalSpy readySpy(&d, SIGNAL(bufferReady()));
92 QSignalSpy bufferChangedSpy(&d, SIGNAL(bufferAvailableChanged(bool)));
93 QSignalSpy errorSpy(&d, SIGNAL(error(QAudioDecoder::Error)));
94
95 // Starting with empty source == error
96 d.start();
97
98 QVERIFY(d.state() == QAudioDecoder::StoppedState);
99 QVERIFY(d.bufferAvailable() == false);
100
101 QCOMPARE(readySpy.count(), 0);
102 QCOMPARE(bufferChangedSpy.count(), 0);
103 QCOMPARE(errorSpy.count(), 1);
104
105 // Set the source to something
106 d.setSourceFilename("Blah");
107 QCOMPARE(d.sourceFilename(), QString("Blah"));
108
109 readySpy.clear();
110 errorSpy.clear();
111 bufferChangedSpy.clear();
112
113 d.start();
114 QCOMPARE(d.state(), QAudioDecoder::DecodingState);
115 QCOMPARE(d.bufferAvailable(), false); // not yet
116
117 // Try to read
118 QAudioBuffer b = d.read();
119 QVERIFY(!b.isValid());
120
121 // Read again with no parameter
122 b = d.read();
123 QVERIFY(!b.isValid());
124
125 // Wait a while
126 QTRY_VERIFY(d.bufferAvailable());
127
128 QVERIFY(d.bufferAvailable());
129
130 b = d.read();
131 QVERIFY(b.format().isValid());
132 QVERIFY(b.isValid());
133 QVERIFY(b.format().channelCount() == 1);
134 QVERIFY(b.sampleCount() == 4);
135
136 QVERIFY(readySpy.count() >= 1);
137 QVERIFY(errorSpy.count() == 0);
138
139 if (d.bufferAvailable()) {
140 QVERIFY(bufferChangedSpy.count() == 1);
141 } else {
142 QVERIFY(bufferChangedSpy.count() == 2);
143 }
144}
145
146void tst_QAudioDecoder::stop()
147{
148 QAudioDecoder d;
149 QVERIFY(d.state() == QAudioDecoder::StoppedState);
150 QVERIFY(d.bufferAvailable() == false);
151
152 QSignalSpy readySpy(&d, SIGNAL(bufferReady()));
153 QSignalSpy bufferChangedSpy(&d, SIGNAL(bufferAvailableChanged(bool)));
154 QSignalSpy errorSpy(&d, SIGNAL(error(QAudioDecoder::Error)));
155
156 // Starting with empty source == error
157 d.start();
158
159 QVERIFY(d.state() == QAudioDecoder::StoppedState);
160 QVERIFY(d.bufferAvailable() == false);
161
162 QCOMPARE(readySpy.count(), 0);
163 QCOMPARE(bufferChangedSpy.count(), 0);
164 QCOMPARE(errorSpy.count(), 1);
165
166 // Set the source to something
167 d.setSourceFilename("Blah");
168 QCOMPARE(d.sourceFilename(), QString("Blah"));
169
170 readySpy.clear();
171 errorSpy.clear();
172 bufferChangedSpy.clear();
173
174 d.start();
175 QCOMPARE(d.state(), QAudioDecoder::DecodingState);
176 QCOMPARE(d.bufferAvailable(), false); // not yet
177
178 // Try to read
179 QAudioBuffer b = d.read();
180 QVERIFY(!b.isValid());
181
182 // Read again with no parameter
183 b = d.read();
184 QVERIFY(!b.isValid());
185
186 // Wait a while
187 QTRY_VERIFY(d.bufferAvailable());
188
189 QVERIFY(d.bufferAvailable());
190
191 // Now stop
192 d.stop();
193
194 QVERIFY(d.state() == QAudioDecoder::StoppedState);
195 QVERIFY(d.bufferAvailable() == false);
196}
197
198void tst_QAudioDecoder::format()
199{
200 QAudioDecoder d;
201 QVERIFY(d.state() == QAudioDecoder::StoppedState);
202 QVERIFY(d.bufferAvailable() == false);
203
204 QSignalSpy readySpy(&d, SIGNAL(bufferReady()));
205 QSignalSpy bufferChangedSpy(&d, SIGNAL(bufferAvailableChanged(bool)));
206 QSignalSpy errorSpy(&d, SIGNAL(error(QAudioDecoder::Error)));
207
208 // Set the source to something
209 d.setSourceFilename("Blah");
210 QCOMPARE(d.sourceFilename(), QString("Blah"));
211
212 readySpy.clear();
213 errorSpy.clear();
214 bufferChangedSpy.clear();
215
216 d.start();
217 QCOMPARE(d.state(), QAudioDecoder::DecodingState);
218 QCOMPARE(d.bufferAvailable(), false); // not yet
219
220 // Try to read
221 QAudioBuffer b = d.read();
222 QVERIFY(!b.isValid());
223
224 // Read again with no parameter
225 b = d.read();
226 QVERIFY(!b.isValid());
227
228 // Wait a while
229 QTRY_VERIFY(d.bufferAvailable());
230
231 b = d.read();
232 QVERIFY(d.audioFormat() == b.format());
233
234 // Setting format while decoding is forbidden
235 QAudioFormat f(d.audioFormat());
236 f.setChannelCount(2);
237
238 d.setAudioFormat(f);
239 QVERIFY(d.audioFormat() != f);
240 QVERIFY(d.audioFormat() == b.format());
241
242 // Now stop, and set something specific
243 d.stop();
244 d.setAudioFormat(f);
245 QVERIFY(d.audioFormat() == f);
246
247 // Decode again
248 d.start();
249 QTRY_VERIFY(d.bufferAvailable());
250
251 b = d.read();
252 QVERIFY(d.audioFormat() == f);
253 QVERIFY(b.format() == f);
254}
255
256void tst_QAudioDecoder::source()
257{
258 QAudioDecoder d;
259
260 QVERIFY(d.sourceFilename().isEmpty());
261 QVERIFY(d.sourceDevice() == 0);
262
263 QFile f;
264 d.setSourceDevice(&f);
265 QVERIFY(d.sourceFilename().isEmpty());
266 QVERIFY(d.sourceDevice() == &f);
267
268 d.setSourceFilename("Foo");
269 QVERIFY(d.sourceFilename() == QString("Foo"));
270 QVERIFY(d.sourceDevice() == 0);
271
272 d.setSourceDevice(0);
273 QVERIFY(d.sourceFilename().isEmpty());
274 QVERIFY(d.sourceDevice() == 0);
275
276 d.setSourceFilename("Foo");
277 QVERIFY(d.sourceFilename() == QString("Foo"));
278 QVERIFY(d.sourceDevice() == 0);
279
280 d.setSourceFilename(QString());
281 QVERIFY(d.sourceFilename() == QString());
282 QVERIFY(d.sourceDevice() == 0);
283}
284
285void tst_QAudioDecoder::readAll()
286{
287 QAudioDecoder d;
288 d.setSourceFilename("Foo");
289 QVERIFY(d.state() == QAudioDecoder::StoppedState);
290
291 QSignalSpy durationSpy(&d, SIGNAL(durationChanged(qint64)));
292 QSignalSpy positionSpy(&d, SIGNAL(positionChanged(qint64)));
293 QSignalSpy stateSpy(&d, SIGNAL(stateChanged(QAudioDecoder::State)));
294 QSignalSpy finishedSpy(&d, SIGNAL(finished()));
295 QSignalSpy bufferAvailableSpy(&d, SIGNAL(bufferAvailableChanged(bool)));
296 d.start();
297 int i = 0;
298 forever {
299 QVERIFY(d.state() == QAudioDecoder::DecodingState);
300 QCOMPARE(stateSpy.count(), 1);
301 QCOMPARE(durationSpy.count(), 1);
302 QVERIFY(finishedSpy.isEmpty());
303 QTRY_VERIFY(bufferAvailableSpy.count() >= 1);
304 if (d.bufferAvailable()) {
305 QAudioBuffer b = d.read();
306 QVERIFY(b.isValid());
307 QCOMPARE(b.startTime() / 1000, d.position());
308 QVERIFY(!positionSpy.isEmpty());
309 QList<QVariant> arguments = positionSpy.takeLast();
310 QCOMPARE(arguments.at(0).toLongLong(), b.startTime() / 1000);
311
312 i++;
313 if (i == MOCK_DECODER_MAX_BUFFERS) {
314 QCOMPARE(finishedSpy.count(), 1);
315 QCOMPARE(stateSpy.count(), 2);
316 QVERIFY(d.state() == QAudioDecoder::StoppedState);
317 QList<QVariant> arguments = stateSpy.takeLast();
318 QVERIFY(arguments.at(0).toInt() == (int)QAudioDecoder::StoppedState);
319 QVERIFY(!d.bufferAvailable());
320 QVERIFY(!bufferAvailableSpy.isEmpty());
321 arguments = bufferAvailableSpy.takeLast();
322 QVERIFY(arguments.at(0).toBool() == false);
323 break;
324 }
325 } else
326 QTest::qWait(ms: 30);
327 }
328}
329
330void tst_QAudioDecoder::nullControl()
331{
332 mockAudioDecoderService->setControlNull();
333 QAudioDecoder d;
334
335 QVERIFY(d.error() == QAudioDecoder::ServiceMissingError);
336 QVERIFY(!d.errorString().isEmpty());
337
338 QVERIFY(d.hasSupport("MIME") == QMultimedia::MaybeSupported);
339
340 QVERIFY(d.state() == QAudioDecoder::StoppedState);
341
342 QVERIFY(d.sourceFilename().isEmpty());
343 d.setSourceFilename("test");
344 QVERIFY(d.sourceFilename().isEmpty());
345
346 QFile f;
347 QVERIFY(d.sourceDevice() == 0);
348 d.setSourceDevice(&f);
349 QVERIFY(d.sourceDevice() == 0);
350
351 QAudioFormat format;
352 format.setChannelCount(2);
353 QVERIFY(!d.audioFormat().isValid());
354 d.setAudioFormat(format);
355 QVERIFY(!d.audioFormat().isValid());
356
357 QVERIFY(!d.read().isValid());
358 QVERIFY(!d.bufferAvailable());
359
360 QVERIFY(d.position() == -1);
361 QVERIFY(d.duration() == -1);
362
363 d.start();
364 QVERIFY(d.error() == QAudioDecoder::ServiceMissingError);
365 QVERIFY(!d.errorString().isEmpty());
366 QVERIFY(d.state() == QAudioDecoder::StoppedState);
367 d.stop();
368}
369
370
371void tst_QAudioDecoder::nullService()
372{
373 mockProvider->service = 0;
374 QAudioDecoder d;
375
376 QVERIFY(d.error() == QAudioDecoder::ServiceMissingError);
377 QVERIFY(!d.errorString().isEmpty());
378
379 QVERIFY(d.hasSupport("MIME") == QMultimedia::MaybeSupported);
380
381 QVERIFY(d.state() == QAudioDecoder::StoppedState);
382
383 QVERIFY(d.sourceFilename().isEmpty());
384 d.setSourceFilename("test");
385 QVERIFY(d.sourceFilename().isEmpty());
386
387 QFile f;
388 QVERIFY(d.sourceDevice() == 0);
389 d.setSourceDevice(&f);
390 QVERIFY(d.sourceDevice() == 0);
391
392 QAudioFormat format;
393 format.setChannelCount(2);
394 QVERIFY(!d.audioFormat().isValid());
395 d.setAudioFormat(format);
396 QVERIFY(!d.audioFormat().isValid());
397
398 QVERIFY(!d.read().isValid());
399 QVERIFY(!d.bufferAvailable());
400
401 QVERIFY(d.position() == -1);
402 QVERIFY(d.duration() == -1);
403
404 d.start();
405 QVERIFY(d.error() == QAudioDecoder::ServiceMissingError);
406 QVERIFY(!d.errorString().isEmpty());
407 QVERIFY(d.state() == QAudioDecoder::StoppedState);
408 d.stop();
409}
410
411QTEST_MAIN(tst_QAudioDecoder)
412
413#include "tst_qaudiodecoder.moc"
414

source code of qtmultimedia/tests/auto/unit/qaudiodecoder/tst_qaudiodecoder.cpp