mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-12 02:40:00 +01:00
Frame grabber threaded initialization
Start gstreamer init of frame grabber in a thread and wait future return from initializer before switching to active recording mode.
This commit is contained in:
@@ -271,8 +271,8 @@ void FrameGrabbing::grabFrame(FrameBuffer *frame_buffer)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
FrameGrabber::FrameGrabber(): finished_(false), active_(false), endofstream_(false), accept_buffer_(false), buffering_full_(false),
|
FrameGrabber::FrameGrabber(): finished_(false), initialized_(false), active_(false), endofstream_(false), accept_buffer_(false), buffering_full_(false),
|
||||||
pipeline_(nullptr), src_(nullptr), caps_(nullptr), timer_(nullptr),
|
pipeline_(nullptr), src_(nullptr), caps_(nullptr), timer_(nullptr), timer_firstframe_(0),
|
||||||
timestamp_(0), duration_(0), frame_count_(0), buffering_size_(MIN_BUFFER_SIZE), timestamp_on_clock_(false)
|
timestamp_(0), duration_(0), frame_count_(0), buffering_size_(MIN_BUFFER_SIZE), timestamp_on_clock_(false)
|
||||||
{
|
{
|
||||||
// unique id
|
// unique id
|
||||||
@@ -315,6 +315,8 @@ uint64_t FrameGrabber::duration() const
|
|||||||
|
|
||||||
void FrameGrabber::stop ()
|
void FrameGrabber::stop ()
|
||||||
{
|
{
|
||||||
|
// TODO if not initialized wait for initializer
|
||||||
|
|
||||||
// stop recording
|
// stop recording
|
||||||
active_ = false;
|
active_ = false;
|
||||||
|
|
||||||
@@ -324,6 +326,8 @@ void FrameGrabber::stop ()
|
|||||||
|
|
||||||
std::string FrameGrabber::info() const
|
std::string FrameGrabber::info() const
|
||||||
{
|
{
|
||||||
|
if (!initialized_)
|
||||||
|
return "Initializing";
|
||||||
if (active_)
|
if (active_)
|
||||||
return GstToolkit::time_to_string(duration_);
|
return GstToolkit::time_to_string(duration_);
|
||||||
else
|
else
|
||||||
@@ -363,6 +367,12 @@ GstPadProbeReturn FrameGrabber::callback_event_probe(GstPad *, GstPadProbeInfo *
|
|||||||
return GST_PAD_PROBE_OK;
|
return GST_PAD_PROBE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string FrameGrabber::initialize(FrameGrabber *rec, GstCaps *caps)
|
||||||
|
{
|
||||||
|
return rec->init(caps);
|
||||||
|
}
|
||||||
|
|
||||||
void FrameGrabber::addFrame (GstBuffer *buffer, GstCaps *caps)
|
void FrameGrabber::addFrame (GstBuffer *buffer, GstCaps *caps)
|
||||||
{
|
{
|
||||||
// ignore
|
// ignore
|
||||||
@@ -371,15 +381,37 @@ void FrameGrabber::addFrame (GstBuffer *buffer, GstCaps *caps)
|
|||||||
|
|
||||||
// first time initialization
|
// first time initialization
|
||||||
if (pipeline_ == nullptr) {
|
if (pipeline_ == nullptr) {
|
||||||
// type specific initialisation
|
initializer_ = std::async( FrameGrabber::initialize, this, caps);
|
||||||
init(caps);
|
}
|
||||||
|
|
||||||
|
// initializer ongoing in separate thread
|
||||||
|
if (initializer_.valid()) {
|
||||||
|
// try to get info from initializer
|
||||||
|
if (initializer_.wait_for( std::chrono::milliseconds(4) ) == std::future_status::ready )
|
||||||
|
{
|
||||||
|
// done initialization
|
||||||
|
std::string msg = initializer_.get();
|
||||||
|
|
||||||
|
// if initialization succeeded
|
||||||
|
if (initialized_) {
|
||||||
// attach EOS detector
|
// attach EOS detector
|
||||||
GstPad *pad = gst_element_get_static_pad (gst_bin_get_by_name (GST_BIN (pipeline_), "sink"), "sink");
|
GstPad *pad = gst_element_get_static_pad (gst_bin_get_by_name (GST_BIN (pipeline_), "sink"), "sink");
|
||||||
gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, FrameGrabber::callback_event_probe, this, NULL);
|
gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, FrameGrabber::callback_event_probe, this, NULL);
|
||||||
gst_object_unref (pad);
|
gst_object_unref (pad);
|
||||||
|
// start recording
|
||||||
|
active_ = true;
|
||||||
|
// inform
|
||||||
|
Log::Info("%s", msg.c_str());
|
||||||
}
|
}
|
||||||
// stop if an incompatilble frame buffer given
|
// else show warning
|
||||||
else if ( !gst_caps_is_subset( caps_, caps ))
|
else {
|
||||||
|
Log::Warning("%s", msg.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// stop if an incompatilble frame buffer given after initialization
|
||||||
|
if (initialized_ && !gst_caps_is_subset( caps_, caps ))
|
||||||
{
|
{
|
||||||
stop();
|
stop();
|
||||||
Log::Warning("Frame capture interrupted because the resolution changed.");
|
Log::Warning("Frame capture interrupted because the resolution changed.");
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#define FRAMEGRABBER_H
|
#define FRAMEGRABBER_H
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <future>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -52,11 +53,12 @@ protected:
|
|||||||
virtual void addFrame(GstBuffer *buffer, GstCaps *caps);
|
virtual void addFrame(GstBuffer *buffer, GstCaps *caps);
|
||||||
|
|
||||||
// only addFrame method shall call those
|
// only addFrame method shall call those
|
||||||
virtual void init(GstCaps *caps) = 0;
|
virtual std::string init(GstCaps *caps) = 0;
|
||||||
virtual void terminate() = 0;
|
virtual void terminate() = 0;
|
||||||
|
|
||||||
// thread-safe testing termination
|
// thread-safe testing termination
|
||||||
std::atomic<bool> finished_;
|
std::atomic<bool> finished_;
|
||||||
|
std::atomic<bool> initialized_;
|
||||||
std::atomic<bool> active_;
|
std::atomic<bool> active_;
|
||||||
std::atomic<bool> endofstream_;
|
std::atomic<bool> endofstream_;
|
||||||
std::atomic<bool> accept_buffer_;
|
std::atomic<bool> accept_buffer_;
|
||||||
@@ -68,6 +70,7 @@ protected:
|
|||||||
GstCaps *caps_;
|
GstCaps *caps_;
|
||||||
|
|
||||||
GstClock *timer_;
|
GstClock *timer_;
|
||||||
|
GstClockTime timer_firstframe_;
|
||||||
GstClockTime timestamp_;
|
GstClockTime timestamp_;
|
||||||
GstClockTime duration_;
|
GstClockTime duration_;
|
||||||
GstClockTime frame_duration_;
|
GstClockTime frame_duration_;
|
||||||
@@ -75,7 +78,10 @@ protected:
|
|||||||
guint64 buffering_size_;
|
guint64 buffering_size_;
|
||||||
bool timestamp_on_clock_;
|
bool timestamp_on_clock_;
|
||||||
|
|
||||||
GstClockTime timer_firstframe_;
|
|
||||||
|
// async threaded initializer
|
||||||
|
std::future<std::string> initializer_;
|
||||||
|
static std::string initialize(FrameGrabber *rec, GstCaps *caps);
|
||||||
|
|
||||||
// gstreamer callbacks
|
// gstreamer callbacks
|
||||||
static void callback_need_data (GstAppSrc *, guint, gpointer user_data);
|
static void callback_need_data (GstAppSrc *, guint, gpointer user_data);
|
||||||
|
|||||||
27
Loopback.cpp
27
Loopback.cpp
@@ -171,16 +171,15 @@ Loopback::Loopback() : FrameGrabber()
|
|||||||
frame_duration_ = gst_util_uint64_scale_int (1, GST_SECOND, 30); // fixed 30 FPS
|
frame_duration_ = gst_util_uint64_scale_int (1, GST_SECOND, 30); // fixed 30 FPS
|
||||||
}
|
}
|
||||||
|
|
||||||
void Loopback::init(GstCaps *caps)
|
std::string Loopback::init(GstCaps *caps)
|
||||||
{
|
{
|
||||||
// ignore
|
// ignore
|
||||||
if (caps == nullptr)
|
if (caps == nullptr)
|
||||||
return;
|
return std::string("Invalid caps");
|
||||||
|
|
||||||
if (!Loopback::systemLoopbackInitialized()){
|
if (!Loopback::systemLoopbackInitialized()){
|
||||||
Log::Warning("Loopback system shall be initialized first.");
|
|
||||||
finished_ = true;
|
finished_ = true;
|
||||||
return;
|
return std::string("Loopback system shall be initialized first.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a gstreamer pipeline
|
// create a gstreamer pipeline
|
||||||
@@ -190,10 +189,10 @@ void Loopback::init(GstCaps *caps)
|
|||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
pipeline_ = gst_parse_launch (description.c_str(), &error);
|
pipeline_ = gst_parse_launch (description.c_str(), &error);
|
||||||
if (error != NULL) {
|
if (error != NULL) {
|
||||||
Log::Warning("Loopback Could not construct pipeline %s:\n%s", description.c_str(), error->message);
|
std::string msg = std::string("Loopback : Could not construct pipeline ") + description + "\n" + std::string(error->message);
|
||||||
g_clear_error (&error);
|
g_clear_error (&error);
|
||||||
finished_ = true;
|
finished_ = true;
|
||||||
return;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup device sink
|
// setup device sink
|
||||||
@@ -238,27 +237,21 @@ void Loopback::init(GstCaps *caps)
|
|||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Log::Warning("Loopback Could not configure source");
|
|
||||||
finished_ = true;
|
finished_ = true;
|
||||||
return;
|
return std::string("Loopback : Could not configure source.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// start recording
|
// start recording
|
||||||
GstStateChangeReturn ret = gst_element_set_state (pipeline_, GST_STATE_PLAYING);
|
GstStateChangeReturn ret = gst_element_set_state (pipeline_, GST_STATE_PLAYING);
|
||||||
if (ret == GST_STATE_CHANGE_FAILURE) {
|
if (ret == GST_STATE_CHANGE_FAILURE) {
|
||||||
Log::Warning("Loopback Could not open %s", Loopback::system_loopback_name.c_str());
|
|
||||||
finished_ = true;
|
finished_ = true;
|
||||||
return;
|
return std::string("Loopback : Could not open ") + Loopback::system_loopback_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
// all good
|
// all good
|
||||||
#if defined(LINUX)
|
initialized_ = true;
|
||||||
Log::Notify("Loopback started (v4l2loopback on %s)", Loopback::system_loopback_name.c_str());
|
|
||||||
#else
|
return std::string("Loopback started on ") + Loopback::system_loopback_name;
|
||||||
Log::Notify("Loopback started (%s)", Loopback::system_loopback_name.c_str());
|
|
||||||
#endif
|
|
||||||
// start
|
|
||||||
active_ = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Loopback::terminate()
|
void Loopback::terminate()
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ class Loopback : public FrameGrabber
|
|||||||
static std::string system_loopback_name;
|
static std::string system_loopback_name;
|
||||||
static bool system_loopback_initialized;
|
static bool system_loopback_initialized;
|
||||||
|
|
||||||
void init(GstCaps *caps) override;
|
std::string init(GstCaps *caps) override;
|
||||||
void terminate() override;
|
void terminate() override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
54
Recorder.cpp
54
Recorder.cpp
@@ -43,11 +43,11 @@ PNGRecorder::PNGRecorder() : FrameGrabber()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void PNGRecorder::init(GstCaps *caps)
|
std::string PNGRecorder::init(GstCaps *caps)
|
||||||
{
|
{
|
||||||
// ignore
|
// ignore
|
||||||
if (caps == nullptr)
|
if (caps == nullptr)
|
||||||
return;
|
return std::string("Invalid caps");
|
||||||
|
|
||||||
// create a gstreamer pipeline
|
// create a gstreamer pipeline
|
||||||
std::string description = "appsrc name=src ! videoconvert ! pngenc ! filesink name=sink";
|
std::string description = "appsrc name=src ! videoconvert ! pngenc ! filesink name=sink";
|
||||||
@@ -56,10 +56,10 @@ void PNGRecorder::init(GstCaps *caps)
|
|||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
pipeline_ = gst_parse_launch (description.c_str(), &error);
|
pipeline_ = gst_parse_launch (description.c_str(), &error);
|
||||||
if (error != NULL) {
|
if (error != NULL) {
|
||||||
Log::Warning("PNG Capture Could not construct pipeline %s:\n%s", description.c_str(), error->message);
|
std::string msg = std::string("PNG Capture Could not construct pipeline ") + description + "\n" + std::string(error->message);
|
||||||
g_clear_error (&error);
|
g_clear_error (&error);
|
||||||
finished_ = true;
|
finished_ = true;
|
||||||
return;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify location path (path is always terminated by the OS dependent separator)
|
// verify location path (path is always terminated by the OS dependent separator)
|
||||||
@@ -102,24 +102,21 @@ void PNGRecorder::init(GstCaps *caps)
|
|||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Log::Warning("PNG Capture Could not configure source");
|
|
||||||
finished_ = true;
|
finished_ = true;
|
||||||
return;
|
return std::string("PNG Capture : Failed to configure frame grabber.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// start pipeline
|
// start pipeline
|
||||||
GstStateChangeReturn ret = gst_element_set_state (pipeline_, GST_STATE_PLAYING);
|
GstStateChangeReturn ret = gst_element_set_state (pipeline_, GST_STATE_PLAYING);
|
||||||
if (ret == GST_STATE_CHANGE_FAILURE) {
|
if (ret == GST_STATE_CHANGE_FAILURE) {
|
||||||
Log::Warning("PNG Capture Could not record %s", filename_.c_str());
|
|
||||||
finished_ = true;
|
finished_ = true;
|
||||||
return;
|
return std::string("PNG Capture : Failed to start frame grabber.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// all good
|
// all good
|
||||||
Log::Info("PNG Capture started.");
|
initialized_ = true;
|
||||||
|
|
||||||
// start recording !!
|
return std::string("PNG Capture started ");
|
||||||
active_ = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PNGRecorder::terminate()
|
void PNGRecorder::terminate()
|
||||||
@@ -289,11 +286,11 @@ VideoRecorder::VideoRecorder() : FrameGrabber()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoRecorder::init(GstCaps *caps)
|
std::string VideoRecorder::init(GstCaps *caps)
|
||||||
{
|
{
|
||||||
// ignore
|
// ignore
|
||||||
if (caps == nullptr)
|
if (caps == nullptr)
|
||||||
return;
|
return std::string("Invalid caps");
|
||||||
|
|
||||||
// apply settings
|
// apply settings
|
||||||
buffering_size_ = MAX( MIN_BUFFER_SIZE, buffering_preset_value[Settings::application.record.buffering_mode]);
|
buffering_size_ = MAX( MIN_BUFFER_SIZE, buffering_preset_value[Settings::application.record.buffering_mode]);
|
||||||
@@ -307,10 +304,10 @@ void VideoRecorder::init(GstCaps *caps)
|
|||||||
|
|
||||||
// test for a hardware accelerated encoder
|
// test for a hardware accelerated encoder
|
||||||
if (Settings::application.render.gpu_decoding &&
|
if (Settings::application.render.gpu_decoding &&
|
||||||
#if GST_GL_HAVE_PLATFORM_GLX
|
//#if GST_GL_HAVE_PLATFORM_GLX
|
||||||
|
|
||||||
glGetString(GL_VENDOR)[0] == 'N' && glGetString(GL_VENDOR)[1] == 'V' && // TODO; hack to test for NVIDIA GPU support
|
// glGetString(GL_VENDOR)[0] == 'N' && glGetString(GL_VENDOR)[1] == 'V' && // TODO; hack to test for NVIDIA GPU support
|
||||||
#endif
|
//#endif
|
||||||
GstToolkit::has_feature(hardware_encoder[Settings::application.record.profile]) ) {
|
GstToolkit::has_feature(hardware_encoder[Settings::application.record.profile]) ) {
|
||||||
|
|
||||||
description += hardware_profile_description[Settings::application.record.profile];
|
description += hardware_profile_description[Settings::application.record.profile];
|
||||||
@@ -345,11 +342,10 @@ void VideoRecorder::init(GstCaps *caps)
|
|||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
pipeline_ = gst_parse_launch (description.c_str(), &error);
|
pipeline_ = gst_parse_launch (description.c_str(), &error);
|
||||||
if (error != NULL) {
|
if (error != NULL) {
|
||||||
Log::Info("Video Recording : Could not construct pipeline %s\n%s", description.c_str(), error->message);
|
std::string msg = std::string("Video Recording : Could not construct pipeline ") + description + "\n" + std::string(error->message);
|
||||||
Log::Warning("Video Recording : Failed to initiate GStreamer.");
|
|
||||||
g_clear_error (&error);
|
g_clear_error (&error);
|
||||||
finished_ = true;
|
finished_ = true;
|
||||||
return;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup file sink
|
// setup file sink
|
||||||
@@ -399,24 +395,22 @@ void VideoRecorder::init(GstCaps *caps)
|
|||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Log::Warning("Video Recording : Failed to configure frame grabber.");
|
|
||||||
finished_ = true;
|
finished_ = true;
|
||||||
return;
|
return std::string("Video Recording : Failed to configure frame grabber.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// start recording
|
// start recording
|
||||||
GstStateChangeReturn ret = gst_element_set_state (pipeline_, GST_STATE_PLAYING);
|
GstStateChangeReturn ret = gst_element_set_state (pipeline_, GST_STATE_PLAYING);
|
||||||
if (ret == GST_STATE_CHANGE_FAILURE) {
|
if (ret == GST_STATE_CHANGE_FAILURE) {
|
||||||
Log::Warning("Video Recording : Failed to start frame grabber.");
|
|
||||||
finished_ = true;
|
finished_ = true;
|
||||||
return;
|
return std::string("Video Recording : Failed to start frame grabber.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// all good
|
// all good
|
||||||
Log::Info("Video Recording started (%s)", profile_name[Settings::application.record.profile]);
|
initialized_ = true;
|
||||||
|
|
||||||
|
return std::string("Video Recording started ") + profile_name[Settings::application.record.profile];
|
||||||
|
|
||||||
// start recording !!
|
|
||||||
active_ = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoRecorder::terminate()
|
void VideoRecorder::terminate()
|
||||||
@@ -445,10 +439,8 @@ void VideoRecorder::terminate()
|
|||||||
|
|
||||||
std::string VideoRecorder::info() const
|
std::string VideoRecorder::info() const
|
||||||
{
|
{
|
||||||
if (active_)
|
if (initialized_ && !active_ && !endofstream_)
|
||||||
return FrameGrabber::info();
|
|
||||||
else if (!endofstream_)
|
|
||||||
return "Saving file...";
|
return "Saving file...";
|
||||||
else
|
|
||||||
return "...";
|
return FrameGrabber::info();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void init(GstCaps *caps) override;
|
std::string init(GstCaps *caps) override;
|
||||||
void terminate() override;
|
void terminate() override;
|
||||||
void addFrame(GstBuffer *buffer, GstCaps *caps) override;
|
void addFrame(GstBuffer *buffer, GstCaps *caps) override;
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ class VideoRecorder : public FrameGrabber
|
|||||||
{
|
{
|
||||||
std::string filename_;
|
std::string filename_;
|
||||||
|
|
||||||
void init(GstCaps *caps) override;
|
std::string init(GstCaps *caps) override;
|
||||||
void terminate() override;
|
void terminate() override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
28
Streamer.cpp
28
Streamer.cpp
@@ -308,11 +308,11 @@ VideoStreamer::VideoStreamer(const NetworkToolkit::StreamConfig &conf): FrameGra
|
|||||||
frame_duration_ = gst_util_uint64_scale_int (1, GST_SECOND, STREAMING_FPS); // fixed 30 FPS
|
frame_duration_ = gst_util_uint64_scale_int (1, GST_SECOND, STREAMING_FPS); // fixed 30 FPS
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoStreamer::init(GstCaps *caps)
|
std::string VideoStreamer::init(GstCaps *caps)
|
||||||
{
|
{
|
||||||
// ignore
|
// ignore
|
||||||
if (caps == nullptr)
|
if (caps == nullptr)
|
||||||
return;
|
return std::string("Invalid caps");
|
||||||
|
|
||||||
// check that config matches the given buffer properties
|
// check that config matches the given buffer properties
|
||||||
gint w = 0, h = 0;
|
gint w = 0, h = 0;
|
||||||
@@ -322,10 +322,9 @@ void VideoStreamer::init(GstCaps *caps)
|
|||||||
if ( gst_structure_has_field (capstruct, "height"))
|
if ( gst_structure_has_field (capstruct, "height"))
|
||||||
gst_structure_get_int (capstruct, "height", &h);
|
gst_structure_get_int (capstruct, "height", &h);
|
||||||
if ( config_.width != w || config_.height != h) {
|
if ( config_.width != w || config_.height != h) {
|
||||||
Log::Warning("Streaming cannot start: given frames (%d x %d) incompatible with stream (%d x %d)",
|
|
||||||
w, w, config_.width, config_.height);
|
|
||||||
finished_ = true;
|
finished_ = true;
|
||||||
return;
|
return std::string("Video Streamer cannot start: given frames (") + std::to_string(w) + " x " + std::to_string(h) +
|
||||||
|
") are incompatible with stream (" + std::to_string(config_.width) + " x " + std::to_string(config_.height) + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
// prevent eroneous protocol values
|
// prevent eroneous protocol values
|
||||||
@@ -340,10 +339,10 @@ void VideoStreamer::init(GstCaps *caps)
|
|||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
pipeline_ = gst_parse_launch (description.c_str(), &error);
|
pipeline_ = gst_parse_launch (description.c_str(), &error);
|
||||||
if (error != NULL) {
|
if (error != NULL) {
|
||||||
Log::Warning("VideoStreamer Could not construct pipeline %s:\n%s", description.c_str(), error->message);
|
std::string msg = std::string("Video Streamer : Could not construct pipeline ") + description + "\n" + std::string(error->message);
|
||||||
g_clear_error (&error);
|
g_clear_error (&error);
|
||||||
finished_ = true;
|
finished_ = true;
|
||||||
return;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup streaming sink
|
// setup streaming sink
|
||||||
@@ -398,24 +397,21 @@ void VideoStreamer::init(GstCaps *caps)
|
|||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Log::Warning("VideoStreamer Could not configure capture source");
|
|
||||||
finished_ = true;
|
finished_ = true;
|
||||||
return;
|
return std::string("Video Streamer : Failed to configure frame grabber.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// start recording
|
// start recording
|
||||||
GstStateChangeReturn ret = gst_element_set_state (pipeline_, GST_STATE_PLAYING);
|
GstStateChangeReturn ret = gst_element_set_state (pipeline_, GST_STATE_PLAYING);
|
||||||
if (ret == GST_STATE_CHANGE_FAILURE) {
|
if (ret == GST_STATE_CHANGE_FAILURE) {
|
||||||
Log::Warning("VideoStreamer failed");
|
|
||||||
finished_ = true;
|
finished_ = true;
|
||||||
return;
|
return std::string("Video Streamer : Failed to start frame grabber.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// all good
|
// all good
|
||||||
Log::Notify("Streaming to %s.", config_.client_name.c_str());
|
initialized_ = true;
|
||||||
|
|
||||||
// start streaming !!
|
return std::string("Streaming to ") + config_.client_name + "started.";
|
||||||
active_ = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoStreamer::terminate()
|
void VideoStreamer::terminate()
|
||||||
@@ -451,7 +447,9 @@ void VideoStreamer::stop ()
|
|||||||
std::string VideoStreamer::info() const
|
std::string VideoStreamer::info() const
|
||||||
{
|
{
|
||||||
std::ostringstream ret;
|
std::ostringstream ret;
|
||||||
if (active_) {
|
if (!initialized_)
|
||||||
|
ret << "Connecting";
|
||||||
|
else if (active_) {
|
||||||
ret << NetworkToolkit::protocol_name[config_.protocol];
|
ret << NetworkToolkit::protocol_name[config_.protocol];
|
||||||
ret << " to ";
|
ret << " to ";
|
||||||
ret << config_.client_name;
|
ret << config_.client_name;
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ class VideoStreamer : public FrameGrabber
|
|||||||
{
|
{
|
||||||
friend class Streaming;
|
friend class Streaming;
|
||||||
|
|
||||||
void init(GstCaps *caps) override;
|
std::string init(GstCaps *caps) override;
|
||||||
void terminate() override;
|
void terminate() override;
|
||||||
void stop() override;
|
void stop() override;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user