mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-05 15:30:00 +01:00
Implement broadcast manager functionality and enhance FrameGrabber info and type methods
This commit is contained in:
@@ -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());
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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...";
|
||||||
|
|
||||||
|
|||||||
@@ -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_; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user