#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,depth=24,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 * 8; // 80x60 pixels, 32 bpp. g_print ("Pushing a buffer of size %d\n", size); // Allocating the memory for the frame 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) { /* nil */ switch (GST_MESSAGE_TYPE (message)) { case GST_MESSAGE_EOS: g_print ("Finished playback\n"); g_main_loop_quit (data->loop); break; case GST_MESSAGE_ERROR: g_print ("Received error\n"); g_main_loop_quit (data->loop); break; default: break; } return TRUE; } int main (int argc, char *argv[]) { ProgramData *data = NULL; gchar *string = NULL; GstBus *bus = NULL; GstElement *testsink = 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 name=testsource caps=\"%s\" ! ffmpegcolorspace ! video/x-raw-yuv, width=80, height=60, bpp=32, depth=24 ! 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); */ gst_object_unref (testsource); 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); g_print ("Let's run!\n"); /* Injecting 300 frames into the pipeline, which should generate a 10 seconds * avi file. */ for (i = 0; i < 300; i++) inject_new_buffer_into_pipeline(data); g_print ("Going out\n"); gst_element_set_state (data->sink, GST_STATE_NULL); gst_object_unref (data->sink); g_main_loop_unref (data->loop); g_free (data); return 0; }