#include #include #define CONTAINER "video/mpegts,systemstream=true,packetsize=188" #define AUDIO "audio/mpeg,mpegversion=1,layer=2" #define VIDEO "video/mpeg,mpegversion=2,systemstream=false" #define VIDEO_RESTRICTION "video/x-raw-yuv,framerate=(fraction)25/1,width=720,height=576" 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_get_caps_reffed (new_pad); 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_get_caps_reffed (new_pad); 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); container = gst_caps_from_string (CONTAINER); audio = gst_caps_from_string (AUDIO); video = gst_caps_from_string (VIDEO); restriction = gst_caps_from_string (VIDEO_RESTRICTION); audio_profile = gst_encoding_audio_profile_new (audio, NULL, NULL, 1); video_profile = gst_encoding_video_profile_new (video, NULL, restriction, 1); container_profile = gst_encoding_container_profile_new (NULL, NULL, container, NULL); gst_encoding_container_profile_add_profile (container_profile, (GstEncodingProfile*) audio_profile); gst_encoding_container_profile_add_profile (container_profile, (GstEncodingProfile*) video_profile); g_object_set (encodebin, "profile", container_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_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", 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; char *output_file; MyData data; GstBus *bus; g_type_init (); gst_init (&argc, &argv); if (argc != 2) { return 1; } output_file = g_strconcat (argv[1], ".mpeg", NULL); src = gst_element_factory_make ("filesrc", NULL); decodebin = gst_element_factory_make ("decodebin2", 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); pipeline = gst_pipeline_new ("transcoder"); data.pipeline = pipeline; gst_bin_add_many (GST_BIN (pipeline), src, decodebin, encodebin, sink, NULL); gst_element_link (src, decodebin); gst_element_link (encodebin, 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; }