Piszę aplikację, która osadza wiele instancji libVlc działających jednocześnie, używając Qt. Wygląda na to, że w bibliotece vlc pojawia się błąd, w którym czasami dochodzi do zakleszczenia libvlc_media_player_stop, jeśli wywołano go z wątku GUI Qt. Na jednym z forów videolan, zaakceptowanym rozwiązaniem było wywołanie funkcji stop z innego wątku. Szukam najmniej zaangażowanej i niezbyt brzydkiej metody wywoływania zatrzymania z innego wątku. Spojrzałem na użycie QThreadPool, który jest przeznaczony właśnie dla tego rodzaju sytuacji, ale w moim przypadku nie czyni to rozwiązania ładnym.Jaki jest najprostszy sposób na wystrzelenie i zapomnienie wątku w języku C++/Qt na Linuksie?
Oto fragment mojego kodu:
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;
}
}
Moje rozwiązanie używając QthreadPool wyglądało:
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();
}
I AsyncVlcPl ay :: run() robi dokładnie to, co robi VlcWidget :: Play() z dodaniem prostego blokowania. I potrzebuję podobnej klasy dla VlcWidget :: Stop(). Nie podoba mi się to rozwiązanie, ponieważ nie powinienem potrzebować 2 nowych klas dla tego, co próbuję osiągnąć. A co gorsza, będę musiał przekazać prywatnych członków VlcWidgets do obiektu innej klasy. Jestem pewien, że istnieje bardzo prosty sposób, którego nie jestem świadomy i mam nadzieję, że jeden z was pomoże mi tutaj. Dzięki!
(W rzeczywistości, naprawdę nie trzeba VlcWidget :: play(), aby być w innym wątku, ale chciałbym zachować odtwarzania i zatrzymania symetryczne)
Może [QtConcurrent] (http : //qt-project.org/doc/qt-4.8/qtconcurrentrun.html) jest tym, czego szukasz. – thuga
@thuga - Wielkie dzięki!Właśnie tego szukałem :) – Kulki
Jeśli zamierzasz używać QtConcurrent, sugeruję najpierw przeczytać: http://comments.gmane.org/gmane.comp.lib.qt.devel/7942 – TheDarkKnight