Solved QAudioDecoder w/ IODevice
-
Hi,
In order to support playing of remote audio streams, I subclassed QIODevice, and I feed my subclass to QAudioDecoder's setSourceDevice. Only had to override the following methods:
- isSequential: Always returns true
- bytesAvailable: Returns actual number of available bytes = total_downloaded - bytes_already_read
- pos: Returns current read position = bytes_already_read
- readData: Works as expected, copies maxlen (or available if less) bytes from download buffer to pointer passed in
- writeData: Does nothing
Works like a charm with Linux/GSstreamer.
However, not so much in Windows. First, nothing happened, the decoder just sat there without doing anything. So it seemed that I must emit the readyRead signal.. But as soon as it happens, the app crashes in MFStream::doRead on the line
HRESULT hr = m_currentReadResult->GetObject(&pUnk);
Crash happens because at this point m_currentReadResult is null. Seems that MFStream::beginRead was never called.
Am I missing something, or maybe this is a bug in MFStream?
Any help would be greatly appreciated.
Qt's MFStream at
https://code.woboq.org/qt5/qtmultimedia/src/plugins/wmf/mfstream.cpp.html -
Hi and welcome to devnet,
Looks surprising indeed.
Which version of Qt are you currently using ?
-
Hi,
Thank you.
I'm using 5.15.2, compiling with MSVC2019 64bit kit.
-
Update:
So I was thinking emitting readyRead must not be the correct way to do this. The following modifications seem to be a step to the right direction:
- readySignal is no longer being emitted
- isSequential now returns false
- I also overrode seek
Now there is no crash anymore. I see pos, seek, readData being called multiple times:
pos 0 seek 0 seek 0 read 16384 16384 seek 0 seek 0 seek 0 networkDownloadProgress 503808 1980416 2561195 seek 0 seek 0 seek 0 seek 0 seek 0 seek 0 seek 0 seek 0 read 56385 56385 pos 56385 seek 0 seek 0 read 16384 16384 seek 0 seek 0 pos 0 read 53248 53248
No more after these, even though the network download continues normally until it's done. There is still no output from QAudioDecoder, bufferReady is never emitted.
This is the progress I made, I'm positive this is the right direction to go, but obviously something is still missing.
-
Maybe the duration is wrongly reported ?
-
@SGaist Sorry, I'm not sure what you mean.
-
OK, got this figured out. Had to overwrite size and atEnd too. That's all it took to make it work.
-
Great ! :-D
With duration I meant QAudioDecoder::duration.
Would you mind posting the final class ?
I might be useful to other people :-)
-
The project is open source, code is available at https://bazaar.launchpad.net/~waver-developers/waver/trunk/files. This class is in decodergenericnetworksource.h & decodergenericnetworksource.cpp.
Please note that it will take some time (possible a week or two) before changes mentioned in this post will be checked in. This is because the solution opens another can of worms: It's evident that the Windows decoder requires random access, but for live streams it's impossible to cache the downloaded raw data forever. This is a problem still needs to be dealt with.
-
Thanks !
You might want to check the Qt 6 implementation of Qt multimedia, there has been a lot of changes and there might be stuff for your in there with regard to network media sources.