Skip to main content
Version: 0.9.0 (next)

PrimarylessVideoSender class

Application-owned video stream, such as GUI panel content, that exists before any receiver connects and is delivered to every receiver that requests its stream id.

Namespace: Quaternar.Qaros · Assembly: Quaternar.Qaros.dll

public sealed class PrimarylessVideoSender : IDisposable

Implements: IDisposable

Remarks​

Unlike RenderSender, which answers one target's render request and hands out poses and FOVs to render with, this sender carries an arbitrary layout and no render metadata. Use RenderSender for remote-rendered content shown in an app volume, this one for video the application produces on its own.

Frame cycle: PrimarylessVideoSender.TryBeginFrame until it returns true, write the frame (PrimarylessVideoSender.GetCpuFrame, PrimarylessVideoSender.GetD3D11Frame, PrimarylessVideoSender.GetOpenGlFrame or PrimarylessVideoSender.GetVulkanFrame, matching the sender's graphics API), then PrimarylessVideoSender.ShowFrame. The frame exists from creation and may be inspected outside a cycle; its contents and synchronization may be written only inside one. Its texture handles stay stable until a layout change, so they can be cached between cycles.

Methods​

MemberDescription
GetStreamId()
TryBeginFrame()Non-blocking: true when a frame cycle was begun for the receivers ready at this moment; false when no cycle exists yet, so poll again later.
GetLayout()
ChangeLayout(VideoFrameLayout)Replaces the frame layout. The new frame resources are created synchronously on the calling thread; if that fails, the previous layout and frame stay usable.
GetCpuFrame()
GetD3D11Frame()
GetOpenGlFrame()Requires a library built with QAR_ENABLE_OPENGL (otherwise EntryPointNotFoundException).
GetVulkanFrame()Sender-owned Vulkan frame; requires a library built with QAR_ENABLE_VULKAN (otherwise EntryPointNotFoundException). Valid until the next call or this sender's disposal.
ShowFrame()Sends the written frame to the receivers reserved by PrimarylessVideoSender.TryBeginFrame and ends the cycle.
Dispose()Closes the stream to every receiver, draining frames still being sent first.

GetStreamId​

public Result<StreamId> GetStreamId()

Returns: Result<StreamId>

TryBeginFrame​

Non-blocking: true when a frame cycle was begun for the receivers ready at this moment; false when no cycle exists yet, so poll again later.

public Result<bool> TryBeginFrame()

Returns: Result<bool>

Remarks

Receivers that become ready afterwards get the next cycle. Recoverable failures, to keep polling through: StatusCode.MediaStreamingNoActiveTransfers while no receiver is connected (the normal state before the first one requests the stream), StatusCode.MediaStreamingStreamIsPaused while every receiver has paused it, and StatusCode.MediaStreamingStreamIsReconnecting while every receiver is reconnecting. Calling it again before PrimarylessVideoSender.ShowFrame fails with StatusCode.LogicError: only one cycle may be open.

GetLayout​

public Result<VideoFrameLayout> GetLayout()

Returns: Result<VideoFrameLayout>

ChangeLayout​

Replaces the frame layout. The new frame resources are created synchronously on the calling thread; if that fails, the previous layout and frame stay usable.

public Result<Unit> ChangeLayout(VideoFrameLayout layout)

Parameters

NameTypeDescription
layoutVideoFrameLayout

Returns: Result<Unit>

Exceptions

ExceptionCondition
ArgumentNullExceptionlayout is null.

Remarks

Texture handles cached from an earlier frame do not survive a successful change: fetch the frame again.

GetCpuFrame​

public Result<VideoFrameCpu> GetCpuFrame()

Returns: Result<VideoFrameCpu>

GetD3D11Frame​

public Result<VideoFrameD3D11> GetD3D11Frame()

Returns: Result<VideoFrameD3D11>

GetOpenGlFrame​

Requires a library built with QAR_ENABLE_OPENGL (otherwise EntryPointNotFoundException).

public Result<VideoFrameOpenGl> GetOpenGlFrame()

Returns: Result<VideoFrameOpenGl>

GetVulkanFrame​

Sender-owned Vulkan frame; requires a library built with QAR_ENABLE_VULKAN (otherwise EntryPointNotFoundException). Valid until the next call or this sender's disposal.

public Result<VideoFrameVulkan> GetVulkanFrame()

Returns: Result<VideoFrameVulkan>

Remarks

Inside a frame cycle, record on it the layout and queue family each image was left in (VideoFrameVulkan.SetTextureState) and the synchronization the rendering signals (VideoFrameVulkan.SetSynchronization) before PrimarylessVideoSender.ShowFrame. PrimarylessVideoSender.ShowFrame fails with StatusCode.LogicError when this was not called in the current cycle.

ShowFrame​

Sends the written frame to the receivers reserved by PrimarylessVideoSender.TryBeginFrame and ends the cycle.

public Result<Unit> ShowFrame()

Returns: Result<Unit>

Remarks

Succeeds when at least one reserved receiver got the frame; fails with StatusCode.MediaStreamingNoActiveTransfers when all of them were lost before delivery.

Dispose​

Closes the stream to every receiver, draining frames still being sent first.

public void Dispose()