最近在芯驰x9hp平台使用qt开发仪表,由于需要播放警告音,所以使用qt的媒体库是最方便的。但是想法是美好的现实却是骨感的。移植过程中,遇到了各种错误。以下做个总结。
先贴出来测试例子代码,很简单:
QMediaPlayer player;
QMediaPlaylist playlist;
playlist.addMedia(QUrl::fromLocalFile("/media/Sound_Alarm/buzzerlong.wav")); // 添加蜂鸣音文件路径
playlist.setPlaybackMode(QMediaPlaylist::Loop); // 设置为循环播放
player.setPlaylist(&playlist);
player.setVolume(50); // 设置音量(0 到 100)
player.play(); // 开始播放
QTimer::singleShot(1000 , &a , [&](){
qDebug() << "This task will be executed after 2000 ms.";
a.quit();
});
错误一:defaultServiceProvider::requestService(): no service found for - "org.qt-project.qt.mediaplayer"
这个错误报的不够明显,使用QT_DEBUG_PLUGINS开启详细错误信息
root@x9hp_ms_a12_vemmc_ap2:/usr/lib# export QT_DEBUG_PLUGINS=1
再次运行报错如下:
root@x9hp_ms_a12_vemmc_ap2:/data# ./test_wav
QFactoryLoader::QFactoryLoader() checking directory path "/usr/lib/plugins/mediaservice" ...
QFactoryLoader::QFactoryLoader() looking at "/usr/lib/plugins/mediaservice/libqtmedia_audioengine.so"
Found metadata in lib /usr/lib/plugins/mediaservice/libqtmedia_audioengine.so, metadata=
{
"IID": "org.qt-project.qt.mediaserviceproviderfactory/5.0",
"MetaData": {
"Keys": [
"audiocapture"
],
"Services": [
"org.qt-project.qt.audiosource"
]
},
"archreq": 0,
"className": "AudioCaptureServicePlugin",
"debug": false,
"version": 330752
}
Got keys from plugin meta data ("audiocapture")
QFactoryLoader::QFactoryLoader() checking directory path "/data/mediaservice" ...
defaultServiceProvider::requestService(): no service found for - "org.qt-project.qt.mediaplayer"
QFactoryLoader::QFactoryLoader() checking directory path "/usr/lib/plugins/bearer" ...
QFactoryLoader::QFactoryLoader() looking at "/usr/lib/plugins/bearer/libqconnmanbearer.so"
Found metadata in lib /usr/lib/plugins/bearer/libqconnmanbearer.so, metadata=
{
"IID": "org.qt-project.Qt.QBearerEngineFactoryInterface",
"MetaData": {
"Keys": [
"connman"
]
},
"archreq": 0,
"className": "QConnmanEnginePlugin",
"debug": false,
"version": 330752
}
这个错误是缺少qt播放的库,于是进入目标板上的目录查看:没有名为:
/usr/lib/plugins/mediaservice
的目录,于是需要在yocto中配置:
IMAGE_INSTALL_append = " qtmultimedia qtmultimedia-plugins"
PACKAGECONFIG_append_pn-qtmultimedia = " gstreamer"
配置编译,烧录。然后运行测试列子会出现第二个错误。
错误二:Warning: "No decoder available for type 'audio/x-wav'."
Got keys from plugin meta data ("networkmanager")
QFactoryLoader::QFactoryLoader() checking directory path "/data/bearer" ...
loaded library "/usr/lib/plugins/bearer/libqconnmanbearer.so"
loaded library "/usr/lib/plugins/bearer/libqgenericbearer.so"
loaded library "/usr/lib/plugins/bearer/libqnmbearer.so"
GStreamer; Unable to play - "file:///media/Sound_Alarm/buzzerlong.wav"
Warning: "No decoder available for type 'audio/x-wav'."
这个问题经过学习查找,是缺少库文件libgstwavparse.so。查找过程如下,使用命令:
GST_DEBUG=3 gst-launch-1.0 filesrc location=/media/Sound_Alarm/buzzerlong.wav ! wavparse ! audioconvert ! audioresample ! autoaudiosink
使用该命令来测试,如果出错就一个一个都去查看gstream的插件。如果插件存在如下图所示:
root@zsos-root:/opt# gst-inspect-1.0 wavparse
Factory Details:
Rank primary (256)
Long-name WAV audio demuxer
Klass Codec/Demuxer/Audio
Description Parse a .wav file into raw audio
Author Erik Walthinsen <omega@cse.ogi.edu>
Plugin Details:
Name wavparse
Description Parse a .wav file into raw audio
Filename /usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstwavparse.so
Version 1.20.3
License LGPL
Source module gst-plugins-good
Source release date 2022-06-15
Binary package GStreamer Good Plugins (Ubuntu)
Origin URL https://launchpad.net/distros/ubuntu/+source/gst-plugins-good1.0
GObject
+----GInitiallyUnowned
+----GstObject
+----GstElement
+----GstWavParse
Pad Templates:
SINK template: 'sink'
Availability: Always
Capabilities:
audio/x-wav
audio/x-rf64
SRC template: 'src'
Availability: Always
Capabilities:
audio/ms-gsm
audio/mpeg
mpegversion: 1
layer: 3
如果插件不存在如下:
gst-launch-1.0 filesrc location=/media/Sound_Alarm/buzzerlong.wav ! decodebin ! audioconvert ! audioresample ! pulsesink
WARNING: erroneous pipeline: no element "decodebin"
附加几条gstream测试
1.播放文件
root@zsos-root:~# gst-launch-1.0 filesrc location=/media/Sound_Alarm/buzzerlong.wav ! wavparse ! audioconvert ! audioresample ! autoaudiosink
设置暂停管道 ...
管道正在 PREROLLING ...
重新分配延迟时间...
管道被 PREROLLED ...
设置播放管道 ...
重新分配延迟时间...
New clock: GstPulseSinkClock
收到来自组件“pipeline0”的 EOS 信号。
Execution ended after 0:00:02.185504227
设置 NULL 管道 ...
释放管道资源 ...
2.使用调试模式播放文件
root@zsos-root:~# GST_DEBUG=3 gst-launch-1.0 filesrc location=/media/Sound_Alarm/buzzerlong.wav ! wavparse ! audioconvert ! audioresample ! autoaudiosink
设置暂停管道 ...
0:00:04.152401428 2227930 0x5a2a23d54f00 WARN basesrc gstbasesrc.c:3688:gst_base_src_start_complete:<filesrc0> pad not activated yet
管道正在 PREROLLING ...
0:00:04.207029888 2227930 0x5a2a23d58520 WARN audio-resampler audio-resampler.c:274:convert_taps_gint16_c: can't find exact taps
重新分配延迟时间...
管道被 PREROLLED ...
设置播放管道 ...
重新分配延迟时间...
New clock: GstPulseSinkClock
0:00:06.349690225 2227930 0x76da30038580 WARN pulse pulsesink.c:703:gst_pulsering_stream_underflow_cb:<autoaudiosink0-actual-sink-pulse> Got underflow
收到来自组件“pipeline0”的 EOS 信号。
Execution ended after 0:00:02.185661915
设置 NULL 管道 ...
释放管道资源 ...
3.长鸣测试
root@x9hp_ms_a12_vemmc_ap2:~# gst-launch-1.0 audiotestsrc ! audioconvert ! audioresample ! alsasink
Setting pipeline to PAUSED ...
Dmix type: 22, pcm areas (0xffffa676a000) silence
Pipeline is PREROLLING ...
Redistribute latency...
Pipeline is PREROLLED ...
Setting pipeline to PLAYING ...
New clock: GstAudioSinkClock
�^Chandling interrupt.
Interrupt: Stopping pipeline ...
Execution ended after 0:00:03.150230333
Setting pipeline to PAUSED ...
Setting pipeline to READY ...
Setting pipeline to NULL ...
Freeing pipeline ...
4.播报测试
root@x9hp_ms_a12_vemmc_ap2:~# speaker-test -t wav -c 2
speaker-test 1.1.5
Playback device is default
Stream parameters are 48000Hz, S16_LE, 2 channels
WAV file(s)
Dmix type: 22, pcm areas (0xffff9e4b5000) silence
Rate set to 48000Hz (requested 48000Hz)
Buffer size range from 1920 to 3840
Period size range from 960 to 960
Using max buffer size 3840
Periods = 4
was set period_size = 960
was set buffer_size = 3840
0 - Front Left
1 - Front Right
Time per period = 2.939456
0 - Front Left
1 - Front Right