// %BANNER_BEGIN%
// ---------------------------------------------------------------------
// %COPYRIGHT_BEGIN%
// Copyright (c) (2018-2022) Magic Leap, Inc. All Rights Reserved.
// Use of this file is governed by the Software License Agreement, located here: https://www.magicleap.com/software-license-agreement-ml2
// Terms and conditions applicable to third-party materials accompanying this distribution may also be found in the top-level NOTICE file appearing herein.
// %COPYRIGHT_END%
// ---------------------------------------------------------------------
// %BANNER_END%
namespace UnityEngine.XR.MagicLeap
{
using System;
using System.Runtime.InteropServices;
using UnityEngine.XR.MagicLeap.Native;
///
/// MLMedia APIs.
///
public sealed partial class MLMedia
{
///
/// Media player script that allows playback of a streaming video (either from file or web URL)
/// This script will update the main texture parameter of the Renderer attached as a sibling
/// with the video frame from playback. Audio is also handled through this class and will
/// playback audio from the file.
///
public partial class Player
{
///
/// See the MLMediaPlayer native plugin "ml_mediaplayer_plugin.cpp" for additional comments.
///
internal partial class NativeBindings : Native.MagicLeapNativeBindings
{
///
/// Delegate for the OnTimedTextUpdate event.
///
public delegate void OnTimedTextUpdateDelegate(ulong mediaPlayerHandle, ulong timedTextHandle, IntPtr data);
///
/// Delegate for the OnMediaSubtitleUpdate event.
///
public delegate void OnMediaSubtitleUpdateDelegate(ulong mediaPlayerHandle, MLMediaPlayerSubtitleData subtitleData, IntPtr data);
///
/// Delegate for the OnFrameAvailable event
///
public delegate void OnFrameAvailableDelegate(ulong mediaPlayerHandle, IntPtr Data);
///
/// Delegate for the OnVideoSizeChanged event
///
public delegate void OnVideoSizeChangedDelegate(ulong mediaPlayerHandle, ref MLMediaPlayerOnVideoSizeChangedInfo videoSizeInfo);
///
/// Delegate for the OnFramePacking event
///
public delegate void OnFramePackingDelegate(ulong mediaPlayerHandle, IntPtr framePackingInfo);
///
/// Delegate for the OnInfo event
///
public delegate void OnInfoDelegate(ulong mediaPlayerHandle, ref MLMediaPlayerOnInfoInfo info);
///
/// Delegate for the OnPrepared event
///
public delegate void OnPreparedDelegate(ulong mediaPlayerHandle, ref MLMediaPlayerOnPreparedInfo preparedInfo);
///
/// Delegate for the OnBufferingUpdate event
///
public delegate void OnBufferingUpdateDelegate(ulong mediaPlayerHandle, ref MLMediaPlayerOnBufferingUpdateInfo updateInfo);
///
/// Delegate for the OnCompletion event
///
public delegate void OnCompletionDelegate(ulong mediaPlayerHandle, ref MLMediaPlayerOnCompletionInfo completionInfo);
///
/// Delegate for the OnError event
///
public delegate void OnErrorDelegate(ulong mediaPlayerHandle, ref MLMediaPlayerOnErrorInfo errorInfo);
///
/// Delegate for the OnSeekComplete event
///
public delegate void OnSeekCompleteDelegate(ulong mediaPlayerHandle, ref MLMediaPlayerOnSeekCompleteInfo seekCompleteInfo);
///
/// Delegate for the OnTrackDRMInfo event
///
public delegate void OnTrackDRMInfoDelegate(ulong mediaPlayerHandle, ref MLMediaPlayerOnTrackDRMInfo trackDrmInfo);
///
/// Delegate for the OnResetComplete event
///
public delegate void OnResetCompleteDelegate(ulong mediaPlayerHandle, ref MLMediaPlayerOnResetCompleteInfo resetCompleteInfo);
///
/// MediaPlayer Video Size Changed callback Info.
///
[StructLayout(LayoutKind.Sequential)]
public struct MLMediaPlayerOnVideoSizeChangedInfo
{
///
/// The new surface width.
///
public int Width;
///
/// The new surface height.
///
public int Height;
///
/// User data as passed to MLMediaPlayerSetEventCallbacksEx().
///
public IntPtr Data;
};
///
/// MediaPlayer Track Information.
///
[StructLayout(LayoutKind.Sequential)]
public struct MLMediaPlayerTrackInfo
{
///
/// Struct version.
///
public uint Version;
///
/// Media track type, can be either audio or video.
///
public Track.Type TrackType;
public MLMediaPlayerTrackInfo(Track.Type type)
{
this.Version = 1;
this.TrackType = type;
}
};
///
/// MediaPlayer DRM Info for a Media Track.
///
[StructLayout(LayoutKind.Sequential)]
public struct MLMediaPlayerTrackDRMInfo
{
///
/// Number of PSSH entries.
///
public ulong PsshInfoCount;
///
/// Pointer to array of #MLMediaPlayerPSSHEntry of size pssh_info_count.
///
public IntPtr PsshInfo;
///
/// Number of supported DRM UUID entries.
///
public ulong UuidCount;
///
/// Pointer to array of #MLUUID of size uuid_count.
///
public IntPtr UUIDs;
///
/// Media track type, can be either audio or video.
///
public Track.Type TrackType;
public MLMedia.Player.Track.DRM.Info Data
{
get
{
var drmTrackInfo = new MLMedia.Player.Track.DRM.Info();
drmTrackInfo.TrackType = this.TrackType;
drmTrackInfo.UUIDS = ConvertArray(this.UUIDs, this.UuidCount);
drmTrackInfo.PSSHEntries = ConvertArray(this.PsshInfo, this.PsshInfoCount);
return drmTrackInfo;
}
}
};
///
/// PSSH entry.
///
[StructLayout(LayoutKind.Sequential)]
public struct MLMediaPlayerPSSHEntry
{
///
/// 16 bytes UUID specifying crypto scheme.
///
public MagicLeapNativeBindings.MLUUID uuid;
///
/// Size of the data payload.
///
public ulong size;
///
/// Data specific to that scheme.
///
public IntPtr data;
};
///
/// MediaPlayer Playback prepared callback Info.
///
[StructLayout(LayoutKind.Sequential)]
public struct MLMediaPlayerOnPreparedInfo
{
///
/// User data as passed to MLMediaPlayerSetEventCallbacksEx().
///
public IntPtr Data;
};
///
/// MediaPlayer subtitle data.
///
[StructLayout(LayoutKind.Sequential)]
public struct MLMediaPlayerSubtitleData
{
///
/// Index of the track the subtitle is on.
///
public uint TrackIndex;
///
/// Start time of the subtitle.
///
public ulong StartTimeUs;
///
/// Duration of the subtitle.
///
public ulong DurationUs;
///
/// Size of the Data array.
///
public uint DataSize;
///
/// Data of the subtitle.
///
public IntPtr Data;
};
///
/// Indicate the buffering settings.
///
[StructLayout(LayoutKind.Sequential)]
public struct MLMediaPlayerBufferingSettings
{
///
/// For prepare.
///
public BufferingMode InitialBufferingMode;
///
/// For playback.
///
public BufferingMode RebufferingMode;
///
/// Time based.
///
public int InitialWatermarkMs;
///
/// Size based.
///
public int InitialWatermarkKb;
///
/// When cached data is below this mark, playback will be paused for buffering until data reaches
/// |mRebufferingWatermarkHighMs| or end of stream.
///
public int RebufferingWatermarkLowMs;
///
/// When cached data is above this mark, buffering will be paused.
///
public int RebufferingWatermarkHighMs;
///
/// When cached data is below this mark, playback will be paused for buffering until data reaches
/// |mRebufferingWatermarkHighKB| or end of stream.
///
public int RebufferingWatermarkLowKb;
///
/// When cached data is above this mark, buffering will be paused.
///
public int RebufferingWatermarkHighKb;
};
///
/// MediaPlayer Buffering update callback Info.
///
[StructLayout(LayoutKind.Sequential)]
public struct MLMediaPlayerOnBufferingUpdateInfo
{
///
/// The new percentage of buffered content.
///
public int Percent;
///
/// User data as passed to MLMediaPlayerSetEventCallbacksEx().
///
public IntPtr Data;
};
///
/// MediaPlayer Playback completion callback Info.
///
[StructLayout(LayoutKind.Sequential)]
public struct MLMediaPlayerOnCompletionInfo
{
///
/// User data as passed to MLMediaPlayerSetEventCallbacksEx().
///
public IntPtr Data;
};
///
/// MediaPlayer Error callback Info.
///
[StructLayout(LayoutKind.Sequential)]
public struct MLMediaPlayerOnErrorInfo
{
///
/// Error/result code indicating failure reason.
///
public MLResult.Code Result;
///
/// User data as passed to MLMediaPlayerSetEventCallbacksEx().
///
public IntPtr Data;
};
///
/// MediaPlayer Information callback Info.
///
[StructLayout(LayoutKind.Sequential)]
public struct MLMediaPlayerOnInfoInfo
{
///
/// Type of informational event.
///
public Info Info;
///
/// MLMediaPlayerInfo type specific extra information. When info is MLMediaPlayerInfo_NetworkBandwidth, this holds
/// bandwidth in kbps. It is 0 for others.
///
public int Extra;
///
/// User data as passed to MLMediaPlayerSetEventCallbacksEx().
///
public IntPtr Data;
};
///
/// MediaPlayer Playback seek completion callback Info.
///
[StructLayout(LayoutKind.Sequential)]
public struct MLMediaPlayerOnSeekCompleteInfo
{
///
/// User data as passed to MLMediaPlayerSetEventCallbacksEx().
///
public IntPtr Data;
};
///
/// MediaPlayer Track DRM Info callback Info.
///
[StructLayout(LayoutKind.Sequential)]
public struct MLMediaPlayerOnTrackDRMInfo
{
///
/// Pointer to MLMediaPlayerTrackDRMInfo.
///
public IntPtr TrackInfo;
///
/// User data as passed to MLMediaPlayerSetEventCallbacksEx().
///
public IntPtr Data;
};
///
/// MediaPlayer reset completion callback Info.
///
[StructLayout(LayoutKind.Sequential)]
public struct MLMediaPlayerOnResetCompleteInfo
{
///
/// User data as passed to MLMediaPlayerSetEventCallbacksEx().
///
public IntPtr Data;
};
///
/// MediaPlayer frame packing callback Info.
///
[StructLayout(LayoutKind.Sequential)]
public struct MLMediaPlayerOnFramePackingInfo
{
///
/// Frame packing more.
///
public FramePackingMode Mode;
///
/// Frame packing flag.
///
public FramePackingFlags Flags;
///
/// User data as passed to MLMediaPlayerSetEventCallbacksEx().
///
public IntPtr Data;
};
///
/// Callbacks for notifying client about
///
[StructLayout(LayoutKind.Sequential)]
public struct MLMediaPlayerEventCallbacksEx
{
///
/// Struct version.
///
private uint version;
///
/// This callback function is invoked when buffered contents percentage changed.
///
public OnBufferingUpdateDelegate OnBufferingUpdate;
///
/// This callback is invoked when media player played back until end of media and has now come to a stop. Note that this
/// callback does not fire when 'looping = true', because
///
public OnCompletionDelegate OnCompletion;
///
/// This callback function is invoked when media player encounters an error.
///
public OnErrorDelegate OnError;
///
/// This callback function is invoked when
///
public OnInfoDelegate OnInfo;
///
/// This callback is invoked when the player has finished preparing media and is ready to playback.
///
public OnPreparedDelegate OnPrepared;
///
/// This callback function is invoked when a seek operation has completed.
///
public OnSeekCompleteDelegate OnSeekComplete;
///
/// This callback function is invoked when the internal surface has changed size.
///
public OnVideoSizeChangedDelegate OnVideoSizeChanged;
///
/// This callback function is invoked when source has DRM protected media track(s).
///
public OnTrackDRMInfoDelegate OnTrackDRMInfo;
///
/// This callback function is invoked when an async reset operation has completed.
///
public OnResetCompleteDelegate OnResetComplete;
///
/// This callback function is invoked when a stereoscopic video frame packing change.
///
public OnFramePackingDelegate OnFramePacking;
///
/// Create and return an initialized version of this struct.
///
/// A new instance of this struct.
public static MLMediaPlayerEventCallbacksEx Create()
{
return new MLMediaPlayerEventCallbacksEx()
{
version = 2,
OnBufferingUpdate = NativeBindings.OnBufferingUpdate,
OnCompletion = NativeBindings.OnCompletion,
OnError = NativeBindings.OnError,
OnInfo = NativeBindings.OnInfo,
OnPrepared = NativeBindings.OnPrepared,
OnSeekComplete = NativeBindings.OnSeekComplete,
OnVideoSizeChanged = NativeBindings.OnVideoSizeChanged,
OnTrackDRMInfo = NativeBindings.OnTrackDRMInfo,
OnResetComplete = NativeBindings.OnResetComplete,
OnFramePacking = NativeBindings.OnFramePacking
};
}
};
///
/// DRM Session information for a MediaPlayer Track.
///
[StructLayout(LayoutKind.Sequential)]
public struct MLMediaPlayerTrackDRMSessionInfo
{
internal MLMediaPlayerTrackDRMSessionInfo(Track.Type type)
{
this.Version = 1;
this.TrackType = type;
this.Uuid = IntPtr.Zero;
this.SessionId = IntPtr.Zero;
}
internal void AllocResources(MagicLeapNativeBindings.MLUUID uuid, Player.Track.DRM.NativeBindings.MLMediaDRMByteArray sessionId)
{
this.Uuid = Marshal.AllocHGlobal(Marshal.SizeOf());
Marshal.StructureToPtr(uuid, this.Uuid, true);
this.SessionId = Marshal.AllocHGlobal(Marshal.SizeOf());
Marshal.StructureToPtr(sessionId, this.SessionId, true);
}
internal void FreeResources()
{
Marshal.FreeHGlobal(this.Uuid);
Marshal.FreeHGlobal(this.SessionId);
}
public uint Version;
///
/// Media track type, can be either audio or video.
///
public Track.Type TrackType;
///
/// UUID of the DRM Scheme of type #MLUUID.
///
public IntPtr Uuid;
///
/// DRM Session ID of type #MLMediaDRMByteArray.
///
public IntPtr SessionId;
};
///
/// MediaPlayer metrics data.
///
[StructLayout(LayoutKind.Sequential)]
public struct MLMediaPlayerMetrics
{
///
/// The average framerate (fps) of video playback
///
public float AverageFramerate;
///
/// The average bitrate (bps) of video playbac
///
public int AverageVideoBitrate;
///
/// The average bitrate (bps) of audio playbac
///
public int AverageAudioBitrate;
};
public enum TTMLLayoutAlignment : uint
{
Unspecified = 0xFFFFFFFF,
Normal = 0,
Center = 1,
Opposite = 2
}
public enum TTMLLineType : uint
{
Unset = 0xFFFFFFFF,
Fraciton = 0,
Number = 1
}
public enum TTMLAnchorType : uint
{
Unset = 0xFFFFFFFF,
Start = 0,
Middle = 1,
End = 2
}
public enum TTMLTextSizeType : uint
{
Unset = 0xFFFFFFFF,
Fractional = 0,
FractionalIgnorePadding = 1,
Absolute = 2
}
///
/// TTMLData data structure.
///
[StructLayout(LayoutKind.Sequential)]
public struct TTMLImage
{
///
/// Image size in bytes.
///
public ushort Size;
///
/// Byte data of the image.
///
public IntPtr Data;
}
///
/// TTMLData data structure.
///
[StructLayout(LayoutKind.Sequential)]
public struct TTMLData
{
///
/// Track cue start time in milliseconds.
///
long startTimeMs;
///
/// Track cue end time in milliseconds.
///
long endTimeMs;
///
/// The cue text encoded as UTF-8. Or null if this is an image cue.
///
public string text;
///
/// The alignment of the cue text within the cue box.
///
TTMLLayoutAlignment textAlignment;
///
/// The cue image if this is an image cue, an empty image otherwise.
///
TTMLImage bitmap;
///
/// The cue position within the viewport in the direction orthogonal to the writing direction.
///
float line;
///
/// The cue line type.
///
TTMLLineType lineType;
///
/// The cue box anchor in the direction of line.
///
TTMLAnchorType lineAnchor;
///
/// The cue position within the viewport in the direction orthogonal to line.
///
float position;
///
/// The cue box anchor in the direction of position.
///
TTMLAnchorType positionAnchor;
///
/// The cue box size in the writing direction, as a fraction of the viewport size.
///
float size;
///
/// The cue bitmap height as a fraction of the viewport size.
///
float bitmapHeight;
///
/// Whether the cue box has a window color.
///
bool windowColorSet;
///
/// The cue window fill color in ARGB format.
///
uint windowColor;
///
/// The cue default text size type, or MLTTMLTextSizeType_Unset if this cue has no default text size.
///
TTMLTextSizeType textSizeType;
///
/// The cue default text size, or MLTTMLDimen_Unset if this cue has no default.
///
float textSize;
}
public enum WebVTTOrientation
{
Horizontal = 0,
Vertical
}
public enum WebVTTDirection
{
Default = 0,
LeftToRight,
RightToLeft
}
public enum WebVTTAlign
{
Start = 0,
Middle,
End,
Left,
Right
}
///
/// WebVTT data structure.
///
[StructLayout(LayoutKind.Sequential)]
public struct WebVTTData
{
///
/// Track cue start time in milliseconds.
///
public long StartTimeMS;
///
/// Track cue end time in milliseconds.
///
public long EndTimeMs;
///
/// WebVTT file body encoded as UTF-8.
///
[MarshalAs(UnmanagedType.LPStr)]
public string Body;
///
/// A sequence of characters unique amongst all the WebVTT cue identifiers.
///
[MarshalAs(UnmanagedType.LPStr)]
public string Id;
///
/// A boolean indicating whether the line is an integer number of lines.
///
[MarshalAs(UnmanagedType.I1)]
public bool SnapToLines;
///
/// Orientation of the cue.
///
public WebVTTOrientation Orientation;
///
/// The writing direction.
///
public WebVTTDirection Direction;
///
/// Relative cue line position.
///
public float RelativeLinePosition;
///
/// WebVTT cue line number.
///
public int LineNumber;
///
/// The indent of the cue box in the direction defined by the writing direction.
///
public float TextPosition;
///
/// WebVTT cue size.
///
public float Size;
///
/// WebVTT cue text alignment.
///
public WebVTTAlign align;
};
///
/// Converts an unmanged array to a managed array of type T.
///
public static T[] ConvertArray(IntPtr arrayPtr, ulong count)
{
T[] convertedArray = new T[count];
IntPtr walkPtr = arrayPtr;
for (ulong i = 0; i < count; ++i)
{
convertedArray[i] = Marshal.PtrToStructure(walkPtr);
walkPtr = new IntPtr(walkPtr.ToInt64() + Marshal.SizeOf());
}
return convertedArray;
}
///
/// Set callbacks to notify clients about player events. This structure must be initialized by calling
/// MLMediaPlayerEventCallbacksExInit() before use. Client needs to implement the callback functions declared in
/// #MLMediaPlayerEventCallbacksEx, but can set to NULL the ones he does not care about.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerSetEventCallbacksEx(ulong mediaPlayerHandle, [In] ref MLMediaPlayerEventCallbacksEx callbacks, IntPtr Data);
///
/// Create a new
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerCreate(out ulong handle);
///
/// Reset the
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerReset(ulong mediaPlayerHandle);
///
/// Set the 'next'
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerSetNextPlayer(ulong mediaPlayerHandle, ulong NextMediaPlayer);
///
/// Stop playback after playback has been stopped or paused.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerStop(ulong mediaPlayerHandle);
///
/// Set the looping mode of the player.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerSetLooping(ulong mediaPlayerHandle, [MarshalAs(UnmanagedType.I1)] bool loop);
///
/// Return current position of playback.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerGetCurrentPosition(ulong mediaPlayerHandle, out int ms);
///
/// Get the handle of the audio stream.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerGetAudioHandle(ulong mediaPlayerHandle, out ulong handle);
///
/// Prepare DRM for the selected media (either audio or video) track
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerPrepareTrackDRM(ulong mediaPlayerHandle, [In] ref MLMediaPlayerTrackDRMSessionInfo drmSessionInfo);
///
/// Add a timedtext source from a URI.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerAddTimedTextSourceForURI(ulong mediaPlayerHandle, [MarshalAs(UnmanagedType.LPStr)] string Uri, [MarshalAs(UnmanagedType.LPStr)] string MimeType);
///
/// Destroy a MediaPlayer object.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerDestroy(ulong mediaPlayerHandle);
[DllImport(CUtilsDLL, CallingConvention = CallingConvention.Cdecl)]
public static extern void MLUnityQueueMediaPlayerResetAndDestroy(ulong mediaPlayerHandle);
///
/// Set a file descriptor as the data source. The file descriptor must be seekable. It is the caller's responsibility to
/// close the file descriptor. It is safe to do so as soon as this call returns.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerSetDataSourceForFD(ulong mediaPlayerHandle, int Fd);
///
/// Set a file descriptor as the data source with offset. The file descriptor must be seekable. It is the caller's
/// responsibility to close the file descriptor. It is safe to do so as soon as this call returns. This API is useful for
/// specifying playable media located in resource files.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerSetOffsetDataSourceForFD(ulong mediaPlayerHandle, int Fd, long Offset, long Length);
///
/// Set a local file path as the data source. The path should be an absolute path and should reference a world-readable
/// file.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerSetDataSourceForPath(ulong mediaPlayerHandle, [MarshalAs(UnmanagedType.LPStr)] string Path);
///
/// Set a URI string as the data source. Supported URI schemes are `file`, `http`, `https`, and `rtsp`. If looking to
/// provide headers, use MLMediaPlayerSetRemoteDataSourceForURI().
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerSetDataSourceForURI(ulong mediaPlayerHandle, [MarshalAs(UnmanagedType.LPStr)] string Uri);
///
/// Return last info received by internal
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerGetInfo(ulong mediaPlayerHandle, IntPtr OutCode, IntPtr OutExtra);
///
/// Set a URI string as the remote data source. Supported URI schemes are `file`, `http`, `https`, and `rtsp`.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerSetRemoteDataSourceForURI(ulong mediaPlayerHandle, [MarshalAs(UnmanagedType.LPStr)] string Uri, out IntPtr Headers, uint Len);
///
/// Set the data source to use.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerSetMediaStreamSource(ulong mediaPlayerHandle, ulong MediaStreamSource);
///
/// Set the data source to use.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerSetMediaDataSource(ulong mediaPlayerHandle, ulong MediaDataSource);
///
/// Add a timedtext source from a file descriptor. The file descriptor must be seekable. It is the caller's responsibility
/// to close the file descriptor. It is safe to do so as soon as this call returns.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerAddTimedTextSourceForFD(ulong mediaPlayerHandle, int Fd, long Offset, long Length, [MarshalAs(UnmanagedType.LPStr)] string MimeType);
///
/// Return last timed text event information.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerGetTimedText(ulong mediaPlayerHandle, IntPtr OutText, IntPtr OutStart, IntPtr OutEnd);
///
/// Reset the
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerResetAsync(ulong mediaPlayerHandle);
///
/// Prepare the player for playback, synchronously. After setting the data source and the #GraphicBufferProducer, you need
/// to either call prepare() or prepareAsync(). For files, it is OK to call prepare(), which blocks until
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerPrepare(ulong mediaPlayerHandle);
///
/// Prepare the player for playback, asynchronously. After setting the data's source and the #GraphicBufferProducer, you
/// need to either call prepare() or prepareAsync(). For streams, you should call prepareAsync(), which returns immediately,
/// rather than blocking until enough data has been buffered. Prepared state will then be obtained via the 'on_prepared'
/// callback if already registered (see MLMediaPlayerSetEventCallbacksEx), or polled for via the MLMediaPlayerPollStates()
/// call with the MLMediaPlayerPollingStateFlag_HasBeenPrepared flag set.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerPrepareAsync(ulong mediaPlayerHandle);
///
/// Start or resumes playback. If playback had previously been paused, playback will continue from where it was paused. If
/// playback had been stopped, or never started before, playback will start at the beginning.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerStart(ulong mediaPlayerHandle);
///
/// Pause playback. Calling pause() is a NOOP if
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerPause(ulong mediaPlayerHandle);
///
/// Seek to specified time position. Note that SeekTo is an async. function and returns immediately. Successful seek
/// result has to be obtained either via the 'on_seek_complete' if already registered (see MLMediaPlayerSetEventCallbacksEx) or
/// by polling for the flag 'MLMediaPlayerPollingStateFlag_HasSeekCompleted' when calling MLMediaPlayerPollStates().
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerSeekTo(ulong mediaPlayerHandle, int Msec, SeekMode Mode);
///
/// Return the size of the video frame.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerGetVideoSize(ulong mediaPlayerHandle, out int width, out int height);
///
/// Return media duration.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerGetDuration(ulong mediaPlayerHandle, out int durationMS);
///
/// Return current buffering percentage.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerGetBufferingUpdate(ulong mediaPlayerHandle, IntPtr OutPercentage);
///
/// Return last error received by internal
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerGetError(ulong mediaPlayerHandle, IntPtr OutResult);
///
/// Return last subtitle event information.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerGetSubtitleEx(ulong mediaPlayerHandle, IntPtr OutSubtitleData);
///
/// Release last subtitle event information.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerReleaseSubtitleEx(ulong mediaPlayerHandle);
///
/// Set callback to get notified when a subtitle update is available along with its data.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerSetOnMediaSubtitleUpdateCallback(ulong mediaPlayerHandle, OnMediaSubtitleUpdateDelegate OnMediaSubtitleCallback, IntPtr Data);
///
/// Return last metadata event information.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerGetMetadata(ulong mediaPlayerHandle, IntPtr OutTime, IntPtr OutSize, IntPtr OutBuffer);
///
/// Set video scaling mode.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerSetVideoScalingMode(ulong mediaPlayerHandle, VideoScalingMode Mode);
///
/// Set the volume on this player.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerSetVolume(ulong mediaPlayerHandle, float Volume);
///
/// Poll the desired states from internal
/// The "is_XXX" states can be polled multiples times and the return value will
/// be the same if internal state hasn't changed since last call.
/// When polling the "has_XXX" states however, internal state is set to false,
/// since they mean : has happened/changed since I last polled
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerPollStates(ulong mediaPlayerHandle, PollingStateFlags flags, out PollingStateFlags polledStates);
///
/// Get the DRM info of the selected media (either audio or video) track. This function has to be called only after
/// DataSource has been set and the MediaPlayer is completely prepared.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerGetTrackDRMInfo(ulong mediaPlayerHandle, ref MLMediaPlayerTrackInfo trackInfo, ref IntPtr drmInfo);
///
/// Get WebVTT data represented by a timed text handle.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerGetWebVTTData(ulong mediaPlayerHandle, ulong TimedText, ref IntPtr webVTTData);
///
/// Release DRM.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerReleaseDRM(ulong mediaPlayerHandle);
///
/// Get default Buffering settings.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerGetDefaultBufferingSettings(ulong mediaPlayerHandle, IntPtr OutBufSettings);
///
/// Get current Buffering settings.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerGetBufferingSettings(ulong mediaPlayerHandle, IntPtr OutBufSettings);
///
/// Set Buffering settings.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerSetBufferingSettings(ulong mediaPlayerHandle, NativeBindings.MLMediaPlayerBufferingSettings BufSettings);
///
/// Set callback to get invoked when a Timed Text update is available along with its data.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerSetOnMediaTimedTextUpdateCallback(ulong mediaPlayerHandle, OnTimedTextUpdateDelegate OnMediaTimedTextCallback, IntPtr Data);
///
/// Retrieve metrics recorded on the MediaPlayer.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerGetMetrics(ulong mediaPlayerHandle, out MLMediaPlayerMetrics metrics);
///
/// Select a track.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerSelectTrack(ulong mediaPlayerHandle, uint trackIndex);
///
/// Unselect a track.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerUnselectTrack(ulong mediaPlayerHandle, uint trackIndex);
///
/// Count the number of tracks found in the data source.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerGetTrackCount(ulong mediaPlayerHandle, out uint trackCount);
///
/// Get TTML data represented by a timed text handle.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerGetTTMLData(ulong mediaPlayerHandle, ulong timedTextHandle, ref IntPtr ttmlData);
///
/// Sets the Native surface to be used as the sink for displaying the video portion of the media.
///
[DllImport(MLMediaPlayerDll, CallingConvention = CallingConvention.Cdecl)]
public static extern MLResult.Code MLMediaPlayerSetSurface(ulong mediaPlayerHandle, ulong surface);
///
/// Callback for the OnVideoSizeChanged event.
///
[AOT.MonoPInvokeCallback(typeof(NativeBindings.OnVideoSizeChangedDelegate))]
private static void OnVideoSizeChanged(ulong mediaPlayerHandle, ref NativeBindings.MLMediaPlayerOnVideoSizeChangedInfo videoSizeInfo)
{
GCHandle gcHandle = GCHandle.FromIntPtr(videoSizeInfo.Data);
Player mediaPlayer = gcHandle.Target as Player;
var resultCode = NativeBindings.MLMediaPlayerGetVideoSize(mediaPlayer.handle, out int width, out int height);
MLResult.DidNativeCallSucceed(resultCode, nameof(NativeBindings.MLMediaPlayerGetVideoSize));
MLThreadDispatch.Call(mediaPlayer, width, height, mediaPlayer.OnVideoSizeChanged);
}
///
/// Callback for the OnFramePacking event.
///
[AOT.MonoPInvokeCallback(typeof(NativeBindings.OnFramePackingDelegate))]
private static void OnFramePacking(ulong mediaPlayerHandle, IntPtr FramePackingInfo)
{
throw new System.NotImplementedException();
}
///
/// Callback for the OnInfo event.
///
[AOT.MonoPInvokeCallback(typeof(NativeBindings.OnInfoDelegate))]
private static void OnInfo(ulong mediaPlayerHandle, ref NativeBindings.MLMediaPlayerOnInfoInfo info)
{
GCHandle gcHandle = GCHandle.FromIntPtr(info.Data);
Player mediaPlayer = gcHandle.Target as Player;
if (info.Info == Info.MetadataUpdate)
{
MLThreadDispatch.Call(mediaPlayer.GetTracks);
}
MLThreadDispatch.Call(mediaPlayer, info.Info, mediaPlayer.OnInfo);
}
///
/// Callback for the OnPrepared event.
///
[AOT.MonoPInvokeCallback(typeof(NativeBindings.OnPreparedDelegate))]
private static void OnPrepared(ulong mediaPlayerHandle, ref NativeBindings.MLMediaPlayerOnPreparedInfo preparedInfo)
{
GCHandle gcHandle = GCHandle.FromIntPtr(preparedInfo.Data);
Player mediaPlayer = gcHandle.Target as Player;
mediaPlayer.IsPrepared = true;
MLThreadDispatch.Call(mediaPlayer.GetTracks);
MLThreadDispatch.Call(mediaPlayer, mediaPlayer.OnPrepared);
foreach (MLMedia.Player.Track.DRM.Info info in mediaPlayer.drmTrackInfos)
MLThreadDispatch.Call(mediaPlayer, info, mediaPlayer.OnDRMTrackInfo);
}
///
/// Callback for the OnBufferingUpdate event.
///
[AOT.MonoPInvokeCallback(typeof(NativeBindings.OnBufferingUpdateDelegate))]
private static void OnBufferingUpdate(ulong mediaPlayerHandle, ref NativeBindings.MLMediaPlayerOnBufferingUpdateInfo updateInfo)
{
GCHandle gcHandle = GCHandle.FromIntPtr(updateInfo.Data);
Player mediaPlayer = gcHandle.Target as Player;
float percent = updateInfo.Percent;
MLThreadDispatch.Call(mediaPlayer, percent, mediaPlayer.OnBufferingUpdate);
}
///
/// Callback for the OnCompletion event.
///
[AOT.MonoPInvokeCallback(typeof(NativeBindings.OnCompletionDelegate))]
private static void OnCompletion(ulong mediaPlayerHandle, ref NativeBindings.MLMediaPlayerOnCompletionInfo completionInfo)
{
GCHandle gcHandle = GCHandle.FromIntPtr(completionInfo.Data);
Player mediaPlayer = gcHandle.Target as Player;
MLThreadDispatch.Call(mediaPlayer, mediaPlayer.OnCompletion);
}
///
/// Callback for the OnError event.
///
[AOT.MonoPInvokeCallback(typeof(NativeBindings.OnErrorDelegate))]
private static void OnError(ulong mediaPlayerHandle, ref NativeBindings.MLMediaPlayerOnErrorInfo errorInfo)
{
GCHandle gcHandle = GCHandle.FromIntPtr(errorInfo.Data);
Player mediaPlayer = gcHandle.Target as Player;
MLThreadDispatch.Call(mediaPlayer, errorInfo.Result, mediaPlayer.OnError);
}
///
/// Callback for the OnSeekComplete event.
///
[AOT.MonoPInvokeCallback(typeof(NativeBindings.OnSeekCompleteDelegate))]
private static void OnSeekComplete(ulong mediaPlayerHandle, ref NativeBindings.MLMediaPlayerOnSeekCompleteInfo seekCompleteInfo)
{
GCHandle gcHandle = GCHandle.FromIntPtr(seekCompleteInfo.Data);
Player mediaPlayer = gcHandle.Target as Player;
MLThreadDispatch.Call(mediaPlayer, mediaPlayer.OnSeekComplete);
}
///
/// Callback for the OnTrackDRMInfo event. This happens before media player is fully prepared.
///
[AOT.MonoPInvokeCallback(typeof(NativeBindings.OnTrackDRMInfoDelegate))]
private static void OnTrackDRMInfo(ulong mediaPlayerHandle, ref NativeBindings.MLMediaPlayerOnTrackDRMInfo trackDrmInfo)
{
GCHandle gcHandle = GCHandle.FromIntPtr(trackDrmInfo.Data);
Player mediaPlayer = gcHandle.Target as Player;
MLMediaPlayerTrackDRMInfo trackInfo = Marshal.PtrToStructure(trackDrmInfo.TrackInfo);
mediaPlayer.drmTrackInfos.Add(trackInfo.Data);
}
///
/// Callback for the OnResetComplete event.
///
[AOT.MonoPInvokeCallback(typeof(NativeBindings.OnResetCompleteDelegate))]
private static void OnResetComplete(ulong mediaPlayerHandle, ref NativeBindings.MLMediaPlayerOnResetCompleteInfo resetCompleteInfo)
{
GCHandle gcHandle = GCHandle.FromIntPtr(resetCompleteInfo.Data);
Player mediaPlayer = gcHandle.Target as Player;
MLThreadDispatch.Call(mediaPlayer, mediaPlayer.OnResetComplete);
}
///
/// Callback for the OnTimedTextUpdate event.
///
[AOT.MonoPInvokeCallback(typeof(NativeBindings.OnTimedTextUpdateDelegate))]
public static void OnTimedTextUpdate(ulong mediaPlayerHandle, ulong timedTextHandle, IntPtr data)
{
GCHandle gcHandle = GCHandle.FromIntPtr(data);
Player mediaPlayer = gcHandle.Target as Player;
Track selectedTrack = mediaPlayer.trackContainers[Track.Type.TimedText].SelectedTrack;
switch (selectedTrack.MimeType)
{
case VTTMime:
{
var resultCode = NativeBindings.MLMediaPlayerGetWebVTTData(mediaPlayerHandle, timedTextHandle, ref mediaPlayer.WebVTTDataPtr);
MLResult.DidNativeCallSucceed(resultCode, nameof(NativeBindings.MLMediaPlayerGetWebVTTData));
WebVTTData webVTTData = Marshal.PtrToStructure(mediaPlayer.WebVTTDataPtr);
MLThreadDispatch.Call(mediaPlayer, webVTTData.Body, mediaPlayer.OnTimedText);
break;
}
case TTMLMime:
{
var resultCode = NativeBindings.MLMediaPlayerGetTTMLData(mediaPlayerHandle, timedTextHandle, ref mediaPlayer.TTMLDataPtr);
MLResult.DidNativeCallSucceed(resultCode, nameof(NativeBindings.MLMediaPlayerGetTTMLData));
TTMLData ttmlData = Marshal.PtrToStructure(mediaPlayer.TTMLDataPtr);
MLThreadDispatch.Call(mediaPlayer, ttmlData.text, mediaPlayer.OnTimedText);
break;
}
}
}
///
/// Callback for the OnMediaSubtitleUpdate event.
///
[AOT.MonoPInvokeCallback(typeof(NativeBindings.OnMediaSubtitleUpdateDelegate))]
public static void OnMediaSubtitleUpdate(ulong mediaPlayerHandle, MLMediaPlayerSubtitleData subtitleData, IntPtr data)
{
GCHandle gcHandle = GCHandle.FromIntPtr(data);
Player mediaPlayer = gcHandle.Target as Player;
Track selectedTrack = mediaPlayer.trackContainers[Track.Type.Subtitle].SelectedTrack;
// TODO : improve this. We can probably determine the available subtitle track formats once the media is prepared
// and we receive the respective MLMediaFormat objects and only initialize the apt parser.
switch (selectedTrack.MimeType)
{
case ParserCEA608.Mime:
{
mediaPlayer.parser608.ParseAsync(subtitleData.Data, subtitleData.DataSize);
break;
}
case ParserCEA708.Mime:
{
mediaPlayer.parser708.ParseAsync(subtitleData.Data, subtitleData.DataSize);
break;
}
}
}
}
}
}
}