Skip to content

Changelog

Changes and updates for all .Net SDKs.

2026.9.1

  • [Video Capture SDK .Net] Removed: the RTSP X network streaming output. NetworkStreamingFormat.RTSP_X and the RTSPXOutput settings class are gone from VideoCaptureCore, and the VisioForge.DotNet.Core.Redist.RTSPX.x64 package is no longer published - it carried its own GStreamer runtime that had not been refreshed since 2024 and loaded alongside the current one. Use VideoCaptureCoreX with RTSPServerOutput/RTSPServerSettings, which serves RTSP from the maintained runtime and needs no extra package. NetworkStreamingFormat.RTSP_H264_AAC_SW remains available on VideoCaptureCore (#1262).

  • [Media Blocks SDK .Net] Fixed: on Windows, stopping an SRT pipeline never returned when the receiving peer had gone away. StopAsync blocked indefinitely on SRTSinkBlock and SRTMPEGTSSinkBlock, and the pipeline could never be disposed - the bundled SRT plugin kept closing and reopening the connection, and End-Of-Stream could not be delivered while the sink's streaming thread was inside that loop. The Windows redistributable now carries the corrected SRT plugin macOS has shipped since 2026.8.5, so a stop against an unreachable or flapping peer completes in about a second (#1190).

  • [Core] The RAV1E AV1 encoder now encodes across CPU cores. rav1enc splits work by tiles and the SDK never set that property, so it ran the whole frame as a single tile and encoded at the same speed on 4 cores as on 32. The new RAV1EEncoderSettings.Tiles defaults to 16: measured on 720p30, 8 seconds of content now takes about 29 seconds instead of 84, for roughly 1% more bitrate at the same Quantizer. Set Tiles = 0 for the previous single-tile output (#1345).

  • [Media Blocks SDK .Net] Fixed: a Basler camera was opened by its position in the device list, not by the camera you named. BaslerCameraInfo read only DeviceIndex, so an instance built with new BaslerCameraInfo(name) - which leaves that index at 0 - read its sensor size from, and streamed, the first Basler device on the machine whatever the name said. The camera is now found by its serial number, full name, user-defined name or name, and pylonsrc is pointed at it by identity rather than by index; a named camera that is not present is now reported and the capture fails to start, instead of quietly streaming another one (#1344).

2026.8.31

  • [Media Blocks SDK .Net] Fixed: a video mixer could save a source that would not load back, and a restored Basler source could report zero frame rate. A mixer source whose camera name had been cleared was written into the document without it, the snapshot reported success, and loading that document failed - it is refused at save time now, naming the block. And a Basler camera whose frame rate could not be read when the document was saved kept a zero frame rate on every later load, which reached the recording's frame info; it is re-read now, as the sensor size already was.

  • [Media Blocks SDK .Net] Fixed: a Spinnaker source could open a different camera than the one it was told to, without saying so. The camera was addressed by its position in the enumerated list rather than by its own index, so one camera failing to initialize - held by another process, for instance - shifted every camera after it, and the source silently opened its neighbour. A name matching no camera at all, or matching two identical bodies (the name is the model name, which they share), was equally silent. The index is now the camera's own, SpinnakerCameraInfo carries the serial number, and all three cases are reported. two handles leaked during enumeration are released; one camera failing to answer no longer hides every other camera on the rig, and no longer leaves a truncated list cached; a camera whose model name cannot be read is listed under its serial number instead of under a name every unreadable camera shares; and a camera index the element cannot address fails the source instead of quietly opening a different camera - the element accepts 0-7, so on a rig with nine or more cameras the ninth and beyond now report an error at build time rather than streaming a neighbour.

  • [X-engines] Fixed: an SDK error killed the process when the application had not subscribed OnError. VideoEditCoreX reported such an error by logging it, and the log is what raises the error event, so every error re-entered the reporting path and recursed until the stack overflowed - the process died with no exception and no message. A render that could not build its encoder was the common way in. The error is now reported once, and shown on the video view exactly as the other engines do. MediaBlocksPipeline had the same loop on its two "VisioForge_MFP.dll not found" messages, which recursed whenever a debugger was attached (#1173).

  • [Media Blocks SDK .Net] Fixed: a virtual camera sink with an input that was created but never connected wedged the pipeline. VirtualCameraSinkBlock built the chain for a pad that exists rather than for one that is connected, so an unconnected input left a branch with nothing feeding it - a branch that can neither preroll nor reach End-Of-Stream, leaving either StartAsync or StopAsync never returning. Two connected inputs of the same type are now reported as an error too - only one of them was ever linked (#1288).

  • [Media Blocks SDK .Net] NDISinkBlock.IsAvailable() now reports false when the NDI runtime is missing. It answered from the GStreamer element alone, so on a machine carrying the plugin but no NDI runtime it reported the sink as available and the pipeline then failed to start (#1288).

  • [Media Blocks SDK .Net] Fixed: stopping a pipeline whose NDISinkBlock had only a video input never returned. StopAsync blocked forever and the pipeline could never be disposed; adding an audio input was the only workaround. The sink built its audio chain even when no audio was connected, and the unfed combiner pad stalled the End-Of-Stream a graceful stop sends. A video-only NDI sink now stops normally. An NDI sink with no video input, which cannot produce an NDI stream at all, is now reported as a build error instead of hanging the same way (#1288).

  • [Media Blocks SDK .Net] Fixed: nothing decoded when a decoder was connected to UniversalDemuxBlock. The demuxer hands out encoded data, so a decoder behind it is the normal way to use it - and that graph delivered no frames at all, while the pipeline reported a successful start and put nothing on the bus. A stream the demuxer was told not to render was sent to a plain null sink, which stalled the demuxer until the pipeline reached playing, and the pipeline could not reach playing because the decoder branch was starved of the frames it needed. This affects UniversalDemuxBlock and UniversalAutoDemuxerBlock with renderVideo or renderAudio turned off, and every decoder behind them, UniversalDecoderBlock, DecodeBinBlock and the codec-specific decoder blocks alike. A demuxer also no longer throws when the file turns out to hold more streams of a type than its media info reported, and UniversalDemuxBlock can now output a metadata stream (#836).

  • [Media Blocks SDK .Net] UniversalDemuxSettings.Type can now be set. It was declared without a setter, so that settings class always meant automatic container detection whatever was assigned to it; the per-format settings classes were the only way to pick a specific demuxer. The default is unchanged (#836).

  • [Media Blocks SDK .Net] Pipeline documents now write enum settings by name instead of by number. Many of the SDK's enums declare their members per platform, so the same ordinal meant a different member elsewhere - 1 was WASAPI on Windows and Decklink on macOS - and a document moved between platforms silently restored the wrong device API, encoder or format. A saved pipeline now reads "api": "WASAPI". Documents written before this still load; a document written by this build cannot be opened by an earlier one (#1322).

  • [Media Blocks SDK .Net] A pipeline document now restores the audio device a block was using. AudioRendererBlock, SystemAudioSourceBlock and the WASAPI, WASAPI2, DirectSound, loopback and PulseAudio audio sources hold an AudioOutputDeviceInfo or AudioCaptureDeviceInfo, and neither could be written to a document and read back - so a saved pipeline came back either refusing to load or holding no device at all. A document now stores what identifies the device (its name, path, API and, on macOS, the stable CoreAudio unique-id), and materialization matches that against the devices the machine actually has, handing the block a live device again. This also fixes a saved configuration opening the wrong speaker or microphone: the numeric CoreAudio id and the WASAPI path are both reassigned between runs, and the match now re-reads the current ones. When the named device is gone, the pipeline still builds on a system device of the same API and materialization reports it as the new MBS063 warning naming both devices. AlliedVisionSourceSettings restores from the camera's identity the same way, without opening the camera (#1322).

  • [Media Blocks SDK .Net] Fixed: a pipeline document silently lost mandatory block settings and restored a block wired to the wrong thing. A setting exposed as a read-only property - the bridge Channel above all, but also CustomMediaBlockSettings.ElementName, GLOverlaySettings.Filename, GLEquirectangularViewSettings.VideoWidth/VideoHeight, AlliedVisionSourceSettings.Camera and the GenICam region, frame rate and pixel format - was never written into a saved document, and came back as null or 0 with validation, deserialization and materialization all reporting success. Two app bridges saved on different channels reloaded onto the same one. Those settings now round-trip, a document missing one is reported as MBS043 naming the property instead of restoring a mis-wired block, and MediaBlockDescriptor.Properties lists them (with the new IsRequired and IsReadOnly flags) so an editor can author them. Eight settings types could not be restored at all, because a constructor parameter matched no property and the serializer refuses to bind such a constructor - every document holding a BridgeAudioSource, HTTPSource, AudioRenderer, OpenCVTemplateMatch, LiveSourceSwitch, LiveSourceSwitchDynamic, AlliedVisionSource or VideoAspectRatioCrop block failed to load. All of them now restore. The parameters are renamed to match their properties: BridgeAudioSourceSettings(channel, info), HTTPSourceSettings(location, isLive), AudioRendererSettings(info), CVTemplateMatchSettings(templateImage) and LiveSourceSwitchSettings(videoWidth, videoHeight, videoFrameRate). Positional calls are unaffected; code passing these by name must be updated (#1322).

  • [Media Blocks SDK .Net] Fixed: a pipeline document holding a SpinnakerSource block could not be loaded, and a mixer holding a Spinnaker source could not be saved. The constructor's first parameter matched no property, which the serializer refuses outright, and the region, frame rate and pixel format were never written into the document. All four settings now round-trip. The parameter is renamed to match its property: SpinnakerSourceSettings(name, region, frameRate, pixelFormat). Positional calls are unaffected; code passing the first argument by name must be updated (#1338).

  • [Media Blocks SDK .Net] Fixed: a pipeline document holding a GenICamSource or BaslerSource block came back without its camera. GenICamSourceSettings declares two constructors and no parameterless one, which the serializer refuses outright, so no document holding the block loaded at all - while its region, frame rate and pixel format were written into the document regardless. BaslerSourceSettings.Camera was never written, so the block restored with no camera while saving, validation and loading all reported success. Both now round-trip from the identity the document carries, and a Basler document that carries the sensor size no longer opens the camera to re-read it. The first parameter of both GenICamSourceSettings constructors is renamed deviceName -> name to match its property; positional calls are unaffected. A SpinnakerSource or GenICamSource document carrying no camera name, or an empty one, is now reported as MBS043 instead of silently opening the first camera on the machine (#1338).

  • [Media Blocks SDK .Net] Fixed: a video mixer holding an Allied Vision or GenICam camera could not be saved. The mixer wrote a source only when it could read it back, and that check looked at public constructors alone - so it refused a settings class whose deserialization constructor is private, with an MBS060, even though loading a document restores it correctly. Both cameras now save and reload as mixer sources. A mixer source missing a mandatory setting - the region above all - is reported now too, where it used to load as a camera with no region and then fail when the pipeline started (#1338).

  • [Core] Fixed: a capture device whose sample rate range lies outside 22050-96000 Hz disappeared from the device's format list. A narrow-band device publishing, say, rate=(int)[ 8000, 16000 ] matched none of the rates the enumeration samples a range at, so it produced no entries at all. Its own bounds are published instead (#1317).

  • [Core] Fixed: a capture device publishing its sample rate or channel count as a list disappeared from the device's format list entirely. AudioCaptureDeviceInfo.Formats read only the single-value and range forms, so a caps structure written as rate=(int){ 44100, 48000 } produced no entries at all rather than one per combination (#1317).

  • [Core] Fixed: audio frames delivered as 24-bit-in-32 or as 20-/18-bit reported the wrong bytes per sample. AudioFrame.Info.BPS carried the number of significant bits rather than the container width, so a consumer of BufferSinkBlock or AudioSampleGrabberBlock read 3 bytes per sample where the buffer holds 4 (S24_32*) - a 25% undercount that garbles the audio - and 2 bytes where 20- and 18-bit formats hold 3. S24BE reported 0. Unchanged for 8-, 16-, 32- and 64-bit formats, which is everything the SDK produces by default (#1317).

  • [Core] Fixed: 24-bit-in-32 audio formats were dropped from capture-device format lists and could not be requested. GStreamer writes these as S24_32LE/S24_32BE/U24_32LE/U24_32BE while the AudioFormatX enum spells them without the underscore, and the SDK converted between the two by name. A device offering one of them lost it from AudioCaptureDeviceInfo.Formats, and asking for it anywhere a format is applied - audio capture, the audio mixer, WAV output, a push source, the iOS/Mac audio renderer - produced a format name no element accepts. Both directions are now translated (#1317).

  • [Core] On macOS and Mac Catalyst the default audio capture format now follows the device's own sample rate. AudioCaptureDeviceInfo.GetDefaultFormat() preferred 44100 Hz and, when a device published no 16-bit stereo combination at all, fell back to whichever entry sorted first alphabetically. Since the capture format is applied to the capture device itself, that could ask CoreAudio to run an input at a rate it does not use - CoreAudio cannot resample an input, so the hardware's nominal rate was changed instead. The rate now comes from the format the device reports as its own; 16-bit stereo is still preferred for the sample format and channel count, which CoreAudio does convert. Devices publishing 16-bit stereo at 44100 or 48000 Hz - the common case - keep the format they had (#1317).

  • [Media Blocks SDK .Net] IsAvailable() on the video and audio encoders and decoders no longer reports a codec that cannot actually be created. It answered from the GStreamer registry alone, and the registry caches a plugin's element list while the elements a plugin registers are decided when it loads — the Media Foundation plugin names its encoders by hardware-MFT enumeration index, and the NVIDIA, Intel and Direct3D plugins register their elements only for the hardware present at scan time. After a driver, GPU or Windows-codec change the registry could still list an element the plugin no longer provides; IsAvailable() returned true and the pipeline then failed to build with an unrelated-looking error. The check now also loads the element's plugin and asks it again, which refreshes the registry's list for that plugin. The first IsAvailable() call for a given backend is correspondingly slower, since it now loads that backend's plugin — around 0.3 s for NVIDIA and 0.7 s for Media Foundation on the measured host, once per plugin per process — and that plugin's vendor libraries are loaded into the process even if the pipeline ends up encoding in software (#1175).

  • [Media Blocks SDK .Net] MFH264EncoderSettings.GetDeviceIDs() and MFHEVCEncoderSettings.GetDeviceIDs() no longer list a Media Foundation device that cannot be created, and they identify each device from the loaded MFT rather than from the cached registry metadata, which could name a different encoder. Two consequences on a host where such a stale entry existed: a device that used to appear and then fail is now absent, and DeviceID — a position in this list — can shift, so an application that persisted a DeviceID should re-resolve it against GetDeviceIDs() rather than assume last run's number (#1175).

  • [Media Blocks SDK .Net] Windows: using a Media Foundation encoder no longer permanently breaks every later NVIDIA NVENC encode in the process. GStreamer eagerly activated NVIDIA's Media Foundation H.264 and HEVC MFTs while registering the plugin, even when the pipeline only requested the Microsoft AAC encoder. If the public NVENC API had already been initialized, the next nvh264enc/nvh265enc session failed with NV_ENC_ERR_INVALID_VERSION (0xf) and no later session could recover. The bundled Media Foundation plugin now excludes NVIDIA's video MFTs before IMFActivate::ActivateObject. Microsoft, Intel, AMD, software Media Foundation video encoders, all Media Foundation audio codecs, video capture (mfvideosrc) and device enumeration remain available. What changes on an NVIDIA machine: NVIDIA's Media Foundation video encoders are no longer registered by the plugin. MFH264EncoderSettings and MFHEVCEncoderSettings keep selecting the same encoder and the same DeviceID numbering as before — they already excluded NVIDIA entries when enumerating — with one exception: a host whose only Media Foundation HEVC encoder was NVIDIA's. There the settings class enumerated nothing and fell back to the bare mfh265enc element, which used to be the NVIDIA one; nothing registers that name now, so HEVCEncoderBlock.IsAvailable(new MFHEVCEncoderSettings()) returns false and HEVCEncoderType.MF_HEVC is unavailable. Install the Microsoft HEVC Video Extensions, or encode HEVC through NVENCHEVCEncoderSettings. H.264 is not affected in the same way: Windows always registers the Microsoft software H.264 MFT. What changes is the plain GStreamer element: mfh264enc and mfh265enc are now backed by the next non-NVIDIA MFT on the host — Intel or AMD hardware where present, otherwise the Microsoft software H.264 MFT and the HEVC Video Extension — so a hand-written pipeline string naming them gets a different encoder. Use NVENCH264EncoderSettings, NVENCHEVCEncoderSettings or NVENCAV1EncoderSettings for NVIDIA hardware encoding; they are unaffected and are the faster path in any case (#842).

  • [Media Blocks SDK .Net] MFAACEncoderSettings is no longer deprecated. It was marked obsolete because using it broke NVENC later in the same process; that was never the AAC encoder's doing — requesting it loads the Media Foundation plugin, whose video-MFT registration was the real cause, and that is fixed above. Code using it no longer produces a compiler warning. AVENCAACEncoderSettings stays the Windows default for MP4Output; prefer MFAACEncoderSettings for VideoEditCoreX render paths, where libav AAC does not round-trip the GstPreset (#842).

  • [Media Blocks SDK .Net] Fixed: AudioRendererBlock.Mute could not turn audio back on on iOS and Mac Catalyst. Setting it to false wrote volume 0 again, leaving the renderer silent and reporting itself muted. Muting now preserves the configured volume, and unmuting restores audible output (#1318).

  • [Core] Fixed: HTTPS and RTSPS connections on Mac Catalyst could not initialize TLS. The GStreamer runtime was searched for in a lib subfolder that Mac Catalyst app bundles do not contain, so its OpenSSL TLS backend and certificate database were never loaded. The SDK now finds the bundled runtime and verifies TLS peers as on macOS (#1327).

  • [Core] On macOS and Mac Catalyst an application no longer re-scans the whole GStreamer plugin set on every launch. The scan is now cached in the application's own Caches directory (Library/Caches/VisioForge/<bundle-id>/gstreamer/, inside the sandbox container for a sandboxed app) and paid once - on the first start after installing or updating the application, and after that only for plugins whose files changed. Nothing needs to be deployed or configured; deleting the cache folder costs one more scan (#1299).

  • [Core] On macOS and Mac Catalyst GST_PLUGIN_PATH is no longer set in the .NET environment. It is published to the process environment GStreamer itself reads, which the .NET one on Unix never was - so Environment.GetEnvironmentVariable("GST_PLUGIN_PATH") now returns nothing on these platforms, and a child process started by the application no longer inherits the application's own plugin directory. Pass it explicitly to a child that needs it (#1299).

2026.8.30

  • [Media Blocks SDK .Net] Fixed: a chroma key saved into a pipeline document lost its source video resolution, and restored as a block that never worked. ChromaKeySettingsX.SourceVideoResolution is the one setting the keying filter cannot do without - it builds its video format from it - and it was read-only, so it was never written into a saved document and every restored chroma key came back with no resolution at all. Materialization reported success, and the failure showed up only when the pipeline was started: the block could not be built, and a block that cannot be built stops the whole pipeline from starting, with nothing in the diagnostics to say why. The property is now settable and round-trips, and ChromaKeyBlock refuses settings whose resolution is missing or has a zero extent, so such a document is reported as failing with MBS040 naming the property instead of restoring a dead block (#1319).

  • [Media Blocks SDK .Net] The OpenCV blocks now work on macOS. All sixteen blocks in the VisioForge.Core.MediaBlocks.OpenCV namespace, VideoStabilizationBlock among them, were documented as cross-platform but their GStreamer plugin shipped for Windows only, so on macOS every one of them reported IsAvailable() as false. Add the new VisioForge.CrossPlatform.OpenCV.macOS redistributable alongside VisioForge.CrossPlatform.Core.macOS and they work as they do on Windows. The package is one universal (x64 + ARM64) plugin with OpenCV 4.14.0 linked into it, so there are no separate OpenCV libraries to deploy. Linux, iOS, Mac Catalyst, Android and Windows arm64 still have no OpenCV redistributable and the blocks stay unavailable there (#1283).

  • [Media Blocks SDK .Net] Fixed: on macOS CVFaceDetectBlock, CVFaceBlurBlock and CVHandDetectBlock never found their default Haar cascade files. The default cascade names were resolved against an x64 or x86 subfolder of the application directory and nowhere else - a layout only the Windows redistributables create. Detection silently produced no results, with the cause visible only in the GStreamer log. The cascades are now looked up in the redistributable's own layout on every platform. Setting a cascade property to a full path is unaffected (#1283).

  • [Core] Fixed: reading or writing a GStreamer property whose type is glong or gulong threw EntryPointNotFoundException on Windows. Those two value types were read and written through four native functions that no shipped GStreamer build has ever exported, so every access to such a property failed on x86, x64 and ARM64 alike. They now go through the standard GLib accessors, and a value too large for the 32-bit Windows glong is reported as an overflow rather than stored as a different number (#1160).

  • [Demos] Fixed: restarting the Bridge Demo no longer leaves an MP4 recorder running in the background. Starting another recording now finalizes and releases the preceding recorder first, whether Start is pressed again directly or after Stop. The output file is no longer held open by an abandoned muxer, and completed recordings retain their MP4 index.

  • [Demos] Fixed: several demos started an operation and moved on without waiting for it. The Bridge, Bridge Source Switch, Audio Extractor and all three PreEventRecording demos (WPF and both Avalonia heads) destroyed the SDK, or let the process go, while engine teardown was still running - a recording being closed with the window could be left unfinalized, and the Media Blocks Avalonia one disposed its pipeline without stopping it first. Those window-close handlers now cancel the close, finish stopping and disposing, and then close for real; a second close request during teardown no longer slips past. The RTSP MultiViewSync demo's Stop button returned before the three pipelines had stopped, and the Video Edit Main Demo's Join button reported completion immediately; both now wait. The macOS Simple Media Player closed its window without blocking the main thread on player teardown, and the two Avalonia PreEventRecording motion handlers no longer block an SDK callback thread on the UI thread.

  • [Media Blocks SDK .Net] OSXAudioSourceBlock has been removed - use SystemAudioSourceBlock with OSXAudioSourceSettings. It was a leftover second macOS audio capture block: it built the same osxaudiosrc, but ignored the requested audio format and offered no volume or mute control, and nothing in the SDK, the demos or the documentation samples that actually ran ever created it - OSXAudioSourceSettings.CreateBlock(), DeviceEnumerator and every macOS demo have built a SystemAudioSourceBlock for years. Replace new OSXAudioSourceBlock(settings) with new SystemAudioSourceBlock(settings); the settings class, the device selection and the captured audio are unchanged. A pipeline JSON document saved with that block in it names a block type the SDK no longer has, so it is reported as unknown at validation and restores without its audio source - rebuild and re-save such a document (#1290).

  • [Media Blocks SDK .Net] Fixed: on macOS and Mac Catalyst the audio format requested through OSXAudioSourceSettings.Format was silently ignored. The capture device negotiated whatever it preferred - typically 32-bit float - so an application asking for 16-bit stereo got something else without any warning. The requested sample format, sample rate and channel count now reach osxaudiosrc. Format no longer defaults to a hardcoded 16-bit 44100 Hz stereo, because that value is now enforced and no longer a placeholder: leave it null to let the device choose, or take a real one from the enumeration with AudioCaptureDeviceInfo.GetDefaultFormat(), which is what CreateSourceSettings() already does (#1290).

  • [Media Blocks SDK .Net] The Metal video processing blocks now work on an iOS device. MetalVideoCompositorBlock, MetalConvertScaleBlock, MetalTransformBlock, MetalDeinterlaceBlock, MetalOverlayBlock and MetalVideoFilterBlock were documented as available on iOS and compiled there, but the Metal plugin behind them was never loaded, so every one of them reported IsAvailable() as false and could not be built into a pipeline. The plugin is now part of the iOS runtime, and it is the same current build the macOS and Mac Catalyst packages carry - so MetalVideoCompositorBlock also composes onto an output of any size, rather than failing negotiation whenever something downstream asked for a size other than the size of its inputs. Two limits remain, both unchanged: the Metal renderer (MetalVideoRendererSettings) is macOS only, and the blocks are unavailable in the iOS Simulator, where IsAvailable() still returns false (#1296).

  • [Media Blocks SDK .Net] Fixed: a pipeline document naming VideoMixerSource passed validation and then failed to build, and the mixer's sources were never saved in the first place. MediaBlocksPipelineValidator reported the block as constructible while MediaBlocksPipelineMaterializer threw MBS040: ... The method or operation is not implemented and discarded the whole pipeline, because VideoMixerSourceSettings.CreateBlock() was not implemented. It now builds the block, so a document restores it. The settings also persist their inputs: the sources, their rectangles and their chroma keys were held in a private list that was silently left out of every saved document and every ToDocument() snapshot, so a two-camera mixer came back as an empty canvas. They are now the public VideoMixerSourceSettings.Sources list of VideoMixerSourceStream, written and read with the source's own settings class named in the JSON; a source class this build does not contain - several are platform-specific - is reported rather than restored as an empty input. Capturing a live pipeline now also warns (MBS060) about any block the document cannot rebuild, instead of reporting the snapshot complete. API change: VideoMixerSourceBlock now derives from SuperMediaBlock rather than SourceMediaBlock, which is what lets a block built from VideoMixerSourceSettings.CreateBlock() wire itself up when you connect only its output - previously that produced a pipeline that stalled at start with no error. It keeps behaving as a source; the only members it no longer inherits are Stop(), which did nothing, and IsSubtitlesAvailable(), which it still provides. Renamed arguments: VideoMixerSourceSettings.Add(source, left, top, width, height) never took a width and a height - the last two arguments went straight into Rect(left, top, right, bottom), so Add(src, 960, 0, 960, 1080) produced a zero-width input, not a 960-wide one. The parameters are now named right and bottom. Behaviour is unchanged, so positional calls keep working; a call that passed the arguments by name (width: / height:) no longer compiles, and it was producing the rectangle the new names describe all along (#1230).

  • [Core] The Windows GStreamer plugin cache is now kept per SDK version, and a rebuilt plugin of the same size is no longer ignored. On Windows the SDK mirrors an application's x64 / x86 native folder into a shared folder under %PUBLIC%\.gstreamer and loads from there, so that every VisioForge application on the machine shares one warm GStreamer plugin registry instead of each paying a full cold scan. That folder was shared by every SDK version ever run on the machine and was only ever added to, so a native library a newer release no longer ships stayed on the load path indefinitely - an application could keep working on a machine that had run an older release and fail on a clean one. It is now %PUBLIC%\.gstreamer\<sdk-version>-<native-set>\<arch>, keyed to the SDK version together with a stamp of the core and Libav redistributables the application actually deployed, so deployments on different natives no longer overwrite each other's files on every start; a cache the SDK created and nothing has started for 30 days is removed, while a folder left by an older SDK that still uses the previous shared layout is left alone. Whether a cached file is up to date is decided by its size and its timestamp, rather than by size alone - a rebuilt library of the same size used to be kept forever. The first start after an SDK upgrade repopulates the cache and rebuilds the registry once. VisioForgeX.CacheFolder still overrides the location: point it at the application's own native folder before InitSDK to skip the shared cache entirely and load exactly what the application deployed (#1289).

  • [Core] Fixed: an ARM64 Windows application could not find the SDK's native libraries. The runtime looked for them in an x64 subfolder whatever the process architecture, while the ARM64 redistributable packages deploy to arm64, so initialization failed with "GStreamer libraries not found. Check the deployment and add required NuGet packages." x86, x64 and ARM64 processes now each use their own folder (#1289).

  • [Media Blocks SDK .Net] Fixed: AOMAV1EncoderSettings can now create and configure the AOM AV1 encoder on macOS, Mac Catalyst, and Linux. The settings are applied for both Media Blocks pipelines and Video Capture / Video Edit output; the required AOM runtime is bundled for the Apple packages. Two defaults changed so that rate control actually works: MaxQuantizer now defaults to 63 - at its previous 0 the quantizer was pinned, the encoder ignored TargetBitrate, the buffer sizes and the overshoot/undershoot values, and a 720p clip asked for 1500 kbits/sec was written at about 66 Mbits/sec - and TargetBitrate now defaults to 0, meaning the encoder scales its own default to the frame size (256 kbits/sec at 320x240, about 6900 kbits/sec at 1920x1080) instead of applying 256 kbits/sec at every resolution. Any value the encoder would refuse - CPUUsed outside 0-9, DropFrame, OvershootPCT or UndershootPCT above 100, TileColumns or TileRows above 6, a resize or super-resolution denominator outside 8-16, a super-resolution threshold outside 1-63, a TargetBitrate above 2000000 kbits/sec, a quantizer above 63 or a minimum above the maximum - is now left unapplied and reported as a warning rather than dropped in silence or failing the whole pipeline inside the encoder; a refused quantizer pair encodes at 0-63 rather than at the element's own 0, which would have disabled rate control. Threads is now always resolved by the SDK: 0 and any value above the 64 threads the encoder accepts both become this machine's processor count, clamped to 1-64, because the encoder's own automatic count is not clamped and fails to initialize on a host wider than that. TileColumns and TileRows are log2 counts (0 = one, 1 = two, 2 = four), as the encoder takes them. AOM is intended for quality-focused offline encoding; prefer SVT-AV1 for general software encoding because it is substantially faster. On Windows, iOS and Android the av1enc element is still not part of the runtime, so AOMAV1EncoderSettings.IsAvailable() stays false there (#1286).

  • [Core] The OpenCV redistributable packages are rebuilt on OpenCV 4.14.0 and are much smaller. VisioForge.CrossPlatform.OpenCV.Windows.x64 and .x86 shipped OpenCV 4.7.0 from February 2023 together with 42 OpenCV libraries the GStreamer OpenCV elements never load. They now carry OpenCV 4.14.0 and only the libraries those elements need, so the x86 package drops from 94 MB to 44 MB and the x64 package from 113 MB to 64 MB. Part of what the x86 package shed is a 26 MB 64-bit opencv_videoio_ffmpeg470_64.dll that no 32-bit application could ever load. All 23 OpenCV elements are unchanged. The plugin now requires GStreamer 1.28 or newer - the version it is built against, and the version the matching VisioForge.CrossPlatform.Core.Windows.* packages ship; it previously declared 1.22. An application that puts an older GStreamer ahead of the SDK's own on PATH will find the plugin refused, and GStreamer reports that as a single warning, so the OpenCV elements would simply be missing (#1276).

  • [Media Blocks SDK .Net] Fixed: AV1EncoderBlock ignored every SVT-AV1 setting, and several of them did nothing on the other engines too. In Media Blocks the encoder was built and then never configured, so Preset, TargetBitrate, MaxBitrate, CQP, CRF and IntraPeriodLength were all dropped and the encoder ran at its own defaults (preset 10, CRF 35). On every engine, Threads, Tier, TileColumns and TileRows were written to element properties svtav1enc does not have, which GStreamer answers with a warning and no effect; they now reach the encoder the way SVT-AV1 takes them, and TileColumns and TileRows are log2 counts (0 = one, 1 = two, 2 = four) - up to 4 for columns, up to 6 for rows, and at most 128 tiles between them. Values above that are clamped rather than passed through: SVT-AV1 rejects such a configuration outright ("MaxTiles is 128 and MaxTileCols is 16") and the encoder can take the process down with it. Every other setting the encoder would refuse - a Preset outside 0-13, a bitrate outside 1-100000 kbits/sec, a CQP or CRF outside 1-63, an IntraPeriodLength below -2 - is now left unapplied and reported as a warning instead of being dropped in silence, and so is any setting a different rate-control mode makes irrelevant. The encoder keeps its own working default in each case rather than being handed a value it cannot use. CQP never took effect either, on any engine: the encoder picks its rate-control mode in the order bitrate, CRF, CQP, and CRF has a non-zero default, so a CQP-only configuration encoded in CRF mode - setting CQP now disables CRF as it always claimed to. Behavior change: an application that set SVT-AV1 properties through Media Blocks and tuned around them being ignored will now get the encoder it asked for. (#835)

  • [Media Blocks SDK .Net] Fixed: the default SVT-AV1 configuration produced a stream with no keyframes after the first. IntraPeriodLength defaulted to -1, which this encoder reads as insert no further intra frames rather than automatic - so a recording was hard to seek, and a client joining an SRT or RIST stream mid-flight never received a keyframe and never rendered. The default is now -2, the encoder's own automatic setting; pass -1 explicitly if a single-keyframe stream is what you want. This affected the VideoCaptureCoreX / VideoEditCoreX render path, where the value was applied; Media Blocks left the encoder at its own -2 default because it applied nothing at all (#835).

  • [Media Blocks SDK .Net] The SVT-AV1 encoder (SVTAV1EncoderSettings) is now available on macOS and Mac Catalyst. The svtav1enc element and its library ship in the additional runtime package - VisioForge.CrossPlatform.Core.macOS.Adds and VisioForge.CrossPlatform.Core.macCatalyst.Adds - the same way gstsvtav1.dll has always shipped in the Windows .Adds packages. Reference the .Adds package for your platform beside the core one - VisioForge.CrossPlatform.Core.macOS.Adds 2026.8.25 or newer, VisioForge.CrossPlatform.Core.macCatalyst.Adds 2026.8.26 or newer; without it AV1EncoderBlock.IsAvailable(new SVTAV1EncoderSettings()) returns false and the rav1e encoder (RAV1EEncoderSettings) remains the software AV1 option. On iOS no AV1 encoder is available at all (#835).

  • [Core] Fixed: AV1 files did not play on iOS. No AV1 decoder was registered at all, and GStreamer's FFmpeg wrapper deliberately does not provide one, so playback worked only on the chips whose VideoToolbox decodes AV1 (A17 Pro and later) and produced nothing anywhere else. The dav1d software decoder is now registered on iOS, so AV1 plays on every supported device; VideoToolbox is still preferred where the hardware has it. AV1 encoding remains unavailable on iOS - Apple ships no AV1 hardware encoder, and the software AV1 encoders are not part of the iOS redistributable, so SVTAV1EncoderSettings and RAV1EEncoderSettings report unavailable there (#1287).

  • [Core] Fixed: several Apple VideoToolbox encoder settings did nothing on iOS. ForceHWUsage was ignored, PreserveAlpha was not offered at all, AppleMediaHEVCProfile.Main10 warned that it could not negotiate, and RateControl / DataRateLimitBitrate / DataRateLimitDuration were dropped with a warning - all because the SDK still assumed the iOS runtime was the old GStreamer 1.24.9 build. iOS has shipped 1.28.6 for some time, so the HEVC alpha encoder (vtenc_h265a), 10-bit HEVC and the CBR/capped-ABR rate control now work there exactly as they do on macOS and Mac Catalyst. AppleMediaH264EncoderSettings.ForceHWUsage, AppleMediaHEVCEncoderSettings.ForceHWUsage and AppleMediaHEVCEncoderSettings.PreserveAlpha are now present in the iOS build; ForceHWUsage has no effect there, because every VideoToolbox encoder on iOS is hardware and GStreamer registers no separate hardware-only element (#1287).

  • [Core] Fixed: VP8 and VP9 were unavailable in the iOS Simulator. The vpx plugin was registered only on a physical device, although the simulator framework contains it (#1287).

  • [Core] Fixed: on Mac Catalyst no GStreamer log message ever reached the SDK. Every GStreamer debug line was routed to a static shim meant for iOS devices instead of to the SDK's own handler, so nothing appeared in the log context or in Trace, and the DeckLink "Signal lost" notification - which is raised from that handler - never fired on this platform. Gst.GstDebug.RemoveLogFunction also always reported that it had removed nothing, so a host's own log handler installed through Gst.GstDebug.AddLogFunction could not be taken down again. Mac Catalyst now behaves exactly as macOS does: log messages are delivered to managed handlers and removing a handler works. Real iOS is unchanged (#1259).

  • [Media Blocks SDK .Net] Fixed: an RTSP RAW or NDI source restored from a pipeline document validated clean, built clean and then refused to start. StartAsync returned false with "Media info is not available" or "Unable to get NDISource info.", because a document carries a source's endpoint but never its media information, and those two sources pick their elements from it - the depayloader and parser for RTSP RAW, the converters for NDI on desktop. MediaBlocksPipeline.StartAsync now probes such a source once, before it builds the graph, so a restored pipeline starts the way a hand-built one does - as does one whose settings you construct with the public constructor and configure by hand. VideoCaptureCoreX and MediaPlayerCoreX build their graph through the synchronous Start, so an NDI or RTSP RAW source there still needs NDISourceSettings.CreateAsync / RTSPRAWSourceSettings.CreateAsync, as before. The endpoint has to be reachable at that moment, and a source that cannot be read is reported by name. The synchronous Start has nowhere to await a probe and is unchanged - use RTSPRAWSourceSettings.CreateAsync / NDISourceSettings.CreateAsync there. NDISourceSettings gains a ReadInfoAsync method for probing an existing instance. Behavior change: MediaBlocksPipeline.Connect now returns false when a block it would have to add is refused - it reported success and left the block out of the pipeline before, so the graph was built without it and nothing said so. That happens when the pipeline is not stopped: use AddBlockLive / ConnectLive to change a running graph (#1229).

2026.8.29

  • [Core] Fixed: Mac Catalyst reported one placeholder audio device and never asked for camera or microphone permission. AudioSources/AudioSourcesAsync and AudioOutputs/AudioOutputsAsync answered every Catalyst caller with a single "Default" entry carrying no CoreAudio identity, the audio device monitors refused to start (so OnDeviceEnumerationCompleted never fired for them), and the permission request was skipped outright. All three are lifted: Catalyst now enumerates the real CoreAudio inputs and outputs, its audio monitors run, and camera and microphone access is requested the same way as on macOS. The behaviour was introduced against a deadlock that turned out to belong to a test host launched as a bare executable rather than to Mac Catalyst itself. Action required for Mac Catalyst apps: the bundle's Info.plist must now declare NSCameraUsageDescription and NSMicrophoneUsageDescription - the system terminates a process that requests access without them, rather than denying it - and prefer AudioSourcesAsync/AudioOutputsAsync over the synchronous overloads there, since starting the CoreAudio device provider waits behind the permission prompt (#1242).

  • [Media Blocks SDK .Net] Fixed: a pipeline that was stopped and disposed still held every block it contained, so memory grew with each pipeline an application built. Each block's input and output pads carry an end-of-stream probe whose callback is pinned for the life of the underlying GStreamer pad, and nothing released it - the pad, the block, its settings and its encoder or renderer element all stayed alive for the rest of the process. Disposing a pipeline now releases the pads of every block it owns, and a block disposed on its own releases its own; restarting a stopped pipeline is unaffected (#827).

  • [Core] New: Gst.Context is now part of the SDK, and Element.GetContexts() hands back real contexts instead of unusable list wrappers. The generated type had been left out of the build and, as generated, was unusable - a structure with no fields at all, so every one of its members was commented out because it would have handed GStreamer a one-byte buffer where a context pointer belongs. It now carries the native context handle and its members work: constructing a context from its type, reading the context type, the payload structure (read-only and writable) and the persistent and writable flags, testing the type, taking a writable copy with MakeWritable(), and Ref/Unref. Gst.Element.SetContext is new, and the Gst.Element.Contexts property is replaced by a Gst.Element.GetContexts() method returning Gst.Context[] - a breaking change against the previous release, where it was GLib.List[]. It is a method because every call takes a reference on every context that is yours to give back: call it once into a local, release each context with its own Unref(), and do not touch the array afterwards. That replaces the previously documented release step, Gst.Global.ContextReplace(ref handle). A struct has no finalizer, so release a long-lived context once, on the owning instance, since Context copies share the handle; after that release, and on the empty value Gst.Context.Zero, its members throw ObjectDisposedException and InvalidOperationException rather than handing NULL to GStreamer, and IsEmpty is the empty-state discriminator. In the same spirit, three calls that GStreamer would have answered with a log line and a plausible-looking result now say what is wrong: WritableStructure() throws InvalidOperationException on a context something else already holds a reference to (only an unshared context is writable, so write before setting it on an element, not after), Element.SetContext throws ArgumentException on an empty or released context instead of silently doing nothing, and a null context type is refused rather than turned into an empty context or a false type match. The struct also carries an internal released flag next to the handle, so pass Gst.Context values to native code by their handle field, not by marshaling the struct itself. Gst.Uri.Zero and the new Gst.Context.Zero are static readonly rather than plain static fields: now that both structs carry a handle, assigning to the shared empty value would have poisoned it process-wide, so code that wrote to Gst.Uri.Zero no longer compiles. Gst.Toc and Gst.TocEntry had the same field-less defect and are covered by their own entry below (#1257).

  • [Core] New: Gst.Toc and Gst.TocEntry are now part of the SDK, so chapters can be read from a file and written into one. Both generated types had been left out of the build and, as generated, were unusable - structures with no fields at all, so every member handed GStreamer a one-byte buffer where a table-of-contents pointer belongs. They now carry the native handle and their members work: building a table of contents and nesting entries under it, reading and writing entry tags (the chapter title lives there), start/stop times and loops, finding an entry by UID at any depth, and Ref/Unref/Copy. Toc.GetEntries() and TocEntry.GetSubEntries() return Gst.TocEntry[] and replace the Toc.Entries / TocEntry.SubEntries properties, which handed back raw handles. Everything a table of contents is actually reached through came back with them: Message.ParseToc / Message.NewToc, Event.ParseToc / Event.NewToc, DiscovererInfo.Toc, DiscovererStreamInfo.Toc, and TocSetterAdapter.GetToc() / SetToc() - so a TOC can be pulled off the pipeline bus or the discoverer and set on a muxer such as matroskamux - chapters written into a Matroska file this way read back out of it with their titles and start/stop times, nested under the edition Matroska wraps them in. The table of contents on a Gst.ITocSetter is a GetToc()/SetToc() pair rather than a Toc property, because the two halves have opposite ownership: reading takes a reference that is yours to release, writing leaves the reference with you. Toc.AppendEntry and TocEntry.AppendSubEntry take their argument by ref: the call takes the entry's reference over, and passing by reference is what lets the binding mark the caller's value released so a later Unref() cannot corrupt GStreamer's reference count. Values that come from a getter GStreamer does not transfer - the entries of a TOC, an entry's parent or sub-entries, a discoverer's TOC - are borrowed: they are readable and editable but refuse Unref(), and IsBorrowed reports which is which; take Ref() or Copy() to keep one past its owner. Calls GStreamer would have answered with a log line and a plausible-looking result now say what is wrong: writing tags to or appending an entry to something else already holds a reference to, appending an entry that already belongs to a table of contents, parsing a TOC out of a message or event that is not a TOC one, and null or out-of-range arguments are all refused with an exception. A struct has no finalizer, so release a long-lived value once, on the owning instance; after that release, and on the empty values Gst.Toc.Zero / Gst.TocEntry.Zero, members throw rather than handing NULL to GStreamer, and IsEmpty is the empty-state discriminator - it is also how a missed FindEntry and a top-level entry's absent parent report themselves. As with Gst.Context, pass these values to native code by their handle field, not by marshaling the struct itself (#1257).

  • [Core] Fixed: GES.Global.ListAssets() could hand out freed assets and leaked a native list on every call. GES lends out the assets its cache owns and asks the caller to free only the list holding them, but the binding did the opposite - it kept the list and released every asset, spending the reference the cache still relies on. An asset could then be finalized while still registered, so a later request for the same asset returned freed memory. The assets are now left alone and the list is released (#1231).

  • [Core] Fixed: overriding a gio or GES virtual method that returns a list could corrupt memory or crash. FileEnumerator.OnNextFilesFinish, the four Resolver lookups, the three VolumeMonitor collections, GES.Container.OnUngroup and the GES track-element creation callback each built two native lists over the same result and released neither, referencing every element twice and then walking the already-freed list from the finalizer, which crashes the process. Every callback that returns a list now hands the caller exactly one, with the ownership its documented transfer mode calls for, and gives up its own claim on it - so a list an override built and still holds is no longer freed twice (Resolver.OnLookupRecords, OnLookupRecordsFinish, TlsDatabase.OnLookupCertificatesIssuedBy, OnLookupCertificatesIssuedByFinish). Resolver.OnLookupService and OnLookupServiceFinish additionally threw on every call and could not be overridden at all; they now work (#1248, #1247).

  • [Media Blocks SDK .Net] Windows: the bundled GStreamer runtime moves from 1.28.2 to 1.28.6, on x64, x86 and ARM64. 1.28.3 through 1.28.6 are bug-fix and security-fix releases - nvcodec, RTP/RTCP, h264parse/h265parse duration handling, a compositor regression and HLS live seekable ranges among them - and Windows now matches the runtime macOS, Mac Catalyst and iOS already ship. The WASAPI capture buffer size restored in 2026.8.1 is unaffected: the patched wasapi2src/wasapi2sink were rebuilt against 1.28.6 and re-measured, since the upstream defect is still present in this release. New elements, on x64 and x86: objectdetectionoverlay and segmentationoverlay for drawing detection and segmentation results, onvifmeta2relationmeta/relationmeta2onvifmeta for moving analytics metadata to and from ONVIF, burn-yoloxinference for YOLOX inference, demucs for audio source separation, msesrc, the curl sinks and source (curlhttpsink, curlfilesink, curlftpsink, curlsmtpsink, curlhttpsrc), and originalbuffersave/originalbufferrestore. rsvgdec and rsvgoverlay reach x86, which did not have them; x64 already did. ARM64 gains no elements in this release and loses dvdreadsrc and rsndvdbin - upstream no longer builds the DVD plugins for that architecture. No bundled library changes file name on x64 or x86, so an incremental rebuild needs nothing special there.

  • [Media Blocks SDK .Net] Windows ARM64: VisioForge.CrossPlatform.Core.Windows.Adds.arm64 is an add-on package now, not a second copy of the runtime. It used to mirror the whole GStreamer install, so installing it next to VisioForge.CrossPlatform.Core.Windows.arm64 downloaded 55 MB twice and wrote every file into the output folder twice, with no way to tell which copy won. It now carries only the additional plugins and their private dependencies, exactly as the x64 and x86 Adds packages do, and declares a dependency on the ARM64 Core package - referencing the Adds package alone is enough, NuGet brings the Core package with it. Nothing is lost: the two packages together still ship every element ARM64 had before. rsvgdec and rsvgoverlay also move from the x86 Adds package into the x86 Core package, so the SVG elements come from the same package on all three architectures (#1261).

  • [Media Blocks SDK .Net] Windows ARM64: three x64 DLLs that could never load are no longer shipped in the ARM64 runtime. libgcc_s_seh-1.dll, libstdc++-6.dll and libwinpthread-1.dll came straight from the upstream ARM64 GStreamer installer, which ships the x64 MinGW runtime under its ARM64 tree; nothing in the ARM64 packages referenced them. Removing them makes the package about 8 MB smaller to download (27 MB on disk) with no element lost (#1261).

  • [Media Blocks SDK .Net] Windows x64 and x86: the unused MinGW C++ runtime is no longer shipped. The GStreamer build drops libstdc++-6.dll and friends into an otherwise MSVC runtime, and on x64 nothing referenced any of them - libgcc_s_seh-1.dll, libstdc++-6.dll and libwinpthread-1.dll are all gone, about 8 MB less to download (27.9 MB on disk). On x86 only libstdc++-6.dll goes, about 7.5 MB less (23.9 MB on disk): the rest of that runtime is really used there, by the mp3 decoder. Every plugin still loads on both architectures - verified with gst-inspect-1.0 against the package files alone, 192 plugins and none blacklisted (#1277).

  • [Core] Fixed: GLib.List and GLib.SList leaked the string copies they allocate. Building a list from managed strings with elementsOwned: false duplicated every string into glib memory and freed nothing on dispose, leaking each copy for the life of the process. The wrapper now releases the storage it allocated itself on Dispose() / Empty(), while elements a native list lent it stay untouched - a list mixing borrowed and managed elements frees exactly what it allocated. A borrowed wrapper that released element storage refuses further use: reads and appends throw ObjectDisposedException instead of touching freed memory, while an owned list survives Empty() as an empty list whose later string appends are released on the next Empty(). Clone() of a string list frees its copies on the clone instead of the source (#1232).

  • [Core] Fixed: six more list-returning GStreamer properties handed back unreadable elements and leaked. VideoDecoder.Frames, VideoEncoder.Frames, Toc.Entries, TocEntry.SubEntries, Adapter.GetList and Adapter.TakeList all typed their elements as the list container itself, so every element was a wrapper over a pointer that is not a list node and read as garbage. Where GStreamer transfers ownership of the elements, disposing that array also released each of them as if it were a GObject - which GStreamer silently ignores, leaking a reference per element on every call. Each property now returns its real element type with the ownership GStreamer documents: Gst.Buffer[] for the two Adapter methods, which release themselves, and raw handles for VideoDecoder.Frames / VideoEncoder.Frames, whose element type cannot carry a native pointer. Note where GStreamer transfers ownership, the reference is now yours to release: each handle from those two with the new Gst.Video.VideoCodecFrame.Unref(IntPtr). The two table-of-contents properties are covered by the Gst.Toc entry above. The old GLib.List[] signatures are removed. The element contexts carried the same defect and are covered by the Gst.Element.GetContexts() entry above (#1240).

  • [Core] Fixed: native text in GStreamer binding structures was decoded with the system ANSI codepage instead of UTF-8. Names, descriptions, hosts, credentials and addresses read through ElementFactory.StaticPadTemplates, Gst.Video.VideoFormatInfo, Gst.Audio.AudioFormatInfo, Gst.FormatDefinition, Gst.PluginDesc, Gst.Rtp.RTPPayloadInfo, the RTSP (RTSPUrl, RTSPTransport, RTSPAuthParam, RTSPAuthCredential, RTSPAddress), SDP, WebRTC, gio and Pango structures all came back as mojibake on any Windows codepage that is not UTF-8. They now decode as UTF-8. ElementFactory.StaticPadTemplates additionally leaked a string copy on every access to a template's Get() or Caps and handed GStreamer a re-encoded copy of its own text in place of the original; that leak is gone. Two consequences there, both breaking: Gst.StaticPadTemplate.NameTemplate and Gst.StaticCaps.String are now read-only properties rather than settable fields (they carry the native pointer, and code that assigned one, took it by ref/out, or reflected over it as a field will not compile), and comparing two StaticPadTemplate or StaticCaps values now compares the native text identity rather than the decoded characters (#1240).

2026.8.28

  • [Core] Fixed: GStreamer wrapper members silently did nothing after Dispose(). Calling any member of a disposed Gst.Caps, Buffer, BufferList, TagList, Structure, Message, Event, Query, Sample, Memory, MiniObject, DateTime, Iterator, Promise or DebugMessage handed a NULL handle to GStreamer, which logged a silent critical and carried on — or returned a quiet default that looked like real data; the struct-field accessors (Buffer.Pts, Caps/Structure field reads) read through a NULL pointer outright. Those members now throw ObjectDisposedException naming the type, so the misuse surfaces at the call site. Dispose() stays idempotent, and Handle, Owned, Equals and GetHashCode keep working on a disposed wrapper, so release-once code and comparisons are unaffected. Also fixed here, the same defect in three places: new Gst.Sample(buffer, caps, segment, null), Message.AddRedirectEntry(location) — which threw on every call — and Buffer.ReplaceMemory/ReplaceAllMemory/ReplaceMemoryRange with a null memory (the way to drop memory blocks without inserting a replacement) all threw NullReferenceException, because the optional argument was dereferenced before its own null check (#1241).

  • [Core] Fixed: Gst.GstDebug.GetAllCategories() returned unusable data. Its elements were typed as GLib.SList while GStreamer actually hands back debug categories, so reading an element produced garbage values or a crash, and a category's name and description were unreachable. The method now returns Gst.DebugCategory[] - a value-copy struct exposing the category name, description, color and current threshold, decoded as UTF-8. Two members that silently did nothing now throw NotSupportedException and are marked [Obsolete]: DebugCategory.Free() (deprecated upstream no-op) and DebugCategory.ResetThreshold() (wrote into a temporary copy, never into the live category). DebugCategory equality now compares the category's native identity plus the copy's threshold and color, instead of comparing decoded strings. The old GLib.SList[] signature is removed (#1233).

  • [Core] Fixed: starting or stopping audio on iOS could hang the app. The bundled iOS GStreamer held the audio ring-buffer lock across the CoreAudio start/stop calls that wait for the render callback to finish; the render callback takes the same lock. The start path was already fixed upstream for iOS 17+, and the same fix now covers the stop path and the pre-1.28 render-callback teardown (#1131).

  • [Core] The iOS bundled GStreamer runtime moved from 1.24.9 to 1.28.6, matching macOS and macCatalyst. Brings the 1.26/1.28 plugin set to iOS (the reworked direct-rendering decode path, io_proc_dropping audio teardown, the VideoToolbox rate-control properties and the alpha encoder variant) and ends the divergence where iOS alone shipped a runtime without the deadlock fixes above. The Metal compositor plugin (vfmetalcompositor) is now part of the iOS framework. The official 1.28.6 iOS package no longer carries frei0r, and it replaces y4mdec/y4menc with the single y4m plugin.
  • [Media Blocks SDK .Net] Fixed: stopping a capture session after a source error could crash the process. A microphone or other live source that failed during the session no longer access-violates on StopAsync; a recording that was still producing video is still finalized (#825).
  • [Media Player SDK .Net] Fixed: switching audio on a multi-track file jumped the picture back to the first video track, and switching video silenced the playing audio. Audio_Stream_Select / Video_Stream_Select on MediaPlayerCoreX and SimplePlayerCoreX now keep the streams they are not switching. SimplePlayerCoreX.Audio_Streams_Current reports the active audio index instead of a hardcoded 1 (#1216).
  • [Core] Gst.Uri members now throw on a released or empty instance instead of failing silently. Reading a property, converting to a string or mutating a Gst.Uri after its Unref() — or on the empty value Gst.Uri.Zero — used to hand NULL to GStreamer, which logged a silent critical or quietly returned an empty result indistinguishable from a real one. These members now throw ObjectDisposedException after release and InvalidOperationException on the empty handle; managed comparison (Equals/GetHashCode), a repeated Unref() and ToString() on the empty value (it renders as an empty string) keep working. The new IsEmpty property is the parse-failure discriminator. Struct copies taken before the release still share the handle and stay unreusable after it — release once, on the owning instance. The struct also carries an internal released flag next to the handle, so pass Gst.Uri values by their handle field to native code, not by marshaling the struct itself (16 bytes on 64-bit) (#1236).
  • [Core] New: Gst.Uri is now part of the SDK. The generated type had been left out of the build and, as generated, was unusable. It now carries the native URI handle and its members work: constructing from parts or parsing a string, reading scheme, host, path, fragment, the query table and the query keys, joining a reference against a base. The handles the constructors return own a reference and a struct has no finalizer, so release a long-lived one with its Unref() method - once, on the owning instance, since Uri copies share the handle. Also, GLib.PtrArray.Clone() on an elements-owned array whose element type is not a GObject now throws ArgumentException instead of silently sharing element storage that dies with the source (#1205).
  • [Core] Fixed: GES.TrackElement.AllControlBindings returned garbage on every read. GStreamer hands back a hash table there, not a list, and the binding read the hash table's memory as a list. The property now returns the control-binding property names through g_hash_table_get_keys and frees the temporary list it builds; the list marshaller refuses any non-list native return with a clear exception, and a NULL return still reads as an empty array (#1205).
  • [Core] Fixed: Gst.GstDebug.GetAllCategories() leaked the native category list on every call. GStreamer hands back a copy of the process-static debug categories that the caller must free, but the GLib.SList wrapper discarded its ownership flags, so disposing the wrapper freed neither that list nor - on any other SList-based API - the elements it claimed to own. The flags are now honoured: an owned SList frees its container and takes a reference per GObject element, a borrowed one releases nothing; ownership of element storage it cannot release (boxed handles, raw ints, value-type copies) is refused with ArgumentException, Clone() on both list wrappers now owns and frees its copy instead of leaking it and enumerating through a lost element type - and copies the elements themselves, so a clone survives its source's disposal - and every read of a disposed wrapper throws ObjectDisposedException instead of reading freed memory (#1205).

2026.8.27

  • [Core] Fixed: device enumeration could hang forever on Mac Catalyst. AudioOutputsAsync, AudioSourcesAsync and camera/microphone permission requests relied on CoreAudio/AVFoundation calls that never return in some macabi processes; the permission ask is now bounded — skipped with a warning only where the query is measured to never answer — and audio enumeration falls back to a safe single default device, so Catalyst apps no longer wedge on startup-time enumeration (#1150).
  • [Core] Fixed: macOS startup logged hundreds of GIO module-load failures and a duplicate OpenSSL TLS backend registration. SSL initialization now loads only the intended GIO TLS module, once, instead of treating every dylib in the app bundle as a GIO module (#1200).
  • [Core] Fixed: reading Video_Streams, Audio_Streams or Subtitle_Streams while a stream switch was in progress could throw InvalidOperationException. The bus thread used to empty and refill those lists in place; a property read that landed in the middle of that update now sees a complete snapshot (#1219).
  • [Video Edit SDK .Net] Fixed: audio settings changed between two renders on one VideoEditCoreX were silently ignored by the second render. Output_AudioChannels and Output_AudioSampleRate written after a render had finished never reached the rebuilt timeline's audio track, so the next output kept the previous render's channel count and sample rate. The output settings are now applied to the tracks of the pipeline being started (#850).
  • [Video Edit SDK .Net] Fixed: Input_AddVideoLayer and Input_AddTestClip threw NullReferenceException when used after a render had finished. Both now rebuild the timeline first, as Input_Clear_List and the file inputs already did, so a second editing session on one instance works (#850).
  • [Video Edit SDK .Net] Fixed: Debug_Mode did not enable the SDK's debug-level diagnostics. The engine configured a debug logger but left its context in non-debug mode, so debug entries were dropped before reaching the log file (#850).
  • [Video Edit SDK .Net] Fixed: memory grew across renders that use fade transitions. Each FadeIn / FadeOut on a clip leaked a GStreamer control source per render, so a long editing session or a batch of renders accumulated them (#850).
  • [Core] GLib.List now refuses to build an element-owning list it cannot honour instead of corrupting reference counts. Passing elementsOwned: true while appending wrapped objects used to store their borrowed handles and release them on Dispose(), spending references the list never took; it now takes a reference of its own for a GObject element, and throws ArgumentException for an element it cannot reference at all - an Opaque, an element that does not match the declared element type, or a disposed wrapper (#839).
  • [Core] Fixed: switching audio or video streams leaked a small amount of native memory on every switch. Audio_Stream_Select / Video_Stream_Select on MediaPlayerCoreX and SimplePlayerCoreX built the SELECT_STREAMS stream-id list without ownership flags, so its disposal freed neither the list nodes nor the copied stream-ID strings; the list is now built owned and freed after the event is sent. A stream with no ID is now rejected with a log entry and false, where SimplePlayerCoreX used to throw on a null stream and both engines silently sent an event that changed nothing (#1208).
  • [Core] Fixed: Gst.Event.ParseSelectStreams leaked the returned list. The C builds a fresh list of copied stream IDs and hands the ownership over, but the binding wrapped it without ownership flags, so disposing the wrapper freed neither the list nodes nor the strings (#1208).
  • [Core] New: DeviceEnumerator.OnDeviceEnumerationCompleted reports when the first enumeration of a device list has finished, so an application can start a device monitor without waiting for it and show its own "enumerating..." state while the list fills through OnVideoSourceAdded / OnAudioSourceAdded / OnAudioSinkAdded. DeviceEnumerationCompletedEventArgs names the list: VideoSources, AudioSources or AudioOutputs (#1108).
  • [Core] Starting a device monitor no longer reads the device list while holding a lock shared by every DeviceEnumerator in the process. The monitor now waits for GStreamer to report that its device providers are up - they start on their own thread from GStreamer 1.28 on - and reads the list afterwards, when that read no longer blocks. On macOS the wait covers the camera or microphone permission dialog, so a dialog left on screen no longer holds up unrelated enumerations for as long as it is up (#1108).
  • [Media Blocks SDK .Net] Fixed: a recording or streaming branch could stop reporting end-of-stream, and a source could hand out a video or audio pad that was already dead. Across the output blocks (MP4, MKV, AVI, WebM, FLV, WMV, MP3, M4A, FLAC, Ogg, YouTube, Facebook Live), the RTMP/RTSP/NDI/UDP sources, the demuxers, the audio and video effects blocks and the overlay managers, a GStreamer pad was released while the block that owned it was still using it. Nothing failed visibly at the time - the next call on that pad simply did nothing - so the symptoms were downstream: end-of-stream never firing, a recording left unfinalized, or a pad handed to an OnVideoPadAdded / OnAudioPadAdded subscriber going inert as soon as the handler returned (#850).
  • [Media Blocks SDK .Net] Fixed: InterPipeSinkBlock.IsAvailable() and InterPipeSourceBlock.IsAvailable() could report that InterPipe was installed when only the unrelated proxy elements were present. The probes now check the actual interpipesink and interpipesrc elements, so platform and deployment availability is reported accurately (#1193).
  • [Core] Reading a queue's fill level no longer enumerates the element's whole property list. QueueBlock.CurrentLevelBuffers, CurrentLevelBytes and CurrentLevelTime are meant to be polled per frame, and each read used to build a managed descriptor for every property the element declares; a poll of all three now allocates about a fifth of what it did. The same applies to any element property probed through PipelineHelper.ElementHasProperty, which additionally reports false for an element that has already been released instead of answering from the base element type.
  • [Media Blocks SDK .Net] A live pipeline can now be saved as a JSON document. MediaBlocksPipeline.ToDocument() captures the running graph - blocks, their identities and their connections - and ToJson() / SaveJsonAsync(path) write it out; the capture is safe while the pipeline is playing, which makes it the save-during-Run path. A block that does not expose its settings contributes its position but not its configuration, and says so through a diagnostic rather than producing a document that would rebuild it on defaults - check MediaBlocksPipelineSnapshotResult.Complete before treating a capture as a faithful copy.
  • [Media Blocks SDK .Net] A relative file path named by a *Location setting now resolves against the document base directory, which is what the HLS sink calls its segments, its playlist and its init segment.
  • [Core] Fixed: reading or animating a video mixer input that has no sink pad crashed instead of reporting no such input. A stream added to the mixer settings after the block was built never gets a pad of its own, and reading it back or starting a fade or move on it walked off the end of the pad list. Such a call now returns null / does nothing and reports it through the log, on VideoMixerBlock and GLVideoMixerBlock on every platform and on the D3D11 compositor on Windows; the Metal compositor on macOS and iOS already behaved this way and now logs it too. A fade or move whose input pad is released while it is running also stops cleanly instead of leaving the input part-way through the animation (#1191).
  • [Core] Fixed: constructing a GLib.PtrArray threw EntryPointNotFoundException on Windows. The type declared its g_ptr_array_* entry points against libgobject and its g_object_unref against libglib - exactly backwards - so the first call into the type failed on Windows, while Linux and macOS resolved the symbols through library dependencies by accident. Each import now names the library that actually owns its symbol (#1207).
  • [Core] Fixed: cloning a GLib.PtrArray crashed the process, and every clone leaked the native container. Clone() called g_ptr_array_copy through a one-argument declaration, while the native function takes three (array, copy function, user data) - the missing arguments arrived as garbage and were called as a function pointer. It now declares the real signature and passes NULL for a shallow copy, as the C API allows, the clone owns its copied container so Dispose() actually frees it, and cloning a disposed array throws ObjectDisposedException instead of crashing later (#1207).
  • [Media Blocks SDK .Net] New: VideoMixerBlock.RemoveInputPadLive removes an input that was added with AddInputPadLive and hands the mixer's input back to it. A live-added input used to occupy a mixer input permanently - the only way to reclaim it was to tear the pipeline down. Removal is safe against a running graph: the input is stopped and unlinked first, then the mixer reclaims its pad. Only live-added inputs can be removed; the inputs configured at build stay index-aligned with the mixer's stream settings. Also fixed: the tee helper and the muxer sinks' ConnectVideo (MP4, MKV, AVI, MOV, WebM, OGG, FLV, MPEG-TS) kept a requested pad when a connection failed instead of handing it back (#1210).
  • [Media Blocks SDK .Net] Fixed: the video and audio effect blocks could not be restored from a pipeline JSON document. VideoBalance, VideoResize, VideoCrop, VideoBox, the OpenGL effects, the audio effects and thirty-odd of their siblings all failed with "no construction path", because their settings class is named after the effect - ResizeVideoEffect, CropVideoEffect - rather than ending in Settings. The block catalog now also reads a block's own Settings property. Across its 387 blocks, and counting the correction below, the number a document can restore went from 314 to 329 and the number a caller holding only a descriptor can create from 216 to 288 - TextOverlay, ImageOverlay, VideoMixer, HLSSink and the OpenCV filters among them.
  • [Media Blocks SDK .Net] Fixed: a crop or a video box restored from a document came back cropping nothing. CropVideoEffect and BoxVideoEffect kept their four edges behind a private setter, so the margins were dropped in both directions of the serializer and the stage became a passthrough while reporting success. The edges are now settable.
  • [Media Blocks SDK .Net] Three blocks that took their whole configuration as a bare value gained a settings class: FlipRotateSettings, WAVSinkSettings and BarcodeDetectorSettings. A rotation, a WAV recording destination and a barcode detector mode can now be stored in a pipeline document and edited through the block catalog's property metadata. The existing constructors are unchanged.
  • [Media Blocks SDK .Net] ResizeVideoEffect, CropVideoEffect, BoxVideoEffect, GLResizeVideoEffect, ImageOverlaySettings and TextOverlaySettings gained a public parameterless constructor, which is what JSON deserialization needs; the crop and the box default to a passthrough and the two resizes to 1920x1080.
  • [Media Blocks SDK .Net] Fixed: seven network sources could not be restored from a pipeline JSON document. HTTPMJPEGSource, NDISource, NDISourceX, RTMPSource, RTSPRAWSource, SRTSource and SRTRAWSource passed preflight validation and then failed halfway through materialization, because the only constructor on their settings class was private - an async CreateAsync probes the endpoint before handing one back. Each of those settings classes now has a public parameterless constructor for the persistence path; CreateAsync is unchanged and remains the way to probe a reachable endpoint up front. A source built from a document does not contact its endpoint until the pipeline opens it.
  • [Media Blocks SDK .Net] Fixed: a document naming SRTSource or NDISourceX built the wrong block. SRTSourceSettings is shared by the decoding and the raw SRT source and NDISourceSettings by the NDI and the Windows-only NDI X source, while CreateBlock() on each names only one of the pair - so the other came up as its sibling, with different pads, and the document's own connections then failed to resolve. A settings class shared by two blocks now reaches its block through the block's own constructor.
  • [Media Blocks SDK .Net] RTSPRAWSourceSettings.Uri and .AudioEnabled are now settable. Both were read-only outside CreateAsync, so a document's endpoint and audio flag were dropped in both directions of the serializer and the source came up pointing nowhere while reporting success.
  • [Media Blocks SDK .Net] Fixed: nineteen block types built a different block than the one you asked for. MediaBlockCatalog.Get(MediaBlockType.MP4Output).CreateBlock() returned an MP4SinkBlock - a bare muxer instead of the whole encode-and-mux stage - and so did a document naming one. PlayBinSource came back as a UniversalSourceBlock, SeparateOutput as a BridgeVideoSourceBlock, UniversalSourceMini as a UniversalSourceBlock, SRTSink as an SRTMPEGTSSinkBlock. The cause: several blocks share one settings class, whose CreateBlock() names only one of them, and the catalog called it for all of them. A shared settings class now reaches its block through the block's own constructor.
  • [Media Blocks SDK .Net] A block whose settings alone cannot build it is now refused up front instead of failing halfway through loading a document. Twenty-four block types name a settings class but also require a second one the document cannot carry - the *Output blocks want encoder settings, DecklinkVideoAudioSink a second sink settings, SeparateOutput a live pipeline. They reported themselves constructible, passed preflight validation, and then failed during materialization, which discards the whole pipeline over one entry. Preflight now reports MBS032 naming the block, and MediaBlockDescriptor.CanConstruct answers what the loader can actually do.
  • [Media Blocks SDK .Net] Fixed: RTSPSource, RTSPRAWSource and RTMPSource threw NullReferenceException instead of reporting an empty URL. The "URL is empty" check dereferenced the URI it was testing, so a source built without one crashed rather than logging and refusing to build.
  • [Media Blocks SDK .Net] Fixed: AudioMixer was configured through the wrong settings class. The block catalog bound it to AudioMixerSourceSettings, which needs a live pipeline and cannot be created at all, instead of AudioMixerSettings - so the mixer offered the wrong properties to edit, a pipeline document could not carry its output format, and IgnoreInactivePads was unreachable from a document. The catalog now prefers a constructor that can actually be called when a block has several.
  • [Demos] Media Blocks Studio: the Player and picture-in-picture scenarios now carry the effect stages they describe - colour balance, a mirror and an upscale on the player, a crop and a resize on the picture-in-picture camera branch.

2026.8.26

  • [Demos] Media Blocks Studio: nine bundled scenarios that run offline. The startup screen shows nine curated pipelines - player and live effects, camera capture, screen+camera picture-in-picture, live mixer, transcoding, multi-output streaming, AI vision, audio lab and RTSP - each with a still captured from its own output, an outcome line, media tags and platform/requirement chips. Every scenario is an ordinary JSON document under Assets/Scenarios that the app reads at runtime, so the file you open, edit and save is the file the gallery runs. The baseline needs no camera, network or media file: five scenarios generate their own video and audio and three read a bundled clip. "Run Demo" opens the graph and starts it; two scenarios first ask for what the bundle cannot carry - an RTSP endpoint and a path to an ONNX detection model.
  • [Demos] Fixed: the Media Blocks Studio editor came up empty. Opening a pipeline showed the toolbar over a blank area with no canvas, block catalog, inspector or panels, and the block catalog reported no blocks at all. The application did not include the Dock and Nodify control themes, presented its panels with the wrong data, and never initialized the SDK. Connections between blocks are now drawn as well: a node was previously built with one input and one output regardless of the block, so anything wired to an indexed pad - a mixer input, a source's audio output - was dropped silently.
  • [Media Blocks SDK .Net] Fixed: several blocks could not be restored from a pipeline JSON document. RTSPSource, VideoMixer and Tee entries failed to materialize, and Volume and Equalizer10 could not carry their gain, mute or band values at all, because those settings types had no constructor the persistence layer could call and, for the two audio blocks, no settings type at all. VolumeSettings and Equalizer10Settings are new; RTSPSourceSettings and VideoMixerBaseSettings gained a public parameterless constructor; TeeBlock gained constructor defaults. Settings whose only constructor takes all-optional parameters - VirtualAudioSource among them - are now accepted too.
  • [Media Blocks SDK .Net] A relative file path in a pipeline document now resolves against the document base directory even when the setting is a URI, which is the shape UniversalSourceSettings uses, so a document can reference an asset shipped beside it.
  • [Media Blocks SDK .Net] Preflight validation now reports an input asset that does not exist - a detection or OCR model path, or a local file URI - as an error instead of letting the pipeline materialize into a stage that silently does nothing. A sink filename is an output and is still not required to exist.
  • [Core] Fixed: ElementX.ReadProperties() returned structure-typed element properties (for example rtspsrc sdes) whose native memory was already freed, so reading such an entry afterwards could crash or return garbage. Boxed values are now kept as a deep copy (#1184).
  • [Core] Fixed: ElementX.ReadProperties() aborted with an exception on elements holding properties without a managed representation (for example gltransformation) instead of skipping them; unreadable properties are now skipped, and calling the method again refreshes existing entries instead of failing (#1184).
  • [Core] Fixed: ElementX.ReadProperties() raised a GLib critical for every write-only element property (for example playbin subtitle-font-desc) by trying to read a value such a property cannot have. Those properties are still listed, with a null value, and are no longer read (#1184).
  • [Demos] Media Blocks Studio: generated Inspector, Help, runtime controls and crash recovery. The editor now generates the Inspector form from each block's descriptor property metadata (typed parsing with min/max clamping; live-safe properties apply to the running pipeline without a rebuild) and a Help card from the block descriptor. The workspace gained Run/Pause/Resume/Stop over MediaBlocksPipelineMaterializer with error/stop event logging, position polling, structured diagnostics navigation and a single-slot live video preview. Pipelines autosave to %AppData% on a 10 s debounce with a restore prompt on the next start, and unsaved changes are confirmed before New/Open/close.
  • [Media Blocks SDK .Net] Local file sources are now JSON-serializable. UniversalSourceSettings and DemuxerSourceSettings had only a private constructor and private setters for their file/URI properties, so a pipeline document carrying a local file could not be loaded or materialized. Both now expose a public constructor and settable URI/Filename/render flags, so file-based pipelines round-trip through the versioned JSON document format.
  • [Core] Fixed: the LUT (color lookup table) video effect silently did nothing on Intel Macs. The native processor library shipped in the macOS and Mac Catalyst packages was built for Apple Silicon only, so on an x86_64 Mac it could not be loaded at all and every LUT-based effect was a no-op. The library is now a universal x86_64+arm64 binary (#1101).
  • [Core] Fixed: calling VProcessor.UpdateFilterParameters threw EntryPointNotFoundException on macOS/macCatalyst. The shipped native library predated the managed wrapper and did not export the entry point; it now does (#1157).
  • [Core] The GStreamer log callback no longer claims ownership of logged objects. The SDK's log handler built a managed wrapper around the subject object of every log line GStreamer emitted, including plugin-internal GObjects the SDK never created; for an object that logs while still floating (any GstObject logging before its owner sinks it) the wrapper adopted the floating reference, so the owner's later unref finalized the object while the binding still held a toggle reference on it — surfacing as [VisioForge-Lifetime] toggle ref outlived its object and, in Release, as a use-after-free risk whenever debug logging was enabled (#1165). Handlers registered through Gst.LogFunction now receive _object = null unless a managed wrapper for the logged object already exists.
  • [Core] Fixed: custom GStreamer log handlers could never be detached on desktop platforms. Gst.GstDebug.RemoveLogFunction compared against a freshly built native function pointer instead of the one recorded at registration time and therefore matched nothing; every handler stayed installed for the life of the process. Removal now unregisters by the handle captured when the handler was added — the same scheme already used on Unity. As a consequence, removing without an argument detaches only the handlers this assembly registered rather than every log function in the process, so third-party and default GStreamer logging survives SDK teardown (#1165).
  • [Core] Fixed: native memory grew steadily while reading GStreamer element properties. Long-running pipelines leaked a small native allocation on every property read: QueueBlock level properties (CurrentLevelBuffers/CurrentLevelBytes/CurrentLevelTime, typically polled per frame), video mixer and compositor input reads, OpenGL shader and 360-view settings updates (a whole structure copy per update, so dragging a slider accumulated allocations for the process lifetime), file sink filename reads, and the volume/mute getters of the system and PulseAudio audio sources and of the audio renderer (#1185).
  • [Core] Fixed: InterPipeSinkBlock.GetNumListeners() always returned 0, whatever the number of connected InterPipe sources (#1185).
  • [Core] Fixed a slow native memory leak in device enumeration: every probed device property leaked one boxed GValue per enumeration pass (#1174).
  • [Core] Fixed: one audio device losing a property-probe race (device removed mid-enumeration) aborted the whole output-enumeration pass, hiding every device enumerated after it; the pass now continues, with the failure contained to that single entry.

2026.8.25

  • [Demos] New: Media Blocks Studio, the cross-platform Avalonia showcase and pipeline editor for Media Blocks SDK. The first stage ships the application shell under _DEMOS/Media Blocks SDK/Avalonia/Media Blocks Studio (Windows net10.0-windows, macOS net10.0-macos, Linux net10.0): a dark broadcast-style startup gallery with New/Open/Recent projects, an IDE-style workspace built on Nodify.Avalonia 2.0.0 (infinite node canvas with pan, zoom, selection and connection dragging) and Dock.Avalonia 12.0.0.2 (catalog on the left, Inspector/Help tabs on the right, Preview/Metrics/Diagnostics/Logs docked at the bottom). The searchable block list reads the SDK's read-only block catalog directly; pipelines are created, edited, validated against MediaBlocksPipelineValidator, saved to and loaded from the versioned JSON document format with undo/redo.
  • [Media Blocks SDK .Net] New: document-to-live materialization and preflight validation. A pipeline JSON document can now be turned into a running-ready MediaBlocksPipeline: MediaBlocksPipelineMaterializer.Materialize builds every block through the block catalog, binds settings from their JSON payloads (including all-optional-parameter constructors), resolves host resources through IMediaBlockResourceResolver, restores connections using the documented input/output/input:N/output:N pad id convention, and returns a document-block-id to live-block mapping with full diagnostics. Blocks that cannot be created - unknown type, missing factory, unavailable on this platform - stay in the document as placeholders with an error diagnostic; they never discard the rest of the pipeline. MediaBlocksPipelineValidator.Validate performs the complete preflight check: structure, known blocks, construction paths, availability probes, pad reference shape, resource resolver presence and unsupported feedback cycles; errors block materialization and run, warnings do not. Relative file paths inside settings resolve against the document directory when one is given (baseDirectory). New convenience: MediaBlocksPipeline.LoadJsonAsync replaces the contents of a stopped pipeline from JSON in one call.
  • [Media Blocks SDK .Net] Metal-accelerated video elements are now available on Intel Macs. The vfmetal* plugin shipped in the macOS and Mac Catalyst runtime packages was built for Apple Silicon only, so on an Intel Mac it could not be loaded at all and every element it provides - the Metal compositor, video sink, filter, converter/scaler, transform, deinterlacer and overlay - was simply absent from the GStreamer registry. It is now a universal x86_64+arm64 binary (#1101).
  • [Video Capture SDK .Net] Fixed: video frames could silently stop flowing after live video effects were removed or cleared during capture (Video_Effects_Remove by instance or name, and Video_Effects_Clear). The pause issued before the filters are unplugged and the resume after are asynchronous GStreamer state changes, but the resume was not waited out - a PAUSED to PLAYING transition that never completes stops frames with no error raised anywhere. Both operations now wait (bounded) for the resume to settle and report through OnError if the pipeline fails to return to the playing state (#1152). Behavior change: removing or clearing effects while capture is paused no longer resumes playback - a deliberate pause is preserved, matching what live effect addition has always done.
  • [Media Blocks SDK .Net] Fixed: stopping an SRT pipeline could hang StopAsync forever on macOS when the peer was unreachable or kept dropping the connection, and a test or app that gave up mid-stream could then die with a SIGSEGV at process exit. The native SRT sink captures the auto-reconnect setting once per write/read call, so turning reconnect off while the streaming thread was already inside its reconnect loop did not end the loop - EOS could never reach the sink and teardown blocked indefinitely. Both SRT sink blocks now receive an early stop signal (RequestStop) that disables auto-reconnect before EOS, and the macOS native package's libgstsrt.dylib honors a mid-flight reconnect switch-off instead of reopening forever (#879).
  • [Media Blocks SDK .Net] Fixed: the raw MPEGTSSinkBlockSRTSinkBlock path published streams that carried bytes but no playable video. The muxer emitted one buffer per 188-byte TS packet and the SRT sink sent each as its own SRT message - seven times the message rate for the same payload, which starved video on the transport. The muxer output is now aligned to 7 TS packets (1316 bytes) per buffer, matching what the combined SRT MPEG-TS sink has always done. The alignment applies to every raw MPEGTSSinkBlock output, including default .ts file recordings; the multiplexed stream itself is unchanged and stays spec-legal (#879).
  • [Media Blocks SDK .Net] Fixed: MPEG-1 video produced no video output through UniversalDemuxDecoderBlock (and could not decode through UniversalSourceBlockV2 in the rare no-parser path). The by-name decoder selectors asked for an element gst-libav never registers - it builds decoder names at runtime and explicitly skips mpeg1video, so avdec_mpeg1video does not exist and element creation failed silently, dropping the video stream. MPEG-1 is now handed to avdec_mpeg2video, which decodes both generations. MPEG audio Layer 1 and Layer 2 hit the same defect family: UniversalSourceBlockV2 routed them to avdec_mp2 and UniversalDecoderBlock's Layer 1/2 ladders listed only names gst-libav does not register (mp1/mp2 are in its audio skip list), so that audio silently got no decoder; both now decode through avdec_mp3, which handles every MPEG audio layer (#1132).
  • [Media Blocks SDK .Net] Fixed: a live element could be stopped while a buffer was still passing through it, which could freeze the pipeline. Updating GLShaderBlock settings on a running pipeline, and removing an AudioMixerBlock input from one, both blocked the surrounding pads and then took the element to the NULL state - but installing a pad block does not wait for a streaming thread already inside it to leave, and stopping an element under that thread deadlocks against it. Both paths now wait for the element to be out of the data flow first, and report a failure instead of stopping it if that wait does not complete (#1143). Breaking: GLShaderBlock.Update() returns bool instead of void, so a caller can see when the new shader did not go live - which is what a paused pipeline gives back, since a sink holding a buffer in preroll keeps a streaming thread inside the chain. Push the settings again after resuming.
  • [Core] macOS: audio capture/render devices are selected by their stable CoreAudio unique ID, not by the numeric device ID. The numeric AudioDeviceID CoreAudio assigns is reassigned on replug, on other devices being added, and across reboots, so a saved configuration could silently open a different device. AudioCaptureDeviceInfo and AudioOutputDeviceInfo now publish the provider's stable UniqueID (plus IsDefault), and OSXAudioSourceSettings / OSXAudioSinkSettings accept it; the pipeline prefers the unique ID and falls back to the recorded numeric ID for configurations saved before this change. A saved unique ID that no longer exists now fails the pipeline start with a diagnostic instead of opening whatever sits at the old numeric ID (#1106).
  • [Core] Fixed: selecting a specific macOS audio input device through DeviceEnumerator never worked - the enumerated AudioCaptureDeviceInfo.DeviceID was never populated and stayed 0, so every capture built from a picked device opened the default input instead (#1106).

  • [Media Blocks SDK .Net] New: a public block catalog. MediaBlockCatalog enumerates every built-in Media Block the loaded SDK assemblies carry - over 400 blocks across VisioForge.Core and the AI/OpenGL satellites - with one descriptor per block: stable type, concrete and settings CLR types, human-readable name, visual category, keywords for search, an availability probe (wired to each block's own IsAvailable()), factory support, and property metadata generated from the settings type (display name, default value, editor kind, enum values). Blocks whose settings are built by factories rather than edited as POCOs - device sources, demuxers created through async Create methods - are classified as runtime-configured instead of pretending to have an editable surface. New types: MediaBlockCatalog, MediaBlockDescriptor, MediaBlockPropertyDescriptor, MediaBlockAvailabilityResult, IMediaBlockResourceResolver.

  • [Media Blocks SDK .Net] Settings JSON now survives round trips for media value objects. VideoFrameRate is persisted as its num/den pair, Size as width/height, and colors (SKColor) as RGBA bytes; previously these either could not be deserialized at all or came back zeroed. Read-only computed members of settings objects no longer enter the payload at all - they cannot be read back and silently corrupted document round trips. The DVB source's native tuning handle is excluded from serialization like every other native pointer.
  • [Media Blocks SDK .Net] MAUI: VideoViewX gains SetIPhotography and SetCamera2Controls on Android, matching the Uno and Avalonia video views. They forward to the native view, so camera photography controls can be configured on the MAUI control itself; outside Android the methods do not exist (#311).
  • [Media Blocks SDK .Net] Fixed: the built-in RTSP server could fail to start with a Media Foundation H264 or HEVC encoder selected. The pipeline string for the RTSP media factory carried every MF encoder property unconditionally, but GStreamer installs those properties only when the Media Foundation transform advertises them - on a host where the MFT exposes less, gst_parse_launch rejected the whole string (no property "qp" in element "mfh264enc") and the server never came up. The launch string now carries the element name and bitrate only, and the remaining settings are applied to the real element after the factory builds the pipeline, skipping any property the MFT does not advertise (#858).
  • [Media Blocks SDK .Net] Breaking: the unused MPEG2VideoEncoderSettings.Profile property and the MPEG2VideoEncoderProfile enum have been removed. The FFmpeg MPEG-2 encoder these settings drive (avenc_mpeg2video) cannot apply an MPEG-2 profile or level at all - gst-libav deliberately skips the codec's profile/level options when exposing element properties and never maps them from caps either - so the property silently did nothing and every stream was written with the libav defaults (Main profile). Verified against GStreamer 1.28.2; a regression test now pins the stream profile the encoder actually produces (#259).
  • [Media Blocks SDK .Net] Breaking: four more dead MPEG2VideoEncoderSettings properties removed - ForceDuplicatedMatrix, IntraQuantBias, InterQuantBias and MPEGQuant. None of them exists as a property on avenc_mpeg2video, so every pipeline logged a GLib critical per property and silently ignored the value; no caller could have observed any effect. Also fixed FrameSkipCompare being rejected at runtime with a type-mismatch critical - the value is boxed as an integer now, like every other enum setting on this encoder.

  • [Core] Mac Catalyst builds no longer silently lose macOS behaviour behind #if !__IOS__ guards. The __IOS__ define is set for net10.0-maccatalyst too, so code guarded only against iOS was compiled out of every Catalyst build with no warning: the video overlay sink never had force-aspect-ratio set, opening or playing media could switch audio off while additional audio streams or audio processing blocks were queued, a file:// URI passed to Audio_AdditionalStreams_AddAsync failed where a plain path worked, and the Video FingerPrinting log context stayed unwired so its diagnostics fell back to raw trace output instead of the SDK logger. All twenty-two affected sites now use the guard shape the rest of the SDK already used, which lets Mac Catalyst through wherever macOS is let through (#1141).

  • [Core] Blu-ray and DVB source types are declared on Mac Catalyst, matching the macOS API surface. Blu-ray playback needs only playbin, tsdemux and h264parse, all of which ship in the macCatalyst GStreamer runtime, so BluRaySourceSettings and BluRaySourceBlock work there exactly as they do on macOS. dvbsrc ships in neither Apple desktop runtime, so the DVB types now exist for API parity alone and their availability check reports false at runtime - the same answer macOS gives (#1141).
  • [Core] Pango.CoreTextFont is now declared on Mac Catalyst, matching the macOS API surface. The file was hidden behind a bare #if !__IOS__, which compiles out of Catalyst as well because __IOS__ is defined for it too (#1142); its DllImport now names the library that actually exports the symbol on the Apple builds (libpangocairo, not libpango).
  • [Media Blocks SDK .Net] The unused public type RemoveSilenceSettings has been removed. No API in the SDK ever accepted it, so code holding an instance could not pass it anywhere; silence removal is configured through RemoveSilenceAudioEffect (for AudioEffectsBlock / MediaPlayerCoreX) or directly on RemoveSilenceBlock, which expose the same Threshold and Squash properties (#1117).
  • [Media Blocks SDK .Net] New: versioned JSON persistence for pipelines and blocks. A pipeline can now be saved to and restored from a human-readable .json document that carries the pipeline settings, every block with its settings, the connections between blocks, and an optional opaque editor section. The integer MediaBlockType value is the authoritative discriminator, so a document restores to exactly the blocks it was written with; unknown properties, unknown sections and blocks this SDK does not know about are preserved without loss, so newer files still load on older SDKs. New public API: MediaBlocksPipelineDocument, MediaBlockDocument, MediaBlocksPipelineJsonSerializer, MediaBlockJsonSerializer, MediaBlocksDiagnostic, and a schema-migration registry (IMediaBlocksPipelineDocumentMigration) for future format versions. Materializing a document into a live pipeline arrives in the next stage.
  • [Media Blocks SDK .Net] Every MediaBlockType member now carries an explicit integer value, identical on every platform and build flavor. The values were previously implicit except for a few anchors, which made them differ between Windows and non-Windows builds around the platform-gated members - any integer-serialized block type crossing a flavor boundary was ambiguous. The numbering follows the existing Windows order, so existing explicit pins (251, 277, 400+) are unchanged. Two members that silently carried duplicate numbers move to fresh unique ones: UDPRAWMPEGTSSource from 400 (collided with ONNXInference) to 443, and WebView2Source from 401 on Windows (collided with YOLOObjectDetector) to 444 - the old numbers were ambiguous by construction, so no working code can have relied on them.
  • [Media Blocks SDK .Net] Blocks that shared a MediaBlockType value now have their own: UniversalAutoDemux, UniversalSourceMini, FallbackSwitchSource, ImageOverlayCairo, FrameDoubler, CustomColorspaceX, SqueezebackBlockV2, PreEventSeparateOutput, TextOverlaySource, ImageVideoSourceCairo, UniversalTransform, UniversalDecoder, UniversalDemuxDecoder, AppBridgeAudioSink/Source/VideoSink/VideoSource, StreamSourceWithDecoder and LiveSourceSwitchDynamic (424-442). The primary class of each pair keeps the historical value; the variants listed here are new members appended at the end, so nothing is renumbered. Affected classes: UniversalAutoDemuxerBlock, UniversalSourceBlockMini, FallbackSwitchSourceBlock, ImageOverlayCairoBlock, FrameDoublerBlock, CustomColorspaceXBlock, SqueezebackBlockV2, PreEventSeparateOutputBlock, TextOverlaySourceBlock, ImageVideoSourceCairoBlock, the AppBridge*Block quartet, StreamSourceBlockWithDecoder, LiveSourceSwitchBlockDynamic, and IOSVideoSourceBlock, which now correctly reports the existing IOSVideoSource instead of SystemVideoSource. Code that switched on these types may need the new members added to its cases.
  • [Media Blocks SDK .Net] Breaking: the unfinished YAML persistence API is removed. YAMLBlock, the commented-out YAMLConfig, IMediaBlock.ToYAMLBlock() and MediaBlock.ToYAMLBlock() are gone; none of them ever produced output (ToYAMLBlock threw NotImplementedException). JSON is the only supported Media Blocks persistence format.
  • [Media Blocks SDK .Net] macOS and Mac Catalyst: the Metal video renderer no longer hangs a process that has no window, and the Metal elements are no longer picked automatically. Two defects in the bundled vfmetal plugin, both of which a customer could reach without ever naming a Metal element. vfmetalvideosink created its own window through a blocking call onto the main thread; in a process whose main thread is not running a Cocoa event loop - a console tool, a service, a test host - that call never returned and the pipeline sat in preroll forever, with nothing on the bus to say why. Worse, the same call could deadlock an ordinary windowed application: an app that starts a pipeline and then waits for it on its UI thread was blocking the very thread the sink needed. The sink no longer waits at all - it asks for the window and drops frames until it appears, which lets the pipeline preroll and frees the UI thread to create it. The first frame is kept rather than discarded, so a pipeline that is only paused - a preview, a scrub, a thumbnail - still shows its picture the moment the window appears. If fifteen seconds pass with no window the pipeline reports an error saying whether a window handle was missing or simply never acted on, and a pipeline that finishes without ever displaying anything says so on the bus when it stops. vfmetalcompositor and vfmetalvideosink also registered at ranks high enough to be auto-selected, so the Metal compositor silently became the mixer inside every VideoEditCoreX timeline and the Metal sink was what autovideosink chose; both now register at rank none, like the other five Metal elements, and are used only when you ask for them by name. Separately, MetalVideoCompositorBlock failed negotiation whenever anything downstream asked for an output size other than the size of its inputs; it now accepts the requested size and composes onto a canvas of that size, as the software compositor does - each input still sits where its pad properties put it rather than being stretched to fill. The plugin is also rebuilt against the 1.28.6 runtime the rest of the package ships (#878).
  • [Media Blocks SDK .Net] macOS: three further fixes in the Metal video renderer, found while fixing the above. Resizing the video window could briefly show the picture offset or stretched: the frame's position was computed against the new window size while the picture itself was still being drawn at the old one. A second defect could crash the process during teardown - the thread delivering frames read the render view at the moment the window was being closed, and could be left holding memory that had just been released. And IVideoView-style re-parenting now works: handing the renderer a second, different window used to be ignored silently, so it kept drawing into the first one; it now detaches and attaches to the new one (#878).
  • [Media Blocks SDK .Net] GStreamer pipelines and reported codecs are built identically on every system locale. Six places wrote or compared locale-sensitive text where GStreamer only ever accepts invariant text. The Apple H.264 encoder writes its quality parameter into the pipeline string - fractional 0.5 by default, so with no property ever set - and on every comma-decimal locale (German, Russian, French and most of continental Europe) it produced quality=0,5, which the parser rejects: an RTSP server built on those settings handed every connecting client an error instead of a stream. The MP3 encoder had the same defect in its VBR quality parameter, reachable by selecting the Quality rate control with a fractional quality such as 2.5; the NVIDIA H.264 and HEVC encoders in their const-quality parameter, reachable with any fractional quality value; and the VP8/VP9 encoders in their three buffer-size parameters - the element takes whole milliseconds there, so on those locales the comma form broke every duration, and a sub-millisecond duration is now truncated to the whole millisecond instead of being written as an unparsable fraction. And under the Turkish and Azerbaijani casing rules a codec name reported by stream discovery came back as VİDEO/H264 instead of H264 - silently, with no error anywhere. gst-launch strings and codec identifiers are invariant by construction and are now written as such, on every platform (#1133).
  • [Media Blocks SDK .Net] macOS and Mac Catalyst: a new AAC encoder, AppleAACEncoderSettings, backed by the AudioToolbox encoder built into the operating system. It is the same encoder the rest of macOS produces AAC with, it handles up to 8 channels where the existing AAC backends stop at six, and it offers four rate control modes including true VBR - set RateControl to Variable and drive the rate with VBRQuality instead of Bitrate, which the two variable modes ignore. It appears in every output's GetAudioEncoders() list as "Apple AAC". It is not the default, and that was a measurement rather than a preference: against a lossless source on Apple Silicon the two encoders trade places with the bitrate - behind avenc_aac at 96 kbps, level at 128 kbps, ahead at 192 kbps - while their CPU cost is indistinguishable, since AAC encoding runs well over a hundred times faster than realtime either way. AVENCAACEncoderSettings therefore stays the default and nothing changes unless you select the new one. Not available on iOS: the GStreamer runtime shipped for iOS does not carry the element yet, so check AppleAACEncoderSettings.IsAvailable() rather than the platform (#1110).
  • [Media Blocks SDK .Net] DV and DVCPRO files no longer fail to open at random with "Cannot access memory for read and write operation". Roughly one attempt in twenty - measured 1 in 30 on macOS - the file never reached PLAYING and the pipeline reported that error from avdec_dvvideo. The libav decoder in GStreamer 1.28 can decode straight into the video renderer's own buffer pool, but it describes the frame with its own, more strongly aligned layout - for 720x480 DV that puts the second colour plane 768 bytes past what the renderer allocated - and reading the frame back then fails. This is not macOS-specific and the change is not platform-gated: the defect is in the runtime both platforms now ship (1.28.6 on macOS, 1.28.2 on Windows); macOS is simply where it was measured. The libav video decoders that take that path now decode into their own memory and copy the finished frame out. That is every libav decoder except H.264, H.265 and H.266, so expect one extra frame copy per frame wherever an avdec_ decoder handles DV, DVCPRO, MPEG-1/2, MPEG-4, DivX/Xvid, WMV, MS-MPEG4 or ProRes - formats that are software-decoded anyway. Hardware decoders and every non-libav element are unchanged. The fix reaches both the blocks that pick a decoder by name - UniversalSourceBlockV2, UniversalDecoderBlock, UniversalDemuxDecoderBlock - and the decoders decodebin, uridecodebin, playbin and GES build for themselves inside MediaBlocksPipeline, VideoEditCoreX and SimplePlayerCoreX. A pipeline you assemble yourself out of raw GStreamer elements is not covered, and neither is the internal media-info discovery graph, which cannot hit this (#1121).
  • [Media Blocks SDK .Net] New: AppleMediaHEVCEncoderSettings - HEVC encoding through Apple VideoToolbox, including 10-bit and an alpha channel. There was no VideoToolbox HEVC encoder in the SDK at all, so on a Mac HEVCEncoderBlock.GetDefaultSettings() found no hardware encoder and HEVC output was unavailable. It now returns this one. Profile selects Main or Main 10 (10-bit), and PreserveAlpha switches to the alpha-capable encoder; both need the GStreamer 1.28.6 runtime, which ships in the macOS and Mac Catalyst packages - the iOS package still bundles 1.24.9, where neither is available.
  • [Media Blocks SDK .Net] New: constant-bitrate rate control on the VideoToolbox encoders. AppleMediaH264EncoderSettings and AppleMediaHEVCEncoderSettings gain RateControl (ABR, the default, or CBR) plus DataRateLimitBitrate / DataRateLimitDuration, a bitrate ceiling averaged over a sliding window - what a fixed-bandwidth endpoint needs on top of a target bitrate. The two are alternatives, not complements: with CBR selected VideoToolbox ignores the data rate limits outright, because constant bitrate is already a ceiling; the limits apply in ABR mode. Two caveats worth planning around: truly constant bitrate requires macOS 13+ or iOS 16+ on Apple Silicon - elsewhere VideoToolbox emulates it through limits of its own and says so in its log, and the output is near-constant rather than constant; and on iOS the properties do not exist in the bundled runtime at all, so the setting is discarded with a warning (#1109).
  • [Media Blocks SDK .Net] macOS and Mac Catalyst: the bundled GStreamer runtime moves from 1.24.12 to 1.28.6, and the audio output no longer hangs on shutdown. Stopping a pipeline whose audio went to the system output could wedge the process: pausing tore the CoreAudio render callback down from inside the audio device's own IO thread, and that inverted two locks against each other. Measured on this machine before the upgrade, one run in five of the audio processing suite hung and had to be killed after 15 minutes; after it, none. Three things come with the new runtime that are worth knowing about. VideoToolbox gains hardware decoding of VP9 and AV1 and 10-bit HEVC encoding, and the H.264/HEVC encoders gain real rate control (constant-bitrate, and a hard data-rate cap) - availability depends on the Mac, so ask the SDK rather than assuming. Vulkan-based elements work on Apple Silicon for the first time: the library we shipped was built for Intel only, so on an M-series Mac none of them loaded at all. And the iSAC speech codec is gone - GStreamer dropped it upstream, and there is no replacement in the runtime; pipelines that asked for it by name will report a missing element. Everything else the SDK creates was checked element by element against the old runtime and is unchanged. Delete bin and obj once after taking this update. Several bundled libraries change file name in this release - OpenSSL, libsoup and the FFmpeg libraries all move to a new major version - and an incremental rebuild leaves the previous ones in the output directory beside the new ones.
  • [Media Blocks SDK .Net] [Video Edit SDK .Net] DV output now pins the video format to PAL SD (720x576, 25 fps) instead of failing negotiation on any non-SD source. The DV encoding profile carried no restriction caps, so the encoder was handed the source's native resolution and framerate and negotiation failed. Note that DV encoding is currently blocked by an upstream gst-libav defect (#1126); this fix makes the profile correct for when it is unblocked.
  • [Media Blocks SDK .Net] macOS and Mac Catalyst: the bundled CoreAudio plugin carries one fix on top of upstream 1.28.6. Stopping a CoreAudio device holds a lock that the device's own audio callback needs, and the thread doing the stopping sits inside CoreAudio holding it for milliseconds - measured on an Apple Silicon Mac at a median of 1.6 ms and as long as 240 ms. Upstream removed that inversion where the device is started and never where it is stopped. In practice 1.28.6 is very hard to hang this way, because the callback now stands down before it touches that lock whenever the pipeline is paused first - which every shutdown does; the case it leaves open is an audio capture source renegotiating its format, which stops the device with no pause in front of it. The bundled libgstosxaudio.dylib is therefore built from upstream 1.28.6 sources with the stop side removed too. Everything else in the runtime is unchanged upstream bytes.
  • [Media Blocks SDK .Net] macOS and Mac Catalyst: barcode detection through BarcodeDetectorBlock (the GStreamer zbar element) no longer crashes the whole process on the first frame. The bundled libzbar was built by a compiler that exploits undefined behaviour in zbar's backward image scan: the scan's row-step arithmetic wraps to an invalid pointer value, and the compiled code materializes that wrapped pointer literally instead of decrementing the pointer, so scanning any image wider than two pixels dereferences address 0xffffffffffffffff and dies with SIGSEGV - deterministically, in every host process, on both Apple Silicon and Intel. The two instructions are corrected in place; QR detection verified working after the fix (#1168).
  • [Media Blocks SDK .Net] A branch of a running pipeline could stop delivering data for good after a dynamic add or remove. Blocking a pad that was already blocked installed a second block the SDK had no handle on - it remembered only the first - so unblocking the pad left the second one in place for the life of the process, and the branch went silent or froze with nothing in the log. Reachable wherever two block scopes could overlap on one pad: the live audio and video mixers, LiveVideoCompositorV2, and element removal or replacement in a running pipeline. The same bookkeeping was a shared static table with no locking, and it never released the pads of removed inputs - one pad object pinned in memory per removed mixer or compositor input, permanently. It is gone: each block now carries its own handle. MediaBlockPad.BlockPadLive() changes with it in two visible ways: blocking an already-blocked pad is now a no-op that reports success rather than a second block nobody can lift, and a block that could not be installed reports false instead of reporting success (#1115).
  • [Media Blocks SDK .Net] Updating an OpenGL shader's settings on a running pipeline no longer leaves the block half-connected. GLShaderBlock.Update() swaps the glshader element for a freshly configured one, and the block kept holding the pads of the element that was removed - every later connection, pad block or end-of-stream notification through that block then went to an element nothing feeds. The block now re-reads both pads after the swap. The element replacement underneath it was also reporting success over a pipeline it had cut in half: a replacement element that has only one of the two pads the position needs threw or silently linked against nothing, and a link the SDK could not make was logged and then reported as a completed replacement. Both are refused now, with the old element left running (#1136).
  • [Core] Media analysis no longer fails on a rotated video when the system locale writes its negative sign with a non-ASCII character. ffprobe reports a portrait phone recording as rotate=-90, and the rotation was read through the machine's current locale. On the 57 cultures whose negative sign is not a plain hyphen - every Arabic locale, which prefixes it with U+061C, and the Persian ones, which use U+200E U+2212 - that parse threw and the file could not be analysed at all. ffprobe output is invariant by construction and is now parsed as such, along with the container bitrate and every duration (#1104).
  • [Core] ONVIF: authenticated requests carry a valid timestamp on any system locale. The Created value of the WS-Security UsernameToken was rendered through the machine's calendar, so a Thai machine sent the year 2569, a Persian one 1405 and a Saudi one 1447 and the camera rejected the request. In the legacy ONVIF client the same string is also what the password digest is computed over, so both were wrong. xs:duration values had the matching defect in both directions: written with a comma on any comma-decimal locale, and read back either failing outright (Russian, French) or silently taken as five seconds instead of half a second (German) (#1104).
  • [Core] ONVIF: a device's log timestamps are read in the right era. The log reader picked out date fields using the machine's locale, so under the Umm al-Qura calendar (ar-SA) a plain ISO timestamp was not recognised at all, and under the Persian and Thai Buddhist calendars it was read into the wrong era - 2026-05-12 became 2647 or 1483. The invariant form is now tried first, with the machine's locale kept only as a fallback for a device that formats its log the same way (#1104).

2026.8.24

  • [Core] macOS: enumerating video sources no longer logs a warning for capture devices that are not AVFoundation cameras. VideoCaptureDeviceInfo read the AVFoundation-only device-index property from every device it was given, and any other device class - a Decklink card, an ATEM surfaced through the Decklink provider - has no such property, so building its entry failed part-way and logged a warning. The property is now read only for AVFoundation devices (#1091).
  • [Core] Breaking: Gst.Rtsp.RTSPConnection.Receive, ReceiveUsec, ConnectWithResponse and ConnectWithResponseUsec take their message by ref, and now actually hand it back. All four marshalled the message into a temporary block, let GStreamer write the parsed message into that block, and then threw the block away - so every successful receive returned Ok with the caller's message unchanged - a fresh one still RTSPMsgType.Invalid, carrying no headers and no body, and everything C had allocated into it leaked. Worse on the failure path: GStreamer releases the message's contents before returning an error, so the caller was left holding freed pointers and a later Unset() released them a second time. The message is read back on every path now, so a read that reached the socket and then failed leaves it empty rather than dangling. A call rejected by GStreamer's own argument checks - a closed connection, which answers Einval - still returns the message untouched and owned by the caller (#1096).
  • [Media Blocks SDK .Net] Stopping or disposing a pipeline no longer waits without a time limit for it to reach the NULL state. A pipeline that reported the change as asynchronous and then never completed it left StopAsync() and Dispose() blocked for good. The wait is bounded now, matching the rest of the stop path: it logs a warning and the teardown carries on (#849).
  • [Media Blocks SDK .Net] AudioMixerBlock.CreateNewInputLive() returns null when the input could not be added, instead of a pad that was never wired to anything. Check the result before linking: the previous pad produced a GLib critical out of gst_pad_link and a link result that looked like an ordinary refusal.
  • [Media Blocks SDK .Net] RemoveSilenceBlock and the RemoveSilence audio effect now actually remove silence. The underlying element's remove property defaults to off and was never set, so the filter detected silence and then passed every buffer through unchanged - the block was a no-op whatever it was configured with. It is enabled now. Check your Threshold before upgrading: it is a linear amplitude, and the documentation used to have its direction backwards - it claimed 1.0 meant "no silence detection", where 1.0 is in fact full scale and classifies every sample as silence. That was harmless while nothing was ever dropped; now a threshold near 1.0 removes the whole stream. Two defaults move with it, both onto the element's own: Threshold from 0.05 (-26 dB, which would have cut ordinary quiet speech) to 0.001 (-60 dB), and Squash from true to false. Neither default breaks existing code - nothing was ever dropped, so neither had any effect to change; they are what the block does now that it works. One thing does: Threshold is validated against its documented 0.0-1.0 range now, the way the compressor's already was, so a value outside it throws ArgumentOutOfRangeException where it used to be accepted and ignored. With the block actually removing audio, an out-of-range threshold empties the track instead. Squash = true pulls every buffer after a removed passage back by its duration, so the audio track ends up shorter than the video of the same recording - set it yourself when you want the gapless, shortened output and nothing has to stay in sync with it. The Squash documentation was describing the missing remove property rather than what Squash does: silence is always dropped, and Squash decides whether the surviving buffers are pulled back to close the gap or keep their original timestamps (the default).
  • [Media Blocks SDK .Net] RemoveSilenceBlock.Threshold and RemoveSilenceAudioEffect.Threshold now reach the silence detector. The linear value was passed straight to an element property that is measured in decibels, and the conversion GLib applied silently turned the default 0.05 into 0 dB - full scale, where practically every sample counts as silence. The linear value is converted properly now; the public API is unchanged.
  • [Core] Gst.Sdp.SDPMessage's property setters now actually set what they say. All seven wrote directly into the native struct at a computed field offset instead of calling GStreamer's own setter. For Version, SessionName, Information and Uri that stored a fresh copy over the old string without releasing it, leaking on every assignment. For Origin, Connection and Key it was worse: those fields are C structs embedded by value - GstSDPOrigin is six strings in a row - and the setter wrote a pointer to a temporary block into the first eight bytes of one, so msg.Origin = o; corrupted the username field, left the other five untouched, and leaked the block, while msg.Connection = c; never wrote Ttl or AddrNumber at all. All seven now go through gst_sdp_message_set_*, which replaces every field properly (#1086).
  • [Core] Breaking: several Gst.Sdp members change shape, and the GStreamer binding's Free(), Unset() and Clear() methods no longer corrupt the heap. SDPMedia.Media/Proto/Information/Key and SDPTime.Start/Stop become read-only properties; SDPMessage.AddMedia, InsertTime and ReplaceTime take their value by ref because C moves it into the message and the caller must not release it again; and the setters on SDPMedia.Fmts/Connections/Bandwidths/Attributes and SDPTime.Repeat are removed - they stored a plain pointer array in a field C keeps a GArray* in, so any call to one guaranteed a crash on the next release (use AddFormat, AddConnection, AddBandwidth, AddAttribute and SDPTime.Set). Those methods marshalled a copy of the value into a temporary native block and released that, which went wrong three ways at once: the marshaller allocates every string field with CoTaskMemAlloc and C frees it with g_free, the block itself was allocated with AllocHGlobal and freed with g_free, and the wrapper then freed the same pointer a second time - so Gst.Rtsp.RTSPTransport.Free(), Gst.Rtsp.RTSPRange.Free(), Gst.Rtsp.Global.RtspRangeFree(), Gst.Sdp.SDPMedia.Free()/Uninit() and the Gst.Sdp.SDPAttribute/SDPBandwidth/SDPConnection/SDPTime/SDPZone Clear() methods aborted the process instead of releasing anything. Values whose fields the binding copies - RTSPTransport, RTSPTimeRange, SDPAttribute, SDPBandwidth, SDPConnection, SDPZone - own no native memory at all, their factory already released it, so releasing one now clears the value and makes no native call. SDPMedia and SDPTime are the exceptions: they wrap live native memory, so their string fields become raw pointers behind read-only properties (SDPMedia.Media/Proto/Information/Key, SDPTime.Start/Stop), which is what makes SetMedia, SetProto, SetInformation, SetKey, SDPTime.Set, Uninit(), Free() and SDPTime.Clear() work; write through those methods rather than the properties, and only on a value you own - on one borrowed from SDPMessage.GetMedia the setter frees a string the message still points at. One thing to know about that: those properties now read native memory on every access, so a value obtained from SDPMessage.GetMedia/GetTime must not be read after the message is disposed - copy what you need out while it is alive. Equals and GetHashCode on those two structs consequently compare by pointer rather than by string content, the way they already did for the array fields - two medias with the same text are no longer equal, and a value's hash changes after a SetMedia. And the release methods on those two now really do release: call Free()/Uninit()/Clear() only on a value you created (New, Init, Copy, SetMediaFromCaps, SDPTime.Set), never on one borrowed from SDPMessage.GetMedia/GetTime - that one is a window onto memory the message owns, and releasing it leaves the message dangling until its own teardown trips over it. A borrowed value is also only valid until the message is next modified: RemoveMedia, ReplaceTime and their siblings release the element they drop, so read what you need out of a GetMedia/GetTime result before changing the message, not after. The same allocator mismatch is gone from the Insert/Replace overloads that take an SDPAttribute, SDPBandwidth, SDPConnection or SDPZone: C copies the struct into the message or media by shallow memcpy and frees its strings with g_free, and the binding was handing it CLR-allocated ones - no signature changed, the strings are now GLib-allocated at the boundary. SDPMessage.AddMedia takes ref because C moves the media into the message and empties the source. The matching leaks are gone with them: Gst.Rtsp.Global.RtspMessageNew/NewData/NewRequest/NewResponse leaked an 88-byte message plus its header array on every call, and SDPMedia.New/Init/Copy/SetMediaFromCaps leaked a media plus four arrays, because the only documented release path was one of the broken methods (#1086).
  • [Core] Breaking: Gst.Sdp.SDPMedia.Fmts, Connections, Bandwidths, Attributes and Gst.Sdp.SDPTime.Repeat return typed arrays and finally read what they describe. All five threw ArgumentException on any value that held something: they walked their field as a NULL-terminated array of pointers, and the helper doing the walking called Marshal.PtrToStructure in a form that refuses a value type - which is the only reason it did not hang instead, because its loop compared the walking address against zero while incrementing that same address and so had no exit at all. In C these fields are GArray *, not pointer arrays, so repairing the walk would still have taken the array's length field for an element pointer. Fmts and Repeat are string[] now, Connections is SDPConnection[], Bandwidths is SDPBandwidth[] and Attributes is SDPAttribute[], read through GStreamer's own indexed accessors - all but Repeat, for which C exports none, so that one reads the array directly; they were IntPtr[]. Reading one on an empty or already-released value returns an empty array rather than crashing. Unlike Media, Proto, Information, Key, Start and Stop, which read native memory on every access, the values these five hand back are copies taken at read time and stay valid after the media or time is released (#1087).
  • [Media Blocks SDK .Net] One stalled pipeline no longer freezes bus message delivery for every other pipeline in the process. Latency recalculation ran directly on the GLib main loop, which is shared process-wide and dispatches one source at a time. A pipeline whose latency query could not complete - a stalled mixer, a wedged source - therefore held that loop and stopped the EOS, error and state-change messages of all other pipelines, including the ones their StopAsync/Dispose were waiting on, so unrelated pipelines appeared to hang (#1065). The recalculation now runs off the bus loop, with bursts of latency notifications coalesced so a graph is never recalculated twice at once.
  • [Core] Breaking: Gst.Object.Replace and Gst.Rtsp.Global.RtspAuthCredentialsFree change signature, and the GStreamer binding's T ** out-parameters now return real data instead of uninitialised heap. Eighteen P/Invoke declarations passed a C out-parameter by value, so native wrote its eight-byte pointer into the front of a caller-allocated struct-sized block and everything past that was read back as garbage - Gst.Rtsp.RTSPUrl.Parse returned a url whose host, path and credentials were undefined, Gst.Rtsp.RTSPRange.Parse returned a range whose unit was a random integer, and the same held for RTSPTransport.New, SDPMedia.New/Copy, the RTSPMessage constructors and RTSPAddressPool.ReserveAddress. Gst.Object.Replace(oldobj, newobj) was worse: it handed native the object pointer where C wants the address of a variable, so every call unreffed the object's class pointer and overwrote it - it becomes Replace(ref Gst.Object oldobj, Gst.Object newobj), and the parameterless overload becomes Replace(ref Gst.Object oldobj). RtspAuthCredentialsFree now takes the credential array pointer (IntPtr) rather than a single RTSPAuthCredential, which native was reading as a pointer and freeing. Two more of the same family are fixed with it: Gst.Sdp.SDPMessage.Init becomes an instance method (msg.Init()) and Gst.Sdp.Global.SdpMessageInit now takes the message, because C's gst_sdp_message_init re-initialises a message you already own - declared as an out-parameter it wrote a whole SDP message through an eight-byte stack slot and aborted the process inside malloc; and WebRTCICE.OnGetLocalCandidates/OnGetRemoteCandidates now return WebRTCICECandidateStats[], since C returns a NULL-terminated array of pointers that was being read as a single struct. Gst.Video.VideoInfo.Init and Gst.Audio.AudioInfo.Init become instance methods for the same reason - C's gst_video_info_init/gst_audio_info_init initialise an info you already own, and as out-parameters they wrote a whole GstVideoInfo over the caller's stack frame and returned null every time; use new VideoInfo() / new AudioInfo() to get one, then Init() to reset it. Gst.Rtsp.Global.RtspTransportInit, RTSPTransport.Init, Gst.Sdp.Global.SdpMediaInit and SDPMedia.Init no longer hand those C functions an uninitialised heap block, which they began by calling g_free on. The Gst.Rtsp.RTSPMessage struct also gains the type_data union it was missing, so its layout matches the native one (#1062).
  • [Core] macOS: video capture no longer opens a different camera than the one selected. The device index passed to avfvideosrc was recorded once at enumeration time, but macOS may reorder cameras between enumeration and pipeline start (USB re-enumeration), so after such a reorder every new capture opened whatever device had taken the selected camera's position - typically failing with "Internal data stream error" or capturing from the wrong webcam. The position is now resolved from AVFoundation's live device list by stable unique ID right before each start; the enumerated index remains as a fallback. If the selected camera is no longer connected, capture now fails with an explicit error instead of silently opening a different camera. VideoCaptureDeviceInfo gains AvfUniqueID on macOS (#843).
  • [Core] iOS: the selected camera is now opened by its AVFoundation unique ID rather than by its localized name. Video capture looked the camera up by display name across every AVFoundation device, microphones included, so a name that was not unique - or that changed with the device language - could open a different camera or none at all. The unique ID recorded at enumeration is now authoritative: a camera that no longer resolves by it fails outright rather than falling back to a name match that could open a different camera. The name search remains only for a settings object built by hand, which carries no unique ID at all. A camera that cannot be found now fails with an error naming both the device and its unique ID (#1089).
  • [Core] Video capture blocks no longer throw NullReferenceException when no camera was found. CreateWithDefaultDeviceAsync() returns a block with no settings when device enumeration comes back empty - camera permission denied, a simulator, a machine with no webcam - and only the Android path checked for it. Every other platform dereferenced the missing settings and threw out of the public Build(); both SystemVideoSourceBlock and IOSVideoSourceBlock now return false and log what is missing. The same applies to settings that exist but name no device, and on iOS to settings with no video format.
  • [Core] SDK log events now carry the exception object, not just its text. Every logging call that takes an exception passed it to Serilog as a message-template value rather than as the exception, and a template with no placeholders discards it - so a sink whose output template renders {Exception} printed nothing there, and exception types and stack traces never reached the log at all. They are attached properly now, across the whole SDK.
  • [Core] KLVDecoder and KLVRemux are now static classes. Both only ever exposed static members, so documented usage (KLVDecoder.DecodeFromFile(...)) is unaffected; code that instantiated them with new will no longer compile.
  • [Core] VideoFrameRate gained the <= and >= operators, completing the comparison set alongside the existing ==, !=, < and >. They use the same 0.0001 tolerance as ==.

2026.8.23

  • [Core] WPF skin controls are now available on every Windows target framework. VisioForge.Core previously compiled the WPF skins (SkinPlaylist, SkinCaptureControls, SkinPlayerControls, …) only for net*-windows10.0 and .NET Framework targets, so projects targeting a plain -windows TFM such as net10.0-windows — including the Skinned Player and Skinned Capture demos under the nano build flavour — failed with "The tag 'SkinPlaylist' does not exist in XML namespace" (#859). Note that SkiaSharp.Views.WPF ships no asset for plain -windows targets, so restore falls back to its .NET Framework asset (NU1701); the controls compile and work.

  • [Media Blocks SDK .Net] Fixed a process crash when a subtitle auto-hide timer fired after the overlay block had been torn down. OverlayManagerBlock.Video_Overlay_Update dereferenced its internal element without a null check on the re-add path, so a late subtitle hide tick raised an unhandled NullReferenceException on a timer thread and aborted the whole process (#823).

  • [Media Blocks SDK .Net] Media Foundation H.264/HEVC encoders no longer log a GLib critical and silently drop the reference-frames setting on every run where it is left at the default. The default of 0 ("encoder default") lies below the encoder element's own property range, which starts at 1; the value is now skipped instead of being written out of range (#857).

2026.8.22

  • [Core] Breaking: new Gst.Buffer(size), new Gst.BufferX(size) and new Gst.BufferList(size) are replaced by Gst.Buffer.NewAllocate(size), Gst.BufferX.NewAllocate(size) and Gst.BufferList.NewSized(size). The size constructor sat one implicit conversion away from the pointer constructor Buffer(IntPtr), and since .NET 7 an int literal converts implicitly to a native integer - so new Gst.Buffer(1024) silently bound to the pointer overload and produced a buffer wrapper over address 1024. Nothing failed at the call site; it crashed later inside GStreamer with no hint of where it came from. The allocating form is now a named factory that cannot be confused with wrapping a pointer, and both old spellings fail to compile with a message naming the replacement. Wrapping an existing native pointer is unchanged.
  • [Core] Long GStreamer sessions no longer grow their native memory footprint on every negotiation, frame push and dropped frame. The managed wrappers for GstCaps, GstBuffer, GstEvent, GstMessage, GstMemory, GstSample, GstQuery and GstTagList never released the native object: Dispose() and using on them did nothing at all, so every capability negotiation, every pad-caps query and every self-allocated buffer that was created and released left its native allocation behind for the life of the process. The effect grew with running time and with the number of pipelines built and torn down; it was largest on paths that touch caps or buffers per frame - pad probes, overlays, VU metering, and the custom mixer's queue-overflow frame drops. Reference counting is restored, so disposing these objects - or letting the garbage collector do it - now actually frees them.
  • [Video Edit SDK .Net] Encoder settings on the render/output path are no longer silently lost on hosts where the encoder element exposes fewer properties. Video Edit renders configured the encoder through the GStreamer encodebin profile, which writes every property with an unchecked g_object_set: a property the concrete element class does not expose - Media Foundation encoder classes are generated per device, so their property set differs from machine to machine - raised a GLib critical and was dropped without any error. The profile now pins only the encoder factory; the settings are applied to the encoder element after encodebin creates it, with each property probed first and a warning logged when one is not available.
  • [Media Blocks SDK .Net] SimpleVideoMarkDetectBlock.VideoMarkDetected now actually fires. The block installed its bus handler with Bus.AddWatch, but a GStreamer bus supports a single watch and the pipeline already owns it, so the install silently failed and watermark detection never reported anything; the handler is now delivered through the pipeline's own bus signal dispatch. Two defects found behind the same dead event are fixed with it: the detection pattern was read from a message field that does not exist (the element posts it as data), and the handler could be handed an already-released message by the pipeline's own bus handler running before it.
  • [Core] Disposing DeviceEnumerator while another thread was starting device monitoring or enumerating NDI/Decklink devices no longer risks disposing the same GStreamer device monitor twice - which surfaced as GLib object-lifetime criticals in the log, or as a device monitor left running after dispose. Monitor teardown now serializes with monitor creation through one lock (so device-monitor work is queued across enumerator instances), and concurrent Dispose() calls are safe. NDI enumeration still never blocks other instances: its potentially slow mDNS discovery runs outside the shared lock on an exclusively claimed monitor.
  • [Core] Disposing any DeviceEnumerator instance no longer breaks NDI device-provider toggling for every other enumerator in the process. Dispose released the shared registry-feature wrapper all instances use to load/unload the NDI provider, so after one enumerator was disposed its siblings passed a dead pointer into the GStreamer registry on every later enumeration (gst_registry_remove_feature: assertion 'GST_IS_PLUGIN_FEATURE' failed in the log). The reference is now dropped instead of disposed.
  • [Core] Dropping an engine object without disposing it no longer risks killing GStreamer for the rest of the process. VideoCaptureCoreX, MediaPlayerCoreX, SimplePlayerCoreX, MediaBlocksPipeline, the Live Video Compositor and its outputs, the overlay managers and several other classes ran their full GStreamer teardown from the garbage collector's finalizer thread when an instance was never disposed - which could take the process-global GStreamer registry with it, so every pipeline created afterwards failed to build with nothing in the log connecting the failure to the object collected minutes earlier. Finalizers now leave the native objects to the binding's deferred release path; Dispose remains the way to stop pipelines deterministically. One trade to know about: a recording whose engine was never disposed ends without a muxer trailer and stays unplayable - dispose explicitly to finalize files.
  • [Core] An undisposed GigE (Aravis) camera now releases its stream and camera handles at collection instead of taking locks, tearing down timers and raising events from the finalizer thread. Stopping acquisition still requires an explicit Disconnect().
  • [Media Player SDK .Net] A faulted dispose of MediaPlayerCoreX no longer leaves the player permanently half-torn-down with no way to finish it. If stopping or closing the pipeline threw during Dispose/DisposeAsync, the player marked itself as disposed while the GStreamer pipeline had never reached NULL and internal resources were never released - and every later dispose call only re-observed the stored failure instead of retrying. A faulted teardown now leaves the player usable, flushes and re-arms the debug log for the next attempt, and a subsequent Dispose() or DisposeAsync() completes the teardown.
  • [Video Capture SDK .Net] DirectShow Picture-in-Picture recording no longer fails with "Unable to set PIP layer settings" in Horizontal and Vertical layouts, and PIP_CustomOutputSize_Set now produces output of exactly the requested size. The struct passed by value to the video mixer filter declared its frame-duration field as 32-bit while the native filter reads it as 64-bit, so every output-settings call was rejected and the mixer silently kept its previous canvas: in Horizontal/Vertical layouts the later layer-position calls then failed with an error at start, and with a custom output size smaller than the main video the recording came out at the wrong size. Output size is now applied before layer positions, the main video fills a custom canvas, and a failed PiP configuration call logs the failing parameters with the native result code.

2026.8.21

  • [Demos] The Avalonia demos and the console RTSP servers build again on macOS regardless of which macOS workload patch is installed. They pinned net10.0-macos26.2, a target platform version that only machines whose workload manifests declare 26.2 accept - everywhere else the build failed before compilation with NETSDK1140: 26.2 is not a valid TargetPlatformVersion for macOS. The demos now use net10.0-macos with no version suffix, like the rest of the sample tree, so the platform version follows whatever the machine has installed.
  • [Demos] The remaining Media Blocks console demos and the Blazor RTSP servers build again on Apple-silicon Macs. An unconditional PlatformTarget x64 conflicted with the osx-arm64 runtime identifier inferred for net10.0-macos (NETSDK1032) in VideoResizer, FrameRateAdjuster, RTSPViewCV and both Blazor RTSP servers; the pin is now Windows-only. The ones used as .app bundles on macOS also lacked a bundle identifier and now declare one.
  • [Demos] The Live Subtitles console sample no longer declares a macOS target. Whisper.net requires static whisper.cpp archives on Apple platforms and Whisper.net.Runtime ships none for macOS, so the sample's speech-to-text pipeline could not link there; it stays available on Windows and Linux.
  • [Media Blocks SDK .Net] Stopping a pipeline with ObjectAnalyticsBlock no longer logs analytics or overlay errors and no longer loses the frame that was in flight. Teardown freed the block's renderer, tracker, zones and lines while the streaming thread could still be using them, so a frame arriving during the stop was dropped with a logged ObjectDisposedException or null-reference message; teardown now waits for the frame in flight before freeing anything.
  • [Media Blocks SDK .Net] FallbackSwitch enabled on source settings passed directly to a source block is no longer silently ignored. RTSPSourceSettings.FallbackSwitch (and the same property on the SRT, NDI, RTMP and HTTP source settings) is applied by VideoCaptureCoreX and by an explicit FallbackSwitchSourceBlock; a bare RTSPSourceBlock, SRTSourceBlock, SRTRAWSourceBlock, NDISourceBlock (or the Windows-only NDISourceXBlock), RTMPSourceBlock or HTTPSourceBlock does not use it, and enabling it there now logs a warning at build time explaining how to get automatic failover instead of proceeding without any message.
  • [Core] MediaInfoReaderX no longer spins up a full-throughput decoder just to read file metadata. The discovery pipeline let GStreamer auto-plug dav1ddec with its defaults - threading and frame delay sized to the CPU core count - so reading the metadata of one 8K AV1 file pre-allocated a reference-frame pool costing ~700 MB of working set on a 14-core machine and growing with every core. Discovery now pins that decoder to low-latency single-thread mode before it starts, bounding the same read by the stream's reference structure instead of the machine's core count (~310 MB for 8K AV1 on any machine).
  • [Core] The built-in HLS/DASH HTTP server on macOS and Linux no longer dies if a player connects while it is starting.
  • [Core] The built-in HLS/DASH HTTP server on macOS and Linux now accepts IPv6 clients, including http://localhost/ when that name resolves to ::1.
  • [Media Blocks SDK .Net] Adding an audio or video effect to a running pipeline no longer leaves it paused. Under concurrent effect changes, the pipeline could still be resuming when the add returned, leaving later effect operations or stopping playback waiting indefinitely.
  • [Media Blocks SDK .Net] A video or audio effect added while the pipeline has just left Playing now reaches the running graph. A pause that landed during the add used to leave a video filter in NULL, and to skip the audio filter until the next build.
  • [Media Blocks SDK .Net] A pipeline that was preloaded and then resumed no longer flickers back to paused, and no longer seeks StartPosition, after playback was already started. Resume (or the next StartAsync) had already published Play, but a late confirmation of the preload's pause could overwrite it and re-seek. MediaPlayerCoreX.State, which reports the pipeline's state, is covered by the same fix.
  • [Media Blocks SDK .Net] A live-added proxy, buffer or subtitle bridge source now brings its whole graph up with the pipeline. Those three sources published no core wrapper, so a live add synced only the one GStreamer element the block exposed and left the rest of the bridge in NULL.
  • [Media Blocks SDK .Net] MediaBlocksPipeline.SyncBlockStateLive no longer throws on a block that was never built, and no longer races the block's own teardown. Calling it out of order - before AddBlockLive built the block, or after it had been cleaned up - raised a NullReferenceException out of the SDK instead of returning false with a logged reason like every other refusal in that method. It also read the block's element and then synchronised it after releasing the lock that guarded it, so a teardown landing in that window left the live add reported as "failed to set block to Playing" with the real reason only in a GStreamer log line. The same "has not been built" refusal now also applies to MediaBlockHelper.SetState and MediaBlockHelper.SendEvent.
  • [Media Blocks SDK .Net] RTSP playback no longer fails with "Failed to link RTSP pad: WasLinked" when the source re-announces a pad. On a reconnect, or when an RTSP server re-announces a stream, UniversalSourceBlockV2 could report a pad it had already linked as a link error and end the session - intermittently, since two of rtspsrc's streaming threads can pass the "is this pad linked" checks together. A duplicate announcement is now recognised from the link result itself - a second attempt reports WasLinked, which is logged at debug level instead of failing the session - and the handler's check-and-link section is serialised.
  • [Core] A handler connected with Connect(...) or with += on a generated GStreamer event no longer keeps that object alive for the life of the process. Every Connect(...) on an element - the mechanism behind source, demuxer and decoder auto-plugging - and every += on a generated event was recorded in a process-wide table that only an explicit unsubscribe ever cleared, and the entry held the element, the handler, and everything the handler had captured. An application that builds and tears down sources or decoders in a loop, a playlist or a transcode over a directory, grew without bound with nothing disposable to blame. A connection is now owned by the object it was made on and is released with it. Two defects of the same family go with it: a handler silently stopped being delivered once its wrapper had been disposed, and the callback's handle was released while an emission could still be inside it - a rare crash on a streaming thread when a recording was stopped on a file split.

2026.8.20

  • [Video Capture SDK .Net] VideoCaptureCoreX.WaitForStartAsync no longer waits forever, and no longer returns before the capture starts. It polled for PLAYING and nothing else, so a source that never gets there - an RTSP or HTTP address that black-holes, a capture device with no signal, a Decklink with no input - parked a thread on a Task that never completed, and an asynchronous failure (which takes the pipeline back to READY without tearing it down) did the same. The wait now ends when the start settles somewhere it will not leave, and has a 30-second deadline; the new WaitForStartAsync(TimeSpan timeout, CancellationToken cancellationToken = default) overload chooses that deadline, cancels the wait, and returns whether PLAYING was actually reached. The documented fire-and-forget pairing _ = StartAsync(); await WaitForStartAsync(); also no longer completes instantly against a capture whose pipeline does not exist yet.
  • [X-engines] A second Start() landing while the first is still building is now rejected instead of building over it. VideoCaptureCoreX.Start() and MediaBlocksPipeline.Start() had the guard only on their async twins, so a concurrent call cleared the first start's state and re-entered the build over the pipeline that call was still assembling. Relatedly, a start that fails now finishes its own rollback before it releases the start, so processing blocks registered by another thread are no longer disposed under it, and a throw out of a restart's teardown no longer leaves the instance permanently unable to start.

  • [Media Blocks SDK .Net] A ChromaKeyBlock added to a running pipeline now brings its whole graph up with the pipeline, not just the compositor. The block builds six elements, and a live add synchronised the state of only one of them, so the other five - the background scaler and capsfilter, the alpha key, and both converters - stayed in whatever state they had been created in. They now live in one bin, which is the one thing the pipeline brings up.

  • [Media Blocks SDK .Net] A start the pipeline refuses is now reported as stopped instead of as playing. When an element refused the transition to playing - a capture device that cannot be opened, a renderer that cannot create its window - Start() returned false but left State reporting Play, and left every element that had already opened a device, handle or socket holding it. The pipeline is now torn down and reports State = Free, so a retry rebuilds it. With PauseOnStop enabled that retry previously returned true without rebuilding anything, on a graph that never started. A start that never started no longer raises OnStop when it is stopped afterwards. MediaPlayerCoreX.State, which reports the pipeline's state, is covered by the same fix, and VideoCaptureCoreX.Start now returns as soon as the pipeline fails instead of going on to start the auto-start outputs against it.
  • [Media Blocks SDK .Net] A preload that fails while prerolling is now reported. StartAsync(onlyPreload: true) and Start(onlyPreload: true) returned true whenever the source failed asynchronously - a camera already in use, an unplayable file, a stream that never connects - and left the pipeline holding whatever its elements had opened, with nothing telling the caller. Only a transition the pipeline refused outright was reported. Both now return false and tear the partial graph down; Pause() on a running pipeline reports the same failure the same way.
  • [Media Blocks SDK .Net] The processing block passed to an LVCVideoInput constructor is now applied. On LiveVideoCompositor V2, the optional processingBlock argument of both LVCVideoInput constructors was stored and never linked into the graph: the input composited unprocessed, with no error and no log line, while the identically shaped argument of LVCVideoAudioInput worked. It is now an alias for LVCVideoInput.ProcessingVideoBlocks, so the block runs between the source and the mixer as the argument always implied. Code that already uses ProcessingVideoBlocks is unaffected.
  • [Media Blocks SDK .Net] The channel parameter of LiveVideoCompositorV2.Video_Effects_* is deprecated. V2 has a single effects block on the composed output, after the mixer, so the index never selected anything - Video_Effects_Clear(channel: 1) cleared the whole composition's effects, where the identically named V1 call validates the index and ignores a channel that does not exist. Every Video_Effects_* method now has a channel-free form; the overloads that take a channel still work, forward to it and warn. To process a single input rather than the composition, add a VideoEffectsBlock to that input's LVCVideoInput.ProcessingVideoBlocks - those blocks run between the source and the mixer, which is where V1's per-channel effects were. V1 is unchanged.
  • [Media Blocks SDK .Net] An effect added to a running pipeline while that pipeline is being stopped is no longer left in the graph unreachable. VideoEffectsBlock.AddOrUpdateAsync and AudioEffectsBlock.AddOrUpdate splice the new effect into the live graph, and that work can take seconds - it runs your OnUpdate handler twice and pauses the pipeline to relink it. A stop that gave up waiting for it went ahead and released the block anyway, and the insertion then carried on and spliced its element in regardless: the block no longer knew about it, so Remove() reported success without removing anything and the next Build() created a second element under the same name, for the rest of the run. Both blocks now stop an insertion the moment a teardown has been through, and leave the element to the pipeline's own disposal - on an ordinary stop that is what releases it. The effect stays registered, so the next build puts it in the graph.
  • [Media Blocks SDK .Net] MediaBlocksPipeline.State now reports Pause as soon as StartAsync(onlyPreload: true) / Start(onlyPreload: true) returns, instead of briefly reporting Free while the pipeline was already preloading. Inside that window a preloaded pipeline looked stopped to every "is anything running?" check: StopAsync and Stop returned without tearing it down and without raising OnStop, Dispose skipped the stop it does first, ClearBlocks disposed the blocks of a live pipeline instead of refusing, a StartPosition set on the preloaded pipeline was dropped instead of seeked, and starting playback right after a preload could be rejected with "Already starting or start in progress". MediaPlayerCoreX.State, which reports the pipeline's state, is covered by the same fix.

2026.8.19

  • [Media Blocks SDK .Net] RTSPSourceSettings.BufferMode and DropOnLatency now reach the RTSP source. Setting them previously had no effect, so jitter-buffer tuning was silently ignored. The default jitter buffer is 500 ms; LowLatencyMode uses 150 ms, or the explicit Latency if you set it to 150 ms or less.
  • [Media Blocks SDK .Net] Changing video mixer settings while the pipeline is being stopped no longer crashes or silently does nothing. SetSettings, Input_Update, Input_Move, StartFadeIn, StartFadeOut, Input_UpdateChromaKeySettings and Input_SetChromaKeyEnabled ran with nothing serialising them against the block's own teardown, so a call that landed during a stop reached GStreamer through an element the teardown had already released - a NullReferenceException, or a change that was accepted and quietly not applied. Building a mixer while it was being stopped had the same problem and could throw out of Build(). Affects VideoMixerBlock, VideoMixerSourceBlock, GLVideoMixerBlock, D3D11VideoCompositorBlock and MetalVideoCompositorBlock. AddInputPadLive on a mixer that is not built now returns null and logs, instead of throwing.
  • [Media Blocks SDK .Net] A video mixer fade or move animation no longer outlives the block that started it. StartFadeIn, StartFadeOut and Input_Move animate on a background thread for the duration requested; stopping or disposing the mixer while one was running left that thread writing to a released element, which took the whole application process down with an unhandled NullReferenceException. Teardown now stops the animations and waits for them first. They also no longer keep the process alive after everything else has finished.
  • [Video Fingerprinting SDK .Net] Disposing a FrameSource while PlayAsync was still starting no longer leaves a playing pipeline behind. The teardown and the start shared no synchronization, so a Dispose() - or a StopAsync() - landing mid-start tore down the session the start was still building, and the start went on to leave a fully wired pipeline that nothing owned: OnVideoFrame kept firing for the rest of the process. Overlapping PlayAsync/StopAsync calls, which a UI can produce with two quick clicks, could also tear the same pipeline down twice. FrameSource now also implements IAsyncDisposable; await frameSource.DisposeAsync() is the deterministic teardown, because a synchronous Dispose() cannot wait for a start already in flight.
  • [Media Blocks SDK .Net] Disposing a pipeline that was only preloaded (StartAsync(onlyPreload: true)) no longer hangs. The teardown skipped the stop for a preloaded pipeline and set its elements to the null state under a live streaming thread, which wedged the disposing thread and the streaming thread against each other indefinitely.
  • [Media Blocks SDK .Net] Disposing a pipeline while it was reporting a state change no longer hangs. The teardown and the pipeline's own message thread could block on each other for good.
  • [Media Blocks SDK .Net] VP8EncoderSettings.GetCaps() now reports video/x-vp8 instead of video/x-vp9.
  • [Media Blocks SDK .Net] An IPv6 URL such as udp://[ff05::1]:5004 now reaches a UDP source, a universal source and an RTSP server without the brackets, so the element binds and joins multicast instead of failing silently. A Windows link-local zone id (%12) is left intact instead of being decoded as a byte.
  • [Media Blocks SDK .Net] LiveSourceSwitchBlock.Switch(i) no longer pairs one source's video with another's audio on a switcher that holds a mix of input types. A video-only input and a video+audio input take their switch pads from two independent counters, so the same index meant a different source in each of the two switches: with a video-only input added first, Switch(1) played the second input's picture with silence, because no input feeds audio pad 1. Switch now resolves the input at the given index and moves each switch to that input's own pad. An input that carries only one of the two streams leaves the other switch where it was, so switching to a video-only input keeps the audio that was playing. New CurrentVideoIndex / CurrentAudioIndex properties report the pads actually selected. Two smaller changes come with it: an index past the last added input is now refused and logged instead of pointing the switch at a reserved pad that carries nothing, and SourceSwitchBlock.Switch returns bool - false when the block is not built yet, the index is out of range, the pad at that index was never obtained, or a concurrent stop tore the element down - where it used to return void. Every one of those is logged; a switch that could not be applied no longer passes silently.
  • [Media Blocks SDK .Net] LiveSourceSwitchBlockDynamic.Switch(slot) no longer silences the audio when the slot holds a video-only input. Nothing feeds that slot's audio pad, so moving the audio switch there played silence; it now stays where it was, matching LiveSourceSwitchBlock.Switch. An empty slot is not that case - switching to a slot with no input in it still takes the audio with it, rather than leaving the previous source's sound playing under a black picture; one limit is structural, in that a switcher whose MaxAudioInputsCount is smaller than its MaxVideoInputsCount has no audio pad above the audio limit for the audio to move to. A slot index past the last slot is now refused and logged; on a switcher whose audio switch has more pads than its video one it used to move the audio switch while the video switch declined, so the sound went silent under a picture that kept running. Its CurrentVideoIndex / CurrentAudioIndex also start at -1 instead of 0 - they used to report slot 0 before any switch had been applied, which was not true, and they now record only a switch the block actually applied. Code that reads either property before the first switch and indexes its own array with the result has to handle -1.
  • [Media Blocks SDK .Net] Disposing a LiveSourceSwitchBlock now releases its inputs and internal resources. The teardown freed nothing at all, so an application that created and disposed switchers - or added file inputs to one - leaked a whole graph, including a pipeline per input, on every instance.
  • [Media Blocks SDK .Net] A LiveSourceSwitchBlock configured for one stream only (VideoStream or AudioStream turned off) now starts. It threw a NullReferenceException on the first StartAsync, so the setting could not be used at all. Input_AddAsync now also refuses an input for a stream the switch does not carry and returns false instead of throwing, or - for an audio input on a video-only switch - accepting it and playing nothing. The same applies to LiveSourceSwitchBlockDynamic.Input_AddToSlotAsync, where a video/audio input on a switch without audio is now refused rather than half-connected.
  • [Media Blocks SDK .Net] Building a BridgeBufferSourceBlock whose paired sink was never created, or has already been disposed, no longer throws ArgumentNullExceptionBuild() returns false instead.
  • [Media Blocks SDK .Net] Retargeting a UDP sink at runtime no longer sends to a mixed destination. UDPSinkBlock.SetFilenameOrURL and the UDP MPEG-TS sinks pushed the new host and the new port as two separate steps, so two calls landing at once could leave the sink streaming to one URL's host and the other's port. An IPv6 URL now reaches the sink correctly - udp://[ff05::1]:5004 used to arrive with the brackets still on the address, which it cannot resolve, the URL reported back by GetFilenameOrURL could not be parsed again, and a link-local zone id (udp://[fe80::1%25eth0]:5004) kept its percent escape. This covers the UDP sink; the UDP source, universal source and RTSP server are the matching follow-up. New public overload UDPSinkSettings.TryParseUrl(string url, out string host, out int port) returns the parsed pair, for callers that must not read it back off shared settings.
  • [Core] Fixed a memory leak on every GStreamer property or caps field set to a string, or to a caps, structure, buffer or tag reference. The value handed to the element was copied but the caller's copy was never released, so each set leaked the string's allocation - or, for caps and elements, held a reference that kept a live GStreamer object alive for the rest of the process. Worst on properties pushed repeatedly: text and image overlay contents, bridge channel names, device paths, file names and URLs, and every caps renegotiation. Numeric and boolean properties were never affected.
  • [Media Blocks SDK .Net] A media block that is garbage-collected without being disposed no longer tears its GStreamer elements down from the finalizer thread. An application that forgot a Dispose(), or dropped a block after an exception, could see a crash or a stall inside the .NET finalizer during collection; abandoned blocks now leave their elements to the pipeline that owns them.
  • [Core] The WPF VideoView no longer shows a black preview in a remote-desktop session when the D3D11 composable renderer is requested. Such a session composes WPF in software and its Direct3D9 device sits on a different adapter, so the GPU surface can never be presented; the view now detects that and falls back to its software rendering path automatically, logging a warning, instead of displaying nothing.
  • [Core] Fixed the WPF VideoView silently dropping back to software rendering on the second playback. After a Stop() the next start rebuilt the view from the engine's renderer mode alone — and both the D3D11Composable and Direct2DManaged paths rewrite that mode to FrameCallback — so GPU-resident composition degraded to a per-frame CPU upload, with no error and GetSurfaceProvider() returning null. The view now remembers the renderer it was asked for and restores it on the next start; setting a different renderer mode on the engine between two starts still switches away from it, as before.
  • [Media Blocks SDK .Net] Audio effects added during playback are now inserted at their position in the effect list, so the applied order no longer depends on whether an effect was added before or during playback - and a second effect added straight after the first is no longer silently left out of the pipeline. The block's output also correctly follows the last effect after live additions and removals; removing the last effect used to leave the block pointing at the removed one.
  • [Media Blocks SDK .Net] An audio or video effect added while the pipeline was being stopped or disposed is no longer silently lost. Stopping the pipeline from the effect's own OnUpdate handler let the block build the effect's element against a pipeline that no longer existed: nothing failed, nothing was reported, and the effect was simply absent from the graph. The block now reports it and keeps the effect registered, so the next start puts it in.
  • [Core] Calling Dispose() on a GStreamer wrapper object no longer prints a GLib critical such as gst_iterator_free: assertion 'it != NULL' failed or gst_structure_free: assertion 'structure != NULL' failed. The object was always freed correctly; a second, redundant free with a null handle produced the log line. This affected Gst.Iterator, Gst.Structure, Gst.Video.VideoInfo, Gst.Audio.AudioInfo, Gst.Video.VideoConverter, Gst.ParseContext and the other non-reference-counted opaque wrapper types, all of which are now safe to dispose.

2026.8.18

  • [Core] Fixed a crash when playback was stopped while the WPF VideoView was rendering through Direct2DManaged. The view freed the RGBA staging buffer on the UI thread while a frame was still being converted into it on the streaming thread, which corrupted the heap or took the process down outright. The same buffer was also sized from the very first frame and never grown, so a source that switched to a higher resolution mid-stream overflowed it.
  • [Core] Fixed the WPF VideoView silently replacing a classic engine's WPF_WinUI_Callback / FrameCallback, None, Direct2DManaged or D3D11Composable renderer mode with EVR. The view built a native HWND renderer instead of the requested one, so WPF controls placed over the video stopped composing (airspace), and for WPF_WinUI_Callback and None the engine's Video_Renderer.VideoRenderer read back EVR — a mode the application never set. (Direct2DManaged and D3D11Composable still read back as FrameCallback: the view draws those itself and the engine feeds it frames.) Calling VideoView1.SetNativeRendering(false) is no longer required for the software rendering path.
  • [Media Blocks SDK .Net] Stopping a pipeline that has already reached the end of its stream no longer waits ten seconds for an end-of-stream that has already happened. The output file was already complete; the stop just took that long to return.
  • [Media Blocks SDK .Net] Fixed stopping a pipeline reporting a spurious errorResume for EOS did not reach PLAYING ... Muxer may not finalize — when the pipeline had not finished starting up yet. The stop also stalled two seconds before reporting it, and applications that treat an SDK error as a failure saw a clean stop as a failed one.
  • [Media Blocks SDK .Net] Fixed a crash when chroma-key settings were changed while the pipeline was being stopped. Updating the key color, alpha or sensitivity from one thread used to be able to land on the filter while another thread was tearing it down.
  • [Media Blocks SDK .Net] Fixed audio effect settings being silently discarded when changed while the pipeline was being stopped. Every audio effect — volume, balance, amplify, echo, compressor/expander, both equalizers, pitch, loudness normalization, RNNoise, HRTF, Csound, the Chebyshev filters, karaoke, wide stereo, reverberation and the rest — used to be able to push a change onto an element another thread had already released, in which case nothing happened and nothing was reported.
  • [Media Blocks SDK .Net] Fixed removing an audio effect while the pipeline is being stopped leaving that effect in the graph. The removal reported success while the effect was still spliced into the chain, and could also throw IndexOutOfRangeException out of AudioEffectsBlock.Clear.
  • [Media Blocks SDK .Net] Fixed AudioEffectsBlock.Remove not removing an effect that had been updated since it was added. The live element was unplugged but the effect stayed in the list, so the next time playback started it came back.
  • [Media Blocks SDK .Net] Fixed AudioEffectsBlock.AddOrUpdate called twice with the same effect object stopping that effect's later property changes from reaching the graph.
  • [Media Blocks SDK .Net] Audio effect names are now matched the same way everywhere — case-insensitively. Adding Volume and then volume used to create two effects that both drove the first one.
  • [Media Blocks SDK .Net] Fixed a NullReferenceException when an audio effect property was changed after the pipeline had been stopped.
  • [Media Blocks SDK .Net] Pipelines containing an AudioEffectsBlock no longer carry one unused audio converter element each.
  • [Media Blocks SDK .Net] Fixed the whole video or audio effect chain silently disappearing for the rest of the run after a stop that had to give up waiting for an effect operation to finish. The block was left claiming it was built while owning nothing, so every later start produced no effects at all and reported no error.
  • [Media Blocks SDK .Net] Fixed VideoEffectsBlock keeping every effect object it was given alive after it was disposed. The effects stayed subscribed to the disposed block, so neither they nor the pipeline's elements could be collected, and changing one of their properties afterwards reached a block whose pipeline was gone.

2026.8.17

  • [Media Blocks SDK .Net] Fixed playback freezing for the rest of the run when a video or audio effect added to a running pipeline is refused by the graph. The effect is simply not applied now, instead of leaving the chain cut at the point it was being inserted.
  • [Media Blocks SDK .Net] Fixed the same freeze on the removal side: removing a video or audio effect from a running pipeline no longer cuts the chain when the surrounding elements cannot be linked to each other. The effect stays in place and the removal reports failure, instead of reporting success over a chain nothing flows through.
  • [Media Blocks SDK .Net] Removing an effect that is built from several elements — box, crop, aspect-ratio crop, resize, pan/zoom, fisheye, LUT, text overlay, image overlay, QR overlay, mouse highlight, overlay manager, pitch, compressor/expander, loudness normalization — now takes them out of a running graph as one unit. A removal that succeeded for some of an effect's elements and failed for the rest used to leave the effect half in the graph: the next effect added live could end up in the wrong position, or the block could stop producing output altogether. The removal now either takes the whole effect out or leaves it running untouched and reports failure.
  • [Media Blocks SDK .Net] Removing a LUT or QR-code overlay effect live no longer leaves the chain pinned to that effect's pixel format. Both build an internal format filter, and it used to stay in the graph after the effect was gone, forcing RGB on everything downstream of it for the rest of the run.
  • [Media Blocks SDK .Net] Repeatedly adding and removing a LUT effect during playback no longer leaves an unused element in the pipeline for every add. That internal format filter is now taken out with the rest of the effect instead of accumulating one per add; the QR-code overlay releases its own the same way.
  • [Media Blocks SDK .Net] Changing an effect's settings from one thread while the pipeline is being stopped on another no longer silently does nothing. The push used to be able to land on an element the teardown had already released, in which case it was discarded without any error being reported. Most visible on Android, where the renderer's resize is updated from the view thread whenever the view is resized or the device is rotated.
  • [Media Blocks SDK .Net] Fixed a NullReferenceException when the Android renderer's view was resized while the pipeline was stopping.

2026.8.16

  • [Core] Fixed video fingerprinting FrameSource.PlayAsync throwing NullReferenceException unless the optional Crop and CustomResolution properties were set.
  • [Core] Video fingerprinting: new FrameSource.StopAsync() stops the current session and releases its pipeline so the instance can be reused — previously the only way to stop was disposing the whole object.
  • [Core] Video fingerprinting: the VFPAnalyzer error callback now fires exactly once per failed analysis, on the caller's thread, with the underlying cause — previously mid-run errors could be swallowed entirely or delivered from the pipeline's internal thread.
  • [Core] Video fingerprinting: a repeated FrameSource.PlayAsync now stops and disposes the previous session instead of leaving its pipeline playing for the life of the process, a failed PlayAsync cleans up the half-built pipeline and is reported through the VFPAnalyzer error callback instead of hanging the analysis, and Dispose tears the session down in a safe order.
  • [Core] Fixed event handlers subscribed after start never being called in VideoCaptureCoreX (OnError, OnStart, including separate outputs), MediaPlayerCoreX (OnError, OnStart, OnPause, OnResume) and the video fingerprinting FrameSource (OnError, OnStop) — the engines captured a snapshot of the handler list at start, so late subscribers were silently ignored and unsubscribing mid-session did not detach.
  • [Media Blocks SDK .Net] Fixed LiveVideoCompositor Video_Effects_Clear removing every channel's effects instead of only the requested channel's — clearing channel 0 no longer wipes the effects of all other channels for the rest of the run.
  • [Media Blocks SDK .Net] LiveVideoCompositor video-effect calls that target a channel which does not exist, or that run after the compositor was disposed, no longer throw ArgumentOutOfRangeException — the call is ignored and reported through the log and OnError. Applies to Video_Effects_AddOrUpdateAsync, Video_Effects_Get, both Video_Effects_RemoveAsync overloads and Video_Effects_Clear.
  • [Media Blocks SDK .Net] Fixed LiveVideoCompositor OnError handlers never being called — pipeline errors were dropped instead of reaching subscribers.
  • [Media Blocks SDK .Net] Video effects added during playback are now inserted at their position in the effect list, so the applied order no longer depends on whether an effect was added before or during playback, and the block's output correctly follows the last effect after live additions and removals.
  • [Media Blocks SDK .Net] Video effect names are now matched without regard to case. Adding "Blur" and then "blur" updates one effect instead of creating a second one that could never be updated or removed, and Video_Effects_Get keeps finding an effect whatever case it is asked for.
  • [Media Blocks SDK .Net] Updating a video effect with one of a different type under the same name now replaces it in the pipeline. The graph used to keep applying the old effect and only report the mismatch.
  • [Media Blocks SDK .Net] Fixed a video effect added while the pipeline was starting never reaching the pipeline for the rest of the run. It is now applied as soon as playback begins.
  • [Media Blocks SDK .Net] Fixed adding, removing and updating video effects from several threads at once leaving a filter in the pipeline that no public call could reach, or applying settings to an effect that was being removed.
  • [Media Blocks SDK .Net] Adding a video effect to a running pipeline now returns only once playback has resumed, so stopping right after it no longer reports that the pipeline could not be resumed.

2026.8.15

  • [Media Player SDK .Net] / [Media Blocks SDK .Net] Fixed Video_Effects_RemoveAsync never returning when the pipeline has nothing to pause — a player that was never opened, or one already being stopped. It polled for the paused state with no way out, and in one overload it blocked the calling thread outright, so the call could not be interrupted from outside either. It now checks the pause once and returns: a pause that did not land is reported through the log and the effect is left in place. LiveVideoCompositor.Video_Effects_RemoveAsync is fixed the same way.
  • [Media Blocks SDK .Net] Fixed adding a video effect never returning when the pipeline is shutting down, and adding one to a paused pipeline waiting forever. The wait for playback to resume is now capped at thirty seconds; past it the effect is left for the next start and the wait is reported.
  • [Media Blocks SDK .Net] Fixed a crash when changing a property of a video effect that is not applied to the running pipeline — one added while playback was paused or stopped, with at least one other effect already active. The property setter threw an exception instead of doing nothing.
  • [Media Blocks SDK .Net] Fixed an effect being applied twice to a running pipeline, leaving a duplicate filter that could no longer be updated or removed, and an effect coming back after being removed when it had been re-added under the same name.

2026.8.14

  • [Video Capture SDK .Net] / [Media Player SDK .Net] Fixed a GStreamer error when removing a video effect (grayscale, balance, and the other live filters) from a paused capture or player pipeline.
  • [Video Capture SDK .Net] / [Media Player SDK .Net] Fixed video stopping after removing an image overlay, overlay manager, pan/zoom, or LUT effect at runtime.
  • [Media Player SDK .Net] Fixed audio going silent after removing an audio effect during file playback.
  • [Media Player SDK .Net] / [Media Blocks SDK .Net] Fixed a hang when removing pitch, compressor, loudnorm, or similar multi-element audio effects from a live pipeline.
  • [Media Blocks SDK .Net] Fixed a crash when disposing an AudioEffectsBlock that still had effects in the public list.
  • [Video Capture SDK .Net] / [Media Blocks SDK .Net] Fixed MP4 recordings that could not be played back after stopping a paused capture (VideoCaptureCoreX / MediaBlocksPipeline). Start → Pause → Stop (without Resume) left a non-zero file with no moov index. Stopping a paused capture now finalizes the file.
  • [Media Blocks SDK .Net] RTSP sources can send their own GET_PARAMETER keep-alive. Set RTSPSourceSettings.ForceCustomKeepAlive (or the same flag on RTSPRAWSourceSettings) to replace the default RTSP keep-alive with a GET_PARAMETER every 30 seconds. Off by default — use it if a camera drops the session under the built-in keep-alive.
  • [Demos] The RTSP Preview demos now have a transport selector (Auto / TCP / UDP) and a Force custom keep-alive checkbox, so a camera that works in VLC but dies after a minute can be tried the same way without rebuilding.

  • [Media Blocks SDK .Net] Fixed the first line of an OverlayManagerText (and OverlayManagerDateTime) disappearing when Y was 0 or close to the top of the frame. X and Y are the top-left corner of the text in pixels; (0, 0) is a valid position and the first line of a multiline string is fully visible there. Previously the coordinates were treated as the Cairo baseline, so a block placed at the origin had its first line clipped off the top of the picture.

  • [Media Player SDK .Net] MediaPlayerCoreX now has the same overlay manager as capture. Set Video_Overlay_Enabled before OpenAsync/PlayAsync and use Video_Overlay_Add with OverlayManagerText (including TextProvider). The overlay is drawn on the preview only — after the sample grabber and after any custom video outputs — so the file on disk, snapshots and exports are not modified. Overlays added once stay across Stop and opening another file.

2026.8.13

  • [Media Blocks SDK .Net] OverlayManagerText can now build its text for every frame through the new TextProvider callback. Set TextProvider to a Func<TimeSpan, string> and it is asked for the text once per frame, receiving the frame timestamp counted from the pipeline start; returning null falls back to Text. This is the supported way to overlay a live readout — sensor values, a clock, a frame counter, or a template mixing all three — without removing and re-adding the overlay or touching the pipeline. Assigning Text directly still works and is equally cheap: the text layout is cached on the element and re-measured only when the string, font or geometry actually changes, so an unchanged value costs nothing. The callback runs on the streaming thread while the overlay list is locked, so it must be short and must not block — calling back into a UI dispatcher from it can deadlock rather than merely drop a frame. A callback that throws is reported once through OnError and is then not called again: the element falls back to Text for the rest of the run, because retrying it would unwind an exception at the frame rate under that lock. Assign TextProvider again to re-enable it — worth knowing if your callback can throw on its first frame, while the values it reads are still being initialised. OverlayManagerDateTime inherits the property and substitutes its [DATETIME] token into whatever the callback returned.
  • [Media Blocks SDK .Net] Overlay elements are now up to twice as fast on multi-core machines. Cairo-based overlays render through cairooverlay, which only accepts BGRx/BGRA/RGB16, so a YUV source pays for two full-frame colour conversions per frame — and those conversions were running single-threaded, which was not enough to sustain 1080p50 on many machines. The recording branch was the first to suffer, because a preview renderer silently drops late frames while an encoder writes whatever reaches it, so the preview looked fine and the recorded file did not. Measured on a 14-core machine at 1920x1080 NV12: 361 to 815 frames per second through OverlayManagerBlock. Affects OverlayManagerBlock, ImageOverlayCairoBlock, PanZoomBlock, the mouse-highlight overlay and the Android text overlay.
  • [Media Blocks SDK .Net] Fixed StartTime and EndTime on overlay elements being ignored unless both were set. The visibility window was only applied when neither value was TimeSpan.Zero, so the common case of "show this for the first ten seconds" — a zero StartTime with a real EndTime — left the element on screen for the whole session. Either bound now defines a window on its own, and an EndTime of TimeSpan.Zero means the element has no end. The break is symmetric, so check both directions: an element with only EndTime set used to stay visible for the whole session and now disappears at that moment, and an element with only StartTime set used to be drawn from the first frame and is now hidden until that moment. If you set either value and relied on it being ignored, clear it. Frames that carry no timestamp at all — an appsrc feeding unstamped buffers, for instance — are outside any window that can be judged, and every element is drawn on them.
  • [Media Blocks SDK .Net] RTCP is now on by default for RTSP sources. RTSPSourceSettings.DoRTCP and RTSPRAWSourceSettings.DoRTCP defaulted to false, and the value is always written to the underlying RTSP source — so no VisioForge application ever sent RTCP receiver reports unless it set the property itself. Many cameras and RTSP servers use those reports to tell that the client is still watching and tear the session down without them: the picture freezes on the last decoded frame and the stream ends a session timeout later, with nothing in between to explain it. The same omission also made NTPSync ineffective, because the NTP mapping arrives in RTCP sender reports. Both properties now default to true, which is also the default of the underlying GStreamer element. Set DoRTCP = false explicitly if you talk to an old server that cannot handle RTCP.
  • [Demos] Fixed the RTSP Preview demos building a second pipeline when Start was clicked twice. Connecting to a camera takes a few seconds, and nothing appears on screen while it happens, so a second click was easy to make — it created a second pipeline over the same VideoView and opened a second session to the same camera. The two fought over the preview window, one of them failed with "Failed to open window", and on a camera that serves a single session its teardown stopped the stream for the surviving pipeline too, leaving a frozen picture. The Start button is now disabled while a start is in progress, a pipeline abandoned by a failed start is released instead of leaking, and the demos now report the stream ending — including a camera dropping the session — in their log instead of leaving a still frame with no explanation.
  • [Media Blocks SDK .Net] A user-defined overlay element can now be drawn through the new IOverlayManagerDrawable interface. Video_Overlay_Add accepts any IOverlayManagerElement, but only the built-in element types were rendered, so a custom type was silently never drawn. An element that implements IOverlayManagerDrawable.Draw now receives the live Cairo context of the frame exactly like OverlayManagerCallback does. A custom type that implements neither the interface nor a built-in type is still not drawn, but is now reported once through OnError naming the type instead of failing silently.

2026.8.7

  • [Core] The BCL cryptography packages now match the framework you target instead of always being the .NET 10 line. System.Security.Cryptography.Pkcs, System.Security.Cryptography.Xml and System.Formats.Asn1 were pinned at 10.0.10 for every target framework, so a .NET 6, 7, 8 or 9 application referencing a VisioForge package was pulled onto the 10.0.x line whether or not it wanted to be there — and an application holding the 8.0.x servicing line got a version conflict it could not resolve, because our own assemblies were compiled against System.Security.Cryptography.Pkcs, Version=10.0.0.0. A .NET 6, 7 or 8 application now resolves the 8.0.x line and .NET 9 the 9.0.x line; .NET 10, .NET Framework 4.7.2/4.8 and .NET Standard are unchanged at 10.0.10. .NET Framework 4.6.1, .NET Core 3.1 and .NET 5 move down to the 6.0.x line — that is the only line these three are supported on, and it is what gives them a real net461 / netcoreapp3.1 build instead of a netstandard fallback, but 6.0.x is out of support and did not receive the 2026 System.Security.Cryptography.Xml fixes. If you target one of those three frameworks and that matters to you, add an explicit PackageReference to System.Security.Cryptography.Xml 10.0.10 in your own project — expect a build warning with it, because 10.0.x states it does not support those frameworks and falls back to its netstandard2.0 build. That warning is exactly the reason the SDK itself does not take 10.0.x there. Every other rung sits at a patched version (8.0.4, 9.0.19, 10.0.10), because those advisories are fixed in each branch separately. On .NET 6 and .NET 7 this also replaces a netstandard2.0 fallback with the real framework build.
  • [Core] System.Text.Encoding.CodePages now matches the framework you target as well — 6.0.1 on .NET Framework 4.6.1, .NET Core 3.1 and .NET 5, 8.0.0 on .NET 6 and .NET 7, and 10.0.6 unchanged on .NET 8 and newer, on .NET Framework 4.7.2/4.8 and on .NET Standard. Those older frameworks were previously handed the 10.0.6 package, which states it does not support them and gave them a netstandard2.0 build; they now get one made for the framework they run on. This package carries no security advisory at any version.
  • [Core] Fixed VisioForge.DotNet.Core not declaring its dependency on System.Security.Cryptography.Pkcs. The package has needed it since 2026.2.19 — the licensing code verifies Authenticode signatures — but it was declared only from 2026.4.21 onwards, and only as a side effect of how the dependency graph happened to be built. If you are on a version between 2026.2.19 and 2026.4.18, the shipped assembly requires System.Security.Cryptography.Pkcs 10.0.0.0 with nothing in the package asking for it; add the package reference yourself or move to a current release.
  • [Demos] Fixed the Unity package's sample scenes logging three "The referenced script (Unknown) on this Behaviour is missing!" errors each in any project that does not use the Universal Render Pipeline and the Input System. The scenes were authored from a URP 2D template and carried a Light2D, a UniversalAdditionalCameraData and an InputSystemUIInputModule that none of the samples use — the video is rendered into a uGUI RawImage, which needs no render pipeline and no input module. They now open cleanly on Built-in, URP and HDRP alike.
  • [Demos] Fixed the Unity RTSP and IP-camera samples printing a "Frame stall" warning the moment a stream starts, on the first connect and on every reconnect after it. The watchdog compared its timeout against the time since the last decoded frame, which is infinite before the first frame ever arrives and, after a drop, still points at the last frame of the previous session — so it fired seconds before the camera could deliver anything. The reported stall is now capped at the age of the current stream, and a camera that genuinely never delivers is still reported after the same timeout.
  • [Core] Fixed the Avalonia VideoView reporting a black background even when one was set. GetBackgroundColor() only read immutable solid-color brushes, so the mutable SolidColorBrush the control installs itself — and any colour a user assigns — always fell back to black, and that wrong colour fed the renderer as its clear colour. It now reads any solid-color brush, mutable or immutable.

2026.8.6

  • [Core] Fixed video editing and video preview breaking on macOS. VideoEditCoreX failed every render that had a video track — any container, any codec — with Internal data stream error, while audio-only output still worked; and VideoRendererBlock froze the pipeline on the first frame in any application without a Cocoa UI running on its main thread, such as a console tool, a background service or a test host. GStreamer picks several elements automatically by rank rather than by name, and the Metal elements' ranks put them ahead of the software ones, so they were selected in places they were never meant for — including as the mixer inside every video-editing timeline. They are now registered for explicit use only, and the Metal video renderer is used only when you give it a view to draw into. MetalVideoCompositor, MetalConvertScale, MetalVideoRendererSettings and the other Metal wrappers are unaffected and still give you GPU rendering when you ask for it.
  • [Core] Fixed VideoRendererBlock(pipeline, windowHandle) ignoring the window handle on Windows and macOS — only the Android and iOS paths read it, so elsewhere the renderer behaved as though no target window had been given and opened one of its own. On macOS this constructor now also defaults to the Metal renderer, which is the only one there that can draw into a handle you supply. Two consequences, both documented on the constructor: the handle must be an NSView* (not an NSWindow*), and your main thread must keep running a Cocoa run loop while the pipeline plays, because the Metal renderer attaches to the view on the main queue.

2026.8.5

  • [Core] The SDK no longer brings a pre-release package into your dependency graph. SkiaSharp moves from 3.119.4-preview.1.1 to the stable 3.119.4, and Avalonia from 12.0.3 to 12.0.5 — the two had to move together, because Avalonia itself switched to the stable SkiaSharp in 12.0.4 and holding it back would have kept a preview build of the WebAssembly native assets in the graph. Restoring a VisioForge package used to pull those preview builds transitively, with no opt-in on your side and no warning: they simply appeared in your lock file and in dotnet list package --include-transitive. That matters if you mirror packages into an internal feed that rejects pre-release versions, or if a policy scan flags them. Everything the SDK resolves is now a stable release. The SkiaSharp difference itself is confined to bundled native libraries (libexpat 2.7.5, libpng 1.6.58) — no API changed.
  • [Core] The Avalonia package no longer brings a nightly build of DialogHost.Avalonia with it. VisioForge.DotNet.Core.UI.Avalonia uses MessageBox.Avalonia for ShowMessageEx, and MessageBox.Avalonia 12.0.0 — still its newest release — depends on DialogHost.Avalonia 0.12.1-nightly.0.1, so that nightly landed in the dependency graph of every application referencing our Avalonia package. DialogHost is now pinned to the stable 0.12.3. No API or behaviour change on our side.
  • [Core] VisioForge.DotNet.Core.AI.Whisper now requires .NET 8 or newer. Seven builds are gone from the package — net5.0, net5.0-windows, net6.0, net6.0-windows, net7.0, net7.0-windows and net7.0-windows10.0.19041.0 — so a WinUI or WPF head on one of those is affected as much as a plain console project. net8.0, net9.0, net10.0 and their Windows, Android, iOS, macOS and Mac Catalyst variants are unchanged. Speech-to-text runs on Whisper.net, which now depends on Microsoft.Extensions.AI.Abstractions and through it on System.Text.Json 10, and System.Text.Json 10 states that it does not support and has not been tested on anything below .NET 8 — so those seven builds could only have shipped in a configuration Microsoft declares untested. .NET 5, 6 and 7 are themselves all out of support. If you reference this package from any .NET 5, 6 or 7 project, retarget it to net8.0 or later — keeping the same platform suffix if it has one; no code changes are needed. Only this package is affected — every other VisioForge package keeps its full framework list, down to .NET Framework 4.6.1.
  • [Core] The macOS native package now ships the SRT and WebRTC GStreamer plugins. Six plugins — libgstsrt.dylib, libgstsrtp.dylib, libgstwebrtc.dylib, libgstrswebrtc.dylib, libgstwebrtcdsp.dylib and libgstwebrtchttp.dylib — and the three libraries they load against (libgstwebrtc-1.0.0.dylib, libgstwebrtcnice-1.0.0.dylib, libsrt.1.5.3.dylib) were built and kept current but never packaged, so on macOS any pipeline using SRT or WebRTC failed to find its element, while identical code worked on Mac Catalyst, whose package has carried them all along. VisioForge.CrossPlatform.Core.macOS.Adds now ships the same 58 files as its Mac Catalyst counterpart.

2026.8.1

  • [Demos] Fixed several shipped samples referencing outdated packages. The macOS and Mac Catalyst native packages in the demo projects were six months behind the published versions, a net472 demo pinned a System.Resources.Extensions build meant for .NET 8 and newer, and the Virtual Camera and WebM redistributables were pinned to 2023-era releases. If you copied a demo project as a starting point, its package references were older than the SDK you installed.
  • [Core] Security: updated System.Security.Cryptography.Xml to 10.0.10, closing five advisories that affected the version shipped before it — CVE-2026-47304, a bypass of XML encryption protections rated 8.1, and four denial-of-service issues rated 7.5. System.Security.Cryptography.Pkcs and System.Formats.Asn1 moved to 10.0.10 with it. The SDK does not call these APIs itself; they are reached through WCF, which ONVIF device communication uses. No action is needed on your side beyond taking the new package — but a security scan run against the previous release will have flagged it.
  • [Core] Fixed a random process crash while GStreamer objects were being released. On any platform, an application could die with an access violation (0xC0000005 on Windows, SIGSEGV on macOS) on a background thread, with no error, no exception and nothing in the log to connect it to what the application had been doing — the crash landed long after the code that caused it. The SDK now checks that a native object is still alive before releasing it, and when it is not, writes one line naming the type instead of taking the process down.
  • [Core] API change: VisioForge.GStreamer.API.CustomAPI.g_signal_connect, g_signal_connect_data and g_signal_handler_disconnect now use UIntPtr for the GLib signal handler id instead of uint. The id is a gulong, which is 64-bit on macOS, Linux, iOS and Android, so the previous declaration truncated it. These are low-level interop helpers; if you call them directly, change the variable holding the handler id to UIntPtr.
  • [Media Blocks SDK .Net] The SDK no longer takes ownership of the elements a decoder builds while playing a file. Playing any file made the SDK hold a native reference to every element inside uridecodebin — parsers, demuxers, queues, several hundred per playback — and those references were given back only later, on a background thread, so the elements stayed alive past the pipeline that owned them. This is the same ownership mistake behind the render-time crash fixed below, on the playback path; measured on a four-class test run, the number of such references dropped by 78%. Affects every engine that plays or captures through a file or URL source.
  • [Core] Fixed an error or warning on the pipeline bus tearing down the bus handler. In VideoEditCoreX and SimplePlayerCoreX, an error message that carried no source element raised a NullReferenceException inside the handler, so that message and every message after it was lost — including the error you needed to see. A state-change message with no source could also be mistaken for one from the pipeline itself while the pipeline was being torn down.
  • [Video Edit SDK .Net] Fixed a process crash after rendering with VideoEditCoreX. An application that rendered several timelines in one session could die with an access violation on a background thread, typically long after the render had finished and the objects involved had been released. Rendering to WMV made it most likely, but the underlying cause affected any render. Applications that create and destroy VideoEditCoreX repeatedly — batch converters, render services — were the most exposed.
  • [Core] Fixed Debug_Mode writing an empty log file. With debug logging enabled, the log was buffered and never flushed when the engine was disposed, so a short session produced an empty file and a longer one lost everything after the last automatic flush — exactly the log you are asked for when reporting a problem. The file also stayed locked for the life of the process, so it could not be read or deleted. Affects VideoCaptureCoreX, MediaPlayerCoreX, SimplePlayerCoreX, VideoEditCoreX and MediaBlocksPipeline.
  • [Core] Fixed the same empty log file when the engine was disposed with await using. The fix above covered the synchronous Dispose() only, so MediaPlayerCoreX and SimplePlayerCoreX released asynchronously — the form most applications use — still produced an empty or truncated log and still held the file open. SimplePlayerCoreX.DisposeAsync is also safe to call twice now, and on all three engines a failure during teardown no longer swallows the log, which is precisely the case you need it for.
  • [Media Blocks SDK .Net] Fixed open-vocabulary detection exhausting memory on Apple hardware. OpenVocabularyDetectorBlock and ObjectAnalyticsBlock with an open-vocabulary detector could consume every gigabyte the machine had and bring it down rather than produce a detection. ONNX Runtime cannot map OWLv2 or Grounding DINO onto CoreML in one piece — it splits them into 126 and 255 separately compiled models — so Provider = Auto now selects the CPU for these two model families on Apple hardware and leaves every other AI block unchanged. Setting Provider to CoreML by name still does what you ask; it is not recommended for these models. On the CPU provider the memory retained after a detector is disposed also drops by about 2.4 GB on the same models, with no change to inference time.
  • [Media Blocks SDK .Net] Fixed a crash while tearing down ObjectAnalyticsBlock with an open-vocabulary detector. Disposing the block while a frame was still being analysed could free the inference session underneath the analysis and abort the process.
  • [Core] Fixed Media Foundation H.264 and H.265 encoder settings being silently ignored. On a machine whose Media Foundation encoder does not advertise a given control - the property set differs by GPU, driver and machine - the SDK wrote the value anyway. Nothing threw, the call reported success, and the encoder quietly kept its default, so the same code produced different output on different machines with no way to tell. Settings the encoder cannot accept are now skipped, and each one is named in a warning. This covers encoders you build yourself (HEVCEncoderBlock, H264EncoderBlock, CreateBlock()) and the AMD MA35D encoders and decoders. Encoding profiles - MP4Output and the other render outputs - are not covered yet, so the original symptom can still occur there.
  • [Core] Fixed an instability while enumerating Decklink capture cards and outputs. Plugging a card in or out, or listing devices from more than one place at once, could leave the SDK using a device object it had already released — harmless in the log on a good day, a crash on a bad one.
  • [Core] Fixed WASAPI2 audio capture breaking up under load and never recovering. From 2026.3.7, audio captured through a WASAPI2 device could develop artifacts that got worse over time and only cleared when the pipeline was restarted; the log filled with Found N frames gap warnings. The bundled GStreamer runtime was requesting a capture buffer of roughly 20 ms instead of the 200 ms it used to, so any brief stall lost audio at the driver. The buffer is back to its previous size on capture and playback alike, and the LowLatency setting again means what it says. Affects Windows x86, x64 and ARM64.
  • [Core] Added BufferTime and LatencyTime to WASAPI2AudioCaptureDeviceSourceSettings, WASAPIAudioCaptureDeviceSourceSettings, LoopbackAudioCaptureDeviceSourceSettings, WASAPIRendererSettings and WASAPI2RendererSettings. They control how much audio the device buffers — raise BufferTime on machines that see brief CPU spikes, lower it when you need latency. Defaults are 200 ms and 10 ms, matching previous behaviour; set either to TimeSpan.Zero to leave the underlying element untouched.
  • [Core] An audio renderer whose output plugin is missing from the deployment now reports a clear error instead of throwing a NullReferenceException out of StartAsync.
  • [Core] Fixed the built-in HLS/DASH HTTP server never starting on Windows unless the application ran as administrator. With Custom_HTTP_Server_Enabled set, the sink reported no error and the pipeline ran, but nothing was ever served — the server binds http://*:<port>/, which Windows refuses to a process without an elevated token unless a URL reservation exists, and the failure went no further than one line in the log. The server now falls back to the loopback prefixes — both http://localhost:<port>/ and http://127.0.0.1:<port>/, so a player on the same machine works whichever of the two it is given — and the log names the netsh http add urlacl command to run once as administrator to reach the server from other devices. Elevated applications and machines that already have the reservation are unaffected, as are macOS and Linux.
  • [Core] Fixed an application that never exits after DestroySDK(). The SDK runs the GStreamer main loop on a foreground thread, and DestroySDK() could return having failed to stop it: the request to stop was dropped whenever it arrived in the moment between that thread being created and it reaching the loop, and nothing checked afterwards. The process then stayed alive with no window, no error and nothing running — visible as an application that closes but keeps a process in the task list, or a console tool that never returns to the prompt. DestroySDK() now waits for the loop thread to actually finish before returning, and reports it in the log if it does not.
  • [Core] Fixed the WASAPI2 audio renderer going silent whenever Volume was below 1.0. The value was passed to the renderer as a whole number, so anything between 0.0 and 1.0 was rounded down to zero — setting Volume = 0.5 produced silence rather than half volume. Only Volume = 1.0 behaved as expected.

2026.7.27

  • [Media Blocks SDK .Net] Fixed a stopped pipeline not resuming when it was started again — after StopAsync(), a StartAsync() on the same MediaBlocksPipeline with the same blocks returned true and then did nothing: a recorder wrote no bytes, a preview stayed black, and no error was reported. Stopping now keeps the blocks and the connections you made, and starting rebuilds the pipeline from them, so the same pipeline instance can be recorded, stopped and recorded again. You no longer have to recreate the pipeline and every block between runs (doing so still works). A sink filename changed between runs — SetFilenameOrURL — is picked up by the next run.
  • [Media Blocks SDK .Net] Fixed a group of blocks that stayed silent after a pipeline was restarted, each in the same way: the block reported a successful start and then produced nothing. OCR (OcrBlock) and Data Matrix (DataMatrixDecoderBlock) stopped raising their detection events; UniversalDemuxBlock, UniversalAutoDemuxerBlock and UniversalDecoderBlock delivered no data on the second run (the demuxer could also throw from a streaming thread); StreamSourceBlock came up over a closed stream, and now also rewinds a seekable one so a restarted source plays from the beginning; PreEventRecordingBlock dropped every frame and then threw from TriggerRecording(); both squeezeback blocks failed to rebuild. The bridge blocks silently lost the OnEOS handler you had attached at the first stop.
  • [Media Blocks SDK .Net] MediaBlocksPipeline.ClearBlocks() now disposes the blocks it removes. Removing a block hands it back to nobody, and the stop path no longer disposes it, so keeping it alive leaked whatever it held — an inference session, an encoder, a device handle. Do not call ClearBlocks() for blocks you mean to reuse; a stopped pipeline can simply be started again with the same blocks.
  • [Media Blocks SDK .Net] A stop no longer closes a file opened by StreamSourceBlock(filename) for good: the file is released on every stop, as before, and reopened when the pipeline is started again. Stopping and then deleting, overwriting or re-recording to the same path keeps working. A stream you passed in yourself is still never closed by the block — it is yours.
  • [Media Blocks SDK .Net] Fixed a crash on Android when the video surface was recreated after the pipeline was stopped — rotating the device or returning from the background after StopAsync() dereferenced the pipeline the stop had already released.
  • [Media Blocks SDK .Net] Fixed an intermittent crash while a pipeline was being stopped or restarted. Under a restart-heavy load the process aborted outright about one run in three, with no exception to catch — a bus message could still be in the middle of being handled when the stop released the pipeline underneath it. Stopping now waits for an in-flight bus message to finish before releasing anything, and gives up after two seconds rather than hanging.
  • [Media Blocks SDK .Net] Fixed a family of latent memory-corruption defects around teardown and restart, in sample grabbers, renderers, sources, decoders, bridge blocks, effects and device enumeration. Nothing failed visibly: GStreamer's own type checks turned the affected calls into no-ops, so the symptom was warnings in the log rather than a crash — but the same code was one timing change away from a hard AccessViolationException. Restarting a pipeline produces far fewer GST_IS_ELEMENT / GST_IS_PAD warnings; the remaining ones are being worked through.
  • [Media Blocks SDK .Net] Fixed removing a video or audio effect at runtime leaving the pipeline holding a released element. Every effect filter — 51 of the video ones and 15 of the audio ones — released its GStreamer element while still pointing its own input and output at it, so removing an effect, or clearing them all, worked on the surface while the next teardown reached through a dangling reference. As with the teardown defects above, GStreamer's type checks kept it to log warnings instead of a crash, but the memory was already gone.
  • [Media Blocks SDK .Net] Fixed UniversalTransformBlock releasing its own pads on the first frame. The transform callback released the pads the block had published, so every later probe, unlink and teardown on that block used a dead reference. CustomMediaBlock did the same to the pads its wrapped element owns, including the pad handed to it when a demuxer creates one.
  • [Core] Fixed a reference-counting error that corrupted GStreamer's encoder registry on Windows. Enumerating the available hardware encoders released a reference the SDK never held, on every encoder registered on the machine — audio ones included. GStreamer detected it, logged a warning per encoder and recovered, so nothing failed visibly, but the accounting was left inconsistent and a concurrent registry change could have turned that into a crash.
  • [Media Blocks SDK .Net] Fixed Vorbis audio bitrate settings being ignored. VorbisEncoderSettings.Bitrate, MaxBitrate and MinBitrate are documented as "-1 to disable", which is also their default, and that default was passed to the encoder as an out-of-range value. The encoder rejected the whole assignment and fell back to its own defaults, so a bitrate you set took effect only if you had also set the other two. Encoding profiles built from these settings carried the same invalid value.
  • [Media Blocks SDK .Net] Fixed the pipeline-graph debug helpers misbehaving once playback had finished. Debug_GetPipeline() and Debug_SavePipeline() called after a stop — including the stop that happens on its own when a file reaches the end — wrote no graph and logged a GStreamer warning instead. Debug_GetPipeline() now returns an empty string, as documented, and Debug_SavePipeline() does nothing. The same applies to VideoCaptureCoreX.Debug_SavePipeline().
  • [Video Capture SDK .Net] Fixed Video_Source_GetResolutionAndFrameRate and Audio_Source_GetInfo damaging a running capture. Both released the source block's own pad, so calling either of these read-only queries while capturing left the source unusable.
  • [Video Capture SDK .Net] Fixed the second recording of a separate-capture output silently producing no file. With an output registered and the engine running, StartCaptureAsync(index, filename) worked the first time and every later call returned true while writing nothing — the record button worked exactly once per application run. All subsequent recordings now write to the file passed to StartCaptureAsync, with the preview left untouched, which is what the API is for.

2026.7.26

  • [Media Blocks SDK .Net] Added AndroidUVCSourceBlock — capture from a USB (UVC) camera connected to an Android device over OTG, such as a webcam or a capture dongle. These cameras are invisible to the regular SystemVideoSourceBlock, because Android only exposes them through Camera2 on devices whose vendor ships the External Camera HAL (Samsung, among others, does not). Connected cameras are listed with AndroidUVCDevices.FindCameras(), access is requested with AndroidUVCDevices.RequestPermissionAsync(), and the requested resolution and frame rate are matched against the modes the camera advertises. Your app must declare and be granted android.permission.CAMERA — Android refuses to hand a USB video device to an app without it, even though the Android camera API is not used. Unplugging the camera ends the stream, so the pipeline reports end-of-stream rather than stalling silently. Requires Android 9 (API 28) or later. Note that a camera enumerating at USB 2.0 speed offers markedly lower frame rates than on a desktop: a Logitech BRIO, for example, tops out at 1080p30 (MJPEG) with no 4K modes available at all.
  • [Video Capture SDK .Net] USB (UVC) cameras on Android can now be used with VideoCaptureCoreX — assign an AndroidUVCSourceSettings to Video_Source and the camera works like any other source, so recording to MP4, network streaming, video effects and snapshots are all available. New AndroidUVCDevices.GetModes() lists the resolutions, frame rates and formats you can actually pick from — formats the SDK cannot stream are left out — so you can offer the real choices instead of requesting a mode and silently getting the nearest one, and AndroidUVCSourceSettings.Format asks for one of them. Two things to know: an unplugged camera is reported through OnError, not OnStop - and only once the stream has been silent for a few seconds, so handle Android's ACTION_USB_DEVICE_DETACHED broadcast as well if your app needs to react the moment the cable comes out; and a camera with a built-in microphone also registers as a USB audio input that Android prefers for recording but that cannot be captured while the camera is streaming, so such a recording is video-only. Live capture should also set the new VideoCaptureCoreX.Video_Output_IsSync = false, which stops the bridge feeding an output pipeline from waiting on the clock - left synced it can fill its queue and stall the preview along with it. Audio_Output_IsSync is the matching switch for the audio branch, so a capture with audio can hand both branches over on the same terms.
  • [Demos] Added a USB Camera Android sample showing live preview from a UVC camera attached over OTG, including the device and permission handling, in both a Media Blocks SDK and a Video Capture SDK version — the latter also records to MP4.

2026.7.24

  • [Video Capture SDK .Net] Fixed Picture-in-Picture crashing on .NET 9 and .NET 10VideoCaptureCore terminated with an unrecoverable ExecutionEngineException at Start/StartAsync as soon as a PiP source was added (the same code worked on .NET 8). Adding a PiP overlay now works on all supported .NET versions.
  • [Video Edit SDK .Net] Fixed the legacy FFMPEG output crashing at start on .NET 9 and .NET 10 with the same ExecutionEngineException; it now works as it did on .NET 8.
  • [Media Blocks SDK .Net] [Video Capture SDK .Net] Fixed video missing or corrupted when streaming MPEG-TS over SRT (SRTMPEGTSSinkBlock, SRTOutput). The MPEG-TS muxer now emits a full 1316-byte payload per buffer instead of one transport packet at a time, so SRT sends whole datagrams rather than seven times as many undersized ones. Receivers such as MediaMTX, ffmpeg or OBS no longer see an audio-only or truncated stream. The UDP, multi-UDP and RIST MPEG-TS outputs get the same alignment.
  • [Media Blocks SDK .Net] [Video Capture SDK .Net] Fixed corrupted video from the Apple (iOS / macOS / Mac Catalyst) H.264 hardware encoder. AppleMediaH264EncoderSettings.AllowFrameReordering was enabled by default; the resulting B-frames left a large share of the encoded frames with a presentation timestamp earlier than their own decode timestamp, so MPEG-TS outputs (SRT, UDP, RIST) and MP4/MOV recordings played back torn or undecodable in MediaMTX, ffmpeg and VLC. RTMP/FLV happened to tolerate it, which is why streaming from iOS looked broken over SRT but fine over RTMP. The property now defaults to false; set it back to true only for offline encoding where you can verify the resulting timestamps.
  • [Media Blocks SDK .Net] [Video Capture SDK .Net] Fixed SRT and RIST output failing to start on macOS and Mac Catalyst when the Apple hardware H.264 encoder was used: the stream parser those outputs need to feed the MPEG-TS muxer was omitted on those platforms.
  • [Media Blocks SDK .Net] [Video Capture SDK .Net] [Video Edit SDK .Net] Fixed MPEG-TS output producing an empty file when AAC audio was encoded with a software encoder (voaacenc, used on macOS, Linux and iOS). The MPEG-TS muxer only accepts framed AAC, which those encoders do not advertise, so the audio never linked and the muxer waited on it instead of writing - the recording ended as a 0-byte .ts. Affects MPEGTSSinkBlock/MPEGTSOutput and the SRT, UDP and RIST outputs built on them.
  • [Media Blocks SDK .Net] Fixed RTSP playback failing with "Failed to link RTSP pad: WasLinked" in UniversalSourceBlockV2. When the source announced a pad it had already handed over - on reconnect, or when a server re-announced a stream - the block tried to link it a second time and reported the result as an error, ending the session.
  • [Media Blocks SDK .Net] Fixed DASH output never starting (DASHSinkBlock): the sink requested its input pads without a name, which dashsink rejects because it takes the stream index from the pad name. No manifest or segments were written and the pipeline hung on start instead of reporting the failure.
  • [Media Blocks SDK .Net] Fixed text overlays rendering as empty boxes (▯▯▯) on iOS, Android and macOS — the SDK now sets up font resolution at startup, so TextOverlayBlock, subtitle overlays and the trial watermark draw real glyphs instead of tofu. Fonts your app bundles are picked up automatically, and on iOS the SDK carries a fallback font so text renders even in an app that bundles none.

2026.7.22

  • [Video Capture SDK .Net] Fixed RTSP / IP camera login and password being URL-encoded, which broke authentication for credentials containing special characters such as &, @, %, ? or spaces (e.g. a password password&@%!?End was sent to the camera as password%26%40%25!%3fEnd). Credentials are now used verbatim. Applies to both the RTSPSourceSettings (X engine) and IPCameraSourceSettings (VideoCaptureCore) sources. If you previously worked around this by storing the pre-encoded value on the device, revert it to the real password after upgrading.
  • [Core] MAUI apps now build cleanly for Android 16: the bundled HarfBuzzSharp native library is updated to a 16 KB page-size-aligned build, removing the XA0141 ("Android 16 will require 16 KB page sizes") warning on Android app builds.

2026.7.21

  • [Media Blocks SDK .Net] Added AMD Alveo MA35D hardware acceleration (via the AMD AMA Video SDK) on Linux: H.264, HEVC and AV1 encoders (AMAH264EncoderSettings / AMAHEVCEncoderSettings / AMAAV1EncoderSettings), matching decoders, and an AMAScalerBlock. A specific MA35D card is selected with the Device property (-1 auto-selects), so you can pin encoding/decoding to the accelerator rather than the host GPU. Requires the AMD AMA Video SDK (kernel driver + GStreamer plugins) to be installed.

2026.7.10

  • [Media Blocks SDK .Net] Added AudioEventDetectorBlock — on-device audio event detection that recognizes real-world sounds (siren, dog bark, glass break, alarm, music, speech, and hundreds more from the 521-class AudioSet ontology) in live or file audio using a YAMNet ONNX classifier. Audio passes through unchanged; detections are raised via OnAudioEvent with a label, confidence, and start/end time, using score smoothing and hysteresis so one continuous sound is a single event rather than a burst of duplicates. Optional class allowlist and a live top-K scores event. Works in VideoCaptureCoreX/MediaPlayerCoreX via Audio_Processing_AddBlock.
  • [Demos] Added an Audio Event Detection WPF sample (Media Blocks SDK): open a file or select a microphone, live event log with label/confidence/time, class-filter box, and threshold slider.

2026.7.9

  • [Core] Video stream info now reports the pixel aspect ratio (VideoStreamInfo.ParNumerator/ParDenominator) when the negotiated caps carry it, so anamorphic sources can be displayed at the correct proportions.
  • [Media Blocks SDK .Net] Fixed pipeline restart after a failed start: blocks no longer report themselves as built when their Build fails, so a retried start rebuilds them instead of running a half-built pipeline.
  • [Media Blocks SDK .Net] File output blocks (M4A/MP4/MKV/AVI) now fail cleanly instead of throwing an unhandled exception when configured with an unsupported encoder, so the pipeline reports a normal start error you can handle.
  • [Core] Fixed stale frame dimensions after a mid-stream resolution change in video frame grabbing: frame callbacks and snapshots kept reporting the old width/height/stride, so the frame data could be mis-read at the new size.
  • [Media Blocks SDK .Net] Added AI auto-reframe (AutoReframeBlock): converts landscape footage into vertical 9:16 (or 1:1, 4:5) video that dynamically crops around the detected subject with smooth, jitter-free tracking — ideal for Shorts/Reels/TikTok.
  • [Demos] Added an Auto Reframe WPF sample (Media Blocks SDK): open a landscape file, follow the subject in a side-by-side original/reframed preview (9:16, 1:1, or 4:5), configure smoothing, dead zone, detection interval, and the followed class, and optionally export the reframed output to MP4.
  • [Media Blocks SDK .Net] Added on-device speaker diarization ("who spoke when"): the new SpeakerDiarizationBlock analyses the audio as it plays and, once the recording has finished, reports every speech turn with the speaker who made it. Diarization is inherently offline — a voice heard at minute 1 can only be matched to the same voice at minute 40 once the whole recording has been heard — so the turns are raised at end-of-stream (OnSpeakerSegment, or GetTimeline() in one piece); check IsTimelineComplete before reading them. Pair it with speech-to-text via DiarizedTranscriptBuilder for a speaker-labeled transcript. Works with MediaPlayerCoreX/VideoCaptureCoreX and manual Media Blocks pipelines. Set NumSpeakers when you know the count, or leave it at -1 and tune ClusterThreshold (a cosine distance — smaller yields more speakers).
  • [Media Blocks SDK .Net] Speaker diarization is multilingual: alongside the default English WeSpeaker voiceprint model you can select the Apache-2.0 3D-Speaker ERes2NetV2 embedding (SpeakerDiarizationSettings.EmbeddingModel = ERes2NetV2Multilingual) for far better speaker separation on non-English or mixed-language audio. The feature front-end adapts to the chosen model automatically, so no other code changes are needed when you switch.
  • [Media Blocks SDK .Net] Fixed degraded speech-to-text accuracy on any source that is not already 16 kHz mono — that is, on essentially every camera, capture card, media file and RTSP stream. The audio front-end decimated to the 16 kHz the model needs without band-limiting first, so everything above 8 kHz folded back into the speech band and corrupted the features both Whisper and the voice-activity detector consume. The audio is now low-pass filtered before the rate conversion.
  • [Media Blocks SDK .Net][Video Capture SDK .Net] Added PTZ auto-tracking — an ONVIF PTZ camera can now automatically follow a detected object. PTZAutoTrackingController turns detections from ObjectAnalyticsBlock (or YOLOObjectDetectorBlock) into continuous pan/tilt/zoom commands with a configurable dead zone, sticky target tracking, a lost-target timeout (with optional return-to-preset), and command rate limiting. Target selection by largest object, first detected, tracker ID, or class label. Includes the new "PTZ Auto Tracking" WPF demo.
  • [Media Blocks SDK .Net][Video Capture SDK .Net] PTZ auto-tracking can now run an idle preset patrol — when no target reappears for a configurable delay, the camera cycles through a list of ONVIF presets (with a per-preset dwell time) until a new target is acquired, which immediately aborts the patrol and resumes tracking.
  • [Demos] Added a PTZ Auto Tracking WPF sample for the Media Blocks SDK — the same ONVIF auto-tracking built on a low-level MediaBlocksPipeline (RTSP source → ObjectAnalyticsBlock → video renderer, with PTZAutoTrackingController driving the camera).
  • [Media Blocks SDK .Net] Added VideoStabilizationBlock — real-time video stabilization that removes camera shake by estimating global inter-frame motion (translation and rotation) with OpenCV optical flow, smoothing the camera trajectory, and warping each frame back onto the smoothed path. Configurable smoothing radius, crop/zoom ratio, and per-frame correction limits; all tunable live. Requires the OpenCV redistributable (Windows).
  • [Media Blocks SDK .Net][Video Capture SDK .Net][Media Player SDK .Net] VideoStabilizationBlock can now be used with the X engines: pass it to Video_Processing_AddBlock() on VideoCaptureCoreX or MediaPlayerCoreX to stabilize a live camera or a playback stream, with live retuning through ApplySettings().
  • [Demos] Added a Video Stabilization WPF sample (Media Blocks SDK): open a file, preview stabilized playback, record the stabilized result to MP4, and adjust the smoothing radius and crop ratio live.
  • [Demos] Added a Video Stabilization Capture X WPF sample (Video Capture SDK X): stabilize a live camera with VideoCaptureCoreX and tune the stabilizer while the capture runs.
  • [Demos] Added a Video Stabilization Camera WPF sample (Media Blocks SDK): stabilize a live camera with a hand-built MediaBlocksPipeline (camera source → stabilizer → renderer), with live tuning.

2026.7.8

  • [Video Edit SDK .Net] Fixed a native process crash (fail-fast) when rendering FLAC output from a timeline with more than one clip (or a gap before the audio clip) in VideoEditCoreX.
  • [Video Capture SDK .Net] Fixed empty WMA audio-only recordings from the legacy VideoCaptureCore engine: the default WMA profile was variable-bitrate (VBR), which the WM ASF Writer cannot produce from a live capture source, so the file contained only an ASF header with no audio data. The default is now an equivalent constant-bitrate WMA profile.
  • [Core][Video Capture SDK .Net][Media Blocks SDK .Net] Fixed a 32-bit (x86) ABI bug that mis-sized the native GMutex field (as a pointer) in the GStreamer object layout, shifting every element's field offsets by 8 bytes on x86. This made the element pad list read as empty and caused a NullReferenceException crash whenever the video/audio sample grabber, snapshots, or a frame-processing block was used on 32-bit. Frame grabbing, snapshots, and per-frame processing now work correctly on x86 (x64 unaffected).

2026.7.6

  • [Media Blocks SDK .Net] Fixed an intermittent "Unable to create sample grabber element" failure that could occur when starting several camera pipelines (e.g. multiple RTSP cameras) at the same time. Managed element construction is now thread-safe.
  • [Media Blocks SDK .Net] Fixed a NullReferenceException crash in the video sample grabber (and related processing elements) that could occur on the streaming thread when a frame buffer was momentarily unavailable.

2026.7.3

  • [Media Blocks SDK .Net] Added PIIRedactionBlock — automatic on-video redaction of personally identifiable information: faces (YuNet), vehicle license plates (FastALPR detector), and on-screen text (PP-OCRv5 detection + recognition — recognition filters out the detector's non-text false positives — with an optional regex filter that redacts only matching text such as e-mails or phone numbers). Redaction styles: Gaussian blur, pixelate, and solid fill. Each category can be toggled live; regions are padded and held between detection cycles so PII stays covered through motion and detector flicker. Works in VideoCaptureCoreX/MediaPlayerCoreX via Video_Processing_AddBlock.
  • [Demos] Added a PII Redaction WPF sample (Media Blocks SDK): webcam, file, or RTSP source with live category/style switching.
  • [Demos] Added Player PII Redaction X and Capture PII Redaction X samples (WPF and MAUI) — live face/plate/text redaction on MediaPlayerCoreX (file playback) and VideoCaptureCoreX (camera) via Video_Processing_AddBlock.

2026.7.2

  • [Media Blocks SDK .Net] Added an open-vocabulary object-detection block (OpenVocabularyDetectorBlock) that detects objects from free-text prompts (OWLv2 / Grounding DINO) instead of a fixed class list, with prompts swappable at runtime. It can also drive ObjectAnalyticsBlock as a detector for tripwire / zone analytics.
  • [Media Blocks SDK .Net] Added a Florence-2 vision-language block (VLMBlock) for frame captioning, OCR, phrase grounding, and object detection.
  • [Media Blocks SDK .Net] Added a CLIP video-embedding block (VideoEmbeddingBlock) with a semantic frame-search index, for natural-language search over indexed video.
  • [Media Blocks SDK .Net] VideoEmbeddingBlock can index a file at full decode speed with no dropped samples via VideoEmbeddingSettings.BackpressureNoDrop (backpressures the pipeline instead of dropping frames when the encoder is busy).
  • [Media Blocks SDK .Net] OpenVocabularyDetectorBlock confidence and IoU thresholds can now be adjusted at runtime (SetConfidenceThreshold / SetIoUThreshold); the new value takes effect on the next frame without rebuilding the pipeline.
  • [Demos] Added three WPF samples: Open Vocabulary Detection, VLM Captioning, and Semantic Video Search.
  • [Media Player SDK .Net] Added MediaPlayerCoreX.Video_Renderer_IsSync — set it to false to run the video renderer without clock synchronization so a file is processed at full decode speed (for offline AI indexing / analysis) instead of in real time; null (default) keeps the automatic behavior.
  • [Demos] Added X-engine versions of the new AI samples (WPF and MAUI): Open Vocabulary Detection and VLM Captioning for both VideoCaptureCoreX (camera) and MediaPlayerCoreX (file), plus Semantic Video Search for MediaPlayerCoreX. Each inserts the AI block through the Video_Processing_AddBlock API.

2026.6.30

  • [Demos] Added Face Recognition and OCR demos for the X engines, in both WPF and MAUI: Player Face Recognition X and Player OCR X (MediaPlayerCoreX), plus Capture Face Recognition X and Capture OCR X (VideoCaptureCoreX). Each inserts the AI block through the Video_Processing_AddBlock API — the face demos enroll people from photos and label them on the video; the OCR demos draw and log recognized text.
  • [Demos] Added a Capture Live Subtitles X WPF sample (VideoCaptureCoreX with on-device Whisper speech-to-text subtitles).

2026.6.29

  • [Media Blocks SDK .Net] Speech-to-text (SpeechToTextBlock) now always transcribes the full input losslessly — the source is paced to Whisper so no audio is ever dropped. The previous live drop-buffer mode and the SpeechToTextSettings.BackpressureWhenBusy option were removed (the lossless behavior is now the only mode).

2026.6.27

  • [Video Capture SDK .Net] VideoCaptureCoreX can now insert AI processing blocks — object detection, OCR, face recognition, license-plate recognition, object analytics, background removal, generic ONNX inference, and Whisper speech-to-text — directly into the capture pipeline through Video_Processing_AddBlock / Audio_Processing_AddBlock, with on-frame overlays and detection events.
  • [Media Player SDK .Net] MediaPlayerCoreX gains the same Video_Processing_AddBlock / Audio_Processing_AddBlock API to run AI processing (object detection, OCR, speech-to-text, and more) on played files and streams.
  • [Demos] Added a Player AI Processing demo (WPF): plays a file in MediaPlayerCoreX with a YOLO object detector or a Whisper speech-to-text block inserted through the new processing-block API.
  • [Demos] Added four MAUI AI demos (Android/iOS/Mac Catalyst/Windows) for the new X-engine processing-block API: Player Object Detection X and Player Live Subtitles X (MediaPlayerCoreX), plus Capture Object Detection X and Capture Live Subtitles X (VideoCaptureCoreX).
  • [Media Blocks SDK .Net] Fixed an AccessViolationException ("Attempted to read or write protected memory") that could crash the application when using text overlays (OverlayManagerBlock / OverlayManagerText) — most reliably reproduced by adding a text overlay right after StartAsync and then stopping. The font-enumeration path freed Pango-owned font objects it did not own, corrupting memory during a later garbage collection or pipeline shutdown.
  • [Media Blocks SDK .Net] Fixed a related intermittent fatal crash ("Attempt to execute managed code after the .NET runtime thread state has been destroyed") that could abort the process during text overlay or font enumeration when a background media thread was recycled, or at application exit. The available-fonts / monospace-detection path no longer attaches a managed callback to Pango's internal font map.

2026.6.24

  • [Media Blocks SDK .Net] Fixed a rare crash during pipeline shutdown or garbage collection in applications with many active GStreamer objects, such as multi-camera RTSP capture with sample grabbers, bridges, and file outputs.
  • [Media Blocks SDK .Net] FaceRecognitionBlock — enrolling a face from a photo that carries an EXIF orientation tag (typical of phone camera shots) now works; the image is rotated upright before detection instead of reporting "no face found".
  • [Demos] Added a Face Recognition Uno demo (Uno Platform): live camera 1:N face recognition with on-frame name/box overlay, photo enrollment, and switchable SFace / AuraFace embedding models. Android-focused.
  • [Demos] The Face Recognition demos (WPF and CLI) now let you pick the embedding model: SFace (128-D) or AuraFace (512-D, ArcFace family, Apache-2.0) — a higher-accuracy, commercially licensed 512-D embedder downloaded on demand. The CLI adds an --embedding sface|auraface switch.
  • [Demos] Face Recognition WPF demo: switching the embedding model now automatically rebuilds the gallery from the enrolled photos, so changing models no longer makes every face read as Unknown (embeddings from different models are not comparable).
  • [Demos] Face Recognition MAUI demo: added the same SFace/AuraFace embedder selection and automatic gallery rebuild, plus a video-file source with a seek bar and a real-time / max-speed playback toggle (in addition to the live camera).

2026.6.23

  • [Media Blocks SDK .Net] Unity samples now use Unity's default Enter Play Mode behavior (Domain + Scene Reload); disabling Domain Reload is no longer required. The SDK survives the Editor's Play/Stop and script-recompile domain reloads via a built-in reload guard.

2026.6.21

  • [Video Capture SDK X .Net] Added Android audio playback capture support to VideoCaptureCoreX — assign AndroidAudioPlaybackCaptureSourceSettings to Audio_Source to record the audio played by other apps (system AudioPlaybackCapture API, Android 10 / API 29+, on top of a MediaProjection token) straight to a file. Includes a new native Android "Audio Playback Capture" demo built on VideoCaptureCoreX that records another app's audio to an .m4a file. Only apps that allow playback capture (usage MEDIA/GAME/UNKNOWN and not opted out) can be captured.

2026.6.20

  • [Media Blocks SDK .Net] VideoSampleGrabberBlock now works as a terminal block: if you leave its output unconnected (e.g. you only poll GetLastFrameAsSKBitmap() or handle OnVideoFrameBuffer), the block self-terminates so frames keep flowing. Previously a grabber with an unconnected output stalled after the first frame, so every snapshot returned the same initial image.
  • [Media Blocks SDK .Net] VideoSampleGrabberBlock.GetLastFrameAsSKBitmap() and GetLastFrameAsBitmap() now return null when no frame has been captured yet, instead of throwing a NullReferenceException.
  • [Media Blocks SDK .Net] Setting VideoSampleGrabberBlock.SaveLastFrame = false now discards the cached frame, so toggling it back on later never hands back a stale frame captured during an earlier session.
  • [Media Blocks SDK .Net] KLVParser now reads MISB KLV packets larger than 127 bytes. Standard MISB ST 0601 metadata uses BER long-form lengths, and the parser previously threw on the common 1- and 2-byte long-form lengths — so real-world packets failed to parse. All BER length forms are now decoded correctly.

2026.6.19

  • [Media Blocks SDK .Net] Added Android audio playback capture — the new AndroidAudioPlaybackCaptureSourceBlock records the audio played by other apps using the system AudioPlaybackCapture API (Android 10 / API 29+) on top of a MediaProjection token, with a configurable format and usage filter (AndroidAudioPlaybackCaptureSourceSettings). Includes a new native Android "Audio Playback Capture" demo that records another app's audio to an .m4a file. Only apps that allow playback capture (usage MEDIA/GAME/UNKNOWN and not opted out) can be captured.
  • [Media Blocks SDK .Net] Speech-to-text (SpeechToTextBlock) gains a lossless file-transcription mode: set SpeechToTextSettings.BackpressureWhenBusy = true to pace a file source to the transcription engine so no audio is dropped and the pipeline position tracks the transcription frontier — ideal for transcribing a file as fast as the engine allows without losing speech. The new SpeechToTextBlock.RequestStop() lets you stop promptly mid-file, and an OnEndOfStream event fires when transcription finishes.

2026.6.18

  • [Media Blocks SDK .Net] Fixed WMV/ASF output where the video stream was written with a roughly 1000-hour timestamp offset while audio started at zero — players saw a broken duration and the video and audio never shared a timeline. WMV/ASF files now have correctly aligned, overlapping video and audio timestamps.
  • [Media Blocks SDK .Net] Fixed MP4 recordings produced from a still/image source (ImageVideoSourceBlock, live mode) ending up unreadable ("moov atom not found") — a live image source now finalizes its file correctly on stop.
  • [Media Blocks SDK .Net] VP9 WebM output now uses a real-time-capable speed/quality default: VP9EncoderSettings.CPUUsed defaults to 4 instead of 0. The previous slowest/highest-quality default could not keep up with a live source, so the recorded video track could be truncated to about a second while audio ran the full length. Set CPUUsed = 0 to restore maximum quality for offline encoding.
  • [Media Blocks SDK .Net] The rav1e AV1 encoder (RAV1EEncoderSettings) now defaults to the fastest speed preset (SpeedPreset = 10) instead of 6. rav1e is a quality-oriented, very slow software encoder; the previous default could encode well under real time (~1 fps at 720p), stalling live and short captures. Lower SpeedPreset for higher quality in offline encoding where throughput does not matter.

2026.6.14

  • [Media Blocks SDK .Net] The AI blocks — YOLOObjectDetectorBlock, OcrBlock, object analytics, ANPR, BackgroundRemovalBlock (VisioForge.DotNet.Core.AI) and SpeechToTextBlock (VisioForge.DotNet.Core.AI.Whisper) — now build and run cross-platform on Linux, macOS, iOS, and Android, including .NET MAUI, in addition to Windows.
  • [Media Blocks SDK .Net] On-device speech-to-text (SpeechToTextBlock, Whisper + Silero VAD) now runs on iOS and Android.
  • [Demos] Added three .NET MAUI sample apps: YOLO Object Detection, OCR Text Recognition, and Live Subtitles (on-device Whisper speech-to-text). The existing Live Subtitles console sample is now cross-platform (Windows, Linux, macOS).
  • [Media Blocks SDK .Net] Fixed a crash that could occur when stopping live speech-to-text with SpeechToTextBlock configured with EnableVad = false (fixed-window mode) — stopping the pipeline at end-of-stream while a transcription was in progress could terminate the process. Transcription of the in-progress window now completes cleanly during shutdown.
  • [Media Blocks SDK .Net] SpeechToTextSettings.FixedWindowSeconds is now clamped to 1–30 s and SileroVadSettings.MaxSpeechMs no longer accepts "0 = unlimited" (a non-positive value falls back to the 15 s cap), so a single transcription window — and the time a stop waits for it to finish — stays bounded.

2026.6.13

  • [Media Blocks SDK .Net] Added live speech-to-text / subtitles — the new SpeechToTextBlock (in the new VisioForge.DotNet.Core.AI.Whisper package) transcribes the audio stream in real time with Whisper (Whisper.net / GGML) on a background worker, gated by Silero VAD so silence is skipped and not mis-transcribed. Audio passes through unchanged. It raises OnSpeechRecognized, can auto-render captions onto video via SubtitleRenderer + OverlayManagerBlock, and can write .srt / .vtt side-car files. Runs fully on-device (CPU or NVIDIA CUDA); Whisper and Silero models are downloaded at runtime. Includes a new WPF Live Subtitles demo.
  • [Media Blocks SDK .Net] Added AI background removal (matting) — the new BackgroundRemovalBlock runs an ONNX segmentation model (for example MODNet) to estimate a per-pixel foreground mask and replaces the background in real time with a blur of the original, a solid color, a static image, or transparency. Includes a new WPF Background Removal demo. The background is composited on every frame, so running the model less often (frame skipping) lowers CPU/GPU load without flicker.

2026.6.11

  • [Media Blocks SDK .Net] Added Object Analytics — multi-object tracking with stable IDs, directed tripwire line crossing (In/Out counts), and polygon zone occupancy on top of ONNX object detection. Includes a turnkey ObjectAnalyticsBlock, a pure C# analytics API (ByteTracker, LineZone, PolygonZone), overlay rendering with traces and counters, a new analytics mode in the YOLO Object Detection demo, and separate Tripwire and Polygon Zone demo applications.

2026.6.8

  • [Video Capture SDK .Net] Updated the bundled FFmpeg DirectShow source and encoder filters to FFmpeg 8.1.1, with refreshed codec libraries (VP8/VP9, Opus, Vorbis, Speex, SRT) and current OpenSSL — bringing newer format support and upstream security and stability fixes to FFmpeg-based capture and output.

2026.6.7

  • [Media Blocks SDK .Net] Fixed a crash when reusing a TSAnalyzerBlock across runs: after the block is stopped, analyzing a second transport stream with the same instance in a new pipeline now works instead of failing during rebuild.
  • [Media Blocks SDK .Net] Fixed MPEG-TS output with KLV metadata aborting (no valid file produced) when a video frame arrived with an out-of-order/duplicate timestamp — the muxer now keeps the stream writable, so KLV-bearing transport streams record reliably.
  • [Core] Fixed native memory steadily growing while reading media information for many different files in sequence with MediaInfoReaderX; per-file discovery resources are now released after each read.

2026.6.6

  • [Media Player SDK .Net] New "Modern Player" MAUI demo. A from-scratch cross-platform sample (Android, iOS, macCatalyst, Windows) built on MediaPlayerCoreX with a dark glassmorphism UI, a YouTube-style seek preview (a thumbnail popup follows the scrub bar — generated in the background from the opened file), a live video + audio effects drawer (brightness/contrast/saturation/hue, gamma, blur/sharpen, grayscale, edge, deinterlace, color presets, flip/rotate, 3D-LUT; plus gain, pitch, 10-band equalizer, reverb, echo, true-bass, and karaoke), frame snapshot, playback-speed control, and volume/mute.
  • [Media Player SDK .Net] [Media Blocks SDK .Net] Fixed opening local media files by absolute file path on Android, iOS, macOS, and Linux. A path starting with / (the form returned by the native file pickers) previously failed with a URI-format error; MediaPlayerCoreX.OpenAsync(string), MediaInfoReaderX, and UniversalSourceSettings.CreateAsync(string) now open such files correctly. Windows paths were unaffected.
  • [Media Blocks SDK .Net] OCR — text recognition: new OcrBlock recognizes text in any video or image source using a multi-stage PaddleOCR (PP-OCRv5) ONNX pipeline — text detection, automatic 180° orientation handling, and text-line recognition. Runs on CPU or GPU (DirectML on Windows, CoreML on Apple, CUDA) and is fully cross-platform (Windows/Linux/macOS/Android). It raises the recognized regions per frame (text, confidence, and the text polygon) and can optionally draw the boxes and recognized text directly into the video. Works with the permissive Apache-2.0 PP-OCRv5 mobile models (100+ languages available); the models ship with the sample, not the package.
  • [Media Blocks SDK .Net] ANPR — license plate recognition: new LicensePlateRecognizerBlock reads vehicle number plates from a live stream or file using a specialized two-stage pipeline — a dedicated license-plate detector locates each plate, then a plate-specific OCR model (a global head covering the USA and 90+ countries, or a European head) reads its characters. Recognition runs on a background thread so live video never stalls; recognized plates (text, confidence, bounding box) are raised per frame and optionally drawn over the video. Cross-platform and GPU-accelerated (DirectML / CUDA / CoreML). The MIT-licensed models ship with the sample, not the package.

2026.6.4

  • [Media Blocks SDK .Net] AI inference package renamed: the AI/ONNX inference package is now published as VisioForge.DotNet.Core.AI (previously VisioForge.DotNet.Core.ONNX). Update your PackageReference to the new id — the API and namespaces of the inference blocks are unchanged.
  • [Media Blocks SDK .Net] Object detection: more models, permissive default. YOLOObjectDetectorBlock now decodes three model families via the new YoloDetectorSettings.Model property — YOLOX and RT-DETR / D-FINE (both Apache-2.0) in addition to YOLOv8/v11. Each family's frame preprocessing (resize mode, normalization, channel order) and the model's input size are applied automatically, so you only pick the family and the .onnx file. The Object Detection demo now ships a ready-to-run Apache-2.0 model (YOLOX-nano) and works out of the box without any third-party model download. RT-DETR / D-FINE detectors are end-to-end (NMS-free).
  • [Media Blocks SDK .Net] TS analyzer — ETSI TR 101 290 monitoring: TSAnalyzerBlock now reports a structured TR 101 290 Priority 1/2/3 check list (sync loss, sync-byte errors, PAT/PMT/PID errors, continuity-count errors, transport errors, CRC errors, PCR/PTS errors, and SI/SDT/EIT/TDT errors), each with its priority, error count, and pass/fail status — turning the block into a broadcast-grade transport-stream monitor.
  • [Media Blocks SDK .Net] TS analyzer — service information: the report now exposes per-program SDT service names, service provider, and service type, the network name, and the stream UTC time (TDT/TOT), so programs show up as their real service name instead of just a program number.
  • [Media Blocks SDK .Net] TS analyzer — audio language: elementary-stream entries now carry the ISO 639 audio language parsed from the PMT descriptors.
  • [Media Blocks SDK .Net] TS analyzer — scrambling detection: per-PID and per-program scrambling state is now reported (transport-scrambling-control and free_CA_mode), along with a scrambled-packet count.
  • [Media Blocks SDK .Net] TS analyzer — null and effective bitrate: the report adds the null-packet count, the null (stuffing) bitrate, and the effective (useful) bitrate, plus per-PID instantaneous and peak bitrate alongside the existing cumulative average.
  • [Media Blocks SDK .Net] TS analyzer — PCR timing and PTS/DTS: PCR statistics now include maximum jitter and PCR repetition errors, and the report tracks PTS/DTS presence per PID and audio/video synchronization offset.
  • [Media Blocks SDK .Net] TS analyzer — codec details: video elementary streams now report parsed codec details (resolution, frame rate, profile, level, chroma format, and display aspect ratio) for H.264, HEVC, and MPEG-2. Frame rate and aspect ratio are reported from the MPEG-1/2 sequence header.
  • [Media Blocks SDK .Net] TS analyzer — optional EPG: when enabled, the analyzer parses EIT events (event id, start time, duration, name, description) and exposes them as an EPG event list. The new analysis options (service info, EPG, scrambling, TR 101 290, PTS/DTS, codec details) are configurable on TSAnalyzerSettings. The WPF and console demos display all of the new information.
  • [Video Capture SDK .Net] Fixed audio capture failing to start with certain WDM capture cards (for example the Viewcast Osprey 460E) when the device was selected by its device path — the device enumerated correctly but capture aborted with an "audio output pin is null" error. Such devices now bind reliably.
  • [Media Blocks SDK .Net] Fixed a MediaBlocksPipeline becoming unusable after a media file played to its end. Once a source reached End-of-Stream, the next StartAsync() was permanently rejected with "Already starting or start in progress." and the pipeline could not be restarted without recreating it — for example when switching from a finished file back to a live camera. Playback now shuts down cleanly at end-of-stream exactly like an explicit StopAsync() (sources stopped, resources released), so the same pipeline can be started again.

2026.6.3

  • [Media Blocks SDK .Net] MPEG-TS analyzer: new TSAnalyzerBlock analyzes a transport stream and reports the program/service line-up (PAT/PMT/PSI), the per-PID stream types and codecs, per-PID and total bitrate, continuity-counter errors, and PCR timing (interval min/avg/max and discontinuity count). It accepts a raw MPEG-TS byte stream from a file, UDP, or SRT source and can run terminal (Input) or inline passthrough (InputOutput); subscribe to OnAnalysisUpdated for periodic snapshots or call GetReport(). New WPF and console demos ("TS Analyzer Demo", "TS Analyzer CLI") show file and live UDP/SRT analysis.
  • [Media Blocks SDK .Net] Raw MPEG-TS UDP source: new UDPRAWMPEGTSSourceBlock receives a live UDP unicast or multicast transport stream and exposes the untouched MPEG-TS byte stream without demuxing — for analysis or passthrough remuxing/recording. The advertised packet size is configurable via UDPRAWMPEGTSSourceSettings.PacketSize (188 by default, or 192 for M2TS-style streams).
  • [Media Blocks SDK .Net] Split-recording segment events: MP4SinkBlock, MPEGTSSinkBlock, and MP4OutputBlock now raise OnSegmentCreated and OnSegmentClosed when configured for split recording (MP4SplitSinkSettings / MPEGTSSplitSinkSettings). The arguments carry the segment file path, fragment index, and timing (running time, plus start offset and duration on close) — so you can be notified when a segment file is finished and, for example, rename it to include its start/end time.
  • [Media Blocks SDK .Net] Custom split-segment file names: the same blocks add an OnSegmentFileNameRequested event, raised just before each new segment file is created, letting you supply a custom file name (for example one that embeds the segment start date/time). Leave it unset to keep the default name from the location pattern.
  • [Media Blocks SDK .Net] New AI inference blocks: OnnxInferenceBlock runs any ONNX Runtime model over the live video frames and raises an event with the raw model outputs, while YOLOObjectDetectorBlock performs YOLOv8/v11 object detection, draws bounding boxes and labels directly on the video (label text auto-scales to the frame resolution so it stays readable on 720p/1080p/4K, or pin a fixed size via YoloDetectorSettings.LabelFontSize), and raises a detections event (with class, confidence, and box for each object). Both support frame skipping to tune throughput. On Windows the package uses the DirectML ONNX Runtime build, so inference runs on any DirectX 12 GPU (NVIDIA, AMD, or Intel) out of the box; the execution provider defaults to Auto, which picks the fastest available backend (DirectML/CUDA/CoreML) and transparently falls back to the CPU. Use OnnxInferenceEngine.GetAvailableProviders() to detect what is available and the new ActiveProvider property on either block to see which provider engaged. The VisioForge.DotNet.Core.ONNX package targets the full SDK framework matrix (.NET Framework 4.6.1 through .NET 10); inference requires a 64-bit (x64 or ARM64) ONNX Runtime native build.

2026.6.2

  • [Video Capture SDK .Net] Fixed KLV metadata progressively drifting out of sync with the video (about 2 seconds per source loop) on the receiving side when restreaming a looping KLV-bearing MPEG-TS via UDP_FFMPEG_EXE. KLV and video now stay aligned across source loop boundaries.
  • [Video Capture SDK .Net] Unity: new VideoCaptureCoreX samples — local webcam preview + MP4 recording (Windows, macOS) and IP/RTSP camera viewing (Windows, Android, macOS, iOS).
  • [Video Edit SDK .Net] Unity: new VideoEditCoreX sample — combine clips, apply effects, preview the timeline in Unity, and render to MP4.

2026.5.31

  • [Media Blocks SDK .Net] New UDPRAWSourceBlock: receives a live UDP stream (MPEG-TS, RTP, or raw elementary) and exposes the parsed, still-encoded media without decoding — ideal for recording or remuxing without re-encoding. MPEG-TS feeds are auto-detected; RTP and raw modes let you set the codec, RTP payload type, and a multicast address. It exposes all common video and audio codecs (video: H264, H265, VP8, VP9, AV1, MPEG-2, MJPEG; audio: AAC, MP3/MPEG audio, AC-3, Opus, FLAC); RTP can also carry audio on a separate port (AudioPort / AudioCodec). A codec without a dedicated parser is passed through unchanged rather than dropped, so a connected recorder/muxer is never starved.
  • [Demos] New WPF "UDP RAW Capture Demo" (Media Blocks SDK .Net): records a live UDP H264/H265 feed to MP4 files without re-encoding, with selectable transport (Auto / MPEG-TS / RTP / raw), starting a new file on a configurable interval and splitting on key-frames so no data is lost between files, while previewing the stream.
  • [Media Player SDK .Net] Unity: new MediaPlayerCoreX sample — play files and network URLs with seek, pause and volume, rendered into a Unity Texture2D.

2026.5.29

  • [Media Blocks SDK .Net] Unity 6 (.NET Standard 2.1) build flavor: the managed SDK now ships as a single netstandard2.1 assembly compatible with Unity's IL2CPP backend (Api Compatibility Level = .NET Standard 2.1). This lets Unity projects target the SDK without requiring the .NET Framework 4.x compatibility surface. The existing net48 Unity package remains supported.
  • [Media Blocks SDK .Net] Unity macOS Standalone player support (Universal arm64 + x86_64): the Unity 6 ns2.1 .unitypackage now ships a third platform flavor for macOS Standalone (in addition to Windows and Android). Includes pre-built P/Invoke for macOS .dylib names, the bundled CrossPlatform.Core.macOS native runtime (GStreamer dylibs + libgioopenssl TLS backend + ca-certificates.crt), and a one-time Configure() bootstrap that prunes any system / homebrew GStreamer from DYLD_LIBRARY_PATH before the loader runs.
  • [Core] New API: VisioForgeX.StopMainLoop() — explicit teardown of the internal GLib main loop independent of DestroySDK(), for scenarios that need to release the loop without tearing the SDK down.

2026.5.22

  • [Demos] Unity .unitypackage distribution: the Unity 6 (net48) integration now ships as a single self-contained .unitypackage
  • [Demos] New Unity 6 (net48) samples: SimplePlayer (file playback) and RTSPViewer (live RTSP camera) render a MediaBlocksPipeline into a Unity RawImage via a reusable VisioForgeVideoView component (Stretch / Letterbox / Crop). The bundled native + managed runtime is set up automatically; a step-by-step setup guide is included.

2026.5.20

  • [Media Blocks SDK .Net] Fix: native memory leak in OverlayManagerFilter and PanZoomFilter on iOS/AOT builds.

2026.5.19

  • [Media Blocks SDK .Net] Fix: CVMotionCellsBlock, CVFaceDetectBlock, CVHandDetectBlock, CVTemplateMatchBlock — event subscriptions added after StartAsync sometimes were silently dropped.
  • [Media Blocks SDK .Net] Fix: CVMotionCellsSettings.Gap and PostNoMotion are now rounded and clamped to the ranges accepted by the underlying motioncells element (Gap[1, 60] s, PostNoMotion[0, 180] s). Previously sub-second values truncated to 0 and were silently rejected.
  • [Media Blocks SDK .Net] Docs: CVMotionCellsSettings.GridSize XML-doc clarified that the minimum is 8x8 (constraint of the underlying motioncells element); smaller values are silently rejected.

2026.5.18

  • [Media Blocks SDK .Net] New API: SRTSinkSettings.PreResolveHostname and SRTSourceSettings.PreResolveHostname (bool, default false). When set to true, the SDK resolves any DNS hostname in the SRT URI to a literal IPv4 on the managed side (via System.Net.Dns) before handing the URI to the native code.

2026.5.16

  • [Core] Public-API XML documentation is now validated for correct syntax across the shipped NuGet packages.

2026.5.15

  • [Core] Added D3D11Composable WPF renderer mode: a pure FrameworkElement video panel built on a D3D11 shared texture + D3DImage bridge that composes natively with the WPF visual tree (transforms, opacity, z-order, rounded clips) and keeps frames GPU-resident end-to-end. New type: D3D11ComposablePanel.
  • [Core] Added true-peak (dBTP) metering per ITU-R BS.1770-4: new TruePeakComputer (4× polyphase FIR oversampling, per-channel running peak, NaN/Inf-safe) and VUMeterXData.TruePeak[] channel array fired alongside the existing sample-peak/RMS data.
  • [Core] Added VolumeMeterLED WPF control: segmented LED-bar VU meter with broadcast-style green/yellow/red zones, optional peak-hold marker (configurable fall time), optional dB scale labels, optional RMS overlay bar, horizontal/vertical orientation.
  • [Core] NuGet packages now ship XML documentation generated from real summaries for the full public API surface (previously the doc files were empty).

2026.5.14

  • [Avalonia] Updated Avalonia, Avalonia.Desktop, Avalonia.Fonts.Inter, Avalonia.Themes.Fluent from 12.0.1 to 12.0.3.
  • [WinForms] Resolve issue with WinForms designer when using VideoView in .Net Framework 4.x projects
  • [Dependencies] Closed two transitive security advisories: pinned System.Drawing.Common per-TFM on bare/cross-platform netN.0 (was 5.0.1 via DlibDotNet — GHSA-rxg9-xrhp-64gj, critical) and added explicit SharpCompress 0.48.1 CPM pin to lift the transitive floor from MongoDB.Driver (was 0.30.1 — GHSA-6c8g-7p36-r338, moderate); bumped MongoDB.Driver 3.8.0 → 3.8.1.
  • [Breaking] VisioForge.Core.CVD and VisioForge.Core.FaceAI assemblies are no longer strong-named. The underlying DlibDotNet dependency is unsigned, so the strong-name chain was already broken at runtime; the <SignAssembly> flag was dropped to silence CS8002. Consumers that referenced these assemblies by fully-qualified strong name (PublicKeyToken=...) or used [InternalsVisibleTo("VisioForge.Core.CVD, PublicKey=...")] must remove the strong-name assertion when upgrading.

2026.5.10

  • [Core] CustomMixerSourceBlock: reliability and throughput improvements under heavy load.

2026.5.8

  • [Dependencies] Upgraded MongoDB.Driver.GridFS 2.30.0 to MongoDB.Driver 3.8.0; pinned Snappier 1.3.1 to resolve NU1903 high-severity vulnerability (GHSA-pggp-6c3x-2xmx)

2026.5.2

  • [Core] Breaking change: licensing APIs now accept only raw certificate bytes. Removed file-path and stream-based certificate setters across shared licensing, public SDK wrappers, legacy Windows wrappers, tests, and licensing docs. Applications must load .vflicense files into memory and call SetLicenseCertificateAsync(byte[]).
  • [Core] AudioMixerBlock: AudioMixerSettings.IgnoreInactivePads is now opt-in (default false). The 2026.4.30 release briefly forced it true, which broke single-input mixers — silent live audio and corrupted MP4 output. Multi-stream consumers (MediaPlayerCoreX additional audio streams, LiveVideoCompositor, and AudioMixerSourceSettings-based multi-source capture) now opt in explicitly. If you wired a multi-stream AudioMixerBlock on 2026.4.30–2026.5.1 and relied on the implicit true, set AudioMixerSettings.IgnoreInactivePads = true explicitly.

2026.4.25

  • [Core] Fixed WinForms designer exception on VideoView in net472 demos — SkiaSharp 3 migration regression
  • [Core] Added transitive SkiaSharp.NativeAssets.Linux dependency for bare cross-platform TFMs (netcoreapp3.1, net5.0net10.0) so consumers publishing to linux-x64/arm64 no longer need to add the package manually; main SkiaSharp already covers Win32/macOS/iOS/Android/MacCatalyst/tvOS via per-TFM nuspec groups
  • [Avalonia] Migrated SDK and all 28 demos from Avalonia 11.3.8 to 12.0.1: replaced Avalonia.Diagnostics with AvaloniaUI.DiagnosticsSupport 2.2.1, switched to ReactiveUI.Avalonia 12.0.1, updated RxApp.MainThreadSchedulerRxSchedulers.MainThreadScheduler (ReactiveUI 23.x), new UseReactiveUI(_ => { }) signature, moved Android CustomizeAppBuilder from MainActivity to new MainApplication : AvaloniaAndroidApplication<App>, migrated SaveFileDialog/OpenFileDialog/FileDialogFilter to IStorageProvider.SaveFilePickerAsync/OpenFilePickerAsync in 4 demos. SkiaSharp pinned to 3.119.3-preview.1.1 (required by Avalonia.Skia 12).

2026.4.23

  • [NuGet] Extracted Intel Quick Sync Video (QSV) plugin (gstqsv.dll) from VisioForge.CrossPlatform.Core.Windows.x64/x86 into new optional packages VisioForge.CrossPlatform.Core.Windows.Intel.x64 and VisioForge.CrossPlatform.Core.Windows.Intel.x86; each depends on the corresponding base Core package
  • [Video Capture SDK .Net] Fixed FFMPEG.exe pipe output argument ordering so resize/aspect options are emitted after all inputs, including KLV metadata pipe input

2026.4.21

  • [Core] Added AutoAV1EncoderSettings: auto-selecting AV1 encoder that walks AMF → NVENC → QSV → SVT-AV1 via EncoderRuntimeTracker, mirroring AutoH264EncoderSettings / AutoHEVCEncoderSettings; AV1 sessions now participate in per-runtime slot accounting
  • [Core] Added typed AV1Encoder.CanCreateSession(IAV1EncoderSettings, out string) probe so AV1 runtime selection can detect driver rejections before wiring a pipeline
  • [Core] Added MFH264EncoderSettings, D3D12H264EncoderSettings, D3D12HEVCEncoderSettings — alternative Windows runtimes (mfh264enc, d3d12h264enc, d3d12h265enc) with independent per-adapter session counters for bypassing per-runtime caps (e.g., AMD iGPU 2-session ceiling)
  • [Core] Added AutoH264EncoderSettings / AutoHEVCEncoderSettings: auto-selecting encoder that probes runtimes in order (AMF → NVENC → QSV → MF → D3D12 → software), tracks in-flight sessions via EncoderRuntimeTracker, and falls back when a runtime's cap is reached
  • [Demo] Added Encoder Concurrency Test WPF demo (Media Blocks SDK): spawn multiple source→encoder→decoder→renderer pipelines with configurable resolution, frame rate, encoder runtime, and adapter to exercise concurrent-session limits end-to-end

2026.4.18

  • [Media Blocks SDK] UniversalSourceBlock: added VideoFlipRotate option for automatic video orientation correction using image-orientation metadata
  • [Core] VOAACEncoderSettings deprecated in favor of AVENCAACEncoderSettings
  • [Core] RTSPXOutput: now accepts any IAACEncoderSettings, not just VOAAC
  • [Core] MediaInfoReaderCore: preserves image-orientation flip metadata during media info reading
  • [Core] H264Encoder: fixed thread-safety issue in KeyFrameDetected callback
  • [iOS] PhotoGalleryHelper: requests PHAccessLevel.AddOnly for iOS 26 compatibility
  • [Android] GStreamer Android NuGet rebuilt with zbar barcode plugin, bumped to 2026.4.18
  • [Platform] macOS demos migrated from net9.0-macos to net10.0-macos
  • [Dependencies] Uno.Sdk bumped 6.4.24 → 6.5.31
  • [Media Blocks SDK] LiveVideoCompositor V2: added OnRenderStatistics event with ActualFps, ConfiguredFps, FramesDelivered, and LastFrameTimestamp payload for detecting when the compositor falls behind the configured frame rate under heavy load
  • [Media Blocks SDK] LiveVideoCompositor V1 (VisioForge.Core.LiveVideoCompositor) marked [Obsolete] — migrate to VisioForge.Core.LiveVideoCompositorV2 (identical class names, single-line using swap); V1 will be removed in a future release
  • [Demos] WPF LVC Demo and MAUI LVC Demo show the real vs configured output FPS in the UI; WinForms Video Mixer Player migrated from V1 to V2

2026.4.11

  • [Media Player SDK X] Added Play_PauseAtFirstFrame property to MediaPlayerCoreX — pauses at the first rendered frame for preview/thumbnail scenarios, matching the existing MediaPlayerCore API
  • [Core] Migrated SkiaSharp from 2.88.9 to 3.119.2 — updated text rendering to SKFont API, replaced SKFilterQuality with SKSamplingOptions, switched SVG library from SkiaSharp.Svg to Svg.Skia
  • [UI] Updated SkiaSharp.Views.WPF and SkiaSharp.Views.Maui.Controls to 3.119.2; WPF skins now use DrawImage with high-quality Mitchell resampling

2026.4.8

  • [Android] Added live camera switching (SwitchCamera) to SystemVideoSourceBlock — switches between front/back cameras without recreating the GStreamer pipeline, preserving resolution and frame rate
  • [Video Capture SDK X] Added Video_Source_SwitchCamera for live camera switching on Android without pipeline restart
  • [Video Capture SDK X] Added Video_Renderer_IsSync and Audio_Renderer_IsSync properties (default false) for lower-latency live preview
  • [Android] New NuGet native version v2026.4.1

2026.3.27

  • [Core] Fixed UNC path media info reading failure: MediaInfoReaderAlt now correctly handles SDK initialization guard, null caps in OnPadAdded, and falls through to MediaInfoReaderX on failure. IsSambaURL() extended to detect file://host/path UNC URIs. OpenAsync uses uri.LocalPath for correct Windows UNC path.

2026.3.18

  • [Media Blocks SDK .Net] Fixed missed context menu issue in WPF VideoView

2026.3.17

  • [Media Blocks SDK .Net] Added UDPSinkBlock and MultiUDPSinkBlock for raw UDP streaming output with single and multi-destination support
  • [Media Blocks SDK .Net] Added UDPMPEGTSSinkBlock and MultiUDPMPEGTSSinkBlock for MPEG-TS multiplexed UDP streaming with single and multi-destination support
  • [Media Blocks SDK .Net] Added UDPSinkSettings, MultiUDPSinkSettings, and UDPSinkSettingsBase for UDP sink configuration with IPv6 support and URL parsing
  • [Media Blocks SDK .Net] Added UDP MPEG-TS streamer demo (screen capture to UDP output)

2026.3.11

  • [Core] Device enumeration: Blackmagic ATEM and Web Presenter devices now appear in regular video/audio device lists instead of being filtered as Decklink hardware. These devices use standard USB/UVC drivers, not the Decklink SDK. Applies to both DirectShow and GStreamer enumeration paths.
  • [Core] RTSP info reader: Added audio channel count and sample rate parsing from SDP rtpmap and GStreamer pad caps.

2026.2.16

  • [Media Blocks SDK .Net] Added PreEventRecordingBlock for circular buffer (pre-event) video recording with configurable buffer duration, keyframe-aware drain, and automatic post-event stop
  • [Video Capture SDK .Net] VideoCaptureCoreX: Added pre-event recording API with TriggerPreEventRecording, ExtendPreEventRecording, StopPreEventRecording, and state query methods
  • [Video Capture SDK .Net] VideoCaptureCoreX: Added PreEventRecordingOutput for configuring circular buffer recording with MP4, MPEG-TS, and MKV container support

2026.2.12

  • [Media Blocks SDK .Net] Added OnNetworkSourceDisconnect event for detecting network source disconnections (RTSP, HTTP, SRT, NDI, RTMP, etc.) with detailed error information and source URI

2026.2.11

  • [Media Player SDK .Net], [Media Blocks SDK .Net] Fixed audio effects pipeline routing

2026.2.10

  • [Core] Added UNC (SMB/Samba) network path support for file sources across all X-engines, fixing File.Exists() failures on network shares
  • [Media Blocks SDK .Net], [Video Capture SDK .Net] Added mouse click highlight support for screen capture with auto-subscribe/unsubscribe, manual click input, and real-time settings update

2026.2.8

  • [Media Blocks SDK .Net] Added OverlayManagerImageSequence: image sequence overlay with per-frame durations, looping, position/size animation, fade effects, and easing support
  • [Media Blocks SDK .Net] Added ImageSequenceItem data class for defining image sequence frames
  • [Media Blocks SDK .Net] OverlayManagerBlock: Added convenience methods for image sequence overlays (Video_Overlay_AddImageSequence, UpdateImageSequencePosition, AnimateImageSequence, ImageSequenceFadeIn/Out)
  • [Core] Extracted OverlayManagerEasingHelper: shared easing functions for all overlay animation types (Image, Fade, Pan, Squeezeback, ImageSequence)

2026.2.4

  • [Media Blocks SDK .Net] Added H264PushSourceBlock for pushing raw H.264 encoded data into a decoding pipeline, with automatic AVC-to-byte-stream conversion and PTS rebasing
  • [Core] Added RtspDescribeClient: lightweight cross-platform RTSP DESCRIBE client for fast stream discovery (~100-200ms), with SDP parsing and Basic/Digest auth support
  • [Core] RTSPSourceSettings: Added fast RTSP discovery path using RtspDescribeClient
  • [Core] RTSPRAWSourceSettings: Added fast RTSP discovery path using RtspDescribeClient
  • [Core] UniversalSourceSettings: Added fast RTSP discovery path for rtsp:// and rtsps:// URIs

2026.2.2

  • [Core] VideoCaptureDeviceInfo: Extended Windows device path population to support Media Foundation (MF) devices in addition to KS
  • [Core] VideoCaptureDeviceInfo: Fixed pre-existing bug where V4L2 device path validation checked wrong variable
  • [Core] VideoCaptureDeviceSourceSettings: Added FindByDevicePath() static methods for restoring saved camera profiles by device path
  • [Core] DeviceEnumerator: Added FindVideoSourceByDevicePathAsync() method for looking up devices by path
  • [Media Blocks SDK .Net] Added RIST (Reliable Internet Stream Transport) MPEG-TS sink output support
  • [Media Blocks SDK .Net] Added WebRTC WHIP (WebRTC-HTTP Ingestion Protocol) output support
  • [Video Capture SDK .Net] Added WebRTC WHIP streaming output
  • [Video Capture SDK .Net] Added RIST streaming output

2026.1.16

  • [Media Blocks SDK .Net] BridgeVideoSourceSettings: Added DoTimestamp property to enable fresh timestamp generation for cross-pipeline scenarios

2026.1.15

  • [Media Blocks SDK .Net] DecklinkVideoSinkSettings: Made Mode parameter required in constructor to prevent frame rate mismatch issues (was defaulting to Unknown mode causing unexpected 23.98fps output)
  • [Media Blocks SDK .Net] DecklinkVideoSinkSettings: Made DeviceNumber and Mode properties read-only for immutability
  • [Core] DecklinkVideoOutputDialog (WPF): Added Video Mode selector for configuring output frame rate

2026.1.12

  • [Core] WPF VideoView: Fixed crash (System.ExecutionEngineException) when minimizing window during video overlay playback

2026.1.11

  • [Media Blocks SDK .Net] RTSPSourceBlock: Fixed video freeze when audio capture is disabled for cameras with multiple audio streams
  • [Media Blocks SDK .Net] RTSPRAWSourceBlock: Added fakesink handling for disabled audio streams to prevent pipeline stalls
  • [Core] MediaInfoReaderCore: Added logging for discovered audio, video, and RTP streams
  • [Core] MediaInfoReaderCore: Fixed excessive block size (5MB) being set for RTSP sources, improving discovery speed

2026.1.10

  • [Video Capture SDK .Net] DSFFMPEGEXEPipeOutput: Fixed preview lag during video capture with optimized pipe handling and queue processing
  • [Video Capture SDK .Net] FFMPEG EXE output: Added real-time encoding optimizations for VP8/VP9, fixed MJPEG quality mode, improved default H264MFSettings defaults

2026.1.6

  • [Video Capture SDK .Net] VideoCaptureCoreX: Fixed video capture resolution issue when ResizeVideoEffect is applied

2025.12.12

  • [Media Blocks SDK .Net] Added PitchBlock for audio pitch shifting with semitone control (-12 to +12 range)
  • [Media Player SDK X .Net] CDGSource: Added pitch shifting support with EnablePitchShifting option and real-time PitchSemitones control
  • [Media Player SDK X .Net / Media Blocks SDK .Net] CDGSourceSettings: Added ZIP archive support for karaoke files (MP3+CDG pairs inside ZIP)

2025.11.8

  • [Media Blocks SDK .Net] OverlayManagerVideo and OverlayManagerDecklinkVideo: Changed AudioOutput property type from MediaBlock to AudioOutputDeviceInfo for direct audio device selection. Audio is now handled internally via AudioRenderer with automatic channel conversion support.

2025.11.4

  • .Net 10 support for all SDKs

2025.11.3

  • WPF VideoView update: Added RotationAngle, RotateCrop, and RotationStretch properties to support rotated video rendering

2025.11.1

  • [Media Blocks SDK .Net] Add synchronized overlay group support for OverlayManagerBlock

2025.10.10

  • [Windows SDKs] Updated VideoEffectRotate with no-crop option

2025.10.6

🚀 Major Feature: Ultra-Low Latency RTSP Streaming

  • [Media Blocks SDK .Net] Revolutionary low latency mode for RTSP sources achieving 60-120ms total latency (10-14x improvement over default 1-2 seconds)
  • Added RTSPSourceSettings.LowLatencyMode property for one-line enablement of optimized streaming
  • Automatic pipeline optimization: RTSP source (80ms), queue buffers (10-20ms), and renderer sync control
  • GStreamer integration: latency=80ms, buffer-mode=0, queue max-size-buffers=2 with leaky=downstream
  • Perfect for real-time surveillance, security systems, live monitoring, and interactive video applications

  • [Media Blocks SDK .Net] Enhanced RTSPSourceBlock with comprehensive low latency configuration

  • Added RTSPBufferMode enum with 5 modes (None, Auto, Slave, Buffer, Synced) for fine-grained jitter buffer control
  • Added RTSPNTPTimeSource enum (NTP, RunningTime, Clock) for NTP timestamp synchronization in multi-camera scenarios
  • New properties: LowLatencyMode, BufferMode, DropOnLatency, NTPSync, NTPTimeSource
  • Optimized QueueElement with automatic low latency configuration (2 frame max, leaky downstream mode)

  • [Video Capture SDK X .Net] Full low latency mode support for RTSP sources

  • Compatible with VideoCaptureCoreX engine across all platforms
  • Same simple API: RTSPSourceSettings.LowLatencyMode = true
  • Works seamlessly with IP Capture demo and RTSP MultiView demo

  • [Cross-Platform Support] Low latency RTSP streaming now available on all platforms:

  • Windows (WPF, WinForms, Console, Blazor)
  • macOS (MAUI, Console)
  • Linux (Console, WPF with Mono)
  • Android (MAUI, Native)
  • iOS (MAUI)

  • [Demo Applications] Updated 6 demos with low latency mode UI controls:

  • Media Blocks SDK: RTSP Preview Demo (WPF), RTSP MultiView Demo (WinForms), MAUI RTSPViewer, Android RTSP Client
  • Video Capture SDK X: IP Capture (WPF), RTSP MultiView Demo (WinForms)
  • All demos include easy-to-use checkboxes or default-enabled low latency for optimal user experience

  • [Documentation] Official help documentation updated with a low-latency section and best practices.

  • [Testing] Validated on real IP cameras across all platforms. Performance benchmarks: Windows (85ms), macOS (95ms), Linux (80ms), Android (110ms), iOS (100ms).

  • [Backward Compatibility] 100% backward compatible implementation:

  • Default behavior unchanged - existing code works without modification
  • Low latency mode is opt-in via explicit property
  • No performance impact when not using low latency mode
  • Queue optimization only applied when LowLatencyMode=true

2025.10.3

  • [Media Blocks SDK .Net] Added DASH (Dynamic Adaptive Streaming over HTTP) sink support with DASHSinkBlock and DASHOutput classes
  • [Media Blocks SDK .Net] Added UniversalSourceBlockV2 with improved memory usage and performance
  • [X-engines] Fixed uvch264src not starting on Linux by properly selecting the appropriate source pad based on video format (vidsrc for H264, vfsrc for raw/MJPEG)

2025.9.5

  • [Video Fingerprinting SDK] Improved support for flipped videos

2025.9.3

  • [Media Blocks SDK .Net] Added DataMatrix barcode support using DataMatrixDecoderBlock block

2025.9.1

  • [Video Fingerprinting SDK] Improved support for flipped videos

2025.8.9

  • [Video Capture SDK .Net] VideoCaptureCoreX: Resolved issue with Snapshot_GetSK call on Android (wrong colorspace)

2025.8.6

  • [X-engines] Updated RTSP RAW source block. Added WaitForKeyframe and SyncAudioWithKeyframe properties. Block can wait for keyframes because some cameras may not send them as first frames.

2025.8.4

  • [X-engines] Added NDI source support in Live Video Compositor

2025.8.2

  • [ALL] New ONVIF manager code in VisioForge.Core.ONVIFX. Full implementation of various ONVIF services including Device Management, Media v1/v2, PTZ, Events, Imaging, Analytics, Recording, and Replay services.

2025.8.1

  • [Media Player SDK] Added PauseOnStop property to MediaPlayerCoreX

2025.6.30

  • [X-engines] Added animated GIF support to ImageVideoSourceBlock/ImageVideoSourceSettings classes
  • [X-engines] Resolved issues with delayed file start in Live Video Compositor
  • [X-engines] Update video mixer API to use GUIDs instead of integer indexes for video sources

2025.6.27

  • [Video Capture SDK] Resolved issue with RTSP Low Latency engine with some cameras

2025.6.5

  • [X-engines] Resolved issue with NDI sources playback without audio streams

2025.6.3

  • [X-engines] Updated GenICam source support for USB Vision cameras. Added GenTL source support.

2025.6.2

  • [X-engines] Added deinterlace support for interlaced Decklink video sources

2025.6.1

  • [Live Video Compositor] Resolved issue with file sources paused on start, and resumed with error

2025.5.1

  • [ALL] Update NuGet dependency packages to the latest versions
  • [X-engines] Resolved issue with RTMP network streaming to a custom server

2025.4.8

  • [ALL] Added Absolute Move API to the ONVIFDeviceX class. You can use this API to move the ONVIF camera to the specified absolute position.

2025.2.24

  • [X-engine] By default, Media Foundation device enumeration is disabled. You can enable it using the DeviceEnumerator.Shared.IsEnumerateMediaFoundationDevices property.

2025.2.18

  • [Media Player SDK.Net] Added loop support for the cross-platform engine.
  • [ALL] Updated RTSP-X engine output, fixed crash issue with RTSP output and VLC player frequent reconnects
  • [X-engines] Changed face detector support to use IFaceDetector interface
  • [Live Video Compositor] Fixed registration issues with custom video view attached to video input

2025.2.9

  • [X-engines] Updated NDI connection speed

2025.2.4

  • [X-engines] RTSP Server Media Block and RTSPServerOutput added to Video Capture SDK. You can use the RTSPServerBlock to create an RTSP server and stream video and audio to it.

2025.2.1

  • [X-engines] Added NVENC and AMF AV1 encoders support

2025.1.25

  • [Windows] Resolved HTTPS issue with the not loaded SSL certificates

2025.1.22

  • [Windows] Resolved issue with missed ONVIF sources while enumerating on PC with multiple network interfaces
  • [Media Blocks SDK .Net] Added the OnEOS event to MediaBlockPad class. You can use this event to get the EOS (End of Stream) event from the media block. It can be useful if you have several file sources with a different duration and you need to stop the pipeline when the first source ends.
  • [Media Blocks SDK .Net] Added the SendEOS method to MediaBlocksPipeline class. You can use this method to send the EOS (End of Stream) event to the pipeline.

2025.1.18

  • [NuGet] VisioForge.Core.UI.Apple, VisioForge.Core.UI.Android, and VisioForge.Core.UI.WinUI packages are merged into the VisioForge.DotNet.Core package. All namespaces are the same.
  • [Media Blocks SDK .Net] Added the ZOrder property to LVCVideoInput and LVCVideoAudioInput classes. You can use this property to set the Z-order for the video input.

2025.1.14

  • [NuGet] VisioForge.Core.UI.WPF and VisioForge.Core.UI.WinForms packages are merged into the VisioForge.DotNet.Core package. In WPF projects you have to update the XAML code if the assembly names are used. All namespaces are the same.

2025.1.11

  • [Video Capture SDK .Net] Resolved QSV H264 FFMPEG encoder issue with the wrong symbols in parameters

2025.1.7

  • [Cross-platform] Added libcamera source support for Linux/Raspberry Pi.

2025.1.5

  • [Cross-platform] Improved previous frame playback in Media Player SDK .Net (Cross-platform engine)

2025.1.4

  • [Cross-platform] Resolved issue with AMD AMF plugin initialization

2025.1.1

  • [Cross-platform] Resolved memory leak in OverlayManagerImage

2025.1.0

  • [Cross-platform] Updated Live Video Compositor engine. Improved Decklink support for input and output. Improved performance. The new engine classes are located in the VisioForge.Core.LiveVideoCompositorV2 namespace.

2025.0.29

  • [Cross-platform] Default video renderer on Windows has been changed to DirectX 11

2025.0.17

  • [Media Blocks SDK .Net] Added libCamera source support (can be used on Raspberry Pi)

2025.0.16

  • [Media Blocks SDK .Net] Resolved issue with adding several AudioRendererBlocks to the pipeline

2025.0.14

  • [Media Blocks SDK .Net] Added the "PushJPEGSourceSettings" class to configure the JPEG source for the "PushSourceBlock". You can use this class to set the JPEG source settings for the "PushSourceBlock". Also "video-from-images" sample added.

2025.0.7

  • [ALL] Resolved window capture issues in cross-platform SDKs
  • [Media Blocks SDK .Net] Added the Bridge Source Switch sample

2025.0.5

  • [iOS] Resolved issues with playback speed for some video files
  • [iOS] Added iOS Simulator support for all SDKs. Camera source is not supported in the simulator.

2025.0.3

  • [MacOS] Resolved wrong stride issue for vertical camera videos on MacOS
  • [Video Capture SDK .Net] Resolved background color issue for the scrolling text overlay

2025.0

  • [ALL] .Net 9 support
  • [Media Blocks SDK .Net] Added AVIOutputBlock to save video and audio streams to the AVI file format
  • [Media Blocks SDK .Net] TeeBlock constructor now accepts the media type as a parameter
  • [Video Capture SDK .Net] Added Video_CaptureDevice_SetDefault and Audio_CaptureDevice_SetDefault methods to the VideoCaptureCore class. You can use this method to set the default video and audio capture devices
  • [Cross-platform] Improved Metal video rendering performance on Apple devices
  • [All] Improved performance of common video processing operations in Windows classic SDKs
  • [CV] Added DNN face detectors for the Media Blocks SDK .Net and Video Capture SDK .Net
  • [Mobile] Improved AOT compatibility for iOS and Android
  • [WinUI] Improved performance of the WinUI video rendering
  • [Media Blocks SDK .Net] Added the GetLastFrameAsSKBitmap and GetLastFrameAsBitmap methods to VideoSampleGrabberBlock to get the last frame as a SkiaSharp.SKBitmap or System.Drawing.Bitmap
  • [Video Capture SDK .Net] VideoCaptureCore: Added the AddFakeAudioSource property to FFMPEGEXEOutput. The Network_Streaming_Audio_Enabled property of VideoCaptureCore should be set to false to use this fake audio.
  • [ALL] Improved WinUI (and MAUI on Windows) VideoView performance
  • [Video Capture SDK .Net] VideoCaptureCore: Added the PIP_Video_CaptureDevice_CameraControl_ API to control the camera settings for the Picture-in-Picture mode
  • [X-engines] Added the headers support for the HTTP sources created using the HTTPSourceSettings class
  • [X-engines] Updated Avalonia samples, with projects for macOS, Linux, and Windows
  • [X-engines] Added NuGet redist packages for macOS and MacCatalyst (including MAUI)
  • [Video Capture SDK .Net] VideoCaptureCore: Added device path support for PIP_Video_CaptureDevice_CameraControl API
  • [Video Capture SDK .Net] VideoCaptureCore: Added the FFMPEG_MaxLoadTimeout property for IP camera sources. It allows you to set the maximum time to wait for the FFMPEG source to load the stream
  • [X-engines] Updated Linux support for ALSA, PulseAudio and PipeWire audio devices
  • [X-engines] Updated Linux support for V4L2 devices
  • [X-engines] Avalonia samples has be changed to a modern 1-project structure
  • [X-engines] Resolved issue with MAUI crashes on Windows after SkiaSharp update
  • [X-engines] Resolved issue with TextureView crashes on Android in MAUI applications
  • [X-engines] Resolved playback issue for http sources using the UniversalSourceBlock
  • [X-engines] Added Mobile Streamer sample for Android
  • [X-engines] Added OverlayManagerBlock support for Android (now it's available for all platforms)
  • [Video Capture SDK .Net] VideoCaptureCoreX: Added CustomVideoProcessor/CustomAudioProcessor properties for all output formats. You can use these properties to set custom video/audio processing blocks for the output format.
  • [Media Blocks SDK .Net] Added the KeyFrameDetectorBlock to detect key frames in video streams (H264, H265, VP8, VP9, AV1, etc.)
  • [Media Blocks SDK .Net] Fixed licensing issue for the LiveVideoCompositor class

15.10.0

  • [Windows] Updated window capture API to capture only the specified parent window by default. Added the UpdateHotkey method to the WindowCaptureForm class to update the hotkey for the window capture form.
  • [X-engines] Better AOT compatibility for default MAUI settings in iOS.
  • [Media Blocks SDK .Net] Added the DNNFaceDetectorBlock to detect faces and blur/pixelate them using OpenCV and DNN models.
  • [Media Blocks SDK .Net] Added the MKVOutputBlock to save video and audio streams to the MKV file format.
  • [X-engines] Better support for video source size dynamic changing in MAUI applications.
  • [X-engines] Resolved an issue with two or more VU meters in the same pipeline.
  • [X-engines] Resolved volume/mute error issue with audio mixer in Live Video Compositor engine.
  • [X-engines] The Spinnaker source for FLIR/Teledyne cameras is included in the main package and no longer requires an additional plugin.
  • [Video Capture SDK .Net] Resolved the issue with the SeparateCapture API if no VideoView was used.
  • [X-engines] The MediaBlocksPipeline constructor no longer has the live parameter. For more customizable pipelines, video and audio renderers got the IsSync property (true by default).
  • [X-engines] Resolved VideoViewTX crash in MAUI Android applications.
  • [X-engines] IVideoEncoder interface added to the MPEG2VideoEncoder class. It allows the use of MPEG2VideoEncoder with MPEGTSOutput, AVIOutput, and other output classes.
  • [X-engines] Resolved the issue with window capture using the ScreenCaptureD3D11SourceSettings class. If the rectangle was incorrect or not specified, it caused an error.
  • [X-engines] Metal renderer was added to SDK for Apple devices and used by default for iOS and MAUI.
  • [Media Blocks SDK .Net] Added the MAUI Screen Capture sample.
  • [Video Capture SDK .Net] VideoCaptureCore: Added the VLC_CustomDefaultFrameRate property to IPCameraSourceSettings to set a custom frame rate for the VLC IP camera source if the source does not provide the correct frame rate.
  • [Media Blocks SDK .Net] RTSPSourceBlock: If the RTSP source has audio but you've disabled the audio stream in RTSPSourceSettings, SDK will add a null renderer automatically to prevent warnings.
  • [ALL] Resolved issue with VideoFrameX.ToBitmap() call (wrong color space)
  • [Windows] Updated KLV support in MPEG-TS output
  • [Windows] Resolved MediaPlayerCore serialization issue
  • [ALL] Video renderer settings class no longer contains background color. Use the VideoView background color property instead.
  • [X-engines] Updated GStreamer libraries
  • [X-engines] Resolved video rendering issues on Android and iOS
  • [X-engines] iOS crash fixed during VideoViewGL usage
  • [X-engines] Added default AAC encoder for iOS
  • [X-engines] iOS camera source update for high frame rate support
  • [Windows] Updated VLC source - improved file loading speed
  • [Media Blocks SDK .Net]: Added the UniversalDemuxBlock allows to demux video and audio streams from a file in MP4, MKV, AVI, MOV, TS, VOB, FLV, OGG, and WebM formats
  • [Windows] Resolved FFMPEG stability issues
  • [X-engines] Resolved issue with loopback audio source using VideoCaptureCoreX and audio capture to file
  • [X-engines] Added SRT source and sink support in Media Blocks SDK .Net and Video Capture SDK .Net
  • [Video Capture SDK .Net] VideoCaptureCore: The IP_Camera_ONVIF_ListSourcesAsyncEx method got an overload version with a callback for a more responsible UI
  • [X-engines] RTSP source compatibility update
  • [X-engines] Breaking API change. Starting with this update, the SDK uses IAudioRendererSettings interface implementations for audio output configuration. WASAPI output got the custom configuration classes. Output_AudioDevice properties of VideoCaptureCoreX/MediaPlayerCoreX type have been changed to IAudioRendererSettings. You can create the AudioRendererSettings class instance from AudioOutputDeviceInfo using the default constructor.
  • [X-engines] Resolved problem with missed Media Foundation sources during device enumeration
  • [X-engines] Resolved RTSP source problems with audio connection in some situations
  • [X-engines] Added the RTSP Preview Demo to Media Blocks SDK .Net
  • [Windows] FFMPEG outputs and source updated to FFMPEG v7.0.
  • [X-engines] Fixed rare crashes in RTSP source when camera information is not available for some reason (network issue)
  • [X-engines] Resolved an issue with WASAPI/WASAPI2 audio renderer usage
  • [X-engines] Resolved an issue with the audio loopback audio source on Windows
  • [X-engines] Improved iOS video rendering performance and stability
  • [X-engines] Added AWS S3 Sink output for Media Blocks SDK .Net
  • [X-engines] Added Allied Vision USB3/GigE cameras support in Media Blocks SDK .Net and Video Capture SDK .Net

15.9

  • [X-engines] Resolved wrong aspect ratio with video resize effect/block
  • [X-engines] Updated GStreamer redist
  • [X-engines] Added Basler USB3/GigE cameras support in Media Blocks SDK .Net and Video Capture SDK .Net
  • [Video Edit SDK .Net] VideoEditCoreX: The TextOverlay class changed to use SkiaSharp-based font settings. Additionally, you can set the custom font file name or configure all rendering parameters using custom SKPaint.
  • [Windows] Added Stream support in MediaInfoReader. You can get the video/audio file information from a stream (DB, network, memory, etc.).
  • [X-engines] Updated Live Video Compositor engine, which improved support of the file sources
  • [Video Capture SDK .Net] Added camera-covered detector into the Computer Vision Demo and the VisioForge.Core.CV package
  • [X-engines] Added API to get snapshots from video files using MediaInfoReaderX: GetFileSnapshotBitmap, GetFileSnapshotSKBitmap, GetFileSnapshotRGB
  • [X-engines] iOS support in MAUI samples
  • [X-engines] Resolved memory leak issue for RTSP sources
  • [Media Player SDK .Net] MediaPlayerCore: Added support for data streams in video files using the FFMPEG source engine. Add the OnDataFrameBuffer event to get data frames (KLV or other) from the video file.
  • [Video Capture SDK .Net] VideoCaptureCore: Added support for data streams in video files using the IP Capture FFMPEG source engine. Add the OnDataFrameBuffer event to get data frames (KLV or other) from the MPEG-TS UDP network stream or other supported source.
  • [Video Capture SDK .Net] VideoCaptureCore: Added the FFMPEG_CustomOptions property to the IPCameraSourceSettings class. This property allows you to set custom FFMPEG options for the IP camera source
  • [Windows] Fixed the hang problem with the FFMPEG source when a network connection is lost
  • [Media Blocks SDK .Net] Added RTSP MultiView in Sync Demo
  • [X-engines] Added support for FLIR/Teledyne cameras (USB3Vision/GigE) using the Spinnaker SDK
  • [Video Edit SDK .Net] VideoEditCoreX: Added support for .Net Stream usage as an input source
  • The IAsyncDisposable interface was added to all SDK's core classes. The DisposeAsync call should be used to dispose of the core objects using async methods.
  • [Video Capture SDK .Net] VideoCaptureCoreX: Resolved issues with Android video capture (sometimes started only one time)
  • [Media Blocks SDK .Net] Added HLS streaming sample
  • [Video Capture SDK .Net] VideoCaptureCore: Resolved crash if the multiscreen is enabled and screens added as window's handles (WinForms)
  • [X-engines] Improved MAUI video rendering speed
  • [X-engines] Resolved MAUI media playback issues (decoding) in MAUI Android
  • [X-engines] Resolved an issue with the H264 webcam sources (sometimes not connected)
  • [X-engines] Resolved an issue with audio stream playback in the Live VideoCompositor engine
  • [Media Blocks SDK .Net] Resolved a bad audio issue while mixing using the Live Video Compositor engine
  • [Media Blocks SDK .Net] Added Decklink output and file source into the Live Video Compositor sample
  • [Media Player SDK .Net] MediaPlayerCore: Added growing MPEG-TS file support for the VLC engine. You can play growing MPEG-TS files while it's recorded

15.8

  • [X-engines] [API breaking change] DeviceEnumerator can now be used only by using DeviceEnumerator.Shared property. One enumerator per app is required. DeviceEnumerator objects used by API have been removed
  • [X-engines] [API breaking change] Android Activity is not required anymore to create SDK engines
  • [X-engines] [API breaking change] X-engines require additional initialization and de-initialization steps. To initialize SDK, use the VisioForge.Core.VisioForgeX.InitSDK() call. To de-initialize SDK, use the VisioForge.Core.VisioForgeX.DestroySDK() call. You need to initialize SDK before any SDK class usage and de-initialize SDK before the application exits.
  • [Windows] Improved MAUI video rendering performance in Windows
  • [Windows] Added a mouse highlight for screen capture sources
  • [Windows] Resolved a CallbackOnCollectedDelegate call issue with the BasicWindow class
  • [Avalonia] Resolved an issue with Avalonia VideoView resize
  • [X-engines] Added the StartPosition and StopPosition properties to UniversalSourceSettings. You can use these properties to set the start and stop positions for the file source.
  • [ALL] Resolved the issue with passwords with special characters used for RTSP sources
  • [ALL] Resolved the rare video flip issue with the Virtual Camera SDK engine
  • [ALL] The VisioForge MJPEG Decoder filter was removed from the SDK's NuGet packages. You can optionally add it to your project by file copying or COM registration deployment.
  • [X-engines] Fixed memory leak in the OverlayManager
  • [Media Blocks SDK .Net] Resolved issue with the VideoSampleGrabberBlock, SetLastFrame option
  • [Video Capture SDK .Net] VideoCaptureCoreX: WASAPI and WASAPI2 audio sources can be used now with the VideoCaptureCoreX engine
  • [X-engines] DeviceEnumerator got events to notify about devices added/removed: OnVideoSourceAdded, OnVideoSourceRemoved, OnAudioSourceAdded, OnAudioSourceRemoved, OnAudioSinkAdded, OnAudioSinkRemoved
  • [X-engines] Added custom error handler support for MediaBlocks, VideoCaptureCoreX, and MediaPlayerCoreX engines. Use the IMediaBlocksPipelineCustomErrorHandler interface and the SetCustomErrorHandler method to set a custom error handler.
  • [Video Capture SDK .Net] VideoCaptureCoreX: Resolved issue with incorrect device index error for KS video sources (Windows)
  • [Video Capture SDK .Net] VideoCaptureCore: Added Virtual_Camera_Output_AlternativeAudioFilterName property to set a custom audio filter for the Virtual Camera SDK output
  • [Video Edit SDK .Net] VideoEditCore: Added Virtual_Camera_Output_AlternativeAudioFilterName property to set a custom audio filter for the Virtual Camera SDK output
  • [Media Player SDK .Net] MediaPlayerCore: Added Virtual_Camera_Output_AlternativeAudioFilterName property to set a custom audio filter for the Virtual Camera SDK output
  • [Video Capture SDK .Net] VideoCaptureCoreX: Added NDI streaming support and sample app.
  • [Media Blocks SDK .Net] Added the BufferSink block to get video/audio frames from the pipeline
  • [Media Blocks SDK .Net] Added the CustomMediaBlock class to create custom media blocks for any GStreamer element
  • [Media Blocks SDK .Net] Added the UpdateChannel method to update the channel of the bridge source or sink
  • [Media Player SDK .Net] MediaPlayerCore: Updated Tempo effect.
  • [X-engines] Updated device enumerator. Removed unwanted firewall dialog when listing NDI sources.
  • [X-engines] Fixed an issue with the video mixer when adding/removing video sources.
  • [Media Blocks SDK .Net] Added VideoCropBlock and VideoAspectRatioCropBlock blocks to crop video frames.
  • [Media Blocks SDK .Net] Resolved wrong frame rate issue with VideoRateBlock.
  • [All] Resolved an issue with the Tempo audio effect.
  • [Video Capture SDK .Net] VideoCaptureCore: Added WASAPI audio renderer support for the VideoCaptureCore engine.

15.7

  • [ALL] .Net 8 support
  • [Video Capture SDK .Net] VideoCaptureCore: Fixed problem with the OnNetworkSourceDisconnect event being called twice.
  • [X-engines] Added the MPEG-2 video encoder.
  • [X-engines] Added the MP2 audio encoder.
  • [X-engines] Resolved Decklink enumeration issues.
  • [X-engines] Default VP8/VP9 settings changed to live recording.
  • [X-engines] Added DNxHD video encoder support.
  • [Video Capture SDK .Net] VideoCaptureCoreX: Fixed problem with audio source format setting (regression).
  • [Video Capture SDK .Net] VideoCaptureCoreX: Resolved WPF native rendering issue with a pop-up window.
  • [All] Avalonia 11.0.5 support.
  • [Video Capture SDK .Net] VideoCaptureCoreX: Resolved licensing issues.
  • [Video Capture SDK .Net] VideoCaptureCore: Start/StartAsync method will return false if the video capture device is already used by another application.
  • [All] Updated VLC source (libVLC 3.0.19).
  • [All] Updated FFMPEG sources and encoders. Resolved issue with missed MSVC dependencies.
  • [Video Capture SDK] Updated ONVIF engine.
  • [Cross-platform SDKs] Updated Decklink source. Resolved the issue with the incorrect device name.
  • [All] SkiaSharp security updates.
  • [Cross-platform SDKs] Updated Overlay Manager. Added OverlayManagerDateTime class to draw current date time and custom text.
  • [Cross-platform SDKs] Updated OverlayManagerImage. Resolved issue with System.Drawing.Bitmap usage.
  • [ALL] VideoCaptureCore: Resolved rare crash issue with WinUI VideoView
  • [Video Capture SDK .Net] VideoCaptureCore: Updated FFMPEG.exe output. Improved support of x264 and x265 encoders of custom FFMPEG builds.

15.6

  • [Video Capture SDK .Net] VideoCaptureCore: Improved video crop performance on modern CPUs
  • [ALL] VideoCaptureCore, MediaPlayerCore, VideoEditCore: Added the static CreateAsync method that can be used instead of the constructor to create engines without UI lag.
  • [Video Capture SDK .Net] VideoCaptureCore: Resolved issues with video crop.
  • [Video Capture SDK .Net] VideoCaptureCoreX: Added video overlays API. The Overlay Manager Demo shows how to use it.
  • [Video Capture SDK .Net] Improved HW encoder detection. If you have several GPUs, sometimes only the major GPU can be used for video encoding.
  • [Cross-platform SDKs] Updated Avalonia VideoView. Resolved issue with VideoView recreation.
  • [Media Player SDK .Net] MediaPlayerCoreX: Resolved startup issue with the Android version of the MediaPlayerCoreX engine.
  • [Media Player SDK .Net] MediaPlayerCore: Video_Stream_Index property has been replaced with Video_Stream_Select/Video_Stream_SelectAsync methods.
  • [Media Player SDK .Net] MediaPlayerCoreX: Added Video_Stream_Select method.
  • [Video Capture SDK .Net] VideoCaptureCore: Network_Streaming_WMV_Maximum_Clients property moved to WMVOutput class. You can set the maximum number of clients for network WMV output.
  • [All] Updated WPF rendering. Improved performance for 4K and 8K videos.
  • [Video Capture SDK .Net] VideoCaptureCoreX: Resolved issue with multiple outputs used.
  • [Video Capture SDK .Net] VideoCaptureCoreX: Resolved issue with OnAudioFrameBuffer event.
  • [Video Capture SDK .Net] Decklink source changed to improve startup speed. The Decklink_CaptureDevices method has been replaced by async Decklink_CaptureDevicesAsync.
  • [Media Player SDK .Net] MediaPlayerCoreX: Added Custom_Video_Outputs/Custom_Audio_Outputs properties to set custom video/audio renderers
  • [Media Player SDK .Net] MediaPlayerCoreX: Added Decklink Output Player Demo (WPF)
  • [Video Edit SDK .Net] Added Multiple Audio Tracks Demo (WPF)
  • [Video Edit SDK .Net] Updated MP4 output for multiple audio tracks
  • [Cross-platform SDKs] Updated device enumerator
  • [Video Capture SDK .Net] Resolved issue with VU meter in cross-platform engine
  • [Cross-platform SDKs] Resolved issue with VU Meter (event not fired)
  • [Media Player SDK .Net] Updated memory playback
  • [ALL] Added IAsyncDisposable interface support for cross-platform core classes. It should be used to dispose of the core objects in async methods.
  • [Video Capture SDK .Net] Added madVR support for mutiscreen
  • [Video Capture SDK .Net] Resolved NDI enumerating issue in the VideoCaptureCore engine
  • [Media Player SDK .Net] Added madVR Demo
  • [Video Capture SDK .Net] Added madVR Demo
  • [ALL] Resolved madVR issues in all SDKs
  • [Media Blocks SDK .Net] Added NDI Source demo
  • [Video Capture SDK .Net] Added NDI support for cross-platform engine
  • [ALL] Resolve the "image not found" issue with the WinUI NuGet package
  • [Media Blocks SDK .Net/Media Player SDK .Net (cross-platform)] Added MP3+CDG Karaoke Player demo
  • [Media Blocks SDK .Net] Added CDGSourceBlock for MP3+CDG karaoke files playback
  • [ALL] Improved madVR support
  • WinUI VideoView updated to fix issues during audio file playback
  • [Video Capture SDK .Net] Improved VNC source support for the VideoCaptureCoreX engine.
  • [Video Capture SDK .Net] Added VNC source support for the VideoCaptureCoreX engine. You can use VNCSourceSettings class to configure Video_Source.
  • [Media Blocks SDK .Net] Added VNC source support. You can use the VNCSourceBlock class as a video source block.
  • [Video Capture SDK .Net] Video_Resize property has been changed to IVideoResizeSettings type. You can use the VideoResizeSettings class to perform classic resize the same as before or use MaxineUpscaleSettings/MaxineSuperResSettings to perform AI resizing on Nvidia GPU using Nvidia Maxine SDK (SDK or SDK models are required to deploy).
  • [ALL] Resolved issues with NDI source detection in the local network
  • [ALL] Added KLVParser class to read and decode data from KLV binary files.
  • [ALL] Added KLVFileSink block. You can export KLV data from MPEG-TS files.
  • [Media Blocks SDK .Net] Added KLV demo.
  • [Video Capture SDK .Net] Added MJPEG network streamer.
  • [ALL] Added WASAPI 2 support.
  • [Media Blocks SDK .Net] Updated Video Effects API. Added Grayscale media block.
  • [Media Blocks SDK .Net] Added Live Video Compositor API and sample.
  • [ALL] Updated Avalonia VideoView control. Resolved issues with video playback on Windows on HighDPI displays.
  • [Video Capture SDK .Net] Added CustomVideoFrameRate property to MFOutput. You can set a custom frame rate if your source provides an incorrect frame rate (IP camera, for example).
  • [Video Capture SDK .Net] Updated NVENC encoder. Resolved issue with high-definition video capture.
  • [Video Capture SDK .Net] Resolved issue with TV Tuning on Avermedia devices
  • [Media Blocks SDK .Net] Added OpenCV blocks: CVDewarp, CVDilate, CVEdgeDetect, CVEqualizeHistogram, CVErode, CVFaceBlur, CVFaceDetect, CVHandDetect, CVLaplace, CVMotionCells, CVSmooth, CVSobel, CVTemplateMatch, CVTextOverlay, CVTracker
  • [CV] Resolved the issue with wrong face coordinates.
  • [CV, Media Blocks SDK .Net] Added Face Detector block.
  • [Media Blocks SDK .Net] Added rav1e AV1 video encoder.
  • [Media Blocks SDK .Net] Added GIF video encoder.
  • [Media Blocks SDK .Net] Added NDI Sink and NDI source blocks.
  • [ALL] Resolved NDI SDK detection issues.
  • [Media Blocks SDK .Net] Updated Speex encoder.
  • [Media Blocks SDK .Net] Updated Video Mixer block.
  • [ALL] Added Save/Load methods for output format to serialize into JSON.
  • [Media Blocks SDK .Net] Added MJPEG HTTP Live streaming sink block.
  • [ALL] Resolved MP4 HW QSV H264 regression.
  • [ALL] WinForms and WPF VideoView stability updates.
  • [Media Player SDK .Net] Removed FilenamesOrURL legacy property. Please use the Playlist API instead.
  • [Media Blocks SDK .Net] Added fade-in/out feature for image overlay block.
  • [ALL] Telemetry update
  • [ALL] SDKs updated to use the ObservableCollection instead of the List in public API.
  • [ALL] Updated MP4 HW output. Improved NVENC performance.
  • [Media Blocks SDK .Net] Added Video Compositor sample.
  • [Media Blocks SDK .Net] Added YouTubeSink and FacebookLiveSink blocks with custom YouTube/Facebook configurations. The RTMPSink can stream to YouTube/Facebook in the same way as before.
  • [Media Blocks SDK .Net] Added SqueezeBack video mixer block.
  • [ALL] Updated scrolling text logo. We've added the Preload method to render a text overlay before playback.
  • [ALL] Updated scrolling text logo (performance)
  • [Media Blocks SDK .Net] Updated Decklink sink blocks
  • [ALL] Resolved crashes with a text logo with a custom resolution
  • [Media Blocks SDK .Net] Added Intel QuickSync H264, HEVC, VP9, and MJPEG encoders support.
  • [Video Edit SDK .Net] Added FastEdit_ExtractAudioStreamAsync method to extract the audio stream from the video file.
  • [Video Edit SDK .Net] Added "Audio Extractor" WinForms sample.
  • [Media Blocks SDK .Net] Updated MP4SinkBlock. The sink can split output files by duration, file size, or timecode. Use MP4SplitSinkSettings instead of MP4SinkSettings to configure.
  • [Video Capture SDK .Net] Added the OnMJPEGLowLatencyRAWFrame event that fired when the MJPEG low latency engine received a RAW frame from a camera.
  • [Media Blocks SDK .Net] Added VideoEffectsBlock to use video effects, available in Windows SDKs
  • [Media Blocks SDK .Net] Updated Decklink source
  • [Media Blocks SDK .Net] Added Decklink Demo (WPF)
  • [ALL] Resolved the DeinterlaceBlend video effect crash
  • [ALL] Used 3rd-party libraries moved to VisioForge.Libs.External assembly/NuGet
  • [ALL] Added Nvidia Maxine Video Effects SDK (BETA) and sample app for Media Player SDK .Net and Video Capture SDK .Net
  • [Video Capture SDK .Net] Added Decklink_Input_GetVideoFramesCount/Decklink_Input_GetVideoFramesCountAsync API to get total and dropped frames for the Decklink source
  • [ALL] VisioForge HW encoders update

15.5

  • .Net 7 support
  • Added NetworkDisconnect event support to MJPEG Low Latency IP camera engine
  • Added Linux support for the VideoEditCoreX-based demos
  • Added OnRTSPLowLatencyRAWFrame event to get RAW frames from RTSP stream, using RTSP Low Latency engine
  • Added AutoTransitions property to the VideoEditCoreX engine
  • System.Drawing.Rectangle and System.Drawing.Size types are replaced by VisioForge.Types.Rectangle and VisioForge.Types.Size in all crossplatform APIs
  • MAUI samples (BETA) are added
  • Improved compatibility with Snap Camera for MP4 HW encoding
  • Online licensing updated
  • Added Camera Light demo
  • Added segments support in Media Player SDK .Net (Cross-platform engine)
  • Added Playlist API in Media Player SDK .Net (Windows-only engine)
  • Resolved issues with the "rtsp_source_create_audio_resampler" call in the RTSP Low Latency engine in Video Capture SDK .Net (Windows-only engine)
  • Added support for multiple Decklink outputs in Video Capture SDK .Net and Video Edit SDK .Net (Windows-only engine)
  • Resolved issues with the reverse playback engine in Media Player SDK .Net (Windows-only engine)
  • ONVIFControl and other ONVIF-related APIs are available for all platforms
  • API breaking change: the frame rate changed from double to VideoFrameRate in all APIs
  • Added GPU HW decoding for VLC engine
  • Resolved issue with WPF HighDPI apps that use EVR
  • Resolved issue with MediaPlayerCore.Video_Renderer_SetCustomWindowHandle method
  • Added previous frame playback in Media Player SDK .Net (Cross-platform engine)
  • Added WPF Screen Capture Demo to Media Blocks SDK .Net

15.4

  • Resolved an issue with ignored Play_PauseAtFirstFrame property
  • Updated HighDPI support in WinForms samples
  • Resolved an issue with HighDPI support for the Direct2D video renderer
  • Added additional API to ONVIFControl class: GetDeviceCapabilities, GetMediaEndpoints
  • Resolved forced reencoding issue with FFMPEG files joining without reencoding
  • Sentry update
  • Added video interpolation settings for Zoom and Pan video effects
  • Added GtkSharp UI framework support for video rendering
  • FastEdit API has been changed to async
  • Resolved screen flip issue with Video_Effects_AllowMultipleStreams property of Video Capture SDK .Net core
  • Updated RTSP MultiView demo (added GPU decoding, added RAW stream access)
  • Added OnLoop event into Media Player SDK .Net
  • Added Loop feature into Media Blocks SDK .Net
  • Avalonia VideoView was downgraded to 0.10.12 because of Avalonia UI problems with NativeControl
  • Added File Encryptor demo for Video Edit SDK .Net

15.3

  • App start-up time improved for PCs with Decklink cards
  • NDI SDK v5 support
  • Resolved an issue with MKV Legacy output (wrong cast exception).
  • Zoom and pan effects performance optimizations
  • Added basic Media Blocks API (WIP)
  • Added HLS network streaming to Video Edit SDK .Net
  • Added Rotate property to WPF VideoView. You can rotate the video by 90, 180, or 270 degrees. Also, you can use the GetImageLayer() method to get the Image layer and apply custom transforms
  • API change - FilterHelpers renamed to FilterDialogHelper
  • VisioForge.Types and VisioForge.MediaFramework assemblies merged into VisioForge.Core
  • UI classes moved to VisioForge.Core.UI.* assemblies and independent NuGet packages
  • VisioForge.Types renamed to VisioForge.Core.Types
  • VisioForge.Core no longer depends on the Windows Forms framework

15.2

  • Added HorizontalAlignment and VerticalAlignment properties to the text and image logos
  • Updated ONVIF support, resolved an issue with username and password specified in URL but not specified in source settings
  • Resolved an issue with the FFMPEG.exe output dialog
  • Resolved an issue with the separate capture in a service applications
  • SDK migrated to System.Text.Json from NewtonsoftJson
  • Updated DirectCapture output for IP cameras
  • Video processing performance optimizations
  • IPCameraSourceSettings.URL property type changed from string to a System.Uri
  • Added DirectCapture ASF output for IP cameras

15.1

  • Disabled Sentry debug messages in the console
  • Added Icecast streaming
  • VideoStreamInfo.FrameRate property type changed to VideoFrameRate (with numerator and denominator) from double
  • Updated WPF VideoView, resolved the issue for IP camera stream playback
  • API breaking change: VisioForge.Controls, VisioForge.Controls.UI, VisioForge.Controls.UI.Dialogs, and VisioForge.Tools assemblies are merged inside the VisioForge.Core assembly
  • Audio effect API now uses string name instead of index
  • Added Android support in Media Player SDK .Net
  • Added a new GStreamer-based cross-platform engine to support Windows and other platforms within the v15 development cycle

15.0

  • Added StatusOverlay property for VideoCapture class. Assign the TextStatusOverlay object to this property to add text status overlay, for example, to show "Connecting..." text during IP camera connecting.
  • RTSP Live555 IP camera engine has been removed. Please use RTSP Low Latency or FFMPEG engines.
  • Resolved SDK_Version possible issue.
  • Added Settings_Load API. You can load the settings file saved by Settings_JSON. Be sure that device names are correct.
  • Resolved issue with an exception if separate capture started before Start/StartAsync method call.
  • RTP support for the VLC source engine.
  • API breaking change: SDK_State property has been removed. We do not have TRIAL and FULL SDK versions anymore.
  • API breaking change: DirectShow_Filters_Show_Dialog, DirectShow_Filters_Has_Dialog, Audio_Codec_HasDialog, Audio_Codec_ShowDialog, Video_Codec_HasDialog, Video_Codec_ShowDialog, Filter_Supported_LAV, Filter_Exists_MatroskaMuxer, Filter_Exists_OGGMuxer, Filter_Exists_VorbisEncoder, Filter_Supported_EVR, Filter_Supported_VMR9 and Filter_Supported_NVENC has been moved to VisioForge.Tools.FilterHelpers class.
  • The VFAudioStreamInfo/VFVideoStreamInfo classes use the Timespan for the duration.
  • Decklink types from VisioForge.Types assembly moved to VisioForge.Types.Decklink namespace.
  • Telemetry updated.
  • Custom redist loader updated.
  • NDI update.
  • API breaking change: The Status property was renamed to the State. The property type is PlaybackState in all SDKs.
  • API breaking change: UI controls split into Core (VideoCaptureCore, MediaPlayerCore, VideoEditCore) and VideoView.
  • API breaking change: Video_CaptureDevice... properties merged into Video_CaptureDevice property of VideoCaptureSource type.
  • API breaking change: Audio_CaptureDevice... properties merged into Audio_CaptureDevice property of AudioCaptureSource type.
  • API breaking change: In the Media Player SDK, the Source_Stream API properties were merged into the Source_MemoryStream property of the MemoryStreamSource type
  • Updated DVD playback
  • Updated FFMPEG source
  • API breaking change: Media Player SDK types moved from VisioForge.Types namespace to VisioForge.Types.MediaPlayer
  • API breaking change: Video Capture SDK types moved from VisioForge.Types namespace to VisioForge.Types.VideoCapture
  • API breaking change: Video Edit SDK types moved from VisioForge.Types namespace to "VisioForge.Types.VideoEdit"
  • API breaking change: Output types moved from VisioForge.Types namespace to VisioForge.Types.Output
  • API breaking change: Video Effects types moved from VisioForge.Types namespace to VisioForge.Types.VideoEffects
  • API breaking change: Audio Effects types moved from VisioForge.Types namespace to VisioForge.Types.AudioEffects
  • API breaking change: Event types moved from VisioForge.Types namespace to VisioForge.Types.Events
  • Added Video_Renderer_SetCustomWindowHandle method to set custom video renderer by Win32 window/control HWND handle

14.4

  • Windows 11 support
  • Telemetry update
  • Resolved issues with Picture-in-Picture in 2x2 mode
  • Resolved issues with MJPEG Low Latency source in .Net 5/.Net 6/.Net Core 3.1
  • Resolved issue with UDP network streaming for Decklink source
  • VFMP4v11Output renamed to VFMP4HWOutput
  • Added Microsoft H265 encoder support
  • Added Intel QuickSync H265 encoder support
  • Added OnDecklinkInputDisconnected/OnDecklinkInputReconnected events
  • Updated Decklink output
  • Resolved issues with Separate capture for MP4 HW, MOV, MPEG-TS, and MKVv2 outputs
  • Added Video_CaptureDevice_CustomPinName property. You can use this property to set a custom output pin name for a video capture device with several output video pins
  • Custom redist configuration updated
  • Updated IP camera RTSP Low Latency engine

14.3

  • An issue with Video Resize filter creation for NuGet redists has been resolved
  • Telemetry update
  • Updated VFDirectCaptureMP4Output output
  • .Net 6 (preview) support
  • Nvidia CUDA removed. NVENC is a modern alternative and is available for H264/HEVC encoding.
  • IP camera MJPEG Low Latency engine has been updated
  • The NDI source listing has been updated
  • Improved ONVIF support
  • Added .Net Core 3.1 support for RTSP Low Latency source engine
  • Resolved issues with Picture-in-Picture for 2x2 mode
  • Split project and solutions by independent files for .Net Framework 4.7.2, .Net Core 3.1, .Net 5 and .Net 6

14.2

  • An issue with audio stream capture with enabled Virtual Camera SDK output was resolved
  • VFMP4v8v10Output was replaced with VFMP4Output
  • The "CanStart" method was added for Video_CaptureDevices items. The method returns true if the device can start and is not used exclusively in another app
  • Added async/await API to the ONVIFControl
  • An issue with wrong ColorKey processing in the Text Overlay video effect was resolved
  • Added forced frame rate support for the RTSP Low Latency IP camera source
  • MP4v11 AMD encoders were updated
  • The timestamp issue that happened during the MP4v11 separate capture pause/resume was resolved
  • FFMPEG.exe network streaming update
  • FFMPEG output was updated to the latest FFMPEG version
  • VC++ redist is no longer required to be installed. VC++ linking changed to static (except optional XIPH output)
  • Many base DirectShow filters moved to the VisioForge_BaseFilters module

14.1

  • Added WPF VideoView control. You can push video frames from the OnVideoFrameBuffer event to control to render them
  • Correct default transparency value for a text logo
  • ONVIF support added to .Net 5 / .Net Core 3.1 builds
  • Added IP_Camera_ONVIF_ListSourcesAsync method to discover ONVIF cameras in the local network
  • (BREAKING API CHANGE) Changed video capture device API for frame rates enumerating to support modern 4K cameras
  • Updated MJPEG Decoder (improved performance)
  • Removed MP4 v8 legacy encoders
  • INotifyPropertyChanged support in WinForms/WPF wrappers to provide MVVM application support
  • Resolved issue with RTMPS streaming to Facebook
  • IP camera source added to the TimeShift demo
  • Added separate output support for MOV
  • Added fast-start FFMPEG flag for MP4v11 output that used FFMPEG MP4 muxer
  • Added GPU decoding for the IP Camera source in demo applications
  • Added CustomRedist_DisableDialog property to disable the redist message dialog
  • Removed Kinect assemblies and demos. Please contact us if you still need Kinect packages
  • MP4v10 default profile has been changed to Baseline / 5.0 for better browser compatibility

14.0

  • .Net 5.0 support
  • Resolved issue with not visible Decklink sources in NuGet SDK version
  • Resolved issue with device added/removed notifier
  • Added alternative NDI source in Video Capture SDK .Net
  • Added NDI streaming (server) in Video Capture SDK .Net
  • Resolved Separate Capture usage issue for NuGet deployment
  • Resolved issue with merged text/image logos
  • Updated device notifier
  • Added CameraPowerLineControl class to control webcam power line frequency option
  • Legacy audio effects have been removed.
  • Removed HTTP_FFMPEG, RTSP_UDP_FFMPEG, RTSP_TCP_FFMPEG and RTSP_HTTP_FFMPEG from VFIPSource enumeration. You can use the Auto_FFMPEG value
  • Updated HLS server. Correct error reporting about used port
  • Added NDI streaming (server) in Video Edit SDK .Net
  • Added NDI streaming (server) in Media Player SDK .Net
  • Added IP_Camera_CheckAvailable method in Video Capture SDK .Net
  • Updated FFMPEG Source filter, more supported codecs, and added GPU decoding

12.1

  • Migrated to .Net 4.6
  • Added Debug_DisableMessageDialogs property to disable error dialog if OnError event is not implemented.
  • Fixed issue with resizing on the pause for WPF controls.
  • Updated ONVIF engine in Video Capture SDK .Net
  • Updated What You Hear source in Video Capture SDK .Net
  • Added OnPause/OnResume events
  • Updated YouTube demo in Media Player SDK .Net
  • Improved support of webcams with integrated H264 encoder in Video Capture SDK .Net
  • Updated VLC source
  • Removed unwanted warning in MP4 v11 output
  • One installer for TRIAL and FULL versions
  • Same NuGet packages for TRIAL and FULL versions
  • .Net Core NuGet packaged merged with .Net Framework package
  • Added NuGet redists. Deployment was never so simple!

12.0

  • Async / await API for all SDKs
  • Breaking API change: All time-related API now uses TimeSpan instead of long (milliseconds)
  • Tag reader/writer - correct logo loading for some video formats
  • Removed legacy DirectX 9 video effects
  • Fixed audio conversion progress issue in Video Edit SDK .Net
  • Improved .Net Core compatibility
  • Virtual Camera SDK output added to Media Player SDK .Net (as one of the video renderers)
  • NewTek NDI devices support added to Video Capture SDK .Net as a new engine for IP cameras
  • Added Video_Effects_MergeImageLogos and Video_Effects_MergeTextLogos properties. If you have three or more logos, you can set these properties to true to optimize video effects' performance
  • Added playlist type option for HLS network streaming
  • Added integrated lightweight HTTP server for HLS network streaming
  • Added VR 360° video support in Media Player SDK .Net
  • Improved DirectX 11 video processing
  • Added MPEG-TS AAC-only no video support for MPEG-TS output
  • Improved What You Hear audio source
  • Several new demo applications
  • Improved MP4 v11 output
  • Separate capture for MP4 v11 can split files without frame lose
  • Many minor bugfixes
  • .Net Core assemblies updated to .Net Core 3.1 LTS
  • Updated demos repository on GitHub

11.4

  • Added ASP.Net MVC video conversion demo app to Video Edit SDK .Net
  • Alternative OSD implementation to handle Windows 10 changes
  • Updated GPU video effects
  • Updated memory source in Media Player SDK .Net
  • Updated OSD API
  • Resolved issues with video encryption using binary keys
  • Update screen capture demos for Video Capture SDK .Net, added window selection to capture. You can capture any window, including windows in the background
  • Mosaic effect added for Computer Vision demo in Video Capture SDK .Net
  • Added Multiple IP Cameras Demo (WPF) in Video Capture SDK .Net
  • Added custom video resize option for MP4v11 output
  • Merge module (MSM) redists added to all SDKs
  • Updated FFMPEG.exe output using pipes instead of virtual devices
  • Resolved issue with PIP custom output resolution option in Video Capture SDK .Net
  • Resolved issue with file lock using LAV engine in Media Player SDK .Net
  • Added DirectX11-based GPU video processing

11.3

  • Resolved issue with audio renderer connection if Virtual Camera SDK output enabled in Video Capture SDK
  • Improved subtitles support with autoloading in Media Player SDK .Net
  • Updated audio fade-in/fade-out effects
  • Added MIDI and KAR files support in Media Player SDK .Net
  • Added CDG karaoke files support (and new demo application) in Media Player SDK .Net
  • Added Async playback in Media Player SDK .Net
  • Updated integrated JSON serializer
  • Added optional GPU decoding in Media Player SDK .Net. Available decoding engines: DXVA2, Direct3D 11, nVidia CUVID, Intel QuickSync
  • Added .Net Core 3.0 support, including WinForms and WPF demo apps (Windows only)

11.2

  • Added Loop property to Video Edit SDK .Net
  • Updated audio enhancer
  • Updated RTSP Low Latency source
  • Resolved crop issue for Decklink source
  • Added property to use TCP or UDP in RTSP Low Latency engine
  • Deployment without COM registration and admin rights for Video Edit SDK and Media Player SDK (BETA)
  • Updated video mixer with improved performance
  • Added YouTube playback code snippet
  • Added method to move OSD

11.1

  • Fixed seeking issue with some MP4 files in Video Edit SDK
  • Fixed stretch/letterbox issue in the WPF version of all SDKs
  • Fixed issue with an equalizer on sample rate 16000 or less
  • Fixed problem with sample grabber for DirectShow source in Media Player SDK
  • Fixed encrypted files playback in Media Player SDK
  • Added DVDInfoReader class to read info about DVD files
  • Resolved issue with wrong file name in OnSeparateCaptureStopped event
  • Improved barcode detection quality for rotated images
  • The minimal .Net Framework version is .Net 4.5 now
  • Improved YouTube playback in Media Player SDK. Added OnYouTubeVideoPlayback event to select video quality for playback
  • Added the Play_PauseAtFirstFrame property to the Media Player SDK .Net. If true playback will be paused on the first frame
  • Multiple screen support in Screen Capture demo in Video Capture SDK .Net
  • Resolved issue with network stream playback in Media Player SDK .Net WPF applications
  • Added low latency HTTP MJPEG stream playback (IP cameras or other sources) in Video Capture SDK .Net
  • Added Fake Audio Source DirectShow filter, which produces a tone signal
  • Updated Computer Vision demo in Video Capture SDK .Net
  • Added Frame_GetCurrentFromRenderer method to all SDKs. Using this method, you can get the currently rendered video frame directly from the video renderer.
  • Added low latency RTSP source playback in Video Capture SDK .Net

11.0

  • Fixed bug with MP4 v11 output, custom GOP settings
  • Updated MJPEG Decoder
  • Fixed bug with MP4 v11 output. Added Windows 7 full support
  • OnStop event of Video Edit SDK returns a successful status
  • Video Capture SDK Main Demo update - multiscreen can automatically use connected external displays
  • Media Player SDK Main Demo update - multiscreen can automatically use connected external displays
  • Added fade-in / fade-out for text logo
  • Updated Decklink output
  • Video Edit SDK can fast-cut files from network sources (HTTP/HTTPS)
  • Added Computer Vision demo, with cars/pedestrian counter and face/eyes/nose/mouth detector/tracker
  • Updated MP4 output to use alternative muxer that provides constant frame rate
  • Added MPEG-TS output
  • Added MOV output