From 007d876dbced166f4b4839a0ed3590ffd869ff7d Mon Sep 17 00:00:00 2001 From: brunoherbelin Date: Wed, 14 Oct 2020 22:58:02 +0200 Subject: [PATCH] Initial commit of Video Streamer. bugFix delete Pbos. --- MediaPlayer.cpp | 2 +- Recorder.cpp | 12 ++++------- Screenshot.cpp | 6 ++++-- Stream.cpp | 2 +- Streamer.cpp | 55 +++++++++++++++++++++++++++++++++++++++++++++++++ Streamer.h | 50 ++++++++++++++++++++++++++++++++++++++++++++ defines.h | 4 ++++ 7 files changed, 119 insertions(+), 12 deletions(-) create mode 100644 Streamer.cpp create mode 100644 Streamer.h diff --git a/MediaPlayer.cpp b/MediaPlayer.cpp index ce530da..c8a3df2 100644 --- a/MediaPlayer.cpp +++ b/MediaPlayer.cpp @@ -632,7 +632,7 @@ void MediaPlayer::init_texture(guint index) } else { // did not work, disable PBO - glDeleteBuffers(4, pbo_); + glDeleteBuffers(2, pbo_); pbo_[0] = pbo_[1] = 0; pbo_size_ = 0; break; diff --git a/Recorder.cpp b/Recorder.cpp index 896a737..f402562 100644 --- a/Recorder.cpp +++ b/Recorder.cpp @@ -20,12 +20,6 @@ #include "Recorder.h" -// use glReadPixel or glGetTextImage -// read pixels & pbo should be the fastest -// https://stackoverflow.com/questions/38140527/glreadpixels-vs-glgetteximage -#define USE_GLREADPIXEL - - PNGRecorder::PNGRecorder() : FrameGrabber() { std::string path = SystemToolkit::path_directory(Settings::application.record.path); @@ -102,7 +96,8 @@ void PNGRecorder::addFrame(FrameBuffer *frame_buffer, float) glUnmapBuffer(GL_PIXEL_PACK_BUFFER); // ok done - glDeleteBuffers(2, pbo_); + if (pbo_[0] > 0) + glDeleteBuffers(2, pbo_); // recorded one frame finished_ = true; @@ -207,7 +202,8 @@ VideoRecorder::~VideoRecorder() gst_object_unref (pipeline_); } - glDeleteBuffers(2, pbo_); + if (pbo_[0] > 0) + glDeleteBuffers(2, pbo_); } void VideoRecorder::addFrame (FrameBuffer *frame_buffer, float dt) diff --git a/Screenshot.cpp b/Screenshot.cpp index fbb3673..24eaa63 100644 --- a/Screenshot.cpp +++ b/Screenshot.cpp @@ -24,8 +24,10 @@ Screenshot::Screenshot() Screenshot::~Screenshot() { - glDeleteBuffers(1, &Pbo); - if (Data) free(Data); + if (Pbo > 0) + glDeleteBuffers(1, &Pbo); + if (Data) + free(Data); } bool Screenshot::isFull() diff --git a/Stream.cpp b/Stream.cpp index 55f617a..471942a 100644 --- a/Stream.cpp +++ b/Stream.cpp @@ -392,7 +392,7 @@ void Stream::init_texture(guint index) } else { // did not work, disable PBO - glDeleteBuffers(4, pbo_); + glDeleteBuffers(2, pbo_); pbo_[0] = pbo_[1] = 0; pbo_size_ = 0; break; diff --git a/Streamer.cpp b/Streamer.cpp new file mode 100644 index 0000000..d15a3f2 --- /dev/null +++ b/Streamer.cpp @@ -0,0 +1,55 @@ +#include + +// Desktop OpenGL function loader +#include + +// standalone image loader +#include +#include + +// gstreamer +#include +#include + +#include "Settings.h" +#include "GstToolkit.h" +#include "defines.h" +#include "SystemToolkit.h" +#include "FrameBuffer.h" +#include "Log.h" + +#include "Streamer.h" + + +const char* VideoStreamer::profile_name[VideoStreamer::DEFAULT] = { + "UDP (JPEG)" +}; + +const std::vector VideoStreamer::profile_description { + + "video/x-raw, format=I420,framerate=30/1 ! jpegenc ! rtpjpegpay ! udpsink host=127.0.0.1 port=500" +}; + + +VideoStreamer::VideoStreamer(): FrameGrabber(), frame_buffer_(nullptr), width_(0), height_(0), + recording_(false), accept_buffer_(false), pipeline_(nullptr), src_(nullptr), timestamp_(0) +{ + + // configure fix parameter + frame_duration_ = gst_util_uint64_scale_int (1, GST_SECOND, 30); // 30 FPS + timeframe_ = 2 * frame_duration_; +} + +VideoStreamer::~VideoStreamer() +{ + if (src_ != nullptr) + gst_object_unref (src_); + if (pipeline_ != nullptr) { + gst_element_set_state (pipeline_, GST_STATE_NULL); + gst_object_unref (pipeline_); + } + + if (pbo_[0] > 0) + glDeleteBuffers(2, pbo_); +} + diff --git a/Streamer.h b/Streamer.h new file mode 100644 index 0000000..f51d96f --- /dev/null +++ b/Streamer.h @@ -0,0 +1,50 @@ +#ifndef STREAMER_H +#define STREAMER_H + +#include + +#include +#include + +#include "FrameGrabber.h" + +class VideoStreamer : public FrameGrabber +{ + // Frame buffer information + FrameBuffer *frame_buffer_; + uint width_; + uint height_; + + // operation + std::atomic recording_; + std::atomic accept_buffer_; + + // gstreamer pipeline + GstElement *pipeline_; + GstAppSrc *src_; + GstClockTime timeframe_; + GstClockTime timestamp_; + GstClockTime frame_duration_; + + static void callback_need_data (GstAppSrc *, guint, gpointer user_data); + static void callback_enough_data (GstAppSrc *, gpointer user_data); + +public: + typedef enum { + UDP_MJPEG = 0, + DEFAULT + } Profile; + static const char* profile_name[DEFAULT]; + static const std::vector profile_description; + + VideoStreamer(); + ~VideoStreamer(); + + void addFrame(FrameBuffer *frame_buffer, float dt) override; + void stop() override; + std::string info() override; + + double duration() override; +}; + +#endif // STREAMER_H diff --git a/defines.h b/defines.h index 558419d..91ee39a 100644 --- a/defines.h +++ b/defines.h @@ -71,5 +71,9 @@ #define COLOR_SLIDER_CIRCLE 0.11f, 0.11f, 0.11f #define COLOR_STASH_CIRCLE 0.06f, 0.06f, 0.06f +// use glReadPixel or glGetTextImage +// read pixels & pbo should be the fastest +// https://stackoverflow.com/questions/38140527/glreadpixels-vs-glgetteximage +#define USE_GLREADPIXEL #endif // VMIX_DEFINES_H