#define GST_USE_UNSTABLE_API #include #include #define VIDEO "image/jpeg,framerate=(fraction)0/1,width=640,height=480" typedef struct { GstElement *encoder; GMainLoop *loop; GstElement *pipeline; gboolean linked_something; } MyData; static void on_no_more_pads (GstElement *element, gpointer user_data) { MyData *data = (MyData *)user_data; if (!data->linked_something) { g_print ("Couldn't link decoder and encoder. Bailing out!\n"); g_main_loop_quit (data->loop); } } static void on_pad_added (GstElement *element, GstPad *new_pad, gpointer user_data) { GstPad *sinkpad; MyData *data = (MyData *)user_data; sinkpad = gst_element_get_compatible_pad (data->encoder, new_pad, NULL); if (sinkpad == NULL) { GstCaps *caps = gst_pad_query_caps (new_pad, NULL); g_signal_emit_by_name (data->encoder, "request-pad", caps, &sinkpad); gst_caps_unref (caps); } if (sinkpad == NULL) { g_print ("Couldn't find compatible encodebin pad for pad '%s'. Ignoring...\n", gst_pad_get_name (new_pad)); return; } if (gst_pad_link (new_pad, sinkpad) != GST_PAD_LINK_OK) { g_print ("Failed to link pad '%s' to pad '%s'\n", gst_pad_get_name (new_pad), gst_pad_get_name (sinkpad)); return; } data->linked_something = TRUE; } static gboolean on_autoplug_continue (GstElement *element, GstPad *new_pad, GstCaps *_caps, gpointer user_data) { GstPad *sinkpad; MyData *data = (MyData *)user_data; GstCaps *caps; caps = gst_pad_query_caps (new_pad, NULL); g_signal_emit_by_name (data->encoder, "request-pad", caps, &sinkpad); gst_caps_unref (caps); if (sinkpad == NULL) { return TRUE; } return FALSE; } static GstElement * setup_encodebin () { GstElement *encodebin; GstCaps *audio, *video, *restriction, *container; GstEncodingAudioProfile *audio_profile; GstEncodingVideoProfile *video_profile; GstEncodingContainerProfile *container_profile; encodebin = gst_element_factory_make ("encodebin", NULL); video = gst_caps_from_string (VIDEO); video_profile = gst_encoding_video_profile_new (video, NULL, NULL, 1); g_object_set (encodebin, "profile", video_profile, NULL); return encodebin; } static gboolean quit_loop (GMainLoop *loop) { g_main_loop_quit (loop); return FALSE; } static gboolean on_bus (GstBus *bus, GstMessage *message, gpointer user_data) { MyData *data = (MyData *)user_data; if (message->type == GST_MESSAGE_STATE_CHANGED) { if (GST_MESSAGE_SRC (message) == (GstObject *)data->pipeline) { GstState old, new; gint64 duration, start = 300 * GST_SECOND; gst_message_parse_state_changed (message, &old, &new, NULL); if (old == GST_STATE_NULL && new == GST_STATE_READY) { GstElement *el; GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (data->pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "encode"); GstFormat format = GST_FORMAT_TIME; gst_element_query_duration (data->pipeline, format, &duration); duration -= GST_MSECOND; } } } if (message->type == GST_MESSAGE_EOS) { g_idle_add ((GSourceFunc) quit_loop, data->loop); return FALSE; } if (message->type == GST_MESSAGE_ERROR || message->type == GST_MESSAGE_WARNING) { GError *error = NULL; gchar *debug; gst_message_parse_error (message, &error, &debug); g_print ("Pipeline failed: %s: %s\n", error->message, debug); g_error_free (error); g_free (debug); g_idle_add ((GSourceFunc) quit_loop, data->loop); return FALSE; } } int main (int argc, char *argv[]) { GstElement *src, *decodebin, *encodebin, *sink, *pipeline, *queue; char *output_file, *basename; MyData data; GstBus *bus; // g_type_init (); gst_init (&argc, &argv); if (argc != 2) { return 1; } gst_preset_set_app_dir ("presets"); output_file = g_strconcat (argv[1], ".mpg", NULL); src = gst_element_factory_make ("filesrc", NULL); decodebin = gst_element_factory_make ("decodebin", NULL); g_signal_connect (decodebin, "pad-added", G_CALLBACK (on_pad_added), &data); g_signal_connect (decodebin, "autoplug-continue", G_CALLBACK (on_autoplug_continue), &data); g_signal_connect (decodebin, "no-more-pads", G_CALLBACK (on_no_more_pads), &data); encodebin = setup_encodebin (); data.encoder = encodebin; sink = gst_element_factory_make ("filesink", NULL); g_object_set (src, "location", argv[1], NULL); g_object_set (sink, "location", output_file, NULL); g_free (output_file); queue = gst_element_factory_make ("queue2", NULL); pipeline = gst_pipeline_new ("transcoder"); data.pipeline = pipeline; gst_bin_add_many (GST_BIN (pipeline), src, decodebin, encodebin, queue, sink, NULL); gst_element_link (src, decodebin); gst_element_link (encodebin, queue); gst_element_link (queue, sink); data.loop = g_main_loop_new (NULL, FALSE); bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); gst_bus_add_watch (bus, on_bus, &data); gst_element_set_state (pipeline, GST_STATE_PLAYING); g_main_loop_run (data.loop); return 0; }