使用QMediaPlayer播放自定义流

时间:2015-06-14 11:00:23

标签: c++ qt

我彻底搜索了我的问题的答案,但到目前为止还没有其他帖子有用。 我正在Qt中开发一个应用程序,我需要播放通过自定义协议接收的视频流。我发现自己试图以各种可能的方式在QMediaPlayer中提供这些数据包而没有成功。我的想法是在QBuffer中写入传入的数据包,然后从QMediaPlayer读取它们。按照我的试用:

/// VideoPlayer.h
class VideoPlayer : public QWidget
{
public slots:
    void play();
    void handlePacket(QByteArray);
    [...]

private:
    QMediaPlayer mediaPlayer;
    QBuffer      buffer;
};

/// VideoPlayer.cpp
VideoPlayer::VideoPlayer(QWidget *parent)
: QWidget(parent)
, mediaPlayer(0, (QMediaPlayer::StreamPlayback))
{
    buffer.open(QBuffer::ReadWrite);
}

void VideoPlayer::handlePacket(QByteArray packet)
{
    buffer.buffer().append(packet);
}

void VideoPlayer::play()
{
    mediaPlayer.setMedia(QMediaContent(), &buffer);
    mediaPlayer.play();
}

上面的QMediaPlayer在调用mediaPlayer.setMedia(QMediaContent(), &buffer)时播放缓冲区中的数据,但似乎忽略了新的数据包被附加到缓冲区。可能是因为我正在直接访问内部QByteArray(我检查了QIODevice :: readyRead信号是否被发出而且是)?我发现除了再次调用setMedia之外,没有办法让QMediaPlayer播放新的传入数据。有没有办法通知QMediaPlayer媒体长度已经改变了?

有更简单的方法吗?我想过编写自己的QIODevice或以某种方式将我的数据包接收器集成到Qt框架中以提供我的自定义流作为QMediaContent?

是否还有其他库或方法可以让我完成这项任务?

我正在使用Qt 5.4。 在此先感谢您的帮助。

3 个答案:

答案 0 :(得分:1)

我的答案不是真正的答案,只是分享我的经验和研究成果。这专注于流的音频部分。

我目前正在处理同样的问题。我有自定义协议,其中包含一个传入[来自网络]数据帧中的一个编码图像和一个编码音频部分。我需要分别处理图像和音频:

  • 解码图像并将原始RGB数据发送到另一个显示它的进程(lol nevermind)
  • 以任何方式播放音频部分

主要:我只能使用Qt库。这是因为libVLC [我现在正在使用这些东西]缓冲音频/视频,我没有找到任何方法来禁用它并实时播放流。我应该注意,传入的流来自摄像机,所以我需要尽可能实时地播放。

在我的快速研究期间,我找到了一种方法来播放某些东西

// init method
{
    // ...
    mPlayer = new QMediaPlayer(this, QMediaPlayer::StreamPlayback);
    mBuffer = new QBuffer(this);
    mBuffer->open(QIODevice::ReadWrite);
    // ...
}

// trying to play audio portion
void MyCoolPlayer::handleFrameAudio(const QByteArray &audioBlob)
{
    mBuffer->seek(0);
    mBuffer->write(audioBlob);
    mBuffer->seek(0);
    mPlayer->setMedia(QMediaContent(), mBuffer);
    mPlayer->play();
}

这会播放一些扭曲的声音,但至少它起到了一些作用。

此外,如果你有一些音频/视频解码器,你可以使用:

  • QPainter :: drawImage在空小部件上绘制解码的rgb图像数据
  • QAudioOutput播放解码的pcm音频数据

答案 1 :(得分:0)

我认为this是同一个问题。阅读。但是其他用户也没有在Qt中找到他需要使用VLC库的解决方案。

答案 2 :(得分:0)

在创建使用QT / QML播放视频流的POC期间,我遇到了相同的问题。对我来说,它也不适用于QBuffer。在播放过程中,我还尝试将视频文件的块从另一个线程追加到缓冲区。 QMediaPlayer仅播放第一个块并停止。我认为这不是模拟流的正确方法。

这是两种有效的方法

  1. 使用setMedia(QUrl("http://127.0.0.1:8080"));使用C ++ QMediaPlayer在QML VideoOutput中播放流。该流是由VLC媒体播放器使用HTTP到8080端口创建的。

  2. 我还成功地将VLC媒体播放器创建的流通过以下方式传递到本地文件: setMedia(QMediaContent(), &localFile);