BugFix Ensure complete close of session upon termination

Async ending of gst pipeline in stream and media player sources caused a crash at termination as source was still not closed when process was ended. Fix is to ask for an immediate termination of gst pipeline upon delete of stream, and to wait for mixer manager to end current session when clearing.
This commit is contained in:
Bruno Herbelin
2024-02-28 00:39:03 +01:00
parent 1ba8ff06e1
commit 05f593e40c
8 changed files with 33 additions and 27 deletions

View File

@@ -100,7 +100,7 @@ MediaPlayer::MediaPlayer()
MediaPlayer::~MediaPlayer() MediaPlayer::~MediaPlayer()
{ {
close(); close(false);
// cleanup opengl texture // cleanup opengl texture
if (textureindex_) if (textureindex_)
@@ -714,9 +714,10 @@ void MediaPlayer::Frame::unmap()
} }
void delayed_terminate( GstElement *p ) void pipeline_terminate( GstElement *p )
{ {
#ifdef MEDIA_PLAYER_DEBUG #ifdef MEDIA_PLAYER_DEBUG
g_printerr("MediaPlayer %s close\n", gst_element_get_name(p));
Log::Info("MediaPlayer %s closed", gst_element_get_name(p)); Log::Info("MediaPlayer %s closed", gst_element_get_name(p));
#endif #endif
@@ -727,7 +728,7 @@ void delayed_terminate( GstElement *p )
gst_object_unref ( p ); gst_object_unref ( p );
} }
void MediaPlayer::close() void MediaPlayer::close(bool async)
{ {
// not opened? // not opened?
if (!opened_) { if (!opened_) {
@@ -751,9 +752,12 @@ void MediaPlayer::close()
// clean up GST // clean up GST
if (pipeline_ != nullptr) { if (pipeline_ != nullptr) {
if (async)
// end pipeline asynchronously // end pipeline asynchronously
std::thread(delayed_terminate, pipeline_).detach(); std::thread(pipeline_terminate, pipeline_).detach();
else
// end pipeline immediately
pipeline_terminate(pipeline_);
pipeline_ = nullptr; pipeline_ = nullptr;
} }

View File

@@ -101,7 +101,7 @@ public:
/** /**
* Close the Media * Close the Media
* */ * */
void close(); void close(bool async = true);
/** /**
* Update texture with latest frame * Update texture with latest frame
* Must be called in rendering update loop * Must be called in rendering update loop

View File

@@ -77,7 +77,7 @@ Mixer::Mixer() : session_(nullptr), back_session_(nullptr), sessionSwapRequested
current_source_index_ = -1; current_source_index_ = -1;
// initialize with a new empty session // initialize with a new empty session
clear(); set( new Session );
setView( View::MIXING ); setView( View::MIXING );
} }
@@ -1580,7 +1580,7 @@ void Mixer::close(bool smooth)
transition_.attach(ts); transition_.attach(ts);
} }
else else
clear(); set( new Session );
// closing session : filename at font in history should not be reloaded // closing session : filename at font in history should not be reloaded
Settings::application.recentSessions.front_is_valid = false; Settings::application.recentSessions.front_is_valid = false;
@@ -1588,18 +1588,18 @@ void Mixer::close(bool smooth)
void Mixer::clear() void Mixer::clear()
{ {
// delete previous back session if needed // wait finish saving / loading
if (back_session_) while (busy())
garbage_.push_back(back_session_); update();
// create empty session // set for an empty session and update to ensure session is deleted
back_session_ = new Session; set(new Session);
while (sessionSwapRequested_ || garbage_.size() > 0)
update();
// swap current with empty // all finished, we can clear the back session we just added
sessionSwapRequested_ = true; delete back_session_;
back_session_ = nullptr;
// need to deeply update view to apply eventual changes
++View::need_deep_update_;
} }
void Mixer::set(Session *s) void Mixer::set(Session *s)

View File

@@ -120,7 +120,7 @@ void MultiFile::execute_open()
src_ = gst_bin_get_by_name (GST_BIN (pipeline_), "src"); src_ = gst_bin_get_by_name (GST_BIN (pipeline_), "src");
} }
void MultiFile::close () void MultiFile::close (bool)
{ {
if (src_ != nullptr) { if (src_ != nullptr) {
gst_object_unref (src_); gst_object_unref (src_);

View File

@@ -25,7 +25,7 @@ class MultiFile : public Stream
public: public:
MultiFile (); MultiFile ();
void open (const MultiFileSequence &sequence, uint framerate = 30); void open (const MultiFileSequence &sequence, uint framerate = 30);
void close () override; void close (bool) override;
void rewind () override; void rewind () override;
// dynamic change of gstreamer multifile source properties // dynamic change of gstreamer multifile source properties

View File

@@ -73,7 +73,7 @@ Stream::Stream()
Stream::~Stream() Stream::~Stream()
{ {
Stream::close(); Stream::close(false);
// cleanup opengl texture // cleanup opengl texture
if (textureindex_) if (textureindex_)
@@ -368,7 +368,7 @@ void async_terminate( GstElement *p )
gst_object_unref ( p ); gst_object_unref ( p );
} }
void Stream::close() void Stream::close(bool async)
{ {
// not opened? // not opened?
if (!opened_) { if (!opened_) {
@@ -386,7 +386,10 @@ void Stream::close()
if (pipeline_ != nullptr) { if (pipeline_ != nullptr) {
// end pipeline asynchronously // end pipeline asynchronously
if (async)
std::thread(async_terminate, pipeline_).detach(); std::thread(async_terminate, pipeline_).detach();
else
async_terminate(pipeline_);
pipeline_ = nullptr; pipeline_ = nullptr;
} }

View File

@@ -74,7 +74,7 @@ public:
/** /**
* Close the Media * Close the Media
* */ * */
virtual void close(); virtual void close(bool async = true);
/** /**
* Update texture with latest frame * Update texture with latest frame
* Must be called in rendering update loop * Must be called in rendering update loop

View File

@@ -248,8 +248,7 @@ int main(int argc, char *argv[])
/// ///
/// MIXER TERMINATE /// MIXER TERMINATE
/// ///
while (Mixer::manager().busy()) Mixer::manager().clear();
Mixer::manager().update();
/// ///
/// RENDERING TERMINATE /// RENDERING TERMINATE