Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Code adapted from https://gist.github.com/nzjrs/725122/16ceee88aafae389bab207818e0661328921e1ab
- #include <gst/gst.h>
- #include <gst/app/gstappsrc.h>
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <raspicam/raspicam_cv.h>
- #include "iostream"
- #include "opencv2/opencv.hpp"
- typedef struct _App App;
- struct _App {
- GstElement *pipeline;
- GstElement *appsrc;
- GMainLoop *loop;
- guint sourceid;
- GTimer *timer;
- };
- App s_app;
- static GstClockTime timestamp = 0;
- raspicam::RaspiCam_Cv camera;
- static void deleteFrame(void *frame) {
- free(frame);
- }
- static gboolean read_data(App *app) {
- GstFlowReturn ret;
- if (timestamp < GST_SECOND * 10) {
- auto *frame = new cv::Mat();
- camera.grab();
- camera.retrieve(*frame);
- cv::resize(*frame, *frame, cv::Size(640, 480));
- GstBuffer *buffer;
- gboolean ok = TRUE;
- gsize size = frame->total() * frame->elemSize();
- buffer = gst_buffer_new_wrapped_full((GstMemoryFlags) 0, (gpointer) frame->data, size, 0, size, frame,
- deleteFrame);
- GST_BUFFER_PTS (buffer) = timestamp;
- GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale_int(1, GST_SECOND, 20);
- timestamp += GST_BUFFER_DURATION (buffer);
- std::cout << "Feeding next buffer" << std::endl;
- g_signal_emit_by_name(app->appsrc, "push-buffer", buffer, &ret);
- gst_buffer_unref(buffer);
- if (ret != GST_FLOW_OK) {
- /* some error, stop sending data */
- std::cout << "Error" << std::endl;
- ok = FALSE;
- }
- g_timer_start(app->timer);
- return ok;
- } else {
- g_signal_emit_by_name(app->appsrc, "end-of-stream", &ret);
- }
- return FALSE;
- }
- static void start_feed(GstElement *pipeline, guint size, App *app) {
- if (app->sourceid == 0) {
- std::cout << "Start feeding" << std::endl;
- app->sourceid = g_idle_add((GSourceFunc) read_data, app);
- }
- }
- static void stop_feed(GstElement *pipeline, App *app) {
- if (app->sourceid != 0) {
- std::cout << "Stop feeding" << std::endl;
- g_source_remove(app->sourceid);
- app->sourceid = 0;
- }
- }
- static gboolean bus_message(GstBus *bus, GstMessage *message, App *app) {
- std::cout << ("got message %s",
- gst_message_type_get_name(GST_MESSAGE_TYPE (message))) << std::endl;
- switch (GST_MESSAGE_TYPE (message)) {
- case GST_MESSAGE_ERROR: {
- GError *err = nullptr;
- gchar *dbg_info = nullptr;
- gst_message_parse_error(message, &err, &dbg_info);
- g_printerr("ERROR from element %s: %s\n", GST_OBJECT_NAME (message->src), err->message);
- g_printerr("Debugging info: %s\n", (dbg_info) ? dbg_info : "none");
- g_error_free(err);
- g_free(dbg_info);
- g_main_loop_quit(app->loop);
- break;
- }
- case GST_MESSAGE_EOS:
- g_main_loop_quit(app->loop);
- break;
- default:
- break;
- }
- return TRUE;
- }
- int
- main(int argc, char *argv[]) {
- App *app = &s_app;
- GstBus *bus;
- GstCaps *caps;
- if (!camera.open()) {
- std::cerr << "Error opening the camera" << std::endl;
- return 1;
- }
- camera.set(cv::CAP_PROP_FPS, 20);
- gst_init(&argc, &argv);
- /* create a mainloop to get messages and to handle the idle handler that will
- * feed data to appsrc. */
- app->loop = g_main_loop_new(nullptr, TRUE);
- app->timer = g_timer_new();
- app->pipeline = gst_parse_launch(
- "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"
- " ! autovideoconvert ! queue ! omxh264enc ! mp4mux ! filesink location=output.mp4",
- nullptr);
- g_assert (app->pipeline);
- bus = gst_pipeline_get_bus(GST_PIPELINE (app->pipeline));
- g_assert(bus);
- /* add watch for messages */
- gst_bus_add_watch(bus, (GstBusFunc) bus_message, app);
- /* get the appsrc */
- app->appsrc = gst_bin_get_by_name(GST_BIN(app->pipeline), "src");
- g_assert(app->appsrc);
- g_assert(GST_IS_APP_SRC(app->appsrc));
- g_signal_connect (app->appsrc, "need-data", G_CALLBACK(start_feed), app);
- g_signal_connect (app->appsrc, "enough-data", G_CALLBACK(stop_feed), app);
- /* go to playing and wait in a mainloop. */
- gst_element_set_state(app->pipeline, GST_STATE_PLAYING);
- /* this mainloop is stopped when we receive an error or EOS */
- g_main_loop_run(app->loop);
- std::cout << "Stopping" << std::endl;
- gst_element_set_state(app->pipeline, GST_STATE_NULL);
- gst_object_unref(bus);
- g_main_loop_unref(app->loop);
- return 0;
- }
Add Comment
Please, Sign In to add comment