[gst-devel] Problem with gst_element_continue_state () [ Resending : Code inline with mail ]
Learner
ruxyz at yahoo.com
Fri May 18 07:53:33 CEST 2007
Hi,
I was trying to use gst_element_continue_state()
API to resume normal state transition after
an asynchronous state change.
I have pasted the code of the dummy plugin below,
but found that the state transition does not proceed.
Could you please help in locating the mistake.
Thanks.
/************* File gstdummy.c *************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <unistd.h>
#include <string.h>
#include "gstdummy.h"
#define NUMBER_OF_BUFFERS 5
/* elementfactory information */
static GstElementDetails gst_dummy_details =
GST_ELEMENT_DETAILS ("Dummy Plugin",
"Dummy test plugin",
"Dummy",
"Dummy");
static GstStaticPadTemplate audio_srctemplate =
GST_STATIC_PAD_TEMPLATE ("audio_src",
GST_PAD_SRC,
GST_PAD_SOMETIMES,
GST_STATIC_CAPS_ANY);
static GstStaticPadTemplate video_srctemplate =
GST_STATIC_PAD_TEMPLATE ("video_src",
GST_PAD_SRC,
GST_PAD_SOMETIMES,
GST_STATIC_CAPS_ANY);
enum
{
LAST_SIGNAL
};
static void gst_dummy_base_init (gpointer g_class);
static void gst_dummy_class_init (GstDummy * klass);
static void gst_dummy_init (GstDummy * src,
GstDummyClass * klass);
static void gst_dummy_install_property (GstDummy *
klass);
static void gst_dummy_set_property (GObject * object,
guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_dummy_get_property (GObject * object,
guint prop_id,
GValue * value, GParamSpec * pspec);
static GstStateChangeReturn gst_dummy_change_state
(GstElement * element,
GstStateChange transition);
static gboolean gst_dummy_activate (GstPad * pad);
static void gst_dummy_create_audio_sourcepad
(GstDummy * src);
static void gst_dummy_destroy_audio_sourcepad
(GstDummy * src);
static void gst_dummy_create_video_sourcepad
(GstDummy * src);
static void gst_dummy_destroy_video_sourcepad
(GstDummy * src);
static gboolean gst_dummy_audio_src_activate_push
(GstPad * pad, gboolean active);
static gboolean gst_dummy_video_src_activate_push
(GstPad * pad, gboolean active);
static void gst_dummy_main_loop (GstDummy * src);
static void gst_dummy_start_main_loop(GstDummy * src);
static void gst_dummy_audio_loop (GstPad * pad);
static void gst_dummy_video_loop (GstPad * pad);
static gboolean gst_dummy_commit_state(GstDummy *
src);
GstElementClass *parent_class = NULL;
GType
gst_dummy_get_type (void)
{
static GType dummy_type = 0;
if (!dummy_type) {
static const GTypeInfo dummy_info = {
sizeof (GstDummyClass),
gst_dummy_base_init,
NULL,
(GClassInitFunc) gst_dummy_class_init,
NULL,
NULL,
sizeof (GstDummy),
0,
(GInstanceInitFunc) gst_dummy_init,
NULL
};
dummy_type =
g_type_register_static (GST_TYPE_ELEMENT,
"GstDummy", &dummy_info,
0);
}
return dummy_type;
}
static void
gst_dummy_base_init (gpointer g_class)
{
GstElementClass *element_class = GST_ELEMENT_CLASS
(g_class);
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get
(&audio_srctemplate));
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get
(&video_srctemplate));
gst_element_class_set_details (element_class,
&gst_dummy_details);
}
static void
gst_dummy_class_init (GstDummy * klass)
{
GObjectClass *gobject_class;
GstElementClass *gstelement_class;
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
gobject_class->set_property =
gst_dummy_set_property;
gobject_class->get_property =
gst_dummy_get_property;
gst_dummy_install_property (klass);
gstelement_class->change_state =
gst_dummy_change_state;
}
static void
gst_dummy_init (GstDummy * src, GstDummyClass * klass)
{
/* FILL THE INIT */
}
static void
gst_dummy_install_property (GstDummy * klass)
{
}
static void
gst_dummy_set_property (GObject * object, guint
prop_id, const GValue * value, GParamSpec * pspec)
{
}
static
void gst_dummy_get_property (GObject * object, guint
prop_id, GValue * value, GParamSpec * pspec)
{
}
static GstStateChangeReturn
gst_dummy_change_state (GstElement * element,
GstStateChange transition)
{
GstDummy *src;
gboolean no_preroll = FALSE;
gboolean do_async = FALSE;
GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
src = GST_DUMMY (element);
switch (transition) {
case GST_STATE_CHANGE_NULL_TO_READY:
g_print ("%s:%s():%d - In case
GST_STATE_CHANGE_NULL_TO_READY \n", __FILE__,
__FUNCTION__, __LINE__ );
/* Using Mutex to trigger the flow in play state
*/
src->trigger_lock=g_mutex_new();
g_mutex_lock(src->trigger_lock);
gst_dummy_start_main_loop(src);
g_print ("%s:%s():%d - Setting return value as
GST_STATE_CHANGE_ASYNC \n", __FILE__, __FUNCTION__,
__LINE__ );
do_async = TRUE;
break;
case GST_STATE_CHANGE_READY_TO_PAUSED:
g_print ("%s:%s():%d - In case
GST_STATE_CHANGE_READY_TO_PAUSED \n", __FILE__,
__FUNCTION__, __LINE__ );
// no_preroll = TRUE;
g_print ("%s:%s():%d - Trigger the Lock to start
Playing \n", __FILE__, __FUNCTION__, __LINE__ );
g_mutex_unlock(src->trigger_lock);
break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
g_print ("%s:%s():%d - In case
GST_STATE_CHANGE_PAUSED_TO_PLAYING \n", __FILE__,
__FUNCTION__, __LINE__ );
break;
default:
break;
}
ret = GST_ELEMENT_CLASS (parent_class)->change_state
(element, transition);
if (ret == GST_STATE_CHANGE_FAILURE)
goto done;
switch (transition) {
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
g_print ("%s:%s():%d - In case
GST_STATE_CHANGE_PLAYING_TO_PAUSED \n", __FILE__,
__FUNCTION__, __LINE__ );
gst_pad_push_event (GST_DUMMY_AUDIO_PAD(src),
gst_event_new_flush_start());
gst_pad_push_event (GST_DUMMY_VIDEO_PAD(src),
gst_event_new_flush_start ());
g_print ("%s:%s():%d - Pausing audio pad task
\n", __FILE__, __FUNCTION__, __LINE__ );
if( TRUE ==
gst_pad_pause_task(GST_DUMMY_AUDIO_PAD(src)))
g_print ("%s:%s():%d - Paused audio pad task
\n", __FILE__, __FUNCTION__, __LINE__ );
else
g_print ("%s:%s():%d - Failed to pause audio
pad task \n", __FILE__, __FUNCTION__, __LINE__ );
g_print ("%s:%s():%d - Pausing video pad task
\n", __FILE__, __FUNCTION__, __LINE__ );
if( TRUE ==
gst_pad_pause_task(GST_DUMMY_VIDEO_PAD(src)))
g_print ("%s:%s():%d - Paused video pad task
\n", __FILE__, __FUNCTION__, __LINE__ );
else
g_print ("%s:%s():%d - Failed to pause video
pad task \n", __FILE__, __FUNCTION__, __LINE__ );
no_preroll = TRUE;
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
g_print ("%s:%s():%d - Destroy the audio/video
source pad \n", __FILE__, __FUNCTION__, __LINE__ );
g_print ("%s:%s():%d - Stopping audio pad task
\n", __FILE__, __FUNCTION__, __LINE__ );
if( TRUE ==
gst_pad_stop_task(GST_DUMMY_AUDIO_PAD(src)))
g_print ("%s:%s():%d - Stopped audio pad task
\n", __FILE__, __FUNCTION__, __LINE__ );
else
g_print ("%s:%s():%d - Failed to stop audio
pad task \n", __FILE__, __FUNCTION__, __LINE__ );
g_print ("%s:%s():%d - Stopping video pad task
\n", __FILE__, __FUNCTION__, __LINE__ );
if( TRUE ==
gst_pad_stop_task(GST_DUMMY_VIDEO_PAD(src)))
g_print ("%s:%s():%d - Stopped video pad task
\n", __FILE__, __FUNCTION__, __LINE__ );
else
g_print ("%s:%s():%d - Failed to stop video
pad task \n", __FILE__, __FUNCTION__, __LINE__ );
g_print ("%s:%s():%d - Stopping main loop task
\n", __FILE__, __FUNCTION__, __LINE__ );
// gst_task_stop (src->main_task);
break;
case GST_STATE_CHANGE_READY_TO_NULL:
g_print ("%s:%s():%d - In case
GST_STATE_CHANGE_READY_TO_NULL \n", __FILE__,
__FUNCTION__, __LINE__ );
gst_dummy_destroy_audio_sourcepad (src);
gst_dummy_destroy_video_sourcepad (src);
break;
default:
break;
}
if (no_preroll && ret == GST_STATE_CHANGE_SUCCESS)
ret = GST_STATE_CHANGE_NO_PREROLL;
if (do_async && ret == GST_STATE_CHANGE_SUCCESS)
ret = GST_STATE_CHANGE_ASYNC;
done:
return ret;
}
static gboolean
gst_dummy_activate (GstPad * pad)
{
g_print ("%s:%s():%d - DUMMY \n", __FILE__,
__FUNCTION__, __LINE__ );
return gst_pad_activate_push (pad, TRUE);
}
static gboolean
gst_dummy_audio_src_activate_push(GstPad * pad,
gboolean active)
{
g_print ("%s:%s():%d - Activate push on Audio source
pad \n", __FILE__, __FUNCTION__, __LINE__ );
if (active) {
return gst_pad_start_task (pad,
(GstTaskFunction)gst_dummy_audio_loop , pad);
} else {
return gst_pad_stop_task (pad);
}
}
static gboolean
gst_dummy_video_src_activate_push(GstPad * pad,
gboolean active)
{
g_print ("%s:%s():%d - Activate push on Video source
pad \n", __FILE__, __FUNCTION__, __LINE__ );
if (active) {
return gst_pad_start_task (pad,
(GstTaskFunction)gst_dummy_video_loop , pad);
} else {
return gst_pad_stop_task (pad);
}
}
static void
gst_dummy_create_audio_sourcepad (GstDummy * src)
{
GstPadTemplate *templ;
g_print ("%s:%s():%d - Create Audio source pad \n",
__FILE__, __FUNCTION__, __LINE__ );
gst_dummy_destroy_audio_sourcepad (src);
/* source */
templ = gst_static_pad_template_get
(&audio_srctemplate);
GST_DUMMY_AUDIO_PAD(src) = gst_pad_new_from_template
(templ, "audio_src");
gst_object_unref (templ);
gst_pad_set_activate_function
(GST_DUMMY_AUDIO_PAD(src), gst_dummy_activate);
gst_pad_set_activatepush_function
(GST_DUMMY_AUDIO_PAD(src),
GST_DEBUG_FUNCPTR
(gst_dummy_audio_src_activate_push));
gst_pad_set_active (GST_DUMMY_AUDIO_PAD (src),
TRUE);
gst_element_add_pad (GST_ELEMENT (src),
GST_DUMMY_AUDIO_PAD (src));
}
static void
gst_dummy_destroy_audio_sourcepad (GstDummy * src)
{
g_print ("%s:%s():%d - Destroy Audio source pad
\n", __FILE__, __FUNCTION__, __LINE__ );
if (GST_DUMMY_AUDIO_PAD(src)) {
gst_element_remove_pad (GST_ELEMENT (src),
GST_DUMMY_AUDIO_PAD(src));
GST_DUMMY_AUDIO_PAD(src) = NULL;
}
}
static void
gst_dummy_create_video_sourcepad (GstDummy * src)
{
GstPadTemplate *templ;
g_print ("%s:%s():%d - Create Video source pad \n",
__FILE__, __FUNCTION__, __LINE__ );
gst_dummy_destroy_video_sourcepad (src);
/* source */
templ = gst_static_pad_template_get
(&video_srctemplate);
GST_DUMMY_VIDEO_PAD(src) = gst_pad_new_from_template
(templ, "video_src");
gst_object_unref (templ);
gst_pad_set_activate_function
(GST_DUMMY_VIDEO_PAD(src), gst_dummy_activate);
gst_pad_set_activatepush_function
(GST_DUMMY_VIDEO_PAD(src),
GST_DEBUG_FUNCPTR
(gst_dummy_video_src_activate_push));
gst_pad_set_active (GST_DUMMY_VIDEO_PAD (src),
TRUE);
gst_element_add_pad (GST_ELEMENT (src),
GST_DUMMY_VIDEO_PAD (src));
}
static void
gst_dummy_destroy_video_sourcepad (GstDummy * src)
{
g_print ("%s:%s():%d - Destroy Video source pad
\n", __FILE__, __FUNCTION__, __LINE__ );
if (GST_DUMMY_VIDEO_PAD(src)) {
gst_element_remove_pad (GST_ELEMENT (src),
GST_DUMMY_VIDEO_PAD(src));
GST_DUMMY_VIDEO_PAD(src) = NULL;
}
}
static void
gst_dummy_audio_loop (GstPad * pad)
{
GstBuffer *dummybuf ;
GstFlowReturn ret ;
static int i = 0 ;
dummybuf = gst_buffer_new_and_alloc (sizeof(int));
gst_buffer_set_data( dummybuf, (guint8 *)&i ,
sizeof(int));
while ( TRUE != gst_pad_is_linked(pad) ){
g_print("gst_dummy_audio_loop: Audio pad not
linked ");
sleep(2);
}
g_print ("%s:%s():%d - Pushing Audio data buffer %d
\n", __FILE__, __FUNCTION__, __LINE__, i );
ret = gst_pad_push( pad, dummybuf);
if( GST_FLOW_OK != ret ){
g_print ("%s:%s():%d - Error pushing the data
across the pad \n", __FILE__, __FUNCTION__, __LINE__
);
gst_pad_pause_task(pad) ;
}
i++ ;
sleep(1);
if ( NUMBER_OF_BUFFERS == i ){
gst_pad_push_event (pad, gst_event_new_eos ());
}
}
static void
gst_dummy_video_loop (GstPad * pad)
{
GstBuffer *dummybuf ;
GstFlowReturn ret ;
static int i = 0 ;
dummybuf = gst_buffer_new_and_alloc (sizeof(int));
gst_buffer_set_data( dummybuf, (guint8 *)&i ,
sizeof(int));
while ( TRUE != gst_pad_is_linked(pad) ){
g_print("gst_dummy_video_loop: Video pad not
linked ");
sleep(2);
}
g_print ("%s:%s():%d - Pushing Video data buffer %d
\n", __FILE__, __FUNCTION__, __LINE__, i );
ret = gst_pad_push( pad, dummybuf);
if( GST_FLOW_OK != ret ){
g_print ("%s:%s():%d - Error pushing the data
across the pad \n", __FILE__, __FUNCTION__, __LINE__
);
gst_pad_pause_task(pad) ;
}
i++ ;
sleep(1);
if ( NUMBER_OF_BUFFERS == i ){
gst_pad_push_event (pad, gst_event_new_eos ());
}
}
static void
gst_dummy_main_loop (GstDummy * src)
{
g_print ("%s:%s():%d - Executing Main task Loop
\n", __FILE__, __FUNCTION__, __LINE__ );
g_print ("%s:%s():%d - Simulating initial setup by
sleeping for 2 sec \n", __FILE__, __FUNCTION__,
__LINE__ );
sleep(2) ;
g_print ("%s:%s():%d - Simulation of initial setup
done \n", __FILE__, __FUNCTION__, __LINE__ );
/* Commit READY state */
gst_dummy_commit_state (src) ;
/* Parse the data */
g_print ("%s:%s():%d - Waiting on lock for play
trigger \n", __FILE__, __FUNCTION__, __LINE__ );
g_mutex_lock(src->trigger_lock);
/* Now the data type is known , so create the
appropriate source pads */
g_print ("%s:%s():%d - Data processing simulation
done ... create output pads \n", __FILE__,
__FUNCTION__, __LINE__ );
gst_dummy_create_audio_sourcepad (src);
gst_dummy_create_video_sourcepad (src);
gst_element_no_more_pads (GST_ELEMENT(src));
g_mutex_unlock(src->trigger_lock);
}
static void
gst_dummy_start_main_loop(GstDummy * src)
{
pthread_t thread ;
g_print ("%s:%s():%d - Do pthread_create for Main
task Loop \n", __FILE__, __FUNCTION__, __LINE__ );
pthread_create( &thread, NULL, (void
*)&gst_dummy_main_loop, (void*) src);
}
static gboolean
gst_dummy_commit_state(GstDummy * src)
{
g_print ("%s:%s():%d - Commit state change \n",
__FILE__, __FUNCTION__, __LINE__ );
GstStateChangeReturn state_return ;
state_return = gst_element_continue_state (
GST_ELEMENT(src), GST_STATE_CHANGE_SUCCESS);
g_print ("%s:%s():%d - Commit state returned %d \n",
__FILE__, __FUNCTION__, __LINE__, state_return );
return state_return ;
}
static gboolean
plugin_init (GstPlugin * plugin)
{
if (!gst_element_register (plugin, "dummy",
GST_RANK_NONE,
GST_TYPE_DUMMY))
return FALSE;
return TRUE;
}
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
GST_VERSION_MINOR,
"dummy",
"DUMMY",
plugin_init,
VERSION,
GST_LICENSE_UNKNOWN,
"GStreamer",
"")
-------------------------------------------------------
/****** File : gstdummy.h **************/
#ifndef __GST_DUMMY_H__
#define __GST_DUMMY_H__
#include <gst/gst.h>
#include <pthread.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define GST_TYPE_DUMMY \
(gst_dummy_get_type())
#define GST_DUMMY(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DUMMY,GstDummy))
#define GST_DUMMY_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DUMMY,GstDummy))
#define GST_IS_DUMMY(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DUMMY))
#define GST_IS_DUMMY_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DUMMY))
typedef struct _GstDummy GstDummy;
typedef struct _GstDummyClass GstDummyClass;
struct _GstDummy {
GstElement element;
/* pads */
GstPad *audio_srcpad;
GstPad *video_srcpad;
/*=========== HACK ==========*/
/* Tasks for processing */
GstTask *main_task;
GStaticRecMutex main_task_lock;
GMutex* trigger_lock;
};
struct _GstDummyClass{
GstElementClass parent_class;
};
GType gst_dummy_get_type(void);
#define GST_DUMMY_CAST(obj) ((GstDummy
*)(obj))
#define GST_DUMMY_AUDIO_PAD(obj) (GST_DUMMY_CAST
(obj)->audio_srcpad)
#define GST_DUMMY_VIDEO_PAD(obj) (GST_DUMMY_CAST
(obj)->video_srcpad)
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GST_DUMMY_H__ */
-------------------------------------------------
#############################
# File : Makefile.am
#############################
plugin_LTLIBRARIES = libgstdummy.la
libgstdummy_la_SOURCES = gstdummy.c
libgstdummy_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS)
$(GST_CFLAGS) \
-I$(top_srcdir)/gst-libs
libgstdummy_la_LIBADD = -lgstriff- at GST_MAJORMINOR@
$(GST_PLUGINS_BASE_LIBS)
libgstdummy_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
noinst_HEADERS = gstdummy.h
__________________________________________________________
Yahoo! India Answers: Share what you know. Learn something new
http://in.answers.yahoo.com/
More information about the gstreamer-devel
mailing list