Guest User

Untitled

a guest
Nov 4th, 2020
347
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.85 KB | None | 0 0
  1. // Code adapted from https://gist.github.com/nzjrs/725122/16ceee88aafae389bab207818e0661328921e1ab
  2.  
  3. #include <gst/gst.h>
  4. #include <gst/app/gstappsrc.h>
  5.  
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <stdlib.h>
  9.  
  10. #include <raspicam/raspicam_cv.h>
  11.  
  12. #include "iostream"
  13.  
  14. #include "opencv2/opencv.hpp"
  15.  
  16. typedef struct _App App;
  17.  
  18. struct _App {
  19.     GstElement *pipeline;
  20.     GstElement *appsrc;
  21.  
  22.     GMainLoop *loop;
  23.     guint sourceid;
  24.  
  25.     GTimer *timer;
  26.  
  27. };
  28.  
  29. App s_app;
  30. static GstClockTime timestamp = 0;
  31.  
  32. raspicam::RaspiCam_Cv camera;
  33.  
  34. static void deleteFrame(void *frame) {
  35.     free(frame);
  36. }
  37.  
  38. static gboolean read_data(App *app) {
  39.     GstFlowReturn ret;
  40.  
  41.     if (timestamp < GST_SECOND * 10) {
  42.         auto *frame = new cv::Mat();
  43.         camera.grab();
  44.         camera.retrieve(*frame);
  45.         cv::resize(*frame, *frame, cv::Size(640, 480));
  46.  
  47.         GstBuffer *buffer;
  48.         gboolean ok = TRUE;
  49.  
  50.         gsize size = frame->total() * frame->elemSize();
  51.         buffer = gst_buffer_new_wrapped_full((GstMemoryFlags) 0, (gpointer) frame->data, size, 0, size, frame,
  52.                                              deleteFrame);
  53.  
  54.         GST_BUFFER_PTS (buffer) = timestamp;
  55.         GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale_int(1, GST_SECOND, 20);
  56.  
  57.         timestamp += GST_BUFFER_DURATION (buffer);
  58.  
  59.         std::cout << "Feeding next buffer" << std::endl;
  60.         g_signal_emit_by_name(app->appsrc, "push-buffer", buffer, &ret);
  61.         gst_buffer_unref(buffer);
  62.  
  63.         if (ret != GST_FLOW_OK) {
  64.             /* some error, stop sending data */
  65.             std::cout << "Error" << std::endl;
  66.             ok = FALSE;
  67.         }
  68.  
  69.         g_timer_start(app->timer);
  70.  
  71.         return ok;
  72.     } else {
  73.         g_signal_emit_by_name(app->appsrc, "end-of-stream", &ret);
  74.     }
  75.     return FALSE;
  76. }
  77.  
  78. static void start_feed(GstElement *pipeline, guint size, App *app) {
  79.     if (app->sourceid == 0) {
  80.         std::cout << "Start feeding" << std::endl;
  81.         app->sourceid = g_idle_add((GSourceFunc) read_data, app);
  82.     }
  83. }
  84.  
  85. static void stop_feed(GstElement *pipeline, App *app) {
  86.     if (app->sourceid != 0) {
  87.         std::cout << "Stop feeding" << std::endl;
  88.         g_source_remove(app->sourceid);
  89.         app->sourceid = 0;
  90.     }
  91. }
  92.  
  93. static gboolean bus_message(GstBus *bus, GstMessage *message, App *app) {
  94.     std::cout << ("got message %s",
  95.             gst_message_type_get_name(GST_MESSAGE_TYPE (message))) << std::endl;
  96.  
  97.     switch (GST_MESSAGE_TYPE (message)) {
  98.         case GST_MESSAGE_ERROR: {
  99.             GError *err = nullptr;
  100.             gchar *dbg_info = nullptr;
  101.  
  102.             gst_message_parse_error(message, &err, &dbg_info);
  103.             g_printerr("ERROR from element %s: %s\n", GST_OBJECT_NAME (message->src), err->message);
  104.             g_printerr("Debugging info: %s\n", (dbg_info) ? dbg_info : "none");
  105.             g_error_free(err);
  106.             g_free(dbg_info);
  107.             g_main_loop_quit(app->loop);
  108.             break;
  109.         }
  110.         case GST_MESSAGE_EOS:
  111.             g_main_loop_quit(app->loop);
  112.             break;
  113.         default:
  114.             break;
  115.     }
  116.     return TRUE;
  117. }
  118.  
  119. int
  120. main(int argc, char *argv[]) {
  121.     App *app = &s_app;
  122.     GstBus *bus;
  123.     GstCaps *caps;
  124.  
  125.     if (!camera.open()) {
  126.         std::cerr << "Error opening the camera" << std::endl;
  127.         return 1;
  128.     }
  129.     camera.set(cv::CAP_PROP_FPS, 20);
  130.  
  131.     gst_init(&argc, &argv);
  132.  
  133.     /* create a mainloop to get messages and to handle the idle handler that will
  134.      * feed data to appsrc. */
  135.     app->loop = g_main_loop_new(nullptr, TRUE);
  136.     app->timer = g_timer_new();
  137.  
  138.     app->pipeline = gst_parse_launch(
  139.             "appsrc name=src format=time is-live=true caps=video/x-raw,format=(string)RGB,width=640,height=480,bpp=24,depth=24,framerate=20/1"
  140.             " ! autovideoconvert ! queue ! omxh264enc ! mp4mux ! filesink location=output.mp4",
  141.             nullptr);
  142.     g_assert (app->pipeline);
  143.  
  144.     bus = gst_pipeline_get_bus(GST_PIPELINE (app->pipeline));
  145.     g_assert(bus);
  146.  
  147.     /* add watch for messages */
  148.     gst_bus_add_watch(bus, (GstBusFunc) bus_message, app);
  149.  
  150.     /* get the appsrc */
  151.     app->appsrc = gst_bin_get_by_name(GST_BIN(app->pipeline), "src");
  152.     g_assert(app->appsrc);
  153.     g_assert(GST_IS_APP_SRC(app->appsrc));
  154.     g_signal_connect (app->appsrc, "need-data", G_CALLBACK(start_feed), app);
  155.     g_signal_connect (app->appsrc, "enough-data", G_CALLBACK(stop_feed), app);
  156.  
  157.     /* go to playing and wait in a mainloop. */
  158.     gst_element_set_state(app->pipeline, GST_STATE_PLAYING);
  159.  
  160.     /* this mainloop is stopped when we receive an error or EOS */
  161.     g_main_loop_run(app->loop);
  162.  
  163.     std::cout << "Stopping" << std::endl;
  164.  
  165.     gst_element_set_state(app->pipeline, GST_STATE_NULL);
  166.  
  167.     gst_object_unref(bus);
  168.     g_main_loop_unref(app->loop);
  169.  
  170.     return 0;
  171. }
Add Comment
Please, Sign In to add comment