Commit 1b28d48c authored by Martin Finkel's avatar Martin Finkel

Sound on Android. Still an issue with JNI array marshalling, needed to...

Sound on Android. Still an issue with JNI array marshalling, needed to complete initialization for video
parent 612f3933
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading;
using Android.App;
using Android.Graphics;
using Android.OS;
using Android.Util;
using Android.Views;
using Java.Interop;
using Java.Lang;
using Thread = Java.Lang.Thread;
......@@ -21,8 +21,8 @@ namespace LibVLCSharp.Android.Sample
class SurfaceHelper
{
AWindow _aWindow;
int _id;
readonly AWindow _aWindow;
readonly int _id;
readonly SurfaceView _surfaceView;
readonly TextureView _textureView;
static ISurfaceHolder _surfaceHolder;
......@@ -183,19 +183,23 @@ namespace LibVLCSharp.Android.Sample
static readonly int SURFACE_STATE_ATTACHED = 1;
static readonly int SURFACE_STATE_READY = 2;
SurfaceHelper[] _surfaceHelpers;
ISurfaceCallback _surfaceCallback;
readonly SurfaceHelper[] _surfaceHelpers;
readonly ISurfaceCallback _surfaceCallback;
int _surfaceState = SURFACE_STATE_INIT;
INewVideoLayoutListener _newVideoLayoutListener;
List<ICallback> _voutCallbacks = new List<ICallback>();
readonly List<ICallback> _voutCallbacks = new List<ICallback>();
readonly Handler _handler = new Handler(Looper.MainLooper);
Surface[] _surfaces;
IntPtr _callbackNativeHandle = IntPtr.Zero;
static Surface[] _surfaces;
long _callbackNativeHandle;
int _mouseAction, _mouseButton, _mouseX, _mouseY, _windowWidth, _windowHeight = -1;
SurfaceTextureThread _surfaceTextureThread = new SurfaceTextureThread();
readonly SurfaceTextureThread mSurfaceTextureThread = new SurfaceTextureThread();
static readonly NativeLock _nativeLock = new NativeLock();
const int AWINDOW_REGISTER_ERROR = 0;
const int AWINDOW_REGISTER_FLAGS_SUCCESS = 0x1;
const int AWINDOW__FLAGS_HAS_VIDEO_LAYOUT_LISTENER = 0x2;
public AWindow(ISurfaceCallback surfaceCallback)
{
_surfaceCallback = surfaceCallback;
......@@ -203,7 +207,6 @@ namespace LibVLCSharp.Android.Sample
_surfaces = new Surface[ID_MAX];
}
void EnsureInitState()
{
if (_surfaceState != SURFACE_STATE_INIT)
......@@ -336,10 +339,9 @@ namespace LibVLCSharp.Android.Sample
}
foreach(var cb in _voutCallbacks)
cb.OnSurfacesDestroyed(this);
if(_surfaceCallback != null)
_surfaceCallback.OnSurfacesDestroyed(this);
_surfaceCallback?.OnSurfacesDestroyed(this);
if(Build.VERSION.SdkInt >= BuildVersionCodes.JellyBean)
_surfaceTextureThread.Release();
mSurfaceTextureThread.Release();
}
public bool AreViewsAttached => _surfaceState != SURFACE_STATE_INIT;
......@@ -378,153 +380,134 @@ namespace LibVLCSharp.Android.Sample
public void AddCallback(ICallback callback)
{
throw new System.NotImplementedException();
if (_voutCallbacks.Contains(callback)) return;
_voutCallbacks.Add(callback);
}
public void RemoveCallback(ICallback callback)
{
throw new System.NotImplementedException();
_voutCallbacks.Remove(callback);
}
//(long nativeHandle, int action, int button, int x, int y) signature: "(JIIII)V", connector:
//[Register(name: "nativeOnMouseEvent")]
//[Export]
internal virtual void NativeOnMouseEvent(long nativeHandle, int action, int button, int x, int y)
{
public void SetWindowSize(int width, int height)
System.Diagnostics.Debug.WriteLine("NativeOnMouseEvent");
}
//[Export]
internal virtual void NativeOnWindowSize(long nativeHandle, int width, int height)
{
throw new System.NotImplementedException();
System.Diagnostics.Debug.WriteLine("NativeOnWindowSize");
}
// used by JNI
// Get the valid Video surface
// return can be null if the surface was destroyed.
// ReSharper disable once UnusedMember.Local
// ReSharper disable once InconsistentNaming
//[Register("getVideoSurface", )]
[Export("getVideoSurface")]
Surface VideoSurface() => GetNativeSurface(ID_VIDEO);
// Get the valid Subtitles surface.
// return can be null if the surface was destroyed.
// ReSharper disable once UnusedMember.Local
// ReSharper disable once InconsistentNaming
[Export("getSubtitlesSurface")]
Surface SubtitlesSurface() => GetNativeSurface(ID_SUBTITLES);
Surface GetNativeSurface(int id)
public void SetWindowSize(int width, int height)
{
lock (_nativeLock)
{
return _surfaces[id];
}
}
void SetNativeSurface(int id, Surface surface)
{
lock (_nativeLock)
if (_callbackNativeHandle != 0 && (_windowHeight != height || _windowWidth != width))
{
_surfaces[id] = surface;
NativeOnWindowSize(_callbackNativeHandle, width, height);
}
_windowHeight = height;
_windowWidth = width;
}
}
public interface IVLCVout
[Export("registerNative")]
int RegisterNative(long handle)
{
/// <summary>
/// Set a surfaceView used for video out.
/// </summary>
/// <param name="videoSurfaceView"></param>
void SetVideoView(SurfaceView videoSurfaceView);
/// <summary>
/// Set a TextureView used for video out.
/// </summary>
/// <param name="videoTextureView"></param>
void SetVideoView(TextureView videoTextureView);
/// <summary>
/// Set a surface used for video out.
/// </summary>
/// <param name="videoSurface">videoSurface if surfaceHolder is null, this surface must be valid and attached.</param>
/// <param name="surfaceHolder">surfaceHolder optional, used to configure buffers geometry before Android ICS and to get notified when surface is destroyed.</param>
void SetVideoSurface(Surface videoSurface, ISurfaceHolder surfaceHolder);
/// <summary>
/// Set a SurfaceTexture used for video out.
/// </summary>
/// <param name="videoSurfaceTexture">this surface must be valid and attached.</param>
void SetVideoSurface(SurfaceTexture videoSurfaceTexture);
/// <summary>
/// Set a surfaceView used for subtitles out.
/// </summary>
/// <param name="subtitlesSurfaceView"></param>
void SetSubtitlesView(SurfaceView subtitlesSurfaceView);
/// <summary>
/// Set a TextureView used for subtitles out.
/// </summary>
/// <param name="subtitlesTextureView"></param>
void SetSubtitlesView(TextureView subtitlesTextureView);
/// <summary>
/// Set a surface used for subtitles out.
/// </summary>
/// <param name="subtitlesSurface">if surfaceHolder is null, this surface must be valid and attached.</param>
/// <param name="surfaceHolder">optional, used to configure buffers geometry before Android ICS and to get notified when surface is destroyed.</param>
void SetSubtitlesSurface(Surface subtitlesSurface, ISurfaceHolder surfaceHolder);
/// <summary>
/// Set a SurfaceTexture used for subtitles out.
/// </summary>
/// <param name="subtitlesSurfaceTexture">this surface must be valid and attached.</param>
void SetSubtitlesSurface(SurfaceTexture subtitlesSurfaceTexture);
//if(handle == IntPtr.Zero)
if(handle == 0)
throw new IllegalArgumentException("handle is null");
/// <summary>
/// Attach views with an OnNewVideoLayoutListener
/// </summary>
/// <param name="onNewVideoLayoutListener"></param>
void AttachViews(INewVideoLayoutListener onNewVideoLayoutListener);
lock (_nativeLock)
{
if (_callbackNativeHandle != 0)
return AWINDOW_REGISTER_ERROR;
void AttachViews();
_callbackNativeHandle = handle;
void DetachViews();
bool AreViewsAttached { get; }
if (_mouseAction != -1)
{
NativeOnMouseEvent(_callbackNativeHandle, _mouseAction, _mouseButton, _mouseX, _mouseY);
}
void AddCallback(ICallback callback);
if (_windowWidth != -1 && _windowHeight != -1)
{
NativeOnWindowSize(_callbackNativeHandle, _windowWidth, _windowHeight);
}
void RemoveCallback(ICallback callback);
var flags = AWINDOW_REGISTER_FLAGS_SUCCESS;
void SendMouseEvent(int action, int button, int x, int y);
if (_newVideoLayoutListener != null)
flags |= AWINDOW__FLAGS_HAS_VIDEO_LAYOUT_LISTENER;
return flags;
}
}
void SetWindowSize(int width, int height);
[Export("unregisterNative")]
void UnregisterNative()
{
lock (_nativeLock)
{
if(_callbackNativeHandle == 0)
throw new IllegalArgumentException("unregister called when not registered");
_callbackNativeHandle = 0;
}
}
public interface INewVideoLayoutListener
[Export("setBuffersGeometry")]
bool SetBuffersGeometry(Surface surface, int width, int height, int format)
{
/**
* This listener is called when the "android-display" "vout display" module request a new
* video layout. The implementation should take care of changing the surface
* LayoutsParams accordingly. If width and height are 0, LayoutParams should be reset to the
* initial state (MATCH_PARENT).
*
* @param vlcVout vlcVout
* @param width Frame width
* @param height Frame height
* @param visibleWidth Visible frame width
* @param visibleHeight Visible frame height
* @param sarNum Surface aspect ratio numerator
* @param sarDen Surface aspect ratio denominator
*/
void OnNewVideoLayout(IVLCVout vlcVout, int width, int height,
int visibleWidth, int visibleHeight, int sarNum, int sarDen);
// TODO: add implementation if build <= ICS. Not used on newer versions.
return false;
}
public interface ICallback
Surface GetNativeSurface(int id)
{
/// <summary>
/// This callback is called when surfaces are created.
/// </summary>
/// <param name="vlcVout"></param>
void OnSurfaceCreated(IVLCVout vlcVout);
lock (_nativeLock)
{
return _surfaces[id];
}
}
/// <summary>
/// This callback is called when surfaces are destroyed.
/// </summary>
/// <param name="vlcVout"></param>
void OnSurfacesDestroyed(IVLCVout vlcVout);
void SetNativeSurface(int id, Surface surface)
{
lock (_nativeLock)
{
_surfaces[id] = surface;
}
}
public interface ISurfaceCallback
[Export("setVideoLayout")]
void SetVideoLayout(int width, int height, int visibleWidth, int visibleHeight, int sarNum, int sarDen)
{
void OnSurfacesCreated(AWindow vout);
void OnSurfacesDestroyed(AWindow vout);
_handler.Post(() =>
{
_newVideoLayoutListener?.OnNewVideoLayout(this, width, height, visibleWidth, visibleHeight, sarNum,
sarDen);
});
}
class SurfaceTextureThread : Java.Lang.Object, IRunnable, SurfaceTexture.IOnFrameAvailableListener
......@@ -538,7 +521,7 @@ namespace LibVLCSharp.Android.Sample
bool _isAttached;
bool _doRelease;
bool AttachToGLContext(int texName)
internal bool AttachToGLContext(int texName)
{
if (_surfaceTexture == null)
{
......@@ -563,19 +546,11 @@ namespace LibVLCSharp.Android.Sample
return true;
}
public void Dispose()
{
}
public IntPtr Handle { get; }
public void OnFrameAvailable(SurfaceTexture surfaceTexture)
{
if (surfaceTexture == _surfaceTexture)
{
if(_frameAvailable)
if (_frameAvailable)
throw new IllegalStateException("An available frame was not updated");
_frameAvailable = true;
_thread.Notify();
......@@ -600,7 +575,7 @@ namespace LibVLCSharp.Android.Sample
Looper.Loop();
}
void DetachFromGLContext()
internal void DetachFromGLContext()
{
if (!_doRelease)
{
......@@ -627,7 +602,7 @@ namespace LibVLCSharp.Android.Sample
_isAttached = false;
}
bool WaitAndUpdateTexImage(float[] transformMatrix)
internal bool WaitAndUpdateTexImage(float[] transformMatrix)
{
lock (_locker)
{
......@@ -649,7 +624,7 @@ namespace LibVLCSharp.Android.Sample
return true;
}
Surface Surface => _surface;
internal Surface Surface => _surface;
internal void Release()
{
......@@ -668,6 +643,153 @@ namespace LibVLCSharp.Android.Sample
}
}
/// <summary>
/// Attach the SurfaceTexture to the OpenGL ES context that is current on the calling thread.
/// </summary>
/// <param name="texName">the OpenGL texture object name (e.g. generated via glGenTextures)</param>
/// <returns>true in case of success</returns>
[Export]
bool SurfaceTexture_attachToGLContext(int texName) => /*AndroidUtil.isJellyBeanOrLater &&*/ mSurfaceTextureThread.AttachToGLContext(texName);
/// <summary>
/// Detach the SurfaceTexture from the OpenGL ES context that owns the OpenGL ES texture object.
/// </summary>
[Export]
void SurfaceTexture_detachFromGLContext() => mSurfaceTextureThread.DetachFromGLContext();
/// <summary>
/// Wait for a frame and update the TexImage
/// </summary>
/// <param name="transformMatrix"></param>
/// <returns>true on success, false on error or timeout</returns>
//[Export]
bool SurfaceTexture_waitAndUpdateTexImage(float[] transformMatrix)
{
return mSurfaceTextureThread.WaitAndUpdateTexImage(transformMatrix);
}
/// <summary>
/// Get a Surface from the SurfaceTexture
/// </summary>
/// <returns></returns>
[Export]
Surface SurfaceTexture_getSurface() => mSurfaceTextureThread.Surface;
}
public interface IVLCVout
{
/// <summary>
/// Set a surfaceView used for video out.
/// </summary>
/// <param name="videoSurfaceView"></param>
void SetVideoView(SurfaceView videoSurfaceView);
/// <summary>
/// Set a TextureView used for video out.
/// </summary>
/// <param name="videoTextureView"></param>
void SetVideoView(TextureView videoTextureView);
/// <summary>
/// Set a surface used for video out.
/// </summary>
/// <param name="videoSurface">videoSurface if surfaceHolder is null, this surface must be valid and attached.</param>
/// <param name="surfaceHolder">surfaceHolder optional, used to configure buffers geometry before Android ICS and to get notified when surface is destroyed.</param>
void SetVideoSurface(Surface videoSurface, ISurfaceHolder surfaceHolder);
/// <summary>
/// Set a SurfaceTexture used for video out.
/// </summary>
/// <param name="videoSurfaceTexture">this surface must be valid and attached.</param>
void SetVideoSurface(SurfaceTexture videoSurfaceTexture);
/// <summary>
/// Set a surfaceView used for subtitles out.
/// </summary>
/// <param name="subtitlesSurfaceView"></param>
void SetSubtitlesView(SurfaceView subtitlesSurfaceView);
/// <summary>
/// Set a TextureView used for subtitles out.
/// </summary>
/// <param name="subtitlesTextureView"></param>
void SetSubtitlesView(TextureView subtitlesTextureView);
/// <summary>
/// Set a surface used for subtitles out.
/// </summary>
/// <param name="subtitlesSurface">if surfaceHolder is null, this surface must be valid and attached.</param>
/// <param name="surfaceHolder">optional, used to configure buffers geometry before Android ICS and to get notified when surface is destroyed.</param>
void SetSubtitlesSurface(Surface subtitlesSurface, ISurfaceHolder surfaceHolder);
/// <summary>
/// Set a SurfaceTexture used for subtitles out.
/// </summary>
/// <param name="subtitlesSurfaceTexture">this surface must be valid and attached.</param>
void SetSubtitlesSurface(SurfaceTexture subtitlesSurfaceTexture);
/// <summary>
/// Attach views with an OnNewVideoLayoutListener
/// </summary>
/// <param name="onNewVideoLayoutListener"></param>
void AttachViews(INewVideoLayoutListener onNewVideoLayoutListener);
void AttachViews();
void DetachViews();
bool AreViewsAttached { get; }
void AddCallback(ICallback callback);
void RemoveCallback(ICallback callback);
void SendMouseEvent(int action, int button, int x, int y);
void SetWindowSize(int width, int height);
}
public interface INewVideoLayoutListener
{
/**
* This listener is called when the "android-display" "vout display" module request a new
* video layout. The implementation should take care of changing the surface
* LayoutsParams accordingly. If width and height are 0, LayoutParams should be reset to the
* initial state (MATCH_PARENT).
*
* @param vlcVout vlcVout
* @param width Frame width
* @param height Frame height
* @param visibleWidth Visible frame width
* @param visibleHeight Visible frame height
* @param sarNum Surface aspect ratio numerator
* @param sarDen Surface aspect ratio denominator
*/
void OnNewVideoLayout(IVLCVout vlcVout, int width, int height,
int visibleWidth, int visibleHeight, int sarNum, int sarDen);
}
public interface ICallback
{
/// <summary>
/// This callback is called when surfaces are created.
/// </summary>
/// <param name="vlcVout"></param>
void OnSurfaceCreated(IVLCVout vlcVout);
/// <summary>
/// This callback is called when surfaces are destroyed.
/// </summary>
/// <param name="vlcVout"></param>
void OnSurfacesDestroyed(IVLCVout vlcVout);
}
public interface ISurfaceCallback
{
void OnSurfacesCreated(AWindow vout);
void OnSurfacesDestroyed(AWindow vout);
}
class NativeLock
{
public bool BuffersGeometryConfigured;
......
<?xml version="1.0" encoding="utf-8"?>
<Weavers>
</Weavers>
\ No newline at end of file
......@@ -17,22 +17,28 @@
<AndroidResgenClass>Resource</AndroidResgenClass>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
<TargetFrameworkVersion>v7.1</TargetFrameworkVersion>
<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
<MonoAndroidResourcePrefix>Resources</MonoAndroidResourcePrefix>
<MonoAndroidAssetsPrefix>Assets</MonoAndroidAssetsPrefix>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>True</DebugSymbols>
<DebugType>Full</DebugType>
<Optimize>False</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DefineConstants>TRACE;DEBUG;__ANDROID__</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AndroidUseSharedRuntime>True</AndroidUseSharedRuntime>
<AndroidLinkMode>None</AndroidLinkMode>
<EmbedAssembliesIntoApk>False</EmbedAssembliesIntoApk>
<AotAssemblies>false</AotAssemblies>
<EnableLLVM>false</EnableLLVM>
<BundleAssemblies>false</BundleAssemblies>
<AndroidSupportedAbis>armeabi-v7a</AndroidSupportedAbis>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugSymbols>True</DebugSymbols>
......@@ -48,6 +54,10 @@
<EmbedAssembliesIntoApk>True</EmbedAssembliesIntoApk>
</PropertyGroup>
<ItemGroup>
<Reference Include="Cauldron.Interception, Version=2.0.0.29, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Cauldron.Interception.Fody.2.0.29\lib\netstandard2.0\Cauldron.Interception.dll</HintPath>
</Reference>
<Reference Include="Mono.Android.Export" />
<Reference Include="System" />
<Reference Include="System.Xml" />
<Reference Include="System.Core" />
......@@ -60,7 +70,7 @@
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="GettingStarted.Xamarin" />
<None Include="packages.config" />
<None Include="Resources\AboutResources.txt" />
<None Include="Properties\AndroidManifest.xml" />
<None Include="Assets\AboutAssets.txt" />
......@@ -80,7 +90,27 @@
<Folder Include="Resources\mipmap-xxhdpi\" />
<Folder Include="Resources\mipmap-xxxhdpi\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LibVLCSharp.Android\LibVLCSharp.Android.csproj">
<Project>{d549b545-66fe-42db-a7f3-34b67f626fb6}</Project>
<Name>LibVLCSharp.Android</Name>
</ProjectReference>
<ProjectReference Include="..\LibVLCSharp\LibVLCSharp.csproj">
<Project>{d1c3b7c4-713b-46b2-b33a-e9298c819921}</Project>
<Name>LibVLCSharp</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="FodyWeavers.xml" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
<Import Project="..\packages\Fody.2.3.3\build\netstandard1.0\Fody.targets" Condition="Exists('..\packages\Fody.2.3.3\build\netstandard1.0\Fody.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Fody.2.3.3\build\netstandard1.0\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Fody.2.3.3\build\netstandard1.0\Fody.targets'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
......
using Android.App;
using System;
using System.Runtime.InteropServices;
using System.Security;
using Android.App;
using Android.Graphics;
using Android.OS;
using Android.Views;
using Java.Interop;
using VideoLAN.LibVLC;
namespace LibVLCSharp.Android.Sample
{
[Activity(Label = "LibVLCSharp.Android.Sample", MainLauncher = true)]
public class MainActivity : Activity
public class MainActivity : Activity, ICallback
{
Instance _instance;
MediaPlayer _mp;
AWindow _awindow;
SurfaceView _surfaceView;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
JniOnLoad(JniRuntime.CurrentRuntime.InvocationPointer);
_instance = new Instance();
_mp = new MediaPlayer(_instance);
_awindow = new AWindow(new SurfaceCallback(_mp));
_awindow.AddCallback(this);
_surfaceView = FindViewById<SurfaceView>(Resource.Id.surfaceView);
}
protected override void OnResume()
{
base.OnResume();
_awindow.SetVideoView(_surfaceView);
_awindow.AttachViews();
_surfaceView.AddOnLayoutChangeListener(new LayoutChangeListener(_awindow));
_mp.SetAndroidContext(_awindow.Handle);
_mp.Media = new Media(_instance, "http://www.quirksmode.org/html5/videos/big_buck_bunny.mp4", Media.FromType.FromLocation);
_mp.Play();
}
[DllImport("libvlc", EntryPoint = "JNI_OnLoad")]
protected static extern int JniOnLoad(IntPtr javaVm, IntPtr reserved = default(IntPtr));
[SuppressUnmanagedCodeSecurity]
[DllImport("libvlc", CallingConvention = CallingConvention.Cdecl,
EntryPoint = "libvlc_get_version")]
internal static extern IntPtr LibVLCVersion();
Version _dllVersion;
Version DllVersion
{
get
{
if (_dllVersion != null) return _dllVersion;
var version = Marshal.PtrToStringAnsi(LibVLCVersion());
if (string.IsNullOrEmpty(version))
throw new VLCException("Cannot retrieve native dll version");
version = version.Split('-', ' ')[0];
_dllVersion = new Version(version);
return _dllVersion;
}
}
public void OnSurfaceCreated(IVLCVout vlcVout)
{
System.Diagnostics.Debug.WriteLine("OnSurfaceCreated");
}
public void OnSurfacesDestroyed(IVLCVout vlcVout)
{
System.Diagnostics.Debug.WriteLine("OnSurfacesDestroyed");
}
public void OnNewVideoLayout(IVLCVout vlcVout, int width, int height, int visibleWidth, int visibleHeight, int sarNum,
int sarDen)
{
_awindow.SetWindowSize(width, height);
}
public void SurfaceChanged(ISurfaceHolder holder, Format format, int width, int height)
{
}
public void SurfaceCreated(ISurfaceHolder holder)
{
}
public void SurfaceDestroyed(ISurfaceHolder holder)
{
}
}
public class SurfaceCallback : Java.Lang.Object, ISurfaceCallback