summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJøger Hansegård <joger.hansegard@qt.io>2024-02-26 20:01:03 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2024-02-29 18:50:07 +0000
commitfce7ad6ca769c829a4e68d6c7b4df0ae60900a80 (patch)
treeb9d1b088d30312143a17e6d0659cd6600b759d7c
parent307dcf5b365af1251c8bbf515322ee31229aa796 (diff)
Fix QWaveDecoder handling of padding bytes in RIFF chunks
This patch adds support for reading WAV files with odd sized payloads in QWaveDecoder. This allows playing WAV files that contains odd-sized chunks before the 'data' chunk that contains the audio data. According to the specification, Multimedia Programming Interface and Data Specifications 1.0. IBM / Microsoft. pp. 10-11, the payload of RIFF chunks should be padded to an even length, so the fix is to round odd payload sizes up to next even size. Tests are extended with two files where a bext section patched in. One file has an odd length bext chunk with padding byte, the second file has an even length bext chunk without padding byte. Fixes: QTBUG-122193 Pick-to: 6.5 Change-Id: I6940db47db91a61e6b97f8f41043b2967b0d155a Reviewed-by: Mikko Hallamaa <mikko.hallamaa@qt.io> Reviewed-by: Artem Dyomin <artem.dyomin@qt.io> Reviewed-by: Tim Blechmann <tim@klingt.org> (cherry picked from commit 7d16111777350deec9ebc5ee1f08288af19534e2) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> (cherry picked from commit 2fe57dae028205b118670e4aa4293d4f8aa14744)
-rw-r--r--src/multimedia/audio/qwavedecoder.cpp8
-rw-r--r--src/multimedia/audio/qwavedecoder.h6
-rw-r--r--tests/auto/unit/multimedia/qwavedecoder/data/isawav_1_8_8000_even_bext.wavbin0 -> 2064 bytes
-rw-r--r--tests/auto/unit/multimedia/qwavedecoder/data/isawav_1_8_8000_odd_bext.wavbin0 -> 2064 bytes
-rw-r--r--tests/auto/unit/multimedia/qwavedecoder/tst_qwavedecoder.cpp5
5 files changed, 15 insertions, 4 deletions
diff --git a/src/multimedia/audio/qwavedecoder.cpp b/src/multimedia/audio/qwavedecoder.cpp
index 2d2e04e87..0df50bcbf 100644
--- a/src/multimedia/audio/qwavedecoder.cpp
+++ b/src/multimedia/audio/qwavedecoder.cpp
@@ -439,9 +439,15 @@ bool QWaveDecoder::findChunk(const char *chunkId)
if (qstrncmp(descriptor.id, chunkId, 4) == 0)
return true;
+ // A program reading a RIFF file can skip over any chunk whose chunk
+ // ID it doesn't recognize; it simply skips the number of bytes specified
+ // by ckSize plus the pad byte, if present. See Multimedia Programming
+ // Interface and Data Specifications 1.0. IBM / Microsoft. August 1991. pp. 10-11.
+ const quint32 sizeWithPad = descriptor.size + (descriptor.size & 1);
+
// It's possible that bytes->available() is less than the chunk size
// if it's corrupt.
- junkToSkip = qint64(sizeof(chunk) + descriptor.size);
+ junkToSkip = qint64(sizeof(chunk) + sizeWithPad);
// Skip the current amount
if (junkToSkip > 0)
diff --git a/src/multimedia/audio/qwavedecoder.h b/src/multimedia/audio/qwavedecoder.h
index 11846aaaa..a96e731db 100644
--- a/src/multimedia/audio/qwavedecoder.h
+++ b/src/multimedia/audio/qwavedecoder.h
@@ -62,9 +62,11 @@ private:
struct chunk
{
- char id[4];
- quint32 size;
+ char id[4]; // A four-character code that identifies the representation of the chunk data
+ // padded on the right with blank characters (ASCII 32)
+ quint32 size; // Does not include the size of the id or size fields or the pad byte at the end of payload
};
+
bool peekChunk(chunk* pChunk, bool handleEndianness = true);
struct RIFFHeader
diff --git a/tests/auto/unit/multimedia/qwavedecoder/data/isawav_1_8_8000_even_bext.wav b/tests/auto/unit/multimedia/qwavedecoder/data/isawav_1_8_8000_even_bext.wav
new file mode 100644
index 000000000..531b0ee58
--- /dev/null
+++ b/tests/auto/unit/multimedia/qwavedecoder/data/isawav_1_8_8000_even_bext.wav
Binary files differ
diff --git a/tests/auto/unit/multimedia/qwavedecoder/data/isawav_1_8_8000_odd_bext.wav b/tests/auto/unit/multimedia/qwavedecoder/data/isawav_1_8_8000_odd_bext.wav
new file mode 100644
index 000000000..467be6312
--- /dev/null
+++ b/tests/auto/unit/multimedia/qwavedecoder/data/isawav_1_8_8000_odd_bext.wav
Binary files differ
diff --git a/tests/auto/unit/multimedia/qwavedecoder/tst_qwavedecoder.cpp b/tests/auto/unit/multimedia/qwavedecoder/tst_qwavedecoder.cpp
index 70c3a4d8c..59d3eaee4 100644
--- a/tests/auto/unit/multimedia/qwavedecoder/tst_qwavedecoder.cpp
+++ b/tests/auto/unit/multimedia/qwavedecoder/tst_qwavedecoder.cpp
@@ -91,7 +91,10 @@ void tst_QWaveDecoder::file_data()
QTest::newRow("File isawav_2_16_44100_be.wav") << testFilePath("isawav_2_16_44100_be.wav") << tst_QWaveDecoder::None << 2 << 16 << 44100;
// The next file has extra data in the wave header.
QTest::newRow("File isawav_1_16_44100_le_2.wav") << testFilePath("isawav_1_16_44100_le_2.wav") << tst_QWaveDecoder::None << 1 << 16 << 44100;
-
+ // The next file has embedded bext chunk with odd payload (QTBUG-122193)
+ QTest::newRow("File isawav_1_8_8000_odd_bext.wav") << testFilePath("isawav_1_8_8000_odd_bext.wav") << tst_QWaveDecoder::None << 1 << 8 << 8000;
+ // The next file has embedded bext chunk with even payload
+ QTest::newRow("File isawav_1_8_8000_even_bext.wav") << testFilePath("isawav_1_8_8000_even_bext.wav") << tst_QWaveDecoder::None << 1 << 8 << 8000;
// 32 bit waves are not supported
QTest::newRow("File isawav_1_32_8000_le.wav") << testFilePath("isawav_1_32_8000_le.wav") << tst_QWaveDecoder::FormatDescriptor << 1 << 32 << 8000;
QTest::newRow("File isawav_1_32_44100_le.wav") << testFilePath("isawav_1_32_44100_le.wav") << tst_QWaveDecoder::FormatDescriptor << 1 << 32 << 44100;