- Fixed problems with video files without audio codec not working properly (closes #280)

- Cleanup and refactoring
This commit is contained in:
Tats
2016-11-09 15:18:20 -05:00
parent 00c8ac2865
commit ff9fbe9125
5 changed files with 317 additions and 254 deletions
+185 -14
View File
@@ -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();
+22 -142
View File
@@ -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;
+6 -6
View File
@@ -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();
+101 -87
View File
@@ -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()
+3 -5
View File
@@ -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;
}