diff --git a/NetworkSource.cpp b/NetworkSource.cpp index 15afec1..8109e09 100644 --- a/NetworkSource.cpp +++ b/NetworkSource.cpp @@ -261,22 +261,34 @@ void NetworkStream::update() // general case : create pipeline and open if (!failed_) { // build the pipeline depending on stream info - std::ostringstream pipeline; - // get generic pipeline string std::string pipelinestring = NetworkToolkit::protocol_receive_pipeline[config_.protocol]; - // find placeholder for PORT - int xxxx = pipelinestring.find("XXXX"); - // keep beginning of pipeline - pipeline << pipelinestring.substr(0, xxxx); - // Replace 'XXXX' by info on port config - pipeline << parameter; - // keep ending of pipeline - pipeline << pipelinestring.substr(xxxx + 4); - // add a videoconverter - pipeline << " ! videoconvert"; + // find placeholder for PORT or SHH socket + size_t xxxx = pipelinestring.find("XXXX"); + if (xxxx != std::string::npos) + // Replace 'XXXX' by info on port config + pipelinestring.replace(xxxx, 4, parameter); + + // find placeholder for WIDTH + size_t wwww = pipelinestring.find("WWWW"); + if (wwww != std::string::npos) + // Replace 'WWWW' by width + pipelinestring.replace(wwww, 4, std::to_string(config_.width) ); + + // find placeholder for HEIGHT + size_t hhhh = pipelinestring.find("HHHH"); + if (hhhh != std::string::npos) + // Replace 'WWWW' by height + pipelinestring.replace(hhhh, 4, std::to_string(config_.height) ); + + // add a videoconverter + pipelinestring.append(" ! videoconvert "); + +#ifdef NETWORK_DEBUG + Log::Info("Openning pipeline %s", pipelinestring.c_str()); +#endif // open the pipeline with generic stream class - Stream::open(pipeline.str(), config_.width, config_.height); + Stream::open(pipelinestring, config_.width, config_.height); } } else { diff --git a/NetworkToolkit.cpp b/NetworkToolkit.cpp index 14fc246..577638f 100644 --- a/NetworkToolkit.cpp +++ b/NetworkToolkit.cpp @@ -78,32 +78,42 @@ * RCV * gst-launch-1.0 shmsrc is-live=true socket-path=/tmp/blah ! video/x-raw, format=RGB, framerate=30/1, width=320, height=240 ! videoconvert ! autovideosink * + * RTP UDP JPEG + * + * SND + * gst-launch-1.0 videotestsrc is-live=true ! video/x-raw, format=RGB, framerate=30/1 ! videoconvert ! video/x-raw, format=I420 ! jpegenc quality=95 ! rtpjpegpay ! udpsink port=5000 host=127.0.0 + * RCV + * gst-launch-1.0 udpsrc buffer-size=200000 port=5000 ! application/x-rtp,encoding-name=JPEG ! rtpjpegdepay ! queue max-size-buffers=10 ! jpegdec ! videoconvert ! video/x-raw, format=RGB ! autovideosink + * * */ const char* NetworkToolkit::protocol_name[NetworkToolkit::DEFAULT] = { - "Shared Memory", - "RTP JPEG Stream", - "RTP H264 Stream", - "RTP JPEG Broadcast", - "RTP H264 Broadcast" + "RGB Stream", + "JPEG Stream", + "H264 Stream", + "JPEG Broadcast", + "H264 Broadcast", + "RGB Shared Memory" }; const std::vector NetworkToolkit::protocol_send_pipeline { - "video/x-raw, format=RGB, framerate=30/1 ! queue max-size-buffers=10 ! shmsink buffer-time=100000 wait-for-connection=true name=sink", - "video/x-raw, format=I420, framerate=30/1 ! queue max-size-buffers=10 ! jpegenc idct-method=float ! rtpjpegpay ! udpsink name=sink", + "video/x-raw, format=RGB, framerate=30/1 ! queue max-size-buffers=3 ! rtpvrawpay ! application/x-rtp,sampling=RGB ! udpsink name=sink", + "video/x-raw, format=I420, framerate=30/1 ! queue max-size-buffers=10 ! jpegenc quality=95 ! rtpjpegpay ! udpsink name=sink", "video/x-raw, format=I420, framerate=30/1 ! queue max-size-buffers=10 ! x264enc tune=\"zerolatency\" threads=2 ! rtph264pay ! udpsink name=sink", "video/x-raw, format=I420, framerate=30/1 ! queue max-size-buffers=3 ! jpegenc idct-method=float ! rtpjpegpay ! rtpstreampay ! tcpserversink name=sink", - "video/x-raw, format=I420, framerate=30/1 ! queue max-size-buffers=3 ! x264enc tune=\"zerolatency\" threads=2 ! rtph264pay ! rtpstreampay ! tcpserversink name=sink" + "video/x-raw, format=I420, framerate=30/1 ! queue max-size-buffers=3 ! x264enc tune=\"zerolatency\" threads=2 ! rtph264pay ! rtpstreampay ! tcpserversink name=sink", + "video/x-raw, format=RGB, framerate=30/1 ! queue max-size-buffers=10 ! shmsink buffer-time=100000 wait-for-connection=true name=sink" }; const std::vector NetworkToolkit::protocol_receive_pipeline { + "udpsrc buffer-size=200000 port=XXXX caps=\"application/x-rtp,media=(string)video,encoding-name=(string)RAW,sampling=(string)RGB,width=(string)WWWW,height=(string)HHHH\" ! rtpvrawdepay ! queue max-size-buffers=10", + "udpsrc buffer-size=200000 port=XXXX ! application/x-rtp,encoding-name=JPEG ! rtpjpegdepay ! queue max-size-buffers=10 ! jpegdec", + "udpsrc buffer-size=200000 port=XXXX ! application/x-rtp,encoding-name=H264 ! rtph264depay ! queue max-size-buffers=10 ! avdec_h264", + "tcpclientsrc timeout=1 port=XXXX ! queue max-size-buffers=30 ! application/x-rtp-stream,media=video,encoding-name=JPEG ! rtpstreamdepay ! rtpjpegdepay ! jpegdec", + "tcpclientsrc timeout=1 port=XXXX ! queue max-size-buffers=30 ! application/x-rtp-stream,media=video,encoding-name=H264 ! rtpstreamdepay ! rtph264depay ! avdec_h264", "shmsrc socket-path=XXXX ! video/x-raw, format=RGB, framerate=30/1 ! queue max-size-buffers=10", - "udpsrc buffer-size=200000 port=XXXX ! application/x-rtp,encoding-name=JPEG,payload=26,clock-rate=90000 ! queue max-size-buffers=10 ! rtpjpegdepay ! jpegdec", - "udpsrc buffer-size=200000 port=XXXX ! application/x-rtp,encoding-name=H264,payload=96,clock-rate=90000 ! queue ! rtph264depay ! avdec_h264", - "tcpclientsrc timeout=1 port=XXXX ! queue max-size-buffers=30 ! application/x-rtp-stream,media=video,encoding-name=JPEG,payload=26,clock-rate=90000 ! rtpstreamdepay ! rtpjpegdepay ! jpegdec", - "tcpclientsrc timeout=1 port=XXXX ! queue max-size-buffers=30 ! application/x-rtp-stream,media=video,encoding-name=H264,payload=96,clock-rate=90000 ! rtpstreamdepay ! rtph264depay ! avdec_h264" }; bool initialized_ = false; diff --git a/NetworkToolkit.h b/NetworkToolkit.h index 96f4483..9cabbc9 100644 --- a/NetworkToolkit.h +++ b/NetworkToolkit.h @@ -23,11 +23,12 @@ namespace NetworkToolkit { typedef enum { - SHM_RAW = 0, + UDP_RAW = 0, UDP_JPEG, UDP_H264, TCP_JPEG, TCP_H264, + SHM_RAW, DEFAULT } Protocol; diff --git a/Settings.cpp b/Settings.cpp index a88db61..dada34c 100644 --- a/Settings.cpp +++ b/Settings.cpp @@ -110,6 +110,7 @@ void Settings::Save(uint64_t runtime) applicationNode->SetAttribute("show_tooptips", application.show_tooptips); applicationNode->SetAttribute("accept_connections", application.accept_connections); applicationNode->SetAttribute("pannel_history_mode", application.pannel_current_session_mode); + applicationNode->SetAttribute("stream_protocol", application.stream_protocol); pRoot->InsertEndChild(applicationNode); // Widgets @@ -354,6 +355,7 @@ void Settings::Load() applicationNode->QueryBoolAttribute("show_tooptips", &application.show_tooptips); applicationNode->QueryBoolAttribute("accept_connections", &application.accept_connections); applicationNode->QueryIntAttribute("pannel_history_mode", &application.pannel_current_session_mode); + applicationNode->QueryIntAttribute("stream_protocol", &application.stream_protocol); } // Widgets diff --git a/Settings.h b/Settings.h index b66f4a6..075c52b 100644 --- a/Settings.h +++ b/Settings.h @@ -242,6 +242,7 @@ struct Application // settings exporters RecordConfig record; + int stream_protocol; // settings new source SourceConfig source; @@ -279,6 +280,7 @@ struct Application current_view = 1; current_workspace= 1; brush = glm::vec3(0.5f, 0.1f, 0.f); + stream_protocol = 0; windows = std::vector(3); windows[0].name = APP_TITLE; windows[0].w = 1600; diff --git a/Streamer.cpp b/Streamer.cpp index 4c1c71e..0663d30 100644 --- a/Streamer.cpp +++ b/Streamer.cpp @@ -267,14 +267,15 @@ void Streaming::addStream(const std::string &sender, int reply_to, const std::st conf.width = FrameGrabbing::manager().width(); conf.height = FrameGrabbing::manager().height(); - // TEMP DISABLED : TODO Fix snap to allow system wide shared access + // set protocol according to settings + conf.protocol = NetworkToolkit::UDP_RAW; + if (Settings::application.stream_protocol >= 0 && Settings::application.stream_protocol < NetworkToolkit::DEFAULT) + conf.protocol = (NetworkToolkit::Protocol) Settings::application.stream_protocol; - // offer SHM if same IP that our host IP (i.e. on the same machine) - // if( NetworkToolkit::is_host_ip(conf.client_address) ) - // conf.protocol = NetworkToolkit::SHM_RAW; - // // any other IP : offer network streaming - // else - conf.protocol = NetworkToolkit::UDP_JPEG; +// TODO : ideal would be Shared Memory, but does not work with linux snap package... +// // offer SHM stream if same IP that our host IP (i.e. on the same machine) +// if( conf.protocol == NetworkToolkit::UDP_RAW && NetworkToolkit::is_host_ip(conf.client_address) ) +// conf.protocol = NetworkToolkit::SHM_RAW; // build OSC message char buffer[IP_MTU_SIZE]; @@ -330,7 +331,7 @@ std::string VideoStreamer::init(GstCaps *caps) // prevent eroneous protocol values if (config_.protocol < 0 || config_.protocol >= NetworkToolkit::DEFAULT) - config_.protocol = NetworkToolkit::UDP_JPEG; + config_.protocol = NetworkToolkit::UDP_RAW; // create a gstreamer pipeline std::string description = "appsrc name=src ! videoconvert ! "; @@ -346,17 +347,17 @@ std::string VideoStreamer::init(GstCaps *caps) } // setup streaming sink - if (config_.protocol == NetworkToolkit::UDP_JPEG || config_.protocol == NetworkToolkit::UDP_H264) { - g_object_set (G_OBJECT (gst_bin_get_by_name (GST_BIN (pipeline_), "sink")), - "host", config_.client_address.c_str(), - "port", config_.port, NULL); - } - else if (config_.protocol == NetworkToolkit::SHM_RAW) { + if (config_.protocol == NetworkToolkit::SHM_RAW) { std::string path = SystemToolkit::full_filename(SystemToolkit::temp_path(), "shm"); path += std::to_string(config_.port); g_object_set (G_OBJECT (gst_bin_get_by_name (GST_BIN (pipeline_), "sink")), "socket-path", path.c_str(), NULL); } + else { + g_object_set (G_OBJECT (gst_bin_get_by_name (GST_BIN (pipeline_), "sink")), + "host", config_.client_address.c_str(), + "port", config_.port, NULL); + } // setup custom app source src_ = GST_APP_SRC( gst_bin_get_by_name (GST_BIN (pipeline_), "src") ); diff --git a/UserInterfaceManager.cpp b/UserInterfaceManager.cpp index c4c8b4d..d83d365 100644 --- a/UserInterfaceManager.cpp +++ b/UserInterfaceManager.cpp @@ -1449,10 +1449,15 @@ void UserInterface::RenderPreview() ImGui::PopStyleColor(1); if (Settings::application.accept_connections) { + ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); + ImGui::Combo("Format", &Settings::application.stream_protocol, NetworkToolkit::protocol_name, 3); + static char dummy_str[512]; sprintf(dummy_str, "%s", Connection::manager().info().name.c_str()); ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); + ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.14f, 0.14f, 0.14f, 0.9f)); ImGui::InputText("My ID", dummy_str, IM_ARRAYSIZE(dummy_str), ImGuiInputTextFlags_ReadOnly); + ImGui::PopStyleColor(1); std::vector ls = Streaming::manager().listStreams(); if (ls.size()>0) {