Advertisement
enginy88

Gstreamer C

Apr 9th, 2012
147
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 17.65 KB | None | 0 0
  1. /*COMPILATION: gcc -g -Wall -O2 work1.c -o work1 `pkg-config --libs --cflags gtk+-2.0 glib-2.0 gstreamer-0.10  gstreamer-interfaces-0.10` -export-dynamic */
  2.  
  3. #include <gst/gst.h>
  4. #include <gtk/gtk.h>
  5. #include <gst/interfaces/xoverlay.h>
  6. #include <gdk/gdkx.h>
  7.  
  8. static const char _GUI[] =
  9. "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
  10. "<interface>"
  11. "  <requires lib=\"gtk+\" version=\"2.24\"/>"
  12. "  <!-- interface-naming-policy project-wide -->"
  13. "  <object class=\"GtkWindow\" id=\"window\">"
  14. "    <property name=\"can_focus\">False</property>"
  15. "    <child>"
  16. "      <object class=\"GtkVBox\" id=\"vbox1\">"
  17. "        <property name=\"visible\">True</property>"
  18. "        <property name=\"can_focus\">False</property>"
  19. "        <child>"
  20. "          <object class=\"GtkHBox\" id=\"hbox1\">"
  21. "            <property name=\"visible\">True</property>"
  22. "            <property name=\"can_focus\">False</property>"
  23. "            <child>"
  24. "              <object class=\"GtkButton\" id=\"button1\">"
  25. "                <property name=\"label\" translatable=\"yes\">button</property>"
  26. "                <property name=\"visible\">True</property>"
  27. "                <property name=\"can_focus\">True</property>"
  28. "                <property name=\"receives_default\">True</property>"
  29. "                <property name=\"use_action_appearance\">False</property>"
  30. "              </object>"
  31. "              <packing>"
  32. "                <property name=\"expand\">True</property>"
  33. "                <property name=\"fill\">True</property>"
  34. "                <property name=\"position\">0</property>"
  35. "              </packing>"
  36. "            </child>"
  37. "            <child>"
  38. "              <object class=\"GtkButton\" id=\"button2\">"
  39. "                <property name=\"label\" translatable=\"yes\">button</property>"
  40. "                <property name=\"visible\">True</property>"
  41. "                <property name=\"can_focus\">True</property>"
  42. "                <property name=\"receives_default\">True</property>"
  43. "                <property name=\"use_action_appearance\">False</property>"
  44. "              </object>"
  45. "              <packing>"
  46. "                <property name=\"expand\">True</property>"
  47. "                <property name=\"fill\">True</property>"
  48. "                <property name=\"position\">1</property>"
  49. "              </packing>"
  50. "            </child>"
  51. "            <child>"
  52. "              <object class=\"GtkButton\" id=\"button3\">"
  53. "                <property name=\"label\" translatable=\"yes\">button</property>"
  54. "                <property name=\"visible\">True</property>"
  55. "                <property name=\"can_focus\">True</property>"
  56. "                <property name=\"receives_default\">True</property>"
  57. "                <property name=\"use_action_appearance\">False</property>"
  58. "              </object>"
  59. "              <packing>"
  60. "                <property name=\"expand\">True</property>"
  61. "                <property name=\"fill\">True</property>"
  62. "                <property name=\"position\">2</property>"
  63. "              </packing>"
  64. "            </child>"
  65. "            <child>"
  66. "              <object class=\"GtkButton\" id=\"button4\">"
  67. "                <property name=\"label\" translatable=\"yes\">button</property>"
  68. "                <property name=\"visible\">True</property>"
  69. "                <property name=\"can_focus\">True</property>"
  70. "                <property name=\"receives_default\">True</property>"
  71. "                <property name=\"use_action_appearance\">False</property>"
  72. "              </object>"
  73. "              <packing>"
  74. "                <property name=\"expand\">True</property>"
  75. "                <property name=\"fill\">True</property>"
  76. "                <property name=\"position\">3</property>"
  77. "              </packing>"
  78. "            </child>"
  79. "          </object>"
  80. "          <packing>"
  81. "            <property name=\"expand\">False</property>"
  82. "            <property name=\"fill\">True</property>"
  83. "            <property name=\"position\">0</property>"
  84. "          </packing>"
  85. "        </child>"
  86. "        <child>"
  87. "          <object class=\"GtkDrawingArea\" id=\"drawingarea\">"
  88. "            <property name=\"width_request\">1600</property>"
  89. "            <property name=\"height_request\">600</property>"
  90. "            <property name=\"visible\">True</property>"
  91. "            <property name=\"can_focus\">False</property>"
  92. "          </object>"
  93. "          <packing>"
  94. "            <property name=\"expand\">True</property>"
  95. "            <property name=\"fill\">True</property>"
  96. "            <property name=\"position\">1</property>"
  97. "          </packing>"
  98. "        </child>"
  99. "        <child>"
  100. "          <object class=\"GtkLabel\" id=\"label\">"
  101. "            <property name=\"visible\">True</property>"
  102. "            <property name=\"can_focus\">False</property>"
  103. "            <property name=\"label\" translatable=\"yes\">label</property>"
  104. "          </object>"
  105. "          <packing>"
  106. "            <property name=\"expand\">False</property>"
  107. "            <property name=\"fill\">True</property>"
  108. "            <property name=\"position\">2</property>"
  109. "          </packing>"
  110. "        </child>"
  111. "      </object>"
  112. "    </child>"
  113. "  </object>"
  114. "</interface>";
  115.  
  116.  
  117.  
  118. GstElement *pipeline;
  119.  
  120. static gboolean expose_cb(GtkWidget* widget, GdkEventExpose* event, GstElement* videosink) {
  121.     g_print ("expose_cb\n");
  122.     //expose callback is garanted to be called after realized callback
  123.     gst_x_overlay_expose (GST_X_OVERLAY (videosink));
  124.     return FALSE;
  125. }
  126.  
  127. static GstBusSyncReply bus_call(GstBus * bus, GstMessage *message, gpointer data) {
  128.     GtkWidget *window = (GtkWidget*) data;
  129.     g_print("***Got message: %s\n", GST_MESSAGE_TYPE_NAME(message));
  130.     // ignore anything but 'prepare-xwindow-id' element messages
  131.     if (GST_MESSAGE_TYPE(message) == GST_MESSAGE_ERROR){
  132.         GError *err;
  133.         gchar *debug;
  134.         gst_message_parse_error(message, &err, &debug);
  135.         g_print("******ERR:%s\n", err->message);
  136.         g_print("******ERR:%s\n", debug);
  137.         g_error_free(err);
  138.         g_free(debug);
  139.         return GST_BUS_PASS;
  140.     }
  141.     if (GST_MESSAGE_TYPE(message) == GST_MESSAGE_WARNING){
  142.         GError *warn;
  143.         gchar *debug;
  144.         gst_message_parse_error(message, &warn, &debug);
  145.         g_print("******ERR:%s\n", warn->message);
  146.         g_error_free(warn);
  147.         g_free(debug);
  148.         return GST_BUS_PASS;
  149.     }
  150.     if (GST_MESSAGE_TYPE(message) != GST_MESSAGE_ELEMENT)
  151.         return GST_BUS_PASS;
  152.     if (!gst_structure_has_name(message->structure, "prepare-xwindow-id"))
  153.         return GST_BUS_PASS;
  154.     g_print("Got prepare-xwindow-id msg\n");
  155.     gst_x_overlay_set_window_handle(GST_X_OVERLAY(GST_MESSAGE_SRC(message)), GDK_WINDOW_XWINDOW(window->window));
  156.     //~ gst_message_unref (message);
  157.     return GST_BUS_PASS;
  158. }
  159.  
  160. static void area_realize_cb(GtkWidget* widget, GstElement* pipeline) {
  161.     g_print ("drawing area realized\n");
  162.  
  163.     #if GTK_CHECK_VERSION(2,18,0)
  164.         if (!gdk_window_ensure_native (widget->window))
  165.             g_error ("Failed to create native window!");
  166.     #endif
  167.  
  168.     //avoid flickering when resizing or obscuring the main window
  169.     gdk_window_set_back_pixmap(widget->window, NULL, FALSE);
  170.     gtk_widget_set_app_paintable(widget,TRUE);
  171.     gtk_widget_set_double_buffered(widget, FALSE);
  172.  
  173.     gst_element_set_state (pipeline, GST_STATE_PLAYING);
  174. }
  175.  
  176. static void make_window_black(GtkWidget *window) {
  177.     GdkColor color;
  178.     gdk_color_parse("black", &color);
  179.     gtk_widget_modify_bg(window, GTK_STATE_NORMAL, &color);
  180. }
  181.  
  182. int destroy_cb(GtkWidget * widget, gpointer data) {
  183.     g_print("Window destroyed\n");
  184.     /* clean up */
  185.     gst_element_set_state(pipeline, GST_STATE_NULL);
  186.     gst_object_unref(pipeline);
  187.     gtk_main_quit();
  188.     return FALSE;
  189. }
  190.  
  191. static gboolean key_press_event_cb(GtkWidget *widget, GdkEventKey *event, gpointer data) {
  192.     if (event->keyval == 'f') {
  193.         g_print("Toggling fullscreen\n");
  194.         gboolean is_fullscreen = (gdk_window_get_state(GDK_WINDOW(widget->window)) == GDK_WINDOW_STATE_FULLSCREEN);
  195.         if (is_fullscreen)
  196.             gtk_window_unfullscreen(GTK_WINDOW(widget));
  197.         else
  198.             gtk_window_fullscreen(GTK_WINDOW(widget));
  199.         return TRUE;
  200.     }
  201.     else if (event->keyval == 'q') {
  202.         destroy_cb(widget, data);
  203.         return TRUE;
  204.     }
  205.     else {
  206.         return TRUE;
  207.     }
  208. }
  209.  
  210. static void on_pad_added (GstElement *element, GstPad *pad, gpointer data) {
  211.     gchar *padname;
  212.     GstPad *sinkpad;
  213.     GstElement *decoder = (GstElement *) data;
  214.     padname = gst_pad_get_name(pad);
  215.     g_print ("A new pad %s was created\n", padname);
  216.     if (g_str_has_prefix(padname, "recv_rtp_src_0")) { //only link video src pad / recv_rtp_src_0 is video, recv_rtp_src_1 is audio
  217.         /* We can now link this pad with the rtsp-decoder sink pad */
  218.         g_print ("%slinking source/demuxer\n", padname);
  219.         sinkpad = gst_element_get_static_pad (decoder, "sink");
  220.         gst_pad_link (pad, sinkpad);
  221.         gst_object_unref (sinkpad);
  222.     }
  223.     g_free (padname);
  224. }
  225.  
  226. //callbacks for gtk buttons
  227. static void button_state_null_cb(GtkWidget* widget, GstElement* pipeline){
  228.     gst_element_set_state (pipeline, GST_STATE_NULL);
  229.     g_print ("GST_STATE_NULL\n");
  230. }
  231. static void button_state_ready_cb(GtkWidget* widget, GstElement* pipeline){
  232.     gst_element_set_state (pipeline, GST_STATE_READY);
  233.     g_print ("GST_STATE_READY\n");
  234. }
  235. static void button_state_paused_cb(GtkWidget* widget, GstElement* pipeline){
  236.     gst_element_set_state (pipeline, GST_STATE_PAUSED);
  237.     g_print ("GST_STATE_PAUSED\n");
  238. }
  239. static void button_state_playing_cb(GtkWidget* widget, GstElement* pipeline){
  240.     gst_element_set_state (pipeline, GST_STATE_PLAYING);
  241.     g_print ("GST_STATE_PLAYING\n");
  242. }
  243.  
  244. //test callbacks
  245. void onbyessrc_cb(GstElement* rtpbin, guint session, guint ssrc, gpointer user_data){
  246.         g_print("*-*-*-*-*-*-*on-bye-ssrc\n");
  247. }
  248. void onssrcactive_cb(GstElement* rtpbin, guint session, guint ssrc, gpointer user_data){
  249.         g_print("*-*-*-*-*-*-*on-ssrc-active\n");
  250. }
  251. void onbyetimeout_cb(GstElement* rtpbin, guint session, guint ssrc, gpointer user_data){
  252.         g_print("*-*-*-*-*-*-*on-bye-timeout\n");
  253. }
  254.  
  255.  
  256. int main (gint argc, gchar *argv[]) {
  257.     GstStateChangeReturn ret;
  258.  
  259.     GstCaps *caps1;
  260.     GstCaps *caps2;
  261.  
  262.     GstElement *src1;
  263.     GstElement *src2;
  264.     GstElement *demux1;
  265.     GstElement *demux2;
  266.     GstElement *decoder1;
  267.     GstElement *decoder2;
  268.     GstElement *videorate1;
  269.     GstElement *videorate2;
  270.     GstElement *videorate3;
  271.     GstElement *colorspace1;
  272.     GstElement *colorspace2;
  273.     GstElement *colorspace3;
  274.     GstElement *colorspace4;
  275.     GstElement *videobox1;
  276.     GstElement *videobox2;
  277.     GstElement *videobox3;
  278.     GstElement *videomixer;
  279.     GstElement *videoscale1;
  280.     GstElement *videoscale2;
  281.     GstElement *videoscale3;
  282.     GstElement *par1;
  283.     GstElement *par2;
  284.     GstElement *par3;
  285.     GstElement *sink;
  286.  
  287.     GtkBuilder *builder;
  288.  
  289.     GtkWidget *window;
  290.     GtkWidget *drawingArea;
  291.     GtkWidget *button1;
  292.     GtkWidget *button2;
  293.     GtkWidget *button3;
  294.     GtkWidget *button4;
  295.  
  296.     /* initialization */
  297.     gst_init(&argc, &argv);
  298.     gtk_init(&argc, &argv);
  299.  
  300.     builder = gtk_builder_new ();
  301.     gtk_builder_add_from_string(builder, _GUI, -1, NULL);
  302.     window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
  303.     drawingArea = GTK_WIDGET (gtk_builder_get_object (builder, "drawingarea"));
  304.     button1 = GTK_WIDGET (gtk_builder_get_object (builder, "button1"));
  305.     button2 = GTK_WIDGET (gtk_builder_get_object (builder, "button2"));
  306.     button3 = GTK_WIDGET (gtk_builder_get_object (builder, "button3"));
  307.     button4 = GTK_WIDGET (gtk_builder_get_object (builder, "button4"));
  308.     gtk_builder_connect_signals (builder, NULL);
  309.     g_object_unref (G_OBJECT (builder));
  310.  
  311.     /* create elements */
  312.     pipeline = gst_pipeline_new("my_pipeline");
  313.  
  314.     videobox1 = gst_element_factory_make ("videobox", "videobox1");
  315.     videobox2 = gst_element_factory_make ("videobox", "videobox2");
  316.     videobox3 = gst_element_factory_make ("videobox", "videobox3");
  317.     videomixer = gst_element_factory_make ("videomixer", "mixer");
  318.  
  319.     src1 = gst_element_factory_make ("rtspsrc", "Source1");
  320.     src2 = gst_element_factory_make ("rtspsrc", "Source2");
  321.     demux1 = gst_element_factory_make ("rtph264depay", "Depay1");
  322.     demux2 = gst_element_factory_make ("rtpmp4vdepay", "Depay2");
  323.     decoder1 = gst_element_factory_make ("ffdec_h264", "Decoder1");
  324.     decoder2 = gst_element_factory_make ("ffdec_mpeg4", "Decoder2");
  325.     videorate1 = gst_element_factory_make ("videorate", "Videorate1");
  326.     videorate2 = gst_element_factory_make ("videorate", "Videorate2");
  327.     videorate3 = gst_element_factory_make ("videorate", "Videorate3");
  328.     colorspace1 = gst_element_factory_make ("ffmpegcolorspace", "Colorspace");
  329.     colorspace2 = gst_element_factory_make ("ffmpegcolorspace", "Colorspace2");
  330.     colorspace3 = gst_element_factory_make ("ffmpegcolorspace", "Colorspace3");
  331.     colorspace4 = gst_element_factory_make ("ffmpegcolorspace", "Colorspace4");
  332.     videoscale1 = gst_element_factory_make ("videoscale", "scalingvideo1");
  333.     videoscale2 = gst_element_factory_make ("videoscale", "scalingvideo2");
  334.     videoscale3 = gst_element_factory_make ("videoscale", "scalingvideo3");
  335.     par1 = gst_element_factory_make ("capsfilter", "capsfilter1");
  336.     par2 = gst_element_factory_make ("capsfilter", "capsfilter2");
  337.     par3 = gst_element_factory_make ("capsfilter", "capsfilter3");
  338.  
  339.     sink = gst_element_factory_make("ximagesink", "videosink");
  340.  
  341.     caps1 = gst_caps_new_simple("video/x-raw-yuv", "width", G_TYPE_INT, 320, "height", G_TYPE_INT, 240, NULL);
  342.     caps2 = gst_caps_new_simple("video/x-raw-yuv", "width", G_TYPE_INT, 320, "height", G_TYPE_INT, 240, NULL);
  343.  
  344.     g_object_set (G_OBJECT (src1), "location", "rtsp://10.0.0.50/udpstream", NULL);
  345.     g_object_set (G_OBJECT (src2), "location", "rtsp://10.0.0.51/udpstream", NULL);
  346.     //~ g_object_set (G_OBJECT (src1), "protocols", (1 << 0), NULL);
  347.     g_object_set (G_OBJECT (src1), "timeout", (guint64)1000000, NULL);
  348.     g_object_set (G_OBJECT (src2), "timeout", (guint64)1000000, NULL);
  349.     g_object_set (G_OBJECT (src1), "tcp-timeout", (guint64)1000000, NULL);
  350.     g_object_set (G_OBJECT (src2), "tcp-timeout", (guint64)1000000, NULL);
  351.     g_object_set (G_OBJECT (src1), "retry", (guint)1, NULL);
  352.     g_object_set (G_OBJECT (src2), "retry", (guint)1, NULL);
  353.     g_object_set (G_OBJECT (src1), "latency", 200, NULL);
  354.     g_object_set (G_OBJECT (src2), "latency", 200, NULL);
  355.     //~ g_object_set (G_OBJECT(par1), "caps", caps, NULL );
  356.     g_object_set (G_OBJECT(par2), "caps", caps1, NULL );
  357.     g_object_set (G_OBJECT(par3), "caps", caps2, NULL );
  358.     g_object_set(videobox1, /*"border-alpha", 0,*/ "top", -300, "left", 0, NULL);
  359.     g_object_set(videobox2, /*"border-alpha", 0,*/ "top", 0, "left", -800, NULL);
  360.     g_object_set(videobox3, /*"border-alpha", 0,*/ "top", 0, "left", 0, NULL);
  361.     g_object_set(G_OBJECT(sink), "force-aspect-ratio", TRUE, NULL);
  362.  
  363.     gst_bin_add_many (GST_BIN (pipeline), src1,src2, demux1,demux2, decoder1, decoder2, videorate1, videorate2,videorate3, colorspace1, colorspace2, colorspace3, colorspace4, videoscale1, videoscale2, videoscale3, par1, par2, par3, sink, videobox1, videobox2,videobox3, videomixer, NULL);
  364.  
  365.     if (!gst_element_link_many (demux1, decoder1, colorspace2, /*videoscale1, par2,*/ videobox2, videorate2, videomixer, NULL)){
  366.         g_warning ("Linking part (B2) Fail...");
  367.         return -1;
  368.     }
  369.     if (!gst_element_link_many (demux2, decoder2, colorspace3, /*videoscale2, par3,*/ videobox3, videorate3, videomixer, NULL)){
  370.         g_warning ("Linking part (B3) Fail...");
  371.         return -1;
  372.     }
  373.     if (!gst_element_link_many (videomixer,colorspace4, /*videoscale3,*/ sink, NULL)){
  374.         g_warning ("Linking part (B4) Fail...");
  375.         return -1;
  376.     }
  377.  
  378.     if (! g_signal_connect (src1, "pad-added", G_CALLBACK (on_pad_added),demux1)) {
  379.         g_warning ("Linking part (A) with part (B) Fail...");
  380.     }
  381.     if (! g_signal_connect (src2, "pad-added", G_CALLBACK (on_pad_added),demux2)) {
  382.         g_warning ("Linking part (A) with part (B) Fail...");
  383.     }
  384.  
  385.     gst_caps_unref(caps1) ;
  386.     gst_caps_unref(caps2) ;
  387.  
  388.     //set window id on this event
  389.     GstBus* bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
  390.     gst_bus_add_watch(bus, (GstBusFunc)bus_call, drawingArea);
  391.     gst_object_unref (bus);
  392.  
  393.     // attach key press signal to key press callback
  394.     gtk_widget_set_events(window, GDK_KEY_PRESS_MASK);
  395.     g_signal_connect(G_OBJECT(window), "key-press-event", G_CALLBACK(key_press_event_cb), pipeline);
  396.     g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(destroy_cb), pipeline);
  397.     g_signal_connect (G_OBJECT(drawingArea), "realize", G_CALLBACK (area_realize_cb), pipeline);
  398.     g_signal_connect(G_OBJECT(drawingArea), "expose-event", G_CALLBACK(expose_cb), sink);
  399.  
  400.     g_signal_connect (G_OBJECT (button1), "clicked", G_CALLBACK (button_state_null_cb), pipeline);
  401.     g_signal_connect (G_OBJECT (button2), "clicked", G_CALLBACK (button_state_ready_cb), pipeline);
  402.     g_signal_connect (G_OBJECT (button3), "clicked", G_CALLBACK (button_state_paused_cb), pipeline);
  403.     g_signal_connect (G_OBJECT (button4), "clicked", G_CALLBACK (button_state_playing_cb), pipeline);
  404.  
  405.  
  406.     /* run */
  407.     make_window_black(drawingArea);
  408.     gtk_widget_show (window);
  409.  
  410.     ret = gst_element_set_state(pipeline, GST_STATE_PLAYING);
  411.     if (ret == GST_STATE_CHANGE_FAILURE) {
  412.         g_print("Failed to start up pipeline!\n");
  413.         return 1;
  414.     }
  415.  
  416.     //trying to connect rtpbin signals inside of the rtpsrc (only first one (src1))
  417.     {
  418.         GList *child = NULL, *children = GST_BIN_CHILDREN (src1);
  419.         gchar *objectName;
  420.         for (child = children; child != NULL; child = g_list_next (child)) {
  421.             objectName = gst_object_get_name(child->data);
  422.             g_print("\tfound object: %s\n", objectName);
  423.             if (g_str_has_prefix(objectName, "rtpbin")) {
  424.                 GstElement *ch = GST_ELEMENT(child->data);
  425.                 g_print("\tselected object name:%s\n", objectName);
  426.                 GstElementFactory *fac;
  427.                 fac=gst_element_get_factory(ch);
  428.                 g_print("\tselected object detail%s\n", fac->details.longname);
  429.                 g_signal_connect (ch, "on-bye-ssrc", G_CALLBACK (onbyessrc_cb), ch);
  430.                 g_signal_connect (ch, "on-bye-timeout", G_CALLBACK (onbyessrc_cb), ch);
  431.                 g_signal_connect (ch, "on-ssrc-active", G_CALLBACK (onbyessrc_cb), ch);
  432.             }
  433.             g_free(objectName);
  434.         }
  435.     }
  436.  
  437.     gtk_main ();
  438.     return 0;
  439. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement