static GstFlowReturn on_new_preroll_from_source (GstAppSink * elt, void * data) { guint size; GstBuffer *buffer; ofGstVideoData * gstData = (ofGstVideoData *) data; //get the buffer from appsink buffer = gst_app_sink_pull_preroll (GST_APP_SINK (elt)); size = GST_BUFFER_SIZE (buffer); /*if(size < data->width*data->height*3){ gst_buffer_unref (buffer); return; }*/ ofGstDataLock(gstData); if(gstData->pixels){ memcpy (gstData->pixels, GST_BUFFER_DATA (buffer), size); gstData->bHavePixelsChanged=true; } ofGstDataUnlock(gstData); /// we don't need the appsink buffer anymore gst_buffer_unref (buffer); return GST_FLOW_OK; }
bool ofGstUtils::startPipeline() { gstData.pipeline=gstPipeline; // pause the pipeline if(gst_element_set_state(GST_ELEMENT(gstPipeline), GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) { // ofLog(OF_LOG_ERROR, "GStreamer: unable to set pipeline to paused\n"); return false; } bool ret = false; if(!bIsStream) { ofGstDataLock(&gstData); ret = allocate(); ofGstDataUnlock(&gstData); } else { ret = true; } if(gstSink) { // set the appsink to emit signals to get eos and errors g_object_set (G_OBJECT (gstSink), "emit-signals", FALSE, "sync", !bFrameByFrame, (void*)NULL); /*g_signal_connect (gstSink, "new-buffer", G_CALLBACK (on_new_buffer_from_source), &gstData); g_signal_connect (gstSink, "new-preroll", G_CALLBACK (on_new_preroll_from_source), &gstData);*/ if(!bFrameByFrame) { // printf("SET CALLBACKS\n"); 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, &gstData, NULL); } } setSpeed(1.0); return ret; }
void ofGstUtils::update(){ gstHandleMessage(); if (bLoaded == true){ if(!bFrameByFrame){ ofGstDataLock(&gstData); bHavePixelsChanged = gstData.bHavePixelsChanged; if (bHavePixelsChanged){ gstData.bHavePixelsChanged=false; bIsMovieDone = false; memcpy(pixels,gstData.pixels,width*height*bpp); } ofGstDataUnlock(&gstData); }else{ GstBuffer *buffer; //get the buffer from appsink if(bPaused) buffer = gst_app_sink_pull_preroll (GST_APP_SINK (gstSink)); else buffer = gst_app_sink_pull_buffer (GST_APP_SINK (gstSink)); if(buffer){ guint size = GST_BUFFER_SIZE (buffer); if(pixels){ memcpy (pixels, GST_BUFFER_DATA (buffer), size); bHavePixelsChanged=true; } /// we don't need the appsink buffer anymore gst_buffer_unref (buffer); } } } bIsFrameNew = bHavePixelsChanged; bHavePixelsChanged = false; }
void ofGstUtils::gstHandleMessage(){ GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(gstPipeline)); while(gst_bus_have_pending(bus)) { GstMessage* msg = gst_bus_pop(bus); ofLog(OF_LOG_VERBOSE,"GStreamer: Got %s message", GST_MESSAGE_TYPE_NAME(msg)); switch (GST_MESSAGE_TYPE (msg)) { case GST_MESSAGE_BUFFERING: gint pctBuffered; gst_message_parse_buffering(msg,&pctBuffered); ofLog(OF_LOG_VERBOSE,"GStreamer: buffering %i\%", pctBuffered); if(bIsStream && !bLoaded){ ofGstDataLock(&gstData); allocate(); ofGstDataUnlock(&gstData); } 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; //if(! gst_element_query_duration(gstPipeline,&format,&durationNanos); // ) //ofLog(OF_LOG_WARNING,"GStreamer: cannot query duration"); }break; case GST_MESSAGE_STATE_CHANGED:{ GstState oldstate, newstate, pendstate; gst_message_parse_state_changed(msg, &oldstate, &newstate, &pendstate); if(!bLoaded){ ofGstDataLock(&gstData); allocate(); ofGstDataUnlock(&gstData); } gstData.pipelineState=newstate; /*seek_lock(); if(posChangingPaused && newstate==GST_STATE_PLAYING){ gst_element_set_state (gstPipeline, GST_STATE_PAUSED); posChangingPaused=false; } seek_unlock();*/ ofLog(OF_LOG_VERBOSE,"GStreamer: state changed from " + getName(oldstate) + " to " + getName(newstate) + " (" + getName(pendstate) + ")"); }break; case GST_MESSAGE_ASYNC_DONE: gstData.speed=speed; ofLog(OF_LOG_VERBOSE,"GStreamer: async done"); break; case GST_MESSAGE_ERROR: { GError *err; gchar *debug; gst_message_parse_error(msg, &err, &debug); ofLog(OF_LOG_ERROR, "GStreamer Plugin: Embedded video playback halted; module %s reported: %s", gst_element_get_name(GST_MESSAGE_SRC (msg)), err->message); g_error_free(err); g_free(debug); gst_element_set_state(GST_ELEMENT(gstPipeline), GST_STATE_NULL); }break; case GST_MESSAGE_EOS: ofLog(OF_LOG_VERBOSE,"GStreamer: end of the stream."); bIsMovieDone = true; 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); float loopSpeed; if(pos>0) loopSpeed=-speed; else loopSpeed=speed; if(!gst_element_seek(GST_ELEMENT(gstPipeline), speed, format, flags, GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, durationNanos)) { ofLog(OF_LOG_WARNING,"GStreamer: unable to seek"); } }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)) { ofLog(OF_LOG_WARNING,"GStreamer: unable to seek"); } }break; } break; default: ofLog(OF_LOG_VERBOSE,"GStreamer: unhandled message"); break; } gst_message_unref(msg); } gst_object_unref(GST_OBJECT(bus)); }