Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * main.c
- *
- * Created on: Jan 6, 2014
- * Author: memphis
- */
- #include <sys/time.h>
- #include <glib.h>
- #include "gst/gst.h"
- typedef struct {
- //Main elements
- GstElement *pipeline;
- GMainLoop *loop;
- GstBus *bus;
- //Gst elements
- GstElement *src;
- GstElement *demux;
- GstElement *parse;
- GstElement *parseCaps;
- GstElement *queue;
- GstElement *sink_bin;
- //Misc
- GstSegment segment;
- gboolean ignoreEOS;
- gulong probeid;
- gulong probeeventid;
- guint64 startTime;
- GstClockTime offset;
- } CustomData;
- guint64 get_time_in_milli() {
- struct timeval tv;
- gettimeofday(&tv, NULL);
- return tv.tv_sec * 1000000ULL + tv.tv_usec;
- }
- void print_segment(GstSegment* segment) {
- g_print("### Segment ###\n");
- g_print("Rate : %"G_GINT64_FORMAT"\n", segment->rate);
- g_print("Base : %"G_GUINT64_FORMAT"\n", segment->base);
- g_print("Offset : %"G_GUINT64_FORMAT"\n", segment->offset);
- g_print("Start : %"G_GUINT64_FORMAT"\n", segment->start);
- g_print("Stop : %"G_GUINT64_FORMAT"\n", segment->stop);
- g_print("Time : %"G_GUINT64_FORMAT"\n", segment->time);
- g_print("Position : %"G_GUINT64_FORMAT"\n", segment->position);
- g_print("Duration : %"G_GUINT64_FORMAT"\n", segment->duration);
- }
- void build_sink_bin(CustomData* data) {
- if (data->sink_bin == NULL) {
- data->sink_bin = gst_bin_new("save_bin");
- GstElement* mux = gst_element_factory_make("matroskamux", NULL);
- GstElement* filesink = gst_element_factory_make("filesink", NULL);
- gchar* filedest = g_strdup_printf("%"G_GINT64_FORMAT".mkv",g_get_real_time());
- g_object_set(filesink, "location", filedest, "sync", TRUE, "async", TRUE, NULL);
- gst_bin_add_many(GST_BIN(data->sink_bin), mux, filesink, NULL);
- gst_element_link(mux, filesink);
- //Create ghost pad
- GstPad* sinkMuxPad = gst_element_get_request_pad(mux, "video_%u");
- gst_element_add_pad (data->sink_bin, gst_ghost_pad_new ("sink", sinkMuxPad));
- gst_object_unref (GST_OBJECT (sinkMuxPad));
- gst_bin_add(GST_BIN(data->pipeline), data->sink_bin);
- gst_element_link(data->queue, data->sink_bin);
- }
- }
- void reset_sink_bin (CustomData *data){
- gst_element_set_state (data->sink_bin, GST_STATE_NULL);
- gst_bin_remove(GST_BIN(data->pipeline), data->sink_bin);
- data->sink_bin = NULL;
- build_sink_bin(data);
- gst_element_set_state (data->sink_bin, GST_STATE_PLAYING);
- }
- static GstPadProbeReturn probe (GstPad *pad, GstPadProbeInfo *info, gpointer user_data) {
- CustomData *data = (CustomData *) user_data;
- GstBuffer* buffer = GST_PAD_PROBE_INFO_BUFFER (info);
- if (data->startTime == 0) {
- data->startTime = get_time_in_milli();
- if (data->offset > 0) {
- // guint64 clipStart;
- // guint64 clipStop;
- // if (gst_segment_clip(&data->segment, GST_FORMAT_TIME, data->offset, -1, &clipStart, &clipStop))
- // g_print("Clip success\n");
- // g_print("ClipStart : %"G_GUINT64_FORMAT" ClipStop %"G_GUINT64_FORMAT"\n", clipStart, clipStop);
- // data->segment.start = data->offset;
- //print_segment(&data->segment);
- /* (POC_Recording2:14630): GStreamer-WARNING **: gstpad.c:4506:store_sticky_event:<sink:proxypad1> Sticky event misordering, got 'segment' before 'stream-start'
- * (POC_Recording2:14630): GStreamer-WARNING **: gstpad.c:4506:store_sticky_event:<save_bin:sink> Sticky event misordering, got 'segment' before 'caps'
- *
- *
- */
- // GstPad* binPad = gst_element_get_static_pad(data->sink_bin, "sink");
- // gst_pad_send_event(binPad, gst_event_new_segment(&data->segment));
- // gst_object_unref(binPad);
- }
- }
- else {
- guint64 diff = get_time_in_milli() - data->startTime;
- if (diff > 5* 1000000ULL) {
- GstBuffer* buffer = GST_PAD_PROBE_INFO_BUFFER (info);
- if (GST_BUFFER_FLAG_IS_SET(buffer,GST_BUFFER_FLAG_DELTA_UNIT) != TRUE) {
- g_print("Sent EOS in sink bin\n");
- data->ignoreEOS = TRUE;
- GstPad* binPad = gst_element_get_static_pad(data->sink_bin, "sink");
- gst_pad_send_event(binPad, gst_event_new_eos());
- gst_object_unref(binPad);
- gst_debug_bin_to_dot_file(GST_BIN(data->pipeline), GST_DEBUG_GRAPH_SHOW_ALL,"eos" );
- data->startTime = 0;
- data->offset = GST_BUFFER_PTS(buffer);
- return GST_PAD_PROBE_OK;
- }
- }
- }
- buffer = gst_buffer_make_writable(buffer);
- //GST_BUFFER_PTS(buffer) -= data->offset;
- GstClockTime pts = GST_BUFFER_PTS(buffer);
- GstClockTime offset = GST_BUFFER_OFFSET(buffer);
- GstClockTime offset_end = GST_BUFFER_OFFSET_END(buffer);
- g_print("PTS %"G_GUINT64_FORMAT" Offset %"G_GUINT64_FORMAT" Offset end %"G_GUINT64_FORMAT"\n", pts, offset, offset_end);
- return GST_PAD_PROBE_PASS;
- }
- static GstPadProbeReturn
- event_probe(GstPad *pad, GstPadProbeInfo *info, gpointer user_data) {
- if (GST_EVENT_TYPE (GST_PAD_PROBE_INFO_DATA (info)) == GST_EVENT_SEGMENT) {
- CustomData* data = (CustomData*) user_data;
- gst_event_copy_segment (GST_PAD_PROBE_INFO_EVENT(info), &data->segment);
- g_print("############### Receive segment ########################\n");
- print_segment(&data->segment);
- }
- return GST_PAD_PROBE_PASS;
- }
- void set_queue_probe(CustomData* data) {
- if (data->queue != NULL) {
- GstPad* queueSrcPad = gst_element_get_static_pad(data->queue, "src");
- if (queueSrcPad) {
- if (data->probeid != 0) {
- gst_pad_remove_probe(queueSrcPad, data->probeid);
- g_print ("Pad unblocked\n");
- }
- if (data->probeeventid != 0) {
- gst_pad_remove_probe(queueSrcPad, data->probeeventid);
- }
- //Set the probe
- data->probeid = gst_pad_add_probe (queueSrcPad, GST_PAD_PROBE_TYPE_BLOCK | GST_PAD_PROBE_TYPE_BUFFER ,(GstPadProbeCallback) probe, data, NULL);
- data->probeeventid = gst_pad_add_probe (queueSrcPad, GST_PAD_PROBE_TYPE_EVENT_BOTH,(GstPadProbeCallback) event_probe, data, NULL);
- gst_object_unref(queueSrcPad);
- } else {
- g_warning("Failed to get the queue src pad.");
- }
- }
- }
- void padAdded (GstElement* object,
- GstPad* arg0,
- gpointer user_data) {
- CustomData* data = (CustomData* ) user_data;
- g_print("Receive pad.\n");
- GstPad* sinkPad = gst_element_get_static_pad(data->parse, "sink");
- if (gst_pad_can_link(arg0, sinkPad)) {
- gst_pad_link(arg0, sinkPad);
- gst_debug_bin_to_dot_file(GST_BIN(data->pipeline), GST_DEBUG_GRAPH_SHOW_ALL,"pad" );
- } else {
- //link to fakesink
- // GstElement* fakesink = gst_element_factory_make("fakesink", NULL);
- // gst_bin_add(GST_BIN(data->pipeline), fakesink);
- //
- // GstPad* fakesinkSinkPad = gst_element_get_static_pad(fakesink, "sink");
- // gst_pad_link(arg0, fakesinkSinkPad);
- // gst_object_unref(fakesinkSinkPad);
- //
- // gst_element_set_state(fakesink, GST_STATE_PLAYING);
- }
- gst_object_unref(sinkPad);
- }
- static gboolean
- bus_call (GstBus *bus,
- GstMessage *msg,
- gpointer user_data)
- {
- CustomData *data = (CustomData *) user_data;
- switch (GST_MESSAGE_TYPE (msg)) {
- case GST_MESSAGE_EOS:
- g_print("Receive EOS\n");
- if (data->ignoreEOS) {
- data->ignoreEOS = FALSE;
- g_print ("Changing file\n");
- reset_sink_bin(data);
- g_print("Unblocking the pad\n");
- set_queue_probe(data);
- } else {
- g_print ("Caught end of stream, strange!\n");
- g_main_loop_quit (data->loop);
- }
- break;
- case GST_MESSAGE_ERROR: {
- gchar *debug;
- GError *error;
- gst_message_parse_error (msg, &error, &debug);
- g_free (debug);
- g_printerr ("Error: %s\n", error->message);
- g_error_free (error);
- gst_debug_bin_to_dot_file(GST_BIN(data->pipeline), GST_DEBUG_GRAPH_SHOW_ALL,"on_error" );
- g_main_loop_quit (data->loop);
- break;
- }
- default:
- break;
- }
- return TRUE;
- }
- void help () {
- g_printerr ("Usage: POC_Segment pathtofile\nExample : POC_Segment /home/user/file.mkv\n");
- }
- int
- main (int argc,
- char *argv[])
- {
- if (argc != 2) {
- help();
- return -1;
- }
- if (!g_file_test(argv[1],G_FILE_TEST_IS_REGULAR)) {
- g_printerr ("FATAL: \"%s\" is not a file\n", argv[2]);
- help();
- return -2;
- }
- gst_init (NULL, NULL);
- CustomData data;
- data.probeid = 0;
- data.probeeventid = 0;
- data.startTime = 0;
- data.sink_bin = NULL;
- data.ignoreEOS = FALSE;
- data.offset = 0;
- data.loop = g_main_loop_new (NULL, FALSE);
- data.pipeline = gst_pipeline_new("segmentation");
- data.src = gst_element_factory_make("filesrc", NULL);
- data.demux = gst_element_factory_make("matroskademux", NULL);
- data.parse = gst_element_factory_make("h264parse", NULL);
- data.parseCaps = gst_element_factory_make("capsfilter", NULL);
- data.queue = gst_element_factory_make("queue", NULL);
- //Set properties and signals
- g_object_set(data.src, "location", argv[1], "do-timestamp", TRUE, NULL);
- g_signal_connect(data.demux, "pad-added", G_CALLBACK(padAdded), &data);
- data.bus = gst_pipeline_get_bus (GST_PIPELINE (data.pipeline));
- guint bus_watch_id = gst_bus_add_watch (data.bus, bus_call, &data);
- gst_object_unref (data.bus);
- /* we add all elements into the pipeline */
- gst_bin_add_many (GST_BIN (data.pipeline), data.src, data.demux, data.parse, data.parseCaps, data.queue, NULL);
- gst_element_link (data.src, data.demux);
- gst_element_link_many(data.parse, data.parseCaps, data.queue, NULL);
- build_sink_bin(&data);
- set_queue_probe(&data);
- gst_element_set_state (data.pipeline, GST_STATE_PLAYING);
- g_print ("Running...\n");
- g_main_loop_run (data.loop);
- g_print ("Loop exited\n");
- gst_element_set_state (data.pipeline, GST_STATE_NULL);
- gst_object_unref (GST_OBJECT (data.pipeline));
- g_source_remove (bus_watch_id);
- g_main_loop_unref (data.loop);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement