GStreamer application to convert a .ogg file to an .mp4 file
William Metcalf
wmetcalf at niftytv.com
Mon Jun 6 11:17:24 PDT 2011
Matt,
Thank you for the tips. It turns out that my problem was that the
numbers after serial_ in the on_pad_added function were changing each
time I ran the application, so my audio and video from the demuxer were
not getting linked to the pads on the corresponding queues. I simply
altered my string comparison and it started working perfectly.
Thank you for your help,
William
On 6/6/2011 12:54 PM, Matt Veenstra wrote:
> Hi William,
>
> When I am trying to debug this cases.
> - I try and simplify the pipeline as much as possible.
> - I would eliminate the audio or video channel and drop this to a fakesink.
> - confirm on_pad_added() being called?
> - I specifically link all items myself instead of using
> gst_element_link_many() to confirm each step. And log in between.
> - Looking at debug is also very useful, but sometimes overwhelming the
> first look.
>
>
> Cheers,
> Matt
>
> On Fri, Jun 3, 2011 at 1:41 PM, William Metcalf<wmetcalf at niftytv.com> wrote:
>> I am writing an application to convert a .ogg file to an .mp4 file. My code
>> is below. I already have the terminal pipeline for completing this task,
>> and I am just trying to convert the terminal pipeline into an actual c
>> program. The pipeline seems correct to be, but when I run the application I
>> get an error "Internal data stream error". Does anyone have any suggestions
>> as to what is wrong with my code? Thank you in advance.
>>
>> #include<gst\gst.h>
>> #include<glib-2.0\glib.h>
>> #include<string.h>
>> #include"Encode_File_Test.h"
>> #include"Preprocessor_Defines.h"
>>
>> /* Handle messages from the pipeline bus */
>> static gboolean bus_call(GstBus *bus, GstMessage *msg, gpointer data)
>> {
>> GMainLoop *loop = (GMainLoop * ) data;
>>
>> switch(GST_MESSAGE_TYPE(msg))
>> {
>> case GST_MESSAGE_EOS:
>> g_print("End of stream\n");
>> g_main_loop_quit(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);
>>
>> g_main_loop_quit(loop);
>> break;
>> }
>> default:
>> break;
>> }
>>
>> return TRUE;
>> }
>>
>> /* Handles when a pad is added to the demuxer */
>> static void on_pad_added(GstElement *element, GstPad *pad, gpointer data)
>> {
>> guint result;
>> GstPad *sinkpad;
>> gchar* name;
>> name = gst_pad_get_name(pad);
>>
>> result = g_strcasecmp(name, "serial_1fa82364");
>> /* This is the audio pad of the demuxer we need to link it to the
>> decoder's audio output in the queue */
>> if(!result)
>> {
>> /* We can now link this pad with the audio decoder's sink pad */
>> g_print("Dynamic pad created, linking the demuxer to the audio
>> decoder\n");
>>
>> sinkpad = gst_element_get_pad(audio_queue, "sink");
>>
>> gst_pad_link(pad, sinkpad);
>>
>> gst_object_unref(sinkpad);
>> }
>>
>> result = g_strcasecmp(name, "serial_0f0678e1");
>> /* This is the video pad of the demuxer we need to link it to the
>> decoder's video output in the queue */
>> if(!result)
>> {
>>
>> /* We can now link this pad with the video decoder's sink pad */
>> g_print("Dynamic pad created, linking the demuxer to the video
>> decoder\n");
>>
>> sinkpad = gst_element_get_static_pad(video_queue, "sink");
>>
>> gst_pad_link(pad, sinkpad);
>>
>> gst_object_unref(sinkpad);
>> }
>> }
>>
>> /* Connects the src pad of the audio out queue to the audio sink pad of the
>> mxuer */
>> static void link_audio_to_multiplexer(GstElement *audio_output, GstElement
>> *muxer)
>> {
>> GstPad *pad, *link_pad;
>>
>> link_pad = gst_element_get_static_pad(audio_output, "src");
>>
>> pad = gst_element_get_request_pad(muxer, "audio_%d");
>>
>> gst_pad_link(link_pad, pad);
>>
>> gst_object_unref(pad);
>> }
>>
>> /* Connects the src pad of the video out queue to the video sink pad of the
>> muxer */
>> static void link_video_to_multiplexer(GstElement *video_output, GstElement
>> *muxer)
>> {
>> GstPad *pad, *link_pad;
>>
>> link_pad = gst_element_get_static_pad(video_output, "src");
>>
>> pad = gst_element_get_request_pad(muxer, "video_%d");
>>
>> gst_pad_link(link_pad, pad);
>>
>> gst_object_unref(pad);
>> }
>>
>> int main (int argc, char *argv[])
>> {
>> gst_init(&argc,&argv);
>>
>> loop = g_main_loop_new(NULL, FALSE);
>>
>> /* Create elements */
>> pipeline = gst_pipeline_new("audio-player");
>>
>> /* Element for reading in a file */
>> source = gst_element_factory_make("filesrc",
>> "file-source");
>>
>> /* OGG elements */
>> oggdemuxer = gst_element_factory_make("oggdemux",
>> "ogg-demuxer");
>> vorbis_decoder = gst_element_factory_make("vorbisdec",
>> "vorbis-decoder");
>> theora_decoder = gst_element_factory_make("theoradec",
>> "theora-decoder");
>>
>> /* MP4 elements */
>> audio_encoder = gst_element_factory_make("faac", "aac-encoder");
>> video_encoder = gst_element_factory_make("ffenc_mpeg4",
>> "avc-encoder");
>> mp4_muxer = gst_element_factory_make("qtmux", "mp4-muxer");
>>
>> /* Audio Video elements */
>> audio_converter = gst_element_factory_make("audioconvert",
>> "audio-converter");
>> video_converter = gst_element_factory_make("ffmpegcolorspace",
>> "video-converter");
>> audio_resample = gst_element_factory_make("audioresample",
>> "audio-resample");
>> audio_rate = gst_element_factory_make("audiorate",
>> "audio-rate");
>> videosink = gst_element_factory_make("autovideosink",
>> "video-sink");
>> audiosink = gst_element_factory_make("autoaudiosink",
>> "audio-sink");
>>
>> /* Queues */
>> video_queue = gst_element_factory_make("queue",
>> "video-queue");
>> audio_queue = gst_element_factory_make("queue",
>> "audio-queue");
>> video_out_queue = gst_element_factory_make("queue",
>> "video-out-queue");
>> audio_out_queue = gst_element_factory_make("queue",
>> "audio-out-queue");
>>
>> /* Element to write to the file */
>> filesink = gst_element_factory_make("filesink",
>> "file-sink");
>>
>> /* Make sure we were able to create all of the elements*/
>> if(!pipeline || !source || !oggdemuxer || !vorbis_decoder ||
>> !theora_decoder || !audio_encoder || !video_encoder || !mp4_muxer ||
>> !audio_converter || !video_converter || !audio_resample || !audio_rate ||
>> !videosink || !audiosink || !video_queue || !audio_queue || !video_out_queue
>> || !audio_out_queue || !filesink )
>> {
>> g_printerr("One ore more elements could not be created. Exiting.\n");
>> return -1;
>> }
>>
>> /* Input file */
>> g_object_set(G_OBJECT(source), "location", "c:\\video.ogg", NULL);
>> g_object_set(G_OBJECT(filesink), "location", "c:\\video(encoded from
>> ogg).mp4", NULL);
>>
>> /* Add a message handler from pipeline bus */
>> bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
>> gst_bus_add_watch(bus, bus_call, loop);
>> gst_object_unref(bus);
>>
>> /* add elements to the pipeline */
>> gst_bin_add_many(GST_BIN(pipeline), source, oggdemuxer, video_queue,
>> theora_decoder, video_converter, video_encoder, video_out_queue,
>> audio_queue, vorbis_decoder, audio_converter, audio_encoder,
>> audio_out_queue, mp4_muxer, filesink, NULL);
>>
>> /* link the elements together */
>> gst_element_link(source, oggdemuxer);
>>
>> /* video_queue -> theoradec -> ffmpegcolorspace -> ffenc_mpeg4 ->
>> video_out_queue ~> qtmux */
>> res = gst_element_link_many(video_queue, theora_decoder, video_converter,
>> video_encoder, video_out_queue, NULL);
>> if(!res)
>> {
>> g_printerr("There was a problem linking video elements.\n");
>> return 1;
>> }
>>
>> /* queue_audio -> vorbisdec -> audioconvert -> faac -> audio_out_queue ~>
>> qtmux */
>> res = gst_element_link_many(audio_queue, vorbis_decoder, audio_converter,
>> audio_encoder, audio_out_queue, NULL);
>> if(!res)
>> {
>> g_printerr("There was a problem linking elements.\n");
>> return 1;
>> }
>> g_signal_connect(oggdemuxer, "pad-added", G_CALLBACK(on_pad_added),
>> NULL);
>>
>> /* qtmux -> filesink */
>> res = gst_element_link(mp4_muxer, filesink);
>>
>> link_video_to_multiplexer(video_out_queue, mp4_muxer);
>> link_audio_to_multiplexer(audio_out_queue, mp4_muxer);
>>
>>
>> /* Set the pipeline stat to play and start the main loop*/
>> g_print("Starting the pipeline\n");
>> gst_element_set_state(pipeline, GST_STATE_PLAYING);
>> g_main_loop_run(loop);
>>
>> /* We are done now, do a little bit of cleaning up */
>> g_print("Stopping the pipeline.\n");
>> gst_element_set_state(pipeline, GST_STATE_NULL);
>> gst_object_unref(GST_OBJECT(pipeline));
>>
>> return 0;
>> }
>> _______________________________________________
>> gstreamer-devel mailing list
>> gstreamer-devel at lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
>>
> _______________________________________________
> gstreamer-devel mailing list
> gstreamer-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
More information about the gstreamer-devel
mailing list