diff --git a/Timeline.cpp b/Timeline.cpp new file mode 100644 index 0000000..cc1336c --- /dev/null +++ b/Timeline.cpp @@ -0,0 +1,87 @@ + +#include + + +#include "defines.h" +#include "Log.h" +#include "Timeline.h" + +#define SEGMENT_ARRAY_MAX_SIZE 1000 + + +Timeline::Timeline() : array_(nullptr) +{ + reset(); +} + +Timeline::~Timeline() +{ + reset(); +} + +void Timeline::reset() +{ + start_ = GST_CLOCK_TIME_NONE; + end_ = GST_CLOCK_TIME_NONE; + num_frames_ = 0; + array_size_ = 0; + // clear segment array + if (array_ != nullptr) + free(array_); +} + +void Timeline::init(GstClockTime start, GstClockTime end, GstClockTime frame_duration) +{ + reset(); + + start_ = start; + end_ = end; + num_frames_ = (size_t) end_ / (size_t) frame_duration; + + array_size_ = MIN( SEGMENT_ARRAY_MAX_SIZE, num_frames_); + array_ = (float *) malloc(array_size_ * sizeof(float)); + for (int i = 0; i < array_size_; ++i) + array_[i] = 1.f; + + Log::Info("%d frames in timeline", array_size_); +} + +bool Timeline::addPlaySegment(GstClockTime begin, GstClockTime end) +{ + return addPlaySegment( MediaSegment(begin, end) ); +} + +bool Timeline::addPlaySegment(MediaSegment s) +{ + if ( s.is_valid() ) + return segments_.insert(s).second; + + return false; +} + +bool Timeline::removeAllPlaySegmentOverlap(MediaSegment s) +{ + bool ret = removePlaySegmentAt(s.begin); + return removePlaySegmentAt(s.end) || ret; +} + +bool Timeline::removePlaySegmentAt(GstClockTime t) +{ + MediaSegmentSet::const_iterator s = std::find_if(segments_.begin(), segments_.end(), containsTime(t)); + + if ( s != segments_.end() ) { + segments_.erase(s); + return true; + } + + return false; +} + +std::list< std::pair > Timeline::getPlaySegments() const +{ + std::list< std::pair > ret; + for (MediaSegmentSet::iterator it = segments_.begin(); it != segments_.end(); it++) + ret.push_back( std::make_pair( it->begin, it->end ) ); + + return ret; +} diff --git a/Timeline.h b/Timeline.h new file mode 100644 index 0000000..97ae369 --- /dev/null +++ b/Timeline.h @@ -0,0 +1,98 @@ +#ifndef TIMELINE_H +#define TIMELINE_H + +#include +#include +#include +#include + +#include + +struct MediaSegment +{ + GstClockTime begin; + GstClockTime end; + + MediaSegment() + { + begin = GST_CLOCK_TIME_NONE; + end = GST_CLOCK_TIME_NONE; + } + + MediaSegment(GstClockTime b, GstClockTime e) + { + if ( b < e ) { + begin = b; + end = e; + } else { + begin = GST_CLOCK_TIME_NONE; + end = GST_CLOCK_TIME_NONE; + } + } + inline bool is_valid() const + { + return begin != GST_CLOCK_TIME_NONE && end != GST_CLOCK_TIME_NONE && begin < end; + } + inline bool operator < (const MediaSegment b) const + { + return (this->is_valid() && b.is_valid() && this->end < b.begin); + } + inline bool operator == (const MediaSegment b) const + { + return (this->begin == b.begin && this->end == b.end); + } + inline bool operator != (const MediaSegment b) const + { + return (this->begin != b.begin || this->end != b.end); + } +}; + +struct containsTime: public std::unary_function +{ + inline bool operator()(const MediaSegment s) const + { + return ( s.is_valid() && _t > s.begin && _t < s.end ); + } + + containsTime(GstClockTime t) : _t(t) { } + +private: + GstClockTime _t; +}; + + +typedef std::set MediaSegmentSet; + + +class Timeline +{ +public: + Timeline(); + ~Timeline(); + + void reset(); + void init(GstClockTime start, GstClockTime end, GstClockTime frame_duration); + + bool addPlaySegment(GstClockTime begin, GstClockTime end); + bool addPlaySegment(MediaSegment s); + bool removePlaySegmentAt(GstClockTime t); + bool removeAllPlaySegmentOverlap(MediaSegment s); + std::list< std::pair > getPlaySegments() const; + + inline float *Array() { return array_; } + inline size_t ArraySize() { return array_size_; } + +private: + + GstClockTime start_; + GstClockTime end_; + size_t num_frames_; + + float *array_; + size_t array_size_; + MediaSegmentSet segments_; + MediaSegmentSet::iterator current_segment_; + +}; + +#endif // TIMELINE_H