Hi, I'm having issues in pushing the data from a mat into a gstreamer
pipeline using the C++ API for gstreamer. I've successfully been able to create pipelines for receiving data from appsink so I know the gstreamer build is fine it's just the appsrc I'm having issues with. My code is as follows (OO, class based) ///////////////////////// transmitter.cpp ///////////////////////////////////////////////////////////////// #include "gst_transmitter.h" cv::Mat out_frame; static void push_data(GstAppSrc *appsrc, guint unused_size, gpointer user_data) { guint num_bytes = out_frame.total() * out_frame.elemSize(); GstBuffer* buffer; GstFlowReturn ret; GstMapInfo map; static GstClockTime timestamp = 0; buffer = gst_buffer_new_and_alloc(num_bytes); gst_buffer_fill(buffer, 0, (gpointer)(out_frame.data), num_bytes); //buffer = gst_buffer_new_wrapped_full(GST_MEMORY_FLAG_READONLY, (gpointer)(out_frame.data), num_bytes, 0, num_bytes, NULL, NULL); /*gst_buffer_map(buffer, &map, GST_MAP_WRITE); memcpy(map.data, out_frame.data, num_bytes); gst_buffer_unmap(buffer, &map);*/ GST_BUFFER_PTS(buffer) = timestamp; GST_BUFFER_DURATION(buffer) = gst_util_uint64_scale_int(1, GST_SECOND, 4); timestamp += GST_BUFFER_DURATION(buffer); //ret = gst_app_src_push_buffer(appsrc, buffer); g_signal_emit_by_name(appsrc, "push-buffer", buffer, &ret); std::cout << ret << std::endl; gst_buffer_unref(buffer); } gst_transmitter::gst_transmitter(int frame_width, int frame_height, int frame_rate, dst_types dst_type, cv::Mat frame, std::string address) :dst_frame_width{frame_width}, dst_frame_height{frame_height}, dst_address{ address }, /*out_frame{frame}, */dst_framerate_hz { frame_rate } { out_frame = frame; dst_port = 5000; num_bytes = frame.total() * frame.elemSize(); gst_init(NULL, NULL); loop = g_main_loop_new(NULL, FALSE); //buffer = gst_buffer_new_and_alloc(num_bytes); switch (dst_type) { case dst_types::H264: create_h264_pipe(); break; case dst_types::H265: create_h265_pipe(); break; default: create_h264_pipe(); break; } pipeline = gst_pipeline_new("ethernet-streamer"); source = gst_element_factory_make("appsrc", "app-source"); conv = gst_element_factory_make("videoconvert", NULL); sink = gst_element_factory_make("udpsink", NULL); GstCaps* incaps = gst_caps_new_simple("video/x-raw", "format", G_TYPE_STRING, "BGR", "width", G_TYPE_INT, dst_frame_width, "height", G_TYPE_INT, dst_frame_height, "framerate", GST_TYPE_FRACTION, dst_framerate_hz, 1, NULL); g_object_set(sink, "host", dst_address, "port", dst_port, NULL); g_object_set(source, "caps", incaps, NULL); for each (GstElement* element in pipeline_elements) { gst_bin_add(GST_BIN(pipeline), element); } gst_bin_add_many(GST_BIN(pipeline), source, conv, sink, NULL); gst_element_link(source, conv); gst_element_link(conv, pipeline_elements.front()); for (int i = 0; i < pipeline_elements.size() - 1; i++) { gst_element_link(pipeline_elements[i], pipeline_elements[i + 1]); } gst_element_link(pipeline_elements.back(), sink); g_object_set(G_OBJECT(source), "stream-type", 0, "is-live", TRUE, "format", GST_FORMAT_TIME, NULL); g_signal_connect(source, "need-data", G_CALLBACK(push_data), NULL); //std::cout << << std::endl; /* Set the pipeline to "playing" state*/ g_print("Now streaming\n"); gst_element_set_state(pipeline, GST_STATE_PLAYING); } gst_transmitter::~gst_transmitter() { /* Out of the main loop, clean up nicely */ g_print("Returned, stopping playback\n"); gst_element_set_state(pipeline, GST_STATE_NULL); g_print("Deleting pipeline\n"); gst_object_unref(GST_OBJECT(pipeline)); //g_source_remove(bus_watch_id); g_main_loop_unref(loop); } void gst_transmitter::run_gst_loop() { g_print("streaming...\n"); g_main_loop_run(loop); } void gst_transmitter::run() { std::thread t1(&gst_transmitter::run_gst_loop, this); t1.detach(); } void gst_transmitter::create_h264_pipe() { GstElement* encoder = gst_element_factory_make("x264enc", "h264-encoder"); pipeline_elements.push_back(encoder); GstElement* encfilter = gst_element_factory_make("capsfilter", NULL); pipeline_elements.push_back(encfilter); GstElement* payloader = gst_element_factory_make("rtph264pay", NULL); pipeline_elements.push_back(payloader); GstCaps* enc_caps = gst_caps_new_simple("video/x-h264", NULL); g_object_set(encfilter, "caps", enc_caps, NULL); gst_caps_unref(enc_caps); } void gst_transmitter::create_h265_pipe() { GstElement* encoder = gst_element_factory_make("x265enc", "h265-encoder"); pipeline_elements.push_back(encoder); GstElement* encfilter = gst_element_factory_make("capsfilter", NULL); pipeline_elements.push_back(encoder); GstElement* payloader = gst_element_factory_make("rtph265pay", NULL); pipeline_elements.push_back(encoder); GstCaps* enc_caps = gst_caps_new_simple("video/x-h265", NULL); g_object_set(encfilter, "caps", enc_caps, NULL); gst_caps_unref(enc_caps); } void gst_transmitter::update_last_frame(cv::Mat& frame) { out_frame = frame; //GstBuffer* buffer = gst_buffer_new_and_alloc(num_bytes); //static GstClockTime timestamp = 0; //////buffer = gst_buffer_new_and_alloc(num_bytes); ///*gst_buffer_map(buffer, &map, GST_MAP_WRITE); //memcpy(map.data, frame.data, num_bytes); //gst_buffer_unmap(buffer, &map);*/ //const auto out = gst_buffer_fill(buffer, 0, frame.data, num_bytes); //GST_BUFFER_PTS(buffer) = 15; //GST_BUFFER_DURATION(buffer) = gst_util_uint64_scale_int(1, GST_SECOND, 4); //timestamp += GST_BUFFER_DURATION(buffer); //bool ret = gst_app_src_push_buffer(GST_APP_SRC(source), buffer); //std::cout << ret << std::endl; //gst_buffer_unref(buffer); } //////////////// transmitter.h ////////////////////////////////////////////////////// #ifndef GSTTRANSMITTER_H #define GSTTRANSMITTER_H #include "gstreamer-1.0/gst/gst.h" #include "gstreamer-1.0/gst/video/video.h" #include "gstreamer-1.0/gst/app/gstappsrc.h" #include "opencv2/opencv.hpp" #include <glib.h> #include <iostream> #include <thread> #include <vector> #include <map> enum class dst_types { H264, H265 }; class gst_transmitter { public: gst_transmitter(int frame_width, int frame_height, int frame_rate, dst_types dst_type, cv::Mat frame, std::string address = ""); ~gst_transmitter(); void run_gst_loop(); void run(); void create_h264_pipe(); void create_h265_pipe(); void update_last_frame(cv::Mat& frame); guint sourceid; private: GMainLoop* loop; GstElement *pipeline, *source, *identity, *conv, *filter, *sink; std::vector<GstElement*> pipeline_elements; //std::string host; std::string dst_address; int dst_port; int dst_frame_width; int dst_frame_height; int dst_framerate_hz; int num_bytes; GstBuffer* buffer; GstFlowReturn ret; GstMapInfo map; gint num_samples; //GstClockTime timestamp; //cv::Mat out_frame; //char* out_data; }; #endif // !GSTTRANSMITTER_H /////////////////////////////////////////////////////////////// I've tried this using signals and by attempting to push buffers every time a frame is available inside my application and each time the return value of push buffer comes back as false. Is there any obvious issues with what I'm doing ? -- Sent from: http://gstreamer-devel.966125.n4.nabble.com/ _______________________________________________ gstreamer-devel mailing list [hidden email] https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel |
Free forum by Nabble | Edit this page |