diff --git a/MediaPlayer.cpp b/MediaPlayer.cpp index f4b8bd5..0b18c04 100644 --- a/MediaPlayer.cpp +++ b/MediaPlayer.cpp @@ -32,6 +32,7 @@ MediaPlayer::MediaPlayer(string name) : id_(name) pipeline_ = nullptr; ready_ = false; + failed_ = false; seeking_ = false; enabled_ = true; rate_ = 1.0; @@ -77,8 +78,6 @@ static MediaInfo UriDiscoverer_(std::string uri) #endif MediaInfo video_stream_info; - // assume it will fail - video_stream_info.failed = true; /* Instantiate the Discoverer */ GError *err = NULL; @@ -118,15 +117,12 @@ static MediaInfo UriDiscoverer_(std::string uri) // no error, handle information found if ( result == GST_DISCOVERER_OK ) { - bool foundvideostream = false; GList *streams = gst_discoverer_info_get_video_streams(info); GList *tmp; - for (tmp = streams; tmp && !foundvideostream; tmp = tmp->next ) { + for (tmp = streams; tmp && !video_stream_info.valid; tmp = tmp->next ) { GstDiscovererStreamInfo *tmpinf = (GstDiscovererStreamInfo *) tmp->data; if ( GST_IS_DISCOVERER_VIDEO_INFO(tmpinf) ) { - // inform that it succeeded - video_stream_info.failed = false; // found a video / image stream : fill-in information GstDiscovererVideoInfo* vinfo = GST_DISCOVERER_VIDEO_INFO(tmpinf); video_stream_info.width = gst_discoverer_video_info_get_width(vinfo); @@ -161,16 +157,18 @@ static MediaInfo UriDiscoverer_(std::string uri) const GstTagList *tags = gst_discoverer_stream_info_get_tags(tmpinf); if ( tags ) { gchar *container = NULL; - gst_tag_list_get_string (tags, GST_TAG_CONTAINER_FORMAT, &container); - if (container) video_stream_info.codec_name += " " + std::string(container); + if ( gst_tag_list_get_string (tags, GST_TAG_CONTAINER_FORMAT, &container) ) + video_stream_info.codec_name += " " + std::string(container); + g_free(container); } // exit loop - foundvideostream = true; + // inform that it succeeded + video_stream_info.valid = true; } } gst_discoverer_stream_info_list_free(streams); - if (!foundvideostream) { + if (!video_stream_info.valid) { Log::Warning("Warning: No video stream in '%s'", uri.c_str()); } } @@ -226,7 +224,7 @@ void MediaPlayer::execute_open() if (error != NULL) { Log::Warning("MediaPlayer %s Could not construct pipeline %s:\n%s", id_.c_str(), description.c_str(), error->message); g_clear_error (&error); - media_.failed = true; + failed_ = true; return; } g_object_set(G_OBJECT(pipeline_), "name", id_.c_str(), NULL); @@ -237,7 +235,7 @@ void MediaPlayer::execute_open() GstCaps *caps = gst_caps_from_string(capstring.c_str()); if (!gst_video_info_from_caps (&v_frame_video_info_, caps)) { Log::Warning("MediaPlayer %s Could not configure video frame info", id_.c_str()); - media_.failed = true; + failed_ = true; return; } @@ -281,7 +279,7 @@ void MediaPlayer::execute_open() } else { Log::Warning("MediaPlayer %s Could not configure sink", id_.c_str()); - media_.failed = true; + failed_ = true; return; } gst_caps_unref (caps); @@ -293,7 +291,7 @@ void MediaPlayer::execute_open() GstStateChangeReturn ret = gst_element_set_state (pipeline_, desired_state_); if (ret == GST_STATE_CHANGE_FAILURE) { Log::Warning("MediaPlayer %s Could not open '%s'", id_.c_str(), uri_.c_str()); - media_.failed = true; + failed_ = true; return; } @@ -320,7 +318,7 @@ bool MediaPlayer::isOpen() const bool MediaPlayer::failed() const { - return media_.failed; + return failed_; } void MediaPlayer::close() @@ -419,7 +417,7 @@ void MediaPlayer::enable(bool on) GstStateChangeReturn ret = gst_element_set_state (pipeline_, requested_state); if (ret == GST_STATE_CHANGE_FAILURE) { Log::Warning("MediaPlayer %s Failed to enable", gst_element_get_name(pipeline_)); - media_.failed = true; + failed_ = true; } } @@ -465,7 +463,7 @@ void MediaPlayer::play(bool on) GstStateChangeReturn ret = gst_element_set_state (pipeline_, desired_state_); if (ret == GST_STATE_CHANGE_FAILURE) { Log::Warning("MediaPlayer %s Failed to play", gst_element_get_name(pipeline_)); - media_.failed = true; + failed_ = true; } #ifdef MEDIA_PLAYER_DEBUG else if (on) @@ -660,7 +658,7 @@ void MediaPlayer::fill_texture(guint index) void MediaPlayer::update() { // discard - if (media_.failed) + if (failed_) return; // not ready yet @@ -671,7 +669,7 @@ void MediaPlayer::update() // ok, discovering thread is finished ! Get the info media_ = discoverer_.get(); // if its ok, open the media - if (!media_.failed) + if (media_.valid) execute_open(); } // wait next frame to display diff --git a/MediaPlayer.h b/MediaPlayer.h index 016334e..4a6061e 100644 --- a/MediaPlayer.h +++ b/MediaPlayer.h @@ -32,7 +32,7 @@ struct MediaInfo { bool isimage; bool interlaced; bool seekable; - bool failed; + bool valid; MediaInfo() { width = par_width = 640; @@ -43,7 +43,7 @@ struct MediaInfo { isimage = false; interlaced = false; seekable = false; - failed = false; + valid = false; } inline MediaInfo& operator = (const MediaInfo& b) @@ -56,7 +56,7 @@ struct MediaInfo { this->bitrate = b.bitrate; this->framerate = b.framerate; this->codec_name = b.codec_name; - this->failed = b.failed; + this->valid = b.valid; this->isimage = b.isimage; this->interlaced = b.interlaced; this->seekable = b.seekable; @@ -253,6 +253,7 @@ private: GstElement *pipeline_; GstVideoInfo v_frame_video_info_; std::atomic ready_; + std::atomic failed_; bool seeking_; bool enabled_; diff --git a/MediaSource.cpp b/MediaSource.cpp index 27c4f63..6cdb34d 100644 --- a/MediaSource.cpp +++ b/MediaSource.cpp @@ -124,8 +124,7 @@ void MediaSource::update(float dt) Source::update(dt); // update video - if (active_) - mediaplayer_->update(); + mediaplayer_->update(); } void MediaSource::render() diff --git a/Mixer.cpp b/Mixer.cpp index 544c4be..38a365c 100644 --- a/Mixer.cpp +++ b/Mixer.cpp @@ -150,13 +150,14 @@ Mixer::Mixer() : session_(nullptr), back_session_(nullptr), current_view_(nullpt void Mixer::update() { + // sort-of garbage collector : just wait for 1 iteration + // before deleting the previous session: this way, the sources + // had time to end properly if (garbage_.size()>0) { - delete garbage_.back(); garbage_.pop_back(); } - #ifdef THREADED_LOADING // if there is a session importer pending if (!sessionImporters_.empty()) { @@ -184,7 +185,7 @@ void Mixer::update() // if a change of session is requested if (sessionSwapRequested_) { sessionSwapRequested_ = false; - // successfully loading + // sanity check if ( back_session_ ) { // swap front and back sessions swap(); @@ -606,21 +607,6 @@ void Mixer::load(const std::string& filename) // Start async thread for loading the session // Will be obtained in the future in update() sessionLoaders_.emplace_back( std::async(std::launch::async, loadSession_, filename) ); - - -// Session *se = new Session; - -// sessionLoaders_.emplace_back(std::async(std::launch::async, -// [](Session *s, const std::string& filename){ -// // actual loading of xml file -// SessionCreator creator( s ); -// if (creator.load(filename)) { -// // loaded ok -// s->setFilename(filename); -// } -// return s; -// }, se, filename)); - } #else set( loadSession_(filename) ); @@ -653,12 +639,16 @@ void Mixer::open(const std::string& filename) void Mixer::import(const std::string& filename) { +#ifdef THREADED_LOADING // import only one at a time if (sessionImporters_.empty()) { // Start async thread for loading the session // Will be obtained in the future in update() sessionImporters_.emplace_back( std::async(std::launch::async, loadSession_, filename) ); } +#else + merge( loadSession_(filename) ); +#endif } void Mixer::merge(Session *session) @@ -671,7 +661,6 @@ void Mixer::merge(Session *session) // import every sources for ( Source *s = session->popSource(); s != nullptr; s = session->popSource()) insertSource(s); - } void Mixer::swap() @@ -730,7 +719,6 @@ void Mixer::swap() update_time_ = GST_CLOCK_TIME_NONE; // delete back (former front session) -// delete back_session_; garbage_.push_back(back_session_); back_session_ = nullptr; @@ -760,7 +748,6 @@ void Mixer::clear() // delete previous back session if needed if (back_session_) garbage_.push_back(back_session_); -// delete back_session_; // create empty session back_session_ = new Session; @@ -781,7 +768,6 @@ void Mixer::set(Session *s) // delete previous back session if needed if (back_session_) garbage_.push_back(back_session_); -// delete back_session_; // set to new given session back_session_ = s; diff --git a/Source.cpp b/Source.cpp index ffd32a9..03fc0b7 100644 --- a/Source.cpp +++ b/Source.cpp @@ -135,7 +135,7 @@ Source::~Source() { // inform clones that they lost their origin for (auto it = clones_.begin(); it != clones_.end(); it++) - (*it)->unlink(); + (*it)->detach(); clones_.clear(); // delete objects @@ -406,7 +406,7 @@ CloneSource *Source::clone() CloneSource::CloneSource(Source *origin) : Source(), origin_(origin) { // create surface: - clonesurface_ = nullptr; + clonesurface_ = new Surface(renderingshader_); } CloneSource::~CloneSource() @@ -415,8 +415,7 @@ CloneSource::~CloneSource() origin_->clones_.remove(this); // delete surface - if (clonesurface_) - delete clonesurface_; + delete clonesurface_; } CloneSource *CloneSource::clone() @@ -438,7 +437,6 @@ void CloneSource::init() if (origin_ && origin_->ready()) { // get the texture index from framebuffer of view, apply it to the surface - clonesurface_ = new Surface(renderingshader_); clonesurface_->setTextureIndex( origin_->texture() ); // create Frame buffer matching size of session diff --git a/Source.h b/Source.h index 3a2d5cf..e1e5fd1 100644 --- a/Source.h +++ b/Source.h @@ -45,10 +45,6 @@ public: // cloning mechanism virtual CloneSource *clone (); -// void unClone(CloneSource *clone); -// inline size_t numClones() const { return clones_.size(); } -// inline CloneList::iterator beginClones () { return clones_.begin(); } -// inline CloneList::iterator endClones () { return clones_.end(); } // Display mode typedef enum { @@ -195,7 +191,7 @@ public: void accept (Visitor& v) override; CloneSource *clone() override; - inline void unlink() { origin_ = nullptr; } + inline void detach() { origin_ = nullptr; } inline Source *origin() const { return origin_; } protected: