Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <cassert>
- #include <functional>
- #include <gst/gst.h>
- #include <gst/app/gstappsrc.h>
- #include <stdexcept>
- #include <string>
- #include <tuple>
- #include <vector>
- #include <iostream>
- using namespace std;
- using namespace std::placeholders;
- #define all(n) (n).begin(), (n).end()
- typedef struct {
- GstPipeline *pipeline;
- GstElement *src, *video_convert, *auto_video_sink;
- GMainLoop *loop;
- guint sourceid;
- FILE *file;
- }gst_app_t;
- #define WIDTH 385
- #define HEIGHT 288
- #define BITDEPTH 3
- #define BUFFER_SIZE (WIDTH*(HEIGHT)*(BITDEPTH) + (HEIGHT))
- uint8_t b_white[BUFFER_SIZE];
- uint8_t b_black[BUFFER_SIZE];
- static gboolean read_data(gst_app_t *app)
- {
- static gboolean white = FALSE;
- static GstClockTime timestamp = 0;
- GstBuffer *buffer;
- guint size;
- GstFlowReturn ret;
- size = BUFFER_SIZE;
- buffer = gst_buffer_new_wrapped_full((GstMemoryFlags) 0, (gpointer)(white?b_white:b_black), size, 0, size, NULL, NULL );
- white = !white;
- GST_BUFFER_PTS (buffer) = timestamp;
- GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale_int (1, GST_SECOND, 1);
- timestamp += GST_BUFFER_DURATION (buffer);
- ret = gst_app_src_push_buffer((GstAppSrc*) app->src, buffer);
- if (ret != GST_FLOW_OK) {
- g_warning("pushing buffer fucked up");
- g_main_loop_quit (app->loop);
- }
- return true;
- }
- static void start_feed (GstElement * pipeline, guint size, gst_app_t *app)
- {
- assert(pipeline); assert(size);
- if (app->sourceid == 0) {
- GST_DEBUG ("start feeding");
- app->sourceid = g_idle_add ((GSourceFunc) read_data, app);
- }
- }
- static void stop_feed (GstElement * pipeline, gst_app_t *app)
- {
- assert(pipeline);
- if (app->sourceid != 0) {
- GST_DEBUG ("stop feeding");
- g_source_remove (app->sourceid);
- app->sourceid = 0;
- }
- }
- static gboolean bus_callback(GstBus *bus, GstMessage *message, gpointer *ptr)
- {
- assert(bus); assert(ptr);
- gst_app_t *app = (gst_app_t*)ptr;
- switch(GST_MESSAGE_TYPE(message)){
- case GST_MESSAGE_ERROR:{
- gchar *debug;
- GError *err;
- gst_message_parse_error(message, &err, &debug);
- cerr << "Error from " << message->src << ": " << err->message << '\n'
- << "\tdebug info: " << debug << '\n';
- g_error_free(err);
- g_free(debug);
- g_main_loop_quit(app->loop);
- }
- break;
- case GST_MESSAGE_EOS:
- cerr << "End of stream, quitting main loop\n";
- g_main_loop_quit(app->loop);
- break;
- default:
- // g_print("got message %s\n",
- // gst_message_type_get_name (GST_MESSAGE_TYPE (message)));
- break;
- }
- return TRUE;
- }
- int main()
- {
- gst_app_t* app = new gst_app_t();
- GstBus *bus;
- GstStateChangeReturn state_ret;
- gst_init(nullptr, nullptr);
- app->src = gst_element_factory_make("appsrc", "appsrc");
- app->video_convert = gst_element_factory_make("videoconvert", "video_convert");
- app->auto_video_sink = gst_element_factory_make("autovideosink", "auto_video_sink");
- assert(app->src);
- assert(app->video_convert);
- assert(app->auto_video_sink);
- app->pipeline = (GstPipeline*) gst_pipeline_new("test");
- gst_bin_add_many(GST_BIN(app->pipeline), app->src, app->video_convert, app->auto_video_sink, nullptr);
- if (not gst_element_link_many(app->src, app->video_convert, app->auto_video_sink, nullptr)) {
- gst_object_unref(app->pipeline);
- delete app;
- throw runtime_error("Linking pipeline failed");
- }
- bus = gst_pipeline_get_bus(app->pipeline);
- gst_bus_add_watch(bus, (GstBusFunc)bus_callback, &app);
- gst_object_unref(bus);
- g_signal_connect(app->src, "need-data", G_CALLBACK(start_feed), app);
- g_signal_connect(app->src, "enough-data", G_CALLBACK(stop_feed), app);
- g_object_set (G_OBJECT (app->src), "caps",
- gst_caps_new_simple ("video/x-raw",
- "format", G_TYPE_STRING, "RGB",
- "width", G_TYPE_INT, WIDTH,
- "height", G_TYPE_INT, HEIGHT,
- "framerate", GST_TYPE_FRACTION, 0, 1,
- NULL), NULL);
- g_object_set (G_OBJECT (app->src),
- "stream-type", 0, // GST_APP_STREAM_TYPE_STREAM
- "format", GST_FORMAT_TIME,
- "is-live", TRUE,
- NULL);
- for (int i = 0; i < BUFFER_SIZE; i+=BITDEPTH) {
- b_black[i] = 0; b_black[i + 1] = 0; b_black[i + 2] = 0;
- b_white[i] = 0xff; b_white[i + 1] = 0xff; b_white[i + 2] = 0xff;
- }
- state_ret = gst_element_set_state((GstElement*)app->pipeline, GST_STATE_PLAYING);
- if (state_ret == GST_STATE_CHANGE_FAILURE) {
- gst_object_unref(app->pipeline);
- delete app;
- throw runtime_error("Could not change pipeline state to playing");
- }
- app->loop = g_main_loop_new(nullptr, FALSE);
- cerr << "Running main loop\n";
- g_main_loop_run(app->loop);
- state_ret = gst_element_set_state((GstElement*)app->pipeline, GST_STATE_NULL);
- gst_object_unref(app->pipeline);
- delete app;
- return 0;
- }
Add Comment
Please, Sign In to add comment