[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