iamthesgt 0 Junior Poster

I am making a video recording program that takes input from a v4l2 webcam and outputs to an avi file. Using gstreamer in c, I have got most of the program to work, and the file is created. I can get the pipeline to display the video to the screen, but I can't get the video file to record anything. It compiles, but I get some run-time errors that allow the program to keep running. If anyone could help, that would be great.
The program is compiled by the following (on a Linux box): gcc -Wall $(pkg-config --cflags --libs gstreamer-0.10) videorecord.c -o recorder
And run by ./recorder testvid.avi


Errors:

(gst-plugin-scanner:3501): GLib-GObject-WARNING **: specified instance size for type `GstRTPBVPay' is smaller than the parent type's `GstBaseRTPAudioPayload' instance size

(gst-plugin-scanner:3501): GLib-CRITICAL **: g_once_init_leave: assertion `initialization_value != 0' failed

(gst-plugin-scanner:3501): GStreamer-CRITICAL **: gst_element_register: assertion `g_type_is_a (type, GST_TYPE_ELEMENT)' failed

(gst-plugin-scanner:3501): GStreamer-CRITICAL **: Could not convert static caps "image/png, width = (int) [ 16, 4096 ], height = (int) [ 16, 4096 ], framerate = (fraction) [ 0.0, MAX ]"
This program is linked against GStreamer 0.10.34 

(recorder:3500): GStreamer-CRITICAL **: gst_pad_link_full: assertion `GST_IS_PAD (sinkpad)' failed

(recorder:3500): GStreamer-CRITICAL **: gst_ghost_pad_new: assertion `GST_IS_PAD (target)' failed

(recorder:3500): GStreamer-CRITICAL **: gst_element_add_pad: assertion `GST_IS_PAD (pad)' failed

(recorder:3500): GStreamer-CRITICAL **: gst_pad_set_caps: assertion `GST_IS_PAD (pad)' failed

(recorder:3500): GStreamer-CRITICAL **: gst_pad_link_full: assertion `GST_IS_PAD (srcpad)' failed

(recorder:3500): GStreamer-CRITICAL **: gst_ghost_pad_new: assertion `GST_IS_PAD (target)' failed

(recorder:3500): GStreamer-CRITICAL **: gst_element_add_pad: assertion `GST_IS_PAD (pad)' failed

(recorder:3500): GStreamer-CRITICAL **: gst_pad_link_full: assertion `GST_IS_PAD (srcpad)' failed

(recorder:3500): GStreamer-CRITICAL **: gst_ghost_pad_new: assertion `GST_IS_PAD (target)' failed

(recorder:3500): GStreamer-CRITICAL **: gst_element_add_pad: assertion `GST_IS_PAD (pad)' failed

Code (videorecord.c):

#include <gst/gst.h>
#include <glib.h>


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;
}

static void
on_pad_added (GstElement *element,
              GstPad     *pad,
              gpointer    data)
{
  GstPad *sinkpad;
  GstElement *source1 = (GstElement *) data;

  g_print ("Dynamic pad created, linking ...\n");

  sinkpad = gst_element_get_static_pad (source1, "output1");

  gst_pad_link (pad, sinkpad);

  gst_object_unref (sinkpad);
}



int main (int argc, char *argv[])
{
	guint major, minor, micro, nano;
	gst_init (&argc, &argv);
	gst_version (&major, &minor, &micro, &nano);

	printf ("This program is linked against GStreamer %d.%d.%d \n",
major, minor, micro);
	
	GMainLoop *loop;

	GstElement *pipeline;
	GstElement *source1, *encoder1, *muxer, *output2;
	GstBus *bus;
	
	loop = g_main_loop_new (NULL, FALSE);

	pipeline = gst_pipeline_new ("video-pipeline");
	source1 = gst_element_factory_make("v4l2src", "video-source"); //video input from webcam
	encoder1 = gst_element_factory_make("x264enc", "video-encoder"); //video encoder for input
	muxer = gst_element_factory_make("avimux", "combining-muxer"); //muxer for A/V streams
	output2 = gst_element_factory_make("filesink", "file-output"); //combo output to file

	if(!source1 | !encoder1 | !muxer | !output2)
	{	printf ("One element could not be created. Exiting.\n");
	return -1;	}

	g_object_set (G_OBJECT (output2), "location", argv[1], NULL); //set the ouput filename to the sink element

	GstCaps *caps1;
	caps1 = gst_caps_new_simple ("video/x-h264", "stream-format", G_TYPE_STRING, "byte-stream", "alignment", G_TYPE_STRING, "au", "width", G_TYPE_INT, 320, "height", G_TYPE_INT, 240, NULL);

	bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
	gst_bus_add_watch (bus, bus_call, loop);
	gst_object_unref (bus);

	GstPad *sinkpadvideo, *srcpadvideo;
	srcpadvideo = gst_element_get_static_pad(source1, "src");
	sinkpadvideo = gst_element_get_request_pad(encoder1, "e264");
	gst_pad_link(srcpadvideo, sinkpadvideo);

	gst_element_link(source1, encoder1); //linking v4l2src to x264enc
	gst_element_add_pad(pipeline, gst_ghost_pad_new("ghst-pad-enc", sinkpadvideo));
	
	g_signal_connect(source1, "pad-added", G_CALLBACK(on_pad_added), encoder1);

	srcpadvideo = gst_element_get_static_pad(encoder1, "e264");
	sinkpadvideo = gst_element_get_request_pad(muxer, "mux");
	gst_pad_set_caps(sinkpadvideo, caps1); //set caps to avimux
	gst_pad_link(srcpadvideo, sinkpadvideo);
	gst_element_link(encoder1, muxer); //linking x264enc to avimux
	gst_element_add_pad(pipeline, gst_ghost_pad_new("ghst-pad-mux", sinkpadvideo));

	g_signal_connect(encoder1, "pad-added", G_CALLBACK(on_pad_added), muxer);

	srcpadvideo = gst_element_get_static_pad(muxer, "mux");
	sinkpadvideo = gst_element_get_request_pad(output2, "sink");
	gst_pad_link(srcpadvideo, sinkpadvideo);
	gst_element_link(muxer, output2); //linking avimux to filesink
	gst_element_add_pad(pipeline, gst_ghost_pad_new("ghst-pad-rec", sinkpadvideo));

	g_signal_connect(muxer, "pad-added", G_CALLBACK(on_pad_added), output2);

	gst_element_set_state(pipeline, GST_STATE_NULL);

	gst_bin_add_many (GST_BIN (pipeline), source1, encoder1, muxer, output2, NULL);
	gst_element_link_many (source1, encoder1, muxer, output2, NULL);
	gst_element_link(source1, output2);
	
	g_signal_connect (source1, "pad-added", G_CALLBACK (on_pad_added), output2);

	g_print ("Now recording to file: %s\n", argv[1]);
  	gst_element_set_state (pipeline, GST_STATE_PLAYING);
	g_main_loop_run (loop);
	g_print ("Ending recording\n");
	gst_element_set_state (pipeline, GST_STATE_NULL);
	g_print ("Cleaning...\n");
	gst_object_unref (GST_OBJECT (pipeline));
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.