// %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%
using System;
using System.Runtime.InteropServices;
using UnityEngine.XR.MagicLeap.Native;
namespace UnityEngine.XR.MagicLeap
{
///
/// APIs for creating and retrieving media format information.
///
public partial class MLMediaFormat
{
///
/// Audio data format for track type.
///
public enum AudioEncoding
{
None = 0,
///
/// Audio data format: PCM 16 bits per sample.
///
PCM16Bits = 2,
///
/// Audio data format: PCM 8 bits per sample.
///
PCM8Bits = 3,
///
/// Audio data format: single-precision floating-point per sample.
///
PCMFloat = 4,
///
/// Audio data format: PCM 32 bits per sample.
///
PCM32Bits = 201,
}
///
/// Handle for the underlying unmanaged object.
///
public ulong Handle { get; private set; }
///
/// Create a video format object.
///
/// Mime type of the content
/// Width of the content in pixels
/// Height of the content in pixels
/// An MLMediaFormat object if successful, null otherwise
public static MLMediaFormat CreateVideo(string mimeType, int width, int height)
{
if (MLResult.DidNativeCallSucceed(NativeBindings.MLMediaFormatCreateVideo(mimeType, width, height, out ulong handle), nameof(NativeBindings.MLMediaFormatCreateVideo)))
{
return new MLMediaFormat(handle);
}
return null;
}
///
/// Create a audio format object.
///
/// Mime type of the content
/// Sample rate of the content
/// Number of audio channels
/// An MLMediaFormat object if successful, null otherwise
public static MLMediaFormat CreateAudio(string mimeType, int sampleRate, int channelCount)
{
if (MLResult.DidNativeCallSucceed(NativeBindings.MLMediaFormatCreateAudio(mimeType, sampleRate, channelCount, out ulong handle), nameof(NativeBindings.MLMediaFormatCreateAudio)))
{
return new MLMediaFormat(handle);
}
return null;
}
///
/// Create a subtitle format object.
///
/// Mime type of the content
/// Language of the content, using either
/// ISO 639-1 or 639-2/T codes. Specify null or "und" if language
/// information is only included in the content.
/// An MLMediaFormat object if successful, null otherwise
public static MLMediaFormat CreateSubtitle(string mimeType, string language)
{
if (MLResult.DidNativeCallSucceed(NativeBindings.MLMediaFormatCreateSubtitle(mimeType, language, out ulong handle), nameof(NativeBindings.MLMediaFormatCreateSubtitle)))
{
return new MLMediaFormat(handle);
}
return null;
}
///
/// Create a copy of the format handle provided.
///
/// This can be particularly useful to persist the media format handle/object that
/// was received through the callbacks(as life cycle of those media format objects
/// are with in the callback context only).
/// The API call to make a copy ensures that the copied object exists until released
/// by the app.
///
/// MLMediaFormat object to copy
/// An MLMediaFormat object if successful, null otherwise
// TODO : can we replace with a "copy-constructor" or Clone() method?
public static MLMediaFormat CreateCopy(MLMediaFormat format)
{
if (MLResult.DidNativeCallSucceed(NativeBindings.MLMediaFormatCreateCopy(format.Handle, out ulong handle), nameof(NativeBindings.MLMediaFormatCreateCopy)))
{
return new MLMediaFormat(handle);
}
return null;
}
///
/// Create an empty format object.
///
/// An MLMediaFormat object if successful, null otherwise
// TODO : replace this with a regular constructor, but then we cant return null value if MLMediaFormatCreate() fails.
public static MLMediaFormat CreateEmpty()
{
if (MLResult.DidNativeCallSucceed(NativeBindings.MLMediaFormatCreate(out ulong handle), nameof(NativeBindings.MLMediaFormatCreate)))
{
return new MLMediaFormat(handle);
}
return null;
}
///
/// Constructor
///
/// Unmanaged handle
internal MLMediaFormat(ulong handle)
{
this.Handle = handle;
}
///
/// Finalizer, destroys unmanaged object.
///
~MLMediaFormat()
{
MLResult.Code resultCode = NativeBindings.MLMediaFormatDestroy(Handle);
MLResult.DidNativeCallSucceed(resultCode, nameof(NativeBindings.MLMediaFormatDestroy));
}
///
/// Human readable representation of the format.
///
/// Human readable representation of the format.
public override string ToString()
{
string objToStr = string.Empty;
IntPtr stringPtr = Marshal.AllocHGlobal(NativeBindings.MAX_FORMAT_STRING_SIZE);
if (MLResult.DidNativeCallSucceed(NativeBindings.MLMediaFormatObjectToString(Handle, stringPtr), nameof(NativeBindings.MLMediaFormatObjectToString)))
{
objToStr = Marshal.PtrToStringAnsi(stringPtr);
}
Marshal.FreeHGlobal(stringPtr);
return objToStr;
}
///
/// Obtain the value of an integer key.
///
/// MLMediaFormatKey name to get the value for
/// Out param to get the value in
/// MLResult.Result.Ok if value was obtained successfully
public MLResult GetValue(string keyName, out int value)
{
MLResult result = MLResult.Create(NativeBindings.MLMediaFormatGetKeyValueInt32(Handle, keyName, out value));
MLResult.DidNativeCallSucceed(result.Result, nameof(NativeBindings.MLMediaFormatGetKeyValueInt32));
return result;
}
///
/// Obtain the value of a long key.
///
/// MLMediaFormatKey name to get the value for
/// Out param to get the value in
/// MLResult.Result.Ok if value was obtained successfully
public MLResult GetValue(string keyName, out long value)
{
MLResult result = MLResult.Create(NativeBindings.MLMediaFormatGetKeyValueInt64(Handle, keyName, out value));
MLResult.DidNativeCallSucceed(result.Result, nameof(NativeBindings.MLMediaFormatGetKeyValueInt64));
return result;
}
///
/// Obtain the value of a float key.
///
/// MLMediaFormatKey name to get the value for
/// Out param to get the value in
/// MLResult.Result.Ok if value was obtained successfully
public MLResult GetValue(string keyName, out float value)
{
MLResult result = MLResult.Create(NativeBindings.MLMediaFormatGetKeyValueFloat(Handle, keyName, out value));
MLResult.DidNativeCallSucceed(result.Result, nameof(NativeBindings.MLMediaFormatGetKeyValueFloat));
return result;
}
///
/// Obtain the value of a string key.
///
/// MLMediaFormatKey name to get the value for
/// Out param to get the value in
/// MLResult.Result.Ok if value was obtained successfully
public MLResult GetValue(string keyName, out string value)
{
value = string.Empty;
IntPtr stringPtr = Marshal.AllocHGlobal(NativeBindings.MAX_KEY_STRING_SIZE);
MLResult result = MLResult.Create(NativeBindings.MLMediaFormatGetKeyString(Handle, keyName, stringPtr));
MLResult.DidNativeCallSucceed(result.Result, nameof(NativeBindings.MLMediaFormatGetKeyString));
if (result.IsOk)
{
value = Marshal.PtrToStringAnsi(stringPtr);
}
Marshal.FreeHGlobal(stringPtr);
return result;
}
///
/// Obtain the value of a byte buffer key.
///
/// MLMediaFormatKey name to get the value for
/// Out param to get the value in
/// MLResult.Result.Ok if value was obtained successfully
public MLResult GetValue(string keyName, out byte[] value)
{
MLResult result = MLResult.Create(NativeBindings.MLMediaFormatGetKeyByteBuffer(Handle, keyName, out NativeBindings.MLMediaFormatByteArray nativeByteBuffer));
MLResult.DidNativeCallSucceed(result.Result, nameof(NativeBindings.MLMediaFormatGetKeyByteBuffer));
if (result.IsOk)
{
value = new byte[nativeByteBuffer.Length];
Marshal.Copy(nativeByteBuffer.Ptr, value, 0, (int)nativeByteBuffer.Length);
MLResult.Code resultCode = NativeBindings.MLMediaFormatKeyByteBufferRelease(Handle, ref nativeByteBuffer);
MLResult.DidNativeCallSucceed(resultCode, nameof(NativeBindings.MLMediaFormatKeyByteBufferRelease));
}
else
{
value = null;
}
return result;
}
///
/// Obtain the value of an unsigned long key.
///
/// MLMediaFormatKey name to get the value for
/// Out param to get the value in
/// MLResult.Result.Ok if value was obtained successfully
public MLResult GetValue(string keyName, out ulong size)
{
MLResult result = MLResult.Create(NativeBindings.MLMediaFormatGetKeySize(Handle, keyName, out size));
MLResult.DidNativeCallSucceed(result.Result, nameof(NativeBindings.MLMediaFormatGetKeySize));
return result;
}
///
/// Set the value of an integer key.
///
/// MLMediaFormatKey name to set the value for
/// Value to set
/// MLResult.Result.Ok if value was set successfully
public MLResult SetValue(string keyName, int value)
{
MLResult result = MLResult.Create(NativeBindings.MLMediaFormatSetKeyInt32(Handle, keyName, value));
MLResult.DidNativeCallSucceed(result.Result, nameof(NativeBindings.MLMediaFormatSetKeyInt32));
return result;
}
///
/// Set the value of a long key.
///
/// MLMediaFormatKey name to set the value for
/// Value to set
/// MLResult.Result.Ok if value was set successfully
public MLResult SetValue(string keyName, long value)
{
MLResult result = MLResult.Create(NativeBindings.MLMediaFormatSetKeyInt64(Handle, keyName, value));
MLResult.DidNativeCallSucceed(result.Result, nameof(NativeBindings.MLMediaFormatSetKeyInt64));
return result;
}
///
/// Set the value of a float key.
///
/// MLMediaFormatKey name to set the value for
/// Value to set
/// MLResult.Result.Ok if value was set successfully
public MLResult SetValue(string keyName, float value)
{
MLResult result = MLResult.Create(NativeBindings.MLMediaFormatSetKeyFloat(Handle, keyName, value));
MLResult.DidNativeCallSucceed(result.Result, nameof(NativeBindings.MLMediaFormatSetKeyFloat));
return result;
}
///
/// Set the value of a string key.
///
/// MLMediaFormatKey name to set the value for
/// Value to set
/// MLResult.Result.Ok if value was set successfully
public MLResult SetValue(string keyName, string value)
{
MLResult result = MLResult.Create(NativeBindings.MLMediaFormatSetKeyString(Handle, keyName, value));
MLResult.DidNativeCallSucceed(result.Result, nameof(NativeBindings.MLMediaFormatSetKeyString));
return result;
}
///
/// Set the value of a byte buffer key.
///
/// MLMediaFormatKey name to set the value for
/// Value to set
/// MLResult.Result.Ok if value was set successfully
public MLResult SetValue(string keyName, byte[] value)
{
IntPtr bufferPtr = Marshal.AllocHGlobal(value.Length);
Marshal.Copy(value, 0, bufferPtr, value.Length);
NativeBindings.MLMediaFormatByteArray nativeBuffer = new NativeBindings.MLMediaFormatByteArray(bufferPtr, (uint)value.Length);
MLResult result = MLResult.Create(NativeBindings.MLMediaFormatSetKeyByteBuffer(Handle, keyName, ref nativeBuffer));
MLResult.DidNativeCallSucceed(result.Result, nameof(NativeBindings.MLMediaFormatSetKeyByteBuffer));
Marshal.FreeHGlobal(bufferPtr);
return result;
}
///
/// Set the value of an unsigned long key.
///
/// MLMediaFormatKey name to set the value for
/// Value to set
/// MLResult.Result.Ok if value was set successfully
public MLResult SetValue(string keyName, ulong size)
{
MLResult result = MLResult.Create(NativeBindings.MLMediaFormatSetKeySize(Handle, keyName, size));
MLResult.DidNativeCallSucceed(result.Result, nameof(NativeBindings.MLMediaFormatSetKeySize));
return result;
}
}
}