mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-15 12:20:01 +01:00
Integration of Shmdata in vimix
Unified menu in output window for streaming (for SRT, Shmdata and peer to peer). Cleanup SRT broadcaster and bugfix on FrameGrabber default frame timing.
This commit is contained in:
@@ -270,7 +270,7 @@ void FrameGrabbing::grabFrame(FrameBuffer *frame_buffer)
|
||||
|
||||
FrameGrabber::FrameGrabber(): finished_(false), initialized_(false), active_(false), endofstream_(false), accept_buffer_(false), buffering_full_(false),
|
||||
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_(true)
|
||||
{
|
||||
// unique id
|
||||
id_ = BaseToolkit::uniqueId();
|
||||
|
||||
@@ -231,10 +231,15 @@ bool Rendering::init()
|
||||
g_setenv ("GST_PLUGIN_SCANNER", plugins_scanner.c_str(), TRUE);
|
||||
}
|
||||
|
||||
std::string plugins_path;
|
||||
const gchar *c = g_getenv("GST_PLUGIN_PATH");
|
||||
std::string plugins_path = c != NULL ? std::string(c) : "";
|
||||
|
||||
std::string local_plugin_path = SystemToolkit::cwd_path() + "gstreamer-1.0";
|
||||
if ( SystemToolkit::file_exists(local_plugin_path))
|
||||
plugins_path = local_plugin_path;
|
||||
if ( SystemToolkit::file_exists(local_plugin_path)){
|
||||
if (!plugins_path.empty())
|
||||
plugins_path += ":";
|
||||
plugins_path += local_plugin_path;
|
||||
}
|
||||
|
||||
#ifdef GSTREAMER_SHMDATA_PLUGIN
|
||||
std::string shmdata_plugin_path = GSTREAMER_SHMDATA_PLUGIN;
|
||||
|
||||
@@ -95,6 +95,7 @@ using namespace std;
|
||||
#include "ImageProcessingShader.h"
|
||||
#include "Metronome.h"
|
||||
#include "VideoBroadcast.h"
|
||||
#include "ShmdataBroadcast.h"
|
||||
#include "MultiFileRecorder.h"
|
||||
|
||||
#include "TextEditor.h"
|
||||
@@ -3863,12 +3864,13 @@ void OutputPreview::Update()
|
||||
video_recorder_->stop();
|
||||
}
|
||||
|
||||
// verify the video broadcaster is valid (change to nullptr if invalid)
|
||||
// verify the broadcasters are valid (change to nullptr if invalid)
|
||||
FrameGrabbing::manager().verify( (FrameGrabber**) &video_broadcaster_);
|
||||
FrameGrabbing::manager().verify( (FrameGrabber**) &shm_broadcaster_);
|
||||
|
||||
#if defined(LINUX)
|
||||
// verify the frame grabber for webcam emulator is valid
|
||||
FrameGrabbing::manager().verify(&webcam_emulator_);
|
||||
FrameGrabbing::manager().verify( (FrameGrabber**) &webcam_emulator_);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -3911,6 +3913,17 @@ void OutputPreview::ToggleBroadcast()
|
||||
}
|
||||
}
|
||||
|
||||
void OutputPreview::ToggleSharedMemory()
|
||||
{
|
||||
if (shm_broadcaster_) {
|
||||
shm_broadcaster_->stop();
|
||||
}
|
||||
else {
|
||||
shm_broadcaster_ = new ShmdataBroadcast;
|
||||
FrameGrabbing::manager().add(shm_broadcaster_);
|
||||
}
|
||||
}
|
||||
|
||||
void OutputPreview::Render()
|
||||
{
|
||||
|
||||
@@ -4096,41 +4109,69 @@ void OutputPreview::Render()
|
||||
}
|
||||
#endif
|
||||
|
||||
if (VideoBroadcast::available()) {
|
||||
// Broadcasting menu
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_BROADCAST, 0.8f));
|
||||
// Stop broadcast menu (broadcaster already exists)
|
||||
if (video_broadcaster_) {
|
||||
if ( ImGui::MenuItem( ICON_FA_SQUARE " Stop Broadcast SRT") )
|
||||
video_broadcaster_->stop();
|
||||
}
|
||||
// start broadcast (broadcaster does not exists)
|
||||
else {
|
||||
if ( ImGui::MenuItem( ICON_FA_PODCAST " Broadcast SRT") ) {
|
||||
video_broadcaster_ = new VideoBroadcast(Settings::application.broadcast_port);
|
||||
FrameGrabbing::manager().add(video_broadcaster_);
|
||||
}
|
||||
}
|
||||
ImGui::PopStyleColor(1);
|
||||
}
|
||||
|
||||
// Stream sharing menu
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_STREAM, 0.9f));
|
||||
if ( ImGui::MenuItem( ICON_FA_SHARE_ALT_SQUARE " Peer-to-peer sharing", NULL, &Settings::application.accept_connections) ) {
|
||||
if ( ImGui::MenuItem( ICON_FA_SHARE_ALT_SQUARE " Peer-to-peer sharing", NULL, &Settings::application.accept_connections) ) {
|
||||
Streaming::manager().enable(Settings::application.accept_connections);
|
||||
}
|
||||
ImGui::PopStyleColor(1);
|
||||
if (Settings::application.accept_connections)
|
||||
{
|
||||
std::vector<std::string> ls = Streaming::manager().listStreams();
|
||||
if (ls.size()>0) {
|
||||
ImGui::Separator();
|
||||
ImGui::MenuItem("Connected peers", nullptr, false, false);
|
||||
for (auto it = ls.begin(); it != ls.end(); ++it)
|
||||
ImGui::Text(" %s", (*it).c_str() );
|
||||
|
||||
// list active streams:
|
||||
std::vector<std::string> ls = Streaming::manager().listStreams();
|
||||
|
||||
|
||||
// Broadcasting menu
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_BROADCAST, 0.9f));
|
||||
if (VideoBroadcast::available()) {
|
||||
bool enabled = (video_broadcaster_!=nullptr);
|
||||
if ( ImGui::MenuItem( ICON_FA_PODCAST " SRT Broadcast", NULL, &enabled) )
|
||||
ToggleBroadcast();
|
||||
}
|
||||
|
||||
// Shared Memory menu
|
||||
if (ShmdataBroadcast::available()) {
|
||||
bool enabled = (shm_broadcaster_!=nullptr);
|
||||
if ( ImGui::MenuItem( ICON_FA_PROJECT_DIAGRAM " Shared Memory", NULL, &enabled) )
|
||||
ToggleSharedMemory();
|
||||
}
|
||||
ImGui::PopStyleColor(1);
|
||||
|
||||
// Display list of active stream
|
||||
if (ls.size()>0 || video_broadcaster_ || shm_broadcaster_) {
|
||||
ImGui::Separator();
|
||||
ImGui::MenuItem("Active streaming", nullptr, false, false);
|
||||
|
||||
// First the list of peer 2 peer
|
||||
for (auto it = ls.begin(); it != ls.end(); ++it)
|
||||
ImGui::Text(" %s ", (*it).c_str() );
|
||||
|
||||
// Second the SRT
|
||||
if (video_broadcaster_) {
|
||||
ImGui::Text(" %s ", video_broadcaster_->info().c_str());
|
||||
|
||||
// copy text icon to give user the srt link to connect to
|
||||
ImVec2 draw_pos = ImGui::GetCursorPos();
|
||||
ImGui::SetCursorPos(draw_pos + ImVec2(ImGui::GetContentRegionAvailWidth() - 1.2 * ImGui::GetTextLineHeightWithSpacing(), -0.8 * ImGui::GetFrameHeight()) );
|
||||
char msg[256];
|
||||
ImFormatString(msg, IM_ARRAYSIZE(msg), "srt//%s:%d", NetworkToolkit::host_ips()[1].c_str(), Settings::application.broadcast_port );
|
||||
if (ImGuiToolkit::IconButton( ICON_FA_COPY, msg))
|
||||
ImGui::SetClipboardText(msg);
|
||||
ImGui::SetCursorPos(draw_pos);
|
||||
}
|
||||
|
||||
// Third the SHMdata
|
||||
if (shm_broadcaster_) {
|
||||
ImGui::Text(" %s ", shm_broadcaster_->info().c_str());
|
||||
|
||||
// copy text icon to give user the socket path to connec to
|
||||
ImVec2 draw_pos = ImGui::GetCursorPos();
|
||||
ImGui::SetCursorPos(draw_pos + ImVec2(ImGui::GetContentRegionAvailWidth() - 1.2 * ImGui::GetTextLineHeightWithSpacing(), -0.8 * ImGui::GetFrameHeight()) );
|
||||
if (ImGuiToolkit::IconButton( ICON_FA_COPY, shm_broadcaster_->socket_path().c_str()))
|
||||
ImGui::SetClipboardText(shm_broadcaster_->socket_path().c_str());
|
||||
ImGui::SetCursorPos(draw_pos);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
ImGui::EndMenuBar();
|
||||
@@ -4194,6 +4235,19 @@ void OutputPreview::Render()
|
||||
ImGui::PopStyleColor(1);
|
||||
ImGui::PopFont();
|
||||
}
|
||||
// shmdata indicator
|
||||
if (shm_broadcaster_)
|
||||
{
|
||||
ImGui::SetCursorScreenPos(ImVec2(draw_pos.x + imagesize.x - 4.5f * r, draw_pos.y + r));
|
||||
ImGuiToolkit::PushFont(ImGuiToolkit::FONT_LARGE);
|
||||
if (shm_broadcaster_->busy())
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_BROADCAST, 0.8f));
|
||||
else
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_BROADCAST, 0.4f));
|
||||
ImGui::Text(ICON_FA_PROJECT_DIAGRAM);
|
||||
ImGui::PopStyleColor(1);
|
||||
ImGui::PopFont();
|
||||
}
|
||||
// streaming indicator
|
||||
if (Settings::application.accept_connections)
|
||||
{
|
||||
@@ -4239,6 +4293,7 @@ void OutputPreview::Render()
|
||||
float h = 1.f;
|
||||
h += (Settings::application.accept_connections ? 1.f : 0.f);
|
||||
h += (video_broadcaster_ ? 1.f : 0.f);
|
||||
h += (shm_broadcaster_ ? 1.f : 0.f);
|
||||
draw_list->AddRectFilled(draw_pos, ImVec2(draw_pos.x + imagesize.x, draw_pos.y + h * r), IMGUI_COLOR_OVERLAY);
|
||||
ImGui::SetCursorScreenPos(draw_pos);
|
||||
ImGui::Text(" " ICON_FA_TV " %d x %d px, %.d fps", output->width(), output->height(), int(Mixer::manager().fps()) );
|
||||
@@ -4248,6 +4303,8 @@ void OutputPreview::Render()
|
||||
Streaming::manager().listStreams().size() );
|
||||
if (video_broadcaster_)
|
||||
ImGui::Text( " " ICON_FA_PODCAST " %s", video_broadcaster_->info().c_str() );
|
||||
if (shm_broadcaster_)
|
||||
ImGui::Text( " " ICON_FA_PROJECT_DIAGRAM " %s", shm_broadcaster_->info().c_str() );
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
@@ -5872,6 +5929,7 @@ void ShaderEditor::Render()
|
||||
{
|
||||
filters_.clear();
|
||||
current_ = nullptr;
|
||||
_editor.SetText("");
|
||||
}
|
||||
|
||||
// if compiling, cannot change source nor do anything else
|
||||
@@ -7800,8 +7858,16 @@ void Navigator::RenderMainPannelSettings()
|
||||
//
|
||||
// Networking preferences
|
||||
//
|
||||
ImGuiToolkit::Spacing();
|
||||
ImGui::Text("Stream");
|
||||
|
||||
ImGuiToolkit::Indication("Peer-to-peer sharing on local network\n\n"
|
||||
"vimix can stream JPEG (default) or H264 (requires less bandwidth but more resources for encoding)", ICON_FA_SHARE_ALT_SQUARE);
|
||||
ImGui::SameLine(0);
|
||||
ImGui::SetCursorPosX(-1.f * IMGUI_RIGHT_ALIGN);
|
||||
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
||||
ImGui::Combo("Share P2P", &Settings::application.stream_protocol, "JPEG\0H264\0");
|
||||
|
||||
if (VideoBroadcast::available()) {
|
||||
char msg[256];
|
||||
ImFormatString(msg, IM_ARRAYSIZE(msg), "Broadcast SRT\n\n"
|
||||
@@ -7819,20 +7885,13 @@ void Navigator::RenderMainPannelSettings()
|
||||
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
||||
char bufport[7] = "";
|
||||
sprintf(bufport, "%d", Settings::application.broadcast_port);
|
||||
ImGui::InputTextWithHint("Broadcast", "7070", bufport, 6, ImGuiInputTextFlags_CharsDecimal);
|
||||
ImGui::InputTextWithHint("Port SRT", "7070", bufport, 6, ImGuiInputTextFlags_CharsDecimal);
|
||||
if (ImGui::IsItemDeactivatedAfterEdit()){
|
||||
if ( BaseToolkit::is_a_number(bufport, &Settings::application.broadcast_port))
|
||||
Settings::application.broadcast_port = CLAMP(Settings::application.broadcast_port, 1029, 49150);
|
||||
}
|
||||
}
|
||||
|
||||
ImGuiToolkit::Indication("Peer-to-peer sharing on local network\n\n"
|
||||
"vimix can stream JPEG (default) or H264 (requires less bandwidth but more resources for encoding)", ICON_FA_SHARE_ALT_SQUARE);
|
||||
ImGui::SameLine(0);
|
||||
ImGui::SetCursorPosX(-1.f * IMGUI_RIGHT_ALIGN);
|
||||
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
||||
ImGui::Combo("P2P Share", &Settings::application.stream_protocol, "JPEG\0H264\0");
|
||||
|
||||
//
|
||||
// OSC preferences
|
||||
//
|
||||
|
||||
@@ -110,6 +110,7 @@ class FrameBufferImage;
|
||||
class FrameGrabber;
|
||||
class VideoRecorder;
|
||||
class VideoBroadcast;
|
||||
class ShmdataBroadcast;
|
||||
|
||||
class SourcePreview {
|
||||
|
||||
@@ -330,6 +331,7 @@ class OutputPreview : public WorkspaceWindow
|
||||
// frame grabbers
|
||||
VideoRecorder *video_recorder_;
|
||||
VideoBroadcast *video_broadcaster_;
|
||||
ShmdataBroadcast *shm_broadcaster_;
|
||||
|
||||
// delayed trigger for recording
|
||||
std::vector< std::future<VideoRecorder *> > _video_recorders;
|
||||
@@ -350,6 +352,9 @@ public:
|
||||
void ToggleBroadcast();
|
||||
inline bool isBroadcasting() const { return video_broadcaster_ != nullptr; }
|
||||
|
||||
void ToggleSharedMemory();
|
||||
inline bool isSharingMemory() const { return shm_broadcaster_ != nullptr; }
|
||||
|
||||
void Render();
|
||||
void setVisible(bool on);
|
||||
|
||||
|
||||
@@ -27,9 +27,9 @@ std::vector< std::pair<std::string, std::string> > pipeline_sink_ {
|
||||
};
|
||||
|
||||
std::vector< std::pair<std::string, std::string> > pipeline_encoder_ {
|
||||
{"nvh264enc", "nvh264enc zerolatency=true rc-mode=cbr-ld-hq bitrate=4000 ! video/x-h264, profile=(string)high ! h264parse config-interval=1 ! mpegtsmux ! queue ! "},
|
||||
{"vaapih264enc", "vaapih264enc rate-control=cqp init-qp=26 ! video/x-h264, profile=high ! h264parse config-interval=1 ! mpegtsmux ! queue ! "},
|
||||
{"x264enc", "x264enc tune=zerolatency ! video/x-h264, profile=high ! mpegtsmux ! "}
|
||||
{"nvh264enc", "nvh264enc zerolatency=true rc-mode=cbr-ld-hq bitrate=4000 ! "},
|
||||
{"vaapih264enc", "vaapih264enc rate-control=cqp init-qp=26 ! "},
|
||||
{"x264enc", "x264enc tune=zerolatency ! "}
|
||||
};
|
||||
|
||||
bool VideoBroadcast::available()
|
||||
@@ -76,18 +76,21 @@ VideoBroadcast::VideoBroadcast(int port): FrameGrabber(), port_(port), stopped_(
|
||||
|
||||
std::string VideoBroadcast::init(GstCaps *caps)
|
||||
{
|
||||
if (!VideoBroadcast::available())
|
||||
return std::string("Video Broadcast : Not available (missing SRT or H264)");
|
||||
|
||||
// ignore
|
||||
if (caps == nullptr)
|
||||
return std::string("Video Broadcast : Invalid caps");
|
||||
|
||||
if (!VideoBroadcast::available())
|
||||
return std::string("Video Broadcast : Not available (missing SRT or H264)");
|
||||
|
||||
// create a gstreamer pipeline
|
||||
std::string description = "appsrc name=src ! videoconvert ! ";
|
||||
|
||||
// complement pipeline with encoder and sink
|
||||
// complement pipeline with encoder
|
||||
description += VideoBroadcast::h264_encoder_;
|
||||
description += "video/x-h264, profile=high ! queue ! h264parse config-interval=-1 ! mpegtsmux ! ";
|
||||
|
||||
// complement pipeline with sink
|
||||
description += VideoBroadcast::srt_sink_;
|
||||
|
||||
// change the placeholder to include the broadcast port
|
||||
@@ -192,11 +195,11 @@ std::string VideoBroadcast::info() const
|
||||
std::ostringstream ret;
|
||||
|
||||
if (!initialized_)
|
||||
ret << "Starting SRT";
|
||||
ret << "SRT starting..";
|
||||
else if (active_)
|
||||
ret << "Broadcasting on SRT (listener mode)";
|
||||
ret << "SRT Broadcast on port " << port_;
|
||||
else
|
||||
ret << "SRT Terminated";
|
||||
ret << "SRT terminated";
|
||||
|
||||
return ret.str();
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
#define IMGUI_COLOR_CAPTURE 1.0, 0.55, 0.05
|
||||
#define IMGUI_COLOR_RECORD 1.0, 0.05, 0.05
|
||||
#define IMGUI_COLOR_STREAM 0.05, 0.8, 1.0
|
||||
#define IMGUI_COLOR_BROADCAST 0.1, 0.9, 0.1
|
||||
#define IMGUI_COLOR_BROADCAST 0.1, 0.5, 1.0
|
||||
#define IMGUI_NOTIFICATION_DURATION 2.5f
|
||||
#define IMGUI_TOOLTIP_TIMEOUT 80
|
||||
|
||||
|
||||
Reference in New Issue
Block a user