diff --git a/VideoImpl.cpp b/VideoImpl.cpp index 26bf540..3fa0d5e 100644 --- a/VideoImpl.cpp +++ b/VideoImpl.cpp @@ -27,8 +27,6 @@ MM_BEGIN_NAMESPACE -// #define VIDEO_IMPL_VERBOSE - // -------- private implementation of VideoImpl ------- bool VideoImpl::hasVideoSupport() @@ -99,8 +97,13 @@ void VideoImpl::setVolume(double volume) _volume = volume; // Set volume element property - g_object_set (_audiovolume0, "mute", (_volume <= 0), NULL); - g_object_set (_audiovolume0, "volume", _volume, NULL); + if (audioIsSupported()) + { + g_object_set (_audiovolume0, "mute", (_volume <= 0), NULL); + g_object_set (_audiovolume0, "volume", _volume, NULL); + } + else + qWarning() << "Cannot change volume cause this video does not support audio." << endl; } } @@ -196,17 +199,18 @@ GstFlowReturn VideoImpl::gstNewSampleCallback(GstElement*, VideoImpl *p) } VideoImpl::VideoImpl() : -_bus(NULL), _pipeline(NULL), _queue0(NULL), _videoconvert0(NULL), -capsfilter0(NULL), +_capsfilter0(NULL), +_videoscale0(NULL), _appsink0(NULL), _audioqueue0(NULL), _audioconvert0(NULL), _audioresample0(NULL), _audiovolume0(NULL), _audiosink0(NULL), +_bus(NULL), _currentFrameSample(NULL), _currentFrameBuffer(NULL), _bitsChanged(false), @@ -221,7 +225,6 @@ _movieReady(false), _playState(false), _uri("") { - _mutexLocker = new QMutexLocker(&_mutex); } @@ -244,23 +247,29 @@ void VideoImpl::freeResources() // Free resources. if (_bus) { - gst_object_unref (_bus); + gst_object_unref (GST_OBJECT(_bus)); _bus = NULL; } if (_pipeline) { gst_element_set_state (_pipeline, GST_STATE_NULL); - gst_object_unref (_pipeline); + gst_object_unref (GST_OBJECT(_pipeline)); _pipeline = NULL; } - // Reset pipeline elements. - _queue0 = NULL; - _videoconvert0 = NULL; - _appsink0 = NULL; - + // Free all components. + _freeElement(&_queue0); + _freeElement(&_capsfilter0); + _freeElement(&_videoscale0); + _freeElement(&_videoconvert0); + _freeElement(&_appsink0); + _freeElement(&_audioqueue0); + _freeElement(&_audioconvert0); + _freeElement(&_audioresample0); + _freeElement(&_audiovolume0); + _freeElement(&_audiosink0); qDebug() << "Freeing remaining samples/buffers" << endl; @@ -272,6 +281,7 @@ void VideoImpl::freeResources() _width = _height = (-1); _duration = 0; _videoIsConnected = false; + _audioIsConnected = false; } void VideoImpl::resetMovie() @@ -294,6 +304,111 @@ void VideoImpl::resetMovie() } } +bool VideoImpl::createVideoComponents() +{ + // Create the video elements. + _queue0 = gst_element_factory_make ("queue", "queue0"); + _videoconvert0 = gst_element_factory_make ("videoconvert", "videoconvert0"); + _videoscale0 = gst_element_factory_make ("videoscale", "videoscale0"); + _capsfilter0 = gst_element_factory_make ("capsfilter", "capsfilter0"); + _appsink0 = gst_element_factory_make ("appsink", "appsink0"); + + // Verify that they were created. + if (!_queue0 || !_videoconvert0 || ! _videoscale0 || ! _capsfilter0 || !_appsink0) + { + qWarning() << "Not all video elements could be created." << endl; + if (! _pipeline) g_printerr("_pipeline"); + if (! _queue0) g_printerr("_queue0"); + if (! _videoconvert0) g_printerr("_videoconvert0"); + if (! _videoscale0) g_printerr("videoscale0"); + if (! _capsfilter0) g_printerr("capsfilter0"); + if (! _appsink0) g_printerr("_appsink0"); + return false; + } + + // Add them to pipeline. + gst_bin_add_many (GST_BIN (_pipeline), + _queue0, _videoconvert0, _videoscale0, _capsfilter0, _appsink0, + NULL); + + // Link. + if (! gst_element_link_many (_queue0, _videoconvert0, _capsfilter0, _videoscale0, _appsink0, NULL)) + { + qWarning() << "Could not link video queue, colorspace converter, caps filter, scaler and app sink." << endl; + return false; + } + + // Configure video appsink. + GstCaps *videoCaps = gst_caps_from_string ("video/x-raw,format=RGBA"); + g_object_set (_capsfilter0, "caps", videoCaps, NULL); + + g_object_set (_appsink0, "emit-signals", TRUE, + "max-buffers", 1, // only one buffer (the last) is maintained in the queue + "drop", TRUE, // ... other buffers are dropped + "sync", TRUE, + NULL); + + g_signal_connect (_appsink0, "new-sample", G_CALLBACK (VideoImpl::gstNewSampleCallback), this); + gst_caps_unref (videoCaps); + + return true; +} + +bool VideoImpl::createAudioComponents() +{ + // Create the audio elements. + _audioqueue0 = gst_element_factory_make ("queue", "audioqueue0"); + _audioconvert0 = gst_element_factory_make ("audioconvert", "audioconvert0"); + _audioresample0 = gst_element_factory_make ("audioresample", "audioresample0"); + _audiovolume0 = gst_element_factory_make ("volume", "audiovolume0"); + _audiosink0 = gst_element_factory_make ("autoaudiosink", "audiosink0"); + + // Verify that they were created. + if (!_audioqueue0 || !_audioconvert0 || !_audioresample0 || !_audiovolume0 || !_audiosink0) + { + qDebug() << "Not all audio elements could be created." << endl; + if (! _audioqueue0) g_printerr("_audioqueue0"); + if (! _audioconvert0) g_printerr("_audioconvert0"); + if (! _audioresample0) g_printerr("_audioresample0"); + if (! _audiovolume0) g_printerr("_audiovolume0"); + if (! _audiosink0) g_printerr("_audiosink0"); + return false; + } + + // Add them to pipeline. + gst_bin_add_many (GST_BIN (_pipeline), + _audioqueue0, _audioconvert0, _audioresample0, _audiovolume0, _audiosink0, + NULL); + + // Link. + if (! gst_element_link_many (_audioqueue0, _audioconvert0, _audioresample0, + _audiovolume0, _audiosink0, NULL)) + { + qDebug() << "Could not link audio queue, converter, resampler and audio sink." << endl; + return false; + } + + // Configure audio appsink. + // TODO: change from mono to stereo + // gchar* audioCapsText = g_strdup_printf ("audio/x-raw-float,channels=1,rate=%d,signed=(boolean)true,width=%d,depth=%d,endianness=BYTE_ORDER", + // Engine::signalInfo().sampleRate(), (int)(sizeof(Signal_T)*8), (int)(sizeof(Signal_T)*8) ); + //GstCaps* audioCaps = gst_caps_from_string (audioCapsText); + /* + GstCaps* audioCaps = gst_caps_from_string ("audio/xraw-float"); + g_object_set (_audioSink, "emit-signals", TRUE, + "caps", audioCaps, + "max-buffers", 1, // only one buffer (the last) is maintained in the queue + "drop", TRUE, // ... other buffers are dropped + "sync", TRUE, + NULL); + g_signal_connect (_audioSink, "new-buffer", G_CALLBACK (VideoImpl::gstNewAudioBufferCallback), this); + gst_caps_unref (audioCaps); + */ + // g_free (audioCapsText); + + return true; +} + void VideoImpl::update() { // Check for end-of-stream or terminate. @@ -317,6 +432,54 @@ void VideoImpl::update() _checkMessages(); } + bool VideoImpl::loadMovie(const QString& filename) { + // Verify if file exists. + const gchar* filetestpath = (const gchar*) filename.toUtf8().constData(); + if (FALSE == g_file_test(filetestpath, G_FILE_TEST_EXISTS)) + { + qDebug() << "File " << filename << " does not exist" << endl; + return false; + } + + qDebug() << "Opening movie: " << filename << "."; + + // Assign URI. + _uri = filename; + + // Free previously allocated structures + unloadMovie(); + + // Prepare handler data. + _videoIsConnected = false; + _audioIsConnected = false; + + // Create the empty pipeline. + _pipeline = gst_pipeline_new ( "video-source-pipeline" ); + if (!_pipeline) + { + qWarning() << "Pipeline could not be created." << endl; + unloadMovie(); + return (-1); + } + + // Create and link video components. + if (!createVideoComponents()) + { + qWarning() << "Video components could not be initialized." << endl; + unloadMovie(); + return (-1); + } + + //setVolume(0); + + // Listen to the bus. + _bus = gst_element_get_bus (_pipeline); + + // Start playing. + + return true; + } + bool VideoImpl::setPlayState(bool play) { if (_pipeline == NULL) @@ -587,6 +750,14 @@ void VideoImpl::_freeCurrentSample() { _data = NULL; } +void VideoImpl::_freeElement(GstElement** element) +{ + if (*element) + { + *element = NULL; + } +} + void VideoImpl::lockMutex() { _mutexLocker->relock(); diff --git a/VideoImpl.h b/VideoImpl.h index ee026d1..d44948b 100644 --- a/VideoImpl.h +++ b/VideoImpl.h @@ -112,6 +112,9 @@ public: bool videoIsConnected() const { return _videoIsConnected; } void videoConnect() { _videoIsConnected = true; } + bool audioIsConnected() const { return _audioIsConnected; } + void audioConnect() { _audioIsConnected = true; } + bool audioIsSupported() const { return _audioqueue0 != NULL; } /** * Performs regular updates (checks if movie is ready and checks messages). @@ -121,137 +124,11 @@ public: /** * Loads a new video stream - * + * * Creates a new GStreamer pipeline, opens a movie, webcam or shmsrc socket, * depending on subclass. */ - virtual bool loadMovie(const QString& filename) { - // Verify if file exists. - const gchar* filetestpath = (const gchar*) filename.toUtf8().constData(); - if (FALSE == g_file_test(filetestpath, G_FILE_TEST_EXISTS)) - { - qDebug() << "File " << filename << " does not exist" << endl; - return false; - } - - qDebug() << "Opening movie: " << filename << "."; - - // Assign URI. - _uri = filename; - - // Free previously allocated structures - unloadMovie(); - - // Initialize GStreamer. - - GstElement *videoscale0 = NULL; - - // Create the elements. - _queue0 = gst_element_factory_make ("queue", "queue0"); - _videoconvert0 = gst_element_factory_make ("videoconvert", "videoconvert0"); - videoscale0 = gst_element_factory_make ("videoscale", "videoscale0"); - capsfilter0 = gst_element_factory_make ("capsfilter", "capsfilter0"); - _appsink0 = gst_element_factory_make ("appsink", "appsink0"); - - // Prepare handler data. - _videoIsConnected = false; - - _audioqueue0 = gst_element_factory_make ("queue", "audioqueue0"); - _audioconvert0 = gst_element_factory_make ("audioconvert", "audioconvert0"); - _audioresample0 = gst_element_factory_make ("audioresample", "audioresample0"); - _audiovolume0 = gst_element_factory_make ("volume", "audiovolume0"); - _audiosink0 = gst_element_factory_make ("autoaudiosink", "audiosink0"); - - // Create the empty pipeline. - _pipeline = gst_pipeline_new ( "video-source-pipeline" ); - if (!_pipeline || - !_queue0 || !_videoconvert0 || ! videoscale0 || ! capsfilter0 || - !_appsink0 || !_audioqueue0 || !_audioconvert0 || !_audioresample0 || - !_audiovolume0 || !_audiosink0) - { - g_printerr ("Not all elements could be created.\n"); - if (! _pipeline) g_printerr("_pipeline"); - if (! _queue0) g_printerr("_queue0"); - if (! _videoconvert0) g_printerr("_videoconvert0"); - if (! videoscale0) g_printerr("videoscale0"); - if (! capsfilter0) g_printerr("capsfilter0"); - if (! _appsink0) g_printerr("_appsink0"); - if (! _audioqueue0) g_printerr("_audioqueue0"); - if (! _audioconvert0) g_printerr("_audioconvert0"); - if (! _audioresample0) g_printerr("_audioresample0"); - if (! _audiovolume0) g_printerr("_audiovolume0"); - if (! _audiosink0) g_printerr("_audiosink0"); - unloadMovie(); - return -1; - } - - // Build the pipeline. Note that we are NOT linking the source at this - // point. We will do it later. - gst_bin_add_many (GST_BIN (_pipeline), - _queue0, _videoconvert0, videoscale0, capsfilter0, _appsink0, - _audioqueue0, _audioconvert0, _audioresample0, _audiovolume0, _audiosink0, - NULL); - // special case for shmsrc - // link uridecodebin -> queue will be performed by callback - - if (! gst_element_link_many (_queue0, _videoconvert0, capsfilter0, videoscale0, _appsink0, NULL)) - { - qDebug() << "Could not link video queue, colorspace converter, caps filter, scaler and app sink." << endl; - unloadMovie(); - return false; - } - - if (! gst_element_link_many (_audioqueue0, _audioconvert0, _audioresample0, - _audiovolume0, _audiosink0, NULL)) - { - g_printerr ("Could not link audio queue, converter, resampler and audio sink.\n"); - unloadMovie(); - return false; - } - - // Configure audio appsink. - // TODO: change from mono to stereo - // gchar* audioCapsText = g_strdup_printf ("audio/x-raw-float,channels=1,rate=%d,signed=(boolean)true,width=%d,depth=%d,endianness=BYTE_ORDER", - // Engine::signalInfo().sampleRate(), (int)(sizeof(Signal_T)*8), (int)(sizeof(Signal_T)*8) ); - //GstCaps* audioCaps = gst_caps_from_string (audioCapsText); - /* - GstCaps* audioCaps = gst_caps_from_string ("audio/xraw-float"); - g_object_set (_audioSink, "emit-signals", TRUE, - "caps", audioCaps, - "max-buffers", 1, // only one buffer (the last) is maintained in the queue - "drop", TRUE, // ... other buffers are dropped - "sync", TRUE, - NULL); - g_signal_connect (_audioSink, "new-buffer", G_CALLBACK (VideoImpl::gstNewAudioBufferCallback), this); - gst_caps_unref (audioCaps); - */ - // g_free (audioCapsText); - - - // Configure video appsink. - GstCaps *videoCaps = gst_caps_from_string ("video/x-raw,format=RGBA"); - g_object_set (capsfilter0, "caps", videoCaps, NULL); - - g_object_set (_appsink0, "emit-signals", TRUE, - "max-buffers", 1, // only one buffer (the last) is maintained in the queue - "drop", TRUE, // ... other buffers are dropped - "sync", TRUE, - NULL); - - g_signal_connect (_appsink0, "new-sample", G_CALLBACK (VideoImpl::gstNewSampleCallback), this); - gst_caps_unref (videoCaps); - - setVolume(0); - - // Listen to the bus. - _bus = gst_element_get_bus (_pipeline); - - // Start playing. - - return true; - } - //virtual GstElement *buildPipeline(Element sink) = 0; - //virtual void loadMovie(const QString& filename) = 0; + virtual bool loadMovie(const QString& filename); bool setPlayState(bool play); bool getPlayState() const { return _playState; } @@ -270,6 +147,9 @@ public: void resetMovie(); protected: + virtual bool createVideoComponents(); + virtual bool createAudioComponents(); + void unloadMovie(); void freeResources(); @@ -295,6 +175,8 @@ private: void _freeCurrentSample(); + void _freeElement(GstElement** element); + public: // GStreamer callback that simply sets the #newSample# flag to point to TRUE. static GstFlowReturn gstNewSampleCallback(GstElement*, VideoImpl *p); @@ -313,32 +195,33 @@ public: /// Wait until first data samples are available (blocking). bool waitForNextBits(int timeout, const uchar** bits=0); - // FIXME these should be private, accessed my subclasses +protected: int _width; int _height; -// bool _isSeekable; + guint64 _duration; // duration (in nanoseconds) (unused for now) + bool _videoIsConnected; - GstElement *_queue0; - GstElement *_audioqueue0; - GstElement *_pipeline; - GstElement *capsfilter0; + bool _audioIsConnected; bool _seekEnabled; -private: - //locals - - // gstreamer elements - GstBus *_bus; + GstElement *_pipeline; + GstElement *_queue0; + GstElement *_capsfilter0; + GstElement *_videoscale0; GstElement *_videoconvert0; GstElement *_appsink0; + GstElement *_audioqueue0; GstElement *_audioconvert0; GstElement *_audioresample0; GstElement *_audiovolume0; GstElement *_audiosink0; + // gstreamer elements + GstBus *_bus; + /** * Temporary contains the image data of the last frame. */ @@ -351,9 +234,6 @@ private: * Contains meta informations about current file. */ - - - /// Raw image data of the last video frame. uchar *_data; diff --git a/VideoShmSrcImpl.cpp b/VideoShmSrcImpl.cpp index aaf0d98..7319066 100644 --- a/VideoShmSrcImpl.cpp +++ b/VideoShmSrcImpl.cpp @@ -46,7 +46,7 @@ void VideoShmSrcImpl::setAttached(bool attach) _attached = attach; } -gboolean +gboolean gstPollShmsrc (void *user_data) { VideoShmSrcImpl *p = (VideoShmSrcImpl*) user_data; @@ -71,16 +71,16 @@ bool VideoShmSrcImpl::loadMovie(const QString& path) { _gdpdepay0 = gst_element_factory_make ("gdpdepay", "gdpdepay0"); _pollSource = g_timeout_source_new (500); - g_source_set_callback (_pollSource, - gstPollShmsrc, - this, + g_source_set_callback (_pollSource, + gstPollShmsrc, + this, NULL); g_source_attach (_pollSource, g_main_context_default()); g_source_unref (_pollSource); if (! _shmsrc0 || ! _gdpdepay0) { - g_printerr ("Not all elements could be created.\n"); + qWarning() << "Not all elements could be created." << endl; if (! _shmsrc0) g_printerr("_shmsrc0"); if (! _gdpdepay0) g_printerr("_gdpdepay0"); unloadMovie(); @@ -90,7 +90,7 @@ bool VideoShmSrcImpl::loadMovie(const QString& path) { gst_bin_add_many (GST_BIN(_pipeline), _shmsrc0, _gdpdepay0, NULL); if (! gst_element_link_many (_shmsrc0, _gdpdepay0, _queue0, NULL)) { - g_printerr ("Could not link shmsrc, deserializer and video queue.\n"); + qWarning() << "Could not link shmsrc, deserializer and video queue." << endl; } QByteArray ba = path.toLocal8Bit(); diff --git a/VideoUriDecodeBinImpl.cpp b/VideoUriDecodeBinImpl.cpp index 2bf7c13..90381d0 100644 --- a/VideoUriDecodeBinImpl.cpp +++ b/VideoUriDecodeBinImpl.cpp @@ -35,7 +35,7 @@ _uridecodebin0(NULL) void VideoUriDecodeBinImpl::gstPadAddedCallback(GstElement *src, GstPad *newPad, VideoUriDecodeBinImpl* p) { - (void)src; //Unused + Q_UNUSED(src); #ifdef VIDEO_IMPL_VERBOSE #ifndef Q_OS_OSX // NOTE: This line was causing a problem on Mac OSX: it caused the software to freeze when loading a new movie. @@ -55,8 +55,11 @@ void VideoUriDecodeBinImpl::gstPadAddedCallback(GstElement *src, GstPad *newPad, #endif g_free(newPadStructStr); + bool isVideoPad = g_str_has_prefix (newPadType, "video/x-raw"); + bool isAudioPad = g_str_has_prefix (newPadType, "audio/x-raw"); + // Check for video pads. - if (g_str_has_prefix (newPadType, "video/x-raw")) + if (isVideoPad) { sinkPad = gst_element_get_static_pad (p->_queue0, "sink"); gst_structure_get_int(newPadStruct, "width", &p->_width); @@ -64,9 +67,15 @@ void VideoUriDecodeBinImpl::gstPadAddedCallback(GstElement *src, GstPad *newPad, } // Check for audio pads. - else if (g_str_has_prefix (newPadType, "audio/x-raw")) + else if (isAudioPad) { - sinkPad = gst_element_get_static_pad (p->_audioqueue0, "sink"); + if (p->audioIsSupported()) + sinkPad = gst_element_get_static_pad (p->_audioqueue0, "sink"); + else if (!p->createAudioComponents()) + { + qWarning() << "Problem creating audio components." << endl; + goto exit; + } } // Other types: ignore. @@ -75,12 +84,12 @@ void VideoUriDecodeBinImpl::gstPadAddedCallback(GstElement *src, GstPad *newPad, goto exit; } + // If our converter is already linked, we have nothing to do here. if (gst_pad_is_linked (sinkPad)) { // Best prefixes. - if (g_str_has_prefix (newPadType, "audio/x-raw-float") || - g_str_has_prefix (newPadType, "video/x-raw-int") ) + if (isVideoPad || isAudioPad) { qDebug() << " Found a better pad." << endl; GstPad* oldPad = gst_pad_get_peer(sinkPad); @@ -103,8 +112,15 @@ void VideoUriDecodeBinImpl::gstPadAddedCallback(GstElement *src, GstPad *newPad, qDebug() << " Type is '" << newPadType << "' but link failed." << endl; #endif // ifdef goto exit; - } else { - p->videoConnect(); + } + else + { + if (isVideoPad) + p->videoConnect(); + else if (isAudioPad) + p->audioConnect(); + else + qWarning() << "Error: this pad is neither valid audio or video." << endl; #ifdef VIDEO_IMPL_VERBOSE qDebug() << " Link succeeded (type '" << newPadType << "')." << endl; #endif // ifdef @@ -128,13 +144,12 @@ bool VideoUriDecodeBinImpl::loadMovie(const QString& path) { VideoImpl::loadMovie(path); _uridecodebin0 = gst_element_factory_make("uridecodebin", NULL); - _videoIsConnected = false; if ( !_uridecodebin0) { - g_printerr ("Not all elements could be created.\n"); + qWarning() << "Not all elements could be created." << endl; unloadMovie(); - return -1; + return (-1); } // Build the pipeline. Note that we are NOT linking the source at this @@ -164,93 +179,92 @@ bool VideoUriDecodeBinImpl::loadMovie(const QString& path) { } g_free(filename_tmp); - // Connect to the pad-added signal - // Extract meta info. - GError* error = NULL; - GstDiscoverer* discoverer = gst_discoverer_new(5*GST_SECOND, &error); - if (!discoverer) - { - qDebug() << "Error creating discoverer: " << error->message << endl; - g_clear_error (&error); - return false; - } - - GstDiscovererInfo* info = gst_discoverer_discover_uri(discoverer, uri, &error); - - if (!info) - { - qDebug() << "Error getting discoverer info: " << error->message << endl; - g_clear_error (&error); - return false; - } - - GstDiscovererResult result = gst_discoverer_info_get_result(info); - - switch (result) { - case GST_DISCOVERER_URI_INVALID: - qDebug()<< "Invalid URI '" << uri << "'" << endl; - break; - case GST_DISCOVERER_ERROR: - qDebug()<< "Discoverer error: " << error->message << endl; - break; - case GST_DISCOVERER_TIMEOUT: - qDebug() << "Timeout" << endl; - break; - case GST_DISCOVERER_BUSY: - qDebug() << "Busy" << endl; - break; - case GST_DISCOVERER_MISSING_PLUGINS:{ - const GstStructure *s; - gchar *str; - - s = gst_discoverer_info_get_misc (info); - str = gst_structure_to_string (s); - - qDebug() << "Missing plugins: " << str << endl; - g_free (str); - break; - } - case GST_DISCOVERER_OK: - qDebug() << "Discovered '" << uri << "'" << endl; - break; - } - +// Connect to the pad-added signal + // Extract meta info. + GError* error = NULL; + GstDiscoverer* discoverer = gst_discoverer_new(5*GST_SECOND, &error); + if (!discoverer) + { + qDebug() << "Error creating discoverer: " << error->message << endl; g_clear_error (&error); + return false; + } - if (result != GST_DISCOVERER_OK) { - qDebug() << "This URI cannot be played" << endl; - return false; + GstDiscovererInfo* info = gst_discoverer_discover_uri(discoverer, uri, &error); + + if (!info) + { + qDebug() << "Error getting discoverer info: " << error->message << endl; + g_clear_error (&error); + return false; + } + + GstDiscovererResult result = gst_discoverer_info_get_result(info); + + switch (result) { + case GST_DISCOVERER_URI_INVALID: + qDebug()<< "Invalid URI '" << uri << "'" << endl; + break; + case GST_DISCOVERER_ERROR: + qDebug()<< "Discoverer error: " << error->message << endl; + break; + case GST_DISCOVERER_TIMEOUT: + qDebug() << "Timeout" << endl; + break; + case GST_DISCOVERER_BUSY: + qDebug() << "Busy" << endl; + break; + case GST_DISCOVERER_MISSING_PLUGINS:{ + const GstStructure *s; + gchar *str; + + s = gst_discoverer_info_get_misc (info); + str = gst_structure_to_string (s); + + qDebug() << "Missing plugins: " << str << endl; + g_free (str); + break; } + case GST_DISCOVERER_OK: + qDebug() << "Discovered '" << uri << "'" << endl; + break; + } - // Gather info from video. - GList *videoStreams = gst_discoverer_info_get_video_streams (info); - if (!videoStreams) - { - qDebug() << "This URI does not contain any video streams" << endl; - return false; - } + g_clear_error (&error); - // Retrieve meta-info. - _width = gst_discoverer_video_info_get_width((GstDiscovererVideoInfo*)videoStreams->data); - _height = gst_discoverer_video_info_get_height((GstDiscovererVideoInfo*)videoStreams->data); - _duration = gst_discoverer_info_get_duration(info); - _seekEnabled = gst_discoverer_info_get_seekable(info); + if (result != GST_DISCOVERER_OK) { + qDebug() << "This URI cannot be played" << endl; + return false; + } - // Free everything. - g_object_unref(discoverer); - gst_discoverer_info_unref(info); - gst_discoverer_stream_info_list_free(videoStreams); + // Gather info from video. + GList *videoStreams = gst_discoverer_info_get_video_streams (info); + if (!videoStreams) + { + qDebug() << "This URI does not contain any video streams" << endl; + return false; + } - // Connect pad signal. - g_signal_connect (_uridecodebin0, "pad-added", G_CALLBACK (VideoUriDecodeBinImpl::gstPadAddedCallback), this); + // Retrieve meta-info. + _width = gst_discoverer_video_info_get_width((GstDiscovererVideoInfo*)videoStreams->data); + _height = gst_discoverer_video_info_get_height((GstDiscovererVideoInfo*)videoStreams->data); + _duration = gst_discoverer_info_get_duration(info); + _seekEnabled = gst_discoverer_info_get_seekable(info); - // Set uri of decoder. - g_object_set (_uridecodebin0, "uri", uri, NULL); + // Free everything. + g_object_unref(discoverer); + gst_discoverer_info_unref(info); + gst_discoverer_stream_info_list_free(videoStreams); + // Connect pad signal. + g_signal_connect (_uridecodebin0, "pad-added", G_CALLBACK (VideoUriDecodeBinImpl::gstPadAddedCallback), this); + // Set uri of decoder. + g_object_set (_uridecodebin0, "uri", uri, NULL); - setPlayState(true); - return TRUE; + setPlayState(true); + + return true; } VideoUriDecodeBinImpl::~VideoUriDecodeBinImpl() diff --git a/VideoV4l2SrcImpl.cpp b/VideoV4l2SrcImpl.cpp index d50c5cb..146794b 100644 --- a/VideoV4l2SrcImpl.cpp +++ b/VideoV4l2SrcImpl.cpp @@ -38,13 +38,12 @@ bool VideoV4l2SrcImpl::loadMovie(const QString& path) { VideoImpl::loadMovie(path); _v4l2src0 = gst_element_factory_make("v4l2src", NULL); - _videoIsConnected = false; if ( !_v4l2src0) { - g_printerr ("Not all elements could be created.\n"); + qWarning() << "Not all elements could be created." << endl; unloadMovie(); - return -1; + return (-1); } // Build the pipeline. Note that we are NOT linking the source at this @@ -62,7 +61,7 @@ bool VideoV4l2SrcImpl::loadMovie(const QString& path) { // Configure video appsink. GstCaps *videoCaps = gst_caps_from_string ("video/x-raw,format=RGBA,width=640,height=480"); - g_object_set (capsfilter0, "caps", videoCaps, NULL); + g_object_set (_capsfilter0, "caps", videoCaps, NULL); gst_caps_unref (videoCaps); // Retrieve meta-info. @@ -71,7 +70,6 @@ bool VideoV4l2SrcImpl::loadMovie(const QString& path) { //_duration = ; _seekEnabled = false; - setPlayState(true); return TRUE; }