Advertisement
Guest User

Untitled

a guest
Jan 6th, 2014
123
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.67 KB | None | 0 0
  1. /*
  2. * main.c
  3. *
  4. * Created on: Jan 6, 2014
  5. * Author: memphis
  6. */
  7.  
  8. #include <sys/time.h>
  9. #include <glib.h>
  10. #include "gst/gst.h"
  11.  
  12. typedef struct {
  13. //Main elements
  14. GstElement *pipeline;
  15. GMainLoop *loop;
  16. GstBus *bus;
  17.  
  18. //Gst elements
  19. GstElement *src;
  20. GstElement *demux;
  21. GstElement *parse;
  22. GstElement *parseCaps;
  23. GstElement *queue;
  24. GstElement *sink_bin;
  25.  
  26. //Misc
  27. GstSegment segment;
  28. gboolean ignoreEOS;
  29. gulong probeid;
  30. gulong probeeventid;
  31. guint64 startTime;
  32. GstClockTime offset;
  33.  
  34. } CustomData;
  35.  
  36. guint64 get_time_in_milli() {
  37. struct timeval tv;
  38. gettimeofday(&tv, NULL);
  39. return tv.tv_sec * 1000000ULL + tv.tv_usec;
  40. }
  41.  
  42. void print_segment(GstSegment* segment) {
  43. g_print("### Segment ###\n");
  44. g_print("Rate : %"G_GINT64_FORMAT"\n", segment->rate);
  45. g_print("Base : %"G_GUINT64_FORMAT"\n", segment->base);
  46. g_print("Offset : %"G_GUINT64_FORMAT"\n", segment->offset);
  47. g_print("Start : %"G_GUINT64_FORMAT"\n", segment->start);
  48. g_print("Stop : %"G_GUINT64_FORMAT"\n", segment->stop);
  49. g_print("Time : %"G_GUINT64_FORMAT"\n", segment->time);
  50.  
  51. g_print("Position : %"G_GUINT64_FORMAT"\n", segment->position);
  52. g_print("Duration : %"G_GUINT64_FORMAT"\n", segment->duration);
  53. }
  54.  
  55. void build_sink_bin(CustomData* data) {
  56. if (data->sink_bin == NULL) {
  57. data->sink_bin = gst_bin_new("save_bin");
  58.  
  59. GstElement* mux = gst_element_factory_make("matroskamux", NULL);
  60. GstElement* filesink = gst_element_factory_make("filesink", NULL);
  61.  
  62. gchar* filedest = g_strdup_printf("%"G_GINT64_FORMAT".mkv",g_get_real_time());
  63. g_object_set(filesink, "location", filedest, "sync", TRUE, "async", TRUE, NULL);
  64.  
  65. gst_bin_add_many(GST_BIN(data->sink_bin), mux, filesink, NULL);
  66. gst_element_link(mux, filesink);
  67.  
  68. //Create ghost pad
  69. GstPad* sinkMuxPad = gst_element_get_request_pad(mux, "video_%u");
  70. gst_element_add_pad (data->sink_bin, gst_ghost_pad_new ("sink", sinkMuxPad));
  71. gst_object_unref (GST_OBJECT (sinkMuxPad));
  72.  
  73. gst_bin_add(GST_BIN(data->pipeline), data->sink_bin);
  74. gst_element_link(data->queue, data->sink_bin);
  75. }
  76. }
  77.  
  78. void reset_sink_bin (CustomData *data){
  79. gst_element_set_state (data->sink_bin, GST_STATE_NULL);
  80. gst_bin_remove(GST_BIN(data->pipeline), data->sink_bin);
  81. data->sink_bin = NULL;
  82.  
  83. build_sink_bin(data);
  84. gst_element_set_state (data->sink_bin, GST_STATE_PLAYING);
  85. }
  86.  
  87. static GstPadProbeReturn probe (GstPad *pad, GstPadProbeInfo *info, gpointer user_data) {
  88. CustomData *data = (CustomData *) user_data;
  89.  
  90. GstBuffer* buffer = GST_PAD_PROBE_INFO_BUFFER (info);
  91.  
  92. if (data->startTime == 0) {
  93. data->startTime = get_time_in_milli();
  94.  
  95. if (data->offset > 0) {
  96. // guint64 clipStart;
  97. // guint64 clipStop;
  98. // if (gst_segment_clip(&data->segment, GST_FORMAT_TIME, data->offset, -1, &clipStart, &clipStop))
  99. // g_print("Clip success\n");
  100. // g_print("ClipStart : %"G_GUINT64_FORMAT" ClipStop %"G_GUINT64_FORMAT"\n", clipStart, clipStop);
  101.  
  102. // data->segment.start = data->offset;
  103. //print_segment(&data->segment);
  104.  
  105. /* (POC_Recording2:14630): GStreamer-WARNING **: gstpad.c:4506:store_sticky_event:<sink:proxypad1> Sticky event misordering, got 'segment' before 'stream-start'
  106. * (POC_Recording2:14630): GStreamer-WARNING **: gstpad.c:4506:store_sticky_event:<save_bin:sink> Sticky event misordering, got 'segment' before 'caps'
  107. *
  108. *
  109. */
  110. // GstPad* binPad = gst_element_get_static_pad(data->sink_bin, "sink");
  111. // gst_pad_send_event(binPad, gst_event_new_segment(&data->segment));
  112. // gst_object_unref(binPad);
  113. }
  114. }
  115. else {
  116. guint64 diff = get_time_in_milli() - data->startTime;
  117. if (diff > 5* 1000000ULL) {
  118. GstBuffer* buffer = GST_PAD_PROBE_INFO_BUFFER (info);
  119. if (GST_BUFFER_FLAG_IS_SET(buffer,GST_BUFFER_FLAG_DELTA_UNIT) != TRUE) {
  120. g_print("Sent EOS in sink bin\n");
  121. data->ignoreEOS = TRUE;
  122. GstPad* binPad = gst_element_get_static_pad(data->sink_bin, "sink");
  123. gst_pad_send_event(binPad, gst_event_new_eos());
  124. gst_object_unref(binPad);
  125.  
  126. gst_debug_bin_to_dot_file(GST_BIN(data->pipeline), GST_DEBUG_GRAPH_SHOW_ALL,"eos" );
  127. data->startTime = 0;
  128. data->offset = GST_BUFFER_PTS(buffer);
  129.  
  130. return GST_PAD_PROBE_OK;
  131. }
  132.  
  133. }
  134. }
  135.  
  136. buffer = gst_buffer_make_writable(buffer);
  137. //GST_BUFFER_PTS(buffer) -= data->offset;
  138.  
  139. GstClockTime pts = GST_BUFFER_PTS(buffer);
  140. GstClockTime offset = GST_BUFFER_OFFSET(buffer);
  141. GstClockTime offset_end = GST_BUFFER_OFFSET_END(buffer);
  142.  
  143. g_print("PTS %"G_GUINT64_FORMAT" Offset %"G_GUINT64_FORMAT" Offset end %"G_GUINT64_FORMAT"\n", pts, offset, offset_end);
  144.  
  145. return GST_PAD_PROBE_PASS;
  146. }
  147.  
  148.  
  149.  
  150. static GstPadProbeReturn
  151. event_probe(GstPad *pad, GstPadProbeInfo *info, gpointer user_data) {
  152.  
  153. if (GST_EVENT_TYPE (GST_PAD_PROBE_INFO_DATA (info)) == GST_EVENT_SEGMENT) {
  154. CustomData* data = (CustomData*) user_data;
  155. gst_event_copy_segment (GST_PAD_PROBE_INFO_EVENT(info), &data->segment);
  156. g_print("############### Receive segment ########################\n");
  157. print_segment(&data->segment);
  158. }
  159.  
  160. return GST_PAD_PROBE_PASS;
  161. }
  162.  
  163. void set_queue_probe(CustomData* data) {
  164. if (data->queue != NULL) {
  165. GstPad* queueSrcPad = gst_element_get_static_pad(data->queue, "src");
  166. if (queueSrcPad) {
  167. if (data->probeid != 0) {
  168. gst_pad_remove_probe(queueSrcPad, data->probeid);
  169. g_print ("Pad unblocked\n");
  170. }
  171. if (data->probeeventid != 0) {
  172. gst_pad_remove_probe(queueSrcPad, data->probeeventid);
  173. }
  174.  
  175. //Set the probe
  176. data->probeid = gst_pad_add_probe (queueSrcPad, GST_PAD_PROBE_TYPE_BLOCK | GST_PAD_PROBE_TYPE_BUFFER ,(GstPadProbeCallback) probe, data, NULL);
  177. data->probeeventid = gst_pad_add_probe (queueSrcPad, GST_PAD_PROBE_TYPE_EVENT_BOTH,(GstPadProbeCallback) event_probe, data, NULL);
  178. gst_object_unref(queueSrcPad);
  179. } else {
  180. g_warning("Failed to get the queue src pad.");
  181. }
  182. }
  183. }
  184.  
  185. void padAdded (GstElement* object,
  186. GstPad* arg0,
  187. gpointer user_data) {
  188. CustomData* data = (CustomData* ) user_data;
  189.  
  190. g_print("Receive pad.\n");
  191. GstPad* sinkPad = gst_element_get_static_pad(data->parse, "sink");
  192. if (gst_pad_can_link(arg0, sinkPad)) {
  193. gst_pad_link(arg0, sinkPad);
  194.  
  195. gst_debug_bin_to_dot_file(GST_BIN(data->pipeline), GST_DEBUG_GRAPH_SHOW_ALL,"pad" );
  196. } else {
  197. //link to fakesink
  198. // GstElement* fakesink = gst_element_factory_make("fakesink", NULL);
  199. // gst_bin_add(GST_BIN(data->pipeline), fakesink);
  200. //
  201. // GstPad* fakesinkSinkPad = gst_element_get_static_pad(fakesink, "sink");
  202. // gst_pad_link(arg0, fakesinkSinkPad);
  203. // gst_object_unref(fakesinkSinkPad);
  204. //
  205. // gst_element_set_state(fakesink, GST_STATE_PLAYING);
  206.  
  207.  
  208. }
  209.  
  210. gst_object_unref(sinkPad);
  211.  
  212.  
  213. }
  214.  
  215. static gboolean
  216. bus_call (GstBus *bus,
  217. GstMessage *msg,
  218. gpointer user_data)
  219. {
  220. CustomData *data = (CustomData *) user_data;
  221.  
  222. switch (GST_MESSAGE_TYPE (msg)) {
  223. case GST_MESSAGE_EOS:
  224. g_print("Receive EOS\n");
  225. if (data->ignoreEOS) {
  226.  
  227. data->ignoreEOS = FALSE;
  228. g_print ("Changing file\n");
  229. reset_sink_bin(data);
  230. g_print("Unblocking the pad\n");
  231. set_queue_probe(data);
  232. } else {
  233. g_print ("Caught end of stream, strange!\n");
  234. g_main_loop_quit (data->loop);
  235. }
  236. break;
  237.  
  238. case GST_MESSAGE_ERROR: {
  239. gchar *debug;
  240. GError *error;
  241.  
  242. gst_message_parse_error (msg, &error, &debug);
  243. g_free (debug);
  244.  
  245. g_printerr ("Error: %s\n", error->message);
  246. g_error_free (error);
  247.  
  248. gst_debug_bin_to_dot_file(GST_BIN(data->pipeline), GST_DEBUG_GRAPH_SHOW_ALL,"on_error" );
  249.  
  250. g_main_loop_quit (data->loop);
  251. break;
  252. }
  253. default:
  254. break;
  255. }
  256.  
  257. return TRUE;
  258. }
  259.  
  260. void help () {
  261. g_printerr ("Usage: POC_Segment pathtofile\nExample : POC_Segment /home/user/file.mkv\n");
  262. }
  263.  
  264. int
  265. main (int argc,
  266. char *argv[])
  267. {
  268. if (argc != 2) {
  269. help();
  270. return -1;
  271. }
  272.  
  273. if (!g_file_test(argv[1],G_FILE_TEST_IS_REGULAR)) {
  274. g_printerr ("FATAL: \"%s\" is not a file\n", argv[2]);
  275. help();
  276. return -2;
  277. }
  278.  
  279. gst_init (NULL, NULL);
  280.  
  281. CustomData data;
  282. data.probeid = 0;
  283. data.probeeventid = 0;
  284. data.startTime = 0;
  285. data.sink_bin = NULL;
  286. data.ignoreEOS = FALSE;
  287. data.offset = 0;
  288.  
  289. data.loop = g_main_loop_new (NULL, FALSE);
  290. data.pipeline = gst_pipeline_new("segmentation");
  291. data.src = gst_element_factory_make("filesrc", NULL);
  292. data.demux = gst_element_factory_make("matroskademux", NULL);
  293. data.parse = gst_element_factory_make("h264parse", NULL);
  294. data.parseCaps = gst_element_factory_make("capsfilter", NULL);
  295. data.queue = gst_element_factory_make("queue", NULL);
  296.  
  297. //Set properties and signals
  298. g_object_set(data.src, "location", argv[1], "do-timestamp", TRUE, NULL);
  299. g_signal_connect(data.demux, "pad-added", G_CALLBACK(padAdded), &data);
  300.  
  301. data.bus = gst_pipeline_get_bus (GST_PIPELINE (data.pipeline));
  302. guint bus_watch_id = gst_bus_add_watch (data.bus, bus_call, &data);
  303. gst_object_unref (data.bus);
  304.  
  305. /* we add all elements into the pipeline */
  306. gst_bin_add_many (GST_BIN (data.pipeline), data.src, data.demux, data.parse, data.parseCaps, data.queue, NULL);
  307. gst_element_link (data.src, data.demux);
  308. gst_element_link_many(data.parse, data.parseCaps, data.queue, NULL);
  309.  
  310. build_sink_bin(&data);
  311.  
  312. set_queue_probe(&data);
  313.  
  314. gst_element_set_state (data.pipeline, GST_STATE_PLAYING);
  315.  
  316. g_print ("Running...\n");
  317. g_main_loop_run (data.loop);
  318.  
  319. g_print ("Loop exited\n");
  320. gst_element_set_state (data.pipeline, GST_STATE_NULL);
  321. gst_object_unref (GST_OBJECT (data.pipeline));
  322. g_source_remove (bus_watch_id);
  323. g_main_loop_unref (data.loop);
  324. return 0;
  325. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement