QT中调用mplayaer(转)

QT中调用mplayaer(转)

技术文章(LINUx/程序编写)    2009-05-02 20:13   阅读18   评论0  
字号:    

转自:http://topkung.blog.163.com/blog/static/10526804320093114558713/

申请博友中。。。。。

如果是想在QT之外打开一个mplayer窗口就很容易:

 

const QString mplayerPath("D:/tools/mplayer/mplayer.exe");
QStringList args;
args<<"2.avi";
QProcess* myProcess=new QProcess;
myProcess->start(mplayerPath,args);
如果是想在QT的窗口里用mplayer,就像smplayer那像,这可不是件容易的事。
在网上只找到一上法文的例子:http://doc.qtfr.org/post/2007/03/21/Un-conteneur-pour-MPlayer-utilisation-de-QProcess 用QProcess实现的。可用google英文翻译后阅读。
代码在:http://doc.qtfr.org/public/2007/qt_mplayer.tar.gz
我在windows下实验成功。

也可以研究一下smplayer的源码。大体思想是(别人总结的,跟上面的例子一样):
发现mplayer的参数-wid可以把输出流重定向的指定的窗体,通过winId()得到窗体的id即可,但是我不知道视频流或者说外部显示的数据是怎么在Qwidget上呈现的。

这是那个法国人的例子程序,我加了些comment,注意要把2.avi放到release文件夹下,执行可执行程序,而不是编译后点运行:

 

 

#include <QApplication>
#include <QProcess>
#include <QVBoxLayout>
#include <QLayoutItem>
#include <QWidget>
#include <QPaintEvent>
#include <QPainter>
#include <QColor>
#include <QRect>
#include <QLinearGradient>
#include <QSizePolicy>
#include <QPushButton>
#include <QTextEdit>
#include <QSlider>
#include <QCloseEvent>
#include <QTimer>

#ifdef Q_OS_WIN32
const QString mplayerPath("D:/tools/mplayer/mplayer.exe");
#else
const QString mplayerPath("/usr/bin/mplayer");
#endif
const QString movieFile("2.avi");

class PlayerWidget: public QWidget
...{
    Q_OBJECT

private:
    QPushButton *controller;
    QWidget *renderTarget;
    QProcess *mplayerProcess; //main thing
    bool isPlaying;
    QSlider *timeLine;
    QTimer *poller;
    QTextEdit *log;
   
public:
    PlayerWidget(QWidget *parent =0)
        :QWidget(parent), isPlaying(false)
    ...{
        controller = new QPushButton("Play");
       
        renderTarget = new QWidget(this);
        renderTarget->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));
        renderTarget->setAttribute(Qt::WA_OpaquePaintEvent );
        renderTarget->setMinimumSize(500, 500);
       
        timeLine = new QSlider(Qt::Horizontal);

        log = new QTextEdit;
        log->setReadOnly(true);

        QVBoxLayout *layout = new QVBoxLayout;
        layout->addWidget(controller);
        layout->addWidget(renderTarget);
        layout->addWidget(timeLine);
        layout->addWidget(log);
        setLayout(layout);

        mplayerProcess = new QProcess(this);

        poller = new QTimer(this);

        connect(controller, SIGNAL(clicked()), this, SLOT(switchPlayState())); //switchPlayState在后面
        connect(mplayerProcess, SIGNAL(readyReadStandardOutput()),
            this, SLOT(catchOutput()));  //catchOutput在后面
        connect(mplayerProcess, SIGNAL(finished(int, QProcess::ExitStatus)),
            this, SLOT(mplayerEnded(int, QProcess::ExitStatus))); //mplayerEnded在后面
        connect(poller, SIGNAL(timeout()), this, SLOT(pollCurrentTime())); //pollCurrentTime在后面
        connect(timeLine, SIGNAL(sliderMoved(int)), this, SLOT(timeLineChanged(int))); //timeLineChanged在后面
    }

protected:
    virtual void closeEvent(QCloseEvent *e)
    ...{
        stopMPlayer();
        e->accept();
    }

private:
    bool startMPlayer()
    ...{
        if(isPlaying)
            return true;

        QStringList args; //运行mplayer需要的参数
       
        // On demande ? utiliser mplayer comme backend
        // are asked to use mplayer as backend
        args << "-slave";
        // Et on veut ne pas avoir trop de chose ? parser :)
        //And we want to not having too many things to parser:)
        args << "-quiet";
#ifdef Q_WS_WIN
        // reinterpret_cast<qlonglong> obligatoire, winId() ne se laissant pas convertir gentiment ;)
        //reinterpret_cast <qlonglong> mandatory winId () not allowing convert nicely;)
        args << "-wid" << QString::number(reinterpret_cast<qlonglong>(renderTarget->winId()));
        args << "-vo" << "directx:noaccel";
#else
        // Sur linux, aucun driver n''a ?t? n?cessaire et pas de manip pour Wid :)
        //On linux, no driver has been necessary and no manip for Wid:)
        args << "-wid" << QString::number(renderTarget->winId());

        log->append("Video output driver may not be necessary for your platform.
                    Check: http://www.mplayerhq.hu/DOCS/man/en/mplayer.1.html
                    at the VIDEO OUTPUT DRIVERS section.");
#endif
       
        args << movieFile;

        // On parse la stdout et stderr au m?me endroit, donc on demande ? "fusionnner" les 2 flux
        //parse the stdout and stderr in the same place, so we are asking "fusionnner"
        mplayerProcess->setProcessChannelMode(QProcess::MergedChannels);
        mplayerProcess->start(mplayerPath, args); //开始运行这个进程
        if(!mplayerProcess->waitForStarted(100))
        ...{
            qDebug("allez, cherche le bug :o");
            return false;
        }

        // On r?cup?re les infos de base
        //retrieve basic information
        mplayerProcess->write("get_video_resolution ");
        mplayerProcess->write("get_time_length ");

        poller->start(1000);

        isPlaying = true;

        return true;
    }

    bool stopMPlayer()
    ...{
        if(!isPlaying)
            return true;

        mplayerProcess->write("quit ");
        if(!mplayerProcess->waitForFinished(100))
        ...{
            qDebug("ZOMG, ?a plante :(");
            return false;
        }

        return true;
    }

private slots:
   
    //响应readyReadStandardOutput消息
    void catchOutput()
    ...{
        while(mplayerProcess->canReadLine())
        ...{
            QByteArray buffer(mplayerProcess->readLine());
            log->append(QString(buffer));
           
            // On v?rifie si on a eu des r?ponses
            //It checks if we had answers
            // r?ponse ? get_video_resolution : ANS_VIDEO_RESOLUTION=''<width> x <height>''
            //response to get_video_resolution: ANS_VIDEO_RESOLUTION
            if(buffer.startsWith("ANS_VIDEO_RESOLUTION"))
            ...{
                buffer.remove(0, 21); // vire ANS_VIDEO_RESOLUTION=
                buffer.replace(QByteArray("''"), QByteArray(""));
                buffer.replace(QByteArray(" "), QByteArray(""));
                buffer.replace(QByteArray(" "), QByteArray(""));
                buffer.replace(QByteArray(" "), QByteArray(""));
                int sepIndex = buffer.indexOf(''x'');
                int resX = buffer.left(sepIndex).toInt();
                int resY = buffer.mid(sepIndex+1).toInt();
                renderTarget->setMinimumSize(resX, resY);
            }
            // r?ponse ? get_time_length : ANS_LENGTH=xx.yy
            //response to get_time_length: ANS_LENGTH =
            else if(buffer.startsWith("ANS_LENGTH"))
            ...{
                buffer.remove(0, 11); // vire ANS_LENGTH=
                buffer.replace(QByteArray("''"), QByteArray(""));
                buffer.replace(QByteArray(" "), QByteArray(""));
                buffer.replace(QByteArray(" "), QByteArray(""));
                buffer.replace(QByteArray(" "), QByteArray(""));
                float maxTime = buffer.toFloat();
                timeLine->setMaximum(static_cast<int>(maxTime+1));
            }
            // r?ponse ? get_time_pos : ANS_TIME_POSITION=xx.y
            //response to get_time_pos: ANS_TIME_POSITION = 2.4
            else if(buffer.startsWith("ANS_TIME_POSITION"))
            ...{
                buffer.remove(0, 18); // vire ANS_TIME_POSITION=
                buffer.replace(QByteArray("''"), QByteArray(""));
                buffer.replace(QByteArray(" "), QByteArray(""));
                buffer.replace(QByteArray(" "), QByteArray(""));
                buffer.replace(QByteArray(" "), QByteArray(""));
                float currTime = buffer.toFloat();
                timeLine->setValue(static_cast<int>(currTime+1));
            }
            //qApp->processEvents();
        }
    }

    void pollCurrentTime()
    ...{
        mplayerProcess->write("get_time_pos ");
    }

    // Dirige la timeline
    //Directs the timeline
    void timeLineChanged(int pos)
    ...{
        mplayerProcess->write(QString("seek " + QString::number(pos) + " 2 ").toUtf8());
    }

    // Play/stop
    void switchPlayState()
    ...{
        if(!isPlaying)
        ...{
            if(!startMPlayer())
                return;

            log->clear();
            controller->setText("Stop");
            isPlaying = true;
        }
        else
        ...{
            if(!stopMPlayer())
                return;

            poller->stop();
            log->clear();
            controller->setText("Play");
            isPlaying = false;
        }
    }

    void mplayerEnded(int exitCode, QProcess::ExitStatus exitStatus)
    ...{
        isPlaying = false;
        controller->setText("Play");
        poller->stop();
    }


};

int main(int argc, char **argv)
...{
    QApplication app(argc, argv);

    PlayerWidget *pw = new PlayerWidget;
    pw->show();

    return app.exec();
}

#include "main.moc" //I don''t understand this.

文章出处:http://www.diybl.com/course/4_webprogram/asp.net/netjs/200847/108687.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值