VS2015+Qt5.9.1,需要播放AAC格式音频,用QMediaPlayer试了不行,其他格式的WMA,WAV,MP3试了都可以,怀疑是没有解码器,下载安装了K-Lite Codec Pack,果然可以了,但只是为了播放个AAC,犯不着给用户装个解码器,而且不装K-Lite之前,用Windows Media Player是可以播放AAC的,所以断定Windows自己是可以搞定的,遂卸载K-Lite。
然后了解到有人说QMediaPlayer的格式支持取决于系统的DirectShow,但我Windows Media Player可以播放啊,难道不是DirectShow支持的,郁闷。再然后又从Qt Multimedia on Windows了解到,Qt提供了两个封装好的插件,一个是使用Microsoft DirectShow API,另一个是使用WMF (Windows Media Foundation) framework。DirectShow自XP起被逐渐弃用,而WMF是从Vista开始新引入的。微软总是喜欢自我否定,那就直奔新引入的吧。其实后来也试了下DirectShow的插件,播放不了AAC。DirectShow插件源码里也有注释推荐WMF。
// The player service provided by the WMF-plugin should preferably be used.
// DirectShow should then only provide the camera (see QTBUG-29172, QTBUG-29175).
经过一番读文档、上网搜、猜想加实践,最后总算是走通了这条路。首先dll需要自己编,WMF的插件名字叫wmfengine.dll,项目wmf.pro(DirectShow,directshow.pro,dsengine.dll),文件位置本地自己搜索,我用的VS,导入pro前需要把pro里的qtConfig(wmf-player): include (player/player.pri)改为 include (player/player.pri)(好吧,直接这样改其实是我不知道怎么让qtConfig(wmf-player)为真,知道的望告知),不然只有MFAudioDecoderService的代码,没有包含进来MFPlayerService的代码。
qtConfig(wmf-player): include (player/player.pri)
include (decoder/decoder.pri)
然而想用Player,还得过代码里的一个关卡,因为#if QT_CONFIG(wmf_player)才会new player,最后发现这个宏是在qtmultimedia-config_p.h里定义的,需要把QT_FEATURE_wmf_player由-1改为1。
QMediaService* WMFServicePlugin::create(QString const& key)
{
#if QT_CONFIG(wmf_player)
if (key == QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER)) {
addRefCount();
return new MFPlayerService;
}
#endif
if (key == QLatin1String(Q_MEDIASERVICE_AUDIODECODER)) {
addRefCount();
return new MFAudioDecoderService;
}
//qDebug() << "unsupported key:" << key;
return 0;
}
//#define QT_CONFIG(feature) (1/QT_FEATURE_##feature == 1)
//qtmultimedia-config_p.h
//...
#define QT_FEATURE_wmf_player 1
//...
编好后外部使用的核心简化代码。
#include <QPluginLoader>
#include <QMediaPlayerControl>
#include <QMediaServiceProviderPlugin>
QPluginLoader loader("wmfengine.dll");
QObject *plugin = loader.instance();
QMediaServiceProviderPlugin *mediaServicePlugin = qobject_cast<QMediaServiceProviderPlugin *>(plugin);
QMediaService *mediaService = mediaServicePlugin->create(Q_MEDIASERVICE_MEDIAPLAYER);
QMediaPlayerControl *mediaControl = qobject_cast<QMediaPlayerControl *>(mediaService->requestControl(QMediaPlayerControl_iid));
QMediaContent media(QUrl::fromLocalFile("Voice.aac"));
mediaControl->setMedia(media, nullptr);
mediaControl->play();
//mediaService->releaseControl(mediaControl);
//mediaServicePlugin->release(mediaService);
OK,这样就可以播放AAC了,只是有个问题,QMediaPlayerControl的信号positionChanged看起来并不会给反馈,所以进度可能需要自己用QTimer来解决。
还有些其他疑问有待研究,没明白这个MFAudioDecoderService怎么使用?也不知道MFPlayerService能否播放视频,QMediaPlayerControl没有setVideoOutput的话,那视频输出到了哪里呢?有研究的可以分享下。