Advertisement
Guest User

Untitled

a guest
Jun 6th, 2021
54
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.59 KB | None | 0 0
  1. #include <gst/gst.h>
  2. #include <stdio.h>
  3.  
  4. /* Structure to contain all our information, so we can pass it to callbacks */
  5. typedef struct _VideoCompositor {
  6. GstElement *pipeline;
  7. GstElement *background;
  8. GstElement *decode;
  9. GstElement *imagefreeze;
  10. GstElement *compositor;
  11. GstElement *convert;
  12. GstElement *sink;
  13. int overlayCount;
  14. } VideoCompositor;
  15.  
  16. typedef struct _OverlayVideo {
  17. GstElement *source;
  18. GstElement *decode;
  19. GstElement *convert;
  20. VideoCompositor *compositor;
  21. int overlayCount;
  22. } OverlayVideo;
  23.  
  24. /* Handler for the pad-added signal */
  25. static void pad_added_handler (GstElement *src, GstPad *pad, VideoCompositor *data);
  26. static void video_pad_added_handler (GstElement *src, GstPad *new_pad, OverlayVideo *data);
  27. static int add_overlay_video (char videoUri[], VideoCompositor compositor);
  28.  
  29. int main(int argc, char *argv[]) {
  30. GstBus *bus;
  31. GstMessage *msg;
  32. GstStateChangeReturn ret;
  33. gboolean terminate = FALSE;
  34.  
  35. VideoCompositor videoCompositor;
  36. videoCompositor.overlayCount = 0;
  37.  
  38. /* Initialize GStreamer */
  39. gst_init (&argc, &argv);
  40.  
  41. /* Compositor init */
  42. videoCompositor.background = gst_element_factory_make ("filesrc", "background");
  43. videoCompositor.decode = gst_element_factory_make ("decodebin", "decode");
  44. videoCompositor.imagefreeze = gst_element_factory_make ("imagefreeze", "imagefreeze");
  45. videoCompositor.compositor = gst_element_factory_make("compositor", "compositor");
  46. videoCompositor.convert = gst_element_factory_make("videoconvert", "videoconvert");
  47. videoCompositor.sink = gst_element_factory_make("filesink", "finalsink");
  48.  
  49. videoCompositor.pipeline = gst_pipeline_new ("compositor_pipeline");
  50.  
  51. if (!videoCompositor.pipeline || !videoCompositor.background || !videoCompositor.decode || !videoCompositor.imagefreeze
  52. || !videoCompositor.compositor || !videoCompositor.convert || !videoCompositor.sink) {
  53. g_printerr ("Not all elements could be created.\n");
  54. return -1;
  55. }
  56.  
  57. gst_bin_add_many (GST_BIN (videoCompositor.pipeline), videoCompositor.background, videoCompositor.decode, videoCompositor.imagefreeze,
  58. videoCompositor.compositor, videoCompositor.convert, videoCompositor.sink, NULL);
  59.  
  60. if (!gst_element_link_many (videoCompositor.background, videoCompositor.decode, NULL)) {
  61. g_printerr ("Elements could not be linked.\n");
  62. gst_object_unref (videoCompositor.pipeline);
  63. return -1;
  64. }
  65.  
  66. // if (!gst_element_link_many (videoCompositor.imagefreeze, videoCompositor.compositor, videoCompositor.convert, videoCompositor.sink, NULL)) {
  67. if (!gst_element_link_many (videoCompositor.compositor, videoCompositor.convert, videoCompositor.sink, NULL)) {
  68. g_printerr ("Elements could not be linked.\n");
  69. gst_object_unref (videoCompositor.pipeline);
  70. return -1;
  71. }
  72.  
  73. // g_object_set (videoCompositor.background, "location", "./resources/street.jpg", NULL);
  74. g_object_set (videoCompositor.background, "location", "./resources/cars/1.mp4", NULL);
  75. g_object_set (videoCompositor.sink, "location", "./file", NULL);
  76.  
  77. /* Connect to the pad-added signal */
  78. g_signal_connect (videoCompositor.decode, "pad-added", G_CALLBACK (pad_added_handler), &videoCompositor);
  79. add_overlay_video("./resources/cars/1.mp4", videoCompositor);
  80.  
  81. ret = gst_element_set_state (videoCompositor.pipeline, GST_STATE_PLAYING);
  82. if (ret == GST_STATE_CHANGE_FAILURE) {
  83. g_printerr ("Unable to set the pipeline to the playing state.\n");
  84. gst_object_unref (videoCompositor.pipeline);
  85. return -1;
  86. }
  87.  
  88.  
  89. /* Listen to the bus */
  90. bus = gst_element_get_bus (videoCompositor.pipeline);
  91. do {
  92. msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,
  93. GST_MESSAGE_STATE_CHANGED | GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
  94.  
  95. /* Parse message */
  96. if (msg != NULL) {
  97. GError *err;
  98. gchar *debug_info;
  99.  
  100. switch (GST_MESSAGE_TYPE (msg)) {
  101. case GST_MESSAGE_ERROR:
  102. gst_message_parse_error (msg, &err, &debug_info);
  103. g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message);
  104. g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none");
  105. g_clear_error (&err);
  106. g_free (debug_info);
  107. terminate = TRUE;
  108. break;
  109. case GST_MESSAGE_EOS:
  110. g_print ("End-Of-Stream reached.\n");
  111. terminate = TRUE;
  112. break;
  113. case GST_MESSAGE_STATE_CHANGED:
  114. /* We are only interested in state-changed messages from the pipeline */
  115. if (GST_MESSAGE_SRC (msg) == GST_OBJECT (videoCompositor.pipeline)) {
  116. GstState old_state, new_state, pending_state;
  117. gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state);
  118. g_print ("Pipeline state changed from %s to %s:\n",
  119. gst_element_state_get_name (old_state), gst_element_state_get_name (new_state));
  120. }
  121. break;
  122. default:
  123. /* We should not reach here */
  124. g_printerr ("Unexpected message received.\n");
  125. break;
  126. }
  127. gst_message_unref (msg);
  128. }
  129. } while (!terminate);
  130.  
  131. /* Free resources */
  132. gst_object_unref (bus);
  133. gst_element_set_state (videoCompositor.pipeline, GST_STATE_NULL);
  134. gst_object_unref (videoCompositor.pipeline);
  135. return 0;
  136. }
  137.  
  138. /* This function will be called by the pad-added signal */
  139. static void pad_added_handler (GstElement *src, GstPad *new_pad, VideoCompositor *data) {
  140. GstPad *sink_pad = gst_element_get_static_pad (data->compositor, "sink");
  141. GstPadLinkReturn ret;
  142. GstCaps *new_pad_caps = NULL;
  143. GstStructure *new_pad_struct = NULL;
  144. const gchar *new_pad_type = NULL;
  145.  
  146. g_print ("Received new pad '%s' from '%s':\n", GST_PAD_NAME (new_pad), GST_ELEMENT_NAME (src));
  147.  
  148. /* If our converter is already linked, we have nothing to do here */
  149. if (gst_pad_is_linked (sink_pad)) {
  150. g_print ("We are already linked. Ignoring.\n");
  151. goto exit;
  152. }
  153.  
  154. /* Check the new pad's type */
  155. new_pad_caps = gst_pad_get_current_caps (new_pad);
  156. new_pad_struct = gst_caps_get_structure (new_pad_caps, 0);
  157. new_pad_type = gst_structure_get_name (new_pad_struct);
  158. if (!g_str_has_prefix (new_pad_type, "video/x-raw")) {
  159. g_print ("It has type '%s' which is not raw video. Ignoring.\n", new_pad_type);
  160. goto exit;
  161. }
  162.  
  163. /* Attempt the link */
  164. ret = gst_pad_link (new_pad, sink_pad);
  165. if (GST_PAD_LINK_FAILED (ret)) {
  166. g_print ("Type is '%s' but link failed.\n", new_pad_type);
  167. } else {
  168. g_print ("Link succeeded (type '%s').\n", new_pad_type);
  169. }
  170.  
  171. exit:
  172. /* Unreference the new pad's caps, if we got them */
  173. if (new_pad_caps != NULL)
  174. gst_caps_unref (new_pad_caps);
  175.  
  176. /* Unreference the sink pad */
  177. gst_object_unref (sink_pad);
  178. }
  179.  
  180. static int add_overlay_video (char videoUri[], VideoCompositor compositor) {
  181. GstStateChangeReturn ret;
  182. OverlayVideo *video = (OverlayVideo*) malloc (sizeof(OverlayVideo));
  183. video->compositor = &compositor;
  184.  
  185. compositor.overlayCount = 1 + compositor.overlayCount;
  186. char bgName[20];
  187. sprintf(bgName, "background%d", compositor.overlayCount);
  188. char decodeName[20];
  189. sprintf(decodeName, "decode%d", compositor.overlayCount);
  190. char convertName[20];
  191. sprintf(convertName, "videoconvert%d", compositor.overlayCount);
  192.  
  193. video->source = gst_element_factory_make ("filesrc", bgName);
  194. video->decode = gst_element_factory_make ("decodebin", decodeName);
  195. video->convert = gst_element_factory_make("videoconvert", convertName);
  196. video->overlayCount = compositor.overlayCount;
  197.  
  198. if (!video->source || !video->decode || !video->convert) {
  199. g_printerr ("Not all elements could be created.\n");
  200. return -1;
  201. }
  202.  
  203. gst_bin_add_many (GST_BIN (compositor.pipeline), video->source, video->decode, video->convert, NULL);
  204.  
  205. if (!gst_element_link_many (video->source, video->decode, NULL)) {
  206. g_printerr ("Elements could not be linked.\n");
  207. gst_object_unref (compositor.pipeline);
  208. return -1;
  209. }
  210.  
  211. if (!gst_element_link_many (video->convert, compositor.compositor, NULL)) {
  212. g_printerr ("Elements could not be linked.\n");
  213. gst_object_unref (compositor.pipeline);
  214. return -1;
  215. }
  216.  
  217. // In info logs, I got no sink for compositor, so I try to manually link sink and src which fails.
  218. GstPad *compositorSinkPad = gst_element_get_request_pad(compositor.compositor, "sink_%u");
  219. GstPad *videoconvertSrcPad = gst_element_get_static_pad(video->convert, "src");
  220. if (!gst_pad_link(videoconvertSrcPad, compositorSinkPad)) {
  221. g_printerr ("Elements could not be linked src sink.\n");
  222. gst_object_unref (compositor.pipeline);
  223. return -1;
  224. }
  225.  
  226. g_object_set (video->source, "location", videoUri, NULL);
  227.  
  228. /* Connect to the pad-added signal */
  229. g_signal_connect (video->decode, "pad-added", G_CALLBACK (video_pad_added_handler), video);
  230.  
  231. ret = gst_element_set_state (compositor.pipeline, GST_STATE_PLAYING);
  232. if (ret == GST_STATE_CHANGE_FAILURE) {
  233. g_printerr ("Unable to set the pipeline to the playing state.\n");
  234. gst_object_unref (compositor.pipeline);
  235. return -1;
  236. }
  237. return 0;
  238. }
  239.  
  240. /* This function will be called by the pad-added signal */
  241. static void video_pad_added_handler (GstElement *src, GstPad *new_pad, OverlayVideo *data) {
  242. gboolean done = FALSE;
  243. GstPad *sink_pad = gst_element_get_static_pad (data->convert, "sink");
  244.  
  245. GstPadLinkReturn ret;
  246. GstCaps *new_pad_caps = NULL;
  247. GstStructure *new_pad_struct = NULL;
  248. const gchar *new_pad_type = NULL;
  249.  
  250. g_print ("Received new pad '%s' from '%s':\n", GST_PAD_NAME (new_pad), GST_ELEMENT_NAME (src));
  251.  
  252. /* If our converter is already linked, we have nothing to do here */
  253. if (gst_pad_is_linked (sink_pad)) {
  254. g_print ("We are already linked. Ignoring.\n");
  255. goto exit;
  256. }
  257.  
  258. /* Check the new pad's type */
  259. new_pad_caps = gst_pad_get_current_caps (new_pad);
  260. new_pad_struct = gst_caps_get_structure (new_pad_caps, 0);
  261. new_pad_type = gst_structure_get_name (new_pad_struct);
  262. if (!g_str_has_prefix (new_pad_type, "video/x-raw")) {
  263. g_print ("It has type '%s' which is not raw video. Ignoring.\n", new_pad_type);
  264. goto exit;
  265. }
  266.  
  267. /* Attempt the link */
  268. ret = gst_pad_link (new_pad, sink_pad);
  269. if (GST_PAD_LINK_FAILED (ret)) {
  270. g_print ("Type is '%s' but link failed.\n", new_pad_type);
  271. } else {
  272. g_print ("Link succeeded (type '%s').\n", new_pad_type);
  273. }
  274.  
  275. exit:
  276. /* Unreference the new pad's caps, if we got them */
  277. if (new_pad_caps != NULL)
  278. gst_caps_unref (new_pad_caps);
  279.  
  280. /* Unreference the sink pad */
  281. gst_object_unref (sink_pad);
  282. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement