feat: enable RTSP path

This commit is contained in:
Ian Chua
2026-08-26 13:53:35 +08:00
parent 167b9fadb5
commit 06a13bae9c
5 changed files with 68 additions and 21 deletions

View File

@@ -155,23 +155,20 @@ CameraStreamMode MediaPlayCtrl::current_mode() const
return agent ? agent->get_camera_stream_mode() : CameraStreamMode::none;
}
bool MediaPlayCtrl::is_web_stream_mode() const
{
const CameraStreamMode mode = current_mode();
return mode == CameraStreamMode::http || mode == CameraStreamMode::http_snapshot;
}
void MediaPlayCtrl::SetMachineObject(MachineObject* obj)
{
if (is_web_stream_mode()) {
switch (current_mode()) {
case CameraStreamMode::http:
case CameraStreamMode::http_snapshot:
case CameraStreamMode::rtsp: {
std::string machine = obj ? obj->get_dev_id() : "";
auto agent = wxGetApp().getAgent();
std::string url = agent ? agent->get_local_camera_stream_url() : "";
m_camera_exists = !url.empty();
Enable(obj && m_camera_exists);
bool changed = machine != m_machine || url != m_http_url;
bool changed = machine != m_machine || url != m_agent_camera_url;
m_machine = machine;
m_http_url = url;
m_agent_camera_url = url;
m_url = from_u8(url);
if (!changed) {
if (m_last_state == MEDIASTATE_IDLE && IsEnabled() && !m_web_user_stopped)
@@ -185,6 +182,9 @@ void MediaPlayCtrl::SetMachineObject(MachineObject* obj)
Play();
return;
}
default:
break;
}
std::string machine = obj ? obj->get_dev_id() : "";
if (obj) {
@@ -294,7 +294,11 @@ void refresh_agora_url(char const* device, char const* dev_ver, char const* chan
void MediaPlayCtrl::Play()
{
if (is_web_stream_mode()) {
switch (current_mode()) {
case CameraStreamMode::http:
case CameraStreamMode::http_snapshot:
if (!m_next_retry.IsValid() || wxDateTime::Now() < m_next_retry)
return;
if (!IsShownOnScreen()) return;
if (m_last_state != MEDIASTATE_IDLE) return;
if (m_machine.empty() || !IsEnabled() || !m_camera_exists || m_url.IsEmpty() || !m_web_ctrl) {
@@ -309,6 +313,21 @@ void MediaPlayCtrl::Play()
m_last_state = wxMEDIASTATE_PLAYING;
SetStatus(_L("Playing..."), false);
return;
case CameraStreamMode::rtsp:
if (m_next_retry.IsValid() && wxDateTime::Now() < m_next_retry)
return;
if (!IsShownOnScreen()) return;
if (m_last_state != MEDIASTATE_IDLE) return;
m_failed_code = 0;
if (m_machine.empty() || !IsEnabled() || !m_camera_exists || m_url.IsEmpty()) {
Stop(_L("Please confirm if the printer is connected."));
return;
}
m_button_play->SetIcon("media_stop");
load();
return;
default:
break;
}
if (!m_next_retry.IsValid() || wxDateTime::Now() < m_next_retry)
@@ -451,7 +470,9 @@ void MediaPlayCtrl::StopWebStream()
void MediaPlayCtrl::Stop(wxString const &msg, wxString const &msg2)
{
if (is_web_stream_mode()) {
switch (current_mode()) {
case CameraStreamMode::http:
case CameraStreamMode::http_snapshot:
if (m_last_state != MEDIASTATE_IDLE) {
if (m_web_ctrl) m_web_ctrl->Stop();
m_button_play->SetIcon("media_play");
@@ -464,6 +485,8 @@ void MediaPlayCtrl::Stop(wxString const &msg, wxString const &msg2)
SetStatus(msg, false);
}
return;
default:
break;
}
int last_state = m_last_state;
@@ -751,7 +774,7 @@ void MediaPlayCtrl::load()
{
m_last_state = MEDIASTATE_LOADING;
SetStatus(_L("Loading..."));
if (wxGetApp().app_config->get("internal_developer_mode") == "true") {
if (current_mode() != CameraStreamMode::rtsp) {
std::string file_h264 = data_dir() + "/video.h264";
std::string file_info = data_dir() + "/video.info";
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl dump video to " << file_h264;

View File

@@ -73,7 +73,6 @@ private:
static bool get_stream_url(std::string *url = nullptr);
CameraStreamMode current_mode() const;
bool is_web_stream_mode() const;
private:
static inline const wxMediaState MEDIASTATE_IDLE = static_cast<wxMediaState>(3);
@@ -86,7 +85,7 @@ private:
wxMediaCtrl2 * m_media_ctrl;
IMediaController * m_web_ctrl = nullptr;
std::string m_http_url;
std::string m_agent_camera_url;
bool m_web_user_stopped = false;
wxMediaState m_last_state = MEDIASTATE_IDLE;
std::string m_machine;

View File

@@ -4,7 +4,16 @@
namespace Slic3r { namespace GUI {
WebMediaController::WebMediaController(wxWebView *webview) : m_webview(webview) {}
WebMediaController::WebMediaController(wxWebView *webview) : m_webview(webview)
{
if (!m_webview)
return;
m_webview->SetBackgroundColour(*wxBLACK);
m_webview->SetPage(
"<html><head><style>html,body{margin:0;height:100%;background:#000;}</style></head><body></body></html>",
"");
}
void WebMediaController::Load(wxURI url)
{

View File

@@ -322,6 +322,9 @@ void wxMediaCtrl2::PostGtkSinkStateEvent(int id)
void wxMediaCtrl2::Load(wxURI url)
{
const wxString scheme = url.GetScheme();
const bool generic_rtsp = scheme.CmpNoCase("rtsp") == 0 || scheme.CmpNoCase("rtsps") == 0;
#ifdef __WIN32__
InvalidateBestSize();
if (m_imp == nullptr) {
@@ -342,7 +345,9 @@ void wxMediaCtrl2::Load(wxURI url)
wxPostEvent(this, event);
return;
}
{
// BambuSource handles the proprietary bambu:// transport. Generic RTSP
// streams must go directly to the native Windows media backend.
if (!generic_rtsp) {
wxRegKey key11(wxRegKey::HKCU, L"SOFTWARE\\Classes\\CLSID\\" CLSID_BAMBU_SOURCE L"\\InProcServer32");
wxRegKey key12(wxRegKey::HKCR, L"CLSID\\" CLSID_BAMBU_SOURCE L"\\InProcServer32");
wxString path = key11.Exists() ? key11.QueryDefaultValue()
@@ -422,8 +427,10 @@ void wxMediaCtrl2::Load(wxURI url)
keyWmp.SetValue("Permissions", permissions);
}
}
url = wxURI(url.BuildURI().append("&hwnd=").append(boost::lexical_cast<std::string>(GetHandle())).append("&tid=").append(
boost::lexical_cast<std::string>(GetCurrentThreadId())));
if (!generic_rtsp) {
url = wxURI(url.BuildURI().append("&hwnd=").append(boost::lexical_cast<std::string>(GetHandle())).append("&tid=").append(
boost::lexical_cast<std::string>(GetCurrentThreadId())));
}
#endif
#ifdef __WXGTK3__
GstElementFactory *factory;
@@ -458,7 +465,10 @@ void wxMediaCtrl2::Load(wxURI url)
gst_object_unref(factory);
}
if (!hasplugins) {
// Generic RTSP streams may use codecs other than H.264; let GStreamer
// select the decoder from the stream caps instead of applying the Bambu
// liveview H.264 preflight.
if (!generic_rtsp && !hasplugins) {
CallAfter([] {
wxMessageBox(_L("Your system is missing H.264 codecs for GStreamer, which are required to play video. (Try installing the gstreamer1.0-plugins-bad or gstreamer1.0-libav packages, then restart Orca Slicer?)"), _L("Error"), wxOK);
});
@@ -473,6 +483,10 @@ void wxMediaCtrl2::Load(wxURI url)
#endif
m_error = 0;
m_loaded = false;
#ifdef __LINUX__
if (generic_rtsp)
gst_bambu_last_error = 0;
#endif
#if defined(__LINUX__) && defined(__WXGTK__)
if (m_use_gtk_sink && m_gtk_playbin) {
const std::string uri = std::string(url.BuildURI().ToUTF8().data());

View File

@@ -22,8 +22,10 @@ public:
int command_start_camera(std::string dev_id) override;
FilamentSyncMode get_filament_sync_mode() const override { return FilamentSyncMode::subscription; }
CameraStreamMode get_camera_stream_mode() const override { return CameraStreamMode::http_snapshot; }
std::string get_camera_url() const override { return device_info.base_url + "/server/files/camera/monitor.jpg"; }
// CameraStreamMode get_camera_stream_mode() const override { return CameraStreamMode::http_snapshot; }
CameraStreamMode get_camera_stream_mode() const override { return CameraStreamMode::rtsp; }
// std::string get_camera_url() const override { return device_info.base_url + "/server/files/camera/monitor.jpg"; }
std::string get_camera_url() const override { return "rtsp://100.99.196.114:8554/stream"; }
private:
// Combine filament_type + filament_sub_type into a unified type string