Qt 使用 Phonon 这个多媒体框架来提供播放常见多媒体格式文件的功能,其中媒体文件可以是本地文件或者通过 QURL 指向的网络流文件。
整体来说,Phonon的架构只需要记住以下的三东西:
可从下图看出彼此的关系
上图是一个有声视频 avi 文件的播放机制图。媒体源 DieHard.avi 由 MediaObject 进行管理,而MediaObject 与两个 Sink 通过 Path 连接,一个是 Audio Sink ,管理着声音播放,另一个是 Video Sink ,管理着视频播放。最终都是由 Sink 将媒体数据传送给物理设备。
所以整个播放影音的流程就是首先由media object开始播放,接著把媒体串流经由path送至sink,sink会经由音效卡等装置重新播放(play back)影音。
【内部机制】
Phonon 有三个基本概念:媒体对象、接收端和路径。一个媒体对象管理一个媒体源,比如一个音乐文件;它提供了简单的播放控制,比如开始、停止和暂停播放。一个接收端输出来自 Phonon 的媒体,比如,通过提供录像到一个窗口,或者通过提供声音到一个声卡上。路径是用来连接 Phonon 对象的,比如,一个媒体对象和一个接收端,从而构成了 Phonon 中的 media graph ,如下:
图1:
上图中,音乐的播放是由 media object 启动和管理的,并且 media object 把媒体流发送给通过路径( path)连接到它的接收端( sink ),继而接收端( sink )通过声卡播放媒体流。
而与其他Qt应用程式一样,若有使用到Phonon函式库的应用程式在build的时候都需要额外设定使用Phonon模组,必须要在qmaek project file(即.pro)中加入:QT += phonon
使用
在此部分将会开始介绍如何使用Phonon这套函式库,并且会列出一些小范例来demo,首先就先来介绍几个简单好用的类别。
VideoPlayer Class
Phonon有提供很多类别可供使用,其中最简单的,莫过於VideoPlayer这个类别了。
VideoPlayer widget如它的名字一样,就是用来播放video,而且使用起来相当简易,而且功能也不会缺少,包括播放、暂停与停止。
而一开始早先提到的MediaObject等类别与VideoPlayer在使用上有什么差异呢?如果不需要更复杂的功能,例如建立一个media graph,你只需要能够播放影音档案的话,其实使用VideoPlayer类别即可达到你的要求。
而另外值得一提的就是,VideoPlayer大部分函式都是非同步,所以载入media source并不会马上播放多媒体档案,只有在呼叫函式play( )之後才会播放。
要怎么使用这个类别呢? 其实相当简单,下面就是程式码片段:VideoPlayer *player = new VideoPlayer(Phonon::VideoCategory, parentWidget); player->play(url);
在实体化VideoPlayer类别物件时,可以在constructor就载入多媒体种类与要放在哪个widget中(即为 parentWidget),而media source可以利用函式load()来载入或是在play()时载入,而载入方式可直接从档案或是从网路位址。
以下就是一个简单的影音播放功能小程式:
#include
#include
#include
#include
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget *widget = new QWidget;
widget->setWindowTitle("Video Player");
widget->resize(400,400);
Phonon::VideoPlayer *player = new Phonon::VideoPlayer(Phonon::VideoCategory, widget);
player->load(Phonon::MediaSource("../Puppet.mpg"));
player->play();
widget->show();
return app.exec();
}
MediaObject Class
MediaObject类别主要提供一个能够处理媒体播放的介面。
MediaObject可说是处理多媒体档案最基本的一部份,它接受并管理来自於MediaSource的媒体档案。而媒体播放、暂停与停止都是由它来控制;而在此之前,media物件必须要与output node连接,如早先所讲的,这个nodes主要将媒体输出至底层的硬体,例如音效卡或显示卡等,而所需要的output node则是根据多媒体的内容而所不同,目前Phonon有两种output node;
如果MediaSource包含声音与影像的话,这两种node都必须要连接至media物件。
就这个类别来说,有几个函式是你必须要知道的,分别是
QUrl url("); // 指定URL 这里我是乱写的URL
mediaObject->setCurrentSource(url);
以下为一个简单的程式片段,说明如何使用:
Phonon::MediaObject *mediaObject = new Phonon::MediaObject(this);
Phonon::VideoWidget *videoWidget = new Phonon::VideoWidget(this);
Phonon::createPath(mediaObject, videoWidget);
Phonon::AudioOutput *audioOutput =new Phonon::AudioOutput(Phonon::VideoCategory, this);
Phonon::createPath(mediaObject, audioOutput);
mediaObject->play();
Phonon::createPath()
这是相当重要的一个函数,主要用於建立一个Path,连接两个MediaNodes,就是source与sink。
其实它的主要用途是在更进阶的部分,就是在使用到media graph,不过如果只是利用Phonon来播放多媒体影音档,其实只要记得它是用来连接source与输出装置即可。
AudioOutput Class
AudioOutput类别主要是用来把多媒体的声音送到声音输出装置。所以它能够经由类似喇叭等输出装置来播放声音,稍早有提过,多媒体资料的来源必须要经过Phonon::createPath()由MediaObject连接。
Phonon::MediaObject *mediaObject = new Phonon::MediaObject(this);
mediaObject->setCurrentSource(Phonon::MediaSource("E:/hello.mp3"));
Phonon::AudioOutput *audioOutput =new Phonon::AudioOutput(Phonon::MusicCategory, this);
Phonon::Path path = Phonon::createPath(mediaObject, audioOutput);
VideoWidget Class
VideoWidget类别提供能够显示出影片的widget,即视频的显示主窗口,没有VideoWidget则可能造成有声音无图像的情况。
VideoWidget类别会在QWidget上播放多媒体串流的影像,跟AudioOutput一样,必须使用 Phonon::createPath()来与MediaObject连接。你可以利用一些函数来控制在QWidget中的VideoWidget显示的大小,你可以利用setAspectRatio()或setScaleMode()来控制,而它们接收的参数可以到网站上察看,使用方式如下(预设是使用aspect ratio):
videowidget->setAspectRatio(Phonon::VideoWidget::AspectRatioAuto);
videowidget->setScaleMode(Phonon::VideoWidget::ScaleAndCrop);
当然也有提供函式让影片进入或退出全萤幕模式。以下为一个简短的程式码范例:
MediaObject *mediaObject = new MediaObject(parent);
VideoWidget *vWidget = new VideoWidget(parent);Phonon::createPath(mediaObeject, vWidget);
SeekSlider Class
SeekSlider类别提供一个可滑动的slider来设定多媒体串流播放的位置,即播放进度条,所以它会连接到MediaObject,并控制串流目前的位置。
以下是一个使用的范例:
Phonon::MediaObject *mediaObject = new Phonon::MediaObject;
Phonon::AudioOutput *audioOutput = new Phonon::AudioOutput;
Phonon::createPath(mediaObject, audioOutput);
mediaObject->setCurrentSource(QString("E:/hello.avi"));
Phonon::SeekSlider *seekSlider = new Phonon::SeekSlider;
seekSlider->setMediaObject(mediaObject); // 与媒体对象mediaObject进行关联
seekSlider->show();
mediaObject->play();
VolumeSlider Class
VolumeSlider widget提供可以控制声音装置音量的widget。
用法其实与上面的SeekSlider类似,使用范例如下:
Phonon::AudioOutput *audioOutput = new Phonon::AudioOutput(Phonon::MusicCategory);
Phonon::createPath(mediaObject, audioOutput);
Phonon::VolumeSlider *volumeSlider = new Phonon::VolumeSlider;
volumeSlider->setAudioOutput(audioOutput); // 与音频输出设备进行关联
简单范例
再看过上面的一些类别介绍之後,其实就可以显一个简单的媒体播放器了,代码如下:
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget *mainWidget = new QWidget;
mainWidget->setWindowTitle("Media Player");
mainWidget->resize(640,480);
Phonon::MediaObject *mediaObject= new Phonon::MediaObject; // 媒体对象
mediaObject->setCurrentSource(Phonon::MediaSource("E:/hello.avi"));
Phonon::VideoWidget *videoWidget = new Phonon::VideoWidget; // 影像窗口
Phonon::createPath(mediaObject, videoWidget);
videoWidget->setAspectRatio(Phonon::VideoWidget::AspectRatioAuto);
Phonon::AudioOutput *audioOutput = new Phonon::AudioOutput(Phonon::VideoCategory); // 音频输出
Phonon::createPath(mediaObject, audioOutput);
QLabel *label = new QLabel("Volume: ");
Phonon::VolumeSlider *volumeSlider = new Phonon::VolumeSlider;
volumeSlider->setAudioOutput(audioOutput);
volumeSlider->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
Phonon::SeekSlider *seekSlider = new Phonon::SeekSlider;
seekSlider->setMediaObject(mediaObject);
// 布局管理 将上述所有控件添加到主窗口中 即mainWidget
QHBoxLayout *hLayout = new QHBoxLayout;
hLayout->addWidget(label);
hLayout->addWidget(volumeSlider);
hLayout->addStretch();
// 垂直布局
QVBoxLayout *vLayout = new QVBoxLayout;
vLayout->addWidget(videoWidget);
vLayout->addWidget(seekSlider);
vLayout->addLayout(hLayout);
mainWidget->setLayout(vLayout);
mainWidget->show();
mediaObject->play(); // 播放
return app.exec();
}
上面的程式码就完成了一个简易的多媒体播放器
PS:
用“添加”按钮来制定媒体源,即要播放的文件,添加音乐文件的槽的代码如下:
void mediaPlayer::addFiles(){
QListWidget *listWidget = new QListWidget(this); // 暂且写在这里 声明为类成员变量较好
QStringList files = QFileDialog::getOpenFileNames(this,tr("Get video files"),
QDesktopServices::storageLocation(QDesktopServices::VideoLocation),
tr("Movie (*.avi *.wmv *.mp4 *.mkv *.rm *.rmvb *.flv *.3gp)"));
int index = sourceList.size(); // 类的私有成员变量 sourcesList 存储多媒体资源信息
QString file;
foreach(file, fileNames){
listWidget->addItem(file); // QListWidget来显示音乐列表
sourceList.append(file); // sourceList声明在类头文件里 即QList sourceList
}
if(!sources.isEmpty()){ // 资源不为空时 设置为当前媒体源 然后播放即可
metaInfomationResolver->setCurrentSource(sourcesList.at(index)); // 指向当前资源的指针,与mediaObject的声明是一样的,在这里没有写出声明而已
mediaObject->setCurrentSource(metaInfomationResolver->currentSource());
mediaObject->play(); // 播放
}
}
转载需声明出处!!!
整体来说,Phonon的架构只需要记住以下的三东西:
- media objectPhonon的基础,用於管理多媒体来源。来源可能是影音档等,而能够提供基本的播放控制,例如开始、暂停或结束。而提供多媒体资料给media object的则为media source,在给media object之前通常是raw data,再由media object进行转换。
- sinks输出多媒体,例如在widget上播放影片或是输出至音效卡(播放音乐)。通常sink是一个播放的装置(例如音效卡等)。而sink只接受media object来的资料,由media object控制播放;而由sink来处理这些多媒体
- paths用来连接Phonon的物件,意即media object与sink之间的连接。
上图是一个有声视频 avi 文件的播放机制图。媒体源 DieHard.avi 由 MediaObject 进行管理,而MediaObject 与两个 Sink 通过 Path 连接,一个是 Audio Sink ,管理着声音播放,另一个是 Video Sink ,管理着视频播放。最终都是由 Sink 将媒体数据传送给物理设备。
所以整个播放影音的流程就是首先由media object开始播放,接著把媒体串流经由path送至sink,sink会经由音效卡等装置重新播放(play back)影音。
【内部机制】
Phonon 有三个基本概念:媒体对象、接收端和路径。一个媒体对象管理一个媒体源,比如一个音乐文件;它提供了简单的播放控制,比如开始、停止和暂停播放。一个接收端输出来自 Phonon 的媒体,比如,通过提供录像到一个窗口,或者通过提供声音到一个声卡上。路径是用来连接 Phonon 对象的,比如,一个媒体对象和一个接收端,从而构成了 Phonon 中的 media graph ,如下:
图1:
上图中,音乐的播放是由 media object 启动和管理的,并且 media object 把媒体流发送给通过路径( path)连接到它的接收端( sink ),继而接收端( sink )通过声卡播放媒体流。
而与其他Qt应用程式一样,若有使用到Phonon函式库的应用程式在build的时候都需要额外设定使用Phonon模组,必须要在qmaek project file(即.pro)中加入:QT += phonon
使用
在此部分将会开始介绍如何使用Phonon这套函式库,并且会列出一些小范例来demo,首先就先来介绍几个简单好用的类别。
VideoPlayer Class
Phonon有提供很多类别可供使用,其中最简单的,莫过於VideoPlayer这个类别了。
VideoPlayer widget如它的名字一样,就是用来播放video,而且使用起来相当简易,而且功能也不会缺少,包括播放、暂停与停止。
而一开始早先提到的MediaObject等类别与VideoPlayer在使用上有什么差异呢?如果不需要更复杂的功能,例如建立一个media graph,你只需要能够播放影音档案的话,其实使用VideoPlayer类别即可达到你的要求。
而另外值得一提的就是,VideoPlayer大部分函式都是非同步,所以载入media source并不会马上播放多媒体档案,只有在呼叫函式play( )之後才会播放。
要怎么使用这个类别呢? 其实相当简单,下面就是程式码片段:VideoPlayer *player = new VideoPlayer(Phonon::VideoCategory, parentWidget); player->play(url);
在实体化VideoPlayer类别物件时,可以在constructor就载入多媒体种类与要放在哪个widget中(即为 parentWidget),而media source可以利用函式load()来载入或是在play()时载入,而载入方式可直接从档案或是从网路位址。
以下就是一个简单的影音播放功能小程式:
#include
#include
#include
#include
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget *widget = new QWidget;
widget->setWindowTitle("Video Player");
widget->resize(400,400);
Phonon::VideoPlayer *player = new Phonon::VideoPlayer(Phonon::VideoCategory, widget);
player->load(Phonon::MediaSource("../Puppet.mpg"));
player->play();
widget->show();
return app.exec();
}
MediaObject Class
MediaObject类别主要提供一个能够处理媒体播放的介面。
MediaObject可说是处理多媒体档案最基本的一部份,它接受并管理来自於MediaSource的媒体档案。而媒体播放、暂停与停止都是由它来控制;而在此之前,media物件必须要与output node连接,如早先所讲的,这个nodes主要将媒体输出至底层的硬体,例如音效卡或显示卡等,而所需要的output node则是根据多媒体的内容而所不同,目前Phonon有两种output node;
- AudioOutput-声音播放
- VideoWidget-影像播放
就这个类别来说,有几个函式是你必须要知道的,分别是
- setCurrentSource():设定MediaObject的多媒体来源,而来源可以是网路上的影音档(利用QUrl来存取)或是本机档案(利用QString),使用上相当简单:
mediaObject->setCurrentSource(url);
- play():开始播放多媒体资料
- pause():暂停播放
- stop():停止播放
Phonon::MediaObject *mediaObject = new Phonon::MediaObject(this);
Phonon::VideoWidget *videoWidget = new Phonon::VideoWidget(this);
Phonon::createPath(mediaObject, videoWidget);
Phonon::AudioOutput *audioOutput =new Phonon::AudioOutput(Phonon::VideoCategory, this);
Phonon::createPath(mediaObject, audioOutput);
mediaObject->play();
Phonon::createPath()
这是相当重要的一个函数,主要用於建立一个Path,连接两个MediaNodes,就是source与sink。
其实它的主要用途是在更进阶的部分,就是在使用到media graph,不过如果只是利用Phonon来播放多媒体影音档,其实只要记得它是用来连接source与输出装置即可。
AudioOutput Class
AudioOutput类别主要是用来把多媒体的声音送到声音输出装置。所以它能够经由类似喇叭等输出装置来播放声音,稍早有提过,多媒体资料的来源必须要经过Phonon::createPath()由MediaObject连接。
Phonon::MediaObject *mediaObject = new Phonon::MediaObject(this);
mediaObject->setCurrentSource(Phonon::MediaSource("E:/hello.mp3"));
Phonon::AudioOutput *audioOutput =new Phonon::AudioOutput(Phonon::MusicCategory, this);
Phonon::Path path = Phonon::createPath(mediaObject, audioOutput);
VideoWidget Class
VideoWidget类别提供能够显示出影片的widget,即视频的显示主窗口,没有VideoWidget则可能造成有声音无图像的情况。
VideoWidget类别会在QWidget上播放多媒体串流的影像,跟AudioOutput一样,必须使用 Phonon::createPath()来与MediaObject连接。你可以利用一些函数来控制在QWidget中的VideoWidget显示的大小,你可以利用setAspectRatio()或setScaleMode()来控制,而它们接收的参数可以到网站上察看,使用方式如下(预设是使用aspect ratio):
videowidget->setAspectRatio(Phonon::VideoWidget::AspectRatioAuto);
videowidget->setScaleMode(Phonon::VideoWidget::ScaleAndCrop);
当然也有提供函式让影片进入或退出全萤幕模式。以下为一个简短的程式码范例:
MediaObject *mediaObject = new MediaObject(parent);
VideoWidget *vWidget = new VideoWidget(parent);Phonon::createPath(mediaObeject, vWidget);
SeekSlider Class
SeekSlider类别提供一个可滑动的slider来设定多媒体串流播放的位置,即播放进度条,所以它会连接到MediaObject,并控制串流目前的位置。
以下是一个使用的范例:
Phonon::MediaObject *mediaObject = new Phonon::MediaObject;
Phonon::AudioOutput *audioOutput = new Phonon::AudioOutput;
Phonon::createPath(mediaObject, audioOutput);
mediaObject->setCurrentSource(QString("E:/hello.avi"));
Phonon::SeekSlider *seekSlider = new Phonon::SeekSlider;
seekSlider->setMediaObject(mediaObject); // 与媒体对象mediaObject进行关联
seekSlider->show();
mediaObject->play();
VolumeSlider Class
VolumeSlider widget提供可以控制声音装置音量的widget。
用法其实与上面的SeekSlider类似,使用范例如下:
Phonon::AudioOutput *audioOutput = new Phonon::AudioOutput(Phonon::MusicCategory);
Phonon::createPath(mediaObject, audioOutput);
Phonon::VolumeSlider *volumeSlider = new Phonon::VolumeSlider;
volumeSlider->setAudioOutput(audioOutput); // 与音频输出设备进行关联
简单范例
再看过上面的一些类别介绍之後,其实就可以显一个简单的媒体播放器了,代码如下:
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget *mainWidget = new QWidget;
mainWidget->setWindowTitle("Media Player");
mainWidget->resize(640,480);
Phonon::MediaObject *mediaObject= new Phonon::MediaObject; // 媒体对象
mediaObject->setCurrentSource(Phonon::MediaSource("E:/hello.avi"));
Phonon::VideoWidget *videoWidget = new Phonon::VideoWidget; // 影像窗口
Phonon::createPath(mediaObject, videoWidget);
videoWidget->setAspectRatio(Phonon::VideoWidget::AspectRatioAuto);
Phonon::AudioOutput *audioOutput = new Phonon::AudioOutput(Phonon::VideoCategory); // 音频输出
Phonon::createPath(mediaObject, audioOutput);
QLabel *label = new QLabel("Volume: ");
Phonon::VolumeSlider *volumeSlider = new Phonon::VolumeSlider;
volumeSlider->setAudioOutput(audioOutput);
volumeSlider->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
Phonon::SeekSlider *seekSlider = new Phonon::SeekSlider;
seekSlider->setMediaObject(mediaObject);
// 布局管理 将上述所有控件添加到主窗口中 即mainWidget
QHBoxLayout *hLayout = new QHBoxLayout;
hLayout->addWidget(label);
hLayout->addWidget(volumeSlider);
hLayout->addStretch();
// 垂直布局
QVBoxLayout *vLayout = new QVBoxLayout;
vLayout->addWidget(videoWidget);
vLayout->addWidget(seekSlider);
vLayout->addLayout(hLayout);
mainWidget->setLayout(vLayout);
mainWidget->show();
mediaObject->play(); // 播放
return app.exec();
}
上面的程式码就完成了一个简易的多媒体播放器
PS:
用“添加”按钮来制定媒体源,即要播放的文件,添加音乐文件的槽的代码如下:
void mediaPlayer::addFiles(){
QListWidget *listWidget = new QListWidget(this); // 暂且写在这里 声明为类成员变量较好
QStringList files = QFileDialog::getOpenFileNames(this,tr("Get video files"),
QDesktopServices::storageLocation(QDesktopServices::VideoLocation),
tr("Movie (*.avi *.wmv *.mp4 *.mkv *.rm *.rmvb *.flv *.3gp)"));
int index = sourceList.size(); // 类的私有成员变量 sourcesList 存储多媒体资源信息
QString file;
foreach(file, fileNames){
listWidget->addItem(file); // QListWidget来显示音乐列表
sourceList.append(file); // sourceList声明在类头文件里 即QList
}
if(!sources.isEmpty()){ // 资源不为空时 设置为当前媒体源 然后播放即可
metaInfomationResolver->setCurrentSource(sourcesList.at(index)); // 指向当前资源的指针,与mediaObject的声明是一样的,在这里没有写出声明而已
mediaObject->setCurrentSource(metaInfomationResolver->currentSource());
mediaObject->play(); // 播放
}
}
转载需声明出处!!!