我正在编写一个嵌入多个使用 Qt 同时运行的 libVlc 实例的应用程序。vlc 库中似乎存在一个错误,如果从 Qt 的 GUI 线程调用,有时 libvlc_media_player_stop 会死锁。在其中一个 videolan 论坛上,公认的解决方案是从另一个线程调用停止函数。我正在寻找最少参与且不太难看的方法来从不同的线程调用停止。我研究了使用 QThreadPool ,它完全适用于这种情况,但在我的特殊情况下,它并没有使解决方案变得漂亮。
这是我的一段代码:
VlcWidget.h
class VlcWidget : public QWidget
{
Q_OBJECT
private:
// State
bool _isPlaying;
// The streaming source, title and quality data
VideoData _videoData;
VIDEO_QUALITY _quality;
// LibVlc related members
libvlc_instance_t *_vlcInstance;
libvlc_media_player_t *_vlcMediaPlayer;
libvlc_media_t *_vlcMedia;
int _vlcTrackID;
}
VlcWidget.c
void VlcWidget::Play()
{
if(_videoData.Source() != "" && !_isPlaying)
{
// Create a new media descriptor
_vlcMedia = libvlc_media_new_location(
_vlcInstance,
_videoData.Source().toStdString().c_str());
// Tell the user about incorrect URL
if(_vlcMedia == NULL)
{
QMessageBox::information(this,
_videoData.Title(),
"Unable to open source Url.\nPlease check the source and try again.");
return;
}
libvlc_media_player_set_media(_vlcMediaPlayer, _vlcMedia);
libvlc_media_release(_vlcMedia);
libvlc_media_player_set_xwindow(_vlcMediaPlayer, parentWidget()->winId());
libvlc_media_player_play(_vlcMediaPlayer);
_vlcTrackID = libvlc_audio_get_track(_vlcMediaPlayer);
_isPlaying = true;
}
}
void VlcWidget::Stop()
{
if(_isPlaying)
{
libvlc_media_player_stop(_vlcMediaPlayer);
_vlcTrackID = -1;
_isPlaying = false;
}
}
我使用 QthreadPool 的解决方案如下所示:
class AsyncVlcPlay : public QRunnable
{
private:
// State
bool *_isPlaying;
// LibVlc related members
libvlc_instance_t *_vlcInstance;
libvlc_media_player_t *_vlcMediaPlayer;
libvlc_media_t *_vlcMedia;
int *_vlcTrackID;
public:
virtual void run();
}
AsyncVlcPlay::run() 与 VlcWidget::Play() 所做的完全一样,只是添加了简单的锁定。而且我还需要一个用于 VlcWidget::Stop() 的类似类。我不喜欢这个解决方案,因为我不应该真的需要 2 个新课程来实现我想要实现的目标。更糟糕的是,我必须将 VlcWidgets 私有成员传递给另一个类的对象。我很确定有一种我不知道的非常简单的方法,希望你们中的一个可以在这里帮助我。谢谢!
(事实上,我真的不需要 VlcWidget::Play() 在另一个线程上,但我想保持 Play 和 Stop 对称)