#include #include #include #include "Pixels.h" #include "ofUtils.h" enum ofLoopType{ OF_LOOP_NONE=0x01, OF_LOOP_PALINDROME=0x02, OF_LOOP_NORMAL=0x03 }; class ofGstAppSink; typedef struct _GstElement GstElement; typedef struct _GstBuffer GstBuffer; typedef struct _GstMessage GstMessage; class ofGstUtils{ public: ofGstUtils(); virtual ~ofGstUtils(); bool setPipelineWithSink(std::string pipeline, std::string sinkname="sink", bool isStream=false); bool setPipelineWithSink(GstElement * pipeline, GstElement * sink, bool isStream=false); void play(); void stop(); void setPaused(bool bPause); bool isPaused(){return bPaused;} bool isLoaded(){return bLoaded;} bool isPlaying(){return bPlaying;} float getPosition(); float getSpeed(); float getDuration(); int64_t getDurationNanos(); bool getIsMovieDone(); void setPosition(float pct); void setVolume(float volume); void setLoopState(ofLoopType state); ofLoopType getLoopState(){return loopMode;} void setSpeed(float speed); void setFrameByFrame(bool bFrameByFrame); bool isFrameByFrame(); GstElement * getPipeline(); GstElement * getSink(); unsigned long getMinLatencyNanos(); unsigned long getMaxLatencyNanos(); virtual void close(); void setSinkListener(ofGstAppSink * appsink); // callbacks to get called from gstreamer virtual GstFlowReturn preroll_cb(GstBuffer * buffer); virtual GstFlowReturn buffer_cb(GstBuffer * buffer); virtual void eos_cb(); static void startGstMainLoop(); void update(); protected: ofGstAppSink * appsink; bool isStream; private: void gstHandleMessage(); //void update(ofEventArgs & args); bool startPipeline(); bool bPlaying; bool bPaused; bool bIsMovieDone; bool bLoaded; bool bFrameByFrame; ofLoopType loopMode; GstElement * gstSink; GstElement * gstPipeline; float speed; int64_t durationNanos; bool isAppSink; }; class ofGstVideoUtils: public ofGstUtils{ public: ofGstVideoUtils(); virtual ~ofGstVideoUtils(); bool setPipeline(std::string pipeline, int bpp=24, bool isStream=false, int w=-1, int h=-1); bool allocate(int w, int h, int bpp); bool isFrameNew(); unsigned char * getPixels(); //ofPixelsRef getPixelsRef(); float getHeight(); float getWidth(); void close(); void update(); protected: GstFlowReturn preroll_cb(GstBuffer * buffer); GstFlowReturn buffer_cb(GstBuffer * buffer); void eos_cb(); Pixels pixels; Pixels backPixels; //ofPixels pixels; // 24 bit: rgb //ofPixels backPixels; //ofPixels eventPixels; private: bool bIsFrameNew; // if we are new bool bHavePixelsChanged; bool bBackPixelsChanged; //ofMutex mutex; GstBuffer * buffer, *prevBuffer; }; //------------------------------------------------- //----------------------------------------- appsink listener //------------------------------------------------- class ofGstAppSink{ public: virtual GstFlowReturn on_preroll(GstBuffer * buffer){ return GST_FLOW_OK; } virtual GstFlowReturn on_buffer(GstBuffer * buffer){ return GST_FLOW_OK; } virtual void on_eos(){} // return true to set the message as attended so upstream doesn't try to process it virtual bool on_message(GstMessage* msg){return false;}; // pings when enough data has arrived to be able to get sink properties virtual void on_stream_prepared(){}; }; class ofGstVideoPlayer: public ofGstAppSink{ public: ofGstVideoPlayer(); ~ofGstVideoPlayer(); /// needs to be called before loadMovie //bool setPixelFormat(ofPixelFormat pixelFormat); //ofPixelFormat getPixelFormat(); bool loadMovie(string uri); void update(); int getCurrentFrame(); int getTotalNumFrames(); void firstFrame(); void nextFrame(); void previousFrame(); void setFrame(int frame); // frame 0 = first frame... bool isStream(); void play(); void stop(); void setPaused(bool bPause); bool isPaused(); bool isLoaded(); bool isPlaying(); float getPosition(); float getSpeed(); float getDuration(); bool getIsMovieDone(); void setPosition(float pct); void setVolume(float volume); void setLoopState(ofLoopType state); ofLoopType getLoopState(); void setSpeed(float speed); void close(); bool isFrameNew(); unsigned char * getPixels(); //ofPixelsRef getPixelsRef(); float getHeight(); float getWidth(); void setFrameByFrame(bool frameByFrame); void setThreadAppSink(bool threaded); ofGstVideoUtils * getGstVideoUtils(); protected: bool allocate(int bpp); void on_stream_prepared(); // return true to set the message as attended so upstream doesn't try to process it virtual bool on_message(GstMessage* msg){return false;}; private: //ofPixelFormat internalPixelFormat; guint64 nFrames; int fps_n, fps_d; bool bIsStream; bool bIsAllocated; bool threadAppSink; ofGstVideoUtils videoUtils; };