Commit b6e75925 authored by Jérémy VIGNELLES's avatar Jérémy VIGNELLES Committed by Martin Finkel

Avoid a copy in StreamMediaInput on modern platforms.

This requires unsafe code to use the newer Span APIs
netstandard1.1 is also removed
parent 1d3856b0
......@@ -166,5 +166,31 @@ namespace LibVLCSharp.Helpers
MarshalUtils.LibVLCFree(ref nativeString);
return Encoding.UTF8.GetString(buffer, 0, buffer.Length);
/// <summary>
/// The Span-based APIs on Stream are not available on older targets. Span can be backported on older TFMs through the System.Memory package,
/// but System.IO does not provide the same benefit. This code is extracted from dotnet/runtime to allow efficient media callbacks implementation.
/// </summary>
/// <remarks></remarks>
/// <param name="stream">the .NET stream</param>
/// <param name="buffer">the buffer to read</param>
/// <returns>number of bytes read</returns>
internal static int Read(this System.IO.Stream stream, Span<byte> buffer)
var sharedBuffer = System.Buffers.ArrayPool<byte>.Shared.Rent(buffer.Length);
var numRead = stream.Read(sharedBuffer, 0, buffer.Length);
if ((uint)numRead > (uint)buffer.Length)
throw new System.IO.IOException("StreamTooLong");
new Span<byte>(sharedBuffer, 0, numRead).CopyTo(buffer);
return numRead;
finally { System.Buffers.ArrayPool<byte>.Shared.Return(sharedBuffer); }
......@@ -28,7 +28,7 @@ This package also contains the views for the following platforms:
If you need Xamarin.Forms support, see LibVLCSharp.Forms.
LibVLC needs to be installed separately, see VideoLAN.LibVLC.* packages.</Description>
<TargetFrameworks Condition="!$([MSBuild]::IsOsPlatform('Linux'))">$(TargetFrameworks);MonoAndroid81;Xamarin.iOS10;Xamarin.Mac20;Xamarin.TVOS10</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOsPlatform('Windows'))">$(TargetFrameworks);uap10.0;uap10.0.16299;net45;net471</TargetFrameworks>
......@@ -49,6 +49,7 @@ LibVLC needs to be installed separately, see VideoLAN.LibVLC.* packages.</Descri
<PropertyGroup Condition="$(TargetFramework.StartsWith('uap'))">
......@@ -60,6 +61,7 @@ LibVLC needs to be installed separately, see VideoLAN.LibVLC.* packages.</Descri
<ItemGroup Condition="$(TargetFramework.StartsWith('MonoAndroid'))">
<Compile Include="Platforms\Android\**\*.cs" />
......@@ -86,7 +88,13 @@ LibVLC needs to be installed separately, see VideoLAN.LibVLC.* packages.</Descri
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="SharpDX.Direct3D11" Version="4.2.0" />
<PackageReference Include="System.Memory" Version="4.5.4" />
<ItemGroup Condition="$(TargetFramework.StartsWith('net4')) Or '$(TargetFramework)' == 'netstandard2.0' ">
<PackageReference Include="System.Memory" Version="4.5.4" />
<Target Name="IncludeAWindow" Condition="$(TargetFramework.StartsWith('MonoAndroid'))">
<BuildOutputInPackage Include="$(OutputPath)LibVLCSharp.Android.AWindow.dll" />
using System;
using System.IO;
using System.Runtime.InteropServices;
using LibVLCSharp.Helpers;
namespace LibVLCSharp
/// <summary>
......@@ -10,7 +12,6 @@ namespace LibVLCSharp
public class StreamMediaInput : MediaInput
private readonly Stream _stream;
private readonly byte[] _readBuffer = new byte[0x4000];
/// <summary>
/// Initializes a new instance of <see cref="StreamMediaInput"/>, which reads from the given .NET stream.
......@@ -61,14 +62,11 @@ namespace LibVLCSharp
/// <param name="buf">The buffer where read data must be written</param>
/// <param name="len">The buffer length</param>
/// <returns>The number of bytes actually read, -1 on error</returns>
public override int Read(IntPtr buf, uint len)
public unsafe override int Read(IntPtr buf, uint len)
var read = _stream.Read(_readBuffer, 0, Math.Min((int)len, _readBuffer.Length));
Marshal.Copy(_readBuffer, 0, buf, read);
return read;
return _stream.Read(new Span<byte>(buf.ToPointer(), (int)Math.Min(len, int.MaxValue)));
catch (Exception)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment