Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 66 additions & 3 deletions src/LibVLCSharp/Shared/MediaPlayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1305,6 +1305,7 @@ public void SetVideoFormat(string chroma, uint width, uint height, uint pitch)
}

LibVLCVideoFormatCb? _videoFormatCb;
LibVLCVideoFormatCbMultiPlane? _videoMultiPlaneFormatCb;
LibVLCVideoCleanupCb? _videoCleanupCb;
IntPtr _videoUserData = IntPtr.Zero;

Expand All @@ -1317,9 +1318,35 @@ public void SetVideoFormat(string chroma, uint width, uint height, uint pitch)
public void SetVideoFormatCallbacks(LibVLCVideoFormatCb formatCb, LibVLCVideoCleanupCb? cleanupCb)
{
_videoFormatCb = formatCb ?? throw new ArgumentNullException(nameof(formatCb));
_videoMultiPlaneFormatCb = null;
_videoCleanupCb = cleanupCb;
Native.LibVLCVideoSetFormatCallbacks(NativeReference, VideoFormatCallbackHandle,
(cleanupCb == null)? null : _videoCleanupCb);
(cleanupCb == null)? null : VideoCleanupCallbackHandle);
}

/// <summary>
/// Set decoded video chroma and dimensions with multi-plane format access.
/// This variant exposes pitches and lines as IntPtr to allow direct
/// multi-plane access to the arrays provided by libVLC.
/// This only works in combination with libvlc_video_set_callbacks().
/// </summary>
/// <param name="formatCb">callback to select the video format (cannot be NULL)</param>
/// <param name="cleanupCb">callback to release any allocated resources (or NULL)</param>
public void SetVideoFormatCallbacksMultiPlane(LibVLCVideoFormatCbMultiPlane formatCb, LibVLCVideoCleanupCb? cleanupCb)
{
_videoMultiPlaneFormatCb = formatCb ?? throw new ArgumentNullException(nameof(formatCb));
_videoFormatCb = null;
_videoCleanupCb = cleanupCb;
Native.LibVLCVideoSetFormatCallbacks(NativeReference, VideoFormatCallbackHandle,
(cleanupCb == null)? null : VideoCleanupCallbackHandle);
}
static readonly LibVLCVideoCleanupCb VideoCleanupCallbackHandle = VideoCleanupCallback;

[MonoPInvokeCallback(typeof(LibVLCVideoCleanupCb))]
private static void VideoCleanupCallback(ref IntPtr opaque)
{
var mediaPlayer = MarshalUtils.GetInstance<MediaPlayer>(opaque);
mediaPlayer?._videoCleanupCb?.Invoke(ref mediaPlayer._videoUserData);
}

/// <summary>
Expand Down Expand Up @@ -1822,9 +1849,37 @@ private static void VideoDisplayCallback(IntPtr opaque, IntPtr picture)
private static uint VideoFormatCallback(ref IntPtr opaque, IntPtr chroma, ref uint width, ref uint height, ref uint pitches, ref uint lines)
{
var mediaPlayer = MarshalUtils.GetInstance<MediaPlayer>(opaque);
if (mediaPlayer?._videoFormatCb != null)
if (mediaPlayer == null)
return 0;

// Route to multi-plane callback
if (mediaPlayer._videoMultiPlaneFormatCb != null)
{
IntPtr pitchesPtr = Marshal.AllocHGlobal(sizeof(uint));
IntPtr linesPtr = Marshal.AllocHGlobal(sizeof(uint));
try
{
Marshal.WriteInt32(pitchesPtr, (int)pitches);
Marshal.WriteInt32(linesPtr, (int)lines);
uint result = mediaPlayer._videoMultiPlaneFormatCb(
ref mediaPlayer._videoUserData,chroma,ref width,ref height,pitchesPtr,
linesPtr);
pitches = (uint)Marshal.ReadInt32(pitchesPtr);
lines = (uint)Marshal.ReadInt32(linesPtr);
return result;
}
finally
{
Marshal.FreeHGlobal(pitchesPtr);
Marshal.FreeHGlobal(linesPtr);
}
}

// Otherwise use legacy single-plane callback
if (mediaPlayer._videoFormatCb != null)
{
return mediaPlayer._videoFormatCb(ref mediaPlayer._videoUserData, chroma, ref width, ref height, ref pitches, ref lines);
return mediaPlayer._videoFormatCb(
ref mediaPlayer._videoUserData,chroma,ref width,ref height,ref pitches,ref lines);
}

return 0;
Expand Down Expand Up @@ -2004,10 +2059,18 @@ private static void AudioCleanupCallback(IntPtr opaque)
/// <para>to not break assumptions that might be held by optimized code</para>
/// <para>in the video decoders, video filters and/or video converters.</para>
/// </remarks>

// Legacy single-plane callback for compatibility
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate uint LibVLCVideoFormatCb(ref IntPtr opaque, IntPtr chroma, ref uint width,
ref uint height, ref uint pitches, ref uint lines);

/// <summary>Callback prototype to configure picture buffers format (multi-plane variant).</summary>
/// <remarks>Passes pitches and lines as IntPtr to allow direct multi-plane data access via Marshal or unsafe pointer arithmetic.</remarks>
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate uint LibVLCVideoFormatCbMultiPlane(ref IntPtr opaque, IntPtr chroma, ref uint width,
ref uint height, IntPtr pitches, IntPtr lines);

/// <summary>Callback prototype to configure picture buffers format.</summary>
/// <param name="opaque">
/// <para>private pointer as passed to libvlc_video_set_callbacks()</para>
Expand Down