Guest User

gstreamer appsrc

a guest
Jun 20th, 2021
152
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.06 KB | None | 0 0
  1. #include <cassert>
  2. #include <functional>
  3. #include <gst/gst.h>
  4. #include <gst/app/gstappsrc.h>
  5. #include <stdexcept>
  6. #include <string>
  7. #include <tuple>
  8. #include <vector>
  9. #include <iostream>
  10. using namespace std;
  11. using namespace std::placeholders;
  12.  
  13. #define all(n) (n).begin(), (n).end()
  14.  
  15. typedef struct {
  16.   GstPipeline *pipeline;
  17.   GstElement  *src, *video_convert, *auto_video_sink;
  18.   GMainLoop *loop;
  19.   guint sourceid;
  20.   FILE *file;
  21. }gst_app_t;
  22.  
  23. #define WIDTH 385
  24. #define HEIGHT 288
  25. #define BITDEPTH 3
  26. #define BUFFER_SIZE (WIDTH*(HEIGHT)*(BITDEPTH) + (HEIGHT))
  27.  
  28. uint8_t b_white[BUFFER_SIZE];
  29. uint8_t b_black[BUFFER_SIZE];
  30.  
  31. static gboolean read_data(gst_app_t *app)
  32. {
  33.     static gboolean white = FALSE;
  34.     static GstClockTime timestamp = 0;
  35.     GstBuffer *buffer;
  36.     guint size;
  37.     GstFlowReturn ret;
  38.  
  39.     size = BUFFER_SIZE;
  40.  
  41.     buffer = gst_buffer_new_wrapped_full((GstMemoryFlags) 0, (gpointer)(white?b_white:b_black), size, 0, size, NULL, NULL );
  42.  
  43.     white = !white;
  44.  
  45.     GST_BUFFER_PTS (buffer) = timestamp;
  46.     GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale_int (1, GST_SECOND, 1);
  47.  
  48.     timestamp += GST_BUFFER_DURATION (buffer);
  49.  
  50.     ret = gst_app_src_push_buffer((GstAppSrc*) app->src, buffer);
  51.  
  52.     if (ret != GST_FLOW_OK) {
  53.       g_warning("pushing buffer fucked up");
  54.        g_main_loop_quit (app->loop);
  55.     }
  56.     return true;
  57. }
  58.  
  59. static void start_feed (GstElement * pipeline, guint size, gst_app_t *app)
  60. {
  61.   assert(pipeline); assert(size);
  62.   if (app->sourceid == 0) {
  63.     GST_DEBUG ("start feeding");
  64.     app->sourceid = g_idle_add ((GSourceFunc) read_data, app);
  65.   }
  66. }
  67.  
  68. static void stop_feed (GstElement * pipeline, gst_app_t *app)
  69. {
  70.   assert(pipeline);
  71.   if (app->sourceid != 0) {
  72.     GST_DEBUG ("stop feeding");
  73.     g_source_remove (app->sourceid);
  74.     app->sourceid = 0;
  75.   }
  76. }
  77.  
  78. static gboolean bus_callback(GstBus *bus, GstMessage *message, gpointer *ptr)
  79. {
  80.   assert(bus); assert(ptr);
  81.   gst_app_t *app = (gst_app_t*)ptr;
  82.  
  83.   switch(GST_MESSAGE_TYPE(message)){
  84.  
  85.   case GST_MESSAGE_ERROR:{
  86.     gchar *debug;
  87.     GError *err;
  88.  
  89.     gst_message_parse_error(message, &err, &debug);
  90.     cerr << "Error from " << message->src << ": " << err->message << '\n'
  91.          << "\tdebug info: " << debug << '\n';
  92.     g_error_free(err);
  93.     g_free(debug);
  94.     g_main_loop_quit(app->loop);
  95.   }
  96.     break;
  97.  
  98.   case GST_MESSAGE_EOS:
  99.     cerr << "End of stream, quitting main loop\n";
  100.     g_main_loop_quit(app->loop);
  101.     break;
  102.  
  103.   default:
  104. //    g_print("got message %s\n",
  105. //            gst_message_type_get_name (GST_MESSAGE_TYPE (message)));
  106.     break;
  107.   }
  108.  
  109.   return TRUE;
  110. }
  111.  
  112. int main()
  113. {
  114.   gst_app_t* app = new gst_app_t();
  115.   GstBus *bus;
  116.   GstStateChangeReturn state_ret;
  117.  
  118.   gst_init(nullptr, nullptr);
  119.  
  120.   app->src = gst_element_factory_make("appsrc", "appsrc");
  121.   app->video_convert = gst_element_factory_make("videoconvert", "video_convert");
  122.   app->auto_video_sink = gst_element_factory_make("autovideosink", "auto_video_sink");
  123.  
  124.   assert(app->src);
  125.   assert(app->video_convert);
  126.   assert(app->auto_video_sink);
  127.  
  128.   app->pipeline = (GstPipeline*) gst_pipeline_new("test");
  129.  
  130.   gst_bin_add_many(GST_BIN(app->pipeline), app->src, app->video_convert, app->auto_video_sink, nullptr);
  131.  
  132.   if (not gst_element_link_many(app->src, app->video_convert, app->auto_video_sink, nullptr)) {
  133.     gst_object_unref(app->pipeline);
  134.     delete app;
  135.     throw runtime_error("Linking pipeline failed");
  136.   }
  137.  
  138.   bus = gst_pipeline_get_bus(app->pipeline);
  139.   gst_bus_add_watch(bus, (GstBusFunc)bus_callback, &app);
  140.   gst_object_unref(bus);
  141.  
  142.   g_signal_connect(app->src, "need-data", G_CALLBACK(start_feed), app);
  143.   g_signal_connect(app->src, "enough-data", G_CALLBACK(stop_feed), app);
  144.  
  145.   g_object_set (G_OBJECT (app->src), "caps",
  146.                 gst_caps_new_simple ("video/x-raw",
  147.                                      "format", G_TYPE_STRING, "RGB",
  148.                                      "width", G_TYPE_INT, WIDTH,
  149.                                      "height", G_TYPE_INT, HEIGHT,
  150.                                      "framerate", GST_TYPE_FRACTION, 0, 1,
  151.                                      NULL), NULL);
  152.  
  153.   g_object_set (G_OBJECT (app->src),
  154.                 "stream-type", 0, // GST_APP_STREAM_TYPE_STREAM
  155.                 "format", GST_FORMAT_TIME,
  156.                 "is-live", TRUE,
  157.                 NULL);
  158.  
  159.   for (int i = 0; i < BUFFER_SIZE; i+=BITDEPTH) {
  160.     b_black[i] = 0; b_black[i + 1] = 0; b_black[i + 2] = 0;
  161.     b_white[i] = 0xff; b_white[i + 1] = 0xff; b_white[i + 2] = 0xff;
  162.   }
  163.  
  164.   state_ret = gst_element_set_state((GstElement*)app->pipeline, GST_STATE_PLAYING);
  165.   if (state_ret == GST_STATE_CHANGE_FAILURE) {
  166.     gst_object_unref(app->pipeline);
  167.     delete app;
  168.     throw runtime_error("Could not change pipeline state to playing");
  169.   }
  170.  
  171.   app->loop = g_main_loop_new(nullptr, FALSE);
  172.   cerr << "Running main loop\n";
  173.   g_main_loop_run(app->loop);
  174.  
  175.   state_ret = gst_element_set_state((GstElement*)app->pipeline, GST_STATE_NULL);
  176.  
  177.   gst_object_unref(app->pipeline);
  178.   delete app;
  179.  
  180.   return 0;
  181. }
  182.  
Add Comment
Please, Sign In to add comment