【问题标题】:Playback custom stream with QMediaPlayer使用 QMediaPlayer 播放自定义流
【发布时间】:2015-08-29 23:15:00
【问题描述】:

我彻底搜索以找到问题的答案,但到目前为止没有其他帖子有帮助。 我正在 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。 提前感谢您的帮助。

【问题讨论】:

  • 您能否提供有关正在播放的媒体类型的更多信息(容器/原始 RTP 或 UDP/...)。我的猜测是,由于各种格式都有数据包边界,也许您正在跳过一些告诉媒体播放器新数据可用的数据?无论如何,继承 QIODevice 听起来是个好方法。

标签: c++ qt


【解决方案1】:

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

这里有两种可行的方法

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

  2. 我还成功地将 VLC 媒体播放器创建的流播放到本地文件,方法是将其传递给 QMediaPlayer setMedia(QMediaContent(), &localFile);.

【讨论】:

    【解决方案2】:

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

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

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

    主要:我只能使用 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 音频数据

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 2015-08-11
        • 1970-01-01
        • 2015-07-12
        • 1970-01-01
        • 2017-05-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多