Fixed behavior seek in timeline: prevent multiple successive seek

events, save and load gaps in XML session.
This commit is contained in:
brunoherbelin
2020-08-22 00:03:22 +02:00
parent 9f954d258f
commit e44832a419
5 changed files with 56 additions and 48 deletions

View File

@@ -673,8 +673,12 @@ void MediaPlayer::update()
// try to get info from discoverer
if (discoverer_.wait_for( std::chrono::milliseconds(4) ) == std::future_status::ready )
{
// ok, discovering thread is finished ! Get the info
// remember loaded gaps
TimeIntervalSet gaps = media_.timeline.gaps();
// ok, discovering thread is finished ! Get the media info
media_ = discoverer_.get();
// restore loaded gaps (overwriten above)
media_.timeline.setGaps( gaps );
// if its ok, open the media
if (media_.valid)
execute_open();
@@ -687,6 +691,13 @@ void MediaPlayer::update()
if (!enabled_ || (media_.isimage && textureindex_>0 ) )
return;
// if (seeking_) {
// GstState state;
// gst_element_get_state (pipeline_, &state, NULL, GST_CLOCK_TIME_NONE);
// seeking_ = false;
// return;
// }
// local variables before trying to update
guint read_index = 0;
bool need_loop = false;
@@ -744,12 +755,17 @@ void MediaPlayer::update()
// unkock frame after reading it
frame_[read_index].access.unlock();
// if already seeking (asynch)
if (seeking_) {
// request status update to pipeline (re-sync gst thread)
GstState state;
gst_element_get_state (pipeline_, &state, NULL, GST_CLOCK_TIME_NONE);
// seek should be resolved next frame
seeking_ = false;
// do NOT do another seek yet
}
// otherwise check for need to seek (pipeline management)
else {
// manage timeline: test if position falls into a gap
TimeInterval gap;
if (position_ != GST_CLOCK_TIME_NONE && media_.timeline.gapAt(position_, gap)) {
@@ -766,12 +782,11 @@ void MediaPlayer::update()
}
}
// manage loop mode
if (need_loop) {
execute_loop_command();
}
}
}
@@ -943,7 +958,8 @@ bool MediaPlayer::fill_frame(GstBuffer *buf, FrameStatus status)
// set the start position (i.e. pts of first frame we got)
if (media_.timeline.start() == GST_CLOCK_TIME_NONE) {
media_.timeline.setFirst(buf->pts);
Log::Info("Timeline %ld [%ld %ld]", media_.timeline.numFrames(), media_.timeline.first(), media_.timeline.end());
Log::Info("Timeline %ld [%ld %ld] %d gaps", media_.timeline.numFrames(),
media_.timeline.first(), media_.timeline.end(), media_.timeline.numGaps());
}
}
// full but invalid frame : will be deleted next iteration

View File

@@ -186,6 +186,7 @@ void SessionCreator::visit(MediaPlayer &n)
// timeline
XMLElement *gapselement = mediaplayerNode->FirstChildElement("Gaps");
if (gapselement) {
Timeline tl;
XMLElement* gap = gapselement->FirstChildElement("Interval");
for( ; gap ; gap = gap->NextSiblingElement())
{
@@ -193,8 +194,9 @@ void SessionCreator::visit(MediaPlayer &n)
GstClockTime b = GST_CLOCK_TIME_NONE;
gap->QueryUnsigned64Attribute("begin", &a);
gap->QueryUnsigned64Attribute("end", &b);
n.timeline().addGap( a, b );
tl.addGap( a, b );
}
n.setTimeline(tl);
}
// playing properties
double speed = 1.0;

View File

@@ -149,11 +149,11 @@ void SessionVisitor::visit(MediaPlayer &n)
// gaps in timeline
XMLElement *gapselement = xmlDoc_->NewElement("Gaps");
std::list< std::pair<guint64, guint64> > gaps = n.timeline().gaps();
TimeIntervalSet gaps = n.timeline().gaps();
for( auto it = gaps.begin(); it!= gaps.end(); it++) {
XMLElement *g = xmlDoc_->NewElement("Interval");
g->SetAttribute("begin", (*it).first);
g->SetAttribute("end", (*it).second);
g->SetAttribute("begin", (*it).begin);
g->SetAttribute("end", (*it).end);
gapselement->InsertEndChild(g);
}
newelement->InsertEndChild(gapselement);

View File

@@ -142,11 +142,6 @@ void Timeline::fillArrayFromGaps(float *array_, size_t array_size_)
}
}
size_t Timeline::numGaps()
{
return gaps_.size();
}
bool Timeline::gapAt(const GstClockTime t, TimeInterval &gap) const
{
TimeIntervalSet::const_iterator g = std::find_if(gaps_.begin(), gaps_.end(), includesTime(t));
@@ -172,6 +167,11 @@ bool Timeline::addGap(TimeInterval s)
return false;
}
void Timeline::setGaps(TimeIntervalSet g)
{
gaps_ = g;
}
//void Timeline::toggleGaps(GstClockTime from, GstClockTime to)
//{
// TimeInterval interval(from, to);
@@ -221,12 +221,4 @@ void Timeline::clearGaps()
gaps_.clear();
}
std::list< std::pair<guint64, guint64> > Timeline::gaps() const
{
std::list< std::pair<guint64, guint64> > ret;
for (TimeIntervalSet::iterator it = gaps_.begin(); it != gaps_.end(); it++)
ret.push_back( std::make_pair( it->begin, it->end ) );
return ret;
}

View File

@@ -98,21 +98,19 @@ public:
inline GstClockTime step() const { return step_; }
inline GstClockTime duration() const { return timing_.duration(); }
inline size_t numFrames() const { return duration() / step_; }
inline TimeIntervalSet gaps() const { return gaps_; }
inline size_t numGaps() const { return gaps_.size(); }
GstClockTime next(GstClockTime time) const;
GstClockTime previous(GstClockTime time) const;
// Add / remove gaps in the timeline
// Add / remove / get gaps in the timeline
void clearGaps();
bool addGap(TimeInterval s);
bool addGap(GstClockTime begin, GstClockTime end);
bool removeGaptAt(GstClockTime t);
void clearGaps();
// void toggleGaps(GstClockTime from, GstClockTime to);
// get gaps
size_t numGaps();
bool gapAt(const GstClockTime t, TimeInterval &gap) const;
std::list< std::pair<guint64, guint64> > gaps() const;
void setGaps(TimeIntervalSet g);
// synchronize data structures
void updateGapsFromArray(float *array_, size_t array_size_);