[prev in list] [next in list] [prev in thread] [next in thread] 

List:       gstreamer-devel
Subject:    Re: [gst-devel] GStreamer and audio and video bins
From:       Oscar_Östlund <oscar.ostlund () gmail ! com>
Date:       2008-11-26 4:52:08
Message-ID: 8E6E350B-457A-4F93-9973-130522F1C50C () gmail ! com
[Download RAW message or body]

Hi

I have a beginner question here.

I wrote an email a few days ago. I still haven't managed to solve it  
yet. I have attached a file that gives an example of the problem(ther  
might be unreffed variables but that shouldn't be the problem here).  
If you uncomment line 267, it doesn't work anymore.

Does anyone have a clue ?

Than you in advance

Oscar


["main.c" (main.c)]

#include <glib.h>
#include <gst/gst.h>



GstElement *pipeline_;
GstElement *dec_, *audio_, *video_;
GMainLoop *loop_;


void pipeline_func (gpointer data, gpointer user_data){
  GstElement * elt = (GstElement*) data;
  gchar * name = gst_element_get_name(elt);
  char * states_to_string[] = {
    "GST_STATE_VOID_PENDING", 
      "GST_STATE_NULL",
      "GST_STATE_READY",
      "GST_STATE_PAUSED",
      "GST_STATE_PLAYING",
    };
        // gst_message_parse_state_changed (msg, &oldstate, &newstate, &pending);
    //       // 
          // g_print ("State changed: \n old: %s\n new: %s\n pending: %s\n",
          //   states_to_string[(int)oldstate], 
          //   states_to_string[(int)newstate], 
          //   states_to_string[(int)pending]);
    GstState state, pending;
    gst_element_get_state (elt,&state, &pending, GST_CLOCK_TIME_NONE );
    g_print("Element :%s\n  state: %s\n",name, states_to_string[(int)state]);
    g_free(name);
  }
  static void
    print_tag (const GstTagList * list, const gchar * tag, gpointer unused)
  {
    gint i, count;

    count = gst_tag_list_get_tag_size (list, tag);

    for (i = 0; i < count; i++) {
      gchar *str;

      if (gst_tag_get_type (tag) == G_TYPE_STRING) {
        if (!gst_tag_list_get_string_index (list, tag, i, &str))
          g_assert_not_reached ();
      } else {
        str =
          g_strdup_value_contents (gst_tag_list_get_value_index (list, tag, i));
      }

      if (i == 0) {
        g_print ("  %15s: %s\n", gst_tag_get_nick (tag), str);
      } else {
        g_print ("                 : %s\n", str);
      }

      g_free (str);
    }
  }

  static gboolean
    bus_call (GstBus     *bus,
    GstMessage *msg,
    gpointer    data)
  {
    GMainLoop *loop = (GMainLoop *) data;

    GstIterator*  it = gst_bin_iterate_recurse((GstBin*)(pipeline_));
    gst_iterator_foreach(it,pipeline_func,NULL);
    gst_iterator_free(it);
    switch (GST_MESSAGE_TYPE (msg)) {

      case GST_MESSAGE_EOS:
      g_print ("End of stream\n");
      g_main_loop_quit (loop);
      break;

      case GST_MESSAGE_ERROR: {
        gchar  *debug;
        GError *error;

        gst_message_parse_error (msg, &error, &debug);
        g_printerr ("Error: %s\n", debug);

        g_free (debug);

        g_printerr ("Error: %s\n", error->message);
        g_error_free (error);

        g_main_loop_quit (loop);
        break;
      }
      case GST_MESSAGE_INFO: {
        gchar  *debug;
        GError *error;

        gst_message_parse_info (msg, &error, &debug);
        g_printerr ("Info: %s\n", debug);

        g_free (debug);

        g_printerr ("Info: %s\n", error->message);
        g_error_free (error);

        break;
      }
      case GST_MESSAGE_TAG: {
        GstTagList *tag_list;

        g_printerr ("\n\nTags:\n");
        gst_message_parse_tag (msg, &tag_list);
        gst_tag_list_foreach (tag_list, print_tag, NULL);
        gst_tag_list_free (tag_list);

        break;
      }
      case GST_MESSAGE_STATE_CHANGED : {
        // GstState oldstate, newstate, pending;
        // char * states_to_string[] = {
        //      "GST_STATE_VOID_PENDING", 
        //      "GST_STATE_NULL",
        //      "GST_STATE_READY",
        //      "GST_STATE_PAUSED",
        //      "GST_STATE_PLAYING",
        //    };
        // gst_message_parse_state_changed (msg, &oldstate, &newstate, &pending);
        //       // 
              // g_print ("State changed: \n old: %s\n new: %s\n pending: %s\n",
              //   states_to_string[(int)oldstate], 
              //   states_to_string[(int)newstate], 
              //   states_to_string[(int)pending]);

        break;
      }
      default: {
        g_print ("\n----Message type: %d\n", GST_MESSAGE_TYPE (msg));
        break;
      }
    }
    return TRUE;
  }
  
  void
  audiopadNew(GstPad *_pad){
    GstPad *audiopad;

    /* only link once */
    g_print ("create audio pad\n");
    audiopad = gst_element_get_static_pad (audio_, "audiosink");
    if (GST_PAD_IS_LINKED (audiopad)) {
      g_object_unref (audiopad);
      g_print ("audiopad is already linked\n");
      return;
    }

    g_print ("link audio pad\n");
    gst_pad_link(_pad, audiopad);    
  }
  
  void
  videopadNew(GstPad *_pad){
    GstPad *videopad;

    /* only link once */
    g_print ("---\ncreate video pad\n");
    videopad = gst_element_get_static_pad (video_, "videosink");
    if (GST_PAD_IS_LINKED (videopad)) {
      g_object_unref (videopad);
      g_print ("videopad is already linked\n---\n");
      return;
    }
  }


  static void
    cb_newpad (GstElement *decodebin,
    GstPad     *_pad,
    gboolean    _last,
    gpointer    _data)
  {
    GstCaps *caps;
    GstStructure *str;

    /* check media type */
    g_print ("get caps\n");

    caps = gst_pad_get_caps (_pad);
    str = gst_caps_get_structure (caps, 0);
    gchar * s = gst_structure_to_string(str);
    g_print( "caps: \n %s\n\n", s);

    /* check audio */
    if (g_strrstr (gst_structure_get_name (str), "audio")) {
      audiopadNew(_pad);
    }
    else{
      g_print ("caps dont have audio\n");
    }

    /* check video */
    if (g_strrstr (gst_structure_get_name (str), "video")) {
      videopadNew(_pad);
    }
    else{
      g_print ("caps dont have video\n");
    }
    gst_caps_unref (caps);
    gst_element_set_state (dec_, GST_STATE_PLAYING);

    gst_element_set_state (pipeline_, GST_STATE_PLAYING);

  }



  void
  createAudiobin(){
    GstElement *queue, *conv, *sink;
    GstPad *audiopad;
    g_print ("create audiobin\n");

    /* create audio output */
    audio_ = gst_bin_new ("audiobin");

    queue = gst_element_factory_make ("queue", "audioqueue");
    g_assert (queue != NULL);
    audiopad = gst_element_get_static_pad (queue, "sink");

    conv = gst_element_factory_make ("audioconvert", "aconv");
    sink = gst_element_factory_make ("osxaudiosink", "myaudiosink");
    gst_bin_add_many (GST_BIN (audio_), queue, conv, sink, NULL);
    gst_element_link_many (queue, conv, sink, NULL );

    g_print ("audio is element :%d\n", GST_IS_ELEMENT(audio_));

    gst_element_add_pad (audio_,
      gst_ghost_pad_new ("audiosink", audiopad));
    gst_object_unref (audiopad);

    g_print ("add audiobin to pipeline\n");
    gst_bin_add (GST_BIN (pipeline_), audio_);

  }
  void
  createVideobin(){
    GstElement *queue, *sink, *cspace;
    GstPad *videopad;
    g_print ("create videobin\n");

    /* create video output */
    video_ = gst_bin_new ("videobin");
    queue = gst_element_factory_make ("queue", "videoqueue");
    g_assert (queue != NULL);
    videopad = gst_element_get_static_pad (queue, "sink");

    cspace = gst_element_factory_make ("ffmpegcolorspace", "ffmpegcolorspace");
    sink = gst_element_factory_make ("autovideosink", "myvideosink");
    gst_bin_add_many (GST_BIN (video_), queue, cspace, sink, NULL);
    gst_element_link_many (queue, cspace, sink, NULL);

    g_print ("video is element :%d\n", GST_IS_ELEMENT(video_));

    gst_element_add_pad (video_,
      gst_ghost_pad_new ("audiosink", videopad));
    gst_object_unref (videopad);

    g_print ("add videobin to pipeline\n");
    //gst_bin_add (GST_BIN (pipeline_), video_);		
  }




  void
  sourceAdd(char * source){

    GstElement *src;
    g_print ("Add source: %s\n",source);
    g_print ("create filesrc\n");

    src = gst_element_factory_make ("filesrc", "source");
    g_object_set (G_OBJECT (src), "location", source, NULL);

    g_print ("create decodebin\n");
    dec_ = gst_element_factory_make ("decodebin2", "decoder");
    g_signal_connect (dec_, "new-decoded-pad", G_CALLBACK(&cb_newpad), NULL);	  
    gst_bin_add_many (GST_BIN (pipeline_), src, dec_, NULL);
    gst_element_link (src, dec_);

  }

  int main(int argc, char* argv[]) {
    GstBus *bus;

    /* Initialisation */
    g_print ("init\n");
    gst_init (&argc, &argv);
    loop_ = g_main_loop_new (NULL, FALSE);

    /* set up */
    g_print ("setup pipeline\n");
    pipeline_ = gst_pipeline_new ("mypipeline");
    bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline_));
    gst_bus_add_watch (bus, bus_call, loop_);
    gst_object_unref (bus);

    createAudiobin();
    createVideobin();
    
    sourceAdd(argv[1]);
    
    gst_element_set_state (pipeline_, GST_STATE_PLAYING);
    
    GstIterator*  it = gst_bin_iterate_recurse((GstBin*)pipeline_);
    gst_iterator_foreach(it,pipeline_func,NULL);
       /* Iterate */
    g_print ("Running...\n");
    g_main_loop_run (loop_);  
    g_print ("Finished running...\n");
     
    
    gst_element_set_state (pipeline_, GST_STATE_NULL);
    
    if(pipeline_){
      gst_element_set_state (pipeline_, GST_STATE_NULL);
      g_print ("Deleting pipeline\n");
      gst_object_unref (GST_OBJECT (pipeline_));
    }
    return 0;
  }


PS: compile with
gcc -Wall $(pkg-config --cflags --libs gstreamer-0.10) main.c -o test1
run with
./test1 filename.ogg


Le 23 nov. 08 à 18:15, Oscar Östlund a écrit :

> Hi
>
> I am pretty new on GStreamer. I am trying to setup an appliaction  
> that uses this cool library.
>
> I have a problem. This is the following setup I use:
> pipeline:
>  - filersrc
>  - decodebin
>  - videodin (type: bin)
>    * ffmpegcolorspace
>    * autovideosink
>  - audiobin (type: bin)
>    * audioconverter
>    * autoaudiosink
>
> So I create the audiobin et videobin first, and add them to the  
> pipeline. Then create the filesrc and the decodebin. A callback is  
> called on new-decoded-pad. This one links the audiobin's and the  
> video bin's ghost pads to the decoder if appliacable. Then I set the  
> state to playing and start the main loop.
>
> If the file is Ogg/Vorbis, then it doesn't work. If I create the  
> videobin but I don't add the videobin to the pipeline, it works  
> fine. If on the other hand I create the videobin and then add it  
> (even if it doesn't get linked), then everything works fine until I  
> start the main loop. Then it just waits and doesn't play the music.  
> It just open the viedo window and runs the mainloop but doesn't play  
> anything. On the other hand, if the file is Ogg/Theora. Then  
> everything works perfectly, in both situations.
>
> Now I have a second problem. If I don't create the videobin, things  
> work fine... as long as I add the audiobin to the pipeline not in  
> the new-decoded-pad callback. My thought was that I wanted to add  
> the video and audiobin to the pipeline only if needed. Apparently, I  
> can't add them in the callback. Is that due to the fact that the  
> callback is called in another thread (if it is) ??
>
> Do you have any idea ?
>
> Thank you for your help.
>
> Oscar
>
> PS I am running GStreamer on MacOSX.
>
> PSS:
> In the normal case, the bus gets a GST_MESSAGE_TAG, then a  
> GST_MESSAGE_ASYNC_DONE and finally GST_MESSAGE_NEW_CLOCK
> When I add the videobin to the pipeline, the bus receives the  
> GST_MESSAGE_TAG but then nothing, just waits...



-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

_______________________________________________
gstreamer-devel mailing list
gstreamer-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/gstreamer-devel


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic