Qt 6.2: QMediaPlayer & QByteArray

Viewed 478

Good day. Has anyone tried QMediaPlayer in Qt 6.2 already? I'm trying this code, but Media Status always remains as "NoMedia" and no any sound :). Full test project: https://github.com/avttrue/MediaPlayerTest

#include "mainwindow.h"

#include <QDebug>
#include <QBuffer>
#include <QFile>
#include <QAudioOutput>
#include <QMediaPlayer>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QFile file("../test/Bankrobber.mp3");
    if(!file.open(QIODevice::ReadOnly))
        qDebug() << "File not opened";
    qDebug() << "File size:" << file.size(); // File size: 11181085

    QByteArray ba = file.readAll();
    qDebug() << "ByteArray size:" << ba.size(); // ByteArray size: 11181085

    QBuffer* buffer = new QBuffer(this);
    buffer->setData(ba);
    if(!buffer->open(QIODevice::ReadOnly))
        qDebug() << "Buffer not opened";
    qDebug() << "Buffer size:" << buffer->size(); // Buffer size: 11181085

    buffer->seek(qint64(0));

    auto audioOutput = new QAudioOutput(this);
    auto player = new QMediaPlayer(this);
    player->setAudioOutput(audioOutput);
    audioOutput->setVolume(50);
    player->setSourceDevice(buffer);
    qDebug() << "Device:" << player->sourceDevice(); // Device: QBuffer(0x563180493020)

    QObject::connect(player, &QMediaPlayer::mediaStatusChanged,
                     [=](QMediaPlayer::MediaStatus status)
    { qDebug() << "MediaStatus:" << player->mediaStatus() << "|" << status; });

    QObject::connect(player, &QMediaPlayer::errorOccurred,
                     [=](QMediaPlayer::Error error)
    { qDebug() << "Error:" << player->errorString() << "|" << error; });

    QObject::connect(player, &QMediaPlayer::playbackStateChanged,
                     [=](QMediaPlayer::PlaybackState state)
    { qDebug() << "PlaybackState:" << player->playbackState() << "|" << state; });

    player->play();
    qDebug() << "MediaStatus:" << player->mediaStatus(); // MediaStatus: QMediaPlayer::NoMedia
} 

3 Answers

As the docs points out:

void QMediaPlayer::setSourceDevice(QIODevice *device, const QUrl &sourceUrl = QUrl())

Sets the current source device.

The media data will be read from device. The sourceUrl can be provided to resolve additional information about the media, mime type etc. The device must be open and readable.

For macOS the device should also be seek-able.

Note: This function returns immediately after recording the specified source of the media. It does not wait for the media to finish loading and does not check for errors. Listen for the mediaStatusChanged() and error() signals to be notified when the media is loaded, and if an error occurs during loading.

(emphasis mine)

QMediaPlayer does not know how to deduce the file format so it does not load it. The solution is to point out that it is an mp3:

player->setSourceDevice(buffer, QUrl("foo.mp3"));

The function setSourceDevice() you are using isn't doing what you think? Maybe you wanted setSource() instead?

Qt has great documentation: https://doc.qt.io/qt-6/qmediaplayer.html#setSourceDevice

Even good examples:

player = new QMediaPlayer;
audioOutput = new QAudioOutput;
player->setAudioOutput(audioOutput);
connect(player, SIGNAL(positionChanged(qint64)), this, SLOT(positionChanged(qint64)));
player->setSource(QUrl::fromLocalFile("/Users/me/Music/coolsong.mp3"));
audioOutput->setVolume(50);
player->play();

Ref. https://doc.qt.io/qt-6/qmediaplayer.html#details

May be this is as variant, but i think it not good:

QTemporaryFile tfile;
if (!tfile.open())
     qDebug() << "TemporaryFile not opened";
 else
 {
     qDebug() << "TemporaryFile writed:" << tfile.write(ba);
     if(tfile.size() != ba.size())
         qDebug() << "TemporaryFile not complited";
     else
         player->setSource(QUrl::fromLocalFile(tfile.fileName()));
 }
Related