v1.28.4
The module release: three new packages ship for the first time — GstSharp.Net.Tag, GstSharp.Net.Allocators and GstSharp.Net.Transcoder — which takes the set to fifteen, and the API reference is published as a site. Beside them, wave D closes more families of the skip ledger (the mutators that consume their instance, the GValue a callback is handed, the fixed-size fields of a record, the GParamSpec callables) and the G4 batch fixes the callback-state leaks the clock and custom-meta entry points were hiding. The ledger goes from 848 entries to 817 even with the entries the new modules bring, and a new ## Fields section counts the 267 record fields no accessor reaches yet.
Highlights
GstSharp.Net.Tag— the GstTag library. The whole gir: the two abstract element bases that tag demuxers and muxers derive from, the XMP writer interface, and the forty functions that turn an ID3v1 record, a Vorbis comment, an XMP packet or an EXIF IFD into a tag list and back. Five returns the gir does not mark nullable are corrected against the C, because NULL is an ordinary answer there and not an error.GstSharp.Net.Allocators— the fd, dmabuf, shm and DRM dumb allocators. The module registers its five allocator classes; the 1.28-only udmabuf type is left out of the registry on older installations, and the two DRM dumb returns that are NULL on every build without libdrm carry a nullable annotation overlay.GstSharp.Net.Transcoder— GstTranscoder.Transcoder.Runis a one-shot per instance and has to be called from a thread that has no thread-default main context — that is, one that uses the global default: build a newTranscoderfor every job, and do not mixRunandRunAsyncon one instance.RunAsyncreports its two synchronous failures — no encoding profile, and a state change the pipeline refused — on the calling thread before it returns, and every other message arrives on the internal worker thread of the transcoder; the recommended route isRunAsynctogether with a poll ofGetMessageBus, which is whatsamples/GstTranscodedoes.TranscoderMessageExtensions.ParseError/ParseWarningare hand written so that a message without issue details answersnull, where the imported pair aborts the process.- API reference site — the API reference extracted from the XML documentation of the packable projects, together with the guides under
docs/, is published with DocFX at https://masa-iwm.github.io/GstSharp.Net/, deployed frommain. - Mutators that consume their instance — the twenty-one callables whose instance is transfer-full are bound. A
_make_writableadopts in place and returns the wrapper it was called on, socaps.MakeWritable()reads as the C idiom it stands for; everything else mints the reference the call takes over and answers a second wrapper, leaving the receiver untouched. - GValue arguments of a callback — a
const GValue*argument arrives asGst.GObject.ValueViewand a writable one asGst.GObject.ValueRef, bothref structs over storage somebody else owns. That unlocks the three structure walks, their_id_strtwins and the two iterator walks. - Fixed-size record fields — 18 get-only properties over GstVideo, GstAudio and GstSdp, the plane stride and offset arrays of
VideoInfoand the per-component tables ofVideoFormatInfoamong them, with hand-writtenFormatandFormatInfoonVideoInfoandAudioInfobeside them. The skip report gains a## Fieldssection that counts the 267 public fields no accessor answers yet. GParamSpeccallables — a parameter specification reaches a generated signature in both directions, which unlocks eight callables:gst_child_proxy_lookup,gst_object_default_deep_notify,gst_value_deserialize_with_pspecand the five child-property members ofGESTimelineElement.- Element factories that carry their properties —
ElementFactory.MakeWithPropertiesand.CreateWithPropertiesask the class of the loaded factory what type each named value has to hold, write a construct-only property rather than refusing it, and answer anArgumentExceptionfor an unknown or unwritable name instead of the console message GLib prints. GLib.Date↔System.DateOnly— a GDate has no identity and no state a caller could observe, so it is converted at the boundary instead of wrapped, at the six date callables of Gst and the GES meta container.- Ledger and diagnostics — sixty-nine C symbols the bindings cover from
src/*/Customand from the runtime are declared hand-bound, so the remaining sections of the skip report measure the gap that is real; a stale overlay entry is now reported (GEN0020 / GEN0023 / GEN0024) and the committed overlays are held to producing none;generatedeletes a committed generated file the run no longer emits andverifyreports it as a difference; and the class remarks now describe every callback scope the planner binds. - Community and coverage — the Contributor Covenant 2.1, a new
docs/platform-notes.mdfor what is a property of a platform rather than of the binding, and new integration tests and samples: BasicTutorial07 and BasicTutorial09,samples/AppSrcPush, the base-utils feature surface, the audio format / meta / converter / volume surfaces, and theVideoCodecFrameuser-data contract.
Behavioural fixes
Gst.Clock.IdWaitAsync — callback state leak, and a double free on a refused wait. gst_clock_id_wait_async writes the callback, its state and the destroy notification onto the entry immediately before it dispatches to the clock, so the three exits in front of that assignment never see the notification and the generated member leaked the GCHandle on every one of them. The entry point is now hand written with the same signature and documentation: it releases the state on GST_CLOCK_BADTIME, on GST_CLOCK_UNSUPPORTED and on a GST_CLOCK_ERROR with no clock alone, and leaves it with the entry for the refusals the clock itself answers — GST_CLOCK_UNSCHEDULED for an entry that was unscheduled beforehand, and GST_CLOCK_ERROR when the clock could not start its waiting thread — which the earlier code freed a second time, hitting an unrelated live handle. The reference taken on the clock of the entry across the call is held as a bare handle rather than through a wrapper, because wrappers are interned and disposing one disposed the clock of the caller.
Gst.Meta.RegisterCustom — transform state leak on a refused registration. gst_meta_register_custom only writes the transform function, its state and the destroy notification onto the implementation block once that block exists; both failures before it — an API type that could not be registered, which is what a name that is already taken produces, and a block that could not be allocated — answer NULL. The generated member allocated the GCHandle of the transform first and reported the NULL as an InvalidOperationException, so the throw leaked it. The entry point is now hand written with the same signature and releases the state before it raises. gst_meta_register_custom_simple is a different entry point and stays generated.
Callback state is allocated after every guard and prologue. A member whose only materializing argument was a callback took the GCHandle of the callback before the guard of a later parameter and before the UTF-8 copy of a later string, so either of those throwing stranded the handle, the delegate and everything the closure captured for the life of the process. The allocation is now the last statement before the call.
WebRTCDataChannel.OnMessageData — documentation correction. The remarks named a streaming thread of the pipeline; the handler in fact runs on the main context of the thread webrtcbin starts for the connection. Doc-only.
Behavioural notes
Two hardenings that only change what happens on input C would have mishandled:
Buffer.MakeWritable(),Caps.MakeWritable()and every generated*.MakeWritable()now throw anInvalidOperationExceptionwhen the writable copy could not be made. The C function consumed the reference all the same, so the wrapper is left disposed and the failure is raised, instead of silently handing back an already-consumed wrapper.Value.SetBoxed(Boxed?)andValue.SetMiniObject(MiniObject?)now check that the value holds a boxed type at all and that the GType of the content is that type or derives from it, and throw anInvalidOperationExceptionotherwise — on an uninitialized value, a value of another family, or a content of another type. GLib copies the content with the copy function of the type the value holds, so a wrapper of another type was silently handed to the wrong copy function and left a corrupt value behind; the rawSetBoxed(nint)overload has no type to check and is unchanged. This mirrors the checkValueRefhas performed since it shipped.
No signature changed for either.
Changes
- Check the content type at the two wrapper setters of Value
- Say which context the discoverer takes and that its signal is bound
- Cover the base utils features and port the tee, discoverer and appsrc samples
- Convert GLib.Date to System.DateOnly at the six date callables
- Count the three new modules across the docs, workflows and tests
- Bind the Gst.Transcoder module, its sample and the API bus parses
- Bind the GstTag library as the GstSharp.Net.Tag module
- Bind the fd, dmabuf, shm and DRM dumb allocators of GstAllocators
- Publish the API reference and guides with DocFX on GitHub Pages
- Bind the element factories that take their properties with them
- Bind the callables that take or hand out a GParamSpec
- Pin the VideoCodecFrame user data contract through theoradec
- Cover the audio format, meta, converter and volume surfaces with integration tests
- Ledger on-message-data as hand bound and correct the thread its remarks name
- Replace the gir returns text of adopt in place members with the wrapper note
- Bind the mutators that consume the instance they are called on
- Answer the fixed size fields of a record and ledger the rest
- Hand callback GValue arguments over as ValueView and ValueRef
- Name the maintainer as the conduct contact
- Mark the two G4 hand bindings as hand bound
- Run the console capturing tests on their own
- Hold the committed overlays to their stale entry diagnostics
- Leave a moved-to twin out of the hand bound ledger
- Drop the byte order marks of the RecordEmitter sources
- Notice a generated file the run no longer emits
- Report an annotation override that matched nothing
- Describe every callback scope the planner binds
- Drop the byte order mark from BufferNative.cs
- Mark the hand bound symbols in the generator ledger
- Bucket the overlay skips of a hand written wrapper as OverlaySkip
- Hold the clock of a wait_async as a handle, not as a wrapper
- Correct three notes that overstate what they saw
- Keep the state a refused wait_async left with the entry
- Wait for the accepted wait_async on a clock of its own
- Add the Contributor Covenant 2.1
- Record the Windows device provider behaviour
- Gate the 1.28 tests on one attribute
- Free the transform state when a custom meta is refused
- Free the callback state when a wait_async is refused
- Keep a fenced code block whole in the documentation
- Allocate callback state after every guard and prologue
- Guard the 1.28.3 surface too
- Say 1.28.3 when nobody passes a version
Full Changelog: v1.28.3...v1.28.4