// %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; using UnityEngine.XR.MagicLeap.Native; /// /// MLMedia APIs. /// public 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 ParserCEA708 { private class NativeBindings : MagicLeapNativeBindings { public delegate void OnEmitEventDelegate(ulong parserHandle, ref Cea708CaptionEvent captionEvent, IntPtr data); private const int MLCea708CaptionWindowsMax = 8; private const int MLCea708CaptionEmitCommandBufferMaxSize = 20; /// /// CEA708 Caption Color. /// MLCea708CaptionColor from ml_media_cea708_caption.h. /// [StructLayout(LayoutKind.Sequential)] public struct Cea708CaptionColor { /// /// Opacity setting. /// public Cea708CaptionColorOpacity Opacity; /// /// Red component. /// public int Red; /// /// Green component. /// public int Green; /// /// Blue component. /// public int Blue; } /// /// CEA708 Caption Pen Attributes. /// MLCea708CaptionPenAttr from ml_media_cea708_caption.h. /// [StructLayout(LayoutKind.Sequential)] public struct Cea708CaptionPenAttr { /// /// Pen size. /// public Cea708CaptionPenSize PenSize; /// /// Pen offset. /// public Cea708CaptionPenOffset PenOffset; /// /// Text tag. /// public int TextTag; /// /// Font tag. /// public int FontTag; /// /// Edge type. /// public int EdgeType; /// /// Underline setting. /// [MarshalAs(UnmanagedType.I1)] public bool Underline; /// /// Italic setting. /// [MarshalAs(UnmanagedType.I1)] public bool Italic; } /// /// CEA708 Caption Pen Color. /// MLCea708CaptionPenColor from ml_media_cea708_caption.h. /// [StructLayout(LayoutKind.Sequential)] public struct Cea708CaptionPenColor { /// /// Foreground color. /// public Cea708CaptionColor ForegroundColor; /// /// Background color. /// public Cea708CaptionColor BackgroundColor; /// /// Edge color. /// public Cea708CaptionColor EdgeColor; } /// /// CEA708 Caption Pen Location. /// MLCea708CaptionPenLocation from ml_media_cea708_caption.h. /// [StructLayout(LayoutKind.Sequential)] public struct Cea708CaptionPenLocation { /// /// Pen row. /// public int Row; /// /// Pen column. /// public int Column; } /// /// CEA708 Caption Window Attributes. /// MLCea708CaptionWindowAttr from ml_media_cea708_caption.h. /// [StructLayout(LayoutKind.Sequential)] public struct Cea708CaptionWindowAttr { /// /// Window fill color. /// public Cea708CaptionColor FillColor; /// /// Window border color. /// public Cea708CaptionColor BorderColor; /// /// Window border type. /// public int BorderType; /// /// Window word wrap setting. /// [MarshalAs(UnmanagedType.I1)] public bool WordWrap; /// /// Window print direction. /// public int PrintDirection; /// /// Window scroll direction. /// public int ScrollDirection; /// /// Window justification setting. /// public int Justify; /// /// Window effect direction. /// public int EffectDirection; /// /// Window effect speed. /// public int EffectSpeed; /// /// Window display effect. /// public int DisplayEffect; } /// /// CEA708 Caption Window. /// MLCea708CaptionWindow from ml_media_cea708_caption.h. /// [StructLayout(LayoutKind.Sequential)] public struct Cea708CaptionWindow { /// /// Window ID. /// public int ID; /// /// Window visible setting. /// [MarshalAs(UnmanagedType.I1)] public bool Visible; /// /// Window row lock setting. /// [MarshalAs(UnmanagedType.I1)] public bool RowLock; /// /// Window column lock setting. /// [MarshalAs(UnmanagedType.I1)] public bool ColumnLock; /// /// Window Priority. /// public int Priority; /// /// Window relative positioning setting. /// [MarshalAs(UnmanagedType.I1)] public bool RelativePositioning; /// /// Window anchor vertical. /// public int AnchorVertical; /// /// Window anchor horizontal. /// public int AnchorHorizontal; /// /// Window anchor ID. /// public int AnchorID; /// /// Window row count. /// public int RowCount; /// /// Window column count. /// public int ColumnCount; /// /// Window pen style. /// public int PenStyle; /// /// Window style. /// public int WindowStyle; } /// /// Internal CEA708 Caption Event. /// MLCea708CaptionEvent from ml_media_cea708_caption.h. /// [StructLayout(LayoutKind.Sequential)] public struct Cea708CaptionEventInternal { /// /// Emitted CEA708 caption event type. /// public Cea708CaptionEmitCommand Type; /// /// Emitted CEA708 caption event specific data, based on the event type. /// If the type is Cea708CaptionEmitCommand.Buffer, Object will point to a null terminated string of maximum size MLCea708CaptionEmitCommandBufferMaxSize bytes. /// If the type is Cea708CaptionEmitCommand.Control, Object will point to one byte character. /// If the type is Cea708CaptionEmitCommand.CWX, Object will point to an integer. /// If the type is Cea708CaptionEmitCommand.CLW, Object will point to an integer. /// If the type is Cea708CaptionEmitCommand.DSW, Object will point to an integer. /// If the type is Cea708CaptionEmitCommand.HDW, Object will point to an integer. /// If the type is Cea708CaptionEmitCommand.TGW, Object will point to an integer. /// If the type is Cea708CaptionEmitCommand.DLW, Object will point to an integer. /// If the type is Cea708CaptionEmitCommand.DLY, Object will point to an integer. /// If the type is Cea708CaptionEmitCommand.DLC, Object will be NULL. /// If the type is Cea708CaptionEmitCommand.RST, Object will be NULL. /// If the type is Cea708CaptionEmitCommand.SPA, Object will point to Cea708CaptionPenAttr. /// If the type is Cea708CaptionEmitCommand.SPC, Object will point to Cea708CaptionPenColor. /// If the type is Cea708CaptionEmitCommand.SPL, Object will point to Cea708CaptionPenLocation. /// If the type is Cea708CaptionEmitCommand.SWA, Object will point to Cea708CaptionWindowAttr. /// If the type is Cea708CaptionEmitCommand.DFX, Object will point to Cea708CaptionWindow. /// public IntPtr Object; } /// /// CEA708 Caption Event. /// [StructLayout(LayoutKind.Sequential)] public struct Cea708CaptionEvent { /// /// Emitted CEA708 caption event type. /// public Cea708CaptionEmitCommand Type; /// /// Emitted CEA708 caption event specific data, based on the event type. /// If the type is Cea708CaptionEmitCommand.Buffer, Object will be a string. /// If the type is Cea708CaptionEmitCommand.Control, Object will be a byte. /// If the type is Cea708CaptionEmitCommand.CWX, Object will be an integer. /// If the type is Cea708CaptionEmitCommand.CLW, Object will be an integer. /// If the type is Cea708CaptionEmitCommand.DSW, Object will be an integer. /// If the type is Cea708CaptionEmitCommand.HDW, Object will be an integer. /// If the type is Cea708CaptionEmitCommand.TGW, Object will be an integer. /// If the type is Cea708CaptionEmitCommand.DLW, Object will be an integer. /// If the type is Cea708CaptionEmitCommand.DLY, Object will be an integer. /// If the type is Cea708CaptionEmitCommand.DLC, Object will be null. /// If the type is Cea708CaptionEmitCommand.RST, Object will be null. /// If the type is Cea708CaptionEmitCommand.SPA, Object will be a Cea708CaptionPenAttr. /// If the type is Cea708CaptionEmitCommand.SPC, Object will be a Cea708CaptionPenColor. /// If the type is Cea708CaptionEmitCommand.SPL, Object will be a Cea708CaptionPenLocation. /// If the type is Cea708CaptionEmitCommand.SWA, Object will be a Cea708CaptionWindowAttr. /// If the type is Cea708CaptionEmitCommand.DFX, Object will be a Cea708CaptionWindow. /// public IntPtr Data; } [DllImport(MLMediaCEA708DLL, CallingConvention = CallingConvention.Cdecl)] public static extern MLResult.Code MLMediaCea708ParserCreate(out ulong parserHandle); [DllImport(MLMediaCEA708DLL, CallingConvention = CallingConvention.Cdecl)] public static extern MLResult.Code MLMediaCea708ParserDestroy(ulong parserHandle); [DllImport(MLMediaCEA708DLL, CallingConvention = CallingConvention.Cdecl)] public static extern MLResult.Code MLMediaCea708ParserSetEmitEventCallback(ulong parserHandle, OnEmitEventDelegate calback, IntPtr data); [DllImport(MLMediaCEA708DLL, CallingConvention = CallingConvention.Cdecl)] public static extern MLResult.Code MLMediaCea708ParserParse(ulong parserHandle, IntPtr subtitleData, uint subtitleDataSize); /// /// Callback for the OnDisplayChanged event. /// [AOT.MonoPInvokeCallback(typeof(NativeBindings.OnEmitEventDelegate))] public static void OnEmitEvent(ulong parserHandle, ref Cea708CaptionEvent captionEvent, IntPtr data) { GCHandle gcHandle = GCHandle.FromIntPtr(data); ParserCEA708 parser708 = gcHandle.Target as ParserCEA708; if (parser708 == null) { return; } object obj = null; switch (captionEvent.Type) { case MLMedia.ParserCEA708.Cea708CaptionEmitCommand.Buffer: obj = MLConvert.DecodeUTF8(captionEvent.Data, MLCea708CaptionEmitCommandBufferMaxSize); break; case MLMedia.ParserCEA708.Cea708CaptionEmitCommand.Control: obj = Marshal.ReadByte(captionEvent.Data); break; case MLMedia.ParserCEA708.Cea708CaptionEmitCommand.CWX: obj = Marshal.ReadInt32(captionEvent.Data); break; case MLMedia.ParserCEA708.Cea708CaptionEmitCommand.CLW: obj = Marshal.ReadInt32(captionEvent.Data); break; case MLMedia.ParserCEA708.Cea708CaptionEmitCommand.DSW: obj = Marshal.ReadInt32(captionEvent.Data); break; case MLMedia.ParserCEA708.Cea708CaptionEmitCommand.HDW: obj = Marshal.ReadInt32(captionEvent.Data); break; case MLMedia.ParserCEA708.Cea708CaptionEmitCommand.TGW: obj = Marshal.ReadInt32(captionEvent.Data); break; case MLMedia.ParserCEA708.Cea708CaptionEmitCommand.DLW: obj = Marshal.ReadInt32(captionEvent.Data); break; case MLMedia.ParserCEA708.Cea708CaptionEmitCommand.DLY: obj = Marshal.ReadInt32(captionEvent.Data); break; case MLMedia.ParserCEA708.Cea708CaptionEmitCommand.DLC: obj = null; break; case MLMedia.ParserCEA708.Cea708CaptionEmitCommand.RST: obj = null; break; case MLMedia.ParserCEA708.Cea708CaptionEmitCommand.SPA: obj = Marshal.PtrToStructure(captionEvent.Data, typeof(Cea708CaptionPenAttr)); break; case MLMedia.ParserCEA708.Cea708CaptionEmitCommand.SPC: obj = Marshal.PtrToStructure(captionEvent.Data, typeof(Cea708CaptionPenColor)); break; case MLMedia.ParserCEA708.Cea708CaptionEmitCommand.SPL: obj = Marshal.PtrToStructure(captionEvent.Data, typeof(Cea708CaptionPenLocation)); break; case MLMedia.ParserCEA708.Cea708CaptionEmitCommand.SWA: obj = Marshal.PtrToStructure(captionEvent.Data, typeof(Cea708CaptionWindowAttr)); break; case MLMedia.ParserCEA708.Cea708CaptionEmitCommand.DFX: obj = Marshal.PtrToStructure(captionEvent.Data, typeof(Cea708CaptionWindow)); break; } MLThreadDispatch.Call(captionEvent.Type, obj, parser708.OnEmitEvent); int winBitmap; switch (captionEvent.Type) { case MLMedia.ParserCEA708.Cea708CaptionEmitCommand.Buffer: if (parser708.cea708WindowID == -1) { parser708.cea708Strings[0] += (string)obj; parser708.subtitleText = parser708.cea708Strings[0]; MLThreadDispatch.Call(parser708.subtitleText, parser708.OnText); } else { if (parser708.cea708WindowID == 0) { parser708.cea708Strings[0] += (string)obj; parser708.subtitleText = parser708.cea708Strings[0]; MLThreadDispatch.Call(parser708.subtitleText, parser708.OnText); } else if (parser708.cea708WindowID == 1) { parser708.cea708Strings[1] += (string)obj; parser708.subtitleText = parser708.cea708Strings[1]; MLThreadDispatch.Call(parser708.subtitleText, parser708.OnText); } } break; case MLMedia.ParserCEA708.Cea708CaptionEmitCommand.Control: break; case MLMedia.ParserCEA708.Cea708CaptionEmitCommand.CWX: parser708.cea708WindowID = (int)obj; if (parser708.cea708WindowID == 0) { parser708.cea708Strings[0] = string.Empty; } else if (parser708.cea708WindowID == 1) { parser708.cea708Strings[1] = string.Empty; } break; case MLMedia.ParserCEA708.Cea708CaptionEmitCommand.CLW: winBitmap = (int)obj; if (parser708.cea708WindowID == -1) { parser708.cea708Strings[0] = string.Empty; } for (int i = 0; i < MLCea708CaptionWindowsMax; i++) { if ((winBitmap & (1 << i)) != 0) { if (i == 0 || i == 1) { parser708.cea708Strings[i] = string.Empty; } } } break; case MLMedia.ParserCEA708.Cea708CaptionEmitCommand.DSW: winBitmap = (int)obj; break; case MLMedia.ParserCEA708.Cea708CaptionEmitCommand.HDW: winBitmap = (int)obj; break; case MLMedia.ParserCEA708.Cea708CaptionEmitCommand.TGW: break; case MLMedia.ParserCEA708.Cea708CaptionEmitCommand.DLW: winBitmap = (int)obj; for (int i = 0; i < MLCea708CaptionWindowsMax; i++) { if (((winBitmap & (1 << i)) == 0) && (i == 0 || i == 1)) { parser708.cea708Strings[i] = string.Empty; } } break; case MLMedia.ParserCEA708.Cea708CaptionEmitCommand.DLY: break; case MLMedia.ParserCEA708.Cea708CaptionEmitCommand.DLC: break; case MLMedia.ParserCEA708.Cea708CaptionEmitCommand.RST: break; case MLMedia.ParserCEA708.Cea708CaptionEmitCommand.SPA: Cea708CaptionPenAttr pen = (Cea708CaptionPenAttr)obj; break; case MLMedia.ParserCEA708.Cea708CaptionEmitCommand.SPC: Cea708CaptionPenColor penColor = (Cea708CaptionPenColor)obj; break; case MLMedia.ParserCEA708.Cea708CaptionEmitCommand.SPL: Cea708CaptionPenLocation penLoc = (Cea708CaptionPenLocation)obj; break; case MLMedia.ParserCEA708.Cea708CaptionEmitCommand.SWA: Cea708CaptionWindowAttr winAttr = (Cea708CaptionWindowAttr)obj; break; case MLMedia.ParserCEA708.Cea708CaptionEmitCommand.DFX: Cea708CaptionWindow win = (Cea708CaptionWindow)obj; break; default: Debug.LogError("Error: ParserCEA708 unknown event type: " + captionEvent.Type); break; } } } } } }