diff --git a/src/osgPlugins/gstreamer/GStreamerImageStream.cpp b/src/osgPlugins/gstreamer/GStreamerImageStream.cpp index fd1469f2c..14e5a852a 100644 --- a/src/osgPlugins/gstreamer/GStreamerImageStream.cpp +++ b/src/osgPlugins/gstreamer/GStreamerImageStream.cpp @@ -1,34 +1,55 @@ #include "GStreamerImageStream.hpp" +#if 0 + #define OSGGST_INFO OSG_NOTICE +#else + #define OSGGST_INFO OSG_INFO +#endif + namespace osgGStreamer { -GStreamerImageStream::GStreamerImageStream() +GStreamerImageStream::GStreamerImageStream(): + _loop(0), + _pipeline(0), + _internal_buffer(0), + _width(0), + _height(0) { setOrigin(osg::Image::TOP_LEFT); - loop = g_main_loop_new(NULL, FALSE); + _loop = g_main_loop_new(NULL, FALSE); } GStreamerImageStream::GStreamerImageStream(const GStreamerImageStream & image, const osg::CopyOp & copyop) : - osg::ImageStream(image, copyop) + osg::ImageStream(image, copyop), + _loop(0), + _pipeline(0), + _internal_buffer(0), + _width(0), + _height(0) { - // TODO: probably incorrect or incomplete + setOrigin(osg::Image::TOP_LEFT); + + _loop = g_main_loop_new(NULL, FALSE); + + if (!getFileName().empty()) + { + open(getFileName()); + } } GStreamerImageStream::~GStreamerImageStream() { - OSG_INFO<<"Destructing GStreamerImageStream..."<message); return false; @@ -78,7 +99,7 @@ bool GStreamerImageStream::open(const std::string &filename) // bus - GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline)); + GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(_pipeline)); gst_bus_add_watch(bus, (GstBusFunc)on_message, this); @@ -87,19 +108,25 @@ bool GStreamerImageStream::open(const std::string &filename) // sink - GstElement *sink = gst_bin_get_by_name(GST_BIN(pipeline), "sink"); + GstElement *sink = gst_bin_get_by_name(GST_BIN(_pipeline), "sink"); g_signal_connect(sink, "new-sample", G_CALLBACK(on_new_sample), this); g_signal_connect(sink, "new-preroll", G_CALLBACK(on_new_preroll), this); gst_object_unref(sink); - gst_element_set_state(pipeline, GST_STATE_PAUSED); - gst_element_get_state(pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); // wait until the state changed + gst_element_set_state(_pipeline, GST_STATE_PAUSED); + gst_element_get_state(_pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); // wait until the state changed - //setPixelBufferObject(new osg::PixelBufferObject(this)); // can help with the performance - setImage(width, height, 1, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, internal_buffer, osg::Image::NO_DELETE); + if (_width==0 || _height==0) + { + // no valid image has been setup by a on_new_preroll() call. + return false; + } + // setLoopingMode(osg::ImageStream::NO_LOOPING); + + // start the thread to run gstreamer main loop start(); return true; @@ -109,32 +136,26 @@ bool GStreamerImageStream::open(const std::string &filename) void GStreamerImageStream::play() { - gst_element_set_state(pipeline, GST_STATE_PLAYING); + OSGGST_INFO<<"GStreamerImageStream::play()"<internal_buffer, info.size); + gst_buffer_extract(buffer, 0, user_data->_internal_buffer, info.size); - OSG_NOTICE<<"on_new_sample("<<(user_data->width)<<", "<<(user_data->height)<<")"<setImage(user_data->width, user_data->height, 1, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, user_data->internal_buffer, osg::Image::NO_DELETE, 4); + // data has been modified so dirty the image so the texture will updated + user_data->dirty(); // clean resources @@ -181,23 +201,35 @@ GstFlowReturn GStreamerImageStream::on_new_preroll(GstAppSink *appsink, GStreame gst_structure_get_int(structure, "width", &width); gst_structure_get_int(structure, "height", &height); - user_data->width = width; - user_data->height = height; - - int row_width = width*3; - if ((row_width%4)!=0) + if (width<=0 || height<=0) { - OSG_NOTICE<<"Rounding up row width from "<width)<<", "<<(user_data->height)<<")"<_internal_buffer) free(user_data->_internal_buffer); + + // allocate buffer + user_data->_internal_buffer = (unsigned char*)malloc(sizeof(unsigned char)*row_width*height); + + // assign buffer to image + user_data->setImage(user_data->_width, user_data->_height, 1, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, user_data->_internal_buffer, osg::Image::NO_DELETE, 4); + } // clean resources - gst_sample_unref(sample); return GST_FLOW_OK; @@ -207,7 +239,11 @@ gboolean GStreamerImageStream::on_message(GstBus *bus, GstMessage *message, GStr { if( GST_MESSAGE_TYPE(message) == GST_MESSAGE_EOS) { - user_data->rewind(); + OSGGST_INFO<<"Video '"<getFileName()<<"' finished."<getLoopingMode()==osg::ImageStream::LOOPING) + { + user_data->rewind(); + } } return TRUE; @@ -215,7 +251,8 @@ gboolean GStreamerImageStream::on_message(GstBus *bus, GstMessage *message, GStr void GStreamerImageStream::run() { - g_main_loop_run(loop); + g_main_loop_run(_loop); } + } // namespace osgGStreamer diff --git a/src/osgPlugins/gstreamer/GStreamerImageStream.hpp b/src/osgPlugins/gstreamer/GStreamerImageStream.hpp index bd89c45e5..504e72db9 100644 --- a/src/osgPlugins/gstreamer/GStreamerImageStream.hpp +++ b/src/osgPlugins/gstreamer/GStreamerImageStream.hpp @@ -20,33 +20,30 @@ namespace osgGStreamer { META_Object(osgGStreamer, GStreamerImageStream); bool open(const std::string &filename); - + virtual void play(); virtual void pause(); virtual void rewind(); virtual void seek(double time); - virtual int s() const; - virtual int t() const; - private: virtual ~GStreamerImageStream(); + virtual void run(); + static gboolean on_message(GstBus *bus, GstMessage *message, GStreamerImageStream *user_data); static GstFlowReturn on_new_sample(GstAppSink *appsink, GStreamerImageStream *user_data); static GstFlowReturn on_new_preroll(GstAppSink *appsink, GStreamerImageStream *user_data); - virtual void run(); + GMainLoop* _loop; + GstElement* _pipeline; - GMainLoop *loop; - GstElement *pipeline; + unsigned char* _internal_buffer; - unsigned char *internal_buffer; - - int width; - int height; + int _width; + int _height; }; }