#include #include #include #include /* these are the caps we are going to pass through the appsrc */ const gchar *video_caps = "video/x-raw-rgb,width=80,height=60,bpp=32,endianness=4321,depth=24,red_mask=65280,green_mask=16711680,blue_mask=-16777216,framerate=30/1"; typedef struct { GMainLoop *loop; GstElement *sink; } ProgramData; /* used to inject a new buffer into the pipeline */ static void inject_new_buffer_into_pipeline (ProgramData * data) { guint size; gpointer raw_buffer; GstBuffer *app_buffer; GstElement *source; size = 80 * 60 * 4; // 80x60 pixels, 32 bpp. g_print ("Pushing a buffer of size %d\n", size); // Allocating the memory for the buffer. raw_buffer = g_malloc0 (size); app_buffer = gst_app_buffer_new (raw_buffer, size, g_free, raw_buffer); /* newer basesrc will set caps for use automatically but it does not really * hurt to set it on the buffer again */ gst_buffer_set_caps (app_buffer, gst_caps_from_string (video_caps)); /* get source an push new buffer */ source = gst_bin_get_by_name (GST_BIN (data->sink), "testsource"); gst_app_src_push_buffer (GST_APP_SRC (source), app_buffer); } /* called when we get a GstMessage from the sink pipeline when we get EOS, we * exit the mainloop and this testapp. */ static gboolean on_sink_message (GstBus * bus, GstMessage * message, ProgramData * data) { GstState state, pending; GstElement *source; switch (GST_MESSAGE_TYPE (message)) { case GST_MESSAGE_EOS: g_print ("Received End of Stream message\n"); g_main_loop_quit (data->loop); break; case GST_MESSAGE_ERROR: g_print ("Received error\n"); g_main_loop_quit (data->loop); break; case GST_MESSAGE_STATE_CHANGED: source = gst_bin_get_by_name (GST_BIN (data->sink), "testsource"); gst_element_get_state(source, &state, &pending, GST_CLOCK_TIME_NONE); g_print ("State changed from %i to %i\n", state, pending); break; default: break; } return TRUE; } int main (int argc, char *argv[]) { ProgramData *data = NULL; gchar *string = NULL; GstBus *bus = NULL; GstElement *testsource = NULL; int i; gst_init (&argc, &argv); data = g_new0 (ProgramData, 1); data->loop = g_main_loop_new (NULL, FALSE); /* setting up sink pipeline, we push video data into this pipeline that will * then be recorded to an avi file. */ string = g_strdup_printf ("appsrc is-live=true name=testsource caps=\"%s\" ! ffmpegcolorspace ! video/x-raw-yuv,format=(fourcc)I420,width=80,height=60 ! queue ! videorate ! video/x-raw-yuv,framerate=30/1 ! xvidenc ! queue ! avimux ! queue ! filesink location=test.avi", video_caps); data->sink = gst_parse_launch (string, NULL); g_free (string); if (data->sink == NULL) { g_print ("Bad sink\n"); return -1; } testsource = gst_bin_get_by_name (GST_BIN (data->sink), "testsource"); /* configure for time-based format */ g_object_set (testsource, "format", GST_FORMAT_TIME, NULL); /* uncomment the next line to block when appsrc has buffered enough */ /* g_object_set (testsource, "block", TRUE, NULL); */ bus = gst_element_get_bus (data->sink); gst_bus_add_watch (bus, (GstBusFunc) on_sink_message, data); gst_object_unref (bus); /* launching things */ gst_element_set_state (data->sink, GST_STATE_PLAYING); /* Injecting 300 frames into the pipeline, which should generate a 1 second * avi file with the current framerate. */ g_print ("Injecting buffers...\n"); for (i = 0; i < 30; i++) inject_new_buffer_into_pipeline(data); gst_app_src_end_of_stream (GST_APP_SRC (testsource)); g_print ("Done.\n"); gst_element_set_state (data->sink, GST_STATE_PLAYING); g_print ("Creating movie...\n"); g_main_loop_run (data->loop); g_print ("Done.\n"); gst_element_set_state (data->sink, GST_STATE_NULL); gst_object_unref (testsource); gst_object_unref (data->sink); g_main_loop_unref (data->loop); g_free (data); return 0; }