mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-11-12 14:57:20 +00:00
[idd] network: make video chroma configurable
This commit is contained in:
@@ -58,11 +58,14 @@ ITransport::OpenResult CNetworkTransport::Open()
|
||||
m_settings = std::move(settings);
|
||||
m_state = State::OPEN;
|
||||
DEBUG_INFO("Network transport configured on [%ls]:%u for up to %u "
|
||||
"clients (%ls authentication)",
|
||||
"clients (%ls authentication, %ls video)",
|
||||
m_settings.bindAddress.c_str(),
|
||||
static_cast<unsigned>(m_settings.port),
|
||||
static_cast<unsigned>(m_settings.maxClients),
|
||||
m_settings.auth == LG_NET_AUTH_PASSWORD ? L"password" : L"none");
|
||||
m_settings.auth == LG_NET_AUTH_PASSWORD ? L"password" : L"none",
|
||||
m_settings.videoChroma ==
|
||||
static_cast<LGNetVideoChromaSubsampling>(LG_NET_VIDEO_CHROMA_420) ?
|
||||
L"4:2:0" : L"4:4:4");
|
||||
return OpenResult::SUCCESS;
|
||||
}
|
||||
|
||||
@@ -106,7 +109,8 @@ bool CNetworkTransport::Initialize()
|
||||
m_server.reset();
|
||||
return false;
|
||||
}
|
||||
if ((m_config.services & TRANSPORT_SERVICE_FRAME) && !m_video.Start())
|
||||
if ((m_config.services & TRANSPORT_SERVICE_FRAME) &&
|
||||
!m_video.Start(m_settings.videoChroma))
|
||||
{
|
||||
DEBUG_ERROR("Failed to start the network video endpoint");
|
||||
m_video.DetachSender();
|
||||
|
||||
@@ -141,6 +141,8 @@ namespace
|
||||
{
|
||||
if (!width || !height || width > MAX_WIDTH || height > MAX_HEIGHT)
|
||||
return false;
|
||||
if (chroma == CHROMA_420 && ((width | height) & 1U))
|
||||
return false;
|
||||
const uint32_t alignedWidth = (std::max)(
|
||||
Align(width, PYROWAVE_ALIGNMENT), PYROWAVE_MIN_DIMENSION);
|
||||
const uint32_t alignedHeight = (std::max)(
|
||||
@@ -157,15 +159,22 @@ namespace
|
||||
|
||||
class NetworkVideoFrameCaps final : public FrameCaps
|
||||
{
|
||||
private:
|
||||
const LGNetVideoChromaSubsampling m_chroma;
|
||||
|
||||
public:
|
||||
explicit NetworkVideoFrameCaps(LGNetVideoChromaSubsampling chroma) :
|
||||
m_chroma(chroma)
|
||||
{
|
||||
}
|
||||
|
||||
bool CanUseMode(const FrameMode& mode,
|
||||
uint32_t * requiredSizeMiB = nullptr) const override
|
||||
{
|
||||
if (requiredSizeMiB)
|
||||
*requiredSizeMiB = 0;
|
||||
return mode.width && mode.height && mode.refresh100uHz &&
|
||||
PlaneElementsFit(mode.width, mode.height,
|
||||
CHROMA_444);
|
||||
PlaneElementsFit(mode.width, mode.height, m_chroma);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2675,11 +2684,12 @@ struct CNetworkVideo::Impl
|
||||
HANDLE m_workerThread = nullptr;
|
||||
std::atomic<bool> m_workerStop = false;
|
||||
|
||||
INetworkVideoSender * m_sender = nullptr;
|
||||
bool m_started = false;
|
||||
bool m_stopped = false;
|
||||
bool m_failed = false;
|
||||
bool m_changing = false;
|
||||
INetworkVideoSender * m_sender = nullptr;
|
||||
LGNetVideoChromaSubsampling m_videoChroma = CHROMA_444;
|
||||
bool m_started = false;
|
||||
bool m_stopped = false;
|
||||
bool m_failed = false;
|
||||
bool m_changing = false;
|
||||
|
||||
FrameCfg m_activeCfg = {};
|
||||
FrameCfg m_pendingCfg = {};
|
||||
@@ -2806,7 +2816,7 @@ struct CNetworkVideo::Impl
|
||||
{
|
||||
if (!m_active)
|
||||
return static_cast<LGNetVideoChromaSubsampling>(0);
|
||||
return CHROMA_444;
|
||||
return m_videoChroma;
|
||||
}
|
||||
|
||||
LGNetVideoStreamConfig StreamConfigNL() const
|
||||
@@ -3540,8 +3550,9 @@ struct CNetworkVideo::Impl
|
||||
|
||||
bool SubmitPending()
|
||||
{
|
||||
PendingFrame pending;
|
||||
uint32_t frameLimit = MAX_FRAME_LENGTH;
|
||||
PendingFrame pending;
|
||||
LGNetVideoChromaSubsampling chroma = CHROMA_444;
|
||||
uint32_t frameLimit = MAX_FRAME_LENGTH;
|
||||
{
|
||||
CSRWExclusiveLock lock(m_lock);
|
||||
if (m_encoder.Busy() || m_frames.empty() || !m_started ||
|
||||
@@ -3562,11 +3573,12 @@ struct CNetworkVideo::Impl
|
||||
}
|
||||
if (!configured)
|
||||
return true;
|
||||
chroma = m_videoChroma;
|
||||
}
|
||||
|
||||
if (m_encoder.Submit(std::move(pending.frame),
|
||||
std::move(pending.lease), pending.cfg,
|
||||
CHROMA_444,
|
||||
chroma,
|
||||
frameLimit))
|
||||
return true;
|
||||
|
||||
@@ -3791,15 +3803,17 @@ void CNetworkVideo::DetachSender()
|
||||
m_impl->m_peers.clear();
|
||||
}
|
||||
|
||||
bool CNetworkVideo::Start()
|
||||
bool CNetworkVideo::Start(LGNetVideoChromaSubsampling videoChroma)
|
||||
{
|
||||
if (!m_impl || !m_impl->WorkerReady())
|
||||
if (!m_impl || !m_impl->WorkerReady() ||
|
||||
(videoChroma != CHROMA_420 && videoChroma != CHROMA_444))
|
||||
return false;
|
||||
{
|
||||
CSRWExclusiveLock lock(m_impl->m_lock);
|
||||
if (m_impl->m_stopped || m_impl->m_failed)
|
||||
return false;
|
||||
m_impl->m_started = true;
|
||||
m_impl->m_videoChroma = videoChroma;
|
||||
m_impl->m_started = true;
|
||||
}
|
||||
m_impl->Wake();
|
||||
return true;
|
||||
@@ -4084,9 +4098,15 @@ const FrameProfile * CNetworkVideo::Profiles(unsigned& count) const
|
||||
|
||||
std::shared_ptr<const FrameCaps> CNetworkVideo::GetFrameCaps() const
|
||||
{
|
||||
static const std::shared_ptr<const FrameCaps> caps(
|
||||
new (std::nothrow) NetworkVideoFrameCaps());
|
||||
return caps;
|
||||
if (!m_impl)
|
||||
return std::shared_ptr<const FrameCaps>();
|
||||
LGNetVideoChromaSubsampling chroma;
|
||||
{
|
||||
CSRWSharedLock lock(m_impl->m_lock);
|
||||
chroma = m_impl->m_videoChroma;
|
||||
}
|
||||
return std::shared_ptr<const FrameCaps>(
|
||||
new (std::nothrow) NetworkVideoFrameCaps(chroma));
|
||||
}
|
||||
|
||||
CfgResult CNetworkVideo::Probe(const FrameCfg& cfg) const
|
||||
@@ -4100,7 +4120,7 @@ CfgResult CNetworkVideo::Probe(const FrameCfg& cfg) const
|
||||
cfg.width > MAX_WIDTH || cfg.height > MAX_HEIGHT ||
|
||||
!SupportedProfile(cfg.profile))
|
||||
return CfgResult::NEXT;
|
||||
const LGNetVideoChromaSubsampling chroma = CHROMA_444;
|
||||
const LGNetVideoChromaSubsampling chroma = m_impl->m_videoChroma;
|
||||
if (!PlaneElementsFit(cfg.width, cfg.height, chroma))
|
||||
return CfgResult::NEXT;
|
||||
return CfgResult::ACCEPTED;
|
||||
|
||||
@@ -96,7 +96,7 @@ public:
|
||||
bool AttachSender(INetworkVideoSender& sender);
|
||||
void DetachSender();
|
||||
|
||||
bool Start();
|
||||
bool Start(LGNetVideoChromaSubsampling videoChroma);
|
||||
void Stop();
|
||||
void Process(uint64_t nowMs);
|
||||
|
||||
|
||||
@@ -29,11 +29,12 @@ namespace
|
||||
{
|
||||
enum Field : unsigned
|
||||
{
|
||||
FIELD_BIND = 1U << 0,
|
||||
FIELD_PORT = 1U << 1,
|
||||
FIELD_MAX_CLIENTS = 1U << 2,
|
||||
FIELD_AUTH = 1U << 3,
|
||||
FIELD_PASSWORD = 1U << 4,
|
||||
FIELD_BIND = 1U << 0,
|
||||
FIELD_PORT = 1U << 1,
|
||||
FIELD_MAX_CLIENTS = 1U << 2,
|
||||
FIELD_AUTH = 1U << 3,
|
||||
FIELD_PASSWORD = 1U << 4,
|
||||
FIELD_VIDEO_CHROMA = 1U << 5,
|
||||
};
|
||||
|
||||
std::wstring Trim(const std::wstring& value)
|
||||
@@ -137,6 +138,20 @@ namespace
|
||||
return Fail(error, L"invalid password");
|
||||
settings.password = value;
|
||||
}
|
||||
else if (Equal(key, L"videoChroma"))
|
||||
{
|
||||
field = FIELD_VIDEO_CHROMA;
|
||||
if (Equal(value, L"420"))
|
||||
settings.videoChroma =
|
||||
static_cast<LGNetVideoChromaSubsampling>(
|
||||
LG_NET_VIDEO_CHROMA_420);
|
||||
else if (Equal(value, L"444"))
|
||||
settings.videoChroma =
|
||||
static_cast<LGNetVideoChromaSubsampling>(
|
||||
LG_NET_VIDEO_CHROMA_444);
|
||||
else
|
||||
return Fail(error, L"invalid video chroma subsampling");
|
||||
}
|
||||
else
|
||||
return Fail(error, L"unknown setting");
|
||||
|
||||
|
||||
@@ -25,21 +25,27 @@
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
static constexpr uint16_t NETWORK_DEFAULT_MAX_CLIENTS = 4;
|
||||
static constexpr uint16_t NETWORK_MAX_CLIENTS = 32;
|
||||
static constexpr uint16_t NETWORK_DEFAULT_MAX_CLIENTS = 4;
|
||||
static constexpr uint16_t NETWORK_MAX_CLIENTS = 32;
|
||||
static constexpr LGNetVideoChromaSubsampling NETWORK_DEFAULT_VIDEO_CHROMA =
|
||||
static_cast<LGNetVideoChromaSubsampling>(LG_NET_VIDEO_CHROMA_444);
|
||||
|
||||
struct NetworkSettings
|
||||
{
|
||||
std::wstring bindAddress = L"*";
|
||||
uint16_t port = static_cast<uint16_t>(LG_NET_DEFAULT_PORT);
|
||||
uint16_t maxClients = NETWORK_DEFAULT_MAX_CLIENTS;
|
||||
LGNetAuthMode auth = LG_NET_AUTH_MODE_DEFAULT;
|
||||
std::wstring password;
|
||||
std::wstring bindAddress = L"*";
|
||||
uint16_t port =
|
||||
static_cast<uint16_t>(LG_NET_DEFAULT_PORT);
|
||||
uint16_t maxClients = NETWORK_DEFAULT_MAX_CLIENTS;
|
||||
LGNetAuthMode auth = LG_NET_AUTH_MODE_DEFAULT;
|
||||
std::wstring password;
|
||||
LGNetVideoChromaSubsampling videoChroma =
|
||||
NETWORK_DEFAULT_VIDEO_CHROMA;
|
||||
};
|
||||
|
||||
// Settings use a semicolon-separated key=value list. Supported keys are
|
||||
// bind, port, maxClients, auth, and password. Password authentication requires
|
||||
// a non-empty password. The default address requests a dual-stack wildcard
|
||||
// listener from the eventual QUIC provider.
|
||||
// bind, port, maxClients, auth, password, and videoChroma. videoChroma accepts
|
||||
// 420 or 444 and defaults to 444. Password authentication requires a non-empty
|
||||
// password. The default address requests a dual-stack wildcard listener from
|
||||
// the eventual QUIC provider.
|
||||
bool ParseNetworkSettings(const std::wstring& source,
|
||||
NetworkSettings& settings, std::wstring * error = nullptr);
|
||||
|
||||
Reference in New Issue
Block a user