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:
Bruno Herbelin
2021-12-29 14:37:56 +01:00
parent ff48877d16
commit 76a2535da3
7 changed files with 73 additions and 40 deletions

View File

@@ -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 {

View File

@@ -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<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=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<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",
"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;

View File

@@ -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;

View File

@@ -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

View File

@@ -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<WindowConfig>(3);
windows[0].name = APP_TITLE;
windows[0].w = 1600;

View File

@@ -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") );

View File

@@ -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<std::string> ls = Streaming::manager().listStreams();
if (ls.size()>0) {