Guest User

Untitled

a guest
Jan 27th, 2014
131
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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. #define VIDEO_FILE_PATH "/home/memphis/test.mkv"
  14.  
  15. typedef struct _CustomData CustomData;
  16. struct _CustomData {
  17. GMainLoop* loop;
  18. GstBus* bus;
  19. GstElement* pipeline;
  20. GstElement* filesrc;
  21. GstElement* filedemux;
  22. GstElement* h264parse;
  23. GstElement* h264dec;
  24. GstElement* videoconvert;
  25. GstElement* enc;
  26. GstElement* sink;
  27.  
  28. gint64 targetPTSTimecode;
  29. gint64 frame_duration;
  30. gint64 lastSeek;
  31. };
  32.  
  33. static gint buffer_count = 0;
  34.  
  35. void print_segment(GstSegment* segment) {
  36. g_print("Segment : Base : %"G_GUINT64_FORMAT" \n", segment->base);
  37. g_print(" Offset : %"G_GUINT64_FORMAT" \n", segment->offset);
  38. g_print(" Start : %"G_GUINT64_FORMAT" \n", segment->start);
  39. g_print(" Stop : %"G_GUINT64_FORMAT" \n", segment->stop);
  40. g_print(" Time : %"G_GUINT64_FORMAT" \n", segment->time);
  41. g_print(" Position: %"G_GUINT64_FORMAT" \n", segment->position);
  42. g_print(" Duration: %"G_GUINT64_FORMAT" \n", segment->duration);
  43.  
  44. }
  45.  
  46. GstPadProbeReturn
  47. demux_src_probe(GstPad * pad, GstPadProbeInfo * info, gpointer user_data) {
  48. if (GST_PAD_PROBE_INFO_TYPE(info) & GST_PAD_PROBE_TYPE_EVENT_BOTH) {
  49. if ((GST_EVENT_TYPE (GST_PAD_PROBE_INFO_DATA (info)) == GST_EVENT_EOS)) {
  50. g_print("Receive EOS on the probe. Dropping...\n");
  51. return GST_PAD_PROBE_DROP;
  52. }
  53.  
  54. // if ((GST_EVENT_TYPE (GST_PAD_PROBE_INFO_DATA (info)) == GST_EVENT_SEGMENT)) {
  55. // //g_print("########## REceive segment \n");
  56. // CustomData* data = (CustomData*) user_data;
  57. // gint64 duration = 0;
  58. // gst_element_query_duration(data->filedemux, GST_FORMAT_TIME, &duration);
  59. // g_print("Duration : %"G_GINT64_FORMAT"\n", duration);
  60. // data->targetPTSTimecode = duration;
  61. // }
  62. } else if (GST_PAD_PROBE_INFO_TYPE(info) & GST_PAD_PROBE_TYPE_BUFFER) {
  63. CustomData* data = (CustomData*) user_data;
  64. g_print("DemuxSrcPad Buffer");
  65. GstBuffer* buffer = GST_PAD_PROBE_INFO_BUFFER (info);
  66. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_LIVE)) g_print(" LIVE");
  67. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DECODE_ONLY)) g_print(" GST_BUFFER_FLAG_DECODE_ONLY");
  68. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DISCONT)) g_print(" GST_BUFFER_FLAG_DISCONT");
  69. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_RESYNC)) g_print(" GST_BUFFER_FLAG_RESYNC");
  70. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_CORRUPTED)) g_print(" GST_BUFFER_FLAG_CORRUPTED");
  71. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_MARKER)) g_print(" GST_BUFFER_FLAG_MARKER");
  72. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_HEADER)) g_print(" GST_BUFFER_FLAG_HEADER");
  73. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_GAP)) g_print(" GST_BUFFER_FLAG_GAP");
  74. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DROPPABLE)) g_print(" GST_BUFFER_FLAG_DROPPABLE");
  75. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT)) g_print(" GST_BUFFER_FLAG_DELTA_UNIT");
  76.  
  77. gint64 pts = GST_BUFFER_PTS(buffer);
  78. g_print(" PTS : %"G_GINT64_FORMAT" Target : %"G_GINT64_FORMAT" \n", pts, data->lastSeek);
  79. }
  80.  
  81. return GST_PAD_PROBE_PASS;
  82. }
  83.  
  84. GstPadProbeReturn
  85. sink_src_probe(GstPad * pad, GstPadProbeInfo * info, gpointer user_data) {
  86. if (GST_PAD_PROBE_INFO_TYPE(info) & GST_PAD_PROBE_TYPE_EVENT_BOTH) {
  87. if ((GST_EVENT_TYPE (GST_PAD_PROBE_INFO_DATA (info)) == GST_EVENT_EOS)) {
  88. g_print("Receive EOS on the probe. Dropping...\n");
  89. return GST_PAD_PROBE_DROP;
  90. }
  91.  
  92. if ((GST_EVENT_TYPE (GST_PAD_PROBE_INFO_DATA (info)) == GST_EVENT_SEGMENT)) {
  93. g_print("########## Receive segment \n");
  94. GstSegment* segment;
  95. gst_event_parse_segment(GST_EVENT(info->data), &segment);
  96. print_segment(segment);
  97. }
  98. } else if (GST_PAD_PROBE_INFO_TYPE(info) & GST_PAD_PROBE_TYPE_BUFFER) {
  99. CustomData* data = (CustomData*) user_data;
  100. g_print("DecodeSrcPad : Buffer %d", buffer_count);
  101. GstBuffer* buffer = GST_PAD_PROBE_INFO_BUFFER (info);
  102. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_LIVE)) g_print(" LIVE");
  103. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DECODE_ONLY)) g_print(" GST_BUFFER_FLAG_DECODE_ONLY");
  104. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DISCONT)) g_print(" GST_BUFFER_FLAG_DISCONT");
  105. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_RESYNC)) g_print(" GST_BUFFER_FLAG_RESYNC");
  106. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_CORRUPTED)) g_print(" GST_BUFFER_FLAG_CORRUPTED");
  107. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_MARKER)) g_print(" GST_BUFFER_FLAG_MARKER");
  108. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_HEADER)) g_print(" GST_BUFFER_FLAG_HEADER");
  109. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_GAP)) g_print(" GST_BUFFER_FLAG_GAP");
  110. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DROPPABLE)) g_print(" GST_BUFFER_FLAG_DROPPABLE");
  111. if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT)) g_print(" GST_BUFFER_FLAG_DELTA_UNIT");
  112.  
  113. g_print(" Duration %"G_GINT64_FORMAT,GST_BUFFER_DURATION(buffer));
  114. gint64 pts = GST_BUFFER_PTS(buffer);
  115. data->frame_duration = GST_BUFFER_DURATION(buffer);
  116. g_print(" PTS : %"G_GINT64_FORMAT" Target : %"G_GINT64_FORMAT" \n", pts, data->lastSeek);
  117. }
  118.  
  119. return GST_PAD_PROBE_PASS;
  120. }
  121.  
  122. void demux_pad_added (GstElement* object, GstPad* arg0, gpointer user_data) {
  123. CustomData *data = (CustomData*)user_data;
  124.  
  125. GstPad* h264parseSinkPad = gst_element_get_static_pad(data->h264parse, "sink");
  126. if (gst_pad_can_link(arg0, h264parseSinkPad)) {
  127. gst_pad_link(arg0, h264parseSinkPad);
  128. 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);
  129. } else {
  130. //TODO : Add fakesink
  131. }
  132. gst_object_unref(h264parseSinkPad);
  133. }
  134.  
  135. static gboolean goto_first(gpointer user_data);
  136. static gboolean goto_end(gpointer user_data) {
  137. g_print("Go to end\n");
  138. CustomData* data = (CustomData*) user_data;
  139. data->lastSeek = 99967000000;
  140. gst_element_seek_simple(data->sink,GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, data->lastSeek);
  141.  
  142. //g_timeout_add_seconds(5, goto_first,data);
  143. return FALSE;
  144. }
  145.  
  146. static gboolean goto_middle(gpointer user_data) {
  147. g_print("Go to midle\n");
  148. CustomData* data = (CustomData*) user_data;
  149. data->lastSeek = data->targetPTSTimecode / 2;
  150. gst_element_seek_simple(data->pipeline,GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, data->targetPTSTimecode / 2);
  151. g_timeout_add_seconds(5, goto_end,data);
  152. return FALSE;
  153.  
  154. }
  155.  
  156. static gboolean goto_first(gpointer user_data) {
  157. g_print("Go to first\n");
  158. CustomData* data = (CustomData*) user_data;
  159. data->lastSeek = 0;
  160. gst_element_seek_simple(data->pipeline,GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, data->lastSeek);
  161. g_timeout_add_seconds(5, goto_middle,data);
  162. return FALSE;
  163. }
  164.  
  165. static gboolean my_bus_callback (GstBus *bus, GstMessage *message, gpointer data)
  166. {
  167. CustomData* source = (CustomData*)data;
  168. switch (GST_MESSAGE_TYPE (message)) {
  169. case GST_MESSAGE_ERROR: {
  170. GError *err;
  171. gchar *debug;
  172. gst_message_parse_error (message, &err, &debug);
  173. g_print ("Error: %s\n", err->message);
  174. g_error_free (err);
  175. g_free (debug);
  176.  
  177. GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(source->pipeline), GST_DEBUG_GRAPH_SHOW_ALL,"test-snapshot-mkv-on-error");
  178.  
  179. g_main_loop_quit (source->loop);
  180. break;
  181. }
  182. case GST_MESSAGE_EOS:
  183. /* end-of-stream */
  184. g_print("Receive EOS on the bus\n");
  185. g_main_loop_quit (source->loop);
  186. break;
  187. case GST_MESSAGE_SEGMENT_DONE:
  188. g_print("Receive segment done\n");
  189. break;
  190. case GST_MESSAGE_ASYNC_DONE:
  191. g_print("Receive async done\n");
  192. gint64 duration;
  193. if (gst_element_query_duration(source->pipeline, GST_FORMAT_TIME, &duration)) {
  194. source->targetPTSTimecode = duration;
  195. g_print("Duration : %"G_GINT64_FORMAT" \n", duration);
  196. } else {
  197. g_print("Failed to query the duration\n");
  198. }
  199. break;
  200. case GST_MESSAGE_DURATION_CHANGED:
  201. g_print("Receive duration change\n");
  202. gint64 durationChange;
  203. if (gst_element_query_duration(source->pipeline, GST_FORMAT_TIME, &durationChange)) {
  204. //source->targetPTSTimecode = duration;
  205. g_print("Duration : %"G_GINT64_FORMAT" \n", durationChange);
  206. } else {
  207. g_print("Failed to query the duration\n");
  208. }
  209. break;
  210. default:
  211. //g_print("%d\n",GST_MESSAGE_TYPE (message));
  212. /* unhandled message */
  213. break;
  214. }
  215.  
  216. return TRUE;
  217. }
  218.  
  219. void new_preroll(GstElement* object, gpointer user_data) {
  220. g_print("########## New preroll\n");
  221. GstSample* sample = gst_app_sink_pull_preroll(GST_APP_SINK(object));
  222. if (sample != NULL) {
  223. g_print("Sample not NULL.\n");
  224. GstBuffer *buffer = gst_sample_get_buffer(sample);
  225. if (buffer) {
  226. g_print("Buffer not NULL !!! \n");
  227. }
  228. }
  229. }
  230.  
  231. void eos(GstElement* object, gpointer user_data) {
  232. g_print("########## EOS\n");
  233. }
  234.  
  235. int main(int argc, char* argv[]) {
  236. gst_init(NULL, NULL);
  237.  
  238. CustomData* data = g_new0(CustomData, 1);
  239. //Initialisation
  240. data->lastSeek= 0;
  241. data->frame_duration = 0;
  242.  
  243. data->pipeline = gst_pipeline_new("snapshot");
  244. data->filesrc = gst_element_factory_make("filesrc", NULL);
  245. data->filedemux = gst_element_factory_make("matroskademux", NULL);
  246. data->h264parse = gst_element_factory_make("h264parse", NULL);
  247. data->h264dec = gst_element_factory_make("avdec_h264", NULL);
  248. data->videoconvert = gst_element_factory_make("videoconvert", NULL);
  249.  
  250. #ifdef USE_VIDEO_SINK
  251. data->enc = gst_element_factory_make("identity", NULL);
  252. data->sink = gst_element_factory_make("xvimagesink", NULL);
  253. g_object_set(data->sink, "sync", FALSE, "async", TRUE, "qos", FALSE, NULL);
  254. #else
  255. data->enc = gst_element_factory_make("pngenc", NULL);
  256. data->sink = gst_element_factory_make("appsink", NULL);
  257. g_object_set(data->sink, "sync", FALSE, "async", FALSE, "emit-signals", TRUE,NULL);
  258. g_object_set(data->enc, "snapshot", FALSE, NULL);
  259. g_signal_connect(data->sink, "new-preroll", G_CALLBACK(new_preroll),data);
  260. g_signal_connect(data->sink, "eos", G_CALLBACK(eos),data);
  261. #endif
  262. //Set initial pipeline settings
  263. g_signal_connect(data->filedemux, "pad-added", G_CALLBACK(demux_pad_added),data);
  264. g_object_set(data->filesrc, "location",VIDEO_FILE_PATH , NULL);
  265.  
  266. gst_bin_add_many(GST_BIN(data->pipeline), data->filesrc, data->filedemux, data->h264parse, data->h264dec, data->videoconvert, data->enc, data->sink, NULL);
  267. gst_element_link(data->filesrc, data->filedemux);
  268. gst_element_link_many(data->h264parse, data->h264dec, data->videoconvert, data->enc, data->sink, NULL);
  269.  
  270. GstPad* sinPad = gst_element_get_static_pad(data->h264dec, "src");
  271. 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);
  272. gst_object_unref(sinPad);
  273.  
  274.  
  275. data->bus = gst_element_get_bus (data->pipeline);
  276. gst_bus_add_watch (data->bus, my_bus_callback, data);
  277. gst_element_set_state(data->pipeline, GST_STATE_PAUSED);
  278. data->loop = g_main_loop_new(NULL,FALSE);
  279. g_timeout_add_seconds(5, goto_end,data);
  280. g_main_loop_run(data->loop);
  281. g_print("Loop exited\n");
  282.  
  283. g_free(data);
  284.  
  285. return 0;
  286. }
RAW Paste Data