diff options
Diffstat (limited to 'rotord/gstvideoloader.cpp')
| -rw-r--r-- | rotord/gstvideoloader.cpp | 1142 |
1 files changed, 0 insertions, 1142 deletions
diff --git a/rotord/gstvideoloader.cpp b/rotord/gstvideoloader.cpp deleted file mode 100644 index 9d04daa..0000000 --- a/rotord/gstvideoloader.cpp +++ /dev/null @@ -1,1142 +0,0 @@ -#include "gstvideoloader.h" - - - -using namespace std; - - - -void ofGstUtils::startGstMainLoop(){ - static bool initialized = false; - if(!initialized){ - g_main_loop_new (NULL, FALSE); - initialized=true; - } -} - -//------------------------------------------------- -//----------------------------------------- gstUtils -//------------------------------------------------- - -static bool plugin_registered = false; -static bool gst_inited = false; - - -// called when the appsink notifies us that there is a new buffer ready for -// processing - -static GstFlowReturn on_new_buffer_from_source (GstAppSink * elt, void * data){ - GstBuffer *buffer = gst_app_sink_pull_buffer (GST_APP_SINK (elt)); - return ((ofGstUtils*)data)->buffer_cb(buffer); -} - -static GstFlowReturn on_new_preroll_from_source (GstAppSink * elt, void * data){ - GstBuffer *buffer = gst_app_sink_pull_preroll(GST_APP_SINK (elt)); - return ((ofGstUtils*)data)->preroll_cb(buffer); -} - -static void on_eos_from_source (GstAppSink * elt, void * data){ - ((ofGstUtils*)data)->eos_cb(); -} - -static gboolean appsink_plugin_init (GstPlugin * plugin) -{ - gst_element_register (plugin, "appsink", GST_RANK_NONE, GST_TYPE_APP_SINK); - - return TRUE; -} - - -ofGstUtils::ofGstUtils() { - bLoaded = false; - speed = 1; - bPaused = false; - bIsMovieDone = false; - bPlaying = false; - loopMode = OF_LOOP_NONE; - bFrameByFrame = false; - - gstPipeline = NULL; - gstSink = NULL; - - durationNanos = 0; - - isAppSink = false; - isStream = false; - - appsink = NULL; - - if(!g_thread_supported()){ - g_thread_init(NULL); - } - if(!gst_inited){ - gst_init (NULL, NULL); - gst_inited=true; - cerr <<"ofGstUtils: gstreamer inited"<<endl; - } - if(!plugin_registered){ - gst_plugin_register_static(GST_VERSION_MAJOR, GST_VERSION_MINOR, - "appsink", (char*)"Element application sink", - appsink_plugin_init, "0.1", "LGPL", "gstvideoloader", "Rotor", - "http://rotored.com/"); - plugin_registered=true; - } - -} - -ofGstUtils::~ofGstUtils() { - close(); -} - -GstFlowReturn ofGstUtils::preroll_cb(GstBuffer * buffer){ - bIsMovieDone = false; - if(appsink) return appsink->on_preroll(buffer); - else return GST_FLOW_OK; -} - -GstFlowReturn ofGstUtils::buffer_cb(GstBuffer * buffer){ - bIsMovieDone = false; - if(appsink) return appsink->on_buffer(buffer); - else return GST_FLOW_OK; -} - -void ofGstUtils::eos_cb(){ - bIsMovieDone = true; - if(appsink) appsink->on_eos(); -} - -bool ofGstUtils::setPipelineWithSink(string pipeline, string sinkname, bool isStream){ - ofGstUtils::startGstMainLoop(); - - gchar* pipeline_string = - g_strdup((pipeline).c_str()); - - GError * error = NULL; - gstPipeline = gst_parse_launch (pipeline_string, &error); - - cerr << "gstreamer pipeline: " <<pipeline_string<<endl; - if(error!=NULL){ - cerr <<"couldnt create pipeline: " << string(error->message)<<endl; - return false; - } - - gstSink = gst_bin_get_by_name(GST_BIN(gstPipeline),sinkname.c_str()); - - if(!gstSink){ - cerr << "couldn't get sink from string pipeline"<<endl; - } - - return setPipelineWithSink(gstPipeline,gstSink,isStream); -} - -bool ofGstUtils::setPipelineWithSink(GstElement * pipeline, GstElement * sink, bool isStream_){ - ofGstUtils::startGstMainLoop(); - - gstPipeline = pipeline; - gstSink = sink; - isStream = isStream_; - - if(gstSink){ - gst_base_sink_set_sync(GST_BASE_SINK(gstSink), true); - } - - if(gstSink && string(gst_plugin_feature_get_name( GST_PLUGIN_FEATURE(gst_element_get_factory(gstSink))))=="appsink"){ - isAppSink = true; - }else{ - isAppSink = false; - } - - return startPipeline(); -} - -void ofGstUtils::setFrameByFrame(bool _bFrameByFrame){ - bFrameByFrame = _bFrameByFrame; - if(gstSink){ - g_object_set (G_OBJECT (gstSink), "sync", !bFrameByFrame, (void*)NULL); - } -} - -bool ofGstUtils::isFrameByFrame(){ - return bFrameByFrame; -} - -bool ofGstUtils::startPipeline(){ - - bPaused = true; - speed = 1.0f; - - - if(gst_element_set_state (GST_ELEMENT(gstPipeline), GST_STATE_READY) == GST_STATE_CHANGE_FAILURE) { - cerr<< "GStreamer: unable to set pipeline to ready\n"; - - return false; - } - if(gst_element_get_state (GST_ELEMENT(gstPipeline), NULL, NULL, 10 * GST_SECOND)==GST_STATE_CHANGE_FAILURE){ - cerr<< "GStreamer: unable to get pipeline to ready\n"; - return false; - } - - // pause the pipeline - if(gst_element_set_state(GST_ELEMENT(gstPipeline), GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) { - cerr<< "GStreamer: unable to set pipeline to paused\n"; - - return false; - } - - // wait for paused state to query the duration - if(!isStream){ - GstState state = GST_STATE_PAUSED; - if(gst_element_get_state(gstPipeline,&state,NULL,2*GST_SECOND)==GST_STATE_CHANGE_FAILURE){ - cerr<< "GStreamer: unable to get pipeline to paused\n"; - return false; - } - bPlaying = true; - bLoaded = true; - } - - - - if(isAppSink){ - cerr << "attaching callbacks\n"; - // set the appsink to not emit signals, we are using callbacks instead - // and frameByFrame to get buffers by polling instead of callback - g_object_set (G_OBJECT (gstSink), "emit-signals", FALSE, "sync", !bFrameByFrame, (void*)NULL); - - if(!bFrameByFrame){ - GstAppSinkCallbacks gstCallbacks; - gstCallbacks.eos = &on_eos_from_source; - gstCallbacks.new_preroll = &on_new_preroll_from_source; - gstCallbacks.new_buffer = &on_new_buffer_from_source; - - gst_app_sink_set_callbacks(GST_APP_SINK(gstSink), &gstCallbacks, this, NULL); - } - - } - - if(!isStream){ - setSpeed(1.0); - } - - //ofAddListener(ofEvents().update,this,&ofGstUtils::update); - - return true; -} - -void ofGstUtils::play(){ - setPaused(false); - - //this is if we set the speed first but it only can be set when we are playing. - if(!isStream) setSpeed(speed); -} - -void ofGstUtils::setPaused(bool _bPause){ - bPaused = _bPause; - //timeLastIdle = ofGetElapsedTimeMillis(); - if(bLoaded){ - if(bPlaying){ - if(bPaused){ - gst_element_set_state (gstPipeline, GST_STATE_PAUSED); - }else{ - gst_element_set_state (gstPipeline, GST_STATE_PLAYING); - } - }else{ - GstState state = GST_STATE_PAUSED; - gst_element_set_state (gstPipeline, state); - gst_element_get_state(gstPipeline,&state,NULL,2*GST_SECOND); - if(!bPaused){ - gst_element_set_state (gstPipeline, GST_STATE_PLAYING); - } - bPlaying = true; - } - } -} - -void ofGstUtils::stop(){ - if(!bPlaying) return; - GstState state = GST_STATE_PAUSED; - if(!bPaused){ - gst_element_set_state (gstPipeline, state); - gst_element_get_state(gstPipeline,&state,NULL,2*GST_SECOND); - } - state = GST_STATE_READY; - gst_element_set_state (gstPipeline, state); - gst_element_get_state(gstPipeline,&state,NULL,2*GST_SECOND); - bPlaying = false; - bPaused = true; -} - -float ofGstUtils::getPosition(){ - if(gstPipeline){ - gint64 pos=0; - GstFormat format=GST_FORMAT_TIME; - if(!gst_element_query_position(GST_ELEMENT(gstPipeline),&format,&pos)){ - cerr<<"GStreamer: cannot query position\n"; - return -1; - } - return (float)pos/(float)durationNanos; - }else{ - return -1; - } -} - -float ofGstUtils::getSpeed(){ - return speed; -} - -float ofGstUtils::getDuration(){ - return (float)getDurationNanos()/(float)GST_SECOND; -} - -int64_t ofGstUtils::getDurationNanos(){ - GstFormat format = GST_FORMAT_TIME; - - if(!gst_element_query_duration(getPipeline(),&format,&durationNanos)) - cerr<<"GStreamer: cannot query time duration\n"; - - return durationNanos; - -} -bool ofGstUtils::getIsMovieDone(){ - if(isAppSink){ - return gst_app_sink_is_eos(GST_APP_SINK(gstSink)); - }else{ - return bIsMovieDone; - } -} - -void ofGstUtils::setPosition(float pct){ - //pct = CLAMP(pct, 0,1);// check between 0 and 1; - GstFormat format = GST_FORMAT_TIME; - GstSeekFlags flags = (GstSeekFlags) (GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_FLUSH); - gint64 pos = (guint64)((double)pct*(double)durationNanos); - - /*if(bPaused){ - seek_lock(); - gst_element_set_state (gstPipeline, GST_STATE_PLAYING); - posChangingPaused=true; - seek_unlock(); - }*/ - if(speed>0){ - if(!gst_element_seek(GST_ELEMENT(gstPipeline),speed, format, - flags, - GST_SEEK_TYPE_SET, - pos, - GST_SEEK_TYPE_SET, - -1)) { - cerr<<"GStreamer: unable to seek\n"; - } - }else{ - if(!gst_element_seek(GST_ELEMENT(gstPipeline),speed, format, - flags, - GST_SEEK_TYPE_SET, - 0, - GST_SEEK_TYPE_SET, - pos)) { - cerr<<"GStreamer: unable to seek\n"; - } - } -} - -void ofGstUtils::setVolume(float volume){ - gdouble gvolume = volume; - g_object_set(G_OBJECT(gstPipeline), "volume", gvolume, (void*)NULL); -} - -void ofGstUtils::setLoopState(ofLoopType state){ - loopMode = state; -} - -void ofGstUtils::setSpeed(float _speed){ - GstFormat format = GST_FORMAT_TIME; - GstSeekFlags flags = (GstSeekFlags) (GST_SEEK_FLAG_SKIP | GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_FLUSH); - gint64 pos; - - if(_speed==0){ - gst_element_set_state (gstPipeline, GST_STATE_PAUSED); - return; - } - - if(!gst_element_query_position(GST_ELEMENT(gstPipeline),&format,&pos) || pos<0){ - //ofLog(OF_LOG_ERROR,"GStreamer: cannot query position"); - return; - } - - speed = _speed; - //pos = (float)gstData.lastFrame * (float)fps_d / (float)fps_n * GST_SECOND; - - if(!bPaused) - gst_element_set_state (gstPipeline, GST_STATE_PLAYING); - - if(speed>0){ - if(!gst_element_seek(GST_ELEMENT(gstPipeline),speed, format, - flags, - GST_SEEK_TYPE_SET, - pos, - GST_SEEK_TYPE_SET, - -1)) { - cerr<<"GStreamer: unable to change speed\n"; - } - }else{ - if(!gst_element_seek(GST_ELEMENT(gstPipeline),speed, format, - flags, - GST_SEEK_TYPE_SET, - 0, - GST_SEEK_TYPE_SET, - pos)) { - cerr<<"GStreamer: unable to change speed\n"; - } - } - - cerr<<"Gstreamer: speed change to "<< speed<<endl; - -} - -void ofGstUtils::close(){ - if(bPlaying){ - stop(); - } - if(bLoaded){ - gst_element_set_state(GST_ELEMENT(gstPipeline), GST_STATE_NULL); - gst_element_get_state(gstPipeline,NULL,NULL,2*GST_SECOND); - // gst_object_unref(gstSink); this crashes, why?? - - //ofEventArgs args; - //update(args); - - gst_object_unref(gstPipeline); - gstPipeline = NULL; - gstSink = NULL; - } - - bLoaded = false; - //ofRemoveListener(ofEvents().update,this,&ofGstUtils::update); -} - -static string getName(GstState state){ - switch(state){ - case GST_STATE_VOID_PENDING: - return "void pending"; - case GST_STATE_NULL: - return "null"; - case GST_STATE_READY: - return "ready"; - case GST_STATE_PAUSED: - return "paused"; - case GST_STATE_PLAYING: - return "playing"; - default: - return ""; - } -} - -void ofGstUtils::update(){ //ofEventArgs & args){ - gstHandleMessage(); -} - -void ofGstUtils::gstHandleMessage(){ - GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(gstPipeline)); - while(gst_bus_have_pending(bus)) { - GstMessage* msg = gst_bus_pop(bus); - if(appsink && appsink->on_message(msg)) continue; - - cerr << "GStreamer: Got " << GST_MESSAGE_TYPE_NAME(msg) << " message from " << GST_MESSAGE_SRC_NAME(msg)<<endl; - - switch (GST_MESSAGE_TYPE (msg)) { - - case GST_MESSAGE_BUFFERING: - gint pctBuffered; - gst_message_parse_buffering(msg,&pctBuffered); - cerr<<"GStreamer: buffering"<<pctBuffered<<endl; - /*if(pctBuffered<100){ - gst_element_set_state (gstPipeline, GST_STATE_PAUSED); - }else if(!bPaused){ - gst_element_set_state (gstPipeline, GST_STATE_PLAYING); - }*/ - break; - - case GST_MESSAGE_DURATION:{ - GstFormat format=GST_FORMAT_TIME; - gst_element_query_duration(gstPipeline,&format,&durationNanos); - }break; - - case GST_MESSAGE_STATE_CHANGED:{ - GstState oldstate, newstate, pendstate; - gst_message_parse_state_changed(msg, &oldstate, &newstate, &pendstate); - if(isStream && newstate==GST_STATE_PAUSED && !bPlaying ){ - bLoaded = true; - bPlaying = true; - if(!bPaused){ - cout << "setting stream pipeline to play " << endl; - play(); - } - } - cerr << "GStreamer: " << GST_MESSAGE_SRC_NAME(msg) << " state changed from " << getName(oldstate) + " to " + getName(newstate) + " (" + getName(pendstate) + ")"; - }break; - - case GST_MESSAGE_ASYNC_DONE: - cerr<<"GStreamer: async done"<<endl; - break; - - case GST_MESSAGE_ERROR: { - GError *err; - gchar *debug; - gst_message_parse_error(msg, &err, &debug); - - cerr<<"GStreamer Plugin: Embedded video playback halted; module "<<gst_element_get_name(GST_MESSAGE_SRC (msg))<< "reported: "<<err->message<<endl; - - g_error_free(err); - g_free(debug); - - gst_element_set_state(GST_ELEMENT(gstPipeline), GST_STATE_NULL); - - }break; - - case GST_MESSAGE_EOS: - cerr<<"GStreamer: end of the stream.\n"; - bIsMovieDone = true; - - if(appsink && !isAppSink) appsink->on_eos(); - - switch(loopMode){ - - case OF_LOOP_NORMAL:{ - GstFormat format = GST_FORMAT_TIME; - GstSeekFlags flags = (GstSeekFlags) (GST_SEEK_FLAG_FLUSH |GST_SEEK_FLAG_KEY_UNIT); - gint64 pos; - gst_element_query_position(GST_ELEMENT(gstPipeline),&format,&pos); - - if(!gst_element_seek(GST_ELEMENT(gstPipeline), - speed, - format, - flags, - GST_SEEK_TYPE_SET, - 0, - GST_SEEK_TYPE_SET, - durationNanos)) { - cerr<<"GStreamer: unable to seek\n"; - } - }break; - - case OF_LOOP_PALINDROME:{ - GstFormat format = GST_FORMAT_TIME; - GstSeekFlags flags = (GstSeekFlags) (GST_SEEK_FLAG_FLUSH |GST_SEEK_FLAG_KEY_UNIT); - gint64 pos; - gst_element_query_position(GST_ELEMENT(gstPipeline),&format,&pos); - float loopSpeed; - if(pos>0) - loopSpeed=-speed; - else - loopSpeed=speed; - if(!gst_element_seek(GST_ELEMENT(gstPipeline), - loopSpeed, - GST_FORMAT_UNDEFINED, - flags, - GST_SEEK_TYPE_NONE, - 0, - GST_SEEK_TYPE_NONE, - 0)) { - cerr<<"GStreamer: unable to seek\n"; - } - }break; - - default: - break; - } - - break; - - default: - cerr << "GStreamer: unhandled message from " << GST_MESSAGE_SRC_NAME(msg)<<endl; - break; - } - gst_message_unref(msg); - } - - gst_object_unref(GST_OBJECT(bus)); -} - -GstElement * ofGstUtils::getPipeline(){ - return gstPipeline; -} - -GstElement * ofGstUtils::getSink(){ - return gstSink; -} - -void ofGstUtils::setSinkListener(ofGstAppSink * appsink_){ - appsink = appsink_; -} - -unsigned long ofGstUtils::getMinLatencyNanos(){ - GstClockTime minlat, maxlat; - GstQuery * q = gst_query_new_latency(); - if (gst_element_query (gstPipeline, q)) { - gboolean live; - gst_query_parse_latency (q, &live, &minlat, &maxlat); - } - gst_query_unref (q); - return minlat; -} - -unsigned long ofGstUtils::getMaxLatencyNanos(){ - GstClockTime minlat, maxlat; - GstQuery * q = gst_query_new_latency(); - if (gst_element_query (gstPipeline, q)) { - gboolean live; - gst_query_parse_latency (q, &live, &minlat, &maxlat); - } - gst_query_unref (q); - return maxlat; -} - - - -//------------------------------------------------- -//----------------------------------------- videoUtils -//------------------------------------------------- - -ofGstVideoUtils::ofGstVideoUtils(){ - bIsFrameNew = false; - bHavePixelsChanged = false; - bBackPixelsChanged = false; - buffer = 0; - prevBuffer = 0; -} - -ofGstVideoUtils::~ofGstVideoUtils(){ - close(); -} - -void ofGstVideoUtils::close(){ - ofGstUtils::close(); - //Poco::ScopedLock<ofMutex> lock(mutex); - pixels.clear(); - backPixels.clear(); - bIsFrameNew = false; - bHavePixelsChanged = false; - bBackPixelsChanged = false; - if(prevBuffer) gst_buffer_unref (prevBuffer); - if(buffer) gst_buffer_unref (buffer); - prevBuffer = 0; - buffer = 0; -} - -bool ofGstVideoUtils::isFrameNew(){ - return bIsFrameNew; -} - -unsigned char * ofGstVideoUtils::getPixels(){ - return pixels.getPixels(); -} - -/* -ofPixelsRef ofGstVideoUtils::getPixelsRef(){ - return pixels; -} -*/ - -void ofGstVideoUtils::update(){ - if (isLoaded()){ - if(!isFrameByFrame()){ - //mutex.lock(); - bHavePixelsChanged = bBackPixelsChanged; - if (bHavePixelsChanged){ - bBackPixelsChanged=false; - pixels.swap(backPixels); - if(prevBuffer) gst_buffer_unref (prevBuffer); - prevBuffer = buffer; - } - - //mutex.unlock(); - }else{ - GstBuffer *buffer; - - //get the buffer from appsink - if(isPaused()) buffer = gst_app_sink_pull_preroll (GST_APP_SINK (getSink())); - else buffer = gst_app_sink_pull_buffer (GST_APP_SINK (getSink())); - - if(buffer){ - if(pixels.isAllocated()){ - if(prevBuffer) gst_buffer_unref (prevBuffer); - //memcpy (pixels.getPixels(), GST_BUFFER_DATA (buffer), size); - pixels.setFromExternalPixels(GST_BUFFER_DATA (buffer),pixels.getWidth(),pixels.getHeight(),pixels.getNumChannels()); - prevBuffer = buffer; - bHavePixelsChanged=true; - } - } - } - }else{ - cerr<<"ofGstVideoUtils not loaded\n"; - } - bIsFrameNew = bHavePixelsChanged; - bHavePixelsChanged = false; -} - -float ofGstVideoUtils::getHeight(){ - return pixels.getHeight(); -} - -float ofGstVideoUtils::getWidth(){ - return pixels.getWidth(); -} - -bool ofGstVideoUtils::setPipeline(string pipeline, int bpp, bool isStream, int w, int h){ - string caps; - if(bpp==8) - caps="video/x-raw-gray, depth=8, bpp=8"; - else if(bpp==32) - caps="video/x-raw-rgb, depth=24, bpp=32, endianness=4321, red_mask=0xff0000, green_mask=0x00ff00, blue_mask=0x0000ff, alpha_mask=0x000000ff"; - else - caps="video/x-raw-rgb, depth=24, bpp=24, endianness=4321, red_mask=0xff0000, green_mask=0x00ff00, blue_mask=0x0000ff, alpha_mask=0x000000ff"; - - if(w!=-1 && h!=-1){ - caps+=", width=" + ofToString(w) + ", height=" + ofToString(h); - } - - gchar* pipeline_string = - g_strdup((pipeline + " ! appsink name=ofappsink caps=\"" + caps + "\"").c_str()); // caps=video/x-raw-rgb - - if((isStream && (w==-1 || h==-1)) || allocate(w,h,bpp)){ - return setPipelineWithSink(pipeline_string,"ofappsink",isStream); - }else{ - return false; - } -} - -bool ofGstVideoUtils::allocate(int w, int h, int _bpp){ - pixels.allocate(w,h,_bpp/8); - backPixels.allocate(w,h,_bpp/8); - prevBuffer = 0; - pixels.set(0); - - bHavePixelsChanged = pixels.isAllocated(); - return pixels.isAllocated(); -} - -GstFlowReturn ofGstVideoUtils::preroll_cb(GstBuffer * _buffer){ - guint size; - - size = GST_BUFFER_SIZE (_buffer); - if(pixels.isAllocated() && pixels.getWidth()*pixels.getHeight()*pixels.getBytesPerPixel()!=(int)size){ - cerr << "on_preproll: error preroll buffer size: " << size<< "!= init size: " << (pixels.getWidth()*pixels.getHeight()*pixels.getBytesPerPixel()) << endl; - gst_buffer_unref (_buffer); - return GST_FLOW_ERROR; - } - //mutex.lock(); - if(bBackPixelsChanged && buffer) gst_buffer_unref (buffer); - if(pixels.isAllocated()){ - buffer = _buffer; - backPixels.setFromExternalPixels(GST_BUFFER_DATA (buffer),pixels.getWidth(),pixels.getHeight(),pixels.getNumChannels()); - //eventPixels.setFromExternalPixels(GST_BUFFER_DATA (buffer),pixels.getWidth(),pixels.getHeight(),pixels.getNumChannels()); - bBackPixelsChanged=true; - //mutex.unlock(); - //ofNotifyEvent(prerollEvent,eventPixels); - }else{ - if(isStream && appsink){ - appsink->on_stream_prepared(); - }else{ - cerr << "received a preroll without allocation\n"; - } - //mutex.unlock(); - } - return ofGstUtils::preroll_cb(_buffer); -} - -GstFlowReturn ofGstVideoUtils::buffer_cb(GstBuffer * _buffer){ - - guint size; - - size = GST_BUFFER_SIZE (_buffer); - if(pixels.isAllocated() && pixels.getWidth()*pixels.getHeight()*pixels.getBytesPerPixel()!=(int)size){ - cerr<<"on_preproll: error on new buffer, buffer size: " <<size<<"!= init size: "<<(pixels.getWidth()*pixels.getHeight()*pixels.getBytesPerPixel())<<endl; - gst_buffer_unref (_buffer); - return GST_FLOW_ERROR; - } - //mutex.lock(); - if(bBackPixelsChanged && buffer) gst_buffer_unref (buffer); - if(pixels.isAllocated()){ - buffer = _buffer; - backPixels.setFromExternalPixels(GST_BUFFER_DATA (buffer),pixels.getWidth(),pixels.getHeight(),pixels.getNumChannels()); - //eventPixels.setFromExternalPixels(GST_BUFFER_DATA (buffer),pixels.getWidth(),pixels.getHeight(),pixels.getNumChannels()); - bBackPixelsChanged=true; - //mutex.unlock(); - //ofNotifyEvent(bufferEvent,eventPixels); - }else{ - if(isStream && appsink){ - appsink->on_stream_prepared(); - }else{ - cerr<<"received a preroll without allocation\n"; - } - //mutex.unlock(); - } - - return ofGstUtils::buffer_cb(buffer); -} - -void ofGstVideoUtils::eos_cb(){ - ofGstUtils::eos_cb(); - //ofEventArgs args; - //ofNotifyEvent(eosEvent,args); -} - -ofGstVideoPlayer::ofGstVideoPlayer(){ - nFrames = 0; - //internalPixelFormat = OF_PIXELS_RGB; - bIsStream = false; - bIsAllocated = false; - threadAppSink = false; - videoUtils.setSinkListener(this); -} - -ofGstVideoPlayer::~ofGstVideoPlayer(){ - close(); -} - -bool ofGstVideoPlayer::loadMovie(string name){ - close(); - /* - if( name.find( "file://",0 ) != string::npos){ - bIsStream = false; - }else if( name.find( "://",0 ) == string::npos){ - name = "file://"+ofToDataPath(name,true); - bIsStream = false; - }else{ - bIsStream = true; - } - */ - cerr<<"loading "<<name<<endl; - - ofGstUtils::startGstMainLoop(); - -#if GST_VERSION_MAJOR==0 - GstElement * gstPipeline = gst_element_factory_make("playbin2","player"); -#else - GstElement * gstPipeline = gst_element_factory_make("playbin","player"); -#endif - g_object_set(G_OBJECT(gstPipeline), "uri", name.c_str(), (void*)NULL); - - // create the oF appsink for video rgb without sync to clock - GstElement * gstSink = gst_element_factory_make("appsink", "app_sink"); - - gst_base_sink_set_sync(GST_BASE_SINK(gstSink), true); - gst_app_sink_set_max_buffers(GST_APP_SINK(gstSink), 8); - gst_app_sink_set_drop (GST_APP_SINK(gstSink),true); - gst_base_sink_set_max_lateness (GST_BASE_SINK(gstSink), -1); - -#if GST_VERSION_MAJOR==0 - int bpp; - string mime; - /* - switch(internalPixelFormat){ - case OF_PIXELS_MONO: - mime = "video/x-raw-gray"; - bpp = 8; - break; - case OF_PIXELS_RGB: - mime = "video/x-raw-rgb"; - bpp = 24; - break; - case OF_PIXELS_RGBA: - case OF_PIXELS_BGRA: - mime = "video/x-raw-rgb"; - bpp = 32; - break; - default: - mime = "video/x-raw-rgb"; - bpp=24; - break; - } - */ - mime = "video/x-raw-rgb"; - bpp=24; - - - GstCaps *caps = gst_caps_new_simple(mime.c_str(), - "bpp", G_TYPE_INT, bpp, - "depth", G_TYPE_INT, 24, - "endianness",G_TYPE_INT,4321, - "red_mask",G_TYPE_INT,0xff0000, - "green_mask",G_TYPE_INT,0x00ff00, - "blue_mask",G_TYPE_INT,0x0000ff, - "alpha_mask",G_TYPE_INT,0x000000ff, - NULL); -#else - int bpp; - string mime="video/x-raw"; - string format; - /* - switch(internalPixelFormat){ - case OF_PIXELS_MONO: - format = "GRAY8"; - bpp = 8; - break; - case OF_PIXELS_RGB: - format = "RGB"; - bpp = 24; - break; - case OF_PIXELS_RGBA: - format = "RGBA"; - bpp = 32; - break; - case OF_PIXELS_BGRA: - format = "BGRA"; - bpp = 32; - break; - default: - format = "RGB"; - bpp=24; - break; - } - */ - format = "RGB"; - bpp=24; - - GstCaps *caps = gst_caps_new_simple(mime.c_str(), - "format", G_TYPE_STRING, format.c_str(), - /*"bpp", G_TYPE_INT, bpp, - "depth", G_TYPE_INT, 24, - "endianness",G_TYPE_INT,4321, - "red_mask",G_TYPE_INT,0xff0000, - "green_mask",G_TYPE_INT,0x00ff00, - "blue_mask",G_TYPE_INT,0x0000ff, - "alpha_mask",G_TYPE_INT,0x000000ff,*/ - NULL); -#endif - - - gst_app_sink_set_caps(GST_APP_SINK(gstSink), caps); - gst_caps_unref(caps); - - if(threadAppSink){ - GstElement * appQueue = gst_element_factory_make("queue","appsink_queue"); - g_object_set(G_OBJECT(appQueue), "leaky", 0, "silent", 1, (void*)NULL); - GstElement* appBin = gst_bin_new("app_bin"); - gst_bin_add(GST_BIN(appBin), appQueue); - GstPad* appQueuePad = gst_element_get_static_pad(appQueue, "sink"); - GstPad* ghostPad = gst_ghost_pad_new("app_bin_sink", appQueuePad); - gst_object_unref(appQueuePad); - gst_element_add_pad(appBin, ghostPad); - - gst_bin_add_many(GST_BIN(appBin), gstSink, NULL); - gst_element_link_many(appQueue, gstSink, NULL); - - g_object_set (G_OBJECT(gstPipeline),"video-sink",appBin,(void*)NULL); - }else{ - g_object_set (G_OBJECT(gstPipeline),"video-sink",gstSink,(void*)NULL); - } - - - videoUtils.setPipelineWithSink(gstPipeline,gstSink,bIsStream); - if(!bIsStream) return allocate(bpp); - else return true; -} - -void ofGstVideoPlayer::setThreadAppSink(bool threaded){ - threadAppSink = threaded; -} - - -bool ofGstVideoPlayer::allocate(int bpp){ - if(bIsAllocated) return true; - - guint64 durationNanos = videoUtils.getDurationNanos(); - - nFrames = 0; - if(GstPad* pad = gst_element_get_static_pad(videoUtils.getSink(), "sink")){ -#if GST_VERSION_MAJOR==0 - int width,height; - if(gst_video_get_size(GST_PAD(pad), &width, &height)){ - if(!videoUtils.allocate(width,height,bpp)) return false; - }else{ - cerr<<"GStreamer: cannot query width and height"<<endl; - return false; - } - - const GValue *framerate = gst_video_frame_rate(pad); - fps_n=0; - fps_d=0; - if(framerate && GST_VALUE_HOLDS_FRACTION (framerate)){ - fps_n = gst_value_get_fraction_numerator (framerate); - fps_d = gst_value_get_fraction_denominator (framerate); - nFrames = (float)(durationNanos / GST_SECOND) * (float)fps_n/(float)fps_d; - cerr<<"ofGstUtils: framerate:"<<fps_n<<"/"<<fps_d<<endl; - }else{ - cerr<<"Gstreamer: cannot get framerate, frame seek won't work"<<endl; - } - bIsAllocated = true; -#else - if(GstCaps *caps = gst_pad_get_current_caps (GST_PAD (pad))){ - GstVideoInfo info; - gst_video_info_init (&info); - if (gst_video_info_from_caps (&info, caps)){ - if(!videoUtils.allocate(info.width,info.height,bpp)) return false; - }else{ - cerr<<"GStreamer: cannot query width and height"<<endl; - return false; - } - - fps_n = info.fps_n; - fps_d = info.fps_d; - nFrames = (float)(durationNanos / GST_SECOND) * (float)fps_n/(float)fps_d; - gst_caps_unref(caps); - bIsAllocated = true; - }else{ - cerr<<"GStreamer: cannot get pipeline caps"<<endl; - bIsAllocated = false; - } -#endif - gst_object_unref(GST_OBJECT(pad)); - }else{ - cerr<<"GStreamer: cannot get sink pad"<<endl; - bIsAllocated = false; - } - - return bIsAllocated; -} - -void ofGstVideoPlayer::on_stream_prepared(){ - if(!bIsAllocated) allocate(24); -} - -int ofGstVideoPlayer::getCurrentFrame(){ - int frame = 0; - - // zach I think this may fail on variable length frames... - float pos = getPosition(); - if(pos == -1) return -1; - - - float framePosInFloat = ((float)getTotalNumFrames() * pos); - int framePosInInt = (int)framePosInFloat; - float floatRemainder = (framePosInFloat - framePosInInt); - if (floatRemainder > 0.5f) framePosInInt = framePosInInt + 1; - //frame = (int)ceil((getTotalNumFrames() * getPosition())); - frame = framePosInInt; - - return frame; -} - -int ofGstVideoPlayer::getTotalNumFrames(){ - return nFrames; -} - -void ofGstVideoPlayer::firstFrame(){ - setFrame(0); -} - -void ofGstVideoPlayer::nextFrame(){ - gint64 currentFrame = getCurrentFrame(); - if(currentFrame!=-1) setFrame(currentFrame + 1); -} - -void ofGstVideoPlayer::previousFrame(){ - gint64 currentFrame = getCurrentFrame(); - if(currentFrame!=-1) setFrame(currentFrame - 1); -} - -void ofGstVideoPlayer::setFrame(int frame){ // frame 0 = first frame... - float pct = (float)frame / (float)nFrames; - setPosition(pct); -} - -bool ofGstVideoPlayer::isStream(){ - return bIsStream; -} - -void ofGstVideoPlayer::update(){ - videoUtils.update(); -} - -void ofGstVideoPlayer::play(){ - videoUtils.play(); -} - -void ofGstVideoPlayer::stop(){ - videoUtils.stop(); -} - -void ofGstVideoPlayer::setPaused(bool bPause){ - videoUtils.setPaused(bPause); -} - -bool ofGstVideoPlayer::isPaused(){ - return videoUtils.isPaused(); -} - -bool ofGstVideoPlayer::isLoaded(){ - return videoUtils.isLoaded(); -} - -bool ofGstVideoPlayer::isPlaying(){ - return videoUtils.isPlaying(); -} - -float ofGstVideoPlayer::getPosition(){ - return videoUtils.getPosition(); -} - -float ofGstVideoPlayer::getSpeed(){ - return videoUtils.getSpeed(); -} - -float ofGstVideoPlayer::getDuration(){ - return videoUtils.getDuration(); -} - -bool ofGstVideoPlayer::getIsMovieDone(){ - return videoUtils.getIsMovieDone(); -} - -void ofGstVideoPlayer::setPosition(float pct){ - videoUtils.setPosition(pct); -} - -void ofGstVideoPlayer::setVolume(float volume){ - videoUtils.setVolume(volume); -} - -void ofGstVideoPlayer::setLoopState(ofLoopType state){ - videoUtils.setLoopState(state); -} - -ofLoopType ofGstVideoPlayer::getLoopState(){ - return videoUtils.getLoopState(); -} - -void ofGstVideoPlayer::setSpeed(float speed){ - videoUtils.setSpeed(speed); -} - -void ofGstVideoPlayer::close(){ - bIsAllocated = false; - videoUtils.close(); -} - -bool ofGstVideoPlayer::isFrameNew(){ - return videoUtils.isFrameNew(); -} - -unsigned char * ofGstVideoPlayer::getPixels(){ - return videoUtils.getPixels(); -} -/* -ofPixelsRef ofGstVideoPlayer::getPixelsRef(){ - return videoUtils.getPixelsRef(); -} -*/ -float ofGstVideoPlayer::getHeight(){ - return videoUtils.getHeight(); -} - -float ofGstVideoPlayer::getWidth(){ - return videoUtils.getWidth(); -} - -ofGstVideoUtils * ofGstVideoPlayer::getGstVideoUtils(){ - return &videoUtils; -} - -void ofGstVideoPlayer::setFrameByFrame(bool frameByFrame){ - videoUtils.setFrameByFrame(frameByFrame); -} - |
