diff options
author | Jøger Hansegård <joger.hansegard@qt.io> | 2024-02-26 20:01:03 +0100 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2024-02-29 18:50:07 +0000 |
commit | fce7ad6ca769c829a4e68d6c7b4df0ae60900a80 (patch) | |
tree | b9d1b088d30312143a17e6d0659cd6600b759d7c | |
parent | 307dcf5b365af1251c8bbf515322ee31229aa796 (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.cpp | 8 | ||||
-rw-r--r-- | src/multimedia/audio/qwavedecoder.h | 6 | ||||
-rw-r--r-- | tests/auto/unit/multimedia/qwavedecoder/data/isawav_1_8_8000_even_bext.wav | bin | 0 -> 2064 bytes | |||
-rw-r--r-- | tests/auto/unit/multimedia/qwavedecoder/data/isawav_1_8_8000_odd_bext.wav | bin | 0 -> 2064 bytes | |||
-rw-r--r-- | tests/auto/unit/multimedia/qwavedecoder/tst_qwavedecoder.cpp | 5 |
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 Binary files differnew file mode 100644 index 000000000..531b0ee58 --- /dev/null +++ b/tests/auto/unit/multimedia/qwavedecoder/data/isawav_1_8_8000_even_bext.wav 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 Binary files differnew file mode 100644 index 000000000..467be6312 --- /dev/null +++ b/tests/auto/unit/multimedia/qwavedecoder/data/isawav_1_8_8000_odd_bext.wav 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; |