Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

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:

    1. isSequential: Always returns true
    2. bytesAvailable: Returns actual number of available bytes = total_downloaded - bytes_already_read
    3. pos: Returns current read position = bytes_already_read
    4. readData: Works as expected, copies maxlen (or available if less) bytes from download buffer to pointer passed in
    5. 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.

    Code at: https://bazaar.launchpad.net/~waver-developers/waver/trunk/view/head:/decodergenericnetworksource.cpp

    Qt's MFStream at
    https://code.woboq.org/qt5/qtmultimedia/src/plugins/wmf/mfstream.cpp.html


  • Lifetime Qt Champion

    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:

    1. readySignal is no longer being emitted
    2. isSequential now returns false
    3. 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.


  • Lifetime Qt Champion

    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.


  • Lifetime Qt Champion

    Great ! :-D

    With duration I meant QAudioDecoder::duration.

    Would you mind posting the final class ?

    I might be useful to other people :-)



  • @SGaist

    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.


  • Lifetime Qt Champion

    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.


Log in to reply