Implement broadcast manager functionality and enhance FrameGrabber info and type methods

This commit is contained in:
brunoherbelin
2025-11-09 11:38:01 +01:00
parent 0ef06e400d
commit 08114e2cbe
16 changed files with 281 additions and 92 deletions

View File

@@ -42,6 +42,7 @@
#include "NetworkToolkit.h" #include "NetworkToolkit.h"
#include "UserInterfaceManager.h" #include "UserInterfaceManager.h"
#include "Streamer.h" #include "Streamer.h"
#include "VideoBroadcast.h"
#include "ControlManager.h" #include "ControlManager.h"
@@ -605,6 +606,16 @@ bool Control::receiveOutputAttribute(const std::string &attribute,
Mixer::manager().session()->setFadingTarget( Mixer::manager().session()->fading() + f * 0.01); Mixer::manager().session()->setFadingTarget( Mixer::manager().session()->fading() + f * 0.01);
need_feedback = true; need_feedback = true;
} }
else if ( attribute.compare(OSC_OUTPUT_SRT_START) == 0) {
float f = (float) Settings::application.broadcast_port;
// if argument is given, it is the connection port
if (!arguments.Eos())
arguments >> f >> osc::EndMessage;
Broadcast::manager().start( new VideoBroadcast((int) f), true);
}
else if ( attribute.compare(OSC_OUTPUT_SRT_STOP) == 0) {
Broadcast::manager().stop(FrameGrabber::GRABBER_BROADCAST);
}
// inform of invalid attribute name // inform of invalid attribute name
else { else {
Log::Info(CONTROL_OSC_MSG "Unknown attribute '%s' for target 'output'", attribute.c_str()); Log::Info(CONTROL_OSC_MSG "Unknown attribute '%s' for target 'output'", attribute.c_str());

View File

@@ -24,6 +24,8 @@
#define OSC_OUTPUT_FADING "/fading" #define OSC_OUTPUT_FADING "/fading"
#define OSC_OUTPUT_FADE_IN "/fade-in" #define OSC_OUTPUT_FADE_IN "/fade-in"
#define OSC_OUTPUT_FADE_OUT "/fade-out" #define OSC_OUTPUT_FADE_OUT "/fade-out"
#define OSC_OUTPUT_SRT_START "/srt-start"
#define OSC_OUTPUT_SRT_STOP "/srt-stop"
#define OSC_ALL "/all" #define OSC_ALL "/all"
#define OSC_SELECTION "/selection" #define OSC_SELECTION "/selection"

View File

@@ -106,6 +106,28 @@ FrameGrabber *FrameGrabbing::get(uint64_t id)
return nullptr; return nullptr;
} }
struct fgType
{
inline bool operator()(const FrameGrabber* elem) const {
return (elem && elem->type() == _t);
}
explicit fgType(FrameGrabber::Type t) : _t(t) { }
private:
FrameGrabber::Type _t;
};
FrameGrabber *FrameGrabbing::get(FrameGrabber::Type t)
{
if (grabbers_.size() > 0 )
{
std::list<FrameGrabber *>::iterator iter = std::find_if(grabbers_.begin(), grabbers_.end(), fgType(t));
if (iter != grabbers_.end())
return (*iter);
}
return nullptr;
}
void FrameGrabbing::stopAll() void FrameGrabbing::stopAll()
{ {
std::list<FrameGrabber *>::iterator iter; std::list<FrameGrabber *>::iterator iter;
@@ -349,8 +371,37 @@ void FrameGrabber::stop ()
} }
std::string FrameGrabber::info() const std::string FrameGrabber::info(bool extended) const
{ {
if (extended) {
std::string typestring;
switch ( type() )
{
case GRABBER_PNG :
typestring = "Portable Network Graphics frame grabber";
break;
case GRABBER_VIDEO :
typestring = "Video file frame grabber";
break;
case GRABBER_P2P :
typestring = "Peer-to-Peer stream frame grabber";
break;
case GRABBER_BROADCAST :
typestring = "SRT Broarcast frame grabber";
break;
case GRABBER_SHM :
typestring = "Shared Memory frame grabber";
break;
case GRABBER_LOOPBACK :
typestring = "Loopback frame grabber";
break;
default:
typestring = "Generic frame grabber";
break;
}
return typestring;
}
if (!initialized_) if (!initialized_)
return "Initializing"; return "Initializing";
if (active_) if (active_)
@@ -603,3 +654,56 @@ guint64 FrameGrabber::frames() const
{ {
return frame_count_; return frame_count_;
} }
uint64_t Broadcast::start(FrameGrabber *ptr, bool singleton)
{
if (singleton)
stop( ptr->type() );
uint64_t b = ptr->id();
FrameGrabbing::manager().add(ptr);
return b;
}
bool Broadcast::enabled(uint64_t b)
{
return ( FrameGrabbing::manager().get(b) != nullptr);
}
bool Broadcast::busy(uint64_t b)
{
FrameGrabber *ptr = FrameGrabbing::manager().get(b);
if (ptr != nullptr)
return ptr->busy();
return false;
}
std::string Broadcast::info(uint64_t b, bool extended)
{
FrameGrabber *ptr = FrameGrabbing::manager().get(b);
if (ptr != nullptr)
return ptr->info(extended);
return "Disabled";
}
void Broadcast::stop(uint64_t b)
{
FrameGrabber *ptr = FrameGrabbing::manager().get(b);
if (ptr != nullptr)
ptr->stop();
}
void Broadcast::stop(FrameGrabber::Type T)
{
FrameGrabber *prev = nullptr;
do {
prev = FrameGrabbing::manager().get( T );
if (prev != nullptr)
prev->stop();
}
while (prev != nullptr);
}

View File

@@ -40,9 +40,22 @@ public:
virtual ~FrameGrabber(); virtual ~FrameGrabber();
inline uint64_t id() const { return id_; } inline uint64_t id() const { return id_; }
// types of sub-classes of FrameGrabber
typedef enum {
GRABBER_GENERIC = 0,
GRABBER_PNG = 1,
GRABBER_VIDEO = 2,
GRABBER_P2P,
GRABBER_BROADCAST,
GRABBER_SHM,
GRABBER_LOOPBACK,
GRABBER_INVALID
} Type;
virtual Type type () const { return GRABBER_GENERIC; }
virtual void stop(); virtual void stop();
virtual std::string info() const; virtual std::string info(bool extended = false) const;
virtual uint64_t duration() const; virtual uint64_t duration() const;
virtual bool finished() const; virtual bool finished() const;
virtual bool busy() const; virtual bool busy() const;
@@ -133,6 +146,7 @@ public:
void verify(FrameGrabber **rec); void verify(FrameGrabber **rec);
bool busy() const; bool busy() const;
FrameGrabber *get(uint64_t id); FrameGrabber *get(uint64_t id);
FrameGrabber *get(FrameGrabber::Type t);
void stopAll(); void stopAll();
void clearAll(); void clearAll();
@@ -154,6 +168,38 @@ private:
GstCaps *caps_; GstCaps *caps_;
}; };
/**
* @brief The Broadcast class gives a global access to launch and stop FrameGrabbers
*
* FrameGrabbers can terminate (normal behavior or failure) and the FrameGrabber
* is deleted automatically; pointer is then invalid and cannot be accessed. To avoid this,
* the Broadcast::manager() gives access to FrameGrabbers by id.
*
* Singleton mechanism also allows starting a unique instance of each FrameGrabber::Type
*/
class Broadcast
{
// Private Constructor
Broadcast() {};
Broadcast(Broadcast const& copy) = delete;
Broadcast& operator=(Broadcast const& copy) = delete;
public:
static Broadcast& manager ()
{
// The only instance
static Broadcast _instance;
return _instance;
}
uint64_t start(FrameGrabber *ptr, bool singleton = false);
bool enabled(uint64_t);
bool busy(uint64_t);
std::string info(uint64_t, bool extended = false);
void stop(uint64_t);
void stop(FrameGrabber::Type);
};
#endif // FRAMEGRABBER_H #endif // FRAMEGRABBER_H

View File

@@ -175,16 +175,21 @@ void Loopback::stop ()
active_ = false; active_ = false;
} }
std::string Loopback::info() const std::string Loopback::info(bool extended) const
{ {
std::ostringstream ret; std::ostringstream ret;
if (!initialized_) if (extended) {
ret << "Loopback starting.."; ret << device_name();
else if (active_) }
ret << "V4L2 Loopback on " << device_name(); else {
else if (!initialized_)
ret << "Loopback terminated"; ret << "Loopback starting..";
else if (active_)
ret << "V4L2 Loopback on " << device_name();
else
ret << "Loopback terminated";
}
return ret.str(); return ret.str();
} }

View File

@@ -12,13 +12,15 @@ public:
Loopback(int deviceid = LOOPBACK_DEFAULT_DEVICE); Loopback(int deviceid = LOOPBACK_DEFAULT_DEVICE);
virtual ~Loopback() {} virtual ~Loopback() {}
FrameGrabber::Type type () const override { return FrameGrabber::GRABBER_LOOPBACK; }
static bool available(); static bool available();
inline int device_id() const { return loopback_device_; } inline int device_id() const { return loopback_device_; }
std::string device_name() const; std::string device_name() const;
void stop() override; void stop() override;
std::string info() const override; std::string info(bool extended = false) const override;
private: private:
std::string init(GstCaps *caps) override; std::string init(GstCaps *caps) override;

View File

@@ -41,7 +41,7 @@
OutputPreviewWindow::OutputPreviewWindow() : WorkspaceWindow("OutputPreview"), OutputPreviewWindow::OutputPreviewWindow() : WorkspaceWindow("OutputPreview"),
video_recorder_(nullptr), video_broadcaster_(nullptr), loopback_broadcaster_(nullptr), video_recorder_(nullptr), srt_(0), shm_(0), loopback_(0),
magnifying_glass(false) magnifying_glass(false)
{ {
@@ -96,11 +96,6 @@ void OutputPreviewWindow::Update()
video_recorder_->stop(); video_recorder_->stop();
} }
// verify the frame grabbers are valid (change to nullptr if invalid)
FrameGrabbing::manager().verify( (FrameGrabber**) &video_broadcaster_);
FrameGrabbing::manager().verify( (FrameGrabber**) &shm_broadcaster_);
FrameGrabbing::manager().verify( (FrameGrabber**) &loopback_broadcaster_);
} }
VideoRecorder *delayTrigger(VideoRecorder *g, std::chrono::milliseconds delay) { VideoRecorder *delayTrigger(VideoRecorder *g, std::chrono::milliseconds delay) {
@@ -140,22 +135,19 @@ void OutputPreviewWindow::ToggleRecordPause()
void OutputPreviewWindow::ToggleVideoBroadcast() void OutputPreviewWindow::ToggleVideoBroadcast()
{ {
if (video_broadcaster_) { if (Broadcast::manager().enabled(srt_) )
video_broadcaster_->stop(); Broadcast::manager().stop(srt_);
}
else { else {
if (Settings::application.broadcast_port<1000) if (Settings::application.broadcast_port<1000)
Settings::application.broadcast_port = BROADCAST_DEFAULT_PORT; Settings::application.broadcast_port = BROADCAST_DEFAULT_PORT;
video_broadcaster_ = new VideoBroadcast(Settings::application.broadcast_port); srt_ = Broadcast::manager().start( new VideoBroadcast(Settings::application.broadcast_port), true);
FrameGrabbing::manager().add(video_broadcaster_);
} }
} }
void OutputPreviewWindow::ToggleSharedMemory() void OutputPreviewWindow::ToggleSharedMemory()
{ {
if (shm_broadcaster_) { if (Broadcast::manager().enabled(shm_) )
shm_broadcaster_->stop(); Broadcast::manager().stop(shm_);
}
else { else {
// find a folder to put the socket for shm // find a folder to put the socket for shm
std::string _shm_socket_file = Settings::application.shm_socket_path; std::string _shm_socket_file = Settings::application.shm_socket_path;
@@ -164,25 +156,22 @@ void OutputPreviewWindow::ToggleSharedMemory()
_shm_socket_file = SystemToolkit::full_filename(_shm_socket_file, ".shm_vimix" + std::to_string(Settings::application.instance_id)); _shm_socket_file = SystemToolkit::full_filename(_shm_socket_file, ".shm_vimix" + std::to_string(Settings::application.instance_id));
// create shhmdata broadcaster with method // create shhmdata broadcaster with method
shm_broadcaster_ = new ShmdataBroadcast( (ShmdataBroadcast::Method) Settings::application.shm_method, _shm_socket_file); shm_ = Broadcast::manager().start( new ShmdataBroadcast( (ShmdataBroadcast::Method) Settings::application.shm_method, _shm_socket_file), true);
FrameGrabbing::manager().add(shm_broadcaster_);
} }
} }
bool OutputPreviewWindow::ToggleLoopbackCamera() bool OutputPreviewWindow::ToggleLoopbackCamera()
{ {
bool need_initialization = false; bool need_initialization = false;
if (loopback_broadcaster_) { if (Broadcast::manager().enabled(loopback_))
loopback_broadcaster_->stop(); Broadcast::manager().stop(loopback_);
}
else { else {
if (Settings::application.loopback_camera < 1) if (Settings::application.loopback_camera < 1)
Settings::application.loopback_camera = LOOPBACK_DEFAULT_DEVICE; Settings::application.loopback_camera = LOOPBACK_DEFAULT_DEVICE;
Settings::application.loopback_camera += Settings::application.instance_id; Settings::application.loopback_camera += Settings::application.instance_id;
try { try {
loopback_broadcaster_ = new Loopback(Settings::application.loopback_camera); loopback_ = Broadcast::manager().start( new Loopback(Settings::application.loopback_camera), true );
FrameGrabbing::manager().add(loopback_broadcaster_);
} }
catch (const std::runtime_error &e) { catch (const std::runtime_error &e) {
need_initialization = true; need_initialization = true;
@@ -400,26 +389,27 @@ void OutputPreviewWindow::Render()
// Broadcasting menu // Broadcasting menu
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_BROADCAST, 0.9f)); ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_BROADCAST, 0.9f));
if (VideoBroadcast::available()) { if (VideoBroadcast::available()) {
if ( ImGui::MenuItem( ICON_FA_GLOBE " SRT Broadcast", NULL, videoBroadcastEnabled()) ) if ( ImGui::MenuItem( ICON_FA_GLOBE " SRT Broadcast", NULL, Broadcast::manager().enabled(srt_) ) )
ToggleVideoBroadcast(); ToggleVideoBroadcast();
} }
// Shared Memory menu // Shared Memory menu
if (ShmdataBroadcast::available()) { if (ShmdataBroadcast::available()) {
if ( ImGui::MenuItem( ICON_FA_MEMORY " SHM Shared Memory", NULL, sharedMemoryEnabled()) ) if ( ImGui::MenuItem( ICON_FA_MEMORY " SHM Shared Memory", NULL, Broadcast::manager().enabled(shm_) ) )
ToggleSharedMemory(); ToggleSharedMemory();
} }
// Loopback camera menu // Loopback camera menu
if (Loopback::available()) { if (Loopback::available()) {
if ( ImGui::MenuItem( ICON_FA_VIDEO " Loopback Camera", NULL, loopbackCameraEnabled()) ) if ( ImGui::MenuItem( ICON_FA_VIDEO " Loopback Camera", NULL, Broadcast::manager().enabled(loopback_)) )
openInitializeSystemLoopback = ToggleLoopbackCamera(); openInitializeSystemLoopback = ToggleLoopbackCamera();
} }
ImGui::PopStyleColor(1); ImGui::PopStyleColor(1);
// Display list of active stream // Display list of active stream
if (ls.size()>0 || videoBroadcastEnabled() || sharedMemoryEnabled() || loopbackCameraEnabled()) { if (ls.size()>0 || Broadcast::manager().enabled(srt_) ||
Broadcast::manager().enabled(shm_) || Broadcast::manager().enabled(loopback_)) {
ImGui::Separator(); ImGui::Separator();
ImGui::MenuItem("Active streams:", nullptr, false, false); ImGui::MenuItem("Active streams:", nullptr, false, false);
@@ -428,37 +418,38 @@ void OutputPreviewWindow::Render()
ImGui::Text(" %s ", (*it).c_str() ); ImGui::Text(" %s ", (*it).c_str() );
// SRT broadcast description // SRT broadcast description
if (videoBroadcastEnabled()) { if (Broadcast::manager().enabled(srt_)) {
ImGui::Text(" %s ", video_broadcaster_->info().c_str()); ImGui::Text(" %s ", Broadcast::manager().info(srt_).c_str());
// copy text icon to give user the srt link to connect to // copy text icon to give user the srt link to connect to
ImVec2 draw_pos = ImGui::GetCursorPos(); ImVec2 draw_pos = ImGui::GetCursorPos();
ImGui::SetCursorPos(draw_pos + ImVec2(ImGui::GetContentRegionAvailWidth() - 1.2 * ImGui::GetTextLineHeightWithSpacing(), -0.8 * ImGui::GetFrameHeight()) ); ImGui::SetCursorPos(draw_pos + ImVec2(ImGui::GetContentRegionAvailWidth() - 1.2 * ImGui::GetTextLineHeightWithSpacing(), -0.8 * ImGui::GetFrameHeight()) );
char msg[256]; std::string moreinfo = Broadcast::manager().info(srt_, true);
ImFormatString(msg, IM_ARRAYSIZE(msg), "srt//%s:%d", NetworkToolkit::host_ips()[1].c_str(), Settings::application.broadcast_port ); if (ImGuiToolkit::IconButton( ICON_FA_COPY, moreinfo.c_str()))
if (ImGuiToolkit::IconButton( ICON_FA_COPY, msg)) ImGui::SetClipboardText(moreinfo.c_str());
ImGui::SetClipboardText(msg);
ImGui::SetCursorPos(draw_pos); ImGui::SetCursorPos(draw_pos);
} }
// Shared memory broadcast description // Shared memory broadcast description
if (sharedMemoryEnabled()) { if (Broadcast::manager().enabled(shm_)) {
ImGui::Text(" %s ", shm_broadcaster_->info().c_str()); ImGui::Text(" %s ", Broadcast::manager().info(shm_).c_str());
// copy text icon to give user the socket path to connect to // copy text icon to give user the socket path to connect to
ImVec2 draw_pos = ImGui::GetCursorPos(); ImVec2 draw_pos = ImGui::GetCursorPos();
ImGui::SetCursorPos(draw_pos + ImVec2(ImGui::GetContentRegionAvailWidth() - 1.2 * ImGui::GetTextLineHeightWithSpacing(), -0.8 * ImGui::GetFrameHeight()) ); ImGui::SetCursorPos(draw_pos + ImVec2(ImGui::GetContentRegionAvailWidth() - 1.2 * ImGui::GetTextLineHeightWithSpacing(), -0.8 * ImGui::GetFrameHeight()) );
if (ImGuiToolkit::IconButton( ICON_FA_COPY, shm_broadcaster_->gst_pipeline().c_str())) std::string moreinfo = Broadcast::manager().info(shm_, true);
ImGui::SetClipboardText(shm_broadcaster_->gst_pipeline().c_str()); if (ImGuiToolkit::IconButton( ICON_FA_COPY, moreinfo.c_str()))
ImGui::SetClipboardText(moreinfo.c_str());
ImGui::SetCursorPos(draw_pos); ImGui::SetCursorPos(draw_pos);
} }
// Loopback camera description // Loopback camera description
if (loopbackCameraEnabled()) { if (Broadcast::manager().enabled(loopback_)) {
ImGui::Text(" %s ", loopback_broadcaster_->info().c_str()); ImGui::Text(" %s ", Broadcast::manager().info(loopback_).c_str());
// copy text icon to give user the device path to connect to // copy text icon to give user the device path to connect to
ImVec2 draw_pos = ImGui::GetCursorPos(); ImVec2 draw_pos = ImGui::GetCursorPos();
ImGui::SetCursorPos(draw_pos + ImVec2(ImGui::GetContentRegionAvailWidth() - 1.2 * ImGui::GetTextLineHeightWithSpacing(), -0.8 * ImGui::GetFrameHeight()) ); ImGui::SetCursorPos(draw_pos + ImVec2(ImGui::GetContentRegionAvailWidth() - 1.2 * ImGui::GetTextLineHeightWithSpacing(), -0.8 * ImGui::GetFrameHeight()) );
if (ImGuiToolkit::IconButton( ICON_FA_COPY, loopback_broadcaster_->device_name().c_str())) std::string moreinfo = Broadcast::manager().info(loopback_, true);
ImGui::SetClipboardText(loopback_broadcaster_->device_name().c_str()); if (ImGuiToolkit::IconButton( ICON_FA_COPY, moreinfo.c_str()))
ImGui::SetClipboardText(moreinfo.c_str());
ImGui::SetCursorPos(draw_pos); ImGui::SetCursorPos(draw_pos);
} }
} }
@@ -558,10 +549,10 @@ void OutputPreviewWindow::Render()
} }
// broadcast indicator // broadcast indicator
float vertical = r; float vertical = r;
if (video_broadcaster_) if (Broadcast::manager().enabled(srt_))
{ {
ImGui::SetCursorScreenPos(ImVec2(draw_pos.x + imagesize.x - 2.5f * r, draw_pos.y + vertical)); ImGui::SetCursorScreenPos(ImVec2(draw_pos.x + imagesize.x - 2.5f * r, draw_pos.y + vertical));
if (video_broadcaster_->busy()) if (Broadcast::manager().busy(srt_))
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_BROADCAST, 0.8f)); ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_BROADCAST, 0.8f));
else else
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_BROADCAST, 0.4f)); ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_BROADCAST, 0.4f));
@@ -570,10 +561,10 @@ void OutputPreviewWindow::Render()
vertical += 2.f * r; vertical += 2.f * r;
} }
// shmdata indicator // shmdata indicator
if (shm_broadcaster_) if (Broadcast::manager().enabled(shm_))
{ {
ImGui::SetCursorScreenPos(ImVec2(draw_pos.x + imagesize.x - 2.5f * r, draw_pos.y + vertical)); ImGui::SetCursorScreenPos(ImVec2(draw_pos.x + imagesize.x - 2.5f * r, draw_pos.y + vertical));
if (shm_broadcaster_->busy()) if (Broadcast::manager().busy(shm_))
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_BROADCAST, 0.8f)); ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_BROADCAST, 0.8f));
else else
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_BROADCAST, 0.4f)); ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_BROADCAST, 0.4f));
@@ -582,10 +573,10 @@ void OutputPreviewWindow::Render()
vertical += 2.f * r; vertical += 2.f * r;
} }
// loopback camera indicator // loopback camera indicator
if (loopback_broadcaster_) if (Broadcast::manager().enabled(loopback_))
{ {
ImGui::SetCursorScreenPos(ImVec2(draw_pos.x + imagesize.x - 2.5f * r, draw_pos.y + vertical)); ImGui::SetCursorScreenPos(ImVec2(draw_pos.x + imagesize.x - 2.5f * r, draw_pos.y + vertical));
if (loopback_broadcaster_->busy()) if (Broadcast::manager().busy(loopback_))
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_BROADCAST, 0.8f)); ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_BROADCAST, 0.8f));
else else
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_BROADCAST, 0.4f)); ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_BROADCAST, 0.4f));

View File

@@ -5,7 +5,6 @@
#include "WorkspaceWindow.h" #include "WorkspaceWindow.h"
class VideoRecorder; class VideoRecorder;
class VideoBroadcast;
class ShmdataBroadcast; class ShmdataBroadcast;
class Loopback; class Loopback;
@@ -13,9 +12,9 @@ class OutputPreviewWindow : public WorkspaceWindow
{ {
// frame grabbers // frame grabbers
VideoRecorder *video_recorder_; VideoRecorder *video_recorder_;
VideoBroadcast *video_broadcaster_; uint64_t srt_;
ShmdataBroadcast *shm_broadcaster_; uint64_t shm_;
Loopback *loopback_broadcaster_; uint64_t loopback_;
// delayed trigger for recording // delayed trigger for recording
std::vector< std::future<VideoRecorder *> > _video_recorders; std::vector< std::future<VideoRecorder *> > _video_recorders;
@@ -34,13 +33,8 @@ public:
inline bool isRecording() const { return video_recorder_ != nullptr; } inline bool isRecording() const { return video_recorder_ != nullptr; }
void ToggleVideoBroadcast(); void ToggleVideoBroadcast();
inline bool videoBroadcastEnabled() const { return video_broadcaster_ != nullptr; }
void ToggleSharedMemory(); void ToggleSharedMemory();
inline bool sharedMemoryEnabled() const { return shm_broadcaster_ != nullptr; }
bool ToggleLoopbackCamera(); bool ToggleLoopbackCamera();
inline bool loopbackCameraEnabled() const { return loopback_broadcaster_!= nullptr; }
void Render(); void Render();
void setVisible(bool on); void setVisible(bool on);

View File

@@ -516,8 +516,11 @@ void VideoRecorder::terminate()
Settings::application.recentRecordings.remove(filename_); Settings::application.recentRecordings.remove(filename_);
} }
std::string VideoRecorder::info() const std::string VideoRecorder::info(bool extended) const
{ {
if (extended)
return filename();
if (initialized_ && !active_ && !endofstream_) if (initialized_ && !active_ && !endofstream_)
return "Saving file..."; return "Saving file...";

View File

@@ -20,6 +20,8 @@ public:
PNGRecorder(const std::string &basename = std::string()); PNGRecorder(const std::string &basename = std::string());
std::string filename() const { return filename_; } std::string filename() const { return filename_; }
FrameGrabber::Type type () const override { return FrameGrabber::GRABBER_PNG; }
protected: protected:
std::string init(GstCaps *caps) override; std::string init(GstCaps *caps) override;
@@ -60,7 +62,9 @@ public:
static const int framerate_preset_value[3]; static const int framerate_preset_value[3];
VideoRecorder(const std::string &basename = std::string()); VideoRecorder(const std::string &basename = std::string());
std::string info() const override; FrameGrabber::Type type () const override { return FrameGrabber::GRABBER_VIDEO; }
std::string info(bool extended = false) const override;
std::string filename() const { return filename_; } std::string filename() const { return filename_; }
}; };

View File

@@ -203,16 +203,21 @@ std::string ShmdataBroadcast::gst_pipeline() const
return pipeline; return pipeline;
} }
std::string ShmdataBroadcast::info() const std::string ShmdataBroadcast::info(bool extended) const
{ {
std::ostringstream ret; std::ostringstream ret;
if (!initialized_) if (extended) {
ret << "Shared Memory starting.."; ret << gst_pipeline();
else if (active_) }
ret << "Shared Memory " << socket_path_; else {
else if (!initialized_)
ret << "Shared Memory terminated"; ret << "Shared Memory starting..";
else if (active_)
ret << "Shared Memory " << socket_path_;
else
ret << "Shared Memory terminated";
}
return ret.str(); return ret.str();
} }

View File

@@ -19,13 +19,15 @@ public:
ShmdataBroadcast(Method m = SHM_SHMSINK, const std::string &socketpath = ""); ShmdataBroadcast(Method m = SHM_SHMSINK, const std::string &socketpath = "");
virtual ~ShmdataBroadcast() {} virtual ~ShmdataBroadcast() {}
FrameGrabber::Type type () const override { return FrameGrabber::GRABBER_SHM; }
static bool available(Method m = SHM_SHMDATAANY); static bool available(Method m = SHM_SHMDATAANY);
inline Method method() const { return method_; } inline Method method() const { return method_; }
inline std::string socket_path() const { return socket_path_; } inline std::string socket_path() const { return socket_path_; }
std::string gst_pipeline() const; std::string gst_pipeline() const;
std::string info() const override; std::string info(bool extended = false) const override;
private: private:
std::string init(GstCaps *caps) override; std::string init(GstCaps *caps) override;

View File

@@ -516,17 +516,24 @@ void VideoStreamer::stop ()
active_ = false; active_ = false;
} }
std::string VideoStreamer::info() const std::string VideoStreamer::info(bool extended) const
{ {
std::ostringstream ret; std::ostringstream ret;
if (!initialized_)
ret << "Connecting"; if (extended) {
else if (active_) { ret << NetworkToolkit::stream_send_pipeline[config_.protocol];
ret << NetworkToolkit::stream_protocol_label[config_.protocol];
ret << " to ";
ret << config_.client_name;
} }
else else {
ret << "Streaming terminated."; if (!initialized_)
ret << "Connecting";
else if (active_) {
ret << NetworkToolkit::stream_protocol_label[config_.protocol];
ret << " to ";
ret << config_.client_name;
}
else
ret << "Streaming terminated.";
}
return ret.str(); return ret.str();
} }

View File

@@ -81,7 +81,9 @@ public:
VideoStreamer(const NetworkToolkit::StreamConfig &conf); VideoStreamer(const NetworkToolkit::StreamConfig &conf);
virtual ~VideoStreamer() {} virtual ~VideoStreamer() {}
std::string info() const override;
FrameGrabber::Type type () const override { return FrameGrabber::GRABBER_P2P; }
std::string info(bool extended = false) const override;
}; };

View File

@@ -29,6 +29,7 @@
#include "Log.h" #include "Log.h"
#include "GstToolkit.h" #include "GstToolkit.h"
#include "NetworkToolkit.h"
#include "Settings.h" #include "Settings.h"
#include "VideoBroadcast.h" #include "VideoBroadcast.h"
@@ -210,16 +211,24 @@ void VideoBroadcast::stop ()
active_ = false; active_ = false;
} }
std::string VideoBroadcast::info() const std::string VideoBroadcast::info(bool extended) const
{ {
std::ostringstream ret; std::ostringstream ret;
if (!initialized_) if (extended) {
ret << "SRT starting.."; ret << "srt://";
else if (active_) ret << NetworkToolkit::host_ips()[1];
ret << "SRT Broadcast on port " << port_; ret << ":";
else ret << port_;
ret << "SRT terminated"; }
else {
if (!initialized_)
ret << "SRT starting..";
else if (active_)
ret << "SRT Broadcast on port " << port_;
else
ret << "SRT terminated";
}
return ret.str(); return ret.str();
} }

View File

@@ -14,11 +14,13 @@ public:
VideoBroadcast(int port = BROADCAST_DEFAULT_PORT); VideoBroadcast(int port = BROADCAST_DEFAULT_PORT);
virtual ~VideoBroadcast() {} virtual ~VideoBroadcast() {}
FrameGrabber::Type type () const override { return FrameGrabber::GRABBER_BROADCAST; }
static bool available(); static bool available();
inline int port() const { return port_; } inline int port() const { return port_; }
void stop() override; void stop() override;
std::string info() const override; std::string info(bool extended = false) const override;
private: private:
std::string init(GstCaps *caps) override; std::string init(GstCaps *caps) override;