[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