如何使用QMediaPlayer播放流 [英] How do i play a stream with QMediaPlayer

查看:3527
本文介绍了如何使用QMediaPlayer播放流的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我设置了一个服务器和视频流,以便我可以使用以下命令行使用ffplay连接到流:

  ffplay rtmp://< IP> / path 

可以使用QMediaPlayer QMediaContent



或者可以使用ffserver创建其他类型的流。



使用与ffplay相同的路径导致不支持的URL方案!



进一步的实验我试过ffserver http服务器流,但结束与Qt崩溃在MFStreamer: :doRead()



显然,它应该为MFStreamer调用BeginRead,但它没有。





videotest.cpp

strong>

  #includevideotest.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(\\\
)。append(d-> mediaPlayer-> errorString())append(:).append(d-> mediaPlayer-> mediaStatus );
ui.textEdit-> setText(text);
}

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

videotest.h
$ b

  #ifndef VIDEOTEST_H 
#define VIDEOTEST_H

#include< QtWidgets / QMainWindow>
#includeui_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


解决方案

我找到了一种使它工作的方法。



我放弃了Qt。 Qt的家伙坚持认为它应该工作,但是无法生成任何有效的配置。他们说,它应该工作,如果你从VLC流,但我没有得到它的工作。我也试过ffmpeg,ffserver和nginx rtmp流。我得到这些东西使用mplayer,ffplay,VLC和一些甚至与Windows Media Player,但从来没有QMediaPlayer。



我试图把URL的setMedia。
我试图做一个自定义的QIODevice读取流数据,并将该数据给QMediaPlayer用StreamPlayback初始化,但它只是不能成功读取数据。



最后,我需要的是播放流的东西,是一个QWidget,不是GPL许可。



我使用 libVLC

这些说明很容易,但你需要记住复制头文件从 vlc-qt / windows / vlc_headers / 2.2 / 更改为 vlc / sdk / include / vlc / plugins (sic)。这很重要,如果你不这样做,你可能会在编译期间得到错误。请注意,如果您有不同版本的平台与我不匹配,这些路径可能不同。



VideoTest.h

  #ifndef VIDEOTEST_H_ 
#define VIDEOTEST_H_

#include< QtWidgets / QMainWindow>
#includeui_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

  #includevideotest.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的视频小部件将被插入。


I have set up a server and video streaming so that I can connect to the stream with ffplay using the following command line:

ffplay rtmp://<IP>/path

Is it possible to use QMediaPlayer QMediaContent or something to connect to this stream?

Or maybe any other kind of stream I can create with ffserver.

using the same path as with ffplay results in "Unsupported url scheme!"

With further experiments i have tried ffserver http server streaming, but that ended with Qt crashing in MFStreamer::doRead()

Apparently it should have called BeginRead for MFStreamer but it didn't.

How do i play video streams with QMediaPlayer?

Edit: here's my code

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

解决方案

I found a way to make it work.

I gave up on Qt. The guys at Qt were insistent that it should work, but were unable to produce any configuration that works. They said that it should work if you stream from VLC, but I didn't get it to work. I also tried ffmpeg, ffserver and nginx rtmp streaming. I got these things working with mplayer, ffplay, VLC and some even with Windows Media Player, but never QMediaPlayer.

I tried to just give the URL to setMedia. I tried to make a custom QIODevice to read the stream data and give that data to QMediaPlayer which was initialized with StreamPlayback, but it just would not succeed in reading the data.

In the end, all I needed was something to play a stream, is a QWidget and isn't GPL licensed.

I used libVLC and vlc-qt both of which work wonderfully.

Following these instructions was easy, but you need to remember to copy the header files from vlc-qt/windows/vlc_headers/2.2/ to vlc/sdk/include/vlc/plugins (sic). This is important, if you don't do this you might get errors during compilation. Note that these paths might be different if you have different versions of your platform doesn't match mine. Also, it might not be necessary when you read this.

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

Make your own, I don't work for you :D

Just make sure that it has pauseButton, playButton, videoUrlEdit(QLineEdit) and videoLayout where the video widget will be inserted.

这篇关于如何使用QMediaPlayer播放流的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆