/tests/icles/output-selector-test.c

https://github.com/rikaunite/gst-opera_gst-plugins-base · C · 173 lines · 120 code · 34 blank · 19 comment · 18 complexity · 87fb3824d48c30f7c1c323de68c16e6f MD5 · raw file

  1. #include <gst/gst.h>
  2. #define SWITCH_TIMEOUT 1000
  3. #define NUM_VIDEO_BUFFERS 500
  4. static GMainLoop *loop;
  5. /* Output selector src pads */
  6. static GstPad *osel_src1 = NULL;
  7. static GstPad *osel_src2 = NULL;
  8. static gboolean
  9. my_bus_callback (GstBus * bus, GstMessage * message, gpointer data)
  10. {
  11. g_print ("Got %s message\n", GST_MESSAGE_TYPE_NAME (message));
  12. switch (GST_MESSAGE_TYPE (message)) {
  13. case GST_MESSAGE_ERROR:{
  14. GError *err;
  15. gchar *debug;
  16. gst_message_parse_error (message, &err, &debug);
  17. g_print ("Error: %s\n", err->message);
  18. g_error_free (err);
  19. g_free (debug);
  20. g_main_loop_quit (loop);
  21. break;
  22. }
  23. case GST_MESSAGE_EOS:
  24. /* end-of-stream */
  25. g_main_loop_quit (loop);
  26. break;
  27. default:
  28. /* unhandled message */
  29. break;
  30. }
  31. /* we want to be notified again the next time there is a message
  32. * on the bus, so returning TRUE (FALSE means we want to stop watching
  33. * for messages on the bus and our callback should not be called again)
  34. */
  35. return TRUE;
  36. }
  37. static gboolean
  38. switch_cb (gpointer user_data)
  39. {
  40. GstElement *sel = GST_ELEMENT (user_data);
  41. GstPad *old_pad, *new_pad = NULL;
  42. g_object_get (G_OBJECT (sel), "active-pad", &old_pad, NULL);
  43. if (old_pad == osel_src1)
  44. new_pad = osel_src2;
  45. else
  46. new_pad = osel_src1;
  47. g_object_set (G_OBJECT (sel), "active-pad", new_pad, NULL);
  48. g_print ("switched from %s:%s to %s:%s\n", GST_DEBUG_PAD_NAME (old_pad),
  49. GST_DEBUG_PAD_NAME (new_pad));
  50. gst_object_unref (old_pad);
  51. return TRUE;
  52. }
  53. static void
  54. on_bin_element_added (GstBin * bin, GstElement * element, gpointer user_data)
  55. {
  56. g_object_set (G_OBJECT (element), "sync", FALSE, "async", FALSE, NULL);
  57. }
  58. gint
  59. main (gint argc, gchar * argv[])
  60. {
  61. GstElement *pipeline, *src, *toverlay, *osel, *sink1, *sink2, *c1, *c2, *c0;
  62. GstPad *sinkpad;
  63. GstBus *bus;
  64. /* init GStreamer */
  65. gst_init (&argc, &argv);
  66. loop = g_main_loop_new (NULL, FALSE);
  67. /* create elements */
  68. pipeline = gst_element_factory_make ("pipeline", "pipeline");
  69. src = gst_element_factory_make ("videotestsrc", "src");
  70. c0 = gst_element_factory_make ("ffmpegcolorspace", NULL);
  71. toverlay = gst_element_factory_make ("timeoverlay", "timeoverlay");
  72. osel = gst_element_factory_make ("output-selector", "osel");
  73. c1 = gst_element_factory_make ("ffmpegcolorspace", NULL);
  74. c2 = gst_element_factory_make ("ffmpegcolorspace", NULL);
  75. sink1 = gst_element_factory_make ("autovideosink", "sink1");
  76. sink2 = gst_element_factory_make ("autovideosink", "sink2");
  77. if (!pipeline || !src || !c0 || !toverlay || !osel || !c1 || !c2 || !sink1 ||
  78. !sink2) {
  79. g_print ("missing element\n");
  80. return -1;
  81. }
  82. /* add them to bin */
  83. gst_bin_add_many (GST_BIN (pipeline), src, c0, toverlay, osel, c1, sink1, c2,
  84. sink2, NULL);
  85. /* set properties */
  86. g_object_set (G_OBJECT (src), "is-live", TRUE, NULL);
  87. g_object_set (G_OBJECT (src), "do-timestamp", TRUE, NULL);
  88. g_object_set (G_OBJECT (src), "num-buffers", NUM_VIDEO_BUFFERS, NULL);
  89. g_object_set (G_OBJECT (osel), "resend-latest", TRUE, NULL);
  90. /* handle deferred properties */
  91. g_signal_connect (G_OBJECT (sink1), "element-added",
  92. G_CALLBACK (on_bin_element_added), NULL);
  93. g_signal_connect (G_OBJECT (sink2), "element-added",
  94. G_CALLBACK (on_bin_element_added), NULL);
  95. /* link src ! timeoverlay ! osel */
  96. if (!gst_element_link_many (src, c0, toverlay, osel, NULL)) {
  97. g_print ("linking failed\n");
  98. return -1;
  99. }
  100. /* link output 1 */
  101. sinkpad = gst_element_get_static_pad (c1, "sink");
  102. osel_src1 = gst_element_get_request_pad (osel, "src%d");
  103. if (gst_pad_link (osel_src1, sinkpad) != GST_PAD_LINK_OK) {
  104. g_print ("linking output 1 converter failed\n");
  105. return -1;
  106. }
  107. gst_object_unref (sinkpad);
  108. if (!gst_element_link (c1, sink1)) {
  109. g_print ("linking output 1 failed\n");
  110. return -1;
  111. }
  112. /* link output 2 */
  113. sinkpad = gst_element_get_static_pad (c2, "sink");
  114. osel_src2 = gst_element_get_request_pad (osel, "src%d");
  115. if (gst_pad_link (osel_src2, sinkpad) != GST_PAD_LINK_OK) {
  116. g_print ("linking output 2 converter failed\n");
  117. return -1;
  118. }
  119. gst_object_unref (sinkpad);
  120. if (!gst_element_link (c2, sink2)) {
  121. g_print ("linking output 2 failed\n");
  122. return -1;
  123. }
  124. /* add switch callback */
  125. g_timeout_add (SWITCH_TIMEOUT, switch_cb, osel);
  126. /* change to playing */
  127. bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
  128. gst_bus_add_watch (bus, my_bus_callback, loop);
  129. gst_object_unref (bus);
  130. gst_element_set_state (pipeline, GST_STATE_PLAYING);
  131. /* now run */
  132. g_main_loop_run (loop);
  133. /* also clean up */
  134. gst_element_set_state (pipeline, GST_STATE_NULL);
  135. gst_element_release_request_pad (osel, osel_src1);
  136. gst_element_release_request_pad (osel, osel_src2);
  137. gst_object_unref (GST_OBJECT (pipeline));
  138. return 0;
  139. }