[gst-devel] Problem with C++ app when pausing and playing
Scott Herrmann
sherrmann2 at insightbb.com
Thu Aug 4 01:17:06 CEST 2005
Hoping someone can help me. I am new to gstreamer and am trying to develop
a C++ application that is using GStreamer. I have it playing a file just
fine. When I pause it it stops, but then when I change the state back to
playing there is no sound. A subsequent pause changes the state back to
paused and then a final attempt to play it again causes a complete lock up.
Attached is the relevant C++ header and source file. The pause routine is
at the bottom.
Thanks in advance for any help.
Scott
////////////////////////////////////////////////////////////////
File: AudioEngineGST.h
#ifndef AUDIOENGINEGST_H_
#define AUDIOENGINEGST_H_
// These two Must be first includes
#include "sys.h"
#include "debug.h"
#include <QThread>
// Gstreamer
#include <gst/gst.h>
#ifdef CWDEBUG
extern pthread_mutex_t debug_mutex ;
#endif
using namespace std;
using namespace libcwd;
class AudioEngineGST : public QObject
{
Q_OBJECT
public:
AudioEngineGST(QObject *parent = 0);
virtual ~AudioEngineGST();
void init ();
void run(void);
public slots:
void pause(void);
void errors(void);
private:
static AudioEngineGST* instance() { return s_instance; }
static AudioEngineGST* s_instance;
static GstElement *thread1;
static GstElement *pipeline;
static GstElement *source;
static GstElement *parser;
static GstElement *decoder;
static GstElement *sink;
static GstPad *audiopad;
static void new_pad (GstElement *element,GstPad *pad, gpointer data);
static void cb_error (GstElement *item, GstElement *src, GError *error,
gchar *debug, gpointer data);
static void cb_eos (GstElement *thread, gpointer data);
bool oActive;
QString oErr;
};
#endif /*AUDIOENGINEGST_H_*/
////////////////////////////////////////////////////////////////
File: AudioEngineGST.cpp
#include "AudioEngineGST.h"
#include <QTimer>
// Required for the Debug code
using namespace libcwd;
using namespace myproj::debug::channels::dc;
AudioEngineGST* AudioEngineGST::s_instance;
GstElement *AudioEngineGST::thread1 = NULL;
GstElement *AudioEngineGST::pipeline = NULL;
GstElement *AudioEngineGST::source = NULL;
GstElement *AudioEngineGST::parser = NULL;
GstElement *AudioEngineGST::decoder = NULL;
GstElement *AudioEngineGST::sink = NULL;
GstPad *AudioEngineGST::audiopad = NULL;
void AudioEngineGST::init (void)
{ s_instance = this;
}
AudioEngineGST::AudioEngineGST(QObject *parent)
: QObject (parent)
{
Douts (m3wproc,"[AudioEngineGST() - CONSTRUCTOR]");
init();
gst_init_check (NULL, NULL);
/* create elements */
AudioEngineGST::thread1 = gst_thread_new ("thread");
// AudioEngineGST::pipeline = gst_pipeline_new ("audio-player");
AudioEngineGST::source = gst_element_factory_make ("filesrc",
"file-source");
AudioEngineGST::parser = gst_element_factory_make ("oggdemux",
"ogg-parser");
AudioEngineGST::decoder = gst_element_factory_make ("vorbisdec",
"vorbis-decoder");
AudioEngineGST::sink = gst_element_factory_make ("alsasink",
"alsa-output");
/* set filename property on the file source */
g_object_set (G_OBJECT (source), "location", "/tmp/crimson.ogg", NULL);
/* link together - note that we cannot link the parser and
* decoder yet, becuse the parser uses dynamic pads. For that,
* we set a new-pad signal handler. */
gst_element_link (AudioEngineGST::source, AudioEngineGST::parser);
gst_element_link (AudioEngineGST::decoder, AudioEngineGST::sink);
g_signal_connect (AudioEngineGST::parser, "new-pad", G_CALLBACK
(AudioEngineGST::new_pad), NULL);
g_signal_connect (AudioEngineGST::thread1, "eos", G_CALLBACK
(AudioEngineGST::cb_eos), NULL);
g_signal_connect (AudioEngineGST::thread1, "error", G_CALLBACK
(AudioEngineGST::cb_error), NULL);
/* put all elements in a bin - or at least the ones we will use
* instantly. */
// gst_bin_add_many (GST_BIN (AudioEngineGST::pipeline),
AudioEngineGST::source, AudioEngineGST::parser, NULL);
gst_bin_add_many (GST_BIN (AudioEngineGST::thread1),
AudioEngineGST::source, AudioEngineGST::parser, NULL);
/* Now set to playing and iterate. We will set the decoder and
* audio output to ready so they initialize their memory already.
* This will decrease the amount of time spent on linking these
* elements when the Ogg parser emits the new-pad signal. */
gst_element_set_state (AudioEngineGST::decoder, GST_STATE_READY);
gst_element_set_state (AudioEngineGST::sink, GST_STATE_READY);
//gst_element_set_state (AudioEngineGST::pipeline, GST_STATE_PLAYING);
gst_element_set_state (AudioEngineGST::thread1, GST_STATE_PLAYING);
// Start the separate playing thread
Dout (m3wdet,"Starting play thread");
// Set indicator to active
oActive = true;
qint64 ik = 0;
qint64 ipauselong = 500000000;
qint64 imax = ipauselong;
qint64 itest = imax;
qint64 ipause = 0;
// Test code, alternate between playing and pausing...
while (1 == 1)
{
sleep(5);
pause();
}
Doute (m3wproc,"[AudioEngineGST() - CONSTRUCTOR]");
/* clean up nicely */
// gst_element_set_state (AudioEngineGST::pipeline, GST_STATE_NULL);
// gst_object_unref (GST_OBJECT (AudioEngineGST::pipeline));
// Doute (m3wproc,"[AudioEngineGST() - CONSTRUCTOR]");
}
AudioEngineGST::~AudioEngineGST()
{
}
void AudioEngineGST::run(void)
{
}
void AudioEngineGST::cb_eos (GstElement *thread, gpointer data)
{
g_print ("EOS in GST");
}
void AudioEngineGST::cb_error (GstElement *item, GstElement *src, GError
*error, gchar *debug, gpointer data)
{
instance()->oErr.append(error->message);
// g_print ("Error in thread %p: %s\n", g_thread_self(),error->message);
QTimer::singleShot( 0, instance(), SLOT( errors() ) );
}
void AudioEngineGST::errors (void)
{
cout << "error ::::: " << oErr.toStdString() << endl;
}
void AudioEngineGST::new_pad (
GstElement *element,
GstPad *pad,
gpointer data)
{
/* We can now link this pad with the audio decoder and
* add both decoder and audio output to the pipeline. */
//GstPad* const audiopad = gst_element_get_pad( decoder, "sink" );
AudioEngineGST::audiopad = gst_element_get_pad( decoder, "sink" );
gst_pad_link (pad, audiopad);
// gst_bin_add_many (GST_BIN (pipeline), decoder, sink, NULL);
gst_bin_add_many (GST_BIN (thread1), decoder, sink, NULL);
/* This function synchronizes a bins state on all of its
* contained children. */
// gst_bin_sync_children_state (GST_BIN (pipeline));
gst_bin_sync_children_state (GST_BIN (thread1));
}
void AudioEngineGST::pause(void)
{
// int i = GST_STATE(AudioEngineGST::pipeline);
int i = GST_STATE(AudioEngineGST::thread1);
int i2 = GST_STATE(AudioEngineGST::sink);
int i3 = GST_STATE(AudioEngineGST::decoder);
int i4 = GST_STATE(AudioEngineGST::source);
int i5 = GST_STATE(AudioEngineGST::parser);
cout << "Inside the pause routine..............................&&&&&" <<
endl;
cout << "Pipeline State = " << i << endl;
cout << "Sink State = " << i2 << endl;
cout << "decoder State = " << i3 << endl;
cout << "source State = " << i4 << endl;
cout << "Parser State = " << i5 << endl;
if (oActive == true)
//if ( GST_STATE( AudioEngineGST::thread1 ) == GST_STATE_PLAYING )
{
cout << "setting state to: PAUSING"<< endl;
// gst_element_set_state (AudioEngineGST::source, GST_STATE_PAUSED);
gst_element_set_state( AudioEngineGST::thread1, GST_STATE_PAUSED );
oActive = false;
}
//else if (GST_STATE( AudioEngineGST::thread1 ) == GST_STATE_PAUSED )
else if (oActive == false)
{
cout << "Setting state to: PLAYING"<< endl;
gst_element_set_state( AudioEngineGST::thread1, GST_STATE_PLAYING );
// gst_element_set_state (AudioEngineGST::source, GST_STATE_PLAYING);
oActive = true;
}
else
cout << "uhhhhhhhhhhhhh ohhhhhhhhhhhhhhhhhhhhhhh" << endl;
i = GST_STATE(AudioEngineGST::thread1);
i2 = GST_STATE(AudioEngineGST::sink);
i3 = GST_STATE(AudioEngineGST::decoder);
i4 = GST_STATE(AudioEngineGST::source);
i5 = GST_STATE(AudioEngineGST::parser);
cout << "Pipeline State = " << i << endl;
cout << "Sink State = " << i2 << endl;
cout << "decoder State = " << i3 << endl;
cout << "source State = " << i4 << endl;
cout << "Parser State = " << i5 << endl;
cout << "LEAVING-----------------------------------" << endl;
}
More information about the gstreamer-devel
mailing list