#include #include #include /* gstreamer helloworld.c audio player example modified to show how to set v4l2src video norm (PAL, NTSC etc.) and input selection (Composite, S-Video, Television, etc.) Compile with: gcc HelloVideo.c -o HelloVideo `pkg-config --cflags --libs gstreamer-0.10 gstreamer-interfaces-0.10` or: gcc -Wall $(pkg-config --cflags --libs gstreamer-0.10 gstreamer-interfaces-0.10) HelloVideo.c -o HelloVideo */ 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; } /* not needed in the video example static void on_pad_added (GstElement *element, GstPad *pad, gpointer data) { GstPad *sinkpad; GstElement *decoder = (GstElement *) data; // We can now link this pad with the vorbis-decoder sink pad // g_print ("Dynamic pad created, linking demuxer/decoder\n"); sinkpad = gst_element_get_static_pad (decoder, "sink"); gst_pad_link (pad, sinkpad); gst_object_unref (sinkpad); } */ int main (int argc, char *argv[]) { GMainLoop *loop; GstElement *pipeline, *source, *queue, *colorspace,/* *demuxer, *decoder, *conv,*/ *sink; GstBus *bus; gboolean link_ok; GstCaps *caps; /* Initialisation */ gst_init (&argc, &argv); loop = g_main_loop_new (NULL, FALSE); /* Check input arguments */ // if (argc != 2) { // g_printerr ("Usage: %s \n", argv[0]); // return -1; // } /* Create gstreamer elements */ pipeline = gst_pipeline_new ("v4l2src-test"); source = gst_element_factory_make ("v4l2src", "video-source"); queue = gst_element_factory_make ("queue", "video-queue"); colorspace = gst_element_factory_make("ffmpegcolorspace", "colorspace"); //demuxer = gst_element_factory_make ("oggdemux", "ogg-demuxer"); //decoder = gst_element_factory_make ("vorbisdec", "vorbis-decoder"); //conv = gst_element_factory_make ("audioconvert", "converter"); sink = gst_element_factory_make ("xvimagesink", "video-output"); if (!pipeline || !source || !queue || !colorspace ||/*!demuxer || !decoder || !conv ||*/ !sink) { g_printerr ("One element could not be created. Exiting.\n"); return -1; } /* Set up the pipeline */ /* we set the input filename to the source element */ //g_object_set (G_OBJECT (source), "location", argv[1], NULL); /* we add a message handler */ bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); gst_bus_add_watch (bus, bus_call, loop); gst_object_unref (bus); /* we add all elements into the pipeline */ /* file-source | ogg-demuxer | vorbis-decoder | converter | alsa-output */ gst_bin_add_many (GST_BIN (pipeline), source, queue, colorspace,/*demuxer, decoder, conv,*/ sink, NULL); /* we link the elements together */ /* file-source -> ogg-demuxer ~> vorbis-decoder -> converter -> alsa-output */ caps = gst_caps_new_simple ("video/x-raw-yuv", "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'), "width", G_TYPE_INT, 640, "height", G_TYPE_INT, 480, "framerate", GST_TYPE_FRACTION, 30000, 1001, NULL); /* // I had planed seperate input and output color spaces, but Ubuntu 8.04 vrl2src doesn't support video/x-raw-gray even though my card and driver does //Don't know if this is a Ubuntu 8.04 issue or a gstreamer issue // from the console: // GST_DEBUG=v4l2*:5 gst-launch v4l2src num-buffers=1 ! fakesink 2>&1 | grep probed // will dump the video formats actually supported by v4l2src on your system caps = gst_caps_new_simple ("video/x-raw-gray", //"format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'), "width", G_TYPE_INT, 640, "height", G_TYPE_INT, 480, "framerate", GST_TYPE_FRACTION, 30, 1, NULL); */ link_ok = gst_element_link_filtered (source, queue, caps); gst_caps_unref (caps); if (!link_ok) { g_warning ("Failed to link v4l2src and queue with filtered caps!\n"); } link_ok=gst_element_link (queue, colorspace); if (!link_ok) { g_warning ("Failed to link queue and colorspace\n"); } link_ok=gst_element_link (colorspace, sink); if (!link_ok) { g_warning ("Failed to link colorspace and xcimagesink\n"); } //gst_element_link_many (decoder, conv, sink, NULL); //g_signal_connect (demuxer, "pad-added", G_CALLBACK (on_pad_added), decoder); /* note that the demuxer will be linked to the decoder dynamically. The reason is that Ogg may contain various streams (for example audio and video). The source pad(s) will be created at run time, by the demuxer when it detects the amount and nature of streams. Therefore we connect a callback function which will be executed when the "pad-added" is emitted.*/ //pipeline is created and linked, set to PAUSED so we can access the v4l2src tuner "interface" gst_element_set_state (pipeline, GST_STATE_PAUSED); #define _V4L2_PROBE 0 GstTuner *tuner = GST_TUNER( (GstTuner *) source); // get a pointer to access the tuner "interface" #if _V4L2_PROBE_ // setup NTSC mode and select correct input source GList *l, *norms = (GList *) gst_tuner_list_norms (tuner); // probe to see what's available for (l = norms; l != NULL; l = l->next) { GstTunerNorm *norm = GST_TUNER_NORM (l->data); if (GST_VALUE_HOLDS_FRACTION (&norm->framerate)) { g_print ("Norm: %s @ %d/%d fps\n", norm->label, gst_value_get_fraction_numerator (&norm->framerate), gst_value_get_fraction_denominator (&norm->framerate)); } else { g_print ("Norm: %s\n", norm->label); } } #endif // report previous video norm GstTunerNorm *ntsc=gst_tuner_get_norm(tuner); g_print("Previous Norm: %s\n\n", ntsc->label); // set desired norm, once you know its "name" above probe can go away. ntsc=gst_tuner_find_norm_by_name (tuner, "NTSC"); if(ntsc) gst_tuner_set_norm (tuner, ntsc); else g_print("Can't set NTSC!\n"); g_print("Current Norm: %s\n\n", ntsc->label); #if _V4L2_PROBE_ GList *chans = (GList *) gst_tuner_list_channels(tuner); // same crap but with input sources this time for (l = chans; l != NULL; l = l->next){ GstTunerChannel *channel = GST_TUNER_CHANNEL (l->data); g_print ("Chan: %s\n", channel->label); } #endif // obviously some user interface code to select between Composite or S-Video would be nice here, NTSC television tuners are now (June 2009) defunct unless you are using an rf modulator //the Video4Linux interface will often lie to you here informing you of the chipset's possibilities, rather than what your card actually has implimented and makes available GstTunerChannel *composite=gst_tuner_find_channel_by_name(tuner, "Composite1"); if(composite) gst_tuner_set_channel(tuner, composite); else g_print("Can't select Composite1 input!\n"); /* Set the pipeline to "playing" state*/ //g_print ("Now playing: %s\n", argv[1]); g_print("Capturing from v4l2src plugin\n"); gst_element_set_state (pipeline, GST_STATE_PLAYING); /* Iterate */ g_print ("Main Loop Running...\n"); g_main_loop_run (loop); // callbacks and "signal" handlers run here /* Out of the main loop, clean up nicely */ g_print ("Returned, stopping playback\n"); gst_element_set_state (pipeline, GST_STATE_NULL); g_print ("Deleting pipeline\n"); gst_object_unref (GST_OBJECT (pipeline)); return 0; }