diff --git a/MediaPlayer.cpp b/MediaPlayer.cpp index cac81a2..88cf80d 100644 --- a/MediaPlayer.cpp +++ b/MediaPlayer.cpp @@ -1,24 +1,19 @@ -#include "MediaPlayer.h" -#include #include using namespace std; +// Desktop OpenGL function loader +#include + + // vmix #include "defines.h" #include "Log.h" -#include "RenderingManager.h" #include "Resource.h" #include "Visitor.h" -#include "UserInterfaceManager.h" #include "SystemToolkit.h" -#include "GstToolkit.h" -// Desktop OpenGL function loader -#include - -// GStreamer -#include +#include "MediaPlayer.h" #ifndef NDEBUG #define MEDIA_PLAYER_DEBUG @@ -52,7 +47,6 @@ MediaPlayer::MediaPlayer(string name) : id_(name) frame_duration_ = GST_CLOCK_TIME_NONE; desired_state_ = GST_STATE_PAUSED; loop_ = LoopMode::LOOP_REWIND; - current_segment_ = segments_.begin(); // start index in frame_ stack write_index_ = 0; @@ -210,6 +204,9 @@ void MediaPlayer::execute_open() return; } + // create & init segment array + + // all good Log::Info("MediaPlayer %s Open %s (%s %d x %d)", id_.c_str(), uri_.c_str(), codec_name_.c_str(), width_, height_); ready_ = true; @@ -436,7 +433,7 @@ void MediaPlayer::rewind() } -void MediaPlayer::seekNextFrame() +void MediaPlayer::step() { // useful only when Paused if (!enabled_ || isPlaying()) @@ -449,7 +446,7 @@ void MediaPlayer::seekNextFrame() gst_element_send_event (pipeline_, gst_event_new_step (GST_FORMAT_BUFFERS, 1, ABS(rate_), TRUE, FALSE)); } -void MediaPlayer::seekTo(GstClockTime pos) +void MediaPlayer::seek(GstClockTime pos) { if (!enabled_ || !seekable_) return; @@ -460,54 +457,14 @@ void MediaPlayer::seekTo(GstClockTime pos) } -void MediaPlayer::fastForward() +void MediaPlayer::jump() { - if (!enabled_ || !seekable_) + if (!enabled_ || !isPlaying()) return; gst_element_send_event (pipeline_, gst_event_new_step (GST_FORMAT_BUFFERS, 1, 30.f * ABS(rate_), TRUE, FALSE)); } -bool MediaPlayer::addPlaySegment(GstClockTime begin, GstClockTime end) -{ - return addPlaySegment( MediaSegment(begin, end) ); -} - -bool MediaPlayer::addPlaySegment(MediaSegment s) -{ - if ( s.is_valid() ) - return segments_.insert(s).second; - - return false; -} - -bool MediaPlayer::removeAllPlaySegmentOverlap(MediaSegment s) -{ - bool ret = removePlaySegmentAt(s.begin); - return removePlaySegmentAt(s.end) || ret; -} - -bool MediaPlayer::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 > MediaPlayer::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; -} - void MediaPlayer::init_texture(guint index) { glActiveTexture(GL_TEXTURE0); @@ -695,6 +652,12 @@ void MediaPlayer::update() execute_loop_command(); } + // manage timeline +// if (position_!=GST_CLOCK_TIME_NONE) { + + +// } + } @@ -1055,12 +1018,12 @@ void MediaPlayer::callback_discoverer_finished(GstDiscoverer *discoverer, MediaP } } -TimeCounter::TimeCounter() { +MediaPlayer::TimeCounter::TimeCounter() { reset(); } -void TimeCounter::tic () +void MediaPlayer::TimeCounter::tic () { // how long since last time GstClockTime t = gst_util_get_timestamp (); @@ -1083,7 +1046,7 @@ void TimeCounter::tic () } } -GstClockTime TimeCounter::dt () +GstClockTime MediaPlayer::TimeCounter::dt () { GstClockTime t = gst_util_get_timestamp (); GstClockTime dt = t - tic_time; @@ -1093,7 +1056,7 @@ GstClockTime TimeCounter::dt () return dt; } -void TimeCounter::reset () +void MediaPlayer::TimeCounter::reset () { last_time = gst_util_get_timestamp ();; tic_time = last_time; @@ -1101,7 +1064,7 @@ void TimeCounter::reset () fps = 0.0; } -double TimeCounter::frameRate() const +double MediaPlayer::TimeCounter::frameRate() const { return fps; } diff --git a/MediaPlayer.h b/MediaPlayer.h index dd628c6..ad54849 100644 --- a/MediaPlayer.h +++ b/MediaPlayer.h @@ -2,14 +2,14 @@ #define __GST_MEDIA_PLAYER_H_ #include -#include -#include -#include #include +// GStreamer +#include #include #include +#include "Timeline.h" // Forward declare classes referenced class Visitor; @@ -18,81 +18,13 @@ class Visitor; #define MIN_PLAY_SPEED 0.1 #define N_VFRAME 3 -struct TimeCounter { - - GstClockTime last_time; - GstClockTime tic_time; - int nbFrames; - gdouble fps; -public: - TimeCounter(); - GstClockTime dt(); - void tic(); - void reset(); - gdouble frameRate() const; -}; - -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 MediaPlayer { public: /** - * Constructor of a GStreamer Media + * Constructor of a GStreamer Media Player */ MediaPlayer( std::string name = std::string() ); /** @@ -103,6 +35,14 @@ public: * Open a media using gstreamer URI * */ void open( std::string path); + /** + * Get name of the media + * */ + std::string uri() const; + /** + * Get name of the file + * */ + std::string filename() const; /** * True if a media was oppenned * */ @@ -120,19 +60,24 @@ public: * Must be called in update loop * */ void update(); - void update_old(); - + /** + * Enable / Disable + * Suspend playing activity + * (restores playing state when re-enabled) + * */ void enable(bool on); - + /** + * True if enabled + * */ bool isEnabled() const; - /** * Pause / Play * Can play backward if play speed is negative * */ void play(bool on); /** - * Get Pause / Play + * Get Pause / Play status + * Performs a full check of the Gstreamer pipeline if testpipeline is true * */ bool isPlaying(bool testpipeline = false) const; /** @@ -146,36 +91,42 @@ public: * */ void setPlaySpeed(double s); /** - * True if the player will loop when at begin or end + * Loop Mode: Behavior when reaching an extremity * */ typedef enum { LOOP_NONE = 0, LOOP_REWIND = 1, LOOP_BIDIRECTIONAL = 2 } LoopMode; + /** + * Get the current loop mode + * */ LoopMode loop() const; /** - * Set the player to loop + * Set the loop mode * */ void setLoop(LoopMode mode); - /** - * Restart from zero - * */ - void rewind(); /** * Seek to next frame when paused + * (aka next frame) * Can go backward if play speed is negative * */ - void seekNextFrame(); + void step(); + /** + * Jump fast when playing + * (aka fast-forward) + * Can go backward if play speed is negative + * */ + void jump(); + /** + * Seek to zero + * */ + void rewind(); /** * Seek to any position in media * pos in nanoseconds. * */ - void seekTo(GstClockTime pos); - /** - * Jump by 10% of the duration - * */ - void fastForward(); + void seek(GstClockTime pos); /** * Get position time * */ @@ -192,38 +143,39 @@ public: * Get framerate of the media * */ double frameRate() const; - /** - * Get name of Codec of the media - * */ - std::string codec() const; /** * Get rendering update framerate * measured during play * */ double updateFrameRate() const; + /** + * Get name of Codec of the media + * */ + std::string codec() const; + /** + * Get frame width + * */ + guint width() const; + /** + * Get frame height + * */ + guint height() const; + /** + * Get frames displayt aspect ratio + * NB: can be different than width() / height() + * */ + float aspectRatio() const; /** * Get the OpenGL texture * Must be called in OpenGL context * */ guint texture() const; - /** - * Get Image properties - * */ - guint width() const; - guint height() const; - float aspectRatio() const; - - /** - * Get name of the media - * */ - std::string uri() const; - std::string filename() const; /** * Accept visitors + * Used for saving session file * */ void accept(Visitor& v); - /** * @brief registered * @return list of media players currently registered @@ -234,12 +186,7 @@ public: private: - bool addPlaySegment(GstClockTime begin, GstClockTime end); - bool addPlaySegment(MediaSegment s); - bool removePlaySegmentAt(GstClockTime t); - bool removeAllPlaySegmentOverlap(MediaSegment s); - std::list< std::pair > getPlaySegments() const; - + // video player description std::string id_; std::string filename_; std::string uri_; @@ -254,7 +201,6 @@ private: GstClockTime frame_duration_; gdouble rate_; LoopMode loop_; - TimeCounter timecount_; gdouble framerate_; GstState desired_state_; GstElement *pipeline_; @@ -263,6 +209,30 @@ private: std::string codec_name_; GstVideoInfo v_frame_video_info_; + // status + bool ready_; + bool failed_; + bool seekable_; + bool isimage_; + bool interlaced_; + bool enabled_; + + // fps counter + struct TimeCounter { + + GstClockTime last_time; + GstClockTime tic_time; + int nbFrames; + gdouble fps; + public: + TimeCounter(); + GstClockTime dt(); + void tic(); + void reset(); + gdouble frameRate() const; + }; + TimeCounter timecount_; + // frame stack typedef enum { EMPTY = 0, @@ -293,16 +263,7 @@ private: guint pbo_index_, pbo_next_index_; guint pbo_size_; - MediaSegmentSet segments_; - MediaSegmentSet::iterator current_segment_; - - bool ready_; - bool failed_; - bool seekable_; - bool isimage_; - bool interlaced_; - bool enabled_; - + // gst pipeline control void execute_open(); void execute_loop_command(); void execute_seek_command(GstClockTime target = GST_CLOCK_TIME_NONE); @@ -311,13 +272,15 @@ private: void init_texture(guint index); void fill_texture(guint index); bool fill_frame(GstBuffer *buf, FrameStatus status); + + // gst callbacks static void callback_end_of_stream (GstAppSink *, gpointer); static GstFlowReturn callback_new_preroll (GstAppSink *, gpointer ); static GstFlowReturn callback_new_sample (GstAppSink *, gpointer); - static void callback_discoverer_process (GstDiscoverer *discoverer, GstDiscovererInfo *info, GError *err, MediaPlayer *m); static void callback_discoverer_finished(GstDiscoverer *discoverer, MediaPlayer *m); + // global list of registered media player static std::list registered_; };