Как играть в поток с помощью QMediaPlayer

Я настроил потоки сервера и видео, чтобы я мог подключиться к потоку с помощью ffplay, используя следующую командную строку:

ffplay rtmp://<IP>/path

Можно ли использовать QMediaPlayer QMediaContent или что-то для подключения к этому потоку?

Или, может быть, любой другой поток, который я могу создать с помощью ffserver.

используя тот же путь, что и для ffplay, в "Unsupported url scheme!"

С дальнейшими экспериментами я пробовал потоки HTTP-сервера ffserver, но это закончилось сбой Qt в MFStreamer:: doRead()

По-видимому, он должен был называть BeginRead для MFStreamer, но это не так.

Как воспроизводить видеопотоки с помощью QMediaPlayer?

Изменить: здесь мой код

videotest.cpp

#include "videotest.h"
#include <QVBoxLayout>
#include <QVideoWidget>
#include <qmediaplayer.h>
#include <QMediaContent>
#include <QNetworkAccessManager>
#include <QNetworkReply>

struct VideoTest::Private
{
    QMediaPlayer * mediaPlayer;
    QNetworkAccessManager * networkAccessManager;
    QNetworkReply * reply;
};

VideoTest::VideoTest(QWidget *parent)
    : QMainWindow(parent)
{
    d = new Private;
    d->mediaPlayer = new QMediaPlayer(this, QMediaPlayer::StreamPlayback);
    d->networkAccessManager = new QNetworkAccessManager(this);
    ui.setupUi(this);

    QVideoWidget * videoWidget = new QVideoWidget(ui.centralWidget);
    videoWidget->show();
    QPalette palette = videoWidget->palette();
    palette.setColor(QPalette::Background, QColor(0, 0, 0));
    videoWidget->setPalette(palette);

    ui.videoLayout->addWidget(videoWidget);
    d->mediaPlayer->setVideoOutput(videoWidget);

    connect(ui.playButton, SIGNAL(clicked()), d->mediaPlayer, SLOT(play()));
    connect(ui.pauseButton, SIGNAL(clicked()), d->mediaPlayer, SLOT(pause()));
    connect(ui.videoUrlEdit, SIGNAL(editingFinished()), this, SLOT(sourceChanged()));
    connect(d->mediaPlayer, SIGNAL(error()), this, SLOT(stateChanged()));
    connect(d->mediaPlayer, SIGNAL(stateChanged), this, SLOT(stateChanged()));
}

VideoTest::~VideoTest()
{
    delete d;
}

void VideoTest::sourceChanged()
{
    d->reply = d->networkAccessManager->get(QNetworkRequest(ui.videoUrlEdit->text()));
    if(d->reply)
    {
        connect(d->reply, SIGNAL(readyRead()), this, SLOT(networkRequestReady()));
    }
}

void VideoTest::stateChanged()
{
    QString text = ui.textEdit->toPlainText();
    text.append("\n").append(d->mediaPlayer->errorString()).append(" : ").append(d->mediaPlayer->mediaStatus());
    ui.textEdit->setText(text);
}

void VideoTest::networkRequestReady()
{
    d->mediaPlayer->setMedia(QMediaContent(), d->reply);
}

videotest.h

#ifndef VIDEOTEST_H
#define VIDEOTEST_H

#include <QtWidgets/QMainWindow>
#include "ui_videotest.h"

class VideoTest : public QMainWindow
{
    Q_OBJECT

public:
    VideoTest(QWidget *parent = 0);
    ~VideoTest();

public slots:
    void sourceChanged();
    void stateChanged();
    void networkRequestReady();

private:
    Ui::VideoTestClass ui;
    struct Private;
    Private * d;
};

#endif // VIDEOTEST_H

Ответ 1

Я нашел способ заставить его работать.

Я сдался на Qt. Ребята из Qt настаивали на том, что они должны работать, но не смогли создать какую-либо конфигурацию, которая работает. Они сказали, что он должен работать, если вы переходите из VLC, но я не получил его на работу. Я также пробовал потоки ffmpeg, ffserver и nginx rtmp. Я получил эти вещи, работающие с mplayer, ffplay, VLC и некоторые даже с Windows Media Player, но никогда не QMediaPlayer.

Я попытался просто указать URL-адрес для setMedia. Я попытался сделать пользовательский QIODevice для чтения данных потока и передать эти данные в QMediaPlayer, который был инициализирован StreamPlayback, но просто не удалось бы прочитать данные.

В конце концов, все, что мне нужно, это что-то, чтобы играть в поток, является QWidget и не лицензируется GPL.

Я использовал libVLC и vlc-qt обе которые работают чудесно.

Следуя этим инструкциям было легко, но вам не нужно копировать файлы заголовков из vlc-qt/windows/vlc_headers/2.2/ до vlc/sdk/include/vlc/plugins (sic). Это важно, если вы этого не сделаете, вы можете получить ошибки во время компиляции. Обратите внимание, что эти пути могут отличаться, если разные версии вашей платформы не совпадают с моими. Кроме того, это может быть необязательно, когда вы читаете это.

VideoTest.h

#ifndef VIDEOTEST_H_
#define VIDEOTEST_H_

#include <QtWidgets/QMainWindow>
#include "ui_videotest.h"

class VideoTest: public QMainWindow
{
    Q_OBJECT

    public:
        VideoTest(QWidget * p_parent = 0);
        ~VideoTest();

    public slots:
        void sourceChanged();

    private:
        struct Private;
        Private * d;
        Ui::VideoTestClass ui;
};

#endif

videotest.cpp

#include "videotest.h"

#include <vlc-qt/Common.h>
#include <vlc-qt/Instance.h>
#include <vlc-qt/Media.h>
#include <vlc-qt/MediaPlayer.h>
#include <vlc-qt/WidgetVideo.h>

struct VideoTest::Private
{
    VlcInstance * vlcInstance;
    VlcMediaPlayer * vlcMediaPlayer;
    VlcMedia * vlcMedia;
    VlcWidgetVideo * vlcVideoWidget;
};

VideoTest::VideoTest(QWidget * p_parent)
{
    d = new Private();
    ui.setupUi(this);

    d->vlcMedia = 0;
    d->vlcInstance = new VlcInstance(VlcCommon::args(), this);
    d->vlcMediaPlayer = new VlcMediaPlayer(d->vlcInstance);
    d->vlcVideoWidget = new VlcWidgetVideo(this);

    d->vlcMediaPlayer->setVideoWidget(d->vlcVideoWidget);
    d->vlcVideoWidget->setMediaPlayer(d->vlcMediaPlayer);

    ui.videoLayout->addWidget(d->vlcVideoWidget);

    connect(ui.playButton, SIGNAL(clicked()), d->vlcMediaPlayer, SLOT(play()));
    connect(ui.pauseButton, SIGNAL(clicked()), d->vlcMediaPlayer, SLOT(pause()));
    connect(ui.videoUrlEdit, SIGNAL(editingFinished()), this, SLOT(sourceChanged()));
}

VideoTest::~VideoTest()
{
    delete d->vlcInstance;
    delete d->vlcMediaPlayer;
    delete d->vlcMedia;

    delete d;
}

VideoTest::sourceChanged()
{
    QUrl url(ui.videoUrlEdit->test());
    if(url.isValid() == false)
    {
        return;
    }

    d->vlcMediaPlayer->stop();

    delete d->vlcMedia;
    d->vlcMedia = new VlcMedia(url.toString(), d->vlcInstance);
    d->vlcMediaPlayer->open(d->vlcMedia);
}

VideoTest.ui

Сделайте свой собственный, я не работаю для вас: D

Просто убедитесь, что у него есть pauseButton, playButton, videoUrlEdit (QLineEdit) и videoLayout, где будет вставлен виджет видео.

Ответ 2

Мне только что удалось воспроизвести поток в QML VideoOutput с C++ QMediaPlayer, используя setMedia(QUrl("http://127.0.0.1:8080"));
Поток был создан медиаплеером VLC с использованием HTTP к порту 8080. Мне также удалось воспроизвести поток, созданный медиаплеером VLC, в локальный файл, передав его в QMediaPlayer через setMedia(QMediaContent(), &localFile);.