在前面几篇文章中详细的介绍了如何利用QT自身提供的Phonon模块来进行音视频的播放和控制,这种方式是QT内部提供的音视频解码器,所以所支持的文件格式不多,而且对音视频的控制方式也是非常有限,所以在这里还是采用Mplayer作后台,QT作前端界面的方式来构建我们的播放器。
1.MPlayer 的特殊控制模式
- mkfifo /tmp/media // 建立管道文件
- cat xxx.mpeg > /tmp/media & // 把媒体文件数据写入管道一端
- mplayer /tmp/media –cache 3000 // mplayer在缓充3M数据后开始播放
注意必须建立缓充,以支持读取数据时的小范围索引
本例里没有用这个功能,但是很多LINUX的网络播放器也是用这个方法来这现的.有兴趣可以参考一下gtk-sopcast(http://code.google.com/p/gsopcast/)这个开源项目,这个软件相信很多人用它的WINDOWS版本看过球.
- mkfifo /tmp/cmd
- mplayer -slave -quiet -input file=/tmp/cmd xxx.mpeg &
- 使用/tmp/cmd做为命令管道
- echo "pause" > /tmp/cmd
- 暂停播放
- seek Float [Integer] 跳到指定时间播放
- speed_incr Float 快进
- speed_set Float 设置指定时间
- quit [Integer] 退出
- pause 暂停,再一次表示重新播放
- get_percent_pos 取得百分比表示的进度
- get_time_pos 取得时间进度
QT的控件都是从QWidget继承下来,因此它本身也有wid,这样只要用 QWidget::winID() 取出WID,即可实现在指定窗口播放视频的功能。
QT是用QProcess(进程类)来执行。创建一个进程后。用start方法来执行.
//执行不带参数的外部命令。
void start ( const QString & program, OpenMode mode = ReadWrite )
//执行带参数
void start ( const QString & program, const QStringList & arguments, OpenMode mode = ReadWrite )
其中arguments就是参数列表。QStringList重定向了 <<,增加参数用这个重载的操作符。
arg << "-wid"<< "0x320001f" <<" -queit" ;
readLine/read来读取信息用于分析。
IO重定向使用signal readyReadStandardOutput。
connect(mplayerProcess, SIGNAL(readyReadStandardOutput()),
this, SLOT(catchOutput()));

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





#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>
const QString mplayerPath(" C:/Program Files/MPlayer for Windows/mplayer/mplayer.exe");//在windows上来运行Mplayer必须先要下载Mplayer For Windows安装到机器上,然后找到安装包中的mplayer.exe,我自己的机器上对应的路径为: C:/Program Files/MPlayer for Windows/mplayer/mplayer.exe//
#else
const QString mplayerPath("/usr/bin/mplayer");//linux下的Mplayer的路径
#endif
const QString movieFile("2.avi");//最好还是通过QFileDialog来选择我们需要播放的文件路径,后面会讲到
...{
Q_OBJECT
QPushButton *controller;
QWidget *renderTarget;//利用一个QWidget对象来播放视频
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->setReadOnly(true);
layout->addWidget(controller);
layout->addWidget(renderTarget);
layout->addWidget(timeLine);
layout->addWidget(log);
setLayout(layout);
connect(mplayerProcess, SIGNAL(readyReadStandardOutput()),
this, SLOT(catchOutput())); //当进程的标准输出上有数据可以读时,QProcess将会发出这个消息,这个消息也就是当我们给Mplayer发送命令后,Mplayer作出相应,将视频信息输出到标准输出上来,这样我们就可以在 catchOutput函数中来解析
this, SLOT(mplayerEnded(int, QProcess::ExitStatus))); //当进程退出时会发出这个信号,包括了退出时的退出码和退出状态
connect(poller, SIGNAL(timeout()), this, SLOT(pollCurrentTime())); //每隔1S中定时器poller就会发出timeout信号,在响应函数中我们继续给Mplayer发送获取视频当前时间的命令get_time_pos
connect(timeLine, SIGNAL(sliderMoved(int)), this, SLOT(timeLineChanged(int))); //当我们拖动滑动条时,视频也应该跟着我们一起播放
}
virtual void closeEvent(QCloseEvent *e)
{
stopMPlayer();
e->accept();
}
bool startMPlayer()
{
if(isPlaying)
return true;
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());
Check: http://www.mplayerhq.hu/DOCS/man/en/mplayer.1.html
at the VIDEO OUTPUT DRIVERS section.");
#endif
args << movieFile;
//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;
}
//retrieve basic information
mplayerProcess->write("get_video_resolution ");
mplayerProcess->write("get_time_length ");
}
{
if(!isPlaying)