Peter Peter - 3 months ago 14
C++ Question

subclassing QIODevice for QAudioDecoder

Qt 5.7

According to the documentation,

QAudioDecoder
does not support streaming media. But is accepts either a filename or a
QIODevice
as source. Came the "bright idea": let's subclass
QIODevice
to create streaming media support.

But I always get an error:


Unable to start decoding process. Stream contains no data.


I have checked and double checked and debugged. Can't figure out what can be the problem.

I'm only testing it, so the code below is by no means final.

header:

class InputBuffer : public QIODevice
{

public:

InputBuffer(QString fileName);
~InputBuffer();

qint64 readData(char *data, qint64 maxlen);
qint64 writeData(const char *data, qint64 len);

bool isSequential();
qint64 bytesAvailable();
qint64 size();


private:

char* bufferRef;
qint64 length;
qint64 position;

};


implementation:

#include "inputbuffer.h"

InputBuffer::InputBuffer(QString fileName)
{
QFileInfo fileInfo(fileName);

length = fileInfo.size();
position = 0;

bufferRef = (char*)malloc(length);

QFile file(fileName);
file.open(QFile::ReadOnly);
file.read(bufferRef, length);
file.close();

emit readyRead();
}


InputBuffer::~InputBuffer()
{
free(bufferRef);
}


qint64 InputBuffer::readData(char *data, qint64 maxlen)
{
if (position >= length) {
return -1;
}

qint64 readSize = qMin(maxlen, length - position);

memcpy(data, bufferRef + position, readSize);
position += readSize;

return readSize;
}


qint64 InputBuffer::writeData(const char *data, qint64 len)
{
return -1;
}


bool InputBuffer::isSequential()
{
return true;
}


qint64 InputBuffer::bytesAvailable()
{
return length - position;
}


qint64 InputBuffer::size()
{
return length;
}


usage:

inputBufferRef = new InputBuffer("/home/pp/Zen├ęk/Test.mp3");
inputBufferRef->open(QIODevice::ReadOnly);

audioDecoderRef = new QAudioDecoder();

audioDecoderRef->setAudioFormat(audioFormat);
audioDecoderRef->setSourceDevice(inputBufferRef);

connect(audioDecoderRef, SIGNAL(bufferReady()), this, SLOT(decoderBufferReady()));
connect(audioDecoderRef, SIGNAL(finished()), this, SLOT(decoderFinished()));
connect(audioDecoderRef, SIGNAL(error(QAudioDecoder::Error)), this, SLOT(decoderError(QAudioDecoder::Error)));

audioDecoderRef->start();

Answer

None of your isSequential(), bytesAvailable(), nor size() methods override the respective method in QIODevice, because the signatures don't match. They are all missing a const qualifier. Using the C++11 override keyword when overriding virtual methods helps.

Comments