Advertisement
Guest User

Untitled

a guest
Jan 25th, 2014
122
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.73 KB | None | 0 0
  1. /*
  2. * main.c
  3. *
  4. * Created on: Jan 22, 2014
  5. * Author: memphis
  6. */
  7.  
  8. #include "glib.h"
  9. #include "gst/gst.h"
  10. #include <gst/app/gstappsink.h>
  11.  
  12. #define USE_VIDEO_SINK
  13.  
  14. typedef struct _CustomData CustomData;
  15. struct _CustomData {
  16. GMainLoop* loop;
  17. GstBus* bus;
  18. GstElement* pipeline;
  19. GstElement* filesrc;
  20. GstElement* filedemux;
  21. GstElement* h264parse;
  22. GstElement* h264dec;
  23. GstElement* videoconvert;
  24. GstElement* enc;
  25. GstElement* sink;
  26.  
  27. gint64 targetPTSTimecode;
  28. gint64 lastSeek;
  29. };
  30.  
  31. static gint buffer_count = 0;
  32.  
  33. void print_segment(GstSegment* segment) {
  34. g_print("Segment : Base : %"G_GUINT64_FORMAT" \n", segment->base);
  35. g_print(" Offset : %"G_GUINT64_FORMAT" \n", segment->offset);
  36. g_print(" Start : %"G_GUINT64_FORMAT" \n", segment->start);
  37. g_print(" Stop : %"G_GUINT64_FORMAT" \n", segment->stop);
  38. g_print(" Time : %"G_GUINT64_FORMAT" \n", segment->time);
  39. g_print(" Position: %"G_GUINT64_FORMAT" \n", segment->position);
  40. g_print(" Duration: %"G_GUINT64_FORMAT" \n", segment->duration);
  41.  
  42. }
  43.  
  44. GstPadProbeReturn
  45. demux_src_probe(GstPad * pad, GstPadProbeInfo * info, gpointer user_data) {
  46. if (GST_PAD_PROBE_INFO_TYPE(info) & GST_PAD_PROBE_TYPE_EVENT_BOTH) {
  47. if ((GST_EVENT_TYPE (GST_PAD_PROBE_INFO_DATA (info)) == GST_EVENT_EOS)) {
  48. g_print("Receive EOS on the probe\n");
  49. exit(0);
  50. return GST_PAD_PROBE_DROP;
  51. }
  52.  
  53. // if ((GST_EVENT_TYPE (GST_PAD_PROBE_INFO_DATA (info)) == GST_EVENT_SEGMENT)) {
  54. // //g_print("########## REceive segment \n");
  55. // CustomData* data = (CustomData*) user_data;
  56. // gint64 duration = 0;
  57. // gst_element_query_duration(data->filedemux, GST_FORMAT_TIME, &duration);
  58. // g_print("Duration : %"G_GINT64_FORMAT"\n", duration);
  59. // data->targetPTSTimecode = duration;
  60. // }
  61. } else if (GST_PAD_PROBE_INFO_TYPE(info) & GST_PAD_PROBE_TYPE_BUFFER) {
  62. CustomData* data = (CustomData*) user_data;
  63. g_print("Buffer %d ", buffer_count);
  64. GstBuffer* buffer = GST_PAD_PROBE_INFO_BUFFER (info);
  65. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_LIVE)) g_print(" LIVE");
  66. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DECODE_ONLY)) g_print(" GST_BUFFER_FLAG_DECODE_ONLY");
  67. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DISCONT)) g_print(" GST_BUFFER_FLAG_DISCONT");
  68. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_RESYNC)) g_print(" GST_BUFFER_FLAG_RESYNC");
  69. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_CORRUPTED)) g_print(" GST_BUFFER_FLAG_CORRUPTED");
  70. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_MARKER)) g_print(" GST_BUFFER_FLAG_MARKER");
  71. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_HEADER)) g_print(" GST_BUFFER_FLAG_HEADER");
  72. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_GAP)) g_print(" GST_BUFFER_FLAG_GAP");
  73. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DROPPABLE)) g_print(" GST_BUFFER_FLAG_DROPPABLE");
  74. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT)) g_print(" GST_BUFFER_FLAG_DELTA_UNIT");
  75.  
  76. g_print(" Duration %"G_GINT64_FORMAT,GST_BUFFER_DURATION(buffer));
  77. gint64 pts = GST_BUFFER_PTS(buffer);
  78. gint64 dts = GST_BUFFER_DTS(buffer);
  79. g_print("PTS : %"G_GINT64_FORMAT" Target : %"G_GINT64_FORMAT" DTS : %"G_GINT64_FORMAT" Offset : %"G_GUINT64_FORMAT"\n", pts, data->lastSeek, dts, GST_BUFFER_OFFSET(buffer));
  80. }
  81.  
  82. return GST_PAD_PROBE_PASS;
  83. }
  84.  
  85. GstPadProbeReturn
  86. sink_src_probe(GstPad * pad, GstPadProbeInfo * info, gpointer user_data) {
  87. if (GST_PAD_PROBE_INFO_TYPE(info) & GST_PAD_PROBE_TYPE_EVENT_BOTH) {
  88. if ((GST_EVENT_TYPE (GST_PAD_PROBE_INFO_DATA (info)) == GST_EVENT_EOS)) {
  89. g_print("Receive EOS on the probe\n");
  90. return GST_PAD_PROBE_DROP;
  91. }
  92.  
  93. if ((GST_EVENT_TYPE (GST_PAD_PROBE_INFO_DATA (info)) == GST_EVENT_SEGMENT)) {
  94. g_print("########## REceive segment \n");
  95. CustomData* data = (CustomData*) user_data;
  96. GstSegment* segment;
  97. gst_event_parse_segment(info->data, &segment);
  98. print_segment(segment);
  99. }
  100. } else if (GST_PAD_PROBE_INFO_TYPE(info) & GST_PAD_PROBE_TYPE_BUFFER) {
  101. CustomData* data = (CustomData*) user_data;
  102. g_print("Sink Buffer %d ", buffer_count);
  103. GstBuffer* buffer = GST_PAD_PROBE_INFO_BUFFER (info);
  104. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_LIVE)) g_print(" LIVE");
  105. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DECODE_ONLY)) g_print(" GST_BUFFER_FLAG_DECODE_ONLY");
  106. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DISCONT)) g_print(" GST_BUFFER_FLAG_DISCONT");
  107. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_RESYNC)) g_print(" GST_BUFFER_FLAG_RESYNC");
  108. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_CORRUPTED)) g_print(" GST_BUFFER_FLAG_CORRUPTED");
  109. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_MARKER)) g_print(" GST_BUFFER_FLAG_MARKER");
  110. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_HEADER)) g_print(" GST_BUFFER_FLAG_HEADER");
  111. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_GAP)) g_print(" GST_BUFFER_FLAG_GAP");
  112. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DROPPABLE)) g_print(" GST_BUFFER_FLAG_DROPPABLE");
  113. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT)) g_print(" GST_BUFFER_FLAG_DELTA_UNIT");
  114.  
  115. g_print(" Duration %"G_GINT64_FORMAT,GST_BUFFER_DURATION(buffer));
  116. gint64 pts = GST_BUFFER_PTS(buffer);
  117. gint64 dts = GST_BUFFER_DTS(buffer);
  118. g_print("PTS : %"G_GINT64_FORMAT" Target : %"G_GINT64_FORMAT" DTS : %"G_GINT64_FORMAT" Offset : %"G_GUINT64_FORMAT"\n", pts, data->lastSeek, dts, GST_BUFFER_OFFSET(buffer));
  119. }
  120.  
  121. return GST_PAD_PROBE_PASS;
  122. }
  123.  
  124. void demux_pad_added (GstElement* object, GstPad* arg0, gpointer user_data) {
  125. CustomData *data = (CustomData*)user_data;
  126.  
  127. GstPad* h264parseSinkPad = gst_element_get_static_pad(data->h264parse, "sink");
  128. if (gst_pad_can_link(arg0, h264parseSinkPad)) {
  129. gst_pad_link(arg0, h264parseSinkPad);
  130. gst_pad_add_probe (arg0, GST_PAD_PROBE_TYPE_DATA_BOTH | GST_PAD_PROBE_TYPE_EVENT_BOTH | GST_PAD_PROBE_TYPE_BLOCKING, demux_src_probe, data, NULL);
  131. } else {
  132. //TODO : Add fakesink
  133. }
  134. gst_object_unref(h264parseSinkPad);
  135. }
  136.  
  137. static gboolean goto_first(gpointer user_data);
  138. static gboolean goto_end(gpointer user_data) {
  139. g_print("Go to end\n");
  140. CustomData* data = (CustomData*) user_data;
  141. //59893000000 YES
  142. //59977000000 don't
  143. //60104291602 don't
  144. //60146000000 duration
  145. //Diff : 253000000
  146. //Frame duration : 41708398
  147. data->lastSeek = 56500000000;
  148. gst_element_seek_simple(data->sink,GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, data->lastSeek);
  149.  
  150. // GstEvent* event = gst_event_new_step(GST_FORMAT_TIME, data->targetPTSTimecode / 2, 1.0, TRUE, FALSE);
  151. // gst_element_send_event(data->sink, event);
  152. //gst_query_unref(query);
  153.  
  154. //g_timeout_add_seconds(5, goto_first,data);
  155. return FALSE;
  156. }
  157.  
  158. static gboolean goto_middle(gpointer user_data) {
  159. g_print("Go to midle\n");
  160. CustomData* data = (CustomData*) user_data;
  161. data->lastSeek = data->targetPTSTimecode / 2;
  162. gst_element_seek_simple(data->pipeline,GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, data->targetPTSTimecode / 2);
  163. g_timeout_add_seconds(5, goto_end,data);
  164. return FALSE;
  165.  
  166. }
  167.  
  168. static gboolean goto_first(gpointer user_data) {
  169. g_print("Go to first\n");
  170. CustomData* data = (CustomData*) user_data;
  171. data->lastSeek = data->targetPTSTimecode / 4;
  172. gst_element_seek_simple(data->pipeline,GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, 0);
  173. g_timeout_add_seconds(5, goto_middle,data);
  174. return FALSE;
  175. }
  176.  
  177. static gboolean my_bus_callback (GstBus *bus, GstMessage *message, gpointer data)
  178. {
  179. CustomData* source = (CustomData*)data;
  180. switch (GST_MESSAGE_TYPE (message)) {
  181. case GST_MESSAGE_ERROR: {
  182. GError *err;
  183. gchar *debug;
  184.  
  185. gst_message_parse_error (message, &err, &debug);
  186. g_print ("Error: %s\n", err->message);
  187. g_error_free (err);
  188. g_free (debug);
  189.  
  190. GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(source->pipeline), GST_DEBUG_GRAPH_SHOW_ALL,"test");
  191.  
  192. g_main_loop_quit (source->loop);
  193. break;
  194. }
  195. case GST_MESSAGE_INFO:
  196. g_print("Receive info");
  197. break;
  198. case GST_MESSAGE_EOS:
  199. /* end-of-stream */
  200. g_print("Receive EOS on the bus\n");
  201. g_main_loop_quit (source->loop);
  202. break;
  203. case GST_MESSAGE_SEGMENT_DONE:
  204. g_print("Receive segment done\n");
  205. //g_main_loop_quit(source->loop);
  206. break;
  207. case GST_MESSAGE_STATE_CHANGED:
  208. // if (message->src == source->pipeline) {
  209. // g_print("Receive state changed\n");
  210. // GstState old_state, new_state, pending;
  211. // gst_message_parse_state_changed(message, &old_state,&new_state, &pending);
  212. // if (new_state == GST_STATE_PAUSED) {
  213. // g_print("Arrive in paused \n");
  214. //
  215. // GstQuery* segmentQuery = gst_query_new_segment(GST_FORMAT_TIME);
  216. // gst_element_query(source->pipeline, segmentQuery);
  217. // gdouble rate = 0.0;
  218. // GstFormat format;
  219. // gint64 startvalue, stop_value;
  220. // gst_query_parse_segment(segmentQuery, &rate, &format, &startvalue, &stop_value);
  221. // g_print("Query : Rate %f Format : %s Start : %"G_GINT64_FORMAT" Stop %"G_GINT64_FORMAT" \n", rate, format == GST_FORMAT_TIME ? "TIME" : "Other", startvalue, stop_value);
  222. // gst_query_unref(segmentQuery);
  223. // }
  224. // }
  225. break;
  226. case GST_MESSAGE_ASYNC_DONE:
  227. g_print("Receive async done\n");
  228. gint64 duration;
  229. if (gst_element_query_duration(source->pipeline, GST_FORMAT_TIME, &duration)) {
  230. source->targetPTSTimecode = duration;
  231. g_print("Duration ASYNC : %"G_GINT64_FORMAT" \n", duration);
  232. } else {
  233. g_print("Failed to query the duration\n");
  234. }
  235.  
  236. break;
  237. case GST_MESSAGE_DURATION_CHANGED:
  238. g_print("Receive duration change\n");
  239.  
  240. break;
  241. default:
  242. //g_print("%d\n",GST_MESSAGE_TYPE (message));
  243. /* unhandled message */
  244. break;
  245. }
  246.  
  247. return TRUE;
  248. }
  249.  
  250. void new_sample(GstElement* object, gpointer user_data) {
  251. g_print("########## New sample\n");
  252. }
  253.  
  254. void new_preroll(GstElement* object, gpointer user_data) {
  255. g_print("########## New preroll\n");
  256. GstSample* sample = gst_app_sink_pull_preroll(GST_APP_SINK(object));
  257. if (sample != NULL) {
  258. g_print("Sample not NULL.\n");
  259. GstBuffer *buffer = gst_sample_get_buffer(sample);
  260. if (buffer) {
  261. g_print("Buffer not NULL !!! \n");
  262. }
  263. }
  264. }
  265.  
  266. void eos(GstElement* object, gpointer user_data) {
  267. g_print("########## EOS\n");
  268. }
  269.  
  270. int main(int argc, char* argv[]) {
  271. gst_init(NULL, NULL);
  272.  
  273. CustomData* data = g_new0(CustomData, 1);
  274. //Initialisation
  275. data->lastSeek= 0;
  276.  
  277. data->pipeline = gst_pipeline_new("snapshot");
  278. data->filesrc = gst_element_factory_make("filesrc", NULL);
  279. data->filedemux = gst_element_factory_make("matroskademux", NULL);
  280. data->h264parse = gst_element_factory_make("h264parse", NULL);
  281. data->h264dec = gst_element_factory_make("avdec_h264", NULL);
  282. data->videoconvert = gst_element_factory_make("videoconvert", NULL);
  283.  
  284. g_object_set(data->videoconvert, "qos", FALSE, NULL);
  285. g_object_set(data->filesrc, "do-timestamp", TRUE, NULL);
  286. g_object_set(data->h264dec, "direct-rendering", FALSE, NULL);
  287. g_object_set(data->h264parse, "disable-passthrough", TRUE, NULL);
  288.  
  289. #ifdef USE_VIDEO_SINK
  290. data->enc = gst_element_factory_make("identity", NULL);
  291. data->sink = gst_element_factory_make("xvimagesink", NULL);
  292. g_object_set(data->sink, "sync", FALSE, "async", TRUE, "qos", FALSE, NULL);
  293. #else
  294. data->enc = gst_element_factory_make("pngenc", NULL);
  295. data->sink = gst_element_factory_make("appsink", NULL);
  296. g_object_set(data->sink, "sync", FALSE, "async", FALSE, "emit-signals", TRUE,NULL);
  297. g_object_set(data->enc, "snapshot", FALSE, NULL);
  298. g_signal_connect(data->sink, "new-sample", G_CALLBACK(new_sample),data);
  299. g_signal_connect(data->sink, "new-preroll", G_CALLBACK(new_preroll),data);
  300. g_signal_connect(data->sink, "eos", G_CALLBACK(eos),data);
  301. #endif
  302. //Set initial pipeline settings
  303. g_signal_connect(data->filedemux, "pad-added", G_CALLBACK(demux_pad_added),data);
  304. g_object_set(data->filesrc, "location", "/home/memphis/test_optimized.mkv", NULL);
  305.  
  306. gst_bin_add_many(GST_BIN(data->pipeline), data->filesrc, data->filedemux, data->h264parse, data->h264dec, data->videoconvert, data->enc, data->sink, NULL);
  307. gst_element_link(data->filesrc, data->filedemux);
  308. gst_element_link_many(data->h264parse, data->h264dec, data->videoconvert, data->enc, data->sink, NULL);
  309.  
  310. GstPad* sinPad = gst_element_get_static_pad(data->h264dec, "src");
  311. gst_pad_add_probe (sinPad, GST_PAD_PROBE_TYPE_DATA_BOTH | GST_PAD_PROBE_TYPE_EVENT_BOTH | GST_PAD_PROBE_TYPE_BLOCKING, sink_src_probe, data, NULL);
  312. gst_object_unref(sinPad);
  313.  
  314.  
  315. data->bus = gst_element_get_bus (data->pipeline);
  316. gst_bus_add_watch (data->bus, my_bus_callback, data);
  317. gst_element_set_state(data->pipeline, GST_STATE_PAUSED);
  318. data->loop = g_main_loop_new(NULL,FALSE);
  319. g_timeout_add_seconds(5, goto_end,data);
  320. g_main_loop_run(data->loop);
  321. g_print("Loop exited\n");
  322.  
  323. g_free(data);
  324.  
  325. return 0;
  326. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement