{"id":842,"date":"2020-11-10T07:44:23","date_gmt":"2020-11-09T21:44:23","guid":{"rendered":"http:\/\/www.nickdu.com\/?p=842"},"modified":"2020-11-10T07:44:23","modified_gmt":"2020-11-09T21:44:23","slug":"unity-bink-player","status":"publish","type":"post","link":"https:\/\/nickdu.com\/?p=842","title":{"rendered":"Unity Bink player"},"content":{"rendered":"\n<p>I have been asked to play a <a rel=\"noreferrer noopener\" href=\"http:\/\/www.radgametools.com\/bnkmain.htm\" data-type=\"URL\" data-id=\"http:\/\/www.radgametools.com\/bnkmain.htm\" target=\"_blank\">bink<\/a> video in <a rel=\"noreferrer noopener\" href=\"https:\/\/unity.com\/\" data-type=\"URL\" data-id=\"https:\/\/unity.com\/\" target=\"_blank\">Unity<\/a>. I googled a lot and couldn&#8217;t find any solution. Then I decided to write my own one and here is my solution to integrate Bink video into Unity.<\/p>\n\n\n\n<p>BinkNativeMethods<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    internal static class BinkNativeMethods\n    {\n        \/\/=======================================================================\n\n        public const ulong BINKOLDFRAMEFORMAT = 0x00008000L; \/\/ using the old Bink frame format (internal use only)\n        public const ulong BINKCUSTOMCOLORSPACE = 0x00010000L; \/\/ file contains a custom colorspace matrix (only internal now)\n\n        public const ulong BINKNOYPLANE = 0x00000200L; \/\/ Don't decompress the Y plane (internal flag)\n        public const ulong BINKWILLLOOP = 0x00000080L; \/\/ You are planning to loop this Bink.\n\n        public const ulong BINKYCRCBNEW = 0x00000010L; \/\/ File uses the new ycrcb colorspace (usually Bink 2)\n        public const ulong BINKHDR = 0x00000004L; \/\/ Video is an HDR video\n        public const ulong BINK_SLICES_2 = 0x00000000L; \/\/ Bink 2 file has two slices\n        public const ulong BINK_SLICES_3 = 0x00000001L; \/\/ Bink 2 file has three slices\n        public const ulong BINK_SLICES_4 = 0x00000002L; \/\/ Bink 2 file has four slices\n        public const ulong BINK_SLICES_8 = 0x00000003L; \/\/ Bink 2 file has eight slices\n        public const ulong BINK_SLICES_MASK = 0x00000003L; \/\/ mask against openflags to get the slice flags\n\n        &#91;DllImport(\"bink2w64\")]\n        internal static extern void BinkClose(IntPtr Bink);\n\n        &#91;DllImport(\"bink2w64\")]\n        internal static extern IntPtr BinkOpen(string name, BINK_OPEN_FLAGS flags);\n\n        &#91;DllImport(\"bink2w64\")]\n        internal static extern string BinkGetError();\n\n        &#91;DllImport(\"bink2w64\")]\n        internal static extern IntPtr BinkDoFrame(IntPtr Bink);\n\n        &#91;DllImport(\"bink2w64\")]\n        internal static extern int BinkWait(IntPtr bink);\n\n        &#91;DllImport(\"bink2w64\")]\n        internal static extern void BinkNextFrame(IntPtr bink);\n\n        &#91;DllImport(\"bink2w64\")]\n        internal static extern int BinkCopyToBuffer(IntPtr bink, byte&#91;] dest_addr, int dest_pitch, uint dest_height, uint dest_x, uint dest_y, BINK_COPY_FLAGS copy_flags);\n\n        public struct BINK\n        {\n            public int Width;\n            public int Height;\n            public uint Frames;\n            public uint FrameNum;\n            public uint FrameRate;\n            public uint FrameRateDiv;\n            public uint ReadError;\n            public BINK_OPEN_FLAGS OpenFlags;\n            public BINKRECT FrameRects;\n            public uint NumRects;\n            public uint FrameChangePercent;\n        };\n\n        public struct BINKRECT\n        {\n            public int Left;\n            public int Top;\n            public int Width;\n            public int Height;\n        };\n\n        public enum BINK_OPEN_FLAGS : ulong\n        {\n            BINKFILEOFFSET = 0x00000020L, \/\/ Use file offset specified by BinkSetFileOffset\n            BINKFILEHANDLE = 0x00800000L, \/\/ Use when passing in a file handle\n            BINKFROMMEMORY = 0x04000000L, \/\/ Use when passing in a pointer to the file\n            BINKNOFRAMEBUFFERS = 0x00000400L, \/\/ Don't allocate internal frame buffers - application must call BinkRegisterFrameBuffers\n            BINKUSETRIPLEBUFFERING = 0x00000008L, \/\/ Use triple buffering in the framebuffers\n            BINKSNDTRACK = 0x00004000L, \/\/ Set the track number to play\n            BINKDONTCLOSETHREADS = 0x00000040L, \/\/ Don't close threads on BinkClose (call BinkFreeGlobals to close threads)\n            BINKGPU = 0x00000100L, \/\/ Open Bink in GPU mode\n            BINKNOSKIP = 0x00080000L, \/\/ Don't skip frames if falling behind\n            BINKPRELOADALL = 0x00002000L, \/\/ Preload the entire animation\n            BINKALPHA = 0x00100000L, \/\/ Decompress alpha plane (if present)\n            BINKGRAYSCALE = 0x00020000L, \/\/ Force Bink to use grayscale\n            BINKFRAMERATE = 0x00001000L, \/\/ Override fr (call BinkFrameRate first)\n            BINKSIMULATE = 0x00400000L, \/\/ Simulate the speed (call BinkSim first)\n            BINKIOSIZE = 0x01000000L, \/\/ Set an io size (call BinkIOSize first)\n            BINKNOFILLIOBUF = 0x00200000L, \/\/ Don't Fill the IO buffer (in BinkOpen and BinkCopyTo)\n            BINKIOPROCESSOR = 0x02000000L, \/\/ Set an io processor (call BinkIO first)\n            BINKNOTHREADEDIO = 0x08000000L \/\/ Don't use a background thread for IO\n        }\n\n        public enum BINK_COPY_FLAGS : ulong\n        {\n            BINKSURFACE32BGRx = 3,\n            BINKSURFACE32RGBx = 4,\n            BINKSURFACE32BGRA = 5,\n            BINKSURFACE32RGBA = 6,\n            BINKSURFACE5551 = 8,\n            BINKSURFACE555 = 9,\n            BINKSURFACE565 = 10,\n            BINKSURFACE32ARGB = 12,\n            BINKSURFACEMASK = 15,\n            BINKGRAYSCALE = 0x00020000L, \/\/ Force Bink to use grayscale\n            BINKNOSKIP = 0x00080000L, \/\/ Don't skip frames if falling behind\n            BINKYAINVERT = 0x00000800L \/\/ Reverse Y and A planes when blitting (for debugging)\n        }\n    }<\/code><\/pre>\n\n\n\n<p>BinkPlayer<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public class BinkPlayer : MonoBehaviour\n{\n    BinkNativeMethods.BINK bk;\n    Texture2D texture;\n    IntPtr bink;\n    byte&#91;] buffer;\n    \/\/ Start is called before the first frame update\n    void Start()\n    {\n        bink = BinkNativeMethods.BinkOpen(\"sample.bk2\", 0);\n\n        bk = Marshal.PtrToStructure&lt;BinkNativeMethods.BINK>(bink);\n\n        texture = new Texture2D(bk.Width, bk.Height, TextureFormat.RGBA32, false);\n        var renderer = GetComponent&lt;SpriteRenderer>();\n        renderer.sprite = Sprite.Create(texture, new Rect(0, 0, bk.Width, bk.Height), Vector2.zero);\n        buffer = new byte&#91;bk.Width * 4 * bk.Height];\n    }\n\n    private void Update()\n    {\n        if (bink != IntPtr.Zero &amp;&amp; BinkNativeMethods.BinkWait(bink) == 0)\n        {\n            BinkNativeMethods.BinkDoFrame(bink);\n            \/\/ do you stuff here\n            BinkNativeMethods.BinkCopyToBuffer(bink, buffer, bk.Width * 3, (uint)bk.Height, 0, 0, BinkNativeMethods.BINK_COPY_FLAGS.BINKSURFACE32RGBA);\n\n            texture.LoadRawTextureData(buffer);\n            texture.Apply();\n            BinkNativeMethods.BinkNextFrame(bink);\n        }\n    }\n}<\/code><\/pre>\n\n\n\n<p>The complete Unity project also can be found at my <a href=\"https:\/\/github.com\/nickdu088\/Bink-Unity-Player\" target=\"_blank\" rel=\"noreferrer noopener\">github<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I have been asked to play a bink video in Unity. I googled a lot and couldn&#8217;t find any solution. Then I decided to write my own one and here is my solution to integrate Bink video into Unity. BinkNativeMethods BinkPlayer The complete Unity project also can be found at my github.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9,2],"tags":[],"class_list":["post-842","post","type-post","status-publish","format-standard","hentry","category-net","category-it"],"_links":{"self":[{"href":"https:\/\/nickdu.com\/index.php?rest_route=\/wp\/v2\/posts\/842","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nickdu.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nickdu.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nickdu.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nickdu.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=842"}],"version-history":[{"count":0,"href":"https:\/\/nickdu.com\/index.php?rest_route=\/wp\/v2\/posts\/842\/revisions"}],"wp:attachment":[{"href":"https:\/\/nickdu.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=842"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nickdu.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=842"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nickdu.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=842"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}