mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-11 18:34:58 +01:00
Fixed issue of low quality stream in JPEG: new default to RGB RAW RTP stream
Backward compatibility through menu un stream output view (allow selecting JPEG)
This commit is contained in:
@@ -261,22 +261,34 @@ void NetworkStream::update()
|
|||||||
// general case : create pipeline and open
|
// general case : create pipeline and open
|
||||||
if (!failed_) {
|
if (!failed_) {
|
||||||
// build the pipeline depending on stream info
|
// build the pipeline depending on stream info
|
||||||
std::ostringstream pipeline;
|
|
||||||
// get generic pipeline string
|
|
||||||
std::string pipelinestring = NetworkToolkit::protocol_receive_pipeline[config_.protocol];
|
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
|
// open the pipeline with generic stream class
|
||||||
Stream::open(pipeline.str(), config_.width, config_.height);
|
Stream::open(pipelinestring, config_.width, config_.height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -78,32 +78,42 @@
|
|||||||
* RCV
|
* 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
|
* 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] = {
|
const char* NetworkToolkit::protocol_name[NetworkToolkit::DEFAULT] = {
|
||||||
"Shared Memory",
|
"RGB Stream",
|
||||||
"RTP JPEG Stream",
|
"JPEG Stream",
|
||||||
"RTP H264 Stream",
|
"H264 Stream",
|
||||||
"RTP JPEG Broadcast",
|
"JPEG Broadcast",
|
||||||
"RTP H264 Broadcast"
|
"H264 Broadcast",
|
||||||
|
"RGB Shared Memory"
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::vector<std::string> NetworkToolkit::protocol_send_pipeline {
|
const std::vector<std::string> 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=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 idct-method=float ! rtpjpegpay ! 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=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 ! 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<std::string> NetworkToolkit::protocol_receive_pipeline {
|
const std::vector<std::string> 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",
|
"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;
|
bool initialized_ = false;
|
||||||
|
|||||||
@@ -23,11 +23,12 @@ namespace NetworkToolkit
|
|||||||
{
|
{
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SHM_RAW = 0,
|
UDP_RAW = 0,
|
||||||
UDP_JPEG,
|
UDP_JPEG,
|
||||||
UDP_H264,
|
UDP_H264,
|
||||||
TCP_JPEG,
|
TCP_JPEG,
|
||||||
TCP_H264,
|
TCP_H264,
|
||||||
|
SHM_RAW,
|
||||||
DEFAULT
|
DEFAULT
|
||||||
} Protocol;
|
} Protocol;
|
||||||
|
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ void Settings::Save(uint64_t runtime)
|
|||||||
applicationNode->SetAttribute("show_tooptips", application.show_tooptips);
|
applicationNode->SetAttribute("show_tooptips", application.show_tooptips);
|
||||||
applicationNode->SetAttribute("accept_connections", application.accept_connections);
|
applicationNode->SetAttribute("accept_connections", application.accept_connections);
|
||||||
applicationNode->SetAttribute("pannel_history_mode", application.pannel_current_session_mode);
|
applicationNode->SetAttribute("pannel_history_mode", application.pannel_current_session_mode);
|
||||||
|
applicationNode->SetAttribute("stream_protocol", application.stream_protocol);
|
||||||
pRoot->InsertEndChild(applicationNode);
|
pRoot->InsertEndChild(applicationNode);
|
||||||
|
|
||||||
// Widgets
|
// Widgets
|
||||||
@@ -354,6 +355,7 @@ void Settings::Load()
|
|||||||
applicationNode->QueryBoolAttribute("show_tooptips", &application.show_tooptips);
|
applicationNode->QueryBoolAttribute("show_tooptips", &application.show_tooptips);
|
||||||
applicationNode->QueryBoolAttribute("accept_connections", &application.accept_connections);
|
applicationNode->QueryBoolAttribute("accept_connections", &application.accept_connections);
|
||||||
applicationNode->QueryIntAttribute("pannel_history_mode", &application.pannel_current_session_mode);
|
applicationNode->QueryIntAttribute("pannel_history_mode", &application.pannel_current_session_mode);
|
||||||
|
applicationNode->QueryIntAttribute("stream_protocol", &application.stream_protocol);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Widgets
|
// Widgets
|
||||||
|
|||||||
@@ -242,6 +242,7 @@ struct Application
|
|||||||
|
|
||||||
// settings exporters
|
// settings exporters
|
||||||
RecordConfig record;
|
RecordConfig record;
|
||||||
|
int stream_protocol;
|
||||||
|
|
||||||
// settings new source
|
// settings new source
|
||||||
SourceConfig source;
|
SourceConfig source;
|
||||||
@@ -279,6 +280,7 @@ struct Application
|
|||||||
current_view = 1;
|
current_view = 1;
|
||||||
current_workspace= 1;
|
current_workspace= 1;
|
||||||
brush = glm::vec3(0.5f, 0.1f, 0.f);
|
brush = glm::vec3(0.5f, 0.1f, 0.f);
|
||||||
|
stream_protocol = 0;
|
||||||
windows = std::vector<WindowConfig>(3);
|
windows = std::vector<WindowConfig>(3);
|
||||||
windows[0].name = APP_TITLE;
|
windows[0].name = APP_TITLE;
|
||||||
windows[0].w = 1600;
|
windows[0].w = 1600;
|
||||||
|
|||||||
29
Streamer.cpp
29
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.width = FrameGrabbing::manager().width();
|
||||||
conf.height = FrameGrabbing::manager().height();
|
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)
|
// TODO : ideal would be Shared Memory, but does not work with linux snap package...
|
||||||
// if( NetworkToolkit::is_host_ip(conf.client_address) )
|
// // offer SHM stream if same IP that our host IP (i.e. on the same machine)
|
||||||
// conf.protocol = NetworkToolkit::SHM_RAW;
|
// if( conf.protocol == NetworkToolkit::UDP_RAW && NetworkToolkit::is_host_ip(conf.client_address) )
|
||||||
// // any other IP : offer network streaming
|
// conf.protocol = NetworkToolkit::SHM_RAW;
|
||||||
// else
|
|
||||||
conf.protocol = NetworkToolkit::UDP_JPEG;
|
|
||||||
|
|
||||||
// build OSC message
|
// build OSC message
|
||||||
char buffer[IP_MTU_SIZE];
|
char buffer[IP_MTU_SIZE];
|
||||||
@@ -330,7 +331,7 @@ std::string VideoStreamer::init(GstCaps *caps)
|
|||||||
|
|
||||||
// prevent eroneous protocol values
|
// prevent eroneous protocol values
|
||||||
if (config_.protocol < 0 || config_.protocol >= NetworkToolkit::DEFAULT)
|
if (config_.protocol < 0 || config_.protocol >= NetworkToolkit::DEFAULT)
|
||||||
config_.protocol = NetworkToolkit::UDP_JPEG;
|
config_.protocol = NetworkToolkit::UDP_RAW;
|
||||||
|
|
||||||
// create a gstreamer pipeline
|
// create a gstreamer pipeline
|
||||||
std::string description = "appsrc name=src ! videoconvert ! ";
|
std::string description = "appsrc name=src ! videoconvert ! ";
|
||||||
@@ -346,17 +347,17 @@ std::string VideoStreamer::init(GstCaps *caps)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// setup streaming sink
|
// setup streaming sink
|
||||||
if (config_.protocol == NetworkToolkit::UDP_JPEG || config_.protocol == NetworkToolkit::UDP_H264) {
|
if (config_.protocol == NetworkToolkit::SHM_RAW) {
|
||||||
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) {
|
|
||||||
std::string path = SystemToolkit::full_filename(SystemToolkit::temp_path(), "shm");
|
std::string path = SystemToolkit::full_filename(SystemToolkit::temp_path(), "shm");
|
||||||
path += std::to_string(config_.port);
|
path += std::to_string(config_.port);
|
||||||
g_object_set (G_OBJECT (gst_bin_get_by_name (GST_BIN (pipeline_), "sink")),
|
g_object_set (G_OBJECT (gst_bin_get_by_name (GST_BIN (pipeline_), "sink")),
|
||||||
"socket-path", path.c_str(), NULL);
|
"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
|
// setup custom app source
|
||||||
src_ = GST_APP_SRC( gst_bin_get_by_name (GST_BIN (pipeline_), "src") );
|
src_ = GST_APP_SRC( gst_bin_get_by_name (GST_BIN (pipeline_), "src") );
|
||||||
|
|||||||
@@ -1449,10 +1449,15 @@ void UserInterface::RenderPreview()
|
|||||||
ImGui::PopStyleColor(1);
|
ImGui::PopStyleColor(1);
|
||||||
if (Settings::application.accept_connections)
|
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];
|
static char dummy_str[512];
|
||||||
sprintf(dummy_str, "%s", Connection::manager().info().name.c_str());
|
sprintf(dummy_str, "%s", Connection::manager().info().name.c_str());
|
||||||
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
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::InputText("My ID", dummy_str, IM_ARRAYSIZE(dummy_str), ImGuiInputTextFlags_ReadOnly);
|
||||||
|
ImGui::PopStyleColor(1);
|
||||||
|
|
||||||
std::vector<std::string> ls = Streaming::manager().listStreams();
|
std::vector<std::string> ls = Streaming::manager().listStreams();
|
||||||
if (ls.size()>0) {
|
if (ls.size()>0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user