1 /* Example application for using GstProfile and encodebin
2 * Copyright (C) 2009 Edward Hervey <edward.hervey@collabora.co.uk>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
27 #include <gst/profile/gstprofile.h>
28 #include <gst/pbutils/pbutils.h>
29 #include <libgupnp-dlna/gupnp-dlna-profile.h>
31 static gboolean silent = FALSE;
34 pad_added_cb (GstElement * uridecodebin, GstPad * pad, GstElement * encodebin)
38 sinkpad = gst_element_get_compatible_pad (encodebin, pad, NULL);
40 if (sinkpad == NULL) {
43 /* Ask encodebin for a compatible pad */
44 caps = gst_pad_get_caps (pad);
45 g_signal_emit_by_name (encodebin, "request-pad", caps, &sinkpad);
47 gst_caps_unref (caps);
49 if (sinkpad == NULL) {
50 g_print ("Couldn't get an encoding channel for pad %s:%s\n",
51 GST_DEBUG_PAD_NAME (pad));
55 if (G_UNLIKELY (gst_pad_link (pad, sinkpad) != GST_PAD_LINK_OK)) {
56 g_print ("Couldn't link pads\n");
63 autoplug_continue_cb (GstElement * uridecodebin, GstPad * somepad,
64 GstCaps * caps, GstElement * encodebin)
68 g_signal_emit_by_name (encodebin, "request-pad", caps, &sinkpad);
77 bus_message_cb (GstBus * bus, GstMessage * message, GMainLoop * mainloop)
79 switch (GST_MESSAGE_TYPE (message)) {
80 case GST_MESSAGE_ERROR:
82 g_main_loop_quit (mainloop);
86 g_main_loop_quit (mainloop);
94 transcode_file (gchar * uri, gchar * outputuri, GstEncodingProfile * prof)
101 GstCaps *profilecaps, *rescaps;
104 g_print (" Input URI : %s\n", uri);
105 g_print (" Output URI : %s\n", outputuri);
107 sink = gst_element_make_from_uri (GST_URI_SINK, outputuri, "sink");
108 if (G_UNLIKELY (sink == NULL)) {
109 g_print ("Can't create output sink, most likely invalid output URI !\n");
113 src = gst_element_factory_make ("uridecodebin", NULL);
114 if (G_UNLIKELY (src == NULL)) {
115 g_print ("Can't create uridecodebin for input URI, aborting!\n");
119 /* Figure out the streams that can be passed as-is to encodebin */
120 g_object_get (src, "caps", &rescaps, NULL);
121 rescaps = gst_caps_copy (rescaps);
122 profilecaps = gst_encoding_profile_get_codec_caps (prof);
123 gst_caps_append (rescaps, profilecaps);
126 g_object_set (src, "uri", uri, "caps", rescaps, NULL);
128 ebin = gst_element_factory_make ("encodebin", NULL);
129 g_object_set (ebin, "profile", prof, NULL);
131 g_signal_connect (src, "autoplug-continue", G_CALLBACK (autoplug_continue_cb),
133 g_signal_connect (src, "pad-added", G_CALLBACK (pad_added_cb), ebin);
135 pipeline = gst_pipeline_new ("encoding-pipeline");
137 gst_bin_add_many (GST_BIN (pipeline), src, ebin, sink, NULL);
139 gst_element_link (ebin, sink);
141 mainloop = g_main_loop_new (NULL, FALSE);
143 bus = gst_pipeline_get_bus ((GstPipeline *) pipeline);
144 gst_bus_add_signal_watch (bus);
145 g_signal_connect (bus, "message", G_CALLBACK (bus_message_cb), mainloop);
147 if (gst_element_set_state (pipeline,
148 GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
149 g_print ("Failed to start the encoding\n");
153 g_main_loop_run (mainloop);
155 gst_element_set_state (pipeline, GST_STATE_NULL);
159 ensure_uri (gchar * location)
164 if (gst_uri_is_valid (location))
165 return g_strdup (location);
167 if (!g_path_is_absolute (location)) {
169 cur_dir = g_get_current_dir ();
170 path = g_build_filename (cur_dir, location, NULL);
173 path = g_strdup (location);
175 res = g_filename_to_uri (path, NULL, NULL);
182 main (int argc, char **argv)
185 gchar *outputuri = NULL;
186 gchar *format = NULL;
187 GOptionEntry options[] = {
188 {"silent", 's', 0, G_OPTION_ARG_NONE, &silent,
189 "Don't output the information structure", NULL},
190 {"outputuri", 'o', 0, G_OPTION_ARG_STRING, &outputuri,
191 "URI to encode to", "URI (<protocol>://<location>)"},
192 {"format", 'f', 0, G_OPTION_ARG_STRING, &format,
193 "DLNA profile to use", NULL},
197 GUPnPDLNAProfile *profile;
200 if (!g_thread_supported ())
201 g_thread_init (NULL);
203 ctx = g_option_context_new ("- encode URIs with GstProfile and encodebin");
204 g_option_context_add_main_entries (ctx, options, NULL);
205 g_option_context_add_group (ctx, gst_init_get_option_group ());
207 if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
208 g_print ("Error initializing: %s\n", err->message);
212 g_option_context_free (ctx);
214 if (outputuri == NULL || argc != 2) {
215 g_print ("usage: %s <inputuri> -o <outputuri> --format <profile>\n",
220 /* Create the profile */
221 profile = gupnp_dlna_profile_from_name (format);
222 if (G_UNLIKELY (profile == NULL)) {
223 g_print ("Encoding arguments are not valid !\n");
227 /* Fixup outputuri to be a URI */
228 inputuri = ensure_uri (argv[1]);
229 outputuri = ensure_uri (outputuri);
232 transcode_file (inputuri, outputuri, profile->enc_profile);
235 g_object_unref (profile);