mirror of
https://github.com/mapmapteam/mapmap.git
synced 2026-06-16 12:33:19 +02:00
- Fixed problems with video files without audio codec not working properly (closes #280)
- Cleanup and refactoring
This commit is contained in:
+185
-14
@@ -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
@@ -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
@@ -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
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user