[
  {
    "path": ".gitattributes",
    "content": "* -text\n\n*.cs        text eol=lf diff=csharp\n*.shader    text eol=lf\n*.cginc     text eol=lf\n*.hlsl      text eol=lf\n*.compute   text eol=lf\n\n*.meta      text eol=lf\n\n*.h         text eol=lf\n*.cpp       text eol=lf\n*.cc        text eol=lf\n*.c         text eol=lf\n\n*.plist     text eol=lf\n\n*.sln               text eol=crlf\n*.vcxproj           text eol=crlf\n*.vcxproj.filters   text eol=crlf\n"
  },
  {
    "path": ".gitignore",
    "content": "# Windows\nThumbs.db\nDesktop.ini\n\n# macOS\n.DS_Store\n\n# Code Editors\n/.idea\n/.vscode\n/*.csproj\n/*.sln\n*.swp\n*.vcxproj.user\n\n# Unity\n/Library\n/Logs\n/Recordings\n/Temp\n/UIElementsSchema\n/UserSettings\n\n# Visual Studio\n/Plugin/Windows/.vs\n/Plugin/Windows/x64\n\n# Xcode\nxcuserdata\nxcshareddata\n\n/Plugin/build-*\n/Plugin/MacOS/arm64\n/Plugin/MacOS/x86_64\n/Plugin/MacOS/*.bundle\n/Plugin/*.bundle\n/*.tgz\n\n/Assets/StreamingAssets/*.mov\n/Assets/StreamingAssets/*.mov.meta\n"
  },
  {
    "path": "AGENTS.md",
    "content": "This repository contains a UPM Unity package project. Refer to the following\ndocument for the workflow:\n\nhttps://raw.githubusercontent.com/keijiro/AgentWorkflows/refs/heads/main/upm-workflow.md\n"
  },
  {
    "path": "Assets/Demo/Hap.mat",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!114 &-8186347925687542841\nMonoBehaviour:\n  m_ObjectHideFlags: 11\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 0}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}\n  m_Name: \n  m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Editor::UnityEditor.Rendering.Universal.AssetVersion\n  version: 10\n--- !u!21 &2100000\nMaterial:\n  serializedVersion: 8\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_Name: Hap\n  m_Shader: {fileID: 4800000, guid: 650dd9526735d5b46b79224bc6e94025, type: 3}\n  m_Parent: {fileID: 0}\n  m_ModifiedSerializedProperties: 0\n  m_ValidKeywords: []\n  m_InvalidKeywords: []\n  m_LightmapFlags: 4\n  m_EnableInstancingVariants: 0\n  m_DoubleSidedGI: 0\n  m_CustomRenderQueue: -1\n  stringTagMap:\n    RenderType: Opaque\n  disabledShaderPasses:\n  - MOTIONVECTORS\n  m_LockedProperties: \n  m_SavedProperties:\n    serializedVersion: 3\n    m_TexEnvs:\n    - _BaseMap:\n        m_Texture: {fileID: 8400000, guid: a4f22813f74e84455bd3d9e41d54ced6, type: 2}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - _BumpMap:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - _DetailAlbedoMap:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - _DetailMask:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - _DetailNormalMap:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - _EmissionMap:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - _MainTex:\n        m_Texture: {fileID: 8400000, guid: a4f22813f74e84455bd3d9e41d54ced6, type: 2}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - _MetallicGlossMap:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - _OcclusionMap:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - _ParallaxMap:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - _SpecGlossMap:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - unity_Lightmaps:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - unity_LightmapsInd:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - unity_ShadowMasks:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    m_Ints: []\n    m_Floats:\n    - _AddPrecomputedVelocity: 0\n    - _AlphaClip: 0\n    - _AlphaToMask: 0\n    - _Blend: 0\n    - _BlendModePreserveSpecular: 1\n    - _BlendOp: 0\n    - _BumpScale: 1\n    - _ClearCoatMask: 0\n    - _ClearCoatSmoothness: 0\n    - _Cull: 2\n    - _Cutoff: 0.5\n    - _DetailAlbedoMapScale: 1\n    - _DetailNormalMapScale: 1\n    - _DstBlend: 0\n    - _DstBlendAlpha: 0\n    - _EnvironmentReflections: 1\n    - _GlossMapScale: 0\n    - _Glossiness: 0\n    - _GlossyReflections: 0\n    - _Metallic: 0\n    - _OcclusionStrength: 1\n    - _Parallax: 0.005\n    - _QueueOffset: 0\n    - _ReceiveShadows: 1\n    - _SampleGI: 0\n    - _Smoothness: 0.5\n    - _SmoothnessTextureChannel: 0\n    - _SpecularHighlights: 1\n    - _SrcBlend: 1\n    - _SrcBlendAlpha: 1\n    - _Surface: 0\n    - _WorkflowMode: 1\n    - _XRMotionVectorsPass: 1\n    - _ZWrite: 1\n    m_Colors:\n    - _BaseColor: {r: 1, g: 1, b: 1, a: 1}\n    - _Color: {r: 1, g: 1, b: 1, a: 1}\n    - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}\n    - _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1}\n  m_BuildTextureStacks: []\n  m_AllowLocking: 1\n"
  },
  {
    "path": "Assets/Demo/Hap.mat.meta",
    "content": "fileFormatVersion: 2\nguid: e127fa53264f341caab6ab276ff39b77\nNativeFormatImporter:\n  externalObjects: {}\n  mainObjectFileID: 2100000\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Demo/Hap.renderTexture",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!84 &8400000\nRenderTexture:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_Name: Hap\n  m_ImageContentsHash:\n    serializedVersion: 2\n    Hash: 00000000000000000000000000000000\n  m_IsAlphaChannelOptional: 0\n  serializedVersion: 6\n  m_Width: 1920\n  m_Height: 1080\n  m_AntiAliasing: 1\n  m_MipCount: -1\n  m_DepthStencilFormat: 0\n  m_ColorFormat: 4\n  m_MipMap: 0\n  m_GenerateMips: 1\n  m_SRGB: 1\n  m_UseDynamicScale: 0\n  m_UseDynamicScaleExplicit: 0\n  m_BindMS: 0\n  m_EnableCompatibleFormat: 1\n  m_EnableRandomWrite: 0\n  m_TextureSettings:\n    serializedVersion: 2\n    m_FilterMode: 2\n    m_Aniso: 8\n    m_MipBias: 0\n    m_WrapU: 1\n    m_WrapV: 1\n    m_WrapW: 1\n  m_Dimension: 2\n  m_VolumeDepth: 1\n  m_ShadowSamplingMode: 2\n"
  },
  {
    "path": "Assets/Demo/Hap.renderTexture.meta",
    "content": "fileFormatVersion: 2\nguid: a4f22813f74e84455bd3d9e41d54ced6\nNativeFormatImporter:\n  externalObjects: {}\n  mainObjectFileID: 8400000\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Demo/HapAlpha.mat",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!21 &2100000\nMaterial:\n  serializedVersion: 8\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_Name: HapAlpha\n  m_Shader: {fileID: 4800000, guid: 650dd9526735d5b46b79224bc6e94025, type: 3}\n  m_Parent: {fileID: 0}\n  m_ModifiedSerializedProperties: 0\n  m_ValidKeywords:\n  - _SURFACE_TYPE_TRANSPARENT\n  m_InvalidKeywords: []\n  m_LightmapFlags: 4\n  m_EnableInstancingVariants: 0\n  m_DoubleSidedGI: 0\n  m_CustomRenderQueue: 3000\n  stringTagMap:\n    RenderType: Transparent\n  disabledShaderPasses:\n  - MOTIONVECTORS\n  - DepthOnly\n  - SHADOWCASTER\n  m_LockedProperties: \n  m_SavedProperties:\n    serializedVersion: 3\n    m_TexEnvs:\n    - _BaseMap:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: -1}\n        m_Offset: {x: 0, y: 1}\n    - _BumpMap:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - _DetailAlbedoMap:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - _DetailMask:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - _DetailNormalMap:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - _EmissionMap:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - _MainTex:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: -1}\n        m_Offset: {x: 0, y: 1}\n    - _MetallicGlossMap:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - _OcclusionMap:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - _ParallaxMap:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - _SpecGlossMap:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - unity_Lightmaps:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - unity_LightmapsInd:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - unity_ShadowMasks:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    m_Ints: []\n    m_Floats:\n    - _AddPrecomputedVelocity: 0\n    - _AlphaClip: 0\n    - _AlphaToMask: 0\n    - _Blend: 0\n    - _BlendModePreserveSpecular: 1\n    - _BlendOp: 0\n    - _BumpScale: 1\n    - _ClearCoatMask: 0\n    - _ClearCoatSmoothness: 0\n    - _Cull: 2\n    - _Cutoff: 0.5\n    - _DetailAlbedoMapScale: 1\n    - _DetailNormalMapScale: 1\n    - _DstBlend: 10\n    - _DstBlendAlpha: 10\n    - _EnvironmentReflections: 1\n    - _GlossMapScale: 0\n    - _Glossiness: 0\n    - _GlossyReflections: 0\n    - _Metallic: 0\n    - _OcclusionStrength: 1\n    - _Parallax: 0.005\n    - _QueueOffset: 0\n    - _ReceiveShadows: 1\n    - _SampleGI: 0\n    - _Smoothness: 0.5\n    - _SmoothnessTextureChannel: 0\n    - _SpecularHighlights: 1\n    - _SrcBlend: 5\n    - _SrcBlendAlpha: 1\n    - _Surface: 1\n    - _WorkflowMode: 1\n    - _XRMotionVectorsPass: 1\n    - _ZWrite: 0\n    m_Colors:\n    - _BaseColor: {r: 1, g: 1, b: 1, a: 1}\n    - _Color: {r: 1, g: 1, b: 1, a: 1}\n    - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}\n    - _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1}\n  m_BuildTextureStacks: []\n  m_AllowLocking: 1\n--- !u!114 &4974996350567476565\nMonoBehaviour:\n  m_ObjectHideFlags: 11\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 0}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}\n  m_Name: \n  m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Editor::UnityEditor.Rendering.Universal.AssetVersion\n  version: 10\n"
  },
  {
    "path": "Assets/Demo/HapAlpha.mat.meta",
    "content": "fileFormatVersion: 2\nguid: 6f1182baee9ac4863bd4c5ea5f7d536d\nNativeFormatImporter:\n  externalObjects: {}\n  mainObjectFileID: 2100000\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Demo/HapQ.mat",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!114 &-1545691033646063671\nMonoBehaviour:\n  m_ObjectHideFlags: 11\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 0}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}\n  m_Name: \n  m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Editor::UnityEditor.Rendering.Universal.AssetVersion\n  version: 10\n--- !u!21 &2100000\nMaterial:\n  serializedVersion: 8\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_Name: HapQ\n  m_Shader: {fileID: 4800000, guid: c6a332340608cdd4f907eb4bc0c17f4a, type: 3}\n  m_Parent: {fileID: 0}\n  m_ModifiedSerializedProperties: 0\n  m_ValidKeywords: []\n  m_InvalidKeywords: []\n  m_LightmapFlags: 4\n  m_EnableInstancingVariants: 0\n  m_DoubleSidedGI: 0\n  m_CustomRenderQueue: -1\n  stringTagMap: {}\n  disabledShaderPasses:\n  - MOTIONVECTORS\n  m_LockedProperties: \n  m_SavedProperties:\n    serializedVersion: 3\n    m_TexEnvs:\n    - _BaseMap:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - _BumpMap:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - _DetailAlbedoMap:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - _DetailMask:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - _DetailNormalMap:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - _EmissionMap:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - _MainTex:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - _MetallicGlossMap:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - _OcclusionMap:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - _ParallaxMap:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - _SpecGlossMap:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - unity_Lightmaps:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - unity_LightmapsInd:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    - unity_ShadowMasks:\n        m_Texture: {fileID: 0}\n        m_Scale: {x: 1, y: 1}\n        m_Offset: {x: 0, y: 0}\n    m_Ints: []\n    m_Floats:\n    - _AddPrecomputedVelocity: 0\n    - _AlphaClip: 0\n    - _AlphaToMask: 0\n    - _Blend: 0\n    - _BlendModePreserveSpecular: 1\n    - _BumpScale: 1\n    - _ClearCoatMask: 0\n    - _ClearCoatSmoothness: 0\n    - _Cull: 2\n    - _Cutoff: 0.5\n    - _DetailAlbedoMapScale: 1\n    - _DetailNormalMapScale: 1\n    - _DstBlend: 0\n    - _DstBlendAlpha: 0\n    - _EnvironmentReflections: 1\n    - _GlossMapScale: 0\n    - _Glossiness: 0\n    - _GlossyReflections: 0\n    - _Metallic: 0\n    - _OcclusionStrength: 1\n    - _Parallax: 0.005\n    - _QueueOffset: 0\n    - _ReceiveShadows: 1\n    - _Smoothness: 0.5\n    - _SmoothnessTextureChannel: 0\n    - _SpecularHighlights: 1\n    - _SrcBlend: 1\n    - _SrcBlendAlpha: 1\n    - _Surface: 0\n    - _WorkflowMode: 1\n    - _XRMotionVectorsPass: 1\n    - _ZWrite: 1\n    m_Colors:\n    - _BaseColor: {r: 1, g: 1, b: 1, a: 1}\n    - _Color: {r: 1, g: 1, b: 1, a: 1}\n    - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}\n    - _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1}\n  m_BuildTextureStacks: []\n  m_AllowLocking: 1\n"
  },
  {
    "path": "Assets/Demo/HapQ.mat.meta",
    "content": "fileFormatVersion: 2\nguid: f4060b9dfe1254ee9bb9d4fad7ae4ebd\nNativeFormatImporter:\n  externalObjects: {}\n  mainObjectFileID: 2100000\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Demo/Manifest.asset",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!114 &11400000\nMonoBehaviour:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 0}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: 5acc6266be6eb4130afc5134ec35fcec, type: 3}\n  m_Name: Manifest\n  m_EditorClassIdentifier: KlutterTools.Editor::KlutterTools.Downloader.Manifest\n  <Caption>k__BackingField: 'Test video files are missing:'\n  <FileEntries>k__BackingField:\n  - <SourceUrl>k__BackingField: https://huggingface.co/keijiro-tk/test-videos/resolve/main/Beeple-CleanRoom-Hap.mov\n    <Destination>k__BackingField: Assets/StreamingAssets\n  - <SourceUrl>k__BackingField: https://huggingface.co/keijiro-tk/test-videos/resolve/main/Beeple-FiberOptical-Hap.mov\n    <Destination>k__BackingField: Assets/StreamingAssets\n  - <SourceUrl>k__BackingField: https://huggingface.co/keijiro-tk/test-videos/resolve/main/Beeple-Hexxx-HapQ.mov\n    <Destination>k__BackingField: Assets/StreamingAssets\n  - <SourceUrl>k__BackingField: https://huggingface.co/keijiro-tk/test-videos/resolve/main/TransparencyTest-HapAlpha.mov\n    <Destination>k__BackingField: Assets/StreamingAssets\n"
  },
  {
    "path": "Assets/Demo/Manifest.asset.meta",
    "content": "fileFormatVersion: 2\nguid: 3dac4bcd1e58c42f1b91f538480ebc79\nNativeFormatImporter:\n  externalObjects: {}\n  mainObjectFileID: 11400000\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Demo/ScriptingTest.cs",
    "content": "using UnityEngine;\nusing Klak.Hap;\n\npublic sealed class ScriptingTest : MonoBehaviour\n{\n    [SerializeField] string _filename = \"Test.mov\";\n    [SerializeField] RenderTexture _destination = null;\n    [SerializeField] float _interval = 1;\n    [SerializeField] int _iteration = 10;\n\n    async void Start()\n    {\n        // Create a HAP player instance.\n        var player = gameObject.AddComponent<HapPlayer>();\n\n        // Open the specified HAP video file.\n        player.Open(_filename);\n\n        // Route playback to the destination render texture.\n        player.targetTexture = _destination;\n\n        // Step through playback changes.\n        for (var i = 0; i < _iteration; i++)\n        {\n            // Jump to a random timestamp after each interval.\n            await Awaitable.WaitForSecondsAsync(_interval);\n            player.time = Random.Range(0, (float)player.streamDuration - _interval);\n        }\n\n        // Clean up the player component.\n        Destroy(player);\n    }\n}\n"
  },
  {
    "path": "Assets/Demo/ScriptingTest.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 2c91f3289fa694fe3ba2e1e6149477b8"
  },
  {
    "path": "Assets/Demo/ScriptingTest.renderTexture",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!84 &8400000\nRenderTexture:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_Name: ScriptingTest\n  m_ImageContentsHash:\n    serializedVersion: 2\n    Hash: 00000000000000000000000000000000\n  m_IsAlphaChannelOptional: 0\n  serializedVersion: 6\n  m_Width: 1920\n  m_Height: 1080\n  m_AntiAliasing: 1\n  m_MipCount: -1\n  m_DepthStencilFormat: 0\n  m_ColorFormat: 4\n  m_MipMap: 0\n  m_GenerateMips: 1\n  m_SRGB: 1\n  m_UseDynamicScale: 0\n  m_UseDynamicScaleExplicit: 0\n  m_BindMS: 0\n  m_EnableCompatibleFormat: 1\n  m_EnableRandomWrite: 0\n  m_TextureSettings:\n    serializedVersion: 2\n    m_FilterMode: 1\n    m_Aniso: 0\n    m_MipBias: 0\n    m_WrapU: 1\n    m_WrapV: 1\n    m_WrapW: 1\n  m_Dimension: 2\n  m_VolumeDepth: 1\n  m_ShadowSamplingMode: 2\n"
  },
  {
    "path": "Assets/Demo/ScriptingTest.renderTexture.meta",
    "content": "fileFormatVersion: 2\nguid: 1bba849debc024a4f8251bd62cceac60\nNativeFormatImporter:\n  externalObjects: {}\n  mainObjectFileID: 8400000\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Demo/SeekBarBind.cs",
    "content": "using Unity.Properties;\nusing UnityEngine;\nusing UnityEngine.UIElements;\nusing Klak.Hap;\n\npublic sealed class SeekBarBind : MonoBehaviour\n{\n    [SerializeField] UIDocument _ui = null;\n\n    HapPlayer _player;\n\n    [CreateProperty]\n    public float SeekPoint\n      { get => _player.time;\n        set => _player.time = value; }\n\n    void Start()\n    {\n        _player = GetComponent<HapPlayer>();\n\n        var slider = _ui.rootVisualElement.Q<Slider>(\"seek-bar\");\n        slider.dataSource = this;\n        slider.highValue = (float)_player.streamDuration;\n    }\n}\n"
  },
  {
    "path": "Assets/Demo/SeekBarBind.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 538bb1d7707cb473f8493b44c63286cc"
  },
  {
    "path": "Assets/Demo/UITK/DefaultTheme.tss",
    "content": "@import url(\"unity-theme://default\");"
  },
  {
    "path": "Assets/Demo/UITK/DefaultTheme.tss.meta",
    "content": "fileFormatVersion: 2\nguid: affeaa67622c24c3991a769c52b9c780\nScriptedImporter:\n  internalIDToNameTable: []\n  externalObjects: {}\n  serializedVersion: 2\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n  script: {fileID: 12388, guid: 0000000000000000e000000000000000, type: 0}\n  disableValidation: 0\n  unsupportedSelectorAction: 0\n"
  },
  {
    "path": "Assets/Demo/UITK/Demo.uxml",
    "content": "<ui:UXML xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:ui=\"UnityEngine.UIElements\" xmlns:uie=\"UnityEditor.UIElements\" noNamespaceSchemaLocation=\"../UIElementsSchema/UIElements.xsd\" editor-extension-mode=\"False\">\n    <ui:Slider name=\"seek-bar\" data-source-type=\"SeekBarBind, Assembly-CSharp\">\n        <Bindings>\n            <ui:DataBinding property=\"value\" data-source-path=\"SeekPoint\" binding-mode=\"TwoWay\"/>\n        </Bindings>\n    </ui:Slider>\n    <ui:VisualElement style=\"position: absolute; left: 10px; bottom: 10px; width: 160px; height: 90px; background-image: url(&quot;project://database/Assets/Demo/ScriptingTest.renderTexture?fileID=8400000&amp;guid=1bba849debc024a4f8251bd62cceac60&amp;type=2#ScriptingTest&quot;);\"/>\n</ui:UXML>\n"
  },
  {
    "path": "Assets/Demo/UITK/Demo.uxml.meta",
    "content": "fileFormatVersion: 2\nguid: f9d1722b31b6d45a8b38e8167775d54d\nScriptedImporter:\n  internalIDToNameTable: []\n  externalObjects: {}\n  serializedVersion: 2\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n  script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}\n"
  },
  {
    "path": "Assets/Demo/UITK/PanelSettings.asset",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!114 &11400000\nMonoBehaviour:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 0}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 19101, guid: 0000000000000000e000000000000000, type: 0}\n  m_Name: PanelSettings\n  m_EditorClassIdentifier: UnityEngine.dll::UnityEngine.UIElements.PanelSettings\n  themeUss: {fileID: -4733365628477956816, guid: affeaa67622c24c3991a769c52b9c780, type: 3}\n  m_DisableNoThemeWarning: 0\n  m_TargetTexture: {fileID: 0}\n  m_RenderMode: 0\n  m_ColliderUpdateMode: 0\n  m_ColliderIsTrigger: 1\n  m_ScaleMode: 1\n  m_ReferenceSpritePixelsPerUnit: 100\n  m_PixelsPerUnit: 100\n  m_Scale: 1\n  m_ReferenceDpi: 96\n  m_FallbackDpi: 96\n  m_ReferenceResolution: {x: 1200, y: 800}\n  m_ScreenMatchMode: 0\n  m_Match: 0\n  m_SortingOrder: 0\n  m_TargetDisplay: 0\n  m_BindingLogLevel: 0\n  m_ClearDepthStencil: 1\n  m_ClearColor: 0\n  m_ColorClearValue: {r: 0, g: 0, b: 0, a: 0}\n  m_VertexBudget: 0\n  m_TextureSlotCount: 8\n  m_DynamicAtlasSettings:\n    m_MinAtlasSize: 64\n    m_MaxAtlasSize: 4096\n    m_MaxSubTextureSize: 64\n    m_ActiveFilters: -1\n  m_AtlasBlitShader: {fileID: 9101, guid: 0000000000000000f000000000000000, type: 0}\n  m_DefaultShader: {fileID: 9100, guid: 0000000000000000f000000000000000, type: 0}\n  m_RuntimeGaussianBlurShader: {fileID: 20300, guid: 0000000000000000f000000000000000, type: 0}\n  m_RuntimeColorEffectShader: {fileID: 20301, guid: 0000000000000000f000000000000000, type: 0}\n  m_SDFShader: {fileID: 19011, guid: 0000000000000000f000000000000000, type: 0}\n  m_BitmapShader: {fileID: 9001, guid: 0000000000000000f000000000000000, type: 0}\n  m_SpriteShader: {fileID: 19012, guid: 0000000000000000f000000000000000, type: 0}\n  m_ICUDataAsset: {fileID: 0}\n  forceGammaRendering: 0\n  textSettings: {fileID: 0}\n"
  },
  {
    "path": "Assets/Demo/UITK/PanelSettings.asset.meta",
    "content": "fileFormatVersion: 2\nguid: 217443c668dc34029b583fa73e5c4dfc\nNativeFormatImporter:\n  externalObjects: {}\n  mainObjectFileID: 11400000\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Demo/UITK.meta",
    "content": "fileFormatVersion: 2\nguid: 231a2176bf9354a2aaa754fd16e8e95e\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Demo/URP/DefaultRenderer.asset",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!114 &11400000\nMonoBehaviour:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 0}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: de640fe3d0db1804a85f9fc8f5cadab6, type: 3}\n  m_Name: DefaultRenderer\n  m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.UniversalRendererData\n  debugShaders:\n    debugReplacementPS: {fileID: 4800000, guid: cf852408f2e174538bcd9b7fda1c5ae7, type: 3}\n    hdrDebugViewPS: {fileID: 4800000, guid: 573620ae32aec764abd4d728906d2587, type: 3}\n    probeVolumeSamplingDebugComputeShader: {fileID: 7200000, guid: 53626a513ea68ce47b59dc1299fe3959, type: 3}\n  probeVolumeResources:\n    probeVolumeDebugShader: {fileID: 0}\n    probeVolumeFragmentationDebugShader: {fileID: 0}\n    probeVolumeOffsetDebugShader: {fileID: 0}\n    probeVolumeSamplingDebugShader: {fileID: 0}\n    probeSamplingDebugMesh: {fileID: 0}\n    probeSamplingDebugTexture: {fileID: 0}\n    probeVolumeBlendStatesCS: {fileID: 0}\n  m_RendererFeatures: []\n  m_RendererFeatureMap: \n  m_UseNativeRenderPass: 0\n  postProcessData: {fileID: 11400000, guid: 41439944d30ece34e96484bdb6645b55, type: 2}\n  m_AssetVersion: 3\n  m_PrepassLayerMask:\n    serializedVersion: 2\n    m_Bits: 4294967295\n  m_OpaqueLayerMask:\n    serializedVersion: 2\n    m_Bits: 4294967295\n  m_TransparentLayerMask:\n    serializedVersion: 2\n    m_Bits: 4294967295\n  m_DefaultStencilState:\n    overrideStencilState: 0\n    stencilReference: 0\n    stencilCompareFunction: 8\n    passOperation: 2\n    failOperation: 0\n    zFailOperation: 0\n  m_ShadowTransparentReceive: 1\n  m_RenderingMode: 0\n  m_DepthPrimingMode: 0\n  m_CopyDepthMode: 1\n  m_DepthAttachmentFormat: 0\n  m_DepthTextureFormat: 0\n  m_AccurateGbufferNormals: 0\n  m_IntermediateTextureMode: 1\n"
  },
  {
    "path": "Assets/Demo/URP/DefaultRenderer.asset.meta",
    "content": "fileFormatVersion: 2\nguid: e707f25f3295f48408bbc74cefc67e0d\nNativeFormatImporter:\n  externalObjects: {}\n  mainObjectFileID: 11400000\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Demo/URP/DefaultVolume.asset",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!114 &-8324776220157134924\nMonoBehaviour:\n  m_ObjectHideFlags: 3\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 0}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: 5485954d14dfb9a4c8ead8edb0ded5b1, type: 3}\n  m_Name: LiftGammaGain\n  m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.LiftGammaGain\n  active: 1\n  lift:\n    m_OverrideState: 1\n    m_Value: {x: 1, y: 1, z: 1, w: 0}\n  gamma:\n    m_OverrideState: 1\n    m_Value: {x: 1, y: 1, z: 1, w: 0}\n  gain:\n    m_OverrideState: 1\n    m_Value: {x: 1, y: 1, z: 1, w: 0}\n--- !u!114 &-4854300222326862063\nMonoBehaviour:\n  m_ObjectHideFlags: 3\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 0}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: 70afe9e12c7a7ed47911bb608a23a8ff, type: 3}\n  m_Name: SplitToning\n  m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.SplitToning\n  active: 1\n  shadows:\n    m_OverrideState: 1\n    m_Value: {r: 0.5, g: 0.5, b: 0.5, a: 1}\n  highlights:\n    m_OverrideState: 1\n    m_Value: {r: 0.5, g: 0.5, b: 0.5, a: 1}\n  balance:\n    m_OverrideState: 1\n    m_Value: 0\n--- !u!114 &-4422322214415224032\nMonoBehaviour:\n  m_ObjectHideFlags: 3\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 0}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: 899c54efeace73346a0a16faa3afe726, type: 3}\n  m_Name: Vignette\n  m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.Vignette\n  active: 1\n  color:\n    m_OverrideState: 1\n    m_Value: {r: 0, g: 0, b: 0, a: 1}\n  center:\n    m_OverrideState: 1\n    m_Value: {x: 0.5, y: 0.5}\n  intensity:\n    m_OverrideState: 1\n    m_Value: 0\n  smoothness:\n    m_OverrideState: 1\n    m_Value: 0.2\n  rounded:\n    m_OverrideState: 1\n    m_Value: 0\n--- !u!114 &-4084026468743712817\nMonoBehaviour:\n  m_ObjectHideFlags: 3\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 0}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: 81180773991d8724ab7f2d216912b564, type: 3}\n  m_Name: ChromaticAberration\n  m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.ChromaticAberration\n  active: 1\n  intensity:\n    m_OverrideState: 1\n    m_Value: 0\n--- !u!114 &-4056193433038019785\nMonoBehaviour:\n  m_ObjectHideFlags: 3\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 0}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: fb60a22f311433c4c962b888d1393f88, type: 3}\n  m_Name: PaniniProjection\n  m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.PaniniProjection\n  active: 1\n  distance:\n    m_OverrideState: 1\n    m_Value: 0\n  cropToFit:\n    m_OverrideState: 1\n    m_Value: 1\n--- !u!114 &-1795136986949859044\nMonoBehaviour:\n  m_ObjectHideFlags: 3\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 0}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: 06437c1ff663d574d9447842ba0a72e4, type: 3}\n  m_Name: ScreenSpaceLensFlare\n  m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.ScreenSpaceLensFlare\n  active: 1\n  intensity:\n    m_OverrideState: 1\n    m_Value: 0\n  tintColor:\n    m_OverrideState: 1\n    m_Value: {r: 1, g: 1, b: 1, a: 1}\n  bloomMip:\n    m_OverrideState: 1\n    m_Value: 1\n  firstFlareIntensity:\n    m_OverrideState: 1\n    m_Value: 1\n  secondaryFlareIntensity:\n    m_OverrideState: 1\n    m_Value: 1\n  warpedFlareIntensity:\n    m_OverrideState: 1\n    m_Value: 1\n  warpedFlareScale:\n    m_OverrideState: 1\n    m_Value: {x: 1, y: 1}\n  samples:\n    m_OverrideState: 1\n    m_Value: 1\n  sampleDimmer:\n    m_OverrideState: 1\n    m_Value: 0.5\n  vignetteEffect:\n    m_OverrideState: 1\n    m_Value: 1\n  startingPosition:\n    m_OverrideState: 1\n    m_Value: 1.25\n  scale:\n    m_OverrideState: 1\n    m_Value: 1.5\n  streaksIntensity:\n    m_OverrideState: 1\n    m_Value: 0\n  streaksLength:\n    m_OverrideState: 1\n    m_Value: 0.5\n  streaksOrientation:\n    m_OverrideState: 1\n    m_Value: 0\n  streaksThreshold:\n    m_OverrideState: 1\n    m_Value: 0.25\n  resolution:\n    m_OverrideState: 1\n    m_Value: 4\n  chromaticAbberationIntensity:\n    m_OverrideState: 1\n    m_Value: 0.5\n--- !u!114 &-598097793118719588\nMonoBehaviour:\n  m_ObjectHideFlags: 3\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 0}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: e021b4c809a781e468c2988c016ebbea, type: 3}\n  m_Name: ColorLookup\n  m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.ColorLookup\n  active: 1\n  texture:\n    m_OverrideState: 1\n    m_Value: {fileID: 0}\n    dimension: 1\n  contribution:\n    m_OverrideState: 1\n    m_Value: 0\n--- !u!114 &-491638309231600550\nMonoBehaviour:\n  m_ObjectHideFlags: 3\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 0}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: 29fa0085f50d5e54f8144f766051a691, type: 3}\n  m_Name: FilmGrain\n  m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.FilmGrain\n  active: 1\n  type:\n    m_OverrideState: 1\n    m_Value: 0\n  intensity:\n    m_OverrideState: 1\n    m_Value: 0\n  response:\n    m_OverrideState: 1\n    m_Value: 0.8\n  texture:\n    m_OverrideState: 1\n    m_Value: {fileID: 0}\n--- !u!114 &-262398843821731637\nMonoBehaviour:\n  m_ObjectHideFlags: 3\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 0}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: 0b2db86121404754db890f4c8dfe81b2, type: 3}\n  m_Name: Bloom\n  m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.Bloom\n  active: 1\n  skipIterations:\n    m_OverrideState: 1\n    m_Value: 1\n  threshold:\n    m_OverrideState: 1\n    m_Value: 0.9\n  intensity:\n    m_OverrideState: 1\n    m_Value: 0\n  scatter:\n    m_OverrideState: 1\n    m_Value: 0.7\n  clamp:\n    m_OverrideState: 1\n    m_Value: 65472\n  tint:\n    m_OverrideState: 1\n    m_Value: {r: 1, g: 1, b: 1, a: 1}\n  highQualityFiltering:\n    m_OverrideState: 1\n    m_Value: 0\n  filter:\n    m_OverrideState: 1\n    m_Value: 0\n  downscale:\n    m_OverrideState: 1\n    m_Value: 0\n  maxIterations:\n    m_OverrideState: 1\n    m_Value: 6\n  dirtTexture:\n    m_OverrideState: 1\n    m_Value: {fileID: 0}\n    dimension: 1\n  dirtIntensity:\n    m_OverrideState: 1\n    m_Value: 0\n--- !u!114 &11400000\nMonoBehaviour:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 0}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: d7fd9488000d3734a9e00ee676215985, type: 3}\n  m_Name: DefaultVolume\n  m_EditorClassIdentifier: Unity.RenderPipelines.Core.Runtime::UnityEngine.Rendering.VolumeProfile\n  components:\n  - {fileID: 451328866785996911}\n  - {fileID: 8855959688280746896}\n  - {fileID: 4256406320919580142}\n  - {fileID: 2026760357700040227}\n  - {fileID: 8862907471677848668}\n  - {fileID: -4422322214415224032}\n  - {fileID: -8324776220157134924}\n  - {fileID: -1795136986949859044}\n  - {fileID: 3728775241584703705}\n  - {fileID: -4854300222326862063}\n  - {fileID: -262398843821731637}\n  - {fileID: 1801325758739867974}\n  - {fileID: -4056193433038019785}\n  - {fileID: -4084026468743712817}\n  - {fileID: 5078066985263128679}\n  - {fileID: -491638309231600550}\n  - {fileID: 1585749192924285193}\n  - {fileID: -598097793118719588}\n  - {fileID: 5892942527586337604}\n--- !u!114 &451328866785996911\nMonoBehaviour:\n  m_ObjectHideFlags: 3\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 0}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: 558a8e2b6826cf840aae193990ba9f2e, type: 3}\n  m_Name: ShadowsMidtonesHighlights\n  m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.ShadowsMidtonesHighlights\n  active: 1\n  shadows:\n    m_OverrideState: 1\n    m_Value: {x: 1, y: 1, z: 1, w: 0}\n  midtones:\n    m_OverrideState: 1\n    m_Value: {x: 1, y: 1, z: 1, w: 0}\n  highlights:\n    m_OverrideState: 1\n    m_Value: {x: 1, y: 1, z: 1, w: 0}\n  shadowsStart:\n    m_OverrideState: 1\n    m_Value: 0\n  shadowsEnd:\n    m_OverrideState: 1\n    m_Value: 0.3\n  highlightsStart:\n    m_OverrideState: 1\n    m_Value: 0.55\n  highlightsEnd:\n    m_OverrideState: 1\n    m_Value: 1\n--- !u!114 &1585749192924285193\nMonoBehaviour:\n  m_ObjectHideFlags: 3\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 0}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: 221518ef91623a7438a71fef23660601, type: 3}\n  m_Name: WhiteBalance\n  m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.WhiteBalance\n  active: 1\n  temperature:\n    m_OverrideState: 1\n    m_Value: 0\n  tint:\n    m_OverrideState: 1\n    m_Value: 0\n--- !u!114 &1801325758739867974\nMonoBehaviour:\n  m_ObjectHideFlags: 3\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 0}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: 66f335fb1ffd8684294ad653bf1c7564, type: 3}\n  m_Name: ColorAdjustments\n  m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.ColorAdjustments\n  active: 1\n  postExposure:\n    m_OverrideState: 1\n    m_Value: 0\n  contrast:\n    m_OverrideState: 1\n    m_Value: 0\n  colorFilter:\n    m_OverrideState: 1\n    m_Value: {r: 1, g: 1, b: 1, a: 1}\n  hueShift:\n    m_OverrideState: 1\n    m_Value: 0\n  saturation:\n    m_OverrideState: 1\n    m_Value: 0\n--- !u!114 &2026760357700040227\nMonoBehaviour:\n  m_ObjectHideFlags: 3\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 0}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: c01700fd266d6914ababb731e09af2eb, type: 3}\n  m_Name: DepthOfField\n  m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.DepthOfField\n  active: 1\n  mode:\n    m_OverrideState: 1\n    m_Value: 0\n  gaussianStart:\n    m_OverrideState: 1\n    m_Value: 10\n  gaussianEnd:\n    m_OverrideState: 1\n    m_Value: 30\n  gaussianMaxRadius:\n    m_OverrideState: 1\n    m_Value: 1\n  highQualitySampling:\n    m_OverrideState: 1\n    m_Value: 0\n  focusDistance:\n    m_OverrideState: 1\n    m_Value: 10\n  aperture:\n    m_OverrideState: 1\n    m_Value: 5.6\n  focalLength:\n    m_OverrideState: 1\n    m_Value: 50\n  bladeCount:\n    m_OverrideState: 1\n    m_Value: 5\n  bladeCurvature:\n    m_OverrideState: 1\n    m_Value: 1\n  bladeRotation:\n    m_OverrideState: 1\n    m_Value: 0\n--- !u!114 &3728775241584703705\nMonoBehaviour:\n  m_ObjectHideFlags: 3\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 0}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: c5e1dc532bcb41949b58bc4f2abfbb7e, type: 3}\n  m_Name: LensDistortion\n  m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.LensDistortion\n  active: 1\n  intensity:\n    m_OverrideState: 1\n    m_Value: 0\n  xMultiplier:\n    m_OverrideState: 1\n    m_Value: 1\n  yMultiplier:\n    m_OverrideState: 1\n    m_Value: 1\n  center:\n    m_OverrideState: 1\n    m_Value: {x: 0.5, y: 0.5}\n  scale:\n    m_OverrideState: 1\n    m_Value: 1\n--- !u!114 &4256406320919580142\nMonoBehaviour:\n  m_ObjectHideFlags: 3\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 0}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: 3eb4b772797da9440885e8bd939e9560, type: 3}\n  m_Name: ColorCurves\n  m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.ColorCurves\n  active: 1\n  master:\n    m_OverrideState: 1\n    m_Value:\n      <length>k__BackingField: 2\n      m_Loop: 0\n      m_ZeroValue: 0\n      m_Range: 1\n      m_Curve:\n        serializedVersion: 2\n        m_Curve:\n        - serializedVersion: 3\n          time: 0\n          value: 0\n          inSlope: 1\n          outSlope: 1\n          tangentMode: 0\n          weightedMode: 0\n          inWeight: 0\n          outWeight: 0\n        - serializedVersion: 3\n          time: 1\n          value: 1\n          inSlope: 1\n          outSlope: 1\n          tangentMode: 0\n          weightedMode: 0\n          inWeight: 0\n          outWeight: 0\n        m_PreInfinity: 2\n        m_PostInfinity: 2\n        m_RotationOrder: 4\n  red:\n    m_OverrideState: 1\n    m_Value:\n      <length>k__BackingField: 2\n      m_Loop: 0\n      m_ZeroValue: 0\n      m_Range: 1\n      m_Curve:\n        serializedVersion: 2\n        m_Curve:\n        - serializedVersion: 3\n          time: 0\n          value: 0\n          inSlope: 1\n          outSlope: 1\n          tangentMode: 0\n          weightedMode: 0\n          inWeight: 0\n          outWeight: 0\n        - serializedVersion: 3\n          time: 1\n          value: 1\n          inSlope: 1\n          outSlope: 1\n          tangentMode: 0\n          weightedMode: 0\n          inWeight: 0\n          outWeight: 0\n        m_PreInfinity: 2\n        m_PostInfinity: 2\n        m_RotationOrder: 4\n  green:\n    m_OverrideState: 1\n    m_Value:\n      <length>k__BackingField: 2\n      m_Loop: 0\n      m_ZeroValue: 0\n      m_Range: 1\n      m_Curve:\n        serializedVersion: 2\n        m_Curve:\n        - serializedVersion: 3\n          time: 0\n          value: 0\n          inSlope: 1\n          outSlope: 1\n          tangentMode: 0\n          weightedMode: 0\n          inWeight: 0\n          outWeight: 0\n        - serializedVersion: 3\n          time: 1\n          value: 1\n          inSlope: 1\n          outSlope: 1\n          tangentMode: 0\n          weightedMode: 0\n          inWeight: 0\n          outWeight: 0\n        m_PreInfinity: 2\n        m_PostInfinity: 2\n        m_RotationOrder: 4\n  blue:\n    m_OverrideState: 1\n    m_Value:\n      <length>k__BackingField: 2\n      m_Loop: 0\n      m_ZeroValue: 0\n      m_Range: 1\n      m_Curve:\n        serializedVersion: 2\n        m_Curve:\n        - serializedVersion: 3\n          time: 0\n          value: 0\n          inSlope: 1\n          outSlope: 1\n          tangentMode: 0\n          weightedMode: 0\n          inWeight: 0\n          outWeight: 0\n        - serializedVersion: 3\n          time: 1\n          value: 1\n          inSlope: 1\n          outSlope: 1\n          tangentMode: 0\n          weightedMode: 0\n          inWeight: 0\n          outWeight: 0\n        m_PreInfinity: 2\n        m_PostInfinity: 2\n        m_RotationOrder: 4\n  hueVsHue:\n    m_OverrideState: 1\n    m_Value:\n      <length>k__BackingField: 0\n      m_Loop: 1\n      m_ZeroValue: 0.5\n      m_Range: 1\n      m_Curve:\n        serializedVersion: 2\n        m_Curve: []\n        m_PreInfinity: 2\n        m_PostInfinity: 2\n        m_RotationOrder: 4\n  hueVsSat:\n    m_OverrideState: 1\n    m_Value:\n      <length>k__BackingField: 0\n      m_Loop: 1\n      m_ZeroValue: 0.5\n      m_Range: 1\n      m_Curve:\n        serializedVersion: 2\n        m_Curve: []\n        m_PreInfinity: 2\n        m_PostInfinity: 2\n        m_RotationOrder: 4\n  satVsSat:\n    m_OverrideState: 1\n    m_Value:\n      <length>k__BackingField: 0\n      m_Loop: 0\n      m_ZeroValue: 0.5\n      m_Range: 1\n      m_Curve:\n        serializedVersion: 2\n        m_Curve: []\n        m_PreInfinity: 2\n        m_PostInfinity: 2\n        m_RotationOrder: 4\n  lumVsSat:\n    m_OverrideState: 1\n    m_Value:\n      <length>k__BackingField: 0\n      m_Loop: 0\n      m_ZeroValue: 0.5\n      m_Range: 1\n      m_Curve:\n        serializedVersion: 2\n        m_Curve: []\n        m_PreInfinity: 2\n        m_PostInfinity: 2\n        m_RotationOrder: 4\n--- !u!114 &5078066985263128679\nMonoBehaviour:\n  m_ObjectHideFlags: 3\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 0}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: 97c23e3b12dc18c42a140437e53d3951, type: 3}\n  m_Name: Tonemapping\n  m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.Tonemapping\n  active: 1\n  mode:\n    m_OverrideState: 1\n    m_Value: 0\n  neutralHDRRangeReductionMode:\n    m_OverrideState: 1\n    m_Value: 2\n  acesPreset:\n    m_OverrideState: 1\n    m_Value: 3\n  hueShiftAmount:\n    m_OverrideState: 1\n    m_Value: 0\n  detectPaperWhite:\n    m_OverrideState: 1\n    m_Value: 0\n  paperWhite:\n    m_OverrideState: 1\n    m_Value: 300\n  detectBrightnessLimits:\n    m_OverrideState: 1\n    m_Value: 1\n  minNits:\n    m_OverrideState: 1\n    m_Value: 0.005\n  maxNits:\n    m_OverrideState: 1\n    m_Value: 1000\n--- !u!114 &5892942527586337604\nMonoBehaviour:\n  m_ObjectHideFlags: 3\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 0}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: 6bd486065ce11414fa40e631affc4900, type: 3}\n  m_Name: ProbeVolumesOptions\n  m_EditorClassIdentifier: Unity.RenderPipelines.Core.Runtime::UnityEngine.Rendering.ProbeVolumesOptions\n  active: 1\n  normalBias:\n    m_OverrideState: 1\n    m_Value: 0.05\n  viewBias:\n    m_OverrideState: 1\n    m_Value: 0.1\n  scaleBiasWithMinProbeDistance:\n    m_OverrideState: 1\n    m_Value: 0\n  samplingNoise:\n    m_OverrideState: 1\n    m_Value: 0.1\n  animateSamplingNoise:\n    m_OverrideState: 1\n    m_Value: 1\n  leakReductionMode:\n    m_OverrideState: 1\n    m_Value: 2\n  minValidDotProductValue:\n    m_OverrideState: 1\n    m_Value: 0.1\n  occlusionOnlyReflectionNormalization:\n    m_OverrideState: 1\n    m_Value: 1\n  intensityMultiplier:\n    m_OverrideState: 1\n    m_Value: 1\n  skyOcclusionIntensityMultiplier:\n    m_OverrideState: 1\n    m_Value: 1\n  worldOffset:\n    m_OverrideState: 1\n    m_Value: {x: 0, y: 0, z: 0}\n--- !u!114 &8855959688280746896\nMonoBehaviour:\n  m_ObjectHideFlags: 3\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 0}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: cdfbdbb87d3286943a057f7791b43141, type: 3}\n  m_Name: ChannelMixer\n  m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.ChannelMixer\n  active: 1\n  redOutRedIn:\n    m_OverrideState: 1\n    m_Value: 100\n  redOutGreenIn:\n    m_OverrideState: 1\n    m_Value: 0\n  redOutBlueIn:\n    m_OverrideState: 1\n    m_Value: 0\n  greenOutRedIn:\n    m_OverrideState: 1\n    m_Value: 0\n  greenOutGreenIn:\n    m_OverrideState: 1\n    m_Value: 100\n  greenOutBlueIn:\n    m_OverrideState: 1\n    m_Value: 0\n  blueOutRedIn:\n    m_OverrideState: 1\n    m_Value: 0\n  blueOutGreenIn:\n    m_OverrideState: 1\n    m_Value: 0\n  blueOutBlueIn:\n    m_OverrideState: 1\n    m_Value: 100\n--- !u!114 &8862907471677848668\nMonoBehaviour:\n  m_ObjectHideFlags: 3\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 0}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: ccf1aba9553839d41ae37dd52e9ebcce, type: 3}\n  m_Name: MotionBlur\n  m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.MotionBlur\n  active: 1\n  mode:\n    m_OverrideState: 1\n    m_Value: 0\n  quality:\n    m_OverrideState: 1\n    m_Value: 0\n  intensity:\n    m_OverrideState: 1\n    m_Value: 0\n  clamp:\n    m_OverrideState: 1\n    m_Value: 0.05\n"
  },
  {
    "path": "Assets/Demo/URP/DefaultVolume.asset.meta",
    "content": "fileFormatVersion: 2\nguid: dc9bac492fb764e719f43f6fff2d42aa\nNativeFormatImporter:\n  externalObjects: {}\n  mainObjectFileID: 11400000\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Demo/URP/GlobalSettings.asset",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!114 &11400000\nMonoBehaviour:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 0}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: 2ec995e51a6e251468d2a3fd8a686257, type: 3}\n  m_Name: GlobalSettings\n  m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.UniversalRenderPipelineGlobalSettings\n  m_ShaderStrippingSetting:\n    m_Version: 0\n    m_ExportShaderVariants: 1\n    m_ShaderVariantLogLevel: 0\n    m_StripRuntimeDebugShaders: 1\n  m_URPShaderStrippingSetting:\n    m_Version: 0\n    m_StripUnusedPostProcessingVariants: 0\n    m_StripUnusedVariants: 1\n    m_StripScreenCoordOverrideVariants: 1\n  m_ShaderVariantLogLevel: 0\n  m_ExportShaderVariants: 1\n  m_StripDebugVariants: 1\n  m_StripUnusedPostProcessingVariants: 0\n  m_StripUnusedVariants: 1\n  m_StripScreenCoordOverrideVariants: 1\n  supportRuntimeDebugDisplay: 0\n  m_EnableRenderGraph: 0\n  m_Settings:\n    m_SettingsList:\n      m_List:\n      - rid: 8017221388498632982\n      - rid: 8017221388498632983\n      - rid: 8017221388498632984\n      - rid: 8017221388498632985\n      - rid: 8017221388498632986\n      - rid: 8017221388498632987\n      - rid: 8017221388498632988\n      - rid: 8017221388498632989\n      - rid: 8017221388498632990\n      - rid: 8017221388498632991\n      - rid: 8017221388498632992\n      - rid: 8017221388498632993\n      - rid: 8017221388498632994\n      - rid: 8017221388498632995\n      - rid: 8017221388498632996\n      - rid: 8017221388498632997\n      - rid: 8017221388498632998\n      - rid: 8017221388498632999\n      - rid: 8017221388498633000\n      - rid: 8017221388498633001\n      - rid: 8017221388498633002\n      - rid: 8017221388498633003\n      - rid: 8017221388498633004\n      - rid: 8017221388498633005\n      - rid: 8017221388498633006\n      - rid: 8017221388498633007\n      - rid: 8017221388498633008\n      - rid: 8017221388498633009\n      - rid: 8017221388498633010\n      - rid: 8017221388498633011\n      - rid: 8017221388498633012\n      - rid: 8017221388498633013\n    m_RuntimeSettings:\n      m_List: []\n  m_AssetVersion: 9\n  m_ObsoleteDefaultVolumeProfile: {fileID: 0}\n  m_RenderingLayerNames:\n  - Default\n  m_ValidRenderingLayers: 0\n  lightLayerName0: \n  lightLayerName1: \n  lightLayerName2: \n  lightLayerName3: \n  lightLayerName4: \n  lightLayerName5: \n  lightLayerName6: \n  lightLayerName7: \n  apvScenesData:\n    obsoleteSceneBounds:\n      m_Keys: []\n      m_Values: []\n    obsoleteHasProbeVolumes:\n      m_Keys: []\n      m_Values: \n  references:\n    version: 2\n    RefIds:\n    - rid: 8017221388498632982\n      type: {class: RayTracingRenderPipelineResources, ns: UnityEngine.Rendering.UnifiedRayTracing, asm: Unity.UnifiedRayTracing.Runtime}\n      data:\n        m_Version: 1\n        m_GeometryPoolKernels: {fileID: 7200000, guid: 98e3d58cae7210c4786f67f504c9e899, type: 3}\n        m_CopyBuffer: {fileID: 7200000, guid: 1b95b5dcf48d1914c9e1e7405c7660e3, type: 3}\n        m_CopyPositions: {fileID: 7200000, guid: 1ad53a96b58d3c3488dde4f14db1aaeb, type: 3}\n        m_BitHistogram: {fileID: 7200000, guid: 8670f7ce4b60cef43bed36148aa1b0a2, type: 3}\n        m_BlockReducePart: {fileID: 7200000, guid: 4e034cc8ea2635c4e9f063e5ddc7ea7a, type: 3}\n        m_BlockScan: {fileID: 7200000, guid: 4d6d5de35fa45ef4a92119397a045cc9, type: 3}\n        m_BuildHlbvh: {fileID: 7200000, guid: 2d70cd6be91bd7843a39a54b51c15b13, type: 3}\n        m_RestructureBvh: {fileID: 7200000, guid: 56641cb88dcb31a4398a4997ef7a7a8c, type: 3}\n        m_Scatter: {fileID: 7200000, guid: a2eaeefdac4637a44b734e85b7be9186, type: 3}\n    - rid: 8017221388498632983\n      type: {class: UniversalRenderPipelineEditorMaterials, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime}\n      data:\n        m_DefaultMaterial: {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2}\n        m_DefaultParticleMaterial: {fileID: 2100000, guid: e823cd5b5d27c0f4b8256e7c12ee3e6d, type: 2}\n        m_DefaultLineMaterial: {fileID: 2100000, guid: e823cd5b5d27c0f4b8256e7c12ee3e6d, type: 2}\n        m_DefaultTerrainMaterial: {fileID: 2100000, guid: 594ea882c5a793440b60ff72d896021e, type: 2}\n        m_DefaultDecalMaterial: {fileID: 2100000, guid: 31d0dcc6f2dd4e4408d18036a2c93862, type: 2}\n        m_DefaultSpriteMaterial: {fileID: 2100000, guid: 9dfc825aed78fcd4ba02077103263b40, type: 2}\n    - rid: 8017221388498632984\n      type: {class: PostProcessData/TextureResources, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime}\n      data:\n        blueNoise16LTex: []\n        filmGrainTex:\n        - {fileID: 2800000, guid: 654c582f7f8a5a14dbd7d119cbde215d, type: 3}\n        - {fileID: 2800000, guid: dd77ffd079630404e879388999033049, type: 3}\n        - {fileID: 2800000, guid: 1097e90e1306e26439701489f391a6c0, type: 3}\n        - {fileID: 2800000, guid: f0b67500f7fad3b4c9f2b13e8f41ba6e, type: 3}\n        - {fileID: 2800000, guid: 9930fb4528622b34687b00bbe6883de7, type: 3}\n        - {fileID: 2800000, guid: bd9e8c758250ef449a4b4bfaad7a2133, type: 3}\n        - {fileID: 2800000, guid: 510a2f57334933e4a8dbabe4c30204e4, type: 3}\n        - {fileID: 2800000, guid: b4db8180660810945bf8d55ab44352ad, type: 3}\n        - {fileID: 2800000, guid: fd2fd78b392986e42a12df2177d3b89c, type: 3}\n        - {fileID: 2800000, guid: 5cdee82a77d13994f83b8fdabed7c301, type: 3}\n        smaaAreaTex: {fileID: 2800000, guid: d1f1048909d55cd4fa1126ab998f617e, type: 3}\n        smaaSearchTex: {fileID: 2800000, guid: 51eee22c2a633ef4aada830eed57c3fd, type: 3}\n        m_TexturesResourcesVersion: 0\n    - rid: 8017221388498632985\n      type: {class: URPDefaultVolumeProfileSettings, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime}\n      data:\n        m_Version: 0\n        m_VolumeProfile: {fileID: 11400000, guid: dc9bac492fb764e719f43f6fff2d42aa, type: 2}\n    - rid: 8017221388498632986\n      type: {class: ScreenSpaceAmbientOcclusionDynamicResources, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime}\n      data:\n        m_BlueNoise256Textures:\n        - {fileID: 2800000, guid: 36f118343fc974119bee3d09e2111500, type: 3}\n        - {fileID: 2800000, guid: 4b7b083e6b6734e8bb2838b0b50a0bc8, type: 3}\n        - {fileID: 2800000, guid: c06cc21c692f94f5fb5206247191eeee, type: 3}\n        - {fileID: 2800000, guid: cb76dd40fa7654f9587f6a344f125c9a, type: 3}\n        - {fileID: 2800000, guid: e32226222ff144b24bf3a5a451de54bc, type: 3}\n        - {fileID: 2800000, guid: 3302065f671a8450b82c9ddf07426f3a, type: 3}\n        - {fileID: 2800000, guid: 56a77a3e8d64f47b6afe9e3c95cb57d5, type: 3}\n        m_Version: 0\n    - rid: 8017221388498632987\n      type: {class: RenderGraphSettings, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime}\n      data:\n        m_Version: 0\n        m_EnableRenderCompatibilityMode: 0\n    - rid: 8017221388498632988\n      type: {class: Renderer2DResources, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime}\n      data:\n        m_Version: 0\n        m_LightShader: {fileID: 4800000, guid: 3f6c848ca3d7bca4bbe846546ac701a1, type: 3}\n        m_ProjectedShadowShader: {fileID: 4800000, guid: ce09d4a80b88c5a4eb9768fab4f1ee00, type: 3}\n        m_SpriteShadowShader: {fileID: 4800000, guid: 44fc62292b65ab04eabcf310e799ccf6, type: 3}\n        m_SpriteUnshadowShader: {fileID: 4800000, guid: de02b375720b5c445afe83cd483bedf3, type: 3}\n        m_GeometryShadowShader: {fileID: 4800000, guid: 19349a0f9a7ed4c48a27445bcf92e5e1, type: 3}\n        m_GeometryUnshadowShader: {fileID: 4800000, guid: 77774d9009bb81447b048c907d4c6273, type: 3}\n        m_CopyDepthPS: {fileID: 4800000, guid: d6dae50ee9e1bfa4db75f19f99355220, type: 3}\n        m_DefaultLitMaterial: {fileID: 2100000, guid: a97c105638bdf8b4a8650670310a4cd3, type: 2}\n        m_DefaultUnlitMaterial: {fileID: 2100000, guid: 9dfc825aed78fcd4ba02077103263b40, type: 2}\n        m_DefaultMaskMaterial: {fileID: 2100000, guid: 15d0c3709176029428a0da2f8cecf0b5, type: 2}\n        m_DefaultMesh2DLitMaterial: {fileID: 2100000, guid: 9452ae1262a74094f8a68013fbcd1834, type: 2}\n    - rid: 8017221388498632989\n      type: {class: URPShaderStrippingSetting, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime}\n      data:\n        m_Version: 0\n        m_StripUnusedPostProcessingVariants: 0\n        m_StripUnusedVariants: 1\n        m_StripScreenCoordOverrideVariants: 1\n    - rid: 8017221388498632990\n      type: {class: UniversalRendererResources, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime}\n      data:\n        m_Version: 0\n        m_CopyDepthPS: {fileID: 4800000, guid: d6dae50ee9e1bfa4db75f19f99355220, type: 3}\n        m_CameraMotionVector: {fileID: 4800000, guid: c56b7e0d4c7cb484e959caeeedae9bbf, type: 3}\n        m_StencilDeferredPS: {fileID: 4800000, guid: e9155b26e1bc55942a41e518703fe304, type: 3}\n        m_ClusterDeferred: {fileID: 4800000, guid: 222cce62363a44a380c36bf03b392608, type: 3}\n        m_StencilDitherMaskSeedPS: {fileID: 4800000, guid: 8c3ee818f2efa514c889881ccb2e95a2, type: 3}\n        m_DBufferClear: {fileID: 4800000, guid: f056d8bd2a1c7e44e9729144b4c70395, type: 3}\n    - rid: 8017221388498632991\n      type: {class: UniversalRenderPipelineRuntimeShaders, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime}\n      data:\n        m_Version: 0\n        m_FallbackErrorShader: {fileID: 4800000, guid: e6e9a19c3678ded42a3bc431ebef7dbd, type: 3}\n        m_BlitHDROverlay: {fileID: 4800000, guid: a89bee29cffa951418fc1e2da94d1959, type: 3}\n        m_CoreBlitPS: {fileID: 4800000, guid: 93446b5c5339d4f00b85c159e1159b7c, type: 3}\n        m_CoreBlitColorAndDepthPS: {fileID: 4800000, guid: d104b2fc1ca6445babb8e90b0758136b, type: 3}\n        m_SamplingPS: {fileID: 4800000, guid: 04c410c9937594faa893a11dceb85f7e, type: 3}\n        m_TerrainDetailLit: {fileID: 4800000, guid: f6783ab646d374f94b199774402a5144, type: 3}\n        m_TerrainDetailGrassBillboard: {fileID: 4800000, guid: 29868e73b638e48ca99a19ea58c48d90, type: 3}\n        m_TerrainDetailGrass: {fileID: 4800000, guid: e507fdfead5ca47e8b9a768b51c291a1, type: 3}\n    - rid: 8017221388498632992\n      type: {class: OnTilePostProcessResource, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime}\n      data:\n        m_Version: 0\n        m_UberPostShader: {fileID: 4800000, guid: fe4f13c1004a07d4ea1e30bfd0326d9e, type: 3}\n    - rid: 8017221388498632993\n      type: {class: URPReflectionProbeSettings, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Universal.Runtime}\n      data:\n        version: 1\n        useReflectionProbeRotation: 1\n    - rid: 8017221388498632994\n      type: {class: UniversalRenderPipelineEditorShaders, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime}\n      data:\n        m_AutodeskInteractive: {fileID: 4800000, guid: 0e9d5a909a1f7e84882a534d0d11e49f, type: 3}\n        m_AutodeskInteractiveTransparent: {fileID: 4800000, guid: 5c81372d981403744adbdda4433c9c11, type: 3}\n        m_AutodeskInteractiveMasked: {fileID: 4800000, guid: 80aa867ac363ac043847b06ad71604cd, type: 3}\n        m_DefaultSpeedTree7Shader: {fileID: 4800000, guid: 0f4122b9a743b744abe2fb6a0a88868b, type: 3}\n        m_DefaultSpeedTree8Shader: {fileID: -6465566751694194690, guid: 9920c1f1781549a46ba081a2a15a16ec, type: 3}\n        m_DefaultSpeedTree9Shader: {fileID: -6465566751694194690, guid: cbd3e1cc4ae141c42a30e33b4d666a61, type: 3}\n    - rid: 8017221388498632995\n      type: {class: ScreenSpaceAmbientOcclusionPersistentResources, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime}\n      data:\n        m_Shader: {fileID: 4800000, guid: 0849e84e3d62649e8882e9d6f056a017, type: 3}\n        m_Version: 0\n    - rid: 8017221388498632996\n      type: {class: UniversalRenderPipelineDebugShaders, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime}\n      data:\n        m_DebugReplacementPS: {fileID: 4800000, guid: cf852408f2e174538bcd9b7fda1c5ae7, type: 3}\n        m_HdrDebugViewPS: {fileID: 4800000, guid: 573620ae32aec764abd4d728906d2587, type: 3}\n        m_ProbeVolumeSamplingDebugComputeShader: {fileID: 7200000, guid: 53626a513ea68ce47b59dc1299fe3959, type: 3}\n    - rid: 8017221388498632997\n      type: {class: UniversalRenderPipelineRuntimeXRResources, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime}\n      data:\n        m_xrOcclusionMeshPS: {fileID: 4800000, guid: 4431b1f1f743fbf4eb310a967890cbea, type: 3}\n        m_xrMirrorViewPS: {fileID: 4800000, guid: d5a307c014552314b9f560906d708772, type: 3}\n        m_xrMotionVector: {fileID: 4800000, guid: f89aac1e4f84468418fe30e611dff395, type: 3}\n    - rid: 8017221388498632998\n      type: {class: UniversalRenderPipelineEditorAssets, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime}\n      data:\n        m_DefaultSettingsVolumeProfile: {fileID: 11400000, guid: eda47df5b85f4f249abf7abd73db2cb2, type: 2}\n    - rid: 8017221388498632999\n      type: {class: PostProcessData/ShaderResources, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime}\n      data:\n        stopNanPS: {fileID: 4800000, guid: 1121bb4e615ca3c48b214e79e841e823, type: 3}\n        subpixelMorphologicalAntialiasingPS: {fileID: 4800000, guid: 63eaba0ebfb82cc43bde059b4a8c65f6, type: 3}\n        gaussianDepthOfFieldPS: {fileID: 4800000, guid: 5e7134d6e63e0bc47a1dd2669cedb379, type: 3}\n        bokehDepthOfFieldPS: {fileID: 4800000, guid: 2aed67ad60045d54ba3a00c91e2d2631, type: 3}\n        cameraMotionBlurPS: {fileID: 4800000, guid: 1edcd131364091c46a17cbff0b1de97a, type: 3}\n        paniniProjectionPS: {fileID: 4800000, guid: a15b78cf8ca26ca4fb2090293153c62c, type: 3}\n        lutBuilderLdrPS: {fileID: 4800000, guid: 65df88701913c224d95fc554db28381a, type: 3}\n        lutBuilderHdrPS: {fileID: 4800000, guid: ec9fec698a3456d4fb18cf8bacb7a2bc, type: 3}\n        bloomPS: {fileID: 4800000, guid: 5f1864addb451f54bae8c86d230f736e, type: 3}\n        temporalAntialiasingPS: {fileID: 4800000, guid: 9c70c1a35ff15f340b38ea84842358bf, type: 3}\n        LensFlareDataDrivenPS: {fileID: 4800000, guid: 6cda457ac28612740adb23da5d39ea92, type: 3}\n        LensFlareScreenSpacePS: {fileID: 4800000, guid: 701880fecb344ea4c9cd0db3407ab287, type: 3}\n        scalingSetupPS: {fileID: 4800000, guid: e8ee25143a34b8c4388709ea947055d1, type: 3}\n        easuPS: {fileID: 4800000, guid: 562b7ae4f629f144aa97780546fce7c6, type: 3}\n        uberPostPS: {fileID: 4800000, guid: e7857e9d0c934dc4f83f270f8447b006, type: 3}\n        finalPostPassPS: {fileID: 4800000, guid: c49e63ed1bbcb334780a3bd19dfed403, type: 3}\n        m_ShaderResourcesVersion: 0\n    - rid: 8017221388498633000\n      type: {class: UniversalRenderPipelineRuntimeTextures, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime}\n      data:\n        m_Version: 1\n        m_BlueNoise64LTex: {fileID: 2800000, guid: e3d24661c1e055f45a7560c033dbb837, type: 3}\n        m_BayerMatrixTex: {fileID: 2800000, guid: f9ee4ed84c1d10c49aabb9b210b0fc44, type: 3}\n        m_DebugFontTex: {fileID: 2800000, guid: 26a413214480ef144b2915d6ff4d0beb, type: 3}\n    - rid: 8017221388498633001\n      type: {class: GPUResidentDrawerResources, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.GPUDriven.Runtime}\n      data:\n        m_Version: 0\n        m_InstanceDataBufferCopyKernels: {fileID: 7200000, guid: f984aeb540ded8b4fbb8a2047ab5b2e2, type: 3}\n        m_InstanceDataBufferUploadKernels: {fileID: 7200000, guid: 53864816eb00f2343b60e1a2c5a262ef, type: 3}\n        m_TransformUpdaterKernels: {fileID: 7200000, guid: 2a567b9b2733f8d47a700c3c85bed75b, type: 3}\n        m_WindDataUpdaterKernels: {fileID: 7200000, guid: fde76746e4fd0ed418c224f6b4084114, type: 3}\n        m_OccluderDepthPyramidKernels: {fileID: 7200000, guid: 08b2b5fb307b0d249860612774a987da, type: 3}\n        m_InstanceOcclusionCullingKernels: {fileID: 7200000, guid: f6d223acabc2f974795a5a7864b50e6c, type: 3}\n        m_OcclusionCullingDebugKernels: {fileID: 7200000, guid: b23e766bcf50ca4438ef186b174557df, type: 3}\n        m_DebugOcclusionTestPS: {fileID: 4800000, guid: d3f0849180c2d0944bc71060693df100, type: 3}\n        m_DebugOccluderPS: {fileID: 4800000, guid: b3c92426a88625841ab15ca6a7917248, type: 3}\n    - rid: 8017221388498633002\n      type: {class: RenderGraphGlobalSettings, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime}\n      data:\n        m_version: 0\n        m_EnableCompilationCaching: 1\n        m_EnableValidityChecks: 1\n    - rid: 8017221388498633003\n      type: {class: VrsRenderPipelineRuntimeResources, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime}\n      data:\n        m_TextureComputeShader: {fileID: 7200000, guid: cacb30de6c40c7444bbc78cb0a81fd2a, type: 3}\n        m_VisualizationShader: {fileID: 4800000, guid: 620b55b8040a88d468e94abe55bed5ba, type: 3}\n        m_VisualizationLookupTable:\n          m_Data:\n          - {r: 0.785, g: 0.23, b: 0.2, a: 1}\n          - {r: 1, g: 0.8, b: 0.8, a: 1}\n          - {r: 0.4, g: 0.2, b: 0.2, a: 1}\n          - {r: 0.51, g: 0.8, b: 0.6, a: 1}\n          - {r: 0.6, g: 0.8, b: 1, a: 1}\n          - {r: 0.2, g: 0.4, b: 0.6, a: 1}\n          - {r: 0.8, g: 1, b: 0.8, a: 1}\n          - {r: 0.2, g: 0.4, b: 0.2, a: 1}\n          - {r: 0.125, g: 0.22, b: 0.36, a: 1}\n        m_ConversionLookupTable:\n          m_Data:\n          - {r: 0.785, g: 0.23, b: 0.2, a: 1}\n          - {r: 1, g: 0.8, b: 0.8, a: 1}\n          - {r: 0.4, g: 0.2, b: 0.2, a: 1}\n          - {r: 0.51, g: 0.8, b: 0.6, a: 1}\n          - {r: 0.6, g: 0.8, b: 1, a: 1}\n          - {r: 0.2, g: 0.4, b: 0.6, a: 1}\n          - {r: 0.8, g: 1, b: 0.8, a: 1}\n          - {r: 0.2, g: 0.4, b: 0.2, a: 1}\n          - {r: 0.125, g: 0.22, b: 0.36, a: 1}\n    - rid: 8017221388498633004\n      type: {class: RenderGraphUtilsResources, ns: UnityEngine.Rendering.RenderGraphModule.Util, asm: Unity.RenderPipelines.Core.Runtime}\n      data:\n        m_Version: 0\n        m_CoreCopyPS: {fileID: 4800000, guid: 12dc59547ea167a4ab435097dd0f9add, type: 3}\n    - rid: 8017221388498633005\n      type: {class: ProbeVolumeGlobalSettings, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime}\n      data:\n        m_Version: 1\n        m_ProbeVolumeDisableStreamingAssets: 0\n    - rid: 8017221388498633006\n      type: {class: RenderingDebuggerRuntimeResources, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime}\n      data:\n        m_version: 0\n    - rid: 8017221388498633007\n      type: {class: ShaderStrippingSetting, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime}\n      data:\n        m_Version: 0\n        m_ExportShaderVariants: 1\n        m_ShaderVariantLogLevel: 0\n        m_StripRuntimeDebugShaders: 1\n    - rid: 8017221388498633008\n      type: {class: LightmapSamplingSettings, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime}\n      data:\n        m_Version: 1\n        m_UseBicubicLightmapSampling: 0\n    - rid: 8017221388498633009\n      type: {class: ProbeVolumeBakingResources, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime}\n      data:\n        m_Version: 1\n        dilationShader: {fileID: 7200000, guid: 6bb382f7de370af41b775f54182e491d, type: 3}\n        subdivideSceneCS: {fileID: 7200000, guid: bb86f1f0af829fd45b2ebddda1245c22, type: 3}\n        voxelizeSceneShader: {fileID: 4800000, guid: c8b6a681c7b4e2e4785ffab093907f9e, type: 3}\n        traceVirtualOffsetCS: {fileID: -6772857160820960102, guid: ff2cbab5da58bf04d82c5f34037ed123, type: 3}\n        traceVirtualOffsetRT: {fileID: -5126288278712620388, guid: ff2cbab5da58bf04d82c5f34037ed123, type: 3}\n        skyOcclusionCS: {fileID: -6772857160820960102, guid: 5a2a534753fbdb44e96c3c78b5a6999d, type: 3}\n        skyOcclusionRT: {fileID: -5126288278712620388, guid: 5a2a534753fbdb44e96c3c78b5a6999d, type: 3}\n        renderingLayerCS: {fileID: -6772857160820960102, guid: 94a070d33e408384bafc1dea4a565df9, type: 3}\n        renderingLayerRT: {fileID: -5126288278712620388, guid: 94a070d33e408384bafc1dea4a565df9, type: 3}\n    - rid: 8017221388498633010\n      type: {class: ProbeVolumeRuntimeResources, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime}\n      data:\n        m_Version: 1\n        probeVolumeBlendStatesCS: {fileID: 7200000, guid: a3f7b8c99de28a94684cb1daebeccf5d, type: 3}\n        probeVolumeUploadDataCS: {fileID: 7200000, guid: 0951de5992461754fa73650732c4954c, type: 3}\n        probeVolumeUploadDataL2CS: {fileID: 7200000, guid: 6196f34ed825db14b81fb3eb0ea8d931, type: 3}\n    - rid: 8017221388498633011\n      type: {class: STP/RuntimeResources, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime}\n      data:\n        m_setupCS: {fileID: 7200000, guid: 33be2e9a5506b2843bdb2bdff9cad5e1, type: 3}\n        m_preTaaCS: {fileID: 7200000, guid: a679dba8ec4d9ce45884a270b0e22dda, type: 3}\n        m_taaCS: {fileID: 7200000, guid: 3923900e2b41b5e47bc25bfdcbcdc9e6, type: 3}\n    - rid: 8017221388498633012\n      type: {class: IncludeAdditionalRPAssets, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime}\n      data:\n        m_version: 0\n        m_IncludeReferencedInScenes: 0\n        m_IncludeAssetsByLabel: 0\n        m_LabelToInclude: \n    - rid: 8017221388498633013\n      type: {class: ProbeVolumeDebugResources, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime}\n      data:\n        m_Version: 1\n        probeVolumeDebugShader: {fileID: 4800000, guid: 3b21275fd12d65f49babb5286f040f2d, type: 3}\n        probeVolumeFragmentationDebugShader: {fileID: 4800000, guid: 3a80877c579b9144ebdcc6d923bca303, type: 3}\n        probeVolumeSamplingDebugShader: {fileID: 4800000, guid: bf54e6528c79a224e96346799064c393, type: 3}\n        probeVolumeOffsetDebugShader: {fileID: 4800000, guid: db8bd7436dc2c5f4c92655307d198381, type: 3}\n        probeSamplingDebugMesh: {fileID: -3555484719484374845, guid: 20be25aac4e22ee49a7db76fb3df6de2, type: 3}\n        numbersDisplayTex: {fileID: 2800000, guid: 73fe53b428c5b3440b7e87ee830b608a, type: 3}\n"
  },
  {
    "path": "Assets/Demo/URP/GlobalSettings.asset.meta",
    "content": "fileFormatVersion: 2\nguid: a0e1abbc8745e464ab699ff4e71959f6\nNativeFormatImporter:\n  externalObjects: {}\n  mainObjectFileID: 11400000\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Demo/URP/URP.asset",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!114 &11400000\nMonoBehaviour:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 0}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: bf2edee5c58d82540a51f03df9d42094, type: 3}\n  m_Name: URP\n  m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.UniversalRenderPipelineAsset\n  k_AssetVersion: 13\n  k_AssetPreviousVersion: 13\n  m_RendererType: 1\n  m_RendererData: {fileID: 0}\n  m_RendererDataList:\n  - {fileID: 11400000, guid: e707f25f3295f48408bbc74cefc67e0d, type: 2}\n  m_DefaultRendererIndex: 0\n  m_RequireDepthTexture: 0\n  m_RequireOpaqueTexture: 0\n  m_OpaqueDownsampling: 1\n  m_SupportsTerrainHoles: 1\n  m_SupportsHDR: 1\n  m_HDRColorBufferPrecision: 0\n  m_MSAA: 1\n  m_RenderScale: 1\n  m_UpscalingFilter: 0\n  m_FsrOverrideSharpness: 0\n  m_FsrSharpness: 0.92\n  m_EnableLODCrossFade: 1\n  m_LODCrossFadeDitheringType: 1\n  m_ShEvalMode: 0\n  m_LightProbeSystem: 0\n  m_ProbeVolumeMemoryBudget: 1024\n  m_ProbeVolumeBlendingMemoryBudget: 256\n  m_SupportProbeVolumeGPUStreaming: 0\n  m_SupportProbeVolumeDiskStreaming: 0\n  m_SupportProbeVolumeScenarios: 0\n  m_SupportProbeVolumeScenarioBlending: 0\n  m_ProbeVolumeSHBands: 1\n  m_MainLightRenderingMode: 1\n  m_MainLightShadowsSupported: 1\n  m_MainLightShadowmapResolution: 2048\n  m_AdditionalLightsRenderingMode: 1\n  m_AdditionalLightsPerObjectLimit: 4\n  m_AdditionalLightShadowsSupported: 0\n  m_AdditionalLightsShadowmapResolution: 2048\n  m_AdditionalLightsShadowResolutionTierLow: 256\n  m_AdditionalLightsShadowResolutionTierMedium: 512\n  m_AdditionalLightsShadowResolutionTierHigh: 1024\n  m_ReflectionProbeBlending: 0\n  m_ReflectionProbeBoxProjection: 0\n  m_ReflectionProbeAtlas: 0\n  m_ShadowDistance: 50\n  m_ShadowCascadeCount: 1\n  m_Cascade2Split: 0.25\n  m_Cascade3Split: {x: 0.1, y: 0.3}\n  m_Cascade4Split: {x: 0.067, y: 0.2, z: 0.467}\n  m_CascadeBorder: 0.2\n  m_ShadowDepthBias: 1\n  m_ShadowNormalBias: 1\n  m_AnyShadowsSupported: 1\n  m_SoftShadowsSupported: 0\n  m_ConservativeEnclosingSphere: 1\n  m_NumIterationsEnclosingSphere: 64\n  m_SoftShadowQuality: 2\n  m_AdditionalLightsCookieResolution: 2048\n  m_AdditionalLightsCookieFormat: 3\n  m_UseSRPBatcher: 1\n  m_SupportsDynamicBatching: 0\n  m_MixedLightingSupported: 1\n  m_SupportsLightCookies: 1\n  m_SupportsLightLayers: 0\n  m_DebugLevel: 0\n  m_StoreActionsOptimization: 0\n  m_UseAdaptivePerformance: 1\n  m_ColorGradingMode: 0\n  m_ColorGradingLutSize: 32\n  m_AllowPostProcessAlphaOutput: 0\n  m_UseFastSRGBLinearConversion: 0\n  m_SupportDataDrivenLensFlare: 1\n  m_SupportScreenSpaceLensFlare: 1\n  m_GPUResidentDrawerMode: 0\n  m_SmallMeshScreenPercentage: 0\n  m_GPUResidentDrawerEnableOcclusionCullingInCameras: 0\n  m_ShadowType: 1\n  m_LocalShadowsSupported: 0\n  m_LocalShadowsAtlasResolution: 256\n  m_MaxPixelLights: 0\n  m_ShadowAtlasResolution: 256\n  m_VolumeFrameworkUpdateMode: 0\n  m_VolumeProfile: {fileID: 0}\n  apvScenesData:\n    obsoleteSceneBounds:\n      m_Keys: []\n      m_Values: []\n    obsoleteHasProbeVolumes:\n      m_Keys: []\n      m_Values: \n  m_PrefilteringModeMainLightShadows: 1\n  m_PrefilteringModeAdditionalLight: 4\n  m_PrefilteringModeAdditionalLightShadows: 1\n  m_PrefilterXRKeywords: 0\n  m_PrefilteringModeForwardPlus: 1\n  m_PrefilteringModeDeferredRendering: 1\n  m_PrefilteringModeScreenSpaceOcclusion: 1\n  m_PrefilterDebugKeywords: 0\n  m_PrefilterWriteRenderingLayers: 0\n  m_PrefilterHDROutput: 0\n  m_PrefilterAlphaOutput: 0\n  m_PrefilterSSAODepthNormals: 0\n  m_PrefilterSSAOSourceDepthLow: 0\n  m_PrefilterSSAOSourceDepthMedium: 0\n  m_PrefilterSSAOSourceDepthHigh: 0\n  m_PrefilterSSAOInterleaved: 0\n  m_PrefilterSSAOBlueNoise: 0\n  m_PrefilterSSAOSampleCountLow: 0\n  m_PrefilterSSAOSampleCountMedium: 0\n  m_PrefilterSSAOSampleCountHigh: 0\n  m_PrefilterDBufferMRT1: 0\n  m_PrefilterDBufferMRT2: 0\n  m_PrefilterDBufferMRT3: 0\n  m_PrefilterSoftShadowsQualityLow: 0\n  m_PrefilterSoftShadowsQualityMedium: 0\n  m_PrefilterSoftShadowsQualityHigh: 0\n  m_PrefilterSoftShadows: 0\n  m_PrefilterScreenCoord: 0\n  m_PrefilterScreenSpaceIrradiance: 0\n  m_PrefilterNativeRenderPass: 0\n  m_PrefilterUseLegacyLightmaps: 0\n  m_PrefilterBicubicLightmapSampling: 0\n  m_PrefilterReflectionProbeRotation: 0\n  m_PrefilterReflectionProbeBlending: 0\n  m_PrefilterReflectionProbeBoxProjection: 0\n  m_PrefilterReflectionProbeAtlas: 0\n  m_ShaderVariantLogLevel: 0\n  m_ShadowCascades: 0\n  m_Textures:\n    blueNoise64LTex: {fileID: 2800000, guid: e3d24661c1e055f45a7560c033dbb837, type: 3}\n    bayerMatrixTex: {fileID: 2800000, guid: f9ee4ed84c1d10c49aabb9b210b0fc44, type: 3}\n"
  },
  {
    "path": "Assets/Demo/URP/URP.asset.meta",
    "content": "fileFormatVersion: 2\nguid: 0f2789a7f25c049d88040a322e46da7c\nNativeFormatImporter:\n  externalObjects: {}\n  mainObjectFileID: 11400000\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Demo/URP.meta",
    "content": "fileFormatVersion: 2\nguid: dea8b7a5d656145a3aba10170830c74e\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Demo.meta",
    "content": "fileFormatVersion: 2\nguid: 2c79d8564f0c64a0684cb4e548733c30\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Demo.unity",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!29 &1\nOcclusionCullingSettings:\n  m_ObjectHideFlags: 0\n  serializedVersion: 2\n  m_OcclusionBakeSettings:\n    smallestOccluder: 5\n    smallestHole: 0.25\n    backfaceThreshold: 100\n  m_SceneGUID: 00000000000000000000000000000000\n  m_OcclusionCullingData: {fileID: 0}\n--- !u!104 &2\nRenderSettings:\n  m_ObjectHideFlags: 0\n  serializedVersion: 10\n  m_Fog: 0\n  m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}\n  m_FogMode: 3\n  m_FogDensity: 0.01\n  m_LinearFogStart: 0\n  m_LinearFogEnd: 300\n  m_AmbientSkyColor: {r: 4.541206, g: 4.541206, b: 4.541206, a: 1}\n  m_AmbientEquatorColor: {r: 0.00073146477, g: 0.00073146477, b: 0.00073146477, a: 1}\n  m_AmbientGroundColor: {r: 0.26915348, g: 0.13803844, b: 0.6226415, a: 1}\n  m_AmbientIntensity: 1\n  m_AmbientMode: 1\n  m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}\n  m_SkyboxMaterial: {fileID: 0}\n  m_HaloStrength: 0.5\n  m_FlareStrength: 1\n  m_FlareFadeSpeed: 3\n  m_HaloTexture: {fileID: 0}\n  m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}\n  m_DefaultReflectionMode: 1\n  m_DefaultReflectionResolution: 128\n  m_ReflectionBounces: 1\n  m_ReflectionIntensity: 1\n  m_CustomReflection: {fileID: 0}\n  m_Sun: {fileID: 0}\n  m_UseRadianceAmbientProbe: 0\n--- !u!157 &3\nLightmapSettings:\n  m_ObjectHideFlags: 0\n  serializedVersion: 13\n  m_BakeOnSceneLoad: 0\n  m_GISettings:\n    serializedVersion: 2\n    m_BounceScale: 1\n    m_IndirectOutputScale: 1\n    m_AlbedoBoost: 1\n    m_EnvironmentLightingMode: 0\n    m_EnableBakedLightmaps: 1\n    m_EnableRealtimeLightmaps: 0\n  m_LightmapEditorSettings:\n    serializedVersion: 12\n    m_Resolution: 2\n    m_BakeResolution: 40\n    m_AtlasSize: 1024\n    m_AO: 0\n    m_AOMaxDistance: 1\n    m_CompAOExponent: 1\n    m_CompAOExponentDirect: 0\n    m_ExtractAmbientOcclusion: 0\n    m_Padding: 2\n    m_LightmapParameters: {fileID: 0}\n    m_LightmapsBakeMode: 1\n    m_TextureCompression: 1\n    m_ReflectionCompression: 2\n    m_MixedBakeMode: 2\n    m_BakeBackend: 2\n    m_PVRSampling: 1\n    m_PVRDirectSampleCount: 32\n    m_PVRSampleCount: 512\n    m_PVRBounces: 2\n    m_PVREnvironmentSampleCount: 256\n    m_PVREnvironmentReferencePointCount: 2048\n    m_PVRFilteringMode: 1\n    m_PVRDenoiserTypeDirect: 1\n    m_PVRDenoiserTypeIndirect: 1\n    m_PVRDenoiserTypeAO: 1\n    m_PVRFilterTypeDirect: 0\n    m_PVRFilterTypeIndirect: 0\n    m_PVRFilterTypeAO: 0\n    m_PVREnvironmentMIS: 1\n    m_PVRCulling: 1\n    m_PVRFilteringGaussRadiusDirect: 1\n    m_PVRFilteringGaussRadiusIndirect: 1\n    m_PVRFilteringGaussRadiusAO: 1\n    m_PVRFilteringAtrousPositionSigmaDirect: 0.5\n    m_PVRFilteringAtrousPositionSigmaIndirect: 2\n    m_PVRFilteringAtrousPositionSigmaAO: 1\n    m_ExportTrainingData: 0\n    m_TrainingDataDestination: TrainingData\n    m_LightProbeSampleCountMultiplier: 4\n  m_LightingDataAsset: {fileID: 20201, guid: 0000000000000000f000000000000000, type: 0}\n  m_LightingSettings: {fileID: 0}\n--- !u!196 &4\nNavMeshSettings:\n  serializedVersion: 2\n  m_ObjectHideFlags: 0\n  m_BuildSettings:\n    serializedVersion: 3\n    agentTypeID: 0\n    agentRadius: 0.5\n    agentHeight: 2\n    agentSlope: 45\n    agentClimb: 0.4\n    ledgeDropHeight: 0\n    maxJumpAcrossDistance: 0\n    minRegionArea: 2\n    manualCellSize: 0\n    cellSize: 0.16666667\n    manualTileSize: 0\n    tileSize: 256\n    buildHeightMesh: 0\n    maxJobWorkers: 0\n    preserveTilesOutsideBounds: 0\n    debug:\n      m_Flags: 0\n  m_NavMeshData: {fileID: 0}\n--- !u!1 &11714847\nGameObject:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  serializedVersion: 6\n  m_Component:\n  - component: {fileID: 11714850}\n  - component: {fileID: 11714849}\n  - component: {fileID: 11714848}\n  m_Layer: 0\n  m_Name: Quad\n  m_TagString: Untagged\n  m_Icon: {fileID: 0}\n  m_NavMeshLayer: 0\n  m_StaticEditorFlags: 0\n  m_IsActive: 1\n--- !u!23 &11714848\nMeshRenderer:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 11714847}\n  m_Enabled: 1\n  m_CastShadows: 1\n  m_ReceiveShadows: 1\n  m_DynamicOccludee: 1\n  m_StaticShadowCaster: 0\n  m_MotionVectors: 1\n  m_LightProbeUsage: 1\n  m_ReflectionProbeUsage: 1\n  m_RayTracingMode: 2\n  m_RayTraceProcedural: 0\n  m_RayTracingAccelStructBuildFlagsOverride: 0\n  m_RayTracingAccelStructBuildFlags: 1\n  m_SmallMeshCulling: 1\n  m_ForceMeshLod: -1\n  m_MeshLodSelectionBias: 0\n  m_RenderingLayerMask: 1\n  m_RendererPriority: 0\n  m_Materials:\n  - {fileID: 2100000, guid: 6f1182baee9ac4863bd4c5ea5f7d536d, type: 2}\n  m_StaticBatchInfo:\n    firstSubMesh: 0\n    subMeshCount: 0\n  m_StaticBatchRoot: {fileID: 0}\n  m_ProbeAnchor: {fileID: 0}\n  m_LightProbeVolumeOverride: {fileID: 0}\n  m_ScaleInLightmap: 1\n  m_ReceiveGI: 1\n  m_PreserveUVs: 0\n  m_IgnoreNormalsForChartDetection: 0\n  m_ImportantGI: 0\n  m_StitchLightmapSeams: 1\n  m_SelectedEditorRenderState: 3\n  m_MinimumChartSize: 4\n  m_AutoUVMaxDistance: 0.5\n  m_AutoUVMaxAngle: 89\n  m_LightmapParameters: {fileID: 0}\n  m_GlobalIlluminationMeshLod: 0\n  m_SortingLayerID: 0\n  m_SortingLayer: 0\n  m_SortingOrder: 0\n  m_MaskInteraction: 0\n  m_AdditionalVertexStreams: {fileID: 0}\n--- !u!33 &11714849\nMeshFilter:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 11714847}\n  m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}\n--- !u!4 &11714850\nTransform:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 11714847}\n  serializedVersion: 2\n  m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}\n  m_LocalPosition: {x: 0, y: 0, z: 0}\n  m_LocalScale: {x: 7.5510006, y: 4.247438, z: 4.247438}\n  m_ConstrainProportionsScale: 1\n  m_Children: []\n  m_Father: {fileID: 28633265}\n  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}\n--- !u!1 &28633263\nGameObject:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  serializedVersion: 6\n  m_Component:\n  - component: {fileID: 28633265}\n  - component: {fileID: 28633264}\n  m_Layer: 0\n  m_Name: Player (HAP Alpha)\n  m_TagString: Untagged\n  m_Icon: {fileID: 0}\n  m_NavMeshLayer: 0\n  m_StaticEditorFlags: 0\n  m_IsActive: 1\n--- !u!114 &28633264\nMonoBehaviour:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 28633263}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: f3775962864755b43a790abf4d029c32, type: 3}\n  m_Name: \n  m_EditorClassIdentifier: Klak.Hap::Klak.Hap.HapPlayer\n  _pathMode: 0\n  _filePath: TransparencyTest-HapAlpha.mov\n  _time: 0\n  _speed: 1\n  _loop: 1\n  _targetTexture: {fileID: 0}\n  _targetRenderer: {fileID: 11714848}\n  _targetMaterialProperty: _BaseMap\n--- !u!4 &28633265\nTransform:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 28633263}\n  serializedVersion: 2\n  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}\n  m_LocalPosition: {x: 0, y: 0, z: 0}\n  m_LocalScale: {x: 1, y: 1, z: 1}\n  m_ConstrainProportionsScale: 0\n  m_Children:\n  - {fileID: 11714850}\n  m_Father: {fileID: 0}\n  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}\n--- !u!1 &201439697\nGameObject:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  serializedVersion: 6\n  m_Component:\n  - component: {fileID: 201439700}\n  - component: {fileID: 201439699}\n  - component: {fileID: 201439698}\n  - component: {fileID: 201439702}\n  m_Layer: 0\n  m_Name: Cube\n  m_TagString: Untagged\n  m_Icon: {fileID: 0}\n  m_NavMeshLayer: 0\n  m_StaticEditorFlags: 0\n  m_IsActive: 1\n--- !u!23 &201439698\nMeshRenderer:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 201439697}\n  m_Enabled: 1\n  m_CastShadows: 1\n  m_ReceiveShadows: 1\n  m_DynamicOccludee: 1\n  m_StaticShadowCaster: 0\n  m_MotionVectors: 1\n  m_LightProbeUsage: 1\n  m_ReflectionProbeUsage: 1\n  m_RayTracingMode: 2\n  m_RayTraceProcedural: 0\n  m_RayTracingAccelStructBuildFlagsOverride: 0\n  m_RayTracingAccelStructBuildFlags: 1\n  m_SmallMeshCulling: 1\n  m_ForceMeshLod: -1\n  m_MeshLodSelectionBias: 0\n  m_RenderingLayerMask: 1\n  m_RendererPriority: 0\n  m_Materials:\n  - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2}\n  m_StaticBatchInfo:\n    firstSubMesh: 0\n    subMeshCount: 0\n  m_StaticBatchRoot: {fileID: 0}\n  m_ProbeAnchor: {fileID: 0}\n  m_LightProbeVolumeOverride: {fileID: 0}\n  m_ScaleInLightmap: 1\n  m_ReceiveGI: 1\n  m_PreserveUVs: 0\n  m_IgnoreNormalsForChartDetection: 0\n  m_ImportantGI: 0\n  m_StitchLightmapSeams: 1\n  m_SelectedEditorRenderState: 3\n  m_MinimumChartSize: 4\n  m_AutoUVMaxDistance: 0.5\n  m_AutoUVMaxAngle: 89\n  m_LightmapParameters: {fileID: 0}\n  m_GlobalIlluminationMeshLod: 0\n  m_SortingLayerID: 0\n  m_SortingLayer: 0\n  m_SortingOrder: 0\n  m_MaskInteraction: 0\n  m_AdditionalVertexStreams: {fileID: 0}\n--- !u!33 &201439699\nMeshFilter:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 201439697}\n  m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}\n--- !u!4 &201439700\nTransform:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 201439697}\n  serializedVersion: 2\n  m_LocalRotation: {x: 0.25000006, y: -0.06698733, z: 0.25000006, w: 0.9330127}\n  m_LocalPosition: {x: 1.6, y: 0, z: -4}\n  m_LocalScale: {x: 0.5, y: 0.5, z: 0.5}\n  m_ConstrainProportionsScale: 1\n  m_Children: []\n  m_Father: {fileID: 246925888}\n  m_LocalEulerAnglesHint: {x: 30, y: 0, z: 30}\n--- !u!114 &201439702\nMonoBehaviour:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 201439697}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: 99b3dd156c03a80f48913a83361c6d4c, type: 3}\n  m_Name: \n  m_EditorClassIdentifier: Klak.Motion::Klak.Motion.LinearMotion\n  velocity:\n    x: 0\n    y: 0\n    z: 0\n  angularVelocity:\n    x: -90\n    y: 0\n    z: 0\n--- !u!1 &246925887\nGameObject:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  serializedVersion: 6\n  m_Component:\n  - component: {fileID: 246925888}\n  - component: {fileID: 246925889}\n  - component: {fileID: 246925890}\n  m_Layer: 0\n  m_Name: Player (HAP)\n  m_TagString: Untagged\n  m_Icon: {fileID: 0}\n  m_NavMeshLayer: 0\n  m_StaticEditorFlags: 0\n  m_IsActive: 1\n--- !u!4 &246925888\nTransform:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 246925887}\n  serializedVersion: 2\n  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}\n  m_LocalPosition: {x: 0, y: 0, z: 0}\n  m_LocalScale: {x: 1, y: 1, z: 1}\n  m_ConstrainProportionsScale: 0\n  m_Children:\n  - {fileID: 327780397}\n  - {fileID: 201439700}\n  m_Father: {fileID: 0}\n  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}\n--- !u!114 &246925889\nMonoBehaviour:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 246925887}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: f3775962864755b43a790abf4d029c32, type: 3}\n  m_Name: \n  m_EditorClassIdentifier: Klak.Hap::Klak.Hap.HapPlayer\n  _pathMode: 0\n  _filePath: Beeple-FiberOptical-Hap.mov\n  _time: 0\n  _speed: 1\n  _loop: 1\n  _targetTexture: {fileID: 8400000, guid: a4f22813f74e84455bd3d9e41d54ced6, type: 2}\n  _targetRenderer: {fileID: 201439698}\n  _targetMaterialProperty: _BaseMap\n--- !u!114 &246925890\nMonoBehaviour:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 246925887}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: 538bb1d7707cb473f8493b44c63286cc, type: 3}\n  m_Name: \n  m_EditorClassIdentifier: Assembly-CSharp::SeekBar\n  _ui: {fileID: 1940121732}\n--- !u!1 &327780394\nGameObject:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  serializedVersion: 6\n  m_Component:\n  - component: {fileID: 327780397}\n  - component: {fileID: 327780396}\n  - component: {fileID: 327780395}\n  m_Layer: 0\n  m_Name: Backdrop\n  m_TagString: Untagged\n  m_Icon: {fileID: 0}\n  m_NavMeshLayer: 0\n  m_StaticEditorFlags: 0\n  m_IsActive: 1\n--- !u!23 &327780395\nMeshRenderer:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 327780394}\n  m_Enabled: 1\n  m_CastShadows: 1\n  m_ReceiveShadows: 1\n  m_DynamicOccludee: 1\n  m_StaticShadowCaster: 0\n  m_MotionVectors: 1\n  m_LightProbeUsage: 1\n  m_ReflectionProbeUsage: 1\n  m_RayTracingMode: 2\n  m_RayTraceProcedural: 0\n  m_RayTracingAccelStructBuildFlagsOverride: 0\n  m_RayTracingAccelStructBuildFlags: 1\n  m_SmallMeshCulling: 1\n  m_ForceMeshLod: -1\n  m_MeshLodSelectionBias: 0\n  m_RenderingLayerMask: 1\n  m_RendererPriority: 0\n  m_Materials:\n  - {fileID: 2100000, guid: e127fa53264f341caab6ab276ff39b77, type: 2}\n  m_StaticBatchInfo:\n    firstSubMesh: 0\n    subMeshCount: 0\n  m_StaticBatchRoot: {fileID: 0}\n  m_ProbeAnchor: {fileID: 0}\n  m_LightProbeVolumeOverride: {fileID: 0}\n  m_ScaleInLightmap: 1\n  m_ReceiveGI: 1\n  m_PreserveUVs: 0\n  m_IgnoreNormalsForChartDetection: 0\n  m_ImportantGI: 0\n  m_StitchLightmapSeams: 1\n  m_SelectedEditorRenderState: 3\n  m_MinimumChartSize: 4\n  m_AutoUVMaxDistance: 0.5\n  m_AutoUVMaxAngle: 89\n  m_LightmapParameters: {fileID: 0}\n  m_GlobalIlluminationMeshLod: 0\n  m_SortingLayerID: 0\n  m_SortingLayer: 0\n  m_SortingOrder: 0\n  m_MaskInteraction: 0\n  m_AdditionalVertexStreams: {fileID: 0}\n--- !u!33 &327780396\nMeshFilter:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 327780394}\n  m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}\n--- !u!4 &327780397\nTransform:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 327780394}\n  serializedVersion: 2\n  m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}\n  m_LocalPosition: {x: 0, y: 0, z: 0}\n  m_LocalScale: {x: 7.5510006, y: 4.247438, z: 4.247438}\n  m_ConstrainProportionsScale: 1\n  m_Children: []\n  m_Father: {fileID: 246925888}\n  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}\n--- !u!1 &395240107\nGameObject:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  serializedVersion: 6\n  m_Component:\n  - component: {fileID: 395240109}\n  - component: {fileID: 395240108}\n  m_Layer: 0\n  m_Name: Player (HAP Q)\n  m_TagString: Untagged\n  m_Icon: {fileID: 0}\n  m_NavMeshLayer: 0\n  m_StaticEditorFlags: 0\n  m_IsActive: 1\n--- !u!114 &395240108\nMonoBehaviour:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 395240107}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: f3775962864755b43a790abf4d029c32, type: 3}\n  m_Name: \n  m_EditorClassIdentifier: Klak.Hap::Klak.Hap.HapPlayer\n  _pathMode: 0\n  _filePath: Beeple-Hexxx-HapQ.mov\n  _time: 0\n  _speed: 1\n  _loop: 1\n  _targetTexture: {fileID: 0}\n  _targetRenderer: {fileID: 2137533910}\n  _targetMaterialProperty: _MainTex\n--- !u!4 &395240109\nTransform:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 395240107}\n  serializedVersion: 2\n  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}\n  m_LocalPosition: {x: 0, y: 0, z: 0}\n  m_LocalScale: {x: 1, y: 1, z: 1}\n  m_ConstrainProportionsScale: 0\n  m_Children:\n  - {fileID: 2137533909}\n  m_Father: {fileID: 0}\n  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}\n--- !u!1 &1585188254\nGameObject:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  serializedVersion: 6\n  m_Component:\n  - component: {fileID: 1585188257}\n  - component: {fileID: 1585188256}\n  - component: {fileID: 1585188255}\n  m_Layer: 0\n  m_Name: Main Camera\n  m_TagString: MainCamera\n  m_Icon: {fileID: 0}\n  m_NavMeshLayer: 0\n  m_StaticEditorFlags: 0\n  m_IsActive: 1\n--- !u!114 &1585188255\nMonoBehaviour:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 1585188254}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3}\n  m_Name: \n  m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.UniversalAdditionalCameraData\n  m_RenderShadows: 0\n  m_RequiresDepthTextureOption: 2\n  m_RequiresOpaqueTextureOption: 2\n  m_CameraType: 0\n  m_Cameras: []\n  m_RendererIndex: -1\n  m_VolumeLayerMask:\n    serializedVersion: 2\n    m_Bits: 1\n  m_VolumeTrigger: {fileID: 0}\n  m_VolumeFrameworkUpdateModeOption: 2\n  m_RenderPostProcessing: 0\n  m_Antialiasing: 0\n  m_AntialiasingQuality: 2\n  m_StopNaN: 0\n  m_Dithering: 0\n  m_ClearDepth: 1\n  m_AllowXRRendering: 1\n  m_AllowHDROutput: 1\n  m_UseScreenCoordOverride: 0\n  m_ScreenSizeOverride: {x: 0, y: 0, z: 0, w: 0}\n  m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0}\n  m_RequiresDepthTexture: 0\n  m_RequiresColorTexture: 0\n  m_TaaSettings:\n    m_Quality: 3\n    m_FrameInfluence: 0.1\n    m_JitterScale: 1\n    m_MipBias: 0\n    m_VarianceClampScale: 0.9\n    m_ContrastAdaptiveSharpening: 0\n  m_Version: 2\n--- !u!20 &1585188256\nCamera:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 1585188254}\n  m_Enabled: 1\n  serializedVersion: 2\n  m_ClearFlags: 2\n  m_BackGroundColor: {r: 0.07489321, g: 0.103773594, b: 0.09363752, a: 0}\n  m_projectionMatrixMode: 1\n  m_GateFitMode: 2\n  m_FOVAxisMode: 0\n  m_Iso: 200\n  m_ShutterSpeed: 0.005\n  m_Aperture: 16\n  m_FocusDistance: 10\n  m_FocalLength: 50\n  m_BladeCount: 5\n  m_Curvature: {x: 2, y: 11}\n  m_BarrelClipping: 0.25\n  m_Anamorphism: 0\n  m_SensorSize: {x: 36, y: 24}\n  m_LensShift: {x: 0, y: 0}\n  m_NormalizedViewPortRect:\n    serializedVersion: 2\n    x: 0\n    y: 0\n    width: 1\n    height: 1\n  near clip plane: 1\n  far clip plane: 20\n  field of view: 24\n  orthographic: 0\n  orthographic size: 5\n  m_Depth: -1\n  m_CullingMask:\n    serializedVersion: 2\n    m_Bits: 4294967295\n  m_RenderingPath: -1\n  m_TargetTexture: {fileID: 0}\n  m_TargetDisplay: 0\n  m_TargetEye: 3\n  m_HDR: 1\n  m_AllowMSAA: 1\n  m_AllowDynamicResolution: 0\n  m_ForceIntoRT: 0\n  m_OcclusionCulling: 0\n  m_StereoConvergence: 10\n  m_StereoSeparation: 0.022\n--- !u!4 &1585188257\nTransform:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 1585188254}\n  serializedVersion: 2\n  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}\n  m_LocalPosition: {x: 0, y: 0, z: -10}\n  m_LocalScale: {x: 1, y: 1, z: 1}\n  m_ConstrainProportionsScale: 0\n  m_Children: []\n  m_Father: {fileID: 0}\n  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}\n--- !u!1 &1940121731\nGameObject:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  serializedVersion: 6\n  m_Component:\n  - component: {fileID: 1940121733}\n  - component: {fileID: 1940121732}\n  m_Layer: 0\n  m_Name: UI\n  m_TagString: Untagged\n  m_Icon: {fileID: 0}\n  m_NavMeshLayer: 0\n  m_StaticEditorFlags: 0\n  m_IsActive: 1\n--- !u!114 &1940121732\nMonoBehaviour:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 1940121731}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 19102, guid: 0000000000000000e000000000000000, type: 0}\n  m_Name: \n  m_EditorClassIdentifier: UnityEngine.dll::UnityEngine.UIElements.UIDocument\n  m_PanelSettings: {fileID: 11400000, guid: 217443c668dc34029b583fa73e5c4dfc, type: 2}\n  m_ParentUI: {fileID: 0}\n  sourceAsset: {fileID: 9197481963319205126, guid: f9d1722b31b6d45a8b38e8167775d54d, type: 3}\n  m_SortingOrder: 0\n  m_Position: 0\n  m_WorldSpaceSizeMode: 1\n  m_WorldSpaceWidth: 1920\n  m_WorldSpaceHeight: 1080\n  m_PivotReferenceSize: 0\n  m_Pivot: 0\n  m_WorldSpaceCollider: {fileID: 0}\n--- !u!4 &1940121733\nTransform:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 1940121731}\n  serializedVersion: 2\n  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}\n  m_LocalPosition: {x: 0, y: 0, z: 0}\n  m_LocalScale: {x: 1, y: 1, z: 1}\n  m_ConstrainProportionsScale: 0\n  m_Children: []\n  m_Father: {fileID: 0}\n  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}\n--- !u!1 &2111630447\nGameObject:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  serializedVersion: 6\n  m_Component:\n  - component: {fileID: 2111630449}\n  - component: {fileID: 2111630448}\n  m_Layer: 0\n  m_Name: Scripting Test\n  m_TagString: Untagged\n  m_Icon: {fileID: 0}\n  m_NavMeshLayer: 0\n  m_StaticEditorFlags: 0\n  m_IsActive: 1\n--- !u!114 &2111630448\nMonoBehaviour:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 2111630447}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: 2c91f3289fa694fe3ba2e1e6149477b8, type: 3}\n  m_Name: \n  m_EditorClassIdentifier: Assembly-CSharp::ScriptingTest\n  _filename: Beeple-CleanRoom-Hap.mov\n  _destination: {fileID: 8400000, guid: 1bba849debc024a4f8251bd62cceac60, type: 2}\n  _interval: 1\n  _iteration: 10\n--- !u!4 &2111630449\nTransform:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 2111630447}\n  serializedVersion: 2\n  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}\n  m_LocalPosition: {x: 0, y: 0, z: 0}\n  m_LocalScale: {x: 1, y: 1, z: 1}\n  m_ConstrainProportionsScale: 0\n  m_Children: []\n  m_Father: {fileID: 0}\n  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}\n--- !u!1 &2137533908\nGameObject:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  serializedVersion: 6\n  m_Component:\n  - component: {fileID: 2137533909}\n  - component: {fileID: 2137533911}\n  - component: {fileID: 2137533910}\n  m_Layer: 0\n  m_Name: Quad\n  m_TagString: Untagged\n  m_Icon: {fileID: 0}\n  m_NavMeshLayer: 0\n  m_StaticEditorFlags: 0\n  m_IsActive: 1\n--- !u!4 &2137533909\nTransform:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 2137533908}\n  serializedVersion: 2\n  m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}\n  m_LocalPosition: {x: -2.75, y: 0, z: 0}\n  m_LocalScale: {x: 1.7777778, y: 1, z: 1}\n  m_ConstrainProportionsScale: 0\n  m_Children: []\n  m_Father: {fileID: 395240109}\n  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}\n--- !u!23 &2137533910\nMeshRenderer:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 2137533908}\n  m_Enabled: 1\n  m_CastShadows: 1\n  m_ReceiveShadows: 1\n  m_DynamicOccludee: 1\n  m_StaticShadowCaster: 0\n  m_MotionVectors: 1\n  m_LightProbeUsage: 1\n  m_ReflectionProbeUsage: 1\n  m_RayTracingMode: 2\n  m_RayTraceProcedural: 0\n  m_RayTracingAccelStructBuildFlagsOverride: 0\n  m_RayTracingAccelStructBuildFlags: 1\n  m_SmallMeshCulling: 1\n  m_ForceMeshLod: -1\n  m_MeshLodSelectionBias: 0\n  m_RenderingLayerMask: 1\n  m_RendererPriority: 0\n  m_Materials:\n  - {fileID: 2100000, guid: f4060b9dfe1254ee9bb9d4fad7ae4ebd, type: 2}\n  m_StaticBatchInfo:\n    firstSubMesh: 0\n    subMeshCount: 0\n  m_StaticBatchRoot: {fileID: 0}\n  m_ProbeAnchor: {fileID: 0}\n  m_LightProbeVolumeOverride: {fileID: 0}\n  m_ScaleInLightmap: 1\n  m_ReceiveGI: 1\n  m_PreserveUVs: 0\n  m_IgnoreNormalsForChartDetection: 0\n  m_ImportantGI: 0\n  m_StitchLightmapSeams: 1\n  m_SelectedEditorRenderState: 3\n  m_MinimumChartSize: 4\n  m_AutoUVMaxDistance: 0.5\n  m_AutoUVMaxAngle: 89\n  m_LightmapParameters: {fileID: 0}\n  m_GlobalIlluminationMeshLod: 0\n  m_SortingLayerID: 0\n  m_SortingLayer: 0\n  m_SortingOrder: 0\n  m_MaskInteraction: 0\n  m_AdditionalVertexStreams: {fileID: 0}\n--- !u!33 &2137533911\nMeshFilter:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 2137533908}\n  m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}\n--- !u!1660057539 &9223372036854775807\nSceneRoots:\n  m_ObjectHideFlags: 0\n  m_Roots:\n  - {fileID: 1940121733}\n  - {fileID: 1585188257}\n  - {fileID: 246925888}\n  - {fileID: 28633265}\n  - {fileID: 395240109}\n  - {fileID: 2111630449}\n"
  },
  {
    "path": "Assets/Demo.unity.meta",
    "content": "fileFormatVersion: 2\nguid: 9d1e54e0ecdcb476597522d5c402dcdb\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/StreamingAssets/Tests/Hap/000001.png.meta",
    "content": "fileFormatVersion: 2\nguid: f71b7a4c945804f1ca842cff0c10b46d\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/StreamingAssets/Tests/Hap/000002.png.meta",
    "content": "fileFormatVersion: 2\nguid: ff68e82d75fdf47d8a5ad6b9c5fc99d3\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/StreamingAssets/Tests/Hap/000003.png.meta",
    "content": "fileFormatVersion: 2\nguid: 0a2d50a92701046c4b2f72fb11f038b8\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/StreamingAssets/Tests/Hap/000004.png.meta",
    "content": "fileFormatVersion: 2\nguid: ded47b6e71da14e1abb2ea48f2e60375\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/StreamingAssets/Tests/Hap/000005.png.meta",
    "content": "fileFormatVersion: 2\nguid: 6861db0b44d0d4e78b701b38376b62c3\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/StreamingAssets/Tests/Hap/TestCards.mov.meta",
    "content": "fileFormatVersion: 2\nguid: e3addd278331242d6b95bb6990e5216f\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/StreamingAssets/Tests/Hap.meta",
    "content": "fileFormatVersion: 2\nguid: c4ca400c14640478aaf9bc0cec9b12c7\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/StreamingAssets/Tests/HapAlpha/000001.png.meta",
    "content": "fileFormatVersion: 2\nguid: 016f08f72c65549f69c9baa63b0e3ed0\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/StreamingAssets/Tests/HapAlpha/HapAlpha.mov.meta",
    "content": "fileFormatVersion: 2\nguid: 9daa334d7e07e4a7092db093efe0efb8\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/StreamingAssets/Tests/HapAlpha.meta",
    "content": "fileFormatVersion: 2\nguid: 362186a70fcc54855bcddda1af9f0e90\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/StreamingAssets/Tests/HapQ/000001.png.meta",
    "content": "fileFormatVersion: 2\nguid: 1c1d2bb1e597e432391ee23db4b75d75\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/StreamingAssets/Tests/HapQ/000002.png.meta",
    "content": "fileFormatVersion: 2\nguid: 469568f79f88b49f593d58b043aab26c\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/StreamingAssets/Tests/HapQ/000003.png.meta",
    "content": "fileFormatVersion: 2\nguid: 6f8073f45b28847209cec3fa77e89e29\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/StreamingAssets/Tests/HapQ/000004.png.meta",
    "content": "fileFormatVersion: 2\nguid: 554c0617cfb824ddfa28f0ea0ae8869c\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/StreamingAssets/Tests/HapQ/000005.png.meta",
    "content": "fileFormatVersion: 2\nguid: 44d4725e9db92447ca83e803922e54f3\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/StreamingAssets/Tests/HapQ/TestCards.mov.meta",
    "content": "fileFormatVersion: 2\nguid: 4ab52f88a57a94f50946db395a7e32c6\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/StreamingAssets/Tests/HapQ.meta",
    "content": "fileFormatVersion: 2\nguid: 0a1a105c4ce2a40b28466bfc9f59f08f\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/StreamingAssets/Tests/RGBCycle/RGBCycle24.mov.meta",
    "content": "fileFormatVersion: 2\nguid: d17c63c5f7293493ca0b65bfc71c7808\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/StreamingAssets/Tests/RGBCycle/RGBCycle24000-1001.mov.meta",
    "content": "fileFormatVersion: 2\nguid: 9b88a94eb79614c7b8be1396430b7fb9\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/StreamingAssets/Tests/RGBCycle/RGBCycle25.mov.meta",
    "content": "fileFormatVersion: 2\nguid: 20f5482d0639347b4b0d62b7f553d61a\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/StreamingAssets/Tests/RGBCycle/RGBCycle30.mov.meta",
    "content": "fileFormatVersion: 2\nguid: 04a711eb985854488a36cecaa629492c\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/StreamingAssets/Tests/RGBCycle/RGBCycle30000-1001.mov.meta",
    "content": "fileFormatVersion: 2\nguid: 5b06b773e4b22470b9572d25f575eb91\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/StreamingAssets/Tests/RGBCycle/RGBCycle50.mov.meta",
    "content": "fileFormatVersion: 2\nguid: 35a0a8d8451fe4dff943ae124f8fc02c\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/StreamingAssets/Tests/RGBCycle/RGBCycle60.mov.meta",
    "content": "fileFormatVersion: 2\nguid: 1103893dcc48f48cbbf5f4681f02ccb4\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/StreamingAssets/Tests/RGBCycle/RGBCycle60000-1001.mov.meta",
    "content": "fileFormatVersion: 2\nguid: 005f182f1b759493eadafadc1102eea9\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/StreamingAssets/Tests/RGBCycle.meta",
    "content": "fileFormatVersion: 2\nguid: eaa1315fa4f1141c987260e3f3023bcf\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/StreamingAssets/Tests/日本語/Test.mov.meta",
    "content": "fileFormatVersion: 2\nguid: a32999a4f135840ec9876594a54a0b6a\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/StreamingAssets/Tests/日本語.meta",
    "content": "fileFormatVersion: 2\nguid: 7a8b3546c2bae4b729e75ccdedeab1d8\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/StreamingAssets/Tests.meta",
    "content": "fileFormatVersion: 2\nguid: 026a9869dae424ee8b8609aa087fec1c\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/StreamingAssets.meta",
    "content": "fileFormatVersion: 2\nguid: de35ded2fd399421a88ca973172cc856\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Tests/Runtime/HapAlphaPlaybackTest.cs",
    "content": "using System.Collections;\nusing System.IO;\nusing Klak.Hap;\nusing NUnit.Framework;\nusing UnityEngine;\nusing UnityEngine.TestTools;\n\npublic sealed class HapAlphaPlaybackTest\n{\n    const string MoviePath = \"Tests/HapAlpha/HapAlpha.mov\";\n    const string FramesDirName = \"Tests/HapAlpha\";\n    const string ExpectedFrame = \"000001.png\";\n\n    const float MatchThreshold = 0.99f;\n    const float ChannelTolerance = 0.08f;\n    const float AlphaTolerance = 0.08f;\n    const int SamplesPerAxis = 64;\n    const bool FlipExpectedY = true;\n\n    [UnityTest]\n    public IEnumerator HapAlphaMatchesExtractedFrame()\n    {\n        if (!Application.isPlaying)\n        {\n            Assert.Ignore(\"PlayMode only.\");\n            yield break;\n        }\n\n        var go = new GameObject(\"HapAlphaTestPlayer\");\n\n        try\n        {\n            var player = go.AddComponent<HapPlayer>();\n            player.Open(MoviePath, HapPlayer.PathMode.StreamingAssets);\n            player.loop = false;\n            player.speed = 0;\n\n            yield return null;\n            player.UpdateNow();\n\n            var pathInfo = $\"Resolved path: {player.resolvedFilePath}\";\n            Assert.That(player.isValid, Is.True, pathInfo);\n            Assert.That(player.frameCount, Is.GreaterThan(0), pathInfo);\n            Assert.That(player.frameWidth, Is.GreaterThan(0), pathInfo);\n            Assert.That(player.frameHeight, Is.GreaterThan(0), pathInfo);\n            Assert.That(player.texture, Is.Not.Null, pathInfo);\n\n            var duration = (float)player.streamDuration;\n            var dt = duration / player.frameCount;\n\n            player.time = dt * 0.1f;\n            player.UpdateNow();\n            yield return null;\n            yield return null;\n\n            var expected = LoadExpectedTexture(ExpectedFrame);\n            try\n            {\n                var ratio = ComputeMatchRatio(player.texture, expected);\n                var message = $\"{pathInfo} Expected:{ExpectedFrame} Match:{ratio:0.000}\";\n                Assert.That(ratio, Is.GreaterThanOrEqualTo(MatchThreshold), message);\n            }\n            finally\n            {\n                Object.Destroy(expected);\n            }\n        }\n        finally\n        {\n            Object.Destroy(go);\n        }\n    }\n\n    static Texture2D LoadExpectedTexture(string fileName)\n    {\n        var path = Path.Combine(Application.streamingAssetsPath, FramesDirName, fileName);\n        var data = File.ReadAllBytes(path);\n        var tex = new Texture2D(2, 2, TextureFormat.RGBA32, false);\n        tex.LoadImage(data);\n        return tex;\n    }\n\n    static float ComputeMatchRatio(Texture2D actual, Texture2D expected)\n    {\n        var width = Mathf.Min(actual.width, expected.width);\n        var height = Mathf.Min(actual.height, expected.height);\n        var stepX = Mathf.Max(1, width / SamplesPerAxis);\n        var stepY = Mathf.Max(1, height / SamplesPerAxis);\n\n        var match = 0;\n        var total = 0;\n\n        for (var y = stepY / 2; y < height; y += stepY)\n            for (var x = stepX / 2; x < width; x += stepX)\n            {\n                var a = actual.GetPixel(x, y);\n                var ey = FlipExpectedY ? height - 1 - y : y;\n                var e = expected.GetPixel(x, ey);\n                if (IsMatch(a, e)) match++;\n                total++;\n            }\n\n        return total > 0 ? (float)match / total : 0;\n    }\n\n    static bool IsMatch(Color actual, Color expected)\n        => Mathf.Abs(actual.r - expected.r) <= ChannelTolerance\n           && Mathf.Abs(actual.g - expected.g) <= ChannelTolerance\n           && Mathf.Abs(actual.b - expected.b) <= ChannelTolerance\n           && Mathf.Abs(actual.a - expected.a) <= AlphaTolerance;\n}\n"
  },
  {
    "path": "Assets/Tests/Runtime/HapAlphaPlaybackTest.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 836849b85f39e4f2eb69dc82dd0bf0fe"
  },
  {
    "path": "Assets/Tests/Runtime/JapanesePathPlaybackTest.cs",
    "content": "using System.Collections;\nusing Klak.Hap;\nusing NUnit.Framework;\nusing UnityEngine;\nusing UnityEngine.TestTools;\n\npublic sealed class JapanesePathPlaybackTest\n{\n    const string TestPath = \"Tests/日本語/Test.mov\";\n\n    [UnityTest]\n    public IEnumerator CanPlayHapInJapanesePath()\n    {\n        if (!Application.isPlaying)\n        {\n            Assert.Ignore(\"PlayMode only.\");\n            yield break;\n        }\n\n        var go = new GameObject(\"HapTestPlayer\");\n        try\n        {\n            var player = go.AddComponent<HapPlayer>();\n            player.Open(TestPath, HapPlayer.PathMode.StreamingAssets);\n\n            for (var i = 0; i < 5; i++)\n            {\n                yield return null;\n                player.UpdateNow();\n            }\n\n            var pathInfo = $\"Resolved path: {player.resolvedFilePath}\";\n            Assert.That(player.isValid, Is.True, pathInfo);\n            Assert.That(player.frameCount, Is.GreaterThan(0), pathInfo);\n            Assert.That(player.frameWidth, Is.GreaterThan(0), pathInfo);\n            Assert.That(player.frameHeight, Is.GreaterThan(0), pathInfo);\n            Assert.That(player.texture, Is.Not.Null, pathInfo);\n            Assert.That(player.codecType, Is.Not.EqualTo(CodecType.Unsupported), pathInfo);\n        }\n        finally\n        {\n            Object.Destroy(go);\n        }\n    }\n}\n"
  },
  {
    "path": "Assets/Tests/Runtime/JapanesePathPlaybackTest.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 0397f44a895774978874377ddf34f82c"
  },
  {
    "path": "Assets/Tests/Runtime/Klak.Hap.Runtime.Tests.asmdef",
    "content": "{\n    \"name\": \"Klak.Hap.Runtime.Tests\",\n    \"rootNamespace\": \"\",\n    \"references\": [\n        \"Klak.Hap\",\n        \"UnityEngine.TestRunner\"\n    ],\n    \"includePlatforms\": [],\n    \"excludePlatforms\": [],\n    \"allowUnsafeCode\": false,\n    \"overrideReferences\": false,\n    \"precompiledReferences\": [],\n    \"autoReferenced\": true,\n    \"defineConstraints\": [],\n    \"versionDefines\": [],\n    \"noEngineReferences\": false\n}"
  },
  {
    "path": "Assets/Tests/Runtime/Klak.Hap.Runtime.Tests.asmdef.meta",
    "content": "fileFormatVersion: 2\nguid: 1c2d58c8d70c843c7a4747274235802b\nAssemblyDefinitionImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Tests/Runtime/RgbCycleFrameMappingTest.cs",
    "content": "using System.Collections;\nusing Klak.Hap;\nusing NUnit.Framework;\nusing UnityEngine;\nusing UnityEngine.TestTools;\n\npublic sealed class RgbCycleFrameMappingTest\n{\n    static readonly string[] TestPaths =\n    {\n        \"Tests/RGBCycle/RGBCycle24.mov\",\n        \"Tests/RGBCycle/RGBCycle24000-1001.mov\",\n        \"Tests/RGBCycle/RGBCycle25.mov\",\n        \"Tests/RGBCycle/RGBCycle30.mov\",\n        \"Tests/RGBCycle/RGBCycle30000-1001.mov\",\n        \"Tests/RGBCycle/RGBCycle50.mov\",\n        \"Tests/RGBCycle/RGBCycle60.mov\",\n        \"Tests/RGBCycle/RGBCycle60000-1001.mov\"\n    };\n\n    enum RgbExpected { Red, Green, Blue }\n\n    [UnityTest]\n    public IEnumerator RgbCycleFrameMappingIsCorrect()\n    {\n        if (!Application.isPlaying)\n        {\n            Assert.Ignore(\"PlayMode only.\");\n            yield break;\n        }\n\n        foreach (var path in TestPaths)\n            foreach (var step in VerifyFile(path))\n                yield return step;\n    }\n\n    IEnumerable VerifyFile(string path)\n    {\n        var go = new GameObject(\"HapTestPlayer\");\n\n        try\n        {\n            var player = go.AddComponent<HapPlayer>();\n            player.Open(path, HapPlayer.PathMode.StreamingAssets);\n            player.loop = false;\n            player.speed = 0;\n\n            yield return null;\n            player.UpdateNow();\n\n            var pathInfo = $\"Resolved path: {player.resolvedFilePath}\";\n            Assert.That(player.isValid, Is.True, pathInfo);\n            Assert.That(player.frameCount, Is.GreaterThan(0), pathInfo);\n            Assert.That(player.frameWidth, Is.GreaterThan(0), pathInfo);\n            Assert.That(player.frameHeight, Is.GreaterThan(0), pathInfo);\n            Assert.That(player.texture, Is.Not.Null, pathInfo);\n\n            var duration = (float)player.streamDuration;\n            var frameCount = player.frameCount;\n            var dt = duration / frameCount;\n            var maxFrames = Mathf.Min(frameCount, Mathf.FloorToInt(0.5f / dt) + 1);\n            var cx = player.frameWidth / 2;\n            var cy = player.frameHeight / 2;\n\n            for (var i = 0; i < maxFrames; i++)\n            {\n                player.time = i * dt + dt * 0.1f;\n\n                player.UpdateNow();\n                yield return null;\n                yield return null;\n\n                var actual = player.texture.GetPixel(cx, cy);\n                var expected = ExpectedForFrame(i);\n                AssertRgbColor(actual, expected, pathInfo, i);\n                yield return null;\n                yield return null;\n            }\n        }\n        finally\n        {\n            Object.Destroy(go);\n        }\n    }\n\n    static RgbExpected ExpectedForFrame(int frameIndex)\n        => (RgbExpected)(frameIndex % 3);\n\n    static void AssertRgbColor(Color actual, RgbExpected expected, string pathInfo, int frameIndex)\n    {\n        var message = $\"{pathInfo} Frame: {frameIndex} Color: {actual}\";\n\n        if (expected == RgbExpected.Red)\n        {\n            Assert.That(actual.r, Is.GreaterThan(0.8f), message);\n            Assert.That(actual.g, Is.LessThan(0.2f), message);\n            Assert.That(actual.b, Is.LessThan(0.2f), message);\n        }\n        else if (expected == RgbExpected.Green)\n        {\n            Assert.That(actual.g, Is.GreaterThan(0.8f), message);\n            Assert.That(actual.r, Is.LessThan(0.2f), message);\n            Assert.That(actual.b, Is.LessThan(0.2f), message);\n        }\n        else\n        {\n            Assert.That(actual.b, Is.GreaterThan(0.8f), message);\n            Assert.That(actual.r, Is.LessThan(0.2f), message);\n            Assert.That(actual.g, Is.LessThan(0.2f), message);\n        }\n    }\n}\n"
  },
  {
    "path": "Assets/Tests/Runtime/RgbCycleFrameMappingTest.cs.meta",
    "content": "fileFormatVersion: 2\nguid: e48e4d437ac8346139c9ba9f277e7beb"
  },
  {
    "path": "Assets/Tests/Runtime/TestCardsPlaybackTest.cs",
    "content": "using System.Collections;\nusing System.IO;\nusing Klak.Hap;\nusing NUnit.Framework;\nusing UnityEngine;\nusing UnityEngine.TestTools;\n\npublic sealed class TestCardsPlaybackTest\n{\n    const string HapMoviePath = \"Tests/Hap/TestCards.mov\";\n    const string HapFramesDirName = \"Tests/Hap\";\n    const string HapQMoviePath = \"Tests/HapQ/TestCards.mov\";\n    const string HapQFramesDirName = \"Tests/HapQ\";\n\n    const float MatchThreshold = 0.99f;\n    const float ChannelTolerance = 0.08f;\n\n    static readonly string[] FramePngs =\n    {\n        \"000001.png\",\n        \"000002.png\",\n        \"000003.png\",\n        \"000004.png\",\n        \"000005.png\"\n    };\n\n    [UnityTest]\n    public IEnumerator TestCardsMatchPngFrames()\n    {\n        if (!Application.isPlaying)\n        {\n            Assert.Ignore(\"PlayMode only.\");\n            yield break;\n        }\n\n        foreach (var step in VerifySet(\"HapTestPlayer\", HapMoviePath, HapFramesDirName))\n            yield return step;\n        foreach (var step in VerifySet(\"HapQTestPlayer\", HapQMoviePath, HapQFramesDirName))\n            yield return step;\n    }\n\n    IEnumerable VerifySet(string objectName, string moviePath, string framesDirName)\n    {\n        var go = new GameObject(objectName);\n        RenderTexture targetTexture = null;\n        Texture2D readbackTexture = null;\n\n        try\n        {\n            var player = go.AddComponent<HapPlayer>();\n            player.Open(moviePath, HapPlayer.PathMode.StreamingAssets);\n            player.loop = false;\n            player.speed = 0;\n\n            yield return null;\n            player.UpdateNow();\n\n            var pathInfo = $\"Resolved path: {player.resolvedFilePath}\";\n            Assert.That(player.isValid, Is.True, pathInfo);\n            Assert.That(player.frameCount, Is.GreaterThanOrEqualTo(FramePngs.Length), pathInfo);\n            Assert.That(player.frameWidth, Is.GreaterThan(0), pathInfo);\n            Assert.That(player.frameHeight, Is.GreaterThan(0), pathInfo);\n            Assert.That(player.texture, Is.Not.Null, pathInfo);\n\n            targetTexture = new RenderTexture(\n                player.frameWidth, player.frameHeight, 0, RenderTextureFormat.ARGB32\n            );\n            targetTexture.wrapMode = TextureWrapMode.Clamp;\n            player.targetTexture = targetTexture;\n            readbackTexture = new Texture2D(\n                player.frameWidth, player.frameHeight, TextureFormat.RGBA32, false\n            );\n\n            var duration = (float)player.streamDuration;\n            var frameCount = player.frameCount;\n            var dt = duration / frameCount;\n\n            for (var i = 0; i < FramePngs.Length; i++)\n            {\n                player.time = i * dt + dt * 0.1f;\n\n                player.UpdateNow();\n                yield return null;\n                yield return null;\n\n                ReadRenderTexture(targetTexture, readbackTexture);\n                var actualTexture = readbackTexture;\n\n                var expected = LoadExpectedTexture(framesDirName, FramePngs[i]);\n                try\n                {\n                    var ratio = ComputeMatchRatio(actualTexture, expected);\n                    var message = $\"{pathInfo} Frame:{i} Expected:{FramePngs[i]} Match:{ratio:0.000}\";\n                    Assert.That(ratio, Is.GreaterThanOrEqualTo(MatchThreshold), message);\n                }\n                finally\n                {\n                    Object.Destroy(expected);\n                }\n\n                yield return null;\n                yield return null;\n            }\n        }\n        finally\n        {\n            if (targetTexture != null)\n                targetTexture.Release();\n            Object.Destroy(targetTexture);\n            Object.Destroy(readbackTexture);\n            Object.Destroy(go);\n        }\n    }\n\n    static Texture2D LoadExpectedTexture(string framesDirName, string fileName)\n    {\n        var path = Path.Combine(Application.streamingAssetsPath, framesDirName, fileName);\n        var data = File.ReadAllBytes(path);\n        var tex = new Texture2D(2, 2, TextureFormat.RGBA32, false);\n        tex.LoadImage(data);\n        return tex;\n    }\n\n    static float ComputeMatchRatio(Texture2D actual, Texture2D expected)\n    {\n        var width = Mathf.Min(actual.width, expected.width);\n        var height = Mathf.Min(actual.height, expected.height);\n\n        var match = 0;\n        var total = width * height;\n\n        for (var y = 0; y < height; y++)\n            for (var x = 0; x < width; x++)\n            {\n                var a = actual.GetPixel(x, y);\n                var e = expected.GetPixel(x, y);\n                if (IsMatch(a, e)) match++;\n            }\n\n        return total > 0 ? (float)match / total : 0;\n    }\n\n    static bool IsMatch(Color actual, Color expected)\n        => Mathf.Abs(actual.r - expected.r) <= ChannelTolerance\n           && Mathf.Abs(actual.g - expected.g) <= ChannelTolerance\n           && Mathf.Abs(actual.b - expected.b) <= ChannelTolerance;\n\n    static void ReadRenderTexture(RenderTexture source, Texture2D destination)\n    {\n        var previous = RenderTexture.active;\n        RenderTexture.active = source;\n        destination.ReadPixels(new Rect(0, 0, source.width, source.height), 0, 0);\n        destination.Apply();\n        RenderTexture.active = previous;\n    }\n}\n"
  },
  {
    "path": "Assets/Tests/Runtime/TestCardsPlaybackTest.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 501079e0a007c4c9686d841e0bcb0b60"
  },
  {
    "path": "Assets/Tests/Runtime.meta",
    "content": "fileFormatVersion: 2\nguid: 6f2caeec0887b4dd5a03360e87b42af7\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/Tests.meta",
    "content": "fileFormatVersion: 2\nguid: c9392bf0e434b4e378744f7ed2695485\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)\nand this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).\n\n## [1.0.0] - 2026-02-05\n\n### Added\n\n- Added a Unity 6.3 demo scene updated for URP and UI Toolkit.\n- Added runtime tests and a test data downloader for Hap, HapQ, and HapAlpha assets.\n\n### Changed\n\n- Updated HAP and Snappy source code and refreshed native plugin binaries.\n- Migrated Windows builds to MinGW and refactored the native build pipelines and Makefiles.\n\n### Fixed\n\n- Fixed a Windows crash when paths contain Japanese characters. (PR #49)\n- Fixed obsolete ShaderUtil API usage in the editor code.\n\n## [0.1.20] - 2021-12-03\n\n### Added\n\n- Added `UpdateNow` for custom Timeline integration.\n\n## [0.1.19] - 2021-06-05\n\n### Added\n\n- Added arm64 binary to the macOS plugin.\n- Added no-delay mode.\n- Added decoder thread control improvement.\n\n### Changed\n\n- Updated for Unity 2020.3.\n- Moved package contexts into the Packages directory.\n\n### Fixed\n\n- Fixed rounding error issue.\n- Fixed compilation error on Unity 2019.4.\n"
  },
  {
    "path": "LICENSE",
    "content": "License summary:\n\nKlakHAP     - MIT license\nHAP codec   - FreeBSD license\nSnappy      - BSD 3-clause license\nMP4 demuxer - CC0 (public domain)\n\n-------------------------------------------------------------------------------\nKlakHAP\nhttps://github.com/keijiro/KlakHap\n-------------------------------------------------------------------------------\n\nCopyright (c) 2019 Unity Technologies\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-------------------------------------------------------------------------------\nHAP\nhttps://github.com/Vidvox/hap\n-------------------------------------------------------------------------------\n\nCopyright (c) 2012-2013, Tom Butterworth and Vidvox LLC. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright\nnotice, this list of conditions and the following disclaimer in the\ndocumentation and/or other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n-------------------------------------------------------------------------------\nSnappy\nhttps://github.com/google/snappy\n-------------------------------------------------------------------------------\n\nCopyright 2011, Google Inc.\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    * Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\ncopyright notice, this list of conditions and the following disclaimer\nin the documentation and/or other materials provided with the\ndistribution.\n    * Neither the name of Google Inc. nor the names of its\ncontributors may be used to endorse or promote products derived from\nthis software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n-------------------------------------------------------------------------------\nMinimalistic MP4 muxer & demuxer\nhttps://github.com/aspt/mp4\n-------------------------------------------------------------------------------\n\nCC0 1.0 Universal\n\nStatement of Purpose\n\nThe laws of most jurisdictions throughout the world automatically confer\nexclusive Copyright and Related Rights (defined below) upon the creator and\nsubsequent owner(s) (each and all, an \"owner\") of an original work of\nauthorship and/or a database (each, a \"Work\").\n\nCertain owners wish to permanently relinquish those rights to a Work for the\npurpose of contributing to a commons of creative, cultural and scientific\nworks (\"Commons\") that the public can reliably and without fear of later\nclaims of infringement build upon, modify, incorporate in other works, reuse\nand redistribute as freely as possible in any form whatsoever and for any\npurposes, including without limitation commercial purposes. These owners may\ncontribute to the Commons to promote the ideal of a free culture and the\nfurther production of creative, cultural and scientific works, or to gain\nreputation or greater distribution for their Work in part through the use and\nefforts of others.\n\nFor these and/or other purposes and motivations, and without any expectation\nof additional consideration or compensation, the person associating CC0 with a\nWork (the \"Affirmer\"), to the extent that he or she is an owner of Copyright\nand Related Rights in the Work, voluntarily elects to apply CC0 to the Work\nand publicly distribute the Work under its terms, with knowledge of his or her\nCopyright and Related Rights in the Work and the meaning and intended legal\neffect of CC0 on those rights.\n\n1. Copyright and Related Rights. A Work made available under CC0 may be\nprotected by copyright and related or neighboring rights (\"Copyright and\nRelated Rights\"). Copyright and Related Rights include, but are not limited\nto, the following:\n\n  i. the right to reproduce, adapt, distribute, perform, display, communicate,\n  and translate a Work;\n\n  ii. moral rights retained by the original author(s) and/or performer(s);\n\n  iii. publicity and privacy rights pertaining to a person's image or likeness\n  depicted in a Work;\n\n  iv. rights protecting against unfair competition in regards to a Work,\n  subject to the limitations in paragraph 4(a), below;\n\n  v. rights protecting the extraction, dissemination, use and reuse of data in\n  a Work;\n\n  vi. database rights (such as those arising under Directive 96/9/EC of the\n  European Parliament and of the Council of 11 March 1996 on the legal\n  protection of databases, and under any national implementation thereof,\n  including any amended or successor version of such directive); and\n\n  vii. other similar, equivalent or corresponding rights throughout the world\n  based on applicable law or treaty, and any national implementations thereof.\n\n2. Waiver. To the greatest extent permitted by, but not in contravention of,\napplicable law, Affirmer hereby overtly, fully, permanently, irrevocably and\nunconditionally waives, abandons, and surrenders all of Affirmer's Copyright\nand Related Rights and associated claims and causes of action, whether now\nknown or unknown (including existing as well as future claims and causes of\naction), in the Work (i) in all territories worldwide, (ii) for the maximum\nduration provided by applicable law or treaty (including future time\nextensions), (iii) in any current or future medium and for any number of\ncopies, and (iv) for any purpose whatsoever, including without limitation\ncommercial, advertising or promotional purposes (the \"Waiver\"). Affirmer makes\nthe Waiver for the benefit of each member of the public at large and to the\ndetriment of Affirmer's heirs and successors, fully intending that such Waiver\nshall not be subject to revocation, rescission, cancellation, termination, or\nany other legal or equitable action to disrupt the quiet enjoyment of the Work\nby the public as contemplated by Affirmer's express Statement of Purpose.\n\n3. Public License Fallback. Should any part of the Waiver for any reason be\njudged legally invalid or ineffective under applicable law, then the Waiver\nshall be preserved to the maximum extent permitted taking into account\nAffirmer's express Statement of Purpose. In addition, to the extent the Waiver\nis so judged Affirmer hereby grants to each affected person a royalty-free,\nnon transferable, non sublicensable, non exclusive, irrevocable and\nunconditional license to exercise Affirmer's Copyright and Related Rights in\nthe Work (i) in all territories worldwide, (ii) for the maximum duration\nprovided by applicable law or treaty (including future time extensions), (iii)\nin any current or future medium and for any number of copies, and (iv) for any\npurpose whatsoever, including without limitation commercial, advertising or\npromotional purposes (the \"License\"). The License shall be deemed effective as\nof the date CC0 was applied by Affirmer to the Work. Should any part of the\nLicense for any reason be judged legally invalid or ineffective under\napplicable law, such partial invalidity or ineffectiveness shall not\ninvalidate the remainder of the License, and in such case Affirmer hereby\naffirms that he or she will not (i) exercise any of his or her remaining\nCopyright and Related Rights in the Work or (ii) assert any associated claims\nand causes of action with respect to the Work, in either case contrary to\nAffirmer's express Statement of Purpose.\n\n4. Limitations and Disclaimers.\n\n  a. No trademark or patent rights held by Affirmer are waived, abandoned,\n  surrendered, licensed or otherwise affected by this document.\n\n  b. Affirmer offers the Work as-is and makes no representations or warranties\n  of any kind concerning the Work, express, implied, statutory or otherwise,\n  including without limitation warranties of title, merchantability, fitness\n  for a particular purpose, non infringement, or the absence of latent or\n  other defects, accuracy, or the present or absence of errors, whether or not\n  discoverable, all to the greatest extent permissible under applicable law.\n\n  c. Affirmer disclaims responsibility for clearing rights of other persons\n  that may apply to the Work or any use thereof, including without limitation\n  any person's Copyright and Related Rights in the Work. Further, Affirmer\n  disclaims responsibility for obtaining any necessary consents, permissions\n  or other rights required for any use of the Work.\n\n  d. Affirmer understands and acknowledges that Creative Commons is not a\n  party to this document and has no duty or obligation with respect to this\n  CC0 or use of the Work.\n\nFor more information, please see\n<http://creativecommons.org/publicdomain/zero/1.0/>\n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/CHANGELOG.md",
    "content": "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)\nand this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).\n\n## [1.0.0] - 2026-02-05\n\n### Added\n\n- Added a Unity 6.3 demo scene updated for URP and UI Toolkit.\n- Added runtime tests and a test data downloader for Hap, HapQ, and HapAlpha assets.\n\n### Changed\n\n- Updated HAP and Snappy source code and refreshed native plugin binaries.\n- Migrated Windows builds to MinGW and refactored the native build pipelines and Makefiles.\n\n### Fixed\n\n- Fixed a Windows crash when paths contain Japanese characters. (PR #49)\n- Fixed obsolete ShaderUtil API usage in the editor code.\n\n## [0.1.20] - 2021-12-03\n\n### Added\n\n- Added `UpdateNow` for custom Timeline integration.\n\n## [0.1.19] - 2021-06-05\n\n### Added\n\n- Added arm64 binary to the macOS plugin.\n- Added no-delay mode.\n- Added decoder thread control improvement.\n\n### Changed\n\n- Updated for Unity 2020.3.\n- Moved package contexts into the Packages directory.\n\n### Fixed\n\n- Fixed rounding error issue.\n- Fixed compilation error on Unity 2019.4.\n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/CHANGELOG.md.meta",
    "content": "fileFormatVersion: 2\nguid: 1f2cacd9a85145aca9f81904d75ae53b\nTextScriptImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Editor/HapPlayerEditor.cs",
    "content": "using UnityEngine;\nusing UnityEditor;\n\nnamespace Klak.Hap\n{\n    [CanEditMultipleObjects]\n    [CustomEditor(typeof(HapPlayer))]\n    sealed class HapPlayerEditor : Editor\n    {\n        SerializedProperty _filePath;\n        SerializedProperty _pathMode;\n\n        SerializedProperty _time;\n        SerializedProperty _speed;\n        SerializedProperty _loop;\n\n        SerializedProperty _targetTexture;\n        SerializedProperty _targetRenderer;\n        SerializedProperty _targetMaterialProperty;\n\n        static class Labels\n        {\n            public static readonly GUIContent Property = new GUIContent(\"Property\");\n            public static readonly GUIContent Select = new GUIContent(\"Select\");\n        }\n\n        string _sourceInfo;\n\n        void ShowSourceInfo(HapPlayer player)\n        {\n            if (!player.enabled || !player.gameObject.activeInHierarchy) return;\n\n            if (!player.isValid)\n            {\n                EditorGUILayout.HelpBox(\n                    \"Failed to open file. \" +\n                    \"Please specify a valid HAP-encoded .mov file.\",\n                    MessageType.Warning\n                );\n                return;\n            }\n\n            if (_sourceInfo == null)\n                _sourceInfo = string.Format(\n                    \"Codec: {0}\\n\" +\n                    \"Frame dimensions: {1} x {2}\\n\" +\n                    \"Stream duration: {3:0.00}\\n\" +\n                    \"Frame rate: {4:0.00}\",\n                    player.codecType,\n                    player.frameWidth, player.frameHeight,\n                    player.streamDuration,\n                    player.frameCount / player.streamDuration\n                );\n\n            EditorGUILayout.HelpBox(_sourceInfo, MessageType.None);\n        }\n\n        void OnEnable()\n        {\n            _filePath = serializedObject.FindProperty(\"_filePath\");\n            _pathMode = serializedObject.FindProperty(\"_pathMode\");\n\n            _time = serializedObject.FindProperty(\"_time\");\n            _speed = serializedObject.FindProperty(\"_speed\");\n            _loop = serializedObject.FindProperty(\"_loop\");\n\n            _targetTexture = serializedObject.FindProperty(\"_targetTexture\");\n            _targetRenderer = serializedObject.FindProperty(\"_targetRenderer\");\n            _targetMaterialProperty = serializedObject.FindProperty(\"_targetMaterialProperty\");\n        }\n\n        public override void OnInspectorGUI()\n        {\n            var reload = false;\n\n            serializedObject.Update();\n\n            // Source infomation\n            if (!_filePath.hasMultipleDifferentValues &&\n                !_pathMode.hasMultipleDifferentValues &&\n                !string.IsNullOrEmpty(_filePath.stringValue))\n            {\n                ShowSourceInfo((HapPlayer)target);\n            }\n\n            // Source file\n            EditorGUI.BeginChangeCheck();\n            EditorGUILayout.DelayedTextField(_filePath);\n            EditorGUILayout.PropertyField(_pathMode);\n            reload = EditorGUI.EndChangeCheck();\n\n            // Playback control\n            EditorGUILayout.PropertyField(_time);\n            EditorGUILayout.PropertyField(_speed);\n            EditorGUILayout.PropertyField(_loop);\n\n            // Target texture/renderer\n            EditorGUILayout.PropertyField(_targetTexture);\n            EditorGUILayout.PropertyField(_targetRenderer);\n\n            EditorGUI.indentLevel++;\n\n            if (_targetRenderer.hasMultipleDifferentValues)\n            {\n                // Multiple renderers selected: Show a simple text field.\n                EditorGUILayout.PropertyField(_targetMaterialProperty, Labels.Property);\n            }\n            else if (_targetRenderer.objectReferenceValue != null)\n            {\n                // Single renderer: Show the material property selection dropdown.\n                MaterialPropertySelector.DropdownList(_targetRenderer, _targetMaterialProperty);\n            }\n\n            EditorGUI.indentLevel--;\n\n            serializedObject.ApplyModifiedProperties();\n\n            if (reload)\n            {\n                // This is a little bit scary hack but we can force a HapPlayer\n                // to reload a given video file by invoking OnDestroy.\n                foreach (HapPlayer hp in targets)\n                {\n                    hp.SendMessage(\"OnDestroy\");\n                    hp.SendMessage(\"LateUpdate\");\n                }\n\n                // Also the source information string should be refreshed.\n                _sourceInfo = null;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Editor/HapPlayerEditor.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 5afaabe3aee5cdb46a3846f74cc3a8a7\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Editor/Klak.Hap.Editor.asmdef",
    "content": "{\n    \"name\": \"Klak.Hap.Editor\",\n    \"references\": [\n        \"Klak.Hap\"\n    ],\n    \"optionalUnityReferences\": [],\n    \"includePlatforms\": [\n        \"Editor\"\n    ],\n    \"excludePlatforms\": [],\n    \"allowUnsafeCode\": false,\n    \"overrideReferences\": false,\n    \"precompiledReferences\": [],\n    \"autoReferenced\": true,\n    \"defineConstraints\": []\n}"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Editor/Klak.Hap.Editor.asmdef.meta",
    "content": "fileFormatVersion: 2\nguid: 59c1346744fe3194291b617e412c56c4\nAssemblyDefinitionImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Editor/MaterialPropertySelector.cs",
    "content": "using UnityEngine;\nusing UnityEngine.Rendering;\nusing UnityEditor;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Klak.Hap\n{\n    static class MaterialPropertySelector\n    {\n        #region Public method\n\n        // Material property drop-down list\n        public static void DropdownList(\n            SerializedProperty rendererProperty,\n            SerializedProperty materialProperty\n        )\n        {\n            // Try retrieving the target shader.\n            var shader = RetrieveTargetShader(rendererProperty);\n\n            // Abandon the current value if it failed to get a shader.\n            if (shader == null)\n            {\n                materialProperty.stringValue = \"\";\n                return;\n            }\n\n            // Cache property names found in the target shader.\n            CachePropertyNames(shader);\n\n            // Abandon the current value if there is no property candidate.\n            if (_propertyNames.Length == 0)\n            {\n                materialProperty.stringValue = \"\";\n                return;\n            }\n\n            // Show the dropdown list.\n            var index = Array.IndexOf(_propertyNames, materialProperty.stringValue);\n            var newIndex = EditorGUILayout.Popup(\"Property\", index, _propertyNames);\n\n            // Update the serialized property if the selection was changed.\n            if (index != newIndex) materialProperty.stringValue = _propertyNames[newIndex];\n        }\n\n        #endregion\n\n        #region Private members\n\n        static string[] _propertyNames; // Property name list\n        static Shader _cachedShader;    // Shader used to cache the name list\n\n        // Retrieve a shader from a given renderer.\n        static Shader RetrieveTargetShader(SerializedProperty rendererProperty)\n        {\n            var renderer = rendererProperty.objectReferenceValue as Renderer;\n            if (renderer == null) return null;\n\n            var material = renderer.sharedMaterial;\n            if (material == null) return null;\n\n            return material.shader;\n        }\n\n        // Cache property names provided within a specified shader.\n        static void CachePropertyNames(Shader shader)\n        {\n            // Exit early when the shader is same to the cached one.\n            if (shader == _cachedShader) return;\n\n            var temp = new List<string>();\n\n            var count = shader.GetPropertyCount();\n            for (var i = 0; i < count; i++)\n            {\n                var propType = shader.GetPropertyType(i);\n                if (propType == ShaderPropertyType.Texture)\n                    temp.Add(shader.GetPropertyName(i));\n            }\n\n            _propertyNames = temp.ToArray();\n            _cachedShader = shader;\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Editor/MaterialPropertySelector.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 8ab866082e30404428d5298d084cc13a\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Editor.meta",
    "content": "fileFormatVersion: 2\nguid: 2a6f023ffc242a743a38d13e6cae3b66\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/LICENSE",
    "content": "License summary:\n\nKlakHAP     - MIT license\nHAP codec   - FreeBSD license\nSnappy      - BSD 3-clause license\nMP4 demuxer - CC0 (public domain)\n\n-------------------------------------------------------------------------------\nKlakHAP\nhttps://github.com/keijiro/KlakHap\n-------------------------------------------------------------------------------\n\nCopyright (c) 2019 Unity Technologies\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-------------------------------------------------------------------------------\nHAP\nhttps://github.com/Vidvox/hap\n-------------------------------------------------------------------------------\n\nCopyright (c) 2012-2013, Tom Butterworth and Vidvox LLC. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright\nnotice, this list of conditions and the following disclaimer in the\ndocumentation and/or other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n-------------------------------------------------------------------------------\nSnappy\nhttps://github.com/google/snappy\n-------------------------------------------------------------------------------\n\nCopyright 2011, Google Inc.\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    * Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\ncopyright notice, this list of conditions and the following disclaimer\nin the documentation and/or other materials provided with the\ndistribution.\n    * Neither the name of Google Inc. nor the names of its\ncontributors may be used to endorse or promote products derived from\nthis software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n-------------------------------------------------------------------------------\nMinimalistic MP4 muxer & demuxer\nhttps://github.com/aspt/mp4\n-------------------------------------------------------------------------------\n\nCC0 1.0 Universal\n\nStatement of Purpose\n\nThe laws of most jurisdictions throughout the world automatically confer\nexclusive Copyright and Related Rights (defined below) upon the creator and\nsubsequent owner(s) (each and all, an \"owner\") of an original work of\nauthorship and/or a database (each, a \"Work\").\n\nCertain owners wish to permanently relinquish those rights to a Work for the\npurpose of contributing to a commons of creative, cultural and scientific\nworks (\"Commons\") that the public can reliably and without fear of later\nclaims of infringement build upon, modify, incorporate in other works, reuse\nand redistribute as freely as possible in any form whatsoever and for any\npurposes, including without limitation commercial purposes. These owners may\ncontribute to the Commons to promote the ideal of a free culture and the\nfurther production of creative, cultural and scientific works, or to gain\nreputation or greater distribution for their Work in part through the use and\nefforts of others.\n\nFor these and/or other purposes and motivations, and without any expectation\nof additional consideration or compensation, the person associating CC0 with a\nWork (the \"Affirmer\"), to the extent that he or she is an owner of Copyright\nand Related Rights in the Work, voluntarily elects to apply CC0 to the Work\nand publicly distribute the Work under its terms, with knowledge of his or her\nCopyright and Related Rights in the Work and the meaning and intended legal\neffect of CC0 on those rights.\n\n1. Copyright and Related Rights. A Work made available under CC0 may be\nprotected by copyright and related or neighboring rights (\"Copyright and\nRelated Rights\"). Copyright and Related Rights include, but are not limited\nto, the following:\n\n  i. the right to reproduce, adapt, distribute, perform, display, communicate,\n  and translate a Work;\n\n  ii. moral rights retained by the original author(s) and/or performer(s);\n\n  iii. publicity and privacy rights pertaining to a person's image or likeness\n  depicted in a Work;\n\n  iv. rights protecting against unfair competition in regards to a Work,\n  subject to the limitations in paragraph 4(a), below;\n\n  v. rights protecting the extraction, dissemination, use and reuse of data in\n  a Work;\n\n  vi. database rights (such as those arising under Directive 96/9/EC of the\n  European Parliament and of the Council of 11 March 1996 on the legal\n  protection of databases, and under any national implementation thereof,\n  including any amended or successor version of such directive); and\n\n  vii. other similar, equivalent or corresponding rights throughout the world\n  based on applicable law or treaty, and any national implementations thereof.\n\n2. Waiver. To the greatest extent permitted by, but not in contravention of,\napplicable law, Affirmer hereby overtly, fully, permanently, irrevocably and\nunconditionally waives, abandons, and surrenders all of Affirmer's Copyright\nand Related Rights and associated claims and causes of action, whether now\nknown or unknown (including existing as well as future claims and causes of\naction), in the Work (i) in all territories worldwide, (ii) for the maximum\nduration provided by applicable law or treaty (including future time\nextensions), (iii) in any current or future medium and for any number of\ncopies, and (iv) for any purpose whatsoever, including without limitation\ncommercial, advertising or promotional purposes (the \"Waiver\"). Affirmer makes\nthe Waiver for the benefit of each member of the public at large and to the\ndetriment of Affirmer's heirs and successors, fully intending that such Waiver\nshall not be subject to revocation, rescission, cancellation, termination, or\nany other legal or equitable action to disrupt the quiet enjoyment of the Work\nby the public as contemplated by Affirmer's express Statement of Purpose.\n\n3. Public License Fallback. Should any part of the Waiver for any reason be\njudged legally invalid or ineffective under applicable law, then the Waiver\nshall be preserved to the maximum extent permitted taking into account\nAffirmer's express Statement of Purpose. In addition, to the extent the Waiver\nis so judged Affirmer hereby grants to each affected person a royalty-free,\nnon transferable, non sublicensable, non exclusive, irrevocable and\nunconditional license to exercise Affirmer's Copyright and Related Rights in\nthe Work (i) in all territories worldwide, (ii) for the maximum duration\nprovided by applicable law or treaty (including future time extensions), (iii)\nin any current or future medium and for any number of copies, and (iv) for any\npurpose whatsoever, including without limitation commercial, advertising or\npromotional purposes (the \"License\"). The License shall be deemed effective as\nof the date CC0 was applied by Affirmer to the Work. Should any part of the\nLicense for any reason be judged legally invalid or ineffective under\napplicable law, such partial invalidity or ineffectiveness shall not\ninvalidate the remainder of the License, and in such case Affirmer hereby\naffirms that he or she will not (i) exercise any of his or her remaining\nCopyright and Related Rights in the Work or (ii) assert any associated claims\nand causes of action with respect to the Work, in either case contrary to\nAffirmer's express Statement of Purpose.\n\n4. Limitations and Disclaimers.\n\n  a. No trademark or patent rights held by Affirmer are waived, abandoned,\n  surrendered, licensed or otherwise affected by this document.\n\n  b. Affirmer offers the Work as-is and makes no representations or warranties\n  of any kind concerning the Work, express, implied, statutory or otherwise,\n  including without limitation warranties of title, merchantability, fitness\n  for a particular purpose, non infringement, or the absence of latent or\n  other defects, accuracy, or the present or absence of errors, whether or not\n  discoverable, all to the greatest extent permissible under applicable law.\n\n  c. Affirmer disclaims responsibility for clearing rights of other persons\n  that may apply to the Work or any use thereof, including without limitation\n  any person's Copyright and Related Rights in the Work. Further, Affirmer\n  disclaims responsibility for obtaining any necessary consents, permissions\n  or other rights required for any use of the Work.\n\n  d. Affirmer understands and acknowledges that Creative Commons is not a\n  party to this document and has no duty or obligation with respect to this\n  CC0 or use of the Work.\n\nFor more information, please see\n<http://creativecommons.org/publicdomain/zero/1.0/>\n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/LICENSE.meta",
    "content": "fileFormatVersion: 2\nguid: ee05d860d6934052af1f4d5fb541a384\nTextScriptImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Plugin/Linux/libKlakHap.so.meta",
    "content": "fileFormatVersion: 2\nguid: aefd4aee030ec9a56930540080f31258\nPluginImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  iconMap: {}\n  executionOrder: {}\n  defineConstraints: []\n  isPreloaded: 0\n  isOverridable: 0\n  isExplicitlyReferenced: 0\n  platformData:\n  - first:\n      '': Any\n    second:\n      enabled: 0\n      settings:\n        Exclude Editor: 0\n        Exclude Linux: 1\n        Exclude Linux64: 0\n        Exclude LinuxUniversal: 0\n        Exclude OSXUniversal: 1\n        Exclude Win: 0\n        Exclude Win64: 0\n  - first:\n      Any: \n    second:\n      enabled: 0\n      settings: {}\n  - first:\n      Editor: Editor\n    second:\n      enabled: 1\n      settings:\n        CPU: x86_64\n        DefaultValueInitialized: true\n        OS: Linux\n  - first:\n      Facebook: Win\n    second:\n      enabled: 0\n      settings:\n        CPU: AnyCPU\n  - first:\n      Facebook: Win64\n    second:\n      enabled: 0\n      settings:\n        CPU: AnyCPU\n  - first:\n      Standalone: Linux\n    second:\n      enabled: 0\n      settings:\n        CPU: None\n  - first:\n      Standalone: Linux64\n    second:\n      enabled: 1\n      settings:\n        CPU: x86_64\n  - first:\n      Standalone: LinuxUniversal\n    second:\n      enabled: 1\n      settings:\n        CPU: x86_64\n  - first:\n      Standalone: OSXUniversal\n    second:\n      enabled: 0\n      settings:\n        CPU: None\n  - first:\n      Standalone: Win\n    second:\n      enabled: 1\n      settings:\n        CPU: AnyCPU\n  - first:\n      Standalone: Win64\n    second:\n      enabled: 1\n      settings:\n        CPU: AnyCPU\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Plugin/Linux.meta",
    "content": "fileFormatVersion: 2\nguid: 18114d790aea9f97e9b9f56ab458bc9d\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Plugin/MacOS/KlakHap.bundle.meta",
    "content": "fileFormatVersion: 2\nguid: 68eb9c44d2cd647b8a246c85c2516a6c\nPluginImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  iconMap: {}\n  executionOrder: {}\n  defineConstraints: []\n  isPreloaded: 0\n  isOverridable: 1\n  isExplicitlyReferenced: 0\n  validateReferences: 1\n  platformData:\n  - first:\n      : Any\n    second:\n      enabled: 0\n      settings:\n        Exclude Editor: 0\n        Exclude Linux64: 1\n        Exclude OSXUniversal: 0\n        Exclude Win: 1\n        Exclude Win64: 1\n        Exclude iOS: 1\n  - first:\n      Any: \n    second:\n      enabled: 0\n      settings: {}\n  - first:\n      Editor: Editor\n    second:\n      enabled: 1\n      settings:\n        CPU: AnyCPU\n        DefaultValueInitialized: true\n        OS: OSX\n  - first:\n      Standalone: Linux64\n    second:\n      enabled: 0\n      settings:\n        CPU: None\n  - first:\n      Standalone: OSXUniversal\n    second:\n      enabled: 1\n      settings:\n        CPU: AnyCPU\n  - first:\n      Standalone: Win\n    second:\n      enabled: 0\n      settings:\n        CPU: x86\n  - first:\n      Standalone: Win64\n    second:\n      enabled: 0\n      settings:\n        CPU: x86_64\n  - first:\n      iPhone: iOS\n    second:\n      enabled: 0\n      settings:\n        AddToEmbeddedBinaries: false\n        CPU: AnyCPU\n        CompileFlags: \n        FrameworkDependencies: \n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Plugin/MacOS.meta",
    "content": "fileFormatVersion: 2\nguid: b3fc36a147f3a4fe19b3fe7371cfe554\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Plugin/Windows/KlakHap.dll.meta",
    "content": "fileFormatVersion: 2\nguid: 3ab59e419166f214abf75fa29aac993e\nPluginImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  iconMap: {}\n  executionOrder: {}\n  defineConstraints: []\n  isPreloaded: 0\n  isOverridable: 0\n  isExplicitlyReferenced: 0\n  platformData:\n  - first:\n      '': Any\n    second:\n      enabled: 0\n      settings:\n        Exclude Editor: 0\n        Exclude Linux: 0\n        Exclude Linux64: 0\n        Exclude LinuxUniversal: 0\n        Exclude OSXUniversal: 0\n        Exclude Win: 1\n        Exclude Win64: 0\n  - first:\n      Any: \n    second:\n      enabled: 1\n      settings: {}\n  - first:\n      Editor: Editor\n    second:\n      enabled: 1\n      settings:\n        CPU: x86_64\n        DefaultValueInitialized: true\n        OS: Windows\n  - first:\n      Facebook: Win\n    second:\n      enabled: 0\n      settings:\n        CPU: None\n  - first:\n      Facebook: Win64\n    second:\n      enabled: 0\n      settings:\n        CPU: AnyCPU\n  - first:\n      Standalone: Linux\n    second:\n      enabled: 1\n      settings:\n        CPU: x86\n  - first:\n      Standalone: Linux64\n    second:\n      enabled: 1\n      settings:\n        CPU: x86_64\n  - first:\n      Standalone: LinuxUniversal\n    second:\n      enabled: 1\n      settings:\n        CPU: AnyCPU\n  - first:\n      Standalone: OSXUniversal\n    second:\n      enabled: 1\n      settings:\n        CPU: AnyCPU\n  - first:\n      Standalone: Win\n    second:\n      enabled: 0\n      settings:\n        CPU: None\n  - first:\n      Standalone: Win64\n    second:\n      enabled: 1\n      settings:\n        CPU: AnyCPU\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Plugin/Windows.meta",
    "content": "fileFormatVersion: 2\nguid: dc34545ab496569488b8cd56973907d2\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Plugin.meta",
    "content": "fileFormatVersion: 2\nguid: 39f09b654953c8e45bc1d12d19cceaef\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/README.md",
    "content": "# KlakHap\n\n![GIF](https://i.imgur.com/exuJAIA.gif)\n\n**KlakHap** is a Unity plugin for playing back video streams encoded with the\n[HAP video codecs].\n\nHAP is a fast and high-quality video codec often used in real-time interactive\napplications. From the HAP Codecs website:\n\n> The HAP codecs are designed to fit the needs of a variety of real-time video\n> workflows where ultra high resolution video is needed such as live event\n> production, set design, 360 video for gaming, projection mapping and creative\n> coding.\n\nKlakHap provides decoded frames as textures that you can use anywhere in\nUnity's rendering pipeline: apply them to a material, present full-screen\nvideo, animate a UI element, and more. Thanks to the efficient design and\nimplementation of the HAP codecs, it can adjust playback time and speed\ndynamically without hiccups.\n\n[HAP video codecs]: https://hap.video/\n\n# System requirements\n\n- Unity 2022.3 or later\n\nCurrently, KlakHap supports only 64-bit desktop platforms (Windows, macOS, and\nLinux).\n\n# Supported formats\n\nKlakHap supports **HAP**, **HAP Alpha**, and **HAP Q**. **HAP Q Alpha** is not\nsupported.\n\nKlakHap only supports the QuickTime File Format as a container, i.e., `.mov`\nfiles.\n\n# How to install\n\nInstall the KlakHap package (`jp.keijiro.klak.hap`) from the \"Keijiro\" scoped\nregistry in Package Manager. Follow [these instructions] to add the registry to\nyour project.\n\n[these instructions]:\n  https://gist.github.com/keijiro/f8c7e8ff29bfe63d86b888901b82644c\n\n# How to specify a video file\n\nThere are two ways to specify a video file in the plugin:\n\n- **Streaming Assets Mode**: Put a video file in the [Streaming Assets]\n  directory and specify its file name.\n- **Local File System Mode**: Put a video file somewhere in local drive and\n  specify its full path.\n\nThe former method is recommended when the video file ships with the\napplication. The latter method is useful when you need to play external\ncontent.\n\n[Streaming Assets]: https://docs.unity3d.com/Manual/StreamingAssets.html\n\n# Hap Player component\n\n![Inspector](https://i.imgur.com/pIACL4W.png)\n\n**File Path** and **Path Mode** specify the source video file. See the previous\nsection for details.\n\n**Time**, **Speed** and **Loop** are used to set the initial playback state.\nYou can also change these values during playback.\n\n**Target Texture** stores decoded frames in a render texture. Note that this\nallocates a small amount of GPU time for data transfer.\n\n**Target Renderer** applies the decoded texture to a specific material\nproperty. Although this is the most performant way to render video frames, it\nrequires a few extra steps to render correctly. Keep the following points in\nmind:\n\n- UV coordinate incompatibility: Decoded textures are upside down due to\n  differences in UV coordinate conventions between Unity and HAP. You can fix\n  this using a vertically inverted texture scale/offset. You can also use the\n  `Klak/Hap` shader for this purpose.\n- Color space conversion for HAP Q: [YCoCg conversion] must be added to a\n  shader when using HAP Q. You can also use the `Klak/HAP Q` shader for this\n  purpose.\n\n[YCoCg conversion]:\n  https://gist.github.com/dlublin/90f879cfe027ebf5792bdadf2c911bb5\n\n# How to control playback\n\n`HapPlayer` provides only a few properties and methods for controlling\nplayback. This is an intentional design choice; I avoid ambiguous methods like\n`Play`, `Stop`, and `Pause`. Use the basic properties and methods instead.\n\n- To jump to a specific point: Assign a time in seconds to `time`.\n- To jump to a specific frame: Calculate the time in seconds using `frameCount`\n  and `streamDuration`, then assign it to `time`.\n- To reverse the playback direction: Assign a negative value to `speed`.\n- To pause: Assign `0` to `speed`.\n- To resume: Assign `1` to `speed`.\n- To stop: Assign `false` to `enabled`.\n- To close the video file: Destroy the `HapPlayer` component.\n- To open another video file: Call `AddComponent<HapPlayer>`, then call `Open`.\n\n# Timeline support\n\n![GIF](https://i.imgur.com/efrvvye.gif)\n\nThe HAP Player component implements the [ITimeControl] interface, which allows\nit to control playback time from a Control Track in a [Timeline]. You can\ncreate a control track by dragging and dropping a HAP Player game object into\nthe Timeline Editor, or manually create a Control Track/Clip and set the\nsource game object.\n\n[ITimeControl]: https://docs.unity3d.com/ScriptReference/Timeline.ITimeControl.html\n[Timeline]: https://docs.unity3d.com/Manual/TimelineSection.html\n\n# Platform differences (internal latency)\n\nOn Windows, KlakHap uses the [Custom Texture Update] feature to hide the\nsynchronization point in the background thread. It guarantees exact-frame\nplayback with minimal load on the main thread.\n\nOn macOS and Linux, the Custom Texture Update feature is unavailable for this\npurpose[^1]. Instead, KlakHap delays synchronization to the next frame to avoid\nmain thread stalls. In other words, it guarantees exact-frame playback but adds\na single-frame latency.\n\nYou can turn off this behavior by adding `HAP_NO_DELAY` to the [Scripting\nDefine Symbols] in the project settings. This stalls the main thread for every\nframe decoding. It significantly slows down the application but is useful when\nexact frame matching is essential (e.g., [volumetric video playback] with\nAlembic animation).\n\n[Custom Texture Update]:\n  https://github.com/keijiro/TextureUpdateExample\n\n[Scripting Define Symbols]:\n  https://docs.unity3d.com/Manual/CustomScriptingSymbols.html\n\n[volumetric video playback]:\n  https://github.com/keijiro/Abcvfx\n\n[^1]: The Custom Texture Update feature is available even on macOS/Linux but\n      doesn't support compressed texture formats, which are essential for HAP\n      decoding.\n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/README.md.meta",
    "content": "fileFormatVersion: 2\nguid: 2a0b411fba8e4ef48cbb46596fdc2de8\nTextScriptImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Resources/Hap1.shader",
    "content": "Shader \"Klak/HAP\"\n{\n    Properties\n    {\n        _MainTex(\"Texture\", 2D) = \"white\" {}\n    }\n\n    CGINCLUDE\n\n    #include \"UnityCG.cginc\"\n\n    struct Attributes\n    {\n        float4 position : POSITION;\n        float2 texcoord : TEXCOORD;\n        UNITY_VERTEX_INPUT_INSTANCE_ID\n    };\n\n    struct Varyings\n    {\n        float4 position : SV_Position;\n        float2 texcoord : TEXCOORD;\n    };\n\n    sampler2D _MainTex;\n    float4 _MainTex_ST;\n\n    Varyings Vertex(Attributes input)\n    {\n        UNITY_SETUP_INSTANCE_ID(input);\n        Varyings output;\n        output.position = UnityObjectToClipPos(input.position);\n        output.texcoord = TRANSFORM_TEX(input.texcoord, _MainTex);\n        output.texcoord.y = 1 - output.texcoord.y;\n        return output;\n    }\n\n    fixed4 Fragment(Varyings input) : SV_Target\n    {\n        return tex2D(_MainTex, input.texcoord);\n    }\n\n    ENDCG\n\n    SubShader\n    {\n        Tags { \"RenderType\"=\"Opaque\" }\n        Pass\n        {\n            CGPROGRAM\n            #pragma vertex Vertex\n            #pragma fragment Fragment\n            #pragma multi_compile_instancing\n            ENDCG\n        }\n    }\n}\n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Resources/Hap1.shader.meta",
    "content": "fileFormatVersion: 2\nguid: e99f77a91d9883a4b890a1fc833b7158\nShaderImporter:\n  externalObjects: {}\n  defaultTextures: []\n  nonModifiableTextures: []\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Resources/Hap5.shader",
    "content": "Shader \"Klak/HAP Alpha\"\n{\n    Properties\n    {\n        _MainTex(\"Texture\", 2D) = \"white\" {}\n    }\n\n    CGINCLUDE\n\n    #include \"UnityCG.cginc\"\n\n    struct Attributes\n    {\n        float4 position : POSITION;\n        float2 texcoord : TEXCOORD;\n        UNITY_VERTEX_INPUT_INSTANCE_ID\n    };\n\n    struct Varyings\n    {\n        float4 position : SV_Position;\n        float2 texcoord : TEXCOORD;\n    };\n\n    sampler2D _MainTex;\n    float4 _MainTex_ST;\n\n    Varyings Vertex(Attributes input)\n    {\n        UNITY_SETUP_INSTANCE_ID(input);\n        Varyings output;\n        output.position = UnityObjectToClipPos(input.position);\n        output.texcoord = TRANSFORM_TEX(input.texcoord, _MainTex);\n        output.texcoord.y = 1 - output.texcoord.y;\n        return output;\n    }\n\n    fixed4 Fragment(Varyings input) : SV_Target\n    {\n        return tex2D(_MainTex, input.texcoord);\n    }\n\n    ENDCG\n\n    SubShader\n    {\n        Tags { \"RenderType\"=\"Transparent\" \"Queue\"=\"Transparent\" }\n        Pass\n        {\n            ZWrite Off\n            Blend SrcAlpha OneMinusSrcAlpha\n            CGPROGRAM\n            #pragma vertex Vertex\n            #pragma fragment Fragment\n            #pragma multi_compile_instancing\n            ENDCG\n        }\n    }\n}\n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Resources/Hap5.shader.meta",
    "content": "fileFormatVersion: 2\nguid: 2fc3460268e46c64695de0f674e4e320\nShaderImporter:\n  externalObjects: {}\n  defaultTextures: []\n  nonModifiableTextures: []\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Resources/HapY.shader",
    "content": "Shader \"Klak/HAP Q\"\n{\n    Properties\n    {\n        _MainTex(\"Texture\", 2D) = \"white\" {}\n    }\n\n    CGINCLUDE\n\n    #include \"UnityCG.cginc\"\n\n    struct Attributes\n    {\n        float4 position : POSITION;\n        float2 texcoord : TEXCOORD;\n        UNITY_VERTEX_INPUT_INSTANCE_ID\n    };\n\n    struct Varyings\n    {\n        float4 position : SV_Position;\n        float2 texcoord : TEXCOORD;\n    };\n\n    sampler2D _MainTex;\n    float4 _MainTex_ST;\n\n    half3 CoCgSY2RGB(half4 i)\n    {\n    #if !defined(UNITY_COLORSPACE_GAMMA)\n        i.xyz = LinearToGammaSpace(i.xyz);\n    #endif\n        i.xy -= half2(0.50196078431373, 0.50196078431373);\n        half s = 1 / ((i.z * (255.0 / 8)) + 1);\n        half3 rgb = half3(i.x - i.y, i.y, -i.x - i.y) * s + i.w;\n    #if !defined(UNITY_COLORSPACE_GAMMA)\n        rgb = GammaToLinearSpace(rgb);\n    #endif\n        return rgb;\n    }\n\n    Varyings Vertex(Attributes input)\n    {\n        UNITY_SETUP_INSTANCE_ID(input);\n        Varyings output;\n        output.position = UnityObjectToClipPos(input.position);\n        output.texcoord = TRANSFORM_TEX(input.texcoord, _MainTex);\n        output.texcoord.y = 1 - output.texcoord.y;\n        return output;\n    }\n\n    fixed4 Fragment(Varyings input) : SV_Target\n    {\n        return fixed4(CoCgSY2RGB(tex2D(_MainTex, input.texcoord)), 1);\n    }\n\n    ENDCG\n\n    SubShader\n    {\n        Tags { \"RenderType\"=\"Opaque\" }\n        Pass\n        {\n            CGPROGRAM\n            #pragma multi_compile _ UNITY_COLORSPACE_GAMMA\n            #pragma vertex Vertex\n            #pragma fragment Fragment\n            #pragma multi_compile_instancing\n            ENDCG\n        }\n    }\n}\n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Resources/HapY.shader.meta",
    "content": "fileFormatVersion: 2\nguid: c6a332340608cdd4f907eb4bc0c17f4a\nShaderImporter:\n  externalObjects: {}\n  defaultTextures: []\n  nonModifiableTextures: []\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Resources.meta",
    "content": "fileFormatVersion: 2\nguid: 1b69560a2379aa94b9fb309127d58020\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Runtime/Common.cs",
    "content": "namespace Klak.Hap\n{\n    public enum CodecType { Unsupported, Hap, HapQ, HapAlpha }\n}\n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Runtime/Common.cs.meta",
    "content": "fileFormatVersion: 2\nguid: ab49f28befbab1341821f02280a3199f\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Runtime/HapPlayer.cs",
    "content": "using UnityEngine;\nusing UnityEngine.Playables;\n\n#if KLAKHAP_HAS_TIMELINE\nusing UnityEngine.Timeline;\n#endif\n\nnamespace Klak.Hap\n{\n    [ExecuteInEditMode, AddComponentMenu(\"Klak/HAP/HAP Player\")]\n    #if KLAKHAP_HAS_TIMELINE\n    public sealed class HapPlayer : MonoBehaviour , ITimeControl, IPropertyPreview\n    #else\n    public sealed class HapPlayer : MonoBehaviour\n    #endif\n    {\n        #region Editable attributes\n\n        public enum PathMode { StreamingAssets, LocalFileSystem }\n\n        [SerializeField] PathMode _pathMode = PathMode.StreamingAssets;\n        [SerializeField] string _filePath = \"\";\n\n        [SerializeField] float _time = 0;\n        [SerializeField, Range(-10, 10)] float _speed = 1;\n        [SerializeField] bool _loop = true;\n\n        [SerializeField] RenderTexture _targetTexture = null;\n        [SerializeField] Renderer _targetRenderer = null;\n        [SerializeField] string _targetMaterialProperty = \"_MainTex\";\n\n        #endregion\n\n        #region Public properties\n\n        public float time {\n            get { return _time; }\n            set { _time = value; }\n        }\n\n        public float speed {\n            get { return _speed; }\n            set { _speed = value; }\n        }\n\n        public bool loop {\n            get { return _loop; }\n            set { _loop = value; }\n        }\n\n        public RenderTexture targetTexture {\n            get { return _targetTexture; }\n            set { _targetTexture = value; }\n        }\n\n        public Renderer targetRenderer {\n            get { return _targetRenderer; }\n            set { _targetRenderer = value; }\n        }\n\n        public string targetMaterialProperty {\n            get { return _targetMaterialProperty; }\n            set { _targetMaterialProperty = value; }\n        }\n\n        #endregion\n\n        #region Read-only properties\n\n        public bool isValid { get { return _demuxer != null; } }\n        public int frameWidth { get { return _demuxer?.Width ?? 0; } }\n        public int frameHeight { get { return _demuxer?.Height ?? 0; } }\n        public int frameCount { get { return _demuxer?.FrameCount ?? 0; } }\n        public double streamDuration { get { return _demuxer?.Duration ?? 0; } }\n\n        public CodecType codecType { get {\n            return Utility.DetermineCodecType(_demuxer?.VideoType ?? 0);\n        } }\n\n        public string resolvedFilePath { get {\n            if (_pathMode == PathMode.StreamingAssets)\n                return System.IO.Path.Combine(Application.streamingAssetsPath, _filePath);\n            else\n                return _filePath;\n        } }\n\n        public Texture2D texture { get { return _texture; } }\n\n        #endregion\n\n        #region Public methods\n\n        public void Open(string filePath, PathMode pathMode = PathMode.StreamingAssets)\n        {\n            if (_demuxer != null)\n            {\n                Debug.LogError(\"Stream has already been opened.\");\n                return;\n            }\n\n            _filePath = filePath;\n            _pathMode = pathMode;\n\n            OpenInternal();\n        }\n\n        public void UpdateNow()\n          => LateUpdate();\n\n        #endregion\n\n        #region Private members\n\n        Demuxer _demuxer;\n        StreamReader _stream;\n        Decoder _decoder;\n\n        Texture2D _texture;\n        TextureUpdater _updater;\n\n        float _storedTime;\n        float _storedSpeed;\n\n        void OpenInternal()\n        {\n            // Demuxer instantiation\n            _demuxer = new Demuxer(resolvedFilePath);\n\n            if (!_demuxer.IsValid)\n            {\n                if (Application.isPlaying)\n                {\n                    // In play mode, show an error message, then disable itself\n                    // to prevent spamming the console.\n                    Debug.LogError(\"Failed to open stream (\" + resolvedFilePath + \").\");\n                    enabled = false;\n                }\n                _demuxer.Dispose();\n                _demuxer = null;\n                return;\n            }\n\n            // Stream reader instantiation\n            _stream = new StreamReader(_demuxer, _time, _speed / 60);\n            (_storedTime, _storedSpeed) = (_time, _speed);\n\n            // Decoder instantiation\n            _decoder = new Decoder(\n                _stream, _demuxer.Width, _demuxer.Height, _demuxer.VideoType\n            );\n\n            // Texture initialization\n            _texture = new Texture2D(\n                _demuxer.Width, _demuxer.Height,\n                Utility.DetermineTextureFormat(_demuxer.VideoType), false\n            );\n            _texture.wrapMode = TextureWrapMode.Clamp;\n            _texture.hideFlags = HideFlags.DontSave;\n\n            _updater = new TextureUpdater(_texture, _decoder);\n        }\n\n        #endregion\n\n        #region External object updaters\n\n        Material _blitMaterial;\n        MaterialPropertyBlock _propertyBlock;\n\n        void UpdateTargetTexture()\n        {\n            if (_targetTexture == null) return;\n\n            // Material lazy initialization\n            if (_blitMaterial == null)\n            {\n                _blitMaterial = new Material(Utility.DetermineBlitShader(_demuxer.VideoType));\n                _blitMaterial.hideFlags = HideFlags.DontSave;\n            }\n\n            // Blit\n            Graphics.Blit(_texture, _targetTexture, _blitMaterial, 0);\n        }\n\n        void UpdateTargetRenderer()\n        {\n            if (_targetRenderer == null) return;\n\n            // Material property block lazy initialization\n            if (_propertyBlock == null)\n                _propertyBlock = new MaterialPropertyBlock();\n\n            // Read-modify-write\n            _targetRenderer.GetPropertyBlock(_propertyBlock);\n            _propertyBlock.SetTexture(_targetMaterialProperty, _texture);\n            _targetRenderer.SetPropertyBlock(_propertyBlock);\n        }\n\n        #endregion\n\n        #region ITimeControl implementation\n\n        bool _externalTime;\n\n        public void OnControlTimeStart()\n        {\n            _externalTime = true;\n\n            // In the external time mode, we can't know the actual playback\n            // speed but sure that it's positive (Control Track doesn't support\n            // reverse playback), so we assume that the speed is 1.0.\n            // Cons: Resync could happen every frame for high speed play back.\n            _speed = 1;\n        }\n\n        public void OnControlTimeStop()\n        {\n            _externalTime = false;\n        }\n\n        public void SetTime(double time)\n        {\n            _time = (float)time;\n            _speed = 1;\n        }\n\n        #endregion\n\n        #region IPropertyPreview implementation\n\n        #if KLAKHAP_HAS_TIMELINE\n        public void GatherProperties(PlayableDirector director, IPropertyCollector driver)\n        {\n            driver.AddFromName<HapPlayer>(gameObject, \"_time\");\n        }\n        #endif\n\n        #endregion\n\n        #region MonoBehaviour implementation\n\n        void OnDestroy()\n        {\n            if (_updater != null)\n            {\n                _updater.Dispose();\n                _updater = null;\n            }\n\n            if (_decoder != null)\n            {\n                _decoder.Dispose();\n                _decoder = null;\n            }\n\n            if (_stream != null)\n            {\n                _stream.Dispose();\n                _stream = null;\n            }\n\n            if (_demuxer != null)\n            {\n                _demuxer.Dispose();\n                _demuxer = null;\n            }\n\n            Utility.Destroy(_texture);\n            Utility.Destroy(_blitMaterial);\n        }\n\n        int _lastUpdateFrameCount = -1;\n\n        void LateUpdate()\n        {\n            // Double update check\n            if (Time.frameCount == _lastUpdateFrameCount) return;\n            _lastUpdateFrameCount = Time.frameCount;\n\n            // Lazy initialization of demuxer\n            if (_demuxer == null && !string.IsNullOrEmpty(_filePath))\n                OpenInternal();\n\n            // Do nothing if the demuxer hasn't been instantiated.\n            if (_demuxer == null) return;\n\n            var duration = (float)_demuxer.Duration;\n\n            // Check if _time is still in the same frame of _storedTime.\n            // Resync is needed when it went out of the frame.\n            var dt = duration / _demuxer.FrameCount;\n            var resync = _time < _storedTime || _time > _storedTime + dt;\n\n            // Check if the speed was externally modified.\n            if (_speed != _storedSpeed)\n            {\n                resync = true; // Resync to adapt to the new speed.\n                _storedSpeed = _speed;\n            }\n\n            // Time clamping\n            var t = _loop ? _time : Mathf.Clamp(_time, 0, duration - 1e-4f);\n\n            // Determine if background decoding is available.\n            // Resync shouldn't happen. Not preferable in edit mode.\n            var bgdec = !resync && Application.isPlaying;\n\n            // Restart the stream reader on resync.\n            if (resync) _stream.Restart(t, _speed / 60);\n\n            if (TextureUpdater.AsyncSupport)\n            {\n                // Asynchronous texture update supported:\n                // Decode a frame and request a texture update.\n                if (bgdec) _decoder.UpdateAsync(t); else _decoder.UpdateSync(t);\n                _updater.RequestAsyncUpdate();\n            }\n            #if !HAP_NO_DELAY\n            else if (bgdec)\n            {\n                // Synchronous texture update with background decoding:\n                // Update first, then start background decoding. This\n                // introduces a single frame delay but makes it possible to\n                // offload decoding load to a background thread.\n                _updater.UpdateNow();\n                _decoder.UpdateAsync(t);\n            }\n            #endif\n            else\n            {\n                // Synchronous decoding and texture update.\n                _decoder.UpdateSync(t);\n                _updater.UpdateNow();\n            }\n\n            // Update the stored time.\n            if (Application.isPlaying && !_externalTime)\n                _time += Time.deltaTime * _speed;\n            _storedTime = _time;\n\n            // External object updates\n            UpdateTargetRenderer();\n            UpdateTargetTexture();\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Runtime/HapPlayer.cs.meta",
    "content": "fileFormatVersion: 2\nguid: f3775962864755b43a790abf4d029c32\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Runtime/Internal/Decoder.cs",
    "content": "using System;\nusing System.Runtime.InteropServices;\nusing System.Threading;\n\nnamespace Klak.Hap\n{\n    internal sealed class Decoder : IDisposable\n    {\n        #region Initialization/finalization\n\n        public Decoder(StreamReader stream, int width, int height, int videoType)\n        {\n            _stream = stream;\n\n            // Plugin initialization\n            _plugin = KlakHap_CreateDecoder(width, height, videoType);\n            _id = ++_instantiationCount;\n            KlakHap_AssignDecoder(_id, _plugin);\n\n            // By default, start from the first frame.\n            _time = 0;\n\n            // Decoder thread startup\n            _resume.req = new AutoResetEvent(true);\n            _resume.ack = new AutoResetEvent(false);\n            _thread = new Thread(DecoderThread);\n            _thread.Start();\n        }\n\n        public void Dispose()\n        {\n            if (_thread != null)\n            {\n                _terminate = true;\n                _resume.req.Set();\n                _thread.Join();\n                _thread = null;\n            }\n\n            if (_plugin != IntPtr.Zero)\n            {\n                KlakHap_AssignDecoder(_id, IntPtr.Zero);\n                KlakHap_DestroyDecoder(_plugin);\n                _plugin = IntPtr.Zero;\n            }\n        }\n\n        #endregion\n\n        #region Public members\n\n        public uint CallbackID { get { return _id; } }\n\n        public int BufferSize { get {\n            return KlakHap_GetDecoderBufferSize(_plugin);\n        } }\n\n        public void UpdateSync(float time)\n        {\n            _time = time;\n            var buffer = _stream.Advance(_time);\n            if (buffer != null)\n                KlakHap_DecodeFrame(_plugin, buffer.PluginPointer);\n        }\n\n        public void UpdateAsync(float time)\n        {\n            _time = time;\n            _resume.req.Set();\n            _resume.ack.WaitOne();\n        }\n\n        public IntPtr LockBuffer()\n        {\n            return KlakHap_LockDecoderBuffer(_plugin);\n        }\n\n        public void UnlockBuffer()\n        {\n            KlakHap_UnlockDecoderBuffer(_plugin);\n        }\n\n        #endregion\n\n        #region Private members\n\n        static uint _instantiationCount;\n\n        IntPtr _plugin;\n        uint _id;\n\n        Thread _thread;\n        (AutoResetEvent req, AutoResetEvent ack) _resume;\n        bool _terminate;\n\n        StreamReader _stream;\n        float _time;\n\n        #endregion\n\n        #region Thread function\n\n        void DecoderThread()\n        {\n            while (true)\n            {\n                _resume.req.WaitOne();\n                _resume.ack.Set();\n\n                if (_terminate) break;\n\n                var buffer = _stream.Advance(_time);\n                if (buffer == null) continue;\n\n                KlakHap_DecodeFrame(_plugin, buffer.PluginPointer);\n            }\n        }\n\n        #endregion\n\n        #region Native plugin entry points\n\n        [DllImport(\"KlakHap\")]\n        internal static extern IntPtr KlakHap_CreateDecoder(int width, int height, int typeID);\n\n        [DllImport(\"KlakHap\")]\n        internal static extern void KlakHap_DestroyDecoder(IntPtr decoder);\n\n        [DllImport(\"KlakHap\")]\n        internal static extern void KlakHap_AssignDecoder(uint id, IntPtr decoder);\n\n        [DllImport(\"KlakHap\")]\n        internal static extern void KlakHap_DecodeFrame(IntPtr decoder, IntPtr input);\n\n        [DllImport(\"KlakHap\")]\n        internal static extern IntPtr KlakHap_LockDecoderBuffer(IntPtr decoder);\n\n        [DllImport(\"KlakHap\")]\n        internal static extern void KlakHap_UnlockDecoderBuffer(IntPtr decoder);\n\n        [DllImport(\"KlakHap\")]\n        internal static extern int KlakHap_GetDecoderBufferSize(IntPtr decoder);\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Runtime/Internal/Decoder.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 6a95a95ecf0e26740a6507fe3474b8f8\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Runtime/Internal/Demuxer.cs",
    "content": "using System;\nusing System.Runtime.InteropServices;\n\nnamespace Klak.Hap\n{\n    internal sealed class Demuxer : IDisposable\n    {\n        #region Public properties\n\n        public bool IsValid { get { return _plugin != IntPtr.Zero; } }\n        public int Width { get { return _width; } }\n        public int Height { get { return _height; } }\n        public int VideoType { get { return _videoType; } }\n        public double Duration { get { return _duration; } }\n        public int FrameCount { get { return _frameCount; } }\n\n        #endregion\n\n        #region Initialization/finalization\n\n        public Demuxer(string filePath)\n        {\n            _plugin = KlakHap_OpenDemuxer(filePath);\n\n            if (KlakHap_DemuxerIsValid(_plugin) == 0)\n            {\n                // Instantiation failed; Close and stop.\n                KlakHap_CloseDemuxer(_plugin);\n                _plugin = IntPtr.Zero;\n                return;\n            }\n\n            // Video properties\n            _width = KlakHap_GetVideoWidth(_plugin);\n            _height = KlakHap_GetVideoHeight(_plugin);\n            _videoType = KlakHap_AnalyzeVideoType(_plugin);\n            _duration = KlakHap_GetDuration(_plugin);\n            _frameCount = KlakHap_CountFrames(_plugin);\n        }\n\n        public void Dispose()\n        {\n            if (_plugin != IntPtr.Zero)\n            {\n                KlakHap_CloseDemuxer(_plugin);\n                _plugin = IntPtr.Zero;\n            }\n        }\n\n        #endregion\n\n        #region Public methods\n\n        public void ReadFrame(ReadBuffer buffer, int index, float time)\n        {\n            KlakHap_ReadFrame(_plugin, index, buffer.PluginPointer);\n            buffer.Index = index;\n            buffer.Time = time;\n        }\n\n        #endregion\n\n        #region Private members\n\n        IntPtr _plugin;\n        int _width, _height, _videoType;\n        double _duration;\n        int _frameCount;\n\n        #endregion\n\n        #region Native plugin entry points\n\n        [DllImport(\"KlakHap\", CharSet = CharSet.Ansi)]\n        internal static extern IntPtr KlakHap_OpenDemuxer([MarshalAs(UnmanagedType.LPUTF8Str)] string filepath);\n\n        [DllImport(\"KlakHap\")]\n        internal static extern void KlakHap_CloseDemuxer(IntPtr demuxer);\n\n        [DllImport(\"KlakHap\")]\n        internal static extern int KlakHap_DemuxerIsValid(IntPtr demuxer);\n\n        [DllImport(\"KlakHap\")]\n        internal static extern int KlakHap_CountFrames(IntPtr demuxer);\n\n        [DllImport(\"KlakHap\")]\n        internal static extern double KlakHap_GetDuration(IntPtr demuxer);\n\n        [DllImport(\"KlakHap\")]\n        internal static extern int KlakHap_GetVideoWidth(IntPtr demuxer);\n\n        [DllImport(\"KlakHap\")]\n        internal static extern int KlakHap_GetVideoHeight(IntPtr demuxer);\n\n        [DllImport(\"KlakHap\")]\n        internal static extern int KlakHap_AnalyzeVideoType(IntPtr demuxer);\n\n        [DllImport(\"KlakHap\")]\n        internal static extern void KlakHap_ReadFrame(IntPtr demuxer, int frameNumber, IntPtr buffer);\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Runtime/Internal/Demuxer.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 080b998a80cb20044adf8fa4a011a182\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Runtime/Internal/ReadBuffer.cs",
    "content": "using System;\nusing System.Runtime.InteropServices;\n\nnamespace Klak.Hap\n{\n    internal sealed class ReadBuffer : IDisposable\n    {\n        #region Initialization/finalization\n\n        public IntPtr PluginPointer { get { return _plugin; } }\n        public int Index { get; set; }\n        public float Time { get; set; }\n\n        #endregion\n\n        #region Initialization/finalization\n\n        public ReadBuffer()\n        {\n            _plugin = KlakHap_CreateReadBuffer();\n            Index = Int32.MaxValue;\n            Time = Single.MaxValue;\n        }\n\n        public void Dispose()\n        {\n            KlakHap_DestroyReadBuffer(_plugin);\n        }\n\n        #endregion\n\n        #region Private members\n\n        IntPtr _plugin;\n\n        #endregion\n\n        #region Native plugin entry points\n\n        [DllImport(\"KlakHap\")]\n        internal static extern IntPtr KlakHap_CreateReadBuffer();\n\n        [DllImport(\"KlakHap\")]\n        internal static extern void KlakHap_DestroyReadBuffer(IntPtr buffer);\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Runtime/Internal/ReadBuffer.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 4e6e9144df4395d4fbff558262502c67\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Runtime/Internal/StreamReader.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Runtime.InteropServices;\nusing System.Threading;\n\nnamespace Klak.Hap\n{\n    internal sealed class StreamReader : IDisposable\n    {\n        #region Public methods\n\n        public StreamReader(Demuxer demuxer, float time, float delta)\n        {\n            _demuxer = demuxer;\n\n            _leadQueue = new Queue<ReadBuffer>();\n            _freeBuffers = new List<ReadBuffer>();\n\n            // Initial buffer entry allocation\n            _freeBuffers.Add(new ReadBuffer());\n            _freeBuffers.Add(new ReadBuffer());\n            _freeBuffers.Add(new ReadBuffer());\n            _freeBuffers.Add(new ReadBuffer());\n\n            // Initial playback settings\n            _restart = (time, SafeDelta(delta));\n\n            // Reader thread startup\n            _updateEvent = new AutoResetEvent(true);\n            _readEvent = new AutoResetEvent(false);\n            _thread = new Thread(ReaderThread);\n            _thread.Start();\n        }\n\n        public void Dispose()\n        {\n            if (_thread != null)\n            {\n                _terminate = true;\n                _updateEvent.Set();\n                _thread.Join();\n                _thread = null;\n            }\n\n            if (_updateEvent != null)\n            {\n                _updateEvent.Dispose();\n                _updateEvent = null;\n            }\n\n            if (_readEvent != null)\n            {\n                _readEvent.Dispose();\n                _readEvent = null;\n            }\n\n            if (_current != null)\n            {\n                _current.Dispose();\n                _current = null;\n            }\n\n            if (_leadQueue != null)\n            {\n                foreach (var rb in _leadQueue) rb.Dispose();\n                _leadQueue.Clear();\n                _leadQueue = null;\n            }\n\n            if (_freeBuffers != null)\n            {\n                foreach (var rb in _freeBuffers) rb.Dispose();\n                _freeBuffers.Clear();\n                _freeBuffers = null;\n            }\n        }\n\n        public void Restart(float time, float delta)\n        {\n            // Restart request\n            lock (_restartLock) _restart = (time, SafeDelta(delta));\n\n            // Wait for reset/read on the reader thread.\n            _readEvent.Reset();\n            while (_restart != null)\n            {\n                _updateEvent.Set();\n                _readEvent.WaitOne();\n            }\n        }\n\n        public ReadBuffer Advance(float time)\n        {\n            // Add an epsilon-ish value to avoid rounding error.\n            time += 1e-6f;\n\n            var changed = false;\n\n            // There is no slow path in this function, so we prefer holding\n            // the queue lock for the entire function block rather than\n            // acquiring/releasing it for each operation.\n            lock (_queueLock)\n            {\n                // Scan the lead queue.\n                while (_leadQueue.Count > 0)\n                {\n                    var peek = _leadQueue.Peek();\n\n                    if (_current != null)\n                    {\n                        if (_current.Time <= peek.Time)\n                        {\n                            // Forward playback case:\n                            // Break if it hasn't reached the next frame.\n                            if (time < peek.Time) break;\n                        }\n                        else\n                        {\n                            // Reverse playback case:\n                            // Break if it's still on the current frame.\n                            if (_current.Time < time) break;\n                        }\n\n                        // Free the current frame before replacing it.\n                        _freeBuffers.Add(_current);\n                    }\n\n                    _current = _leadQueue.Dequeue();\n                    changed = true;\n                }\n            }\n\n            // Poke the reader thread.\n            _updateEvent.Set();\n\n            // Only returns a buffer object when the frame was changed.\n            return changed ? _current : null;\n        }\n\n        #endregion\n\n        #region Private members\n\n        // Assigned demuxer\n        Demuxer _demuxer;\n\n        // Thread and synchronization objects\n        Thread _thread;\n        AutoResetEvent _updateEvent;\n        AutoResetEvent _readEvent;\n        bool _terminate;\n\n        // Read buffer objects\n        ReadBuffer _current;\n        Queue<ReadBuffer> _leadQueue;\n        List<ReadBuffer> _freeBuffers;\n        readonly object _queueLock = new object();\n\n        // Restart request\n        (float, float)? _restart;\n        readonly object _restartLock = new object();\n\n        // Used to avoid too small delta time values.\n        float SafeDelta(float delta)\n        {\n            var min = (float)(_demuxer.Duration / _demuxer.FrameCount);\n            return Math.Max(Math.Abs(delta), min) * (delta < 0 ? -1 : 1);\n        }\n\n        #endregion\n\n        #region Thread function\n\n        void ReaderThread()\n        {\n            // Initial time settings from the restart request tuple\n            var (time, delta) = _restart.Value;\n            _restart = null;\n\n            // Stream attributes\n            var totalTime = _demuxer.Duration;\n            var totalFrames = _demuxer.FrameCount;\n\n            while (true)\n            {\n                // Synchronization with the parent thread\n                _updateEvent.WaitOne();\n                if (_terminate) break;\n\n                // Check if there is a restart request.\n                lock (_restartLock) if (_restart != null)\n                {\n                    // Flush out the current contents of the lead queue.\n                    lock (_queueLock) while (_leadQueue.Count > 0)\n                        _freeBuffers.Add(_leadQueue.Dequeue());\n\n                    // Apply the restart request.\n                    (time, delta) = _restart.Value;\n                    _restart = null;\n                }\n\n                // Time -> Frame count\n                // Rounding strategy: We don't prefer Math.Round because it can\n                // show a frame before the playhead reaches it (especially when\n                // using slow-mo). On the other hand, Math.Floor causes frame\n                // skipping due to rounding errors. To avoid these problems,\n                // we use the \"adding a very-very small fractional frame\"\n                // approach. 1/1000 might be safe and enough for all the cases.\n                var frameCount = (int)(time * totalFrames / totalTime + 1e-3f);\n\n                // Frame count -> Frame snapped time\n                var snappedTime = (float)(frameCount * totalTime / totalFrames);\n\n                // Frame count -> Wrapped frame number\n                var frameNumber = frameCount % totalFrames;\n                if (frameNumber < 0) frameNumber += totalFrames;\n\n                lock (_queueLock)\n                {\n                    // Do nothing if there is no free buffer; It indicates that\n                    // the lead queue is fully filled.\n                    if (_freeBuffers.Count == 0) continue;\n\n                    ReadBuffer buffer = null;\n\n                    // Look for a free buffer that has the same frame number.\n                    foreach (var temp in _freeBuffers)\n                    {\n                        if (temp.Index == frameNumber)\n                        {\n                            buffer = temp;\n                            break;\n                        }\n                    }\n\n                    if (buffer != null)\n                    {\n                        // Reuse the found buffer; Although we can use it\n                        // without reading frame data, the time field should\n                        // be updated to handle wrapping-around hits.\n                        _freeBuffers.Remove(buffer);\n                        buffer.Time = snappedTime;\n                    }\n                    else\n                    {\n                        // Allocate a buffer from the free buffer list.\n                        buffer = _freeBuffers[_freeBuffers.Count - 1];\n                        _freeBuffers.RemoveAt(_freeBuffers.Count - 1);\n\n                        // Frame data read\n                        _demuxer.ReadFrame(buffer, frameNumber, snappedTime);\n                    }\n\n                    // Push the buffer to the lead queue.\n                    _leadQueue.Enqueue(buffer);\n                }\n\n                _readEvent.Set();\n\n                time += delta;\n            }\n        }\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Runtime/Internal/StreamReader.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 435d6c4db4ba1ea40b2289d7ef613a3c\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Runtime/Internal/TextureUpdater.cs",
    "content": "using System;\nusing System.Runtime.InteropServices;\nusing UnityEngine;\nusing UnityEngine.Rendering;\n\nnamespace Klak.Hap\n{\n    internal sealed class TextureUpdater : IDisposable\n    {\n        #region Public properties\n\n        public static bool AsyncSupport { get {\n            return SystemInfo.graphicsDeviceType == GraphicsDeviceType.Direct3D11;\n        } }\n\n        #endregion\n\n        #region Public methods\n\n        public TextureUpdater(Texture2D texture, Decoder decoder)\n        {\n            _texture = texture;\n            _decoder = decoder;\n\n            if (AsyncSupport)\n            {\n                _command = new CommandBuffer();\n                _command.name = \"Klak HAP\";\n                _command.IssuePluginCustomTextureUpdateV2(\n                    KlakHap_GetTextureUpdateCallback(),\n                    texture, decoder.CallbackID\n                );\n            }\n        }\n\n        public void Dispose()\n        {\n            if (_command != null)\n            {\n                _command.Dispose();\n                _command = null;\n            }\n        }\n\n        public void UpdateNow()\n        {\n            _texture.LoadRawTextureData(\n                _decoder.LockBuffer(),\n                _decoder.BufferSize\n            );\n            _texture.Apply();\n            _decoder.UnlockBuffer();\n        }\n\n        public void RequestAsyncUpdate()\n        {\n            if (_command != null) Graphics.ExecuteCommandBuffer(_command);\n        }\n\n        #endregion\n\n        #region Private fields\n\n        Texture2D _texture;\n        Decoder _decoder;\n        CommandBuffer _command;\n\n        #endregion\n\n        #region Native plugin entry points\n\n        [DllImport(\"KlakHap\")]\n        internal static extern IntPtr KlakHap_GetTextureUpdateCallback();\n\n        #endregion\n    }\n}\n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Runtime/Internal/TextureUpdater.cs.meta",
    "content": "fileFormatVersion: 2\nguid: f9e27f5a05bda2e4eab2f548840a9fb1\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Runtime/Internal/Utility.cs",
    "content": "using UnityEngine;\n\nnamespace Klak.Hap\n{\n    internal static class Utility\n    {\n        public static void Destroy(Object o)\n        {\n            if (o == null) return;\n            if (Application.isPlaying)\n                Object.Destroy(o);\n            else\n                Object.DestroyImmediate(o);\n        }\n\n        public static CodecType DetermineCodecType(int videoType)\n        {\n            switch (videoType & 0xf)\n            {\n                case 0xb: return CodecType.Hap;\n                case 0xe: return CodecType.HapAlpha;\n                case 0xf: return CodecType.HapQ;\n            }\n            return CodecType.Unsupported;\n        }\n\n        public static TextureFormat DetermineTextureFormat(int videoType)\n        {\n            switch (videoType & 0xf)\n            {\n                case 0xb: return TextureFormat.DXT1;\n                case 0xe: return TextureFormat.DXT5;\n                case 0xf: return TextureFormat.DXT5;\n                case 0xc: return TextureFormat.BC7;\n                case 0x1: return TextureFormat.BC4;\n            }\n            return TextureFormat.DXT1;\n        }\n\n        public static Shader DetermineBlitShader(int videoType)\n        {\n            if ((videoType & 0xf) == 0xf)\n                return Shader.Find(\"Klak/HAP Q\");\n            else\n                return Shader.Find(\"Klak/HAP\");\n        }\n    }\n}\n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Runtime/Internal/Utility.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 970c4e0f94959ac4b9b108dc1a34306e\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Runtime/Internal.meta",
    "content": "fileFormatVersion: 2\nguid: d37984629e38a1c439a98815991ec09f\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Runtime/Klak.Hap.asmdef",
    "content": "{\n    \"name\": \"Klak.Hap\",\n    \"references\": [\n        \"GUID:f06555f75b070af458a003d92f9efb00\"\n    ],\n    \"includePlatforms\": [],\n    \"excludePlatforms\": [],\n    \"allowUnsafeCode\": false,\n    \"overrideReferences\": false,\n    \"precompiledReferences\": [],\n    \"autoReferenced\": true,\n    \"defineConstraints\": [],\n    \"versionDefines\": [\n        {\n            \"name\": \"com.unity.timeline\",\n            \"expression\": \"1.0.0\",\n            \"define\": \"KLAKHAP_HAS_TIMELINE\"\n        }\n    ],\n    \"noEngineReferences\": false\n}"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Runtime/Klak.Hap.asmdef.meta",
    "content": "fileFormatVersion: 2\nguid: 63ee2b3a69c095740bf1e4ff4d11f294\nAssemblyDefinitionImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/Runtime.meta",
    "content": "fileFormatVersion: 2\nguid: 2d10b798fb99ee94981f7dbf19d8d6a9\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/package.json",
    "content": "{\n  \"name\": \"jp.keijiro.klak.hap\",\n  \"version\": \"1.0.0\",\n  \"displayName\": \"KlakHAP\",\n  \"description\": \"HAP video player\",\n  \"unity\": \"2022.3\",\n  \"author\": \"Keijiro Takahashi\",\n  \"dependencies\": {},\n  \"changelogUrl\": \"https://github.com/keijiro/KlakHap/blob/master/CHANGELOG.md\",\n  \"documentationUrl\": \"https://github.com/keijiro/KlakHap\",\n  \"licensesUrl\": \"https://github.com/keijiro/KlakHap/blob/master/LICENSE\",\n  \"license\": \"SEE LICENSE IN LICENSE\",\n  \"_upm\": {\n    \"changelog\": \"<b>Added</b><br>- Added a Unity 6.3 demo scene updated for URP and UI Toolkit.<br>- Added runtime tests and a test data downloader for Hap, HapQ, and HapAlpha assets.<br><br><b>Changed</b><br>- Updated HAP and Snappy source code and refreshed native plugin binaries.<br>- Migrated Windows builds to MinGW and refactored the native build pipelines and Makefiles.<br><br><b>Fixed</b><br>- Fixed a Windows crash when paths contain Japanese characters. (PR #49)<br>- Fixed obsolete ShaderUtil API usage in the editor code.\"\n  }\n}\n"
  },
  {
    "path": "Packages/jp.keijiro.klak.hap/package.json.meta",
    "content": "fileFormatVersion: 2\nguid: 251c3b05c5e2c694da8fe8fe9b07eb5c\nTextScriptImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Packages/manifest.json",
    "content": "{\n  \"dependencies\": {\n    \"com.unity.inputsystem\": \"1.18.0\",\n    \"com.unity.render-pipelines.universal\": \"17.3.0\",\n    \"com.unity.timeline\": \"1.8.10\",\n    \"jp.keijiro.klak.motion\": \"1.1.1\",\n    \"jp.keijiro.klutter-tools\": \"2.6.0\",\n    \"com.unity.modules.imageconversion\": \"1.0.0\",\n    \"com.unity.modules.uielements\": \"1.0.0\"\n  },\n  \"scopedRegistries\": [\n    {\n      \"name\": \"Keijiro\",\n      \"url\": \"https://registry.npmjs.com\",\n      \"scopes\": [\n        \"jp.keijiro\"\n      ]\n    }\n  ]\n}\n"
  },
  {
    "path": "Packages/packages-lock.json",
    "content": "{\n  \"dependencies\": {\n    \"com.unity.burst\": {\n      \"version\": \"1.8.27\",\n      \"depth\": 2,\n      \"source\": \"registry\",\n      \"dependencies\": {\n        \"com.unity.mathematics\": \"1.2.1\",\n        \"com.unity.modules.jsonserialize\": \"1.0.0\"\n      },\n      \"url\": \"https://packages.unity.com\"\n    },\n    \"com.unity.collections\": {\n      \"version\": \"2.6.2\",\n      \"depth\": 2,\n      \"source\": \"registry\",\n      \"dependencies\": {\n        \"com.unity.burst\": \"1.8.23\",\n        \"com.unity.mathematics\": \"1.3.2\",\n        \"com.unity.test-framework\": \"1.4.6\",\n        \"com.unity.nuget.mono-cecil\": \"1.11.5\",\n        \"com.unity.test-framework.performance\": \"3.0.3\"\n      },\n      \"url\": \"https://packages.unity.com\"\n    },\n    \"com.unity.ext.nunit\": {\n      \"version\": \"2.0.5\",\n      \"depth\": 4,\n      \"source\": \"builtin\",\n      \"dependencies\": {}\n    },\n    \"com.unity.inputsystem\": {\n      \"version\": \"1.18.0\",\n      \"depth\": 0,\n      \"source\": \"registry\",\n      \"dependencies\": {\n        \"com.unity.modules.uielements\": \"1.0.0\"\n      },\n      \"url\": \"https://packages.unity.com\"\n    },\n    \"com.unity.mathematics\": {\n      \"version\": \"1.3.3\",\n      \"depth\": 1,\n      \"source\": \"registry\",\n      \"dependencies\": {},\n      \"url\": \"https://packages.unity.com\"\n    },\n    \"com.unity.nuget.mono-cecil\": {\n      \"version\": \"1.11.6\",\n      \"depth\": 3,\n      \"source\": \"registry\",\n      \"dependencies\": {},\n      \"url\": \"https://packages.unity.com\"\n    },\n    \"com.unity.render-pipelines.core\": {\n      \"version\": \"17.3.0\",\n      \"depth\": 1,\n      \"source\": \"builtin\",\n      \"dependencies\": {\n        \"com.unity.burst\": \"1.8.14\",\n        \"com.unity.mathematics\": \"1.3.2\",\n        \"com.unity.ugui\": \"2.0.0\",\n        \"com.unity.collections\": \"2.4.3\",\n        \"com.unity.modules.physics\": \"1.0.0\",\n        \"com.unity.modules.terrain\": \"1.0.0\",\n        \"com.unity.modules.jsonserialize\": \"1.0.0\"\n      }\n    },\n    \"com.unity.render-pipelines.universal\": {\n      \"version\": \"17.3.0\",\n      \"depth\": 0,\n      \"source\": \"builtin\",\n      \"dependencies\": {\n        \"com.unity.render-pipelines.core\": \"17.3.0\",\n        \"com.unity.shadergraph\": \"17.3.0\",\n        \"com.unity.render-pipelines.universal-config\": \"17.0.3\"\n      }\n    },\n    \"com.unity.render-pipelines.universal-config\": {\n      \"version\": \"17.0.3\",\n      \"depth\": 1,\n      \"source\": \"builtin\",\n      \"dependencies\": {\n        \"com.unity.render-pipelines.core\": \"17.0.3\"\n      }\n    },\n    \"com.unity.searcher\": {\n      \"version\": \"4.9.4\",\n      \"depth\": 2,\n      \"source\": \"registry\",\n      \"dependencies\": {},\n      \"url\": \"https://packages.unity.com\"\n    },\n    \"com.unity.shadergraph\": {\n      \"version\": \"17.3.0\",\n      \"depth\": 1,\n      \"source\": \"builtin\",\n      \"dependencies\": {\n        \"com.unity.render-pipelines.core\": \"17.3.0\",\n        \"com.unity.searcher\": \"4.9.3\"\n      }\n    },\n    \"com.unity.test-framework\": {\n      \"version\": \"1.6.0\",\n      \"depth\": 3,\n      \"source\": \"builtin\",\n      \"dependencies\": {\n        \"com.unity.ext.nunit\": \"2.0.3\",\n        \"com.unity.modules.imgui\": \"1.0.0\",\n        \"com.unity.modules.jsonserialize\": \"1.0.0\"\n      }\n    },\n    \"com.unity.test-framework.performance\": {\n      \"version\": \"3.2.0\",\n      \"depth\": 3,\n      \"source\": \"registry\",\n      \"dependencies\": {\n        \"com.unity.test-framework\": \"1.1.33\",\n        \"com.unity.modules.jsonserialize\": \"1.0.0\"\n      },\n      \"url\": \"https://packages.unity.com\"\n    },\n    \"com.unity.timeline\": {\n      \"version\": \"1.8.10\",\n      \"depth\": 0,\n      \"source\": \"registry\",\n      \"dependencies\": {\n        \"com.unity.modules.audio\": \"1.0.0\",\n        \"com.unity.modules.director\": \"1.0.0\",\n        \"com.unity.modules.animation\": \"1.0.0\",\n        \"com.unity.modules.particlesystem\": \"1.0.0\"\n      },\n      \"url\": \"https://packages.unity.com\"\n    },\n    \"com.unity.ugui\": {\n      \"version\": \"2.0.0\",\n      \"depth\": 2,\n      \"source\": \"builtin\",\n      \"dependencies\": {\n        \"com.unity.modules.ui\": \"1.0.0\",\n        \"com.unity.modules.imgui\": \"1.0.0\"\n      }\n    },\n    \"jp.keijiro.klak.hap\": {\n      \"version\": \"file:jp.keijiro.klak.hap\",\n      \"depth\": 0,\n      \"source\": \"embedded\",\n      \"dependencies\": {}\n    },\n    \"jp.keijiro.klak.motion\": {\n      \"version\": \"1.1.1\",\n      \"depth\": 0,\n      \"source\": \"registry\",\n      \"dependencies\": {\n        \"com.unity.mathematics\": \"1.2.1\"\n      },\n      \"url\": \"https://registry.npmjs.com\"\n    },\n    \"jp.keijiro.klutter-tools\": {\n      \"version\": \"2.6.0\",\n      \"depth\": 0,\n      \"source\": \"registry\",\n      \"dependencies\": {},\n      \"url\": \"https://registry.npmjs.com\"\n    },\n    \"com.unity.modules.animation\": {\n      \"version\": \"1.0.0\",\n      \"depth\": 1,\n      \"source\": \"builtin\",\n      \"dependencies\": {}\n    },\n    \"com.unity.modules.audio\": {\n      \"version\": \"1.0.0\",\n      \"depth\": 1,\n      \"source\": \"builtin\",\n      \"dependencies\": {}\n    },\n    \"com.unity.modules.director\": {\n      \"version\": \"1.0.0\",\n      \"depth\": 1,\n      \"source\": \"builtin\",\n      \"dependencies\": {\n        \"com.unity.modules.audio\": \"1.0.0\",\n        \"com.unity.modules.animation\": \"1.0.0\"\n      }\n    },\n    \"com.unity.modules.hierarchycore\": {\n      \"version\": \"1.0.0\",\n      \"depth\": 1,\n      \"source\": \"builtin\",\n      \"dependencies\": {}\n    },\n    \"com.unity.modules.imageconversion\": {\n      \"version\": \"1.0.0\",\n      \"depth\": 0,\n      \"source\": \"builtin\",\n      \"dependencies\": {}\n    },\n    \"com.unity.modules.imgui\": {\n      \"version\": \"1.0.0\",\n      \"depth\": 1,\n      \"source\": \"builtin\",\n      \"dependencies\": {}\n    },\n    \"com.unity.modules.jsonserialize\": {\n      \"version\": \"1.0.0\",\n      \"depth\": 1,\n      \"source\": \"builtin\",\n      \"dependencies\": {}\n    },\n    \"com.unity.modules.particlesystem\": {\n      \"version\": \"1.0.0\",\n      \"depth\": 1,\n      \"source\": \"builtin\",\n      \"dependencies\": {}\n    },\n    \"com.unity.modules.physics\": {\n      \"version\": \"1.0.0\",\n      \"depth\": 1,\n      \"source\": \"builtin\",\n      \"dependencies\": {}\n    },\n    \"com.unity.modules.terrain\": {\n      \"version\": \"1.0.0\",\n      \"depth\": 2,\n      \"source\": \"builtin\",\n      \"dependencies\": {}\n    },\n    \"com.unity.modules.ui\": {\n      \"version\": \"1.0.0\",\n      \"depth\": 1,\n      \"source\": \"builtin\",\n      \"dependencies\": {}\n    },\n    \"com.unity.modules.uielements\": {\n      \"version\": \"1.0.0\",\n      \"depth\": 0,\n      \"source\": \"builtin\",\n      \"dependencies\": {\n        \"com.unity.modules.ui\": \"1.0.0\",\n        \"com.unity.modules.imgui\": \"1.0.0\",\n        \"com.unity.modules.jsonserialize\": \"1.0.0\",\n        \"com.unity.modules.hierarchycore\": \"1.0.0\",\n        \"com.unity.modules.physics\": \"1.0.0\"\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "Plugin/Common.mk",
    "content": "#\n# File listings\n#\n\nPRODUCT = KlakHap\n\nSRCS_C = Hap/hap.c MP4/mp4demux.c\nvpath %.c Hap MP4\n\nSRCS_CC = Snappy/snappy-c.cc \\\n\t      Snappy/snappy-sinksource.cc \\\n\t      Snappy/snappy-stubs-internal.cc \\\n\t      Snappy/snappy.cc\nvpath %.cc Snappy\n\nSRCS_CPP = Source/KlakHap.cpp\nvpath %.cpp Source\n\nSRCS = $(SRCS_C) $(SRCS_CC) $(SRCS_CPP)\n\nOBJ_DIR = build-$(PLATFORM)-$(ARCH)\n\n#\n# Intermediate/output files\n#\n\nOBJS_C   = $(addprefix $(OBJ_DIR)/, $(notdir $(patsubst %.c,  %.o, $(SRCS_C)  )))\nOBJS_CC  = $(addprefix $(OBJ_DIR)/, $(notdir $(patsubst %.cc, %.o, $(SRCS_CC) )))\nOBJS_CPP = $(addprefix $(OBJ_DIR)/, $(notdir $(patsubst %.cpp,%.o, $(SRCS_CPP))))\n\nOBJS = $(OBJS_C) $(OBJS_CC) $(OBJS_CPP)\n\nifeq ($(TARGET_TYPE), dll)\n  TARGET = $(OBJ_DIR)/$(PRODUCT).$(TARGET_TYPE)\nelse\n  TARGET = $(OBJ_DIR)/lib$(PRODUCT).$(TARGET_TYPE)\nendif\n\n#\n# Toolchain\n#\n\nifndef AR\n  AR = ar\nendif\n\nifeq ($(origin CC),default)\n  CC = clang\nendif\n\nifeq ($(origin CXX),default)\n  CXX = clang++\nendif\n\nifndef STRIP\n  STRIP = strip\nendif\n\n#\n# Compiler/linker options\n#\n\nCPPFLAGS += -ISnappy -IHap -IMP4 -IUnity\nCFLAGS += -O2 -Wall -Wextra -Wno-sign-compare -Wno-implicit-fallthrough\nCXXFLAGS += -O2 -Wall -Wextra -Wno-unused-parameter -Wno-switch -Wno-unknown-pragmas -std=c++17\n\n#\n# Building rules\n#\n\nall: $(TARGET)\n\nclean:\n\trm -f $(TARGET) $(OBJS)\n\ncopy: $(TARGET)\n\tcp $(TARGET) ../Packages/jp.keijiro.klak.hap/Plugin/$(PLATFORM)\n\n$(OBJ_DIR)/$(PRODUCT).dll: $(OBJS)\n\t$(CXX) $(LDFLAGS) -o $@ $^ $(LIBS)\n\t$(STRIP) $@\n\n$(OBJ_DIR)/lib$(PRODUCT).dylib: $(OBJS)\n\t$(CXX) $(LDFLAGS) -o $@ $^ $(LIBS)\n\n$(OBJ_DIR)/lib$(PRODUCT).so: $(OBJS)\n\t$(CXX) $(LDFLAGS) -o $@ $^ $(LIBS)\n\n$(OBJ_DIR)/%.o: %.c | $(OBJ_DIR)\n\t$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<\n\n$(OBJ_DIR)/%.o: %.cc | $(OBJ_DIR)\n\t$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<\n\n$(OBJ_DIR)/%.o: %.cpp | $(OBJ_DIR)\n\t$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<\n\n$(OBJ_DIR):\n\tmkdir -p $(OBJ_DIR)\n"
  },
  {
    "path": "Plugin/Hap/hap.c",
    "content": "/*\n hap.c\n \n Copyright (c) 2011-2013, Tom Butterworth and Vidvox LLC. All rights reserved.\n \n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are met:\n \n * Redistributions of source code must retain the above copyright\n notice, this list of conditions and the following disclaimer.\n \n * Redistributions in binary form must reproduce the above copyright\n notice, this list of conditions and the following disclaimer in the\n documentation and/or other materials provided with the distribution.\n \n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY\n DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"hap.h\"\n#include <stdlib.h>\n#include <stdint.h>\n#include <string.h> // For memcpy for uncompressed frames\n#include \"snappy-c.h\"\n\n#define kHapUInt24Max 0x00FFFFFF\n\n/*\n Hap Constants\n First four bits represent the compressor\n Second four bits represent the format\n */\n#define kHapCompressorNone 0xA\n#define kHapCompressorSnappy 0xB\n#define kHapCompressorComplex 0xC\n\n#define kHapFormatRGBDXT1 0xB\n#define kHapFormatRGBADXT5 0xE\n#define kHapFormatYCoCgDXT5 0xF\n#define kHapFormatARGTC1 0x1\n#define kHapFormatRGBABPTC 0xC\n#define kHapFormatRGBBPTCUF 0x2\n#define kHapFormatRGBBPTCSF 0x3\n\n/*\n Packed byte values for Hap\n \n Format                     Compressor      Byte Code\n ----------------------------------------------------\n RGB_DXT1                   None            0xAB\n RGB_DXT1                   Snappy          0xBB\n RGB_DXT1                   Complex         0xCB\n RGBA_DXT5                  None            0xAE\n RGBA_DXT5                  Snappy          0xBE\n RGBA_DXT5                  Complex         0xCE\n YCoCg_DXT5                 None            0xAF\n YCoCg_DXT5                 Snappy          0xBF\n YCoCg_DXT5                 Complex         0xCF\n A_RGTC1                    None            0xA1\n A_RGTC1                    Snappy          0xB1\n A_RGTC1                    Complex         0xC1\n RGBA_BPTC_UNORM            None            0xAC\n RGBA_BPTC_UNORM            Snappy          0xBC\n RGBA_BPTC_UNORM            Complex         0xCC\n RGB_BPTC_UNSIGNED_FLOAT    None            0xA2\n RGB_BPTC_UNSIGNED_FLOAT    Snappy          0xB2\n RGB_BPTC_UNSIGNED_FLOAT    Complex         0xC2\n RGB_BPTC_SIGNED_FLOAT      None            0xA3\n RGB_BPTC_SIGNED_FLOAT      Snappy          0xB3\n RGB_BPTC_SIGNED_FLOAT      Complex         0xC3\n */\n\n/*\n Hap Frame Section Types\n */\n#define kHapSectionMultipleImages 0x0D\n#define kHapSectionDecodeInstructionsContainer 0x01\n#define kHapSectionChunkSecondStageCompressorTable 0x02\n#define kHapSectionChunkSizeTable 0x03\n#define kHapSectionChunkOffsetTable 0x04\n\n/*\n To decode we use a struct to store details of each chunk\n */\ntypedef struct HapChunkDecodeInfo {\n    unsigned int result;\n    unsigned int compressor;\n    const char *compressed_chunk_data;\n    size_t compressed_chunk_size;\n    char *uncompressed_chunk_data;\n    size_t uncompressed_chunk_size;\n} HapChunkDecodeInfo;\n\n// TODO: rename the defines we use for codes used in stored frames\n// to better differentiate them from the enums used for the API\n\n// These read and write little-endian values on big or little-endian architectures\nstatic unsigned int hap_read_3_byte_uint(const void *buffer)\n{\n    return (*(uint8_t *)buffer) + ((*(((uint8_t *)buffer) + 1)) << 8) + ((*(((uint8_t *)buffer) + 2)) << 16);\n}\n\nstatic void hap_write_3_byte_uint(void *buffer, unsigned int value)\n{\n    *(uint8_t *)buffer = value & 0xFF;\n    *(((uint8_t *)buffer) + 1) = (value >> 8) & 0xFF;\n    *(((uint8_t *)buffer) + 2) = (value >> 16) & 0xFF;\n}\n\nstatic unsigned int hap_read_4_byte_uint(const void *buffer)\n{\n    return (*(uint8_t *)buffer) + ((*(((uint8_t *)buffer) + 1)) << 8) + ((*(((uint8_t *)buffer) + 2)) << 16) + ((*(((uint8_t *)buffer) + 3)) << 24);\n}\n\nstatic void hap_write_4_byte_uint(const void *buffer, unsigned int value)\n{\n    *(uint8_t *)buffer = value & 0xFF;\n    *(((uint8_t *)buffer) + 1) = (value >> 8) & 0xFF;\n    *(((uint8_t *)buffer) + 2) = (value >> 16) & 0xFF;\n    *(((uint8_t *)buffer) + 3) = (value >> 24) & 0xFF;\n}\n\n#define hap_top_4_bits(x) (((x) & 0xF0) >> 4)\n\n#define hap_bottom_4_bits(x) ((x) & 0x0F)\n\n#define hap_4_bit_packed_byte(top_bits, bottom_bits) (((top_bits) << 4) | ((bottom_bits) & 0x0F))\n\nstatic int hap_read_section_header(const void *buffer, uint32_t buffer_length, uint32_t *out_header_length, uint32_t *out_section_length, unsigned int *out_section_type)\n{\n    /*\n     Verify buffer is big enough to contain a four-byte header\n     */\n    if (buffer_length < 4U)\n    {\n        return HapResult_Bad_Frame;\n    }\n\n    /*\n     The first three bytes are the length of the section (not including the header) or zero\n     if the length is stored in the last four bytes of an eight-byte header\n     */\n    *out_section_length = hap_read_3_byte_uint(buffer);\n\n    /*\n     If the first three bytes are zero, the size is in the following four bytes\n     */\n    if (*out_section_length == 0U)\n    {\n        /*\n         Verify buffer is big enough to contain an eight-byte header\n         */\n        if (buffer_length < 8U)\n        {\n            return HapResult_Bad_Frame;\n        }\n        *out_section_length = hap_read_4_byte_uint(((uint8_t *)buffer) + 4U);\n        *out_header_length = 8U;\n    }\n    else\n    {\n        *out_header_length = 4U;\n    }\n\n    /*\n     The fourth byte stores the section type\n     */\n    *out_section_type = *(((uint8_t *)buffer) + 3U);\n    \n    /*\n     Verify the section does not extend beyond the buffer\n     */\n    if (*out_header_length + *out_section_length > buffer_length)\n    {\n        return HapResult_Bad_Frame;\n    }\n\n    return HapResult_No_Error;\n}\n\nstatic void hap_write_section_header(void *buffer, size_t header_length, uint32_t section_length, unsigned int section_type)\n{\n    /*\n     The first three bytes are the length of the section (not including the header) or zero\n     if using an eight-byte header\n     */\n    if (header_length == 4U)\n    {\n        hap_write_3_byte_uint(buffer, (unsigned int)section_length);\n    }\n    else\n    {\n        /*\n         For an eight-byte header, the length is in the last four bytes\n         */\n        hap_write_3_byte_uint(buffer, 0U);\n        hap_write_4_byte_uint(((uint8_t *)buffer) + 4U, section_length);\n    }\n    \n    /*\n     The fourth byte stores the section type\n     */\n    *(((uint8_t *)buffer) + 3) = section_type;\n}\n\n// Returns an API texture format constant or 0 if not recognised\nstatic unsigned int hap_texture_format_constant_for_format_identifier(unsigned int identifier)\n{\n    switch (identifier)\n    {\n        case kHapFormatRGBDXT1:\n            return HapTextureFormat_RGB_DXT1;\n        case kHapFormatRGBADXT5:\n            return HapTextureFormat_RGBA_DXT5;\n        case kHapFormatYCoCgDXT5:\n            return HapTextureFormat_YCoCg_DXT5;\n        case kHapFormatARGTC1:\n            return HapTextureFormat_A_RGTC1;\n        case kHapFormatRGBABPTC:\n            return HapTextureFormat_RGBA_BPTC_UNORM;\n        case kHapFormatRGBBPTCUF:\n            return HapTextureFormat_RGB_BPTC_UNSIGNED_FLOAT;\n        case kHapFormatRGBBPTCSF:\n            return HapTextureFormat_RGB_BPTC_SIGNED_FLOAT;\n        default:\n            return 0;\n            \n    }\n}\n\n// Returns a frame identifier or 0 if not recognised\nstatic unsigned int hap_texture_format_identifier_for_format_constant(unsigned int constant)\n{\n    switch (constant)\n    {\n        case HapTextureFormat_RGB_DXT1:\n            return kHapFormatRGBDXT1;\n        case HapTextureFormat_RGBA_DXT5:\n            return kHapFormatRGBADXT5;\n        case HapTextureFormat_YCoCg_DXT5:\n            return kHapFormatYCoCgDXT5;\n        case HapTextureFormat_A_RGTC1:\n            return kHapFormatARGTC1;\n        case HapTextureFormat_RGBA_BPTC_UNORM:\n            return kHapFormatRGBABPTC;\n        case HapTextureFormat_RGB_BPTC_UNSIGNED_FLOAT:\n            return kHapFormatRGBBPTCUF;\n        case HapTextureFormat_RGB_BPTC_SIGNED_FLOAT:\n            return kHapFormatRGBBPTCSF;\n        default:\n            return 0;\n    }\n}\n\n// Returns the length of a decode instructions container of chunk_count chunks\n// not including the section header\nstatic size_t hap_decode_instructions_length(unsigned int chunk_count)\n{\n    /*\n     Calculate the size of our Decode Instructions Section\n     = Second-Stage Compressor Table + Chunk Size Table + headers for both sections\n     = chunk_count + (4 * chunk_count) + 4 + 4\n     */\n    size_t length = (5 * chunk_count) + 8;\n\n    return length;\n}\n\nstatic unsigned int hap_limited_chunk_count_for_frame(size_t input_bytes, unsigned int texture_format, unsigned int chunk_count)\n{\n    // This is a hard limit due to the 4-byte headers we use for the decode instruction container\n    // (0xFFFFFF == count + (4 x count) + 20)\n    if (chunk_count > 3355431)\n    {\n        chunk_count = 3355431;\n    }\n    // Divide frame equally on DXT block boundries (8 or 16 bytes)\n    unsigned long dxt_block_count;\n    switch (texture_format) {\n        case HapTextureFormat_RGB_DXT1:\n        case HapTextureFormat_A_RGTC1:\n            dxt_block_count = input_bytes / 8;\n            break;\n        default:\n            dxt_block_count = input_bytes / 16;\n    }\n    while (dxt_block_count % chunk_count != 0) {\n        chunk_count--;\n    }\n\n    return chunk_count;\n}\n\nstatic size_t hap_max_encoded_length(size_t input_bytes, unsigned int texture_format, unsigned int compressor, unsigned int chunk_count)\n{\n    size_t decode_instructions_length, max_compressed_length;\n\n    chunk_count = hap_limited_chunk_count_for_frame(input_bytes, texture_format, chunk_count);\n\n    decode_instructions_length = hap_decode_instructions_length(chunk_count);\n\n    if (compressor == HapCompressorSnappy)\n    {\n        size_t chunk_size = input_bytes / chunk_count;\n        max_compressed_length = snappy_max_compressed_length(chunk_size) * chunk_count;\n    }\n    else\n    {\n        max_compressed_length = input_bytes;\n    }\n\n    // top section header + decode instructions section header + decode instructions + compressed data\n    return max_compressed_length + 8U + decode_instructions_length + 4U;\n}\n\nunsigned long HapMaxEncodedLength(unsigned int count,\n                                  unsigned long *inputBytes,\n                                  unsigned int *textureFormats,\n                                  unsigned int *chunkCounts)\n{\n    // Start with the length of a multiple-image section header\n    unsigned long total_length = 8;\n\n    // Return 0 for bad arguments\n    if (count == 0 || count > 2\n        || inputBytes == NULL\n        || textureFormats == NULL\n        || chunkCounts == NULL)\n    {\n        return 0;\n    }\n\n    for (int i = 0; i < count; i++)\n    {\n        if (chunkCounts[i] == 0)\n        {\n            return 0;\n        }\n\n        // Assume snappy, the worst case\n        total_length += hap_max_encoded_length(inputBytes[i], textureFormats[i], HapCompressorSnappy, chunkCounts[i]);\n    }\n\n    return total_length;\n}\n\nstatic unsigned int hap_encode_texture(const void *inputBuffer, unsigned long inputBufferBytes, unsigned int textureFormat,\n                                       unsigned int compressor, unsigned int chunkCount, void *outputBuffer,\n                                       unsigned long outputBufferBytes, unsigned long *outputBufferBytesUsed)\n{\n    size_t top_section_header_length;\n    size_t top_section_length;\n    unsigned int storedCompressor;\n    unsigned int storedFormat;\n\n    /*\n     Check arguments\n     */\n    if (inputBuffer == NULL\n        || inputBufferBytes == 0\n        || (textureFormat != HapTextureFormat_RGB_DXT1\n            && textureFormat != HapTextureFormat_RGBA_DXT5\n            && textureFormat != HapTextureFormat_YCoCg_DXT5\n            && textureFormat != HapTextureFormat_A_RGTC1\n            && textureFormat != HapTextureFormat_RGBA_BPTC_UNORM\n            && textureFormat != HapTextureFormat_RGB_BPTC_UNSIGNED_FLOAT\n            && textureFormat != HapTextureFormat_RGB_BPTC_SIGNED_FLOAT\n            )\n        || (compressor != HapCompressorNone\n            && compressor != HapCompressorSnappy\n            )\n        || outputBuffer == NULL\n        || outputBufferBytesUsed == NULL\n        )\n    {\n        return HapResult_Bad_Arguments;\n    }\n    else if (outputBufferBytes < hap_max_encoded_length(inputBufferBytes, textureFormat, compressor, chunkCount))\n    {\n        return HapResult_Buffer_Too_Small;\n    }\n    \n    /*\n     To store frames of length greater than can be expressed in three bytes, we use an eight byte header (the last four bytes are the\n     frame size). We don't know the compressed size until we have performed compression, but we know the worst-case size\n     (the uncompressed size), so choose header-length based on that.\n     \n     A simpler encoder could always use the eight-byte header variation.\n     */\n    if (inputBufferBytes > kHapUInt24Max)\n    {\n        top_section_header_length = 8U;\n    }\n    else\n    {\n        top_section_header_length = 4U;\n    }\n\n    if (compressor == HapCompressorSnappy)\n    {\n        /*\n         We attempt to chunk as requested, and if resulting frame is larger than it is uncompressed then\n         store frame uncompressed\n         */\n\n        size_t decode_instructions_length;\n        size_t chunk_size, compress_buffer_remaining;\n        uint8_t *second_stage_compressor_table;\n        void *chunk_size_table;\n        char *compressed_data;\n        unsigned int i;\n\n        chunkCount = hap_limited_chunk_count_for_frame(inputBufferBytes, textureFormat, chunkCount);\n        decode_instructions_length = hap_decode_instructions_length(chunkCount);\n\n        // Check we have space for the Decode Instructions Container\n        if ((inputBufferBytes + decode_instructions_length + 4) > kHapUInt24Max)\n        {\n            top_section_header_length = 8U;\n        }\n\n        second_stage_compressor_table = ((uint8_t *)outputBuffer) + top_section_header_length + 4 + 4;\n        chunk_size_table = ((uint8_t *)outputBuffer) + top_section_header_length + 4 + 4 + chunkCount + 4;\n\n        chunk_size = inputBufferBytes / chunkCount;\n\n        // write the Decode Instructions section header\n        hap_write_section_header(((uint8_t *)outputBuffer) + top_section_header_length, 4U, decode_instructions_length, kHapSectionDecodeInstructionsContainer);\n        // write the Second Stage Compressor Table section header\n        hap_write_section_header(((uint8_t *)outputBuffer) + top_section_header_length + 4U, 4U, chunkCount, kHapSectionChunkSecondStageCompressorTable);\n        // write the Chunk Size Table section header\n        hap_write_section_header(((uint8_t *)outputBuffer) + top_section_header_length + 4U + 4U + chunkCount, 4U, chunkCount * 4U, kHapSectionChunkSizeTable);\n\n        compressed_data = (char *)(((uint8_t *)outputBuffer) + top_section_header_length + 4 + decode_instructions_length);\n\n        compress_buffer_remaining = outputBufferBytes - top_section_header_length - 4 - decode_instructions_length;\n\n        top_section_length = 4 + decode_instructions_length;\n\n        for (i = 0; i < chunkCount; i++) {\n            size_t chunk_packed_length = compress_buffer_remaining;\n            const char *chunk_input_start = (const char *)(((uint8_t *)inputBuffer) + (chunk_size * i));\n            if (compressor == HapCompressorSnappy)\n            {\n                snappy_status result = snappy_compress(chunk_input_start, chunk_size, (char *)compressed_data, &chunk_packed_length);\n                if (result != SNAPPY_OK)\n                {\n                    return HapResult_Internal_Error;\n                }\n            }\n\n            if (compressor == HapCompressorNone || chunk_packed_length >= chunk_size)\n            {\n                // store the chunk uncompressed\n                memcpy(compressed_data, chunk_input_start, chunk_size);\n                chunk_packed_length = chunk_size;\n                second_stage_compressor_table[i] = kHapCompressorNone;\n            }\n            else\n            {\n                // ie we used snappy and saved some space\n                second_stage_compressor_table[i] = kHapCompressorSnappy;\n            }\n            hap_write_4_byte_uint(((uint8_t *)chunk_size_table) + (i * 4), chunk_packed_length);\n            compressed_data += chunk_packed_length;\n            top_section_length += chunk_packed_length;\n            compress_buffer_remaining -= chunk_packed_length;\n        }\n\n        if (top_section_length < inputBufferBytes + top_section_header_length)\n        {\n            // use the complex storage because snappy compression saved space\n            storedCompressor = kHapCompressorComplex;\n        }\n        else\n        {\n            // Signal to store the frame uncompressed\n            compressor = HapCompressorNone;\n        }\n    }\n\n    if (compressor == HapCompressorNone)\n    {\n        memcpy(((uint8_t *)outputBuffer) + top_section_header_length, inputBuffer, inputBufferBytes);\n        top_section_length = inputBufferBytes;\n        storedCompressor = kHapCompressorNone;\n    }\n    \n    storedFormat = hap_texture_format_identifier_for_format_constant(textureFormat);\n    \n    hap_write_section_header(outputBuffer, top_section_header_length, top_section_length, hap_4_bit_packed_byte(storedCompressor, storedFormat));\n\n    *outputBufferBytesUsed = top_section_length + top_section_header_length;\n\n    return HapResult_No_Error;\n}\n\nunsigned int HapEncode(unsigned int count,\n                       const void **inputBuffers, unsigned long *inputBuffersBytes,\n                       unsigned int *textureFormats,\n                       unsigned int *compressors,\n                       unsigned int *chunkCounts,\n                       void *outputBuffer, unsigned long outputBufferBytes,\n                       unsigned long *outputBufferBytesUsed)\n{\n    size_t top_section_header_length;\n    size_t top_section_length;\n    unsigned long section_length;\n\n    if (count == 0 || count > 2 // A frame must contain one or two textures\n        || inputBuffers == NULL\n        || inputBuffersBytes == NULL\n        || textureFormats == NULL\n        || compressors == NULL\n        || chunkCounts == NULL\n        || outputBuffer == NULL\n        || outputBufferBytes == 0\n        || outputBufferBytesUsed == NULL)\n    {\n        return HapResult_Bad_Arguments;\n    }\n\n    for (int i = 0; i < count; i++)\n    {\n        if (chunkCounts[i] == 0)\n        {\n            return HapResult_Bad_Arguments;\n        }\n    }\n\n    if (count == 1)\n    {\n        // Encode without the multi-image layout\n        return hap_encode_texture(inputBuffers[0],\n                                  inputBuffersBytes[0],\n                                  textureFormats[0],\n                                  compressors[0],\n                                  chunkCounts[0],\n                                  outputBuffer,\n                                  outputBufferBytes,\n                                  outputBufferBytesUsed);\n    }\n    else if ((textureFormats[0] != HapTextureFormat_YCoCg_DXT5 && textureFormats[1] != HapTextureFormat_YCoCg_DXT5)\n             && (textureFormats[0] != HapTextureFormat_A_RGTC1 && textureFormats[1] != HapTextureFormat_A_RGTC1))\n    {\n        /*\n         Permitted combinations:\n         HapTextureFormat_YCoCg_DXT5 + HapTextureFormat_A_RGTC1\n         */\n        return HapResult_Bad_Arguments;\n    }\n    else\n    {\n        // Calculate the worst-case size for the top section and choose a header-length based on that\n        top_section_length = 0;\n        for (int i = 0; i < count; i++)\n        {\n            top_section_length += inputBuffersBytes[i] + hap_decode_instructions_length(chunkCounts[i]) + 4;\n        }\n\n        if (top_section_length > kHapUInt24Max)\n        {\n            top_section_header_length = 8U;\n        }\n        else\n        {\n            top_section_header_length = 4U;\n        }\n\n        // Encode each texture\n        top_section_length = 0;\n        for (int i = 0; i < count; i++)\n        {\n            void *section = ((uint8_t *)outputBuffer) + top_section_header_length + top_section_length;\n            unsigned int result = hap_encode_texture(inputBuffers[i],\n                                                     inputBuffersBytes[i],\n                                                     textureFormats[i],\n                                                     compressors[i],\n                                                     chunkCounts[i],\n                                                     section,\n                                                     outputBufferBytes - (top_section_header_length + top_section_length),\n                                                     &section_length);\n            if (result != HapResult_No_Error)\n            {\n                return result;\n            }\n            top_section_length += section_length;\n        }\n\n        hap_write_section_header(outputBuffer, top_section_header_length, top_section_length, kHapSectionMultipleImages);\n\n        *outputBufferBytesUsed = top_section_length + top_section_header_length;\n\n        return HapResult_No_Error;\n    }\n}\n\nstatic void hap_decode_chunk(HapChunkDecodeInfo chunks[], unsigned int index)\n{\n    if (chunks)\n    {\n        if (chunks[index].compressor == kHapCompressorSnappy)\n        {\n            snappy_status snappy_result = snappy_uncompress(chunks[index].compressed_chunk_data,\n                                                            chunks[index].compressed_chunk_size,\n                                                            chunks[index].uncompressed_chunk_data,\n                                                            &chunks[index].uncompressed_chunk_size);\n\n            switch (snappy_result)\n            {\n                case SNAPPY_INVALID_INPUT:\n                    chunks[index].result = HapResult_Bad_Frame;\n                    break;\n                case SNAPPY_OK:\n                    chunks[index].result = HapResult_No_Error;\n                    break;\n                default:\n                    chunks[index].result = HapResult_Internal_Error;\n                    break;\n            }\n        }\n        else if (chunks[index].compressor == kHapCompressorNone)\n        {\n            memcpy(chunks[index].uncompressed_chunk_data,\n                   chunks[index].compressed_chunk_data,\n                   chunks[index].compressed_chunk_size);\n            chunks[index].result = HapResult_No_Error;\n        }\n        else\n        {\n            chunks[index].result = HapResult_Bad_Frame;\n        }\n    }\n}\n\nstatic unsigned int hap_decode_header_complex_instructions(const void *texture_section, uint32_t texture_section_length, int * chunk_count,\n                                                   const void **compressors, const void **chunk_sizes, const void **chunk_offsets, const char **frame_data){\n    int result = HapResult_No_Error;\n    const void *section_start;\n    uint32_t section_header_length;\n    uint32_t section_length;\n    unsigned int section_type;\n    size_t bytes_remaining = 0;\n\n    *compressors = NULL;\n    *chunk_sizes = NULL;\n    *chunk_offsets = NULL;\n\n    result = hap_read_section_header(texture_section, texture_section_length, &section_header_length, &section_length, &section_type);\n\n    if (result == HapResult_No_Error && section_type != kHapSectionDecodeInstructionsContainer)\n    {\n        result = HapResult_Bad_Frame;\n    }\n\n    if (result != HapResult_No_Error)\n    {\n        return result;\n    }\n\n    /*\n     Frame data follows immediately after the Decode Instructions Container\n     */\n    *frame_data = ((const char *)texture_section) + section_header_length + section_length;\n\n    /*\n     Step through the sections inside the Decode Instructions Container\n     */\n    section_start = ((uint8_t *)texture_section) + section_header_length;\n    bytes_remaining = section_length;\n\n    while (bytes_remaining > 0) {\n        unsigned int section_chunk_count = 0;\n        result = hap_read_section_header(section_start, bytes_remaining, &section_header_length, &section_length, &section_type);\n        if (result != HapResult_No_Error)\n        {\n            return result;\n        }\n        section_start = ((uint8_t *)section_start) + section_header_length;\n        switch (section_type) {\n            case kHapSectionChunkSecondStageCompressorTable:\n                *compressors = section_start;\n                section_chunk_count = section_length;\n                break;\n            case kHapSectionChunkSizeTable:\n                *chunk_sizes = section_start;\n                section_chunk_count = section_length / 4;\n                break;\n            case kHapSectionChunkOffsetTable:\n                *chunk_offsets = section_start;\n                section_chunk_count = section_length / 4;\n                break;\n            default:\n                // Ignore unrecognized sections\n                break;\n        }\n\n        /*\n         If we calculated a chunk count and already have one, make sure they match\n         */\n        if (section_chunk_count != 0)\n        {\n            if ((*chunk_count) != 0 && section_chunk_count != (*chunk_count))\n            {\n                return HapResult_Bad_Frame;\n            }\n            *chunk_count = section_chunk_count;\n        }\n\n        section_start = ((uint8_t *)section_start) + section_length;\n        bytes_remaining -= section_header_length + section_length;\n    }\n\n    /*\n     The Chunk Second-Stage Compressor Table and Chunk Size Table are required\n     */\n    if (*compressors == NULL || *chunk_sizes == NULL)\n    {\n        return HapResult_Bad_Frame;\n    }\n    return result;\n}\n\nunsigned int hap_decode_single_texture(const void *texture_section, uint32_t texture_section_length,\n                                       unsigned int texture_section_type,\n                                       HapDecodeCallback callback, void *info,\n                                       void *outputBuffer, unsigned long outputBufferBytes,\n                                       unsigned long *outputBufferBytesUsed,\n                                       unsigned int *outputBufferTextureFormat)\n{\n    int result = HapResult_No_Error;\n    unsigned int textureFormat;\n    unsigned int compressor;\n    size_t bytesUsed = 0;\n\n    /*\n     One top-level section type describes texture-format and second-stage compression\n     Hap compressor/format constants can be unpacked by reading the top and bottom four bits.\n     */\n    compressor = hap_top_4_bits(texture_section_type);\n    textureFormat = hap_bottom_4_bits(texture_section_type);\n\n    /*\n     Pass the texture format out\n     */\n    *outputBufferTextureFormat = hap_texture_format_constant_for_format_identifier(textureFormat);\n    if (*outputBufferTextureFormat == 0)\n    {\n        return HapResult_Bad_Frame;\n    }\n\n    if (compressor == kHapCompressorComplex)\n    {\n        /*\n         The top-level section should contain a Decode Instructions Container followed by frame data\n         */\n        int chunk_count = 0;\n        const void *compressors = NULL;\n        const void *chunk_sizes = NULL;\n        const void *chunk_offsets = NULL;\n        const char *frame_data = NULL;\n\n        result = hap_decode_header_complex_instructions(texture_section, texture_section_length, &chunk_count, &compressors, &chunk_sizes, &chunk_offsets, &frame_data);\n\n        if (result != HapResult_No_Error)\n        {\n            return result;\n        }\n\n        if (chunk_count > 0)\n        {\n            /*\n             Step through the chunks, storing information for their decompression\n             */\n            HapChunkDecodeInfo *chunk_info = (HapChunkDecodeInfo *)malloc(sizeof(HapChunkDecodeInfo) * chunk_count);\n\n            size_t running_compressed_chunk_size = 0;\n            size_t running_uncompressed_chunk_size = 0;\n            int i;\n\n            if (chunk_info == NULL)\n            {\n                return HapResult_Internal_Error;\n            }\n\n            for (i = 0; i < chunk_count; i++) {\n\n                chunk_info[i].compressor = *(((uint8_t *)compressors) + i);\n\n                chunk_info[i].compressed_chunk_size = hap_read_4_byte_uint(((uint8_t *)chunk_sizes) + (i * 4));\n\n                if (chunk_offsets)\n                {\n                    chunk_info[i].compressed_chunk_data = frame_data + hap_read_4_byte_uint(((uint8_t *)chunk_offsets) + (i * 4));\n                }\n                else\n                {\n                    chunk_info[i].compressed_chunk_data = frame_data + running_compressed_chunk_size;\n                }\n\n                running_compressed_chunk_size += chunk_info[i].compressed_chunk_size;\n\n                if (chunk_info[i].compressor == kHapCompressorSnappy)\n                {\n                    snappy_status snappy_result = snappy_uncompressed_length(chunk_info[i].compressed_chunk_data,\n                        chunk_info[i].compressed_chunk_size,\n                        &(chunk_info[i].uncompressed_chunk_size));\n\n                    if (snappy_result != SNAPPY_OK)\n                    {\n                        switch (snappy_result)\n                        {\n                        case SNAPPY_INVALID_INPUT:\n                            result = HapResult_Bad_Frame;\n                            break;\n                        default:\n                            result = HapResult_Internal_Error;\n                            break;\n                        }\n                        break;\n                    }\n                }\n                else\n                {\n                    chunk_info[i].uncompressed_chunk_size = chunk_info[i].compressed_chunk_size;\n                }\n\n                chunk_info[i].uncompressed_chunk_data = (char *)(((uint8_t *)outputBuffer) + running_uncompressed_chunk_size);\n                running_uncompressed_chunk_size += chunk_info[i].uncompressed_chunk_size;\n            }\n\n            if (result == HapResult_No_Error && running_uncompressed_chunk_size > outputBufferBytes)\n            {\n                result = HapResult_Buffer_Too_Small;\n            }\n\n            if (result == HapResult_No_Error)\n            {\n                /*\n                 Perform decompression\n                 */\n                bytesUsed = running_uncompressed_chunk_size;\n\n                if (chunk_count == 1)\n                {\n                    /*\n                     We don't invoke the callback for one chunk, just decode it directly\n                     */\n                    hap_decode_chunk(chunk_info, 0);\n                }\n                else\n                {\n                    callback((HapDecodeWorkFunction)hap_decode_chunk, chunk_info, chunk_count, info);\n                }\n\n                /*\n                 Check to see if we encountered any errors and report one of them\n                 */\n                for (i = 0; i < chunk_count; i++)\n                {\n                    if (chunk_info[i].result != HapResult_No_Error)\n                    {\n                        result = chunk_info[i].result;\n                        break;\n                    }\n                }\n            }\n\n            free(chunk_info);\n\n            if (result != HapResult_No_Error)\n            {\n                return result;\n            }\n        }\n    }\n    else if (compressor == kHapCompressorSnappy)\n    {\n        /*\n         Only one section is present containing a single block of snappy-compressed texture data\n         */\n        snappy_status snappy_result = snappy_uncompressed_length((const char *)texture_section, texture_section_length, &bytesUsed);\n        if (snappy_result != SNAPPY_OK)\n        {\n            return HapResult_Internal_Error;\n        }\n        if (bytesUsed > outputBufferBytes)\n        {\n            return HapResult_Buffer_Too_Small;\n        }\n        snappy_result = snappy_uncompress((const char *)texture_section, texture_section_length, (char *)outputBuffer, &bytesUsed);\n        if (snappy_result != SNAPPY_OK)\n        {\n            return HapResult_Internal_Error;\n        }\n    }\n    else if (compressor == kHapCompressorNone)\n    {\n        /*\n         Only one section is present containing a single block of uncompressed texture data\n         */\n        bytesUsed = texture_section_length;\n        if (texture_section_length > outputBufferBytes)\n        {\n            return HapResult_Buffer_Too_Small;\n        }\n        memcpy(outputBuffer, texture_section, texture_section_length);\n    }\n    else\n    {\n        return HapResult_Bad_Frame;\n    }\n    /*\n     Fill out the remaining return value\n     */\n    if (outputBufferBytesUsed != NULL)\n    {\n        *outputBufferBytesUsed = bytesUsed;\n    }\n    \n    return HapResult_No_Error;\n}\n\nint hap_get_section_at_index(const void *input_buffer, uint32_t input_buffer_bytes,\n                             unsigned int index,\n                             const void **section, uint32_t *section_length, unsigned int *section_type)\n{\n    int result;\n    uint32_t section_header_length;\n\n    result = hap_read_section_header(input_buffer, input_buffer_bytes, &section_header_length, section_length, section_type);\n\n    if (result != HapResult_No_Error)\n    {\n        return result;\n    }\n\n    if (*section_type == kHapSectionMultipleImages)\n    {\n        /*\n         Step through until we find the section at index\n         */\n        size_t offset = 0;\n        size_t top_section_length = *section_length;\n        input_buffer = ((uint8_t *)input_buffer) + section_header_length;\n        section_header_length = 0;\n        *section_length = 0;\n        for (int i = 0; i <= index; i++) {\n            offset += section_header_length + *section_length;\n            if (offset >= top_section_length)\n            {\n                return HapResult_Bad_Arguments;\n            }\n            result = hap_read_section_header(((uint8_t *)input_buffer) + offset,\n                                             top_section_length - offset,\n                                             &section_header_length,\n                                             section_length,\n                                             section_type);\n            if (result != HapResult_No_Error)\n            {\n                return result;\n            }\n        }\n        offset += section_header_length;\n        *section = ((uint8_t *)input_buffer) + offset;\n        return HapResult_No_Error;\n    }\n    else if (index == 0)\n    {\n        /*\n         A single-texture frame with the texture as the top section.\n         */\n        *section = ((uint8_t *)input_buffer) + section_header_length;\n        return HapResult_No_Error;\n    }\n    else\n    {\n        *section = NULL;\n        *section_length = 0;\n        *section_type = 0;\n        return HapResult_Bad_Arguments;\n    }\n}\n\nunsigned int HapDecode(const void *inputBuffer, unsigned long inputBufferBytes,\n                       unsigned int index,\n                       HapDecodeCallback callback, void *info,\n                       void *outputBuffer, unsigned long outputBufferBytes,\n                       unsigned long *outputBufferBytesUsed,\n                       unsigned int *outputBufferTextureFormat)\n{\n    int result = HapResult_No_Error;\n    const void *section;\n    uint32_t section_length;\n    unsigned int section_type;\n\n    /*\n     Check arguments\n     */\n    if (inputBuffer == NULL\n        || index > 1\n        || callback == NULL\n        || outputBuffer == NULL\n        || outputBufferTextureFormat == NULL\n        )\n    {\n        return HapResult_Bad_Arguments;\n    }\n\n    /*\n     Locate the section at the given index, which will either be the top-level section in a single texture image, or one of the\n     sections inside a multi-image top-level section.\n     */\n    result = hap_get_section_at_index(inputBuffer, inputBufferBytes, index, &section, &section_length, &section_type);\n\n    if (result == HapResult_No_Error)\n    {\n        /*\n         Decode the located texture\n         */\n        result = hap_decode_single_texture(section,\n                                           section_length,\n                                           section_type,\n                                           callback, info,\n                                           outputBuffer,\n                                           outputBufferBytes,\n                                           outputBufferBytesUsed,\n                                           outputBufferTextureFormat);\n    }\n\n    return result;\n}\n\nunsigned int HapGetFrameTextureCount(const void *inputBuffer, unsigned long inputBufferBytes, unsigned int *outputTextureCount)\n{\n    int result;\n    uint32_t section_header_length;\n    uint32_t section_length;\n    unsigned int section_type;\n\n    result = hap_read_section_header(inputBuffer, inputBufferBytes, &section_header_length, &section_length, &section_type);\n\n    if (result != HapResult_No_Error)\n    {\n        return result;\n    }\n\n    if (section_type == kHapSectionMultipleImages)\n    {\n        /*\n         Step through, counting sections\n         */\n        uint32_t offset = section_header_length;\n        uint32_t top_section_length = section_length;\n        *outputTextureCount = 0;\n        while (offset < top_section_length) {\n            result = hap_read_section_header(((uint8_t *)inputBuffer) + offset,\n                                             inputBufferBytes - offset,\n                                             &section_header_length,\n                                             &section_length,\n                                             &section_type);\n            if (result != HapResult_No_Error)\n            {\n                return result;\n            }\n            offset += section_header_length + section_length;\n            *outputTextureCount += 1;\n        }\n        return HapResult_No_Error;\n    }\n    else\n    {\n        /*\n         A single-texture frame with the texture as the top section.\n         */\n        *outputTextureCount = 1;\n        return HapResult_No_Error;\n    }\n}\n\nunsigned int HapGetFrameTextureFormat(const void *inputBuffer, unsigned long inputBufferBytes, unsigned int index, unsigned int *outputBufferTextureFormat)\n{\n    unsigned int result = HapResult_No_Error;\n    const void *section;\n    uint32_t section_length;\n    unsigned int section_type;\n    /*\n     Check arguments\n     */\n    if (inputBuffer == NULL\n        || index > 1\n        || outputBufferTextureFormat == NULL\n        )\n    {\n        return HapResult_Bad_Arguments;\n    }\n    /*\n     Locate the section at the given index, which will either be the top-level section in a single texture image, or one of the\n     sections inside a multi-image top-level section.\n     */\n    result = hap_get_section_at_index(inputBuffer, inputBufferBytes, index, &section, &section_length, &section_type);\n\n    if (result == HapResult_No_Error)\n    {\n        /*\n         Pass the API enum value to match the constant out\n         */\n        *outputBufferTextureFormat = hap_texture_format_constant_for_format_identifier(hap_bottom_4_bits(section_type));\n        /*\n         Check a valid format was present\n         */\n        if (*outputBufferTextureFormat == 0)\n        {\n            result = HapResult_Bad_Frame;\n        }\n    }\n    return result;\n}\n\nunsigned int HapGetFrameTextureChunkCount(const void *inputBuffer, unsigned long inputBufferBytes, unsigned int index, int *chunk_count)\n{\n    unsigned int result = HapResult_No_Error;\n    const void *section;\n    uint32_t section_length;\n    unsigned int section_type;\n    *chunk_count = 0;\n\n    /*\n     Check arguments\n     */\n    if (inputBuffer == NULL\n        || index > 1\n        )\n    {\n        return HapResult_Bad_Arguments;\n    }\n    /*\n     Locate the section at the given index, which will either be the top-level section in a single texture image, or one of the\n     sections inside a multi-image top-level section.\n     */\n    result = hap_get_section_at_index(inputBuffer, inputBufferBytes, index, &section, &section_length, &section_type);\n\n    if (result == HapResult_No_Error)\n    {\n        unsigned int compressor;\n\n        /*\n         One top-level section type describes texture-format and second-stage compression\n         Hap compressor/format constants can be unpacked by reading the top and bottom four bits.\n         */\n        compressor = hap_top_4_bits(section_type);\n\n        if (compressor == kHapCompressorComplex)\n        {\n            /*\n             The top-level section should contain a Decode Instructions Container followed by frame data\n             */\n            const void *compressors = NULL;\n            const void *chunk_sizes = NULL;\n            const void *chunk_offsets = NULL;\n            const char *frame_data = NULL;\n\n            result = hap_decode_header_complex_instructions(section, section_length, chunk_count, &compressors, &chunk_sizes, &chunk_offsets, &frame_data);\n\n            if (result != HapResult_No_Error)\n            {\n                return result;\n            }\n        }\n        else if ((compressor == kHapCompressorSnappy)||(compressor == kHapCompressorNone))\n        {\n            *chunk_count = 1;\n        }\n        else\n        {\n            return HapResult_Bad_Frame;\n        }\n    }\n    return result;\n}\n"
  },
  {
    "path": "Plugin/Hap/hap.h",
    "content": "/*\n hap.h\n \n Copyright (c) 2011-2013, Tom Butterworth and Vidvox LLC. All rights reserved.\n \n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are met:\n \n * Redistributions of source code must retain the above copyright\n notice, this list of conditions and the following disclaimer.\n \n * Redistributions in binary form must reproduce the above copyright\n notice, this list of conditions and the following disclaimer in the\n documentation and/or other materials provided with the distribution.\n \n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY\n DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef hap_h\n#define hap_h\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*\n These match the constants defined by GL_EXT_texture_compression_s3tc,\n GL_ARB_texture_compression_rgtc and GL_ARB_texture_compression_bptc\n */\n\nenum HapTextureFormat {\n    HapTextureFormat_RGB_DXT1 = 0x83F0,\n    HapTextureFormat_RGBA_DXT5 = 0x83F3,\n    HapTextureFormat_YCoCg_DXT5 = 0x01,\n    HapTextureFormat_A_RGTC1 = 0x8DBB,\n    HapTextureFormat_RGBA_BPTC_UNORM = 0x8E8C,\n    HapTextureFormat_RGB_BPTC_UNSIGNED_FLOAT = 0x8E8F,\n    HapTextureFormat_RGB_BPTC_SIGNED_FLOAT = 0x8E8E,\n};\n\nenum HapCompressor {\n    HapCompressorNone,\n    HapCompressorSnappy\n};\n\nenum HapResult {\n    HapResult_No_Error = 0,\n    HapResult_Bad_Arguments,\n    HapResult_Buffer_Too_Small,\n    HapResult_Bad_Frame,\n    HapResult_Internal_Error\n};\n\n/*\n See HapDecode for descriptions of these function types.\n */\ntypedef void (*HapDecodeWorkFunction)(void *p, unsigned int index);\ntypedef void (*HapDecodeCallback)(HapDecodeWorkFunction function, void *p, unsigned int count, void *info);\n\n/*\n Returns the maximum size of an output buffer for a frame composed of one or more textures, or returns 0 on error.\n count is the number of textures (1 or 2) and matches the number of values in the array arguments\n lengths is an array of input texture lengths in bytes\n textureFormats is an array of HapTextureFormats\n chunkCounts is an array of chunk counts (1 or more)\n */\nunsigned long HapMaxEncodedLength(unsigned int count,\n                                  unsigned long *lengths,\n                                  unsigned int *textureFormats,\n                                  unsigned int *chunkCounts);\n\n/*\n Encodes one or multiple textures into one Hap frame, or returns an error.\n\n Permitted multiple-texture combinations are:\n  HapTextureFormat_YCoCg_DXT5 + HapTextureFormat_A_RGTC1\n\n Use HapMaxEncodedLength() to discover the minimal value for outputBufferBytes.\n count is the number of textures (1 or 2) and matches the number of values in the array arguments\n inputBuffers is an array of count pointers to texture data\n inputBufferBytes is an array of texture data lengths in bytes\n textureFormats is an array of HapTextureFormats\n compressors is an array of HapCompressors\n chunkCounts is an array of chunk counts to permit multithreaded decoding (1 or more)\n outputBuffer is the destination buffer to receive the encoded frame\n outputBufferBytes is the destination buffer's length in bytes\n outputBufferBytesUsed will be set to the actual encoded length of the frame on return\n*/\nunsigned int HapEncode(unsigned int count,\n                       const void **inputBuffers, unsigned long *inputBuffersBytes,\n                       unsigned int *textureFormats,\n                       unsigned int *compressors,\n                       unsigned int *chunkCounts,\n                       void *outputBuffer, unsigned long outputBufferBytes,\n                       unsigned long *outputBufferBytesUsed);\n\n/*\n Decodes a texture from inputBuffer which is a Hap frame.\n\n A frame may contain multiple textures which are to be combined to create the final image. Use HapGetFrameTextureCount()\n to discover the number of textures in a frame, and then access each texture by incrementing the index argument to this\n function.\n\n If the frame permits multithreaded decoding, callback will be called once for you to invoke a platform-appropriate\n mechanism to assign work to threads, and trigger that work by calling the function passed to your callback the number\n of times indicated by the count argument, usually from a number of different threads. This callback must not return\n until all the work has been completed.\n\n void MyHapDecodeCallback(HapDecodeWorkFunction function, void *p, unsigned int count, void *info)\n {\n     int i;\n     for (i = 0; i < count; i++) {\n         // Invoke your multithreading mechanism to cause this function to be called\n         // on a suitable number of threads.\n         function(p, i);\n     }\n }\n info is an argument for your own use to pass context to the callback.\n If the frame does not permit multithreaded decoding, callback will not be called.\n If outputBufferBytesUsed is not NULL then it will be set to the decoded length of the output buffer.\n outputBufferTextureFormat must be non-NULL, and will be set to one of the HapTextureFormat constants.\n */\nunsigned int HapDecode(const void *inputBuffer, unsigned long inputBufferBytes,\n                       unsigned int index,\n                       HapDecodeCallback callback, void *info,\n                       void *outputBuffer, unsigned long outputBufferBytes,\n                       unsigned long *outputBufferBytesUsed,\n                       unsigned int *outputBufferTextureFormat);\n\n/*\n If this returns HapResult_No_Error then outputTextureCount is set to the count of textures in the frame.\n */\nunsigned int HapGetFrameTextureCount(const void *inputBuffer, unsigned long inputBufferBytes, unsigned int *outputTextureCount);\n\n/*\n On return sets outputBufferTextureFormat to a HapTextureFormat constant describing the format of the texture at index in the frame.\n */\nunsigned int HapGetFrameTextureFormat(const void *inputBuffer, unsigned long inputBufferBytes, unsigned int index, unsigned int *outputBufferTextureFormat);\n\n/*\n On return sets chunk_count to the chunk count value of the texture at index in the frame.\n*/\nunsigned int HapGetFrameTextureChunkCount(const void *inputBuffer, unsigned long inputBufferBytes, unsigned int index, int *chunk_count);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "Plugin/MP4/mp4defs.h",
    "content": "/** 25.09.2018 @file\n*\n*   Common MP4 definitions\n*\n*   Acronyms:\n*       AVC = Advanced Video Coding (AKA H.264)\n*       AAC = Advanced Audio Coding\n*       OD  = Object descriptor\n*       DSI = Decoder Specific Info (AAC element)\n*       LC  = Low Complexity (AAC profile)\n*       SPS = Sequence Parameter Set (H.264 element)\n*       PPS = Picture Parameter Set (H.264 element)\n*\n*   The MP4 file has several tracks. Each track contains a number of 'samples'\n*   (audio or video frames). Position and size of each sample in the track\n*   encoded in the track index.\n*\n*/\n\n#ifndef mp4defs_H_INCLUDED\n#define mp4defs_H_INCLUDED\n\n/************************************************************************/\n/*          Some values of MP4X_track_t::object_type_indication         */\n/************************************************************************/\nenum\n{\n    // MPEG-4 AAC (all profiles)\n    MP4_OBJECT_TYPE_AUDIO_ISO_IEC_14496_3 = 0x40,\n\n    // MPEG-2 AAC, Main profile\n    MP4_OBJECT_TYPE_AUDIO_ISO_IEC_13818_7_MAIN_PROFILE = 0x66,\n\n    // MPEG-2 AAC, LC profile\n    MP4_OBJECT_TYPE_AUDIO_ISO_IEC_13818_7_LC_PROFILE = 0x67,\n\n    // MPEG-2 AAC, SSR profile\n    MP4_OBJECT_TYPE_AUDIO_ISO_IEC_13818_7_SSR_PROFILE = 0x68,\n\n    // H.264 (AVC) video \n    MP4_OBJECT_TYPE_AVC = 0x21,\n\n    // http://www.mp4ra.org/object.html 0xC0-E0  && 0xE2 - 0xFE are specified as \"user private\"\n    MP4_OBJECT_TYPE_USER_PRIVATE = 0xC0\n};\n\n\n/************************************************************************/\n/*          Some values of MP4X_track_t::handler_type                   */\n/************************************************************************/\nenum\n{\n    // Video track : 'vide'\n    MP4_HANDLER_TYPE_VIDE = 0x76696465,\n    // Audio track : 'soun'\n    MP4_HANDLER_TYPE_SOUN = 0x736F756E,\n    // General MPEG-4 systems streams (without specific handler). \n    // Used for private stream, as suggested in http://www.mp4ra.org/handler.html\n    MP4_HANDLER_TYPE_GESM = 0x6765736D,\n    // Text comment track\n    MP4_HANDLER_TYPE_MDIR = 0x6d646972\n};\n\n/************************************************************************/\n/*      Complete box list (most of them not used here)                  */\n/************************************************************************/\n#define FOUR_CHAR_INT( a, b, c, d ) (((((((unsigned)(a)<<8)|(b))<<8)|(c))<<8)|(d))\nenum\n{\n    BOX_co64    = FOUR_CHAR_INT( 'c', 'o', '6', '4' ),//ChunkLargeOffsetAtomType\n    BOX_stco    = FOUR_CHAR_INT( 's', 't', 'c', 'o' ),//ChunkOffsetAtomType\n    BOX_crhd    = FOUR_CHAR_INT( 'c', 'r', 'h', 'd' ),//ClockReferenceMediaHeaderAtomType\n    BOX_ctts    = FOUR_CHAR_INT( 'c', 't', 't', 's' ),//CompositionOffsetAtomType\n    BOX_cprt    = FOUR_CHAR_INT( 'c', 'p', 'r', 't' ),//CopyrightAtomType\n    BOX_url_    = FOUR_CHAR_INT( 'u', 'r', 'l', ' ' ),//DataEntryURLAtomType\n    BOX_urn_    = FOUR_CHAR_INT( 'u', 'r', 'n', ' ' ),//DataEntryURNAtomType\n    BOX_dinf    = FOUR_CHAR_INT( 'd', 'i', 'n', 'f' ),//DataInformationAtomType\n    BOX_dref    = FOUR_CHAR_INT( 'd', 'r', 'e', 'f' ),//DataReferenceAtomType\n    BOX_stdp    = FOUR_CHAR_INT( 's', 't', 'd', 'p' ),//DegradationPriorityAtomType\n    BOX_edts    = FOUR_CHAR_INT( 'e', 'd', 't', 's' ),//EditAtomType\n    BOX_elst    = FOUR_CHAR_INT( 'e', 'l', 's', 't' ),//EditListAtomType\n    BOX_uuid    = FOUR_CHAR_INT( 'u', 'u', 'i', 'd' ),//ExtendedAtomType\n    BOX_free    = FOUR_CHAR_INT( 'f', 'r', 'e', 'e' ),//FreeSpaceAtomType\n    BOX_hdlr    = FOUR_CHAR_INT( 'h', 'd', 'l', 'r' ),//HandlerAtomType\n    BOX_hmhd    = FOUR_CHAR_INT( 'h', 'm', 'h', 'd' ),//HintMediaHeaderAtomType\n    BOX_hint    = FOUR_CHAR_INT( 'h', 'i', 'n', 't' ),//HintTrackReferenceAtomType\n    BOX_mdia    = FOUR_CHAR_INT( 'm', 'd', 'i', 'a' ),//MediaAtomType\n    BOX_mdat    = FOUR_CHAR_INT( 'm', 'd', 'a', 't' ),//MediaDataAtomType\n    BOX_mdhd    = FOUR_CHAR_INT( 'm', 'd', 'h', 'd' ),//MediaHeaderAtomType\n    BOX_minf    = FOUR_CHAR_INT( 'm', 'i', 'n', 'f' ),//MediaInformationAtomType\n    BOX_moov    = FOUR_CHAR_INT( 'm', 'o', 'o', 'v' ),//MovieAtomType\n    BOX_mvhd    = FOUR_CHAR_INT( 'm', 'v', 'h', 'd' ),//MovieHeaderAtomType\n    BOX_stsd    = FOUR_CHAR_INT( 's', 't', 's', 'd' ),//SampleDescriptionAtomType\n    BOX_stsz    = FOUR_CHAR_INT( 's', 't', 's', 'z' ),//SampleSizeAtomType\n    BOX_stz2    = FOUR_CHAR_INT( 's', 't', 'z', '2' ),//CompactSampleSizeAtomType\n    BOX_stbl    = FOUR_CHAR_INT( 's', 't', 'b', 'l' ),//SampleTableAtomType\n    BOX_stsc    = FOUR_CHAR_INT( 's', 't', 's', 'c' ),//SampleToChunkAtomType\n    BOX_stsh    = FOUR_CHAR_INT( 's', 't', 's', 'h' ),//ShadowSyncAtomType\n    BOX_skip    = FOUR_CHAR_INT( 's', 'k', 'i', 'p' ),//SkipAtomType\n    BOX_smhd    = FOUR_CHAR_INT( 's', 'm', 'h', 'd' ),//SoundMediaHeaderAtomType\n    BOX_stss    = FOUR_CHAR_INT( 's', 't', 's', 's' ),//SyncSampleAtomType\n    BOX_stts    = FOUR_CHAR_INT( 's', 't', 't', 's' ),//TimeToSampleAtomType\n    BOX_trak    = FOUR_CHAR_INT( 't', 'r', 'a', 'k' ),//TrackAtomType\n    BOX_tkhd    = FOUR_CHAR_INT( 't', 'k', 'h', 'd' ),//TrackHeaderAtomType\n    BOX_tref    = FOUR_CHAR_INT( 't', 'r', 'e', 'f' ),//TrackReferenceAtomType\n    BOX_udta    = FOUR_CHAR_INT( 'u', 'd', 't', 'a' ),//UserDataAtomType\n    BOX_vmhd    = FOUR_CHAR_INT( 'v', 'm', 'h', 'd' ),//VideoMediaHeaderAtomType\n    BOX_url     = FOUR_CHAR_INT( 'u', 'r', 'l', ' ' ),\n    BOX_urn     = FOUR_CHAR_INT( 'u', 'r', 'n', ' ' ),\n\n    BOX_gnrv    = FOUR_CHAR_INT( 'g', 'n', 'r', 'v' ),//GenericVisualSampleEntryAtomType\n    BOX_gnra    = FOUR_CHAR_INT( 'g', 'n', 'r', 'a' ),//GenericAudioSampleEntryAtomType\n\n    //V2 atoms\n    BOX_ftyp    = FOUR_CHAR_INT( 'f', 't', 'y', 'p' ),//FileTypeAtomType\n    BOX_padb    = FOUR_CHAR_INT( 'p', 'a', 'd', 'b' ),//PaddingBitsAtomType\n\n    //MP4 Atoms\n    BOX_sdhd    = FOUR_CHAR_INT( 's', 'd', 'h', 'd' ),//SceneDescriptionMediaHeaderAtomType\n    BOX_dpnd    = FOUR_CHAR_INT( 'd', 'p', 'n', 'd' ),//StreamDependenceAtomType\n    BOX_iods    = FOUR_CHAR_INT( 'i', 'o', 'd', 's' ),//ObjectDescriptorAtomType\n    BOX_odhd    = FOUR_CHAR_INT( 'o', 'd', 'h', 'd' ),//ObjectDescriptorMediaHeaderAtomType\n    BOX_mpod    = FOUR_CHAR_INT( 'm', 'p', 'o', 'd' ),//ODTrackReferenceAtomType\n    BOX_nmhd    = FOUR_CHAR_INT( 'n', 'm', 'h', 'd' ),//MPEGMediaHeaderAtomType\n    BOX_esds    = FOUR_CHAR_INT( 'e', 's', 'd', 's' ),//ESDAtomType\n    BOX_sync    = FOUR_CHAR_INT( 's', 'y', 'n', 'c' ),//OCRReferenceAtomType\n    BOX_ipir    = FOUR_CHAR_INT( 'i', 'p', 'i', 'r' ),//IPIReferenceAtomType\n    BOX_mp4s    = FOUR_CHAR_INT( 'm', 'p', '4', 's' ),//MPEGSampleEntryAtomType\n    BOX_mp4a    = FOUR_CHAR_INT( 'm', 'p', '4', 'a' ),//MPEGAudioSampleEntryAtomType\n    BOX_mp4v    = FOUR_CHAR_INT( 'm', 'p', '4', 'v' ),//MPEGVisualSampleEntryAtomType\n\n    // http://www.itscj.ipsj.or.jp/sc29/open/29view/29n7644t.doc\n    BOX_avc1    = FOUR_CHAR_INT( 'a', 'v', 'c', '1' ),\n    BOX_avc2    = FOUR_CHAR_INT( 'a', 'v', 'c', '2' ),\n    BOX_svc1    = FOUR_CHAR_INT( 's', 'v', 'c', '1' ),\n    BOX_avcC    = FOUR_CHAR_INT( 'a', 'v', 'c', 'C' ),\n    BOX_svcC    = FOUR_CHAR_INT( 's', 'v', 'c', 'C' ),\n    BOX_btrt    = FOUR_CHAR_INT( 'b', 't', 'r', 't' ),\n    BOX_m4ds    = FOUR_CHAR_INT( 'm', '4', 'd', 's' ),\n    BOX_seib    = FOUR_CHAR_INT( 's', 'e', 'i', 'b' ),\n\n    //3GPP atoms\n    BOX_samr    = FOUR_CHAR_INT( 's', 'a', 'm', 'r' ),//AMRSampleEntryAtomType\n    BOX_sawb    = FOUR_CHAR_INT( 's', 'a', 'w', 'b' ),//WB_AMRSampleEntryAtomType\n    BOX_damr    = FOUR_CHAR_INT( 'd', 'a', 'm', 'r' ),//AMRConfigAtomType\n    BOX_s263    = FOUR_CHAR_INT( 's', '2', '6', '3' ),//H263SampleEntryAtomType\n    BOX_d263    = FOUR_CHAR_INT( 'd', '2', '6', '3' ),//H263ConfigAtomType\n\n    //V2 atoms - Movie Fragments\n    BOX_mvex    = FOUR_CHAR_INT( 'm', 'v', 'e', 'x' ),//MovieExtendsAtomType\n    BOX_trex    = FOUR_CHAR_INT( 't', 'r', 'e', 'x' ),//TrackExtendsAtomType\n    BOX_moof    = FOUR_CHAR_INT( 'm', 'o', 'o', 'f' ),//MovieFragmentAtomType\n    BOX_mfhd    = FOUR_CHAR_INT( 'm', 'f', 'h', 'd' ),//MovieFragmentHeaderAtomType\n    BOX_traf    = FOUR_CHAR_INT( 't', 'r', 'a', 'f' ),//TrackFragmentAtomType\n    BOX_tfhd    = FOUR_CHAR_INT( 't', 'f', 'h', 'd' ),//TrackFragmentHeaderAtomType\n    BOX_trun    = FOUR_CHAR_INT( 't', 'r', 'u', 'n' ),//TrackFragmentRunAtomType\n\n    // Object Descriptors (OD) data coding\n    // These takes only 1 byte; this implementation translate <od_tag> to\n    // <od_tag> + OD_BASE to keep API uniform and safe for string functions\n    OD_BASE    = FOUR_CHAR_INT( '$', '$', '$', '0' ),//\n    OD_ESD     = FOUR_CHAR_INT( '$', '$', '$', '3' ),//SDescriptor_Tag\n    OD_DCD     = FOUR_CHAR_INT( '$', '$', '$', '4' ),//DecoderConfigDescriptor_Tag\n    OD_DSI     = FOUR_CHAR_INT( '$', '$', '$', '5' ),//DecoderSpecificInfo_Tag\n    OD_SLC     = FOUR_CHAR_INT( '$', '$', '$', '6' ),//SLConfigDescriptor_Tag\n\n    BOX_meta   = FOUR_CHAR_INT( 'm', 'e', 't', 'a' ),\n    BOX_ilst   = FOUR_CHAR_INT( 'i', 'l', 's', 't' ),\n\n    // Metagata tags, see http://atomicparsley.sourceforge.net/mpeg-4files.html\n    BOX_calb    = FOUR_CHAR_INT( '\\xa9', 'a', 'l', 'b'),    // album\n    BOX_cart    = FOUR_CHAR_INT( '\\xa9', 'a', 'r', 't'),    // artist\n    BOX_aART    = FOUR_CHAR_INT( 'a', 'A', 'R', 'T' ),      // album artist\n    BOX_ccmt    = FOUR_CHAR_INT( '\\xa9', 'c', 'm', 't'),    // comment\n    BOX_cday    = FOUR_CHAR_INT( '\\xa9', 'd', 'a', 'y'),    // year (as string)\n    BOX_cnam    = FOUR_CHAR_INT( '\\xa9', 'n', 'a', 'm'),    // title\n    BOX_cgen    = FOUR_CHAR_INT( '\\xa9', 'g', 'e', 'n'),    // custom genre (as string or as byte!)\n    BOX_trkn    = FOUR_CHAR_INT( 't', 'r', 'k', 'n'),       // track number (byte)\n    BOX_disk    = FOUR_CHAR_INT( 'd', 'i', 's', 'k'),       // disk number (byte)\n    BOX_cwrt    = FOUR_CHAR_INT( '\\xa9', 'w', 'r', 't'),    // composer\n    BOX_ctoo    = FOUR_CHAR_INT( '\\xa9', 't', 'o', 'o'),    // encoder\n    BOX_tmpo    = FOUR_CHAR_INT( 't', 'm', 'p', 'o'),       // bpm (byte)\n    BOX_cpil    = FOUR_CHAR_INT( 'c', 'p', 'i', 'l'),       // compilation (byte)\n    BOX_covr    = FOUR_CHAR_INT( 'c', 'o', 'v', 'r'),       // cover art (JPEG/PNG)\n    BOX_rtng    = FOUR_CHAR_INT( 'r', 't', 'n', 'g'),       // rating/advisory (byte)\n    BOX_cgrp    = FOUR_CHAR_INT( '\\xa9', 'g', 'r', 'p'),    // grouping\n    BOX_stik    = FOUR_CHAR_INT( 's', 't', 'i', 'k'),       // stik (byte)  0 = Movie   1 = Normal  2 = Audiobook  5 = Whacked Bookmark  6 = Music Video  9 = Short Film  10 = TV Show  11 = Booklet  14 = Ringtone\n    BOX_pcst    = FOUR_CHAR_INT( 'p', 'c', 's', 't'),       // podcast (byte)\n    BOX_catg    = FOUR_CHAR_INT( 'c', 'a', 't', 'g'),       // category\n    BOX_keyw    = FOUR_CHAR_INT( 'k', 'e', 'y', 'w'),       // keyword\n    BOX_purl    = FOUR_CHAR_INT( 'p', 'u', 'r', 'l'),       // podcast URL (byte)\n    BOX_egid    = FOUR_CHAR_INT( 'e', 'g', 'i', 'd'),       // episode global unique ID (byte)\n    BOX_desc    = FOUR_CHAR_INT( 'd', 'e', 's', 'c'),       // description\n    BOX_clyr    = FOUR_CHAR_INT( '\\xa9', 'l', 'y', 'r'),    // lyrics (may be > 255 bytes)\n    BOX_tven    = FOUR_CHAR_INT( 't', 'v', 'e', 'n'),       // tv episode number\n    BOX_tves    = FOUR_CHAR_INT( 't', 'v', 'e', 's'),       // tv episode (byte)\n    BOX_tvnn    = FOUR_CHAR_INT( 't', 'v', 'n', 'n'),       // tv network name\n    BOX_tvsh    = FOUR_CHAR_INT( 't', 'v', 's', 'h'),       // tv show name\n    BOX_tvsn    = FOUR_CHAR_INT( 't', 'v', 's', 'n'),       // tv season (byte)\n    BOX_purd    = FOUR_CHAR_INT( 'p', 'u', 'r', 'd'),       // purchase date\n    BOX_pgap    = FOUR_CHAR_INT( 'p', 'g', 'a', 'p'),       // Gapless Playback (byte)\n\n    //BOX_aart   = FOUR_CHAR_INT( 'a', 'a', 'r', 't' ),     // Album artist\n    BOX_cART    = FOUR_CHAR_INT( '\\xa9', 'A', 'R', 'T'),    // artist\n    BOX_gnre    = FOUR_CHAR_INT( 'g', 'n', 'r', 'e'),\n\n    // 3GPP metatags  (http://cpansearch.perl.org/src/JHAR/MP4-Info-1.12/Info.pm)\n    BOX_auth    = FOUR_CHAR_INT( 'a', 'u', 't', 'h'),       // author\n    BOX_titl    = FOUR_CHAR_INT( 't', 'i', 't', 'l'),       // title\n    BOX_dscp    = FOUR_CHAR_INT( 'd', 's', 'c', 'p'),       // description\n    BOX_perf    = FOUR_CHAR_INT( 'p', 'e', 'r', 'f'),       // performer\n    BOX_mean    = FOUR_CHAR_INT( 'm', 'e', 'a', 'n'),       //\n    BOX_name    = FOUR_CHAR_INT( 'n', 'a', 'm', 'e'),       //\n    BOX_data    = FOUR_CHAR_INT( 'd', 'a', 't', 'a'),       //\n\n    // these from http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/2008-September/053151.html\n    BOX_albm    = FOUR_CHAR_INT( 'a', 'l', 'b', 'm'),      // album\n    BOX_yrrc    = FOUR_CHAR_INT( 'y', 'r', 'r', 'c'),      // album\n\n    // Hap subtypes\n    BOX_Hap1    = FOUR_CHAR_INT( 'H', 'a', 'p', '1' ),\n    BOX_Hap5    = FOUR_CHAR_INT( 'H', 'a', 'p', '5' ),\n    BOX_HapY    = FOUR_CHAR_INT( 'H', 'a', 'p', 'Y' ),\n    BOX_HapM    = FOUR_CHAR_INT( 'H', 'a', 'p', 'M' ),\n    BOX_HapA    = FOUR_CHAR_INT( 'H', 'a', 'p', 'A' )\n};\n\n#endif //mp4defs_H_INCLUDED\n"
  },
  {
    "path": "Plugin/MP4/mp4demux.c",
    "content": "/** 20.09.2009 ASP @file\n*\n*/\n\n#include \"mp4demux.h\"\n#include <stdlib.h>\n#include <string.h>\n#include <assert.h>\n#include <limits.h>     // LONG_MAX\n#include <sys/types.h>  // struct stat\n#include <sys/stat.h>   // fstat       - for file size\n\n/************************************************************************/\n/*      Build config                                                    */\n/************************************************************************/\n// Max chunks nesting level\n#define MP4D_MAX_CHUNKS_DEPTH            64\n\n// Debug trace\n#ifndef MP4D_DEBUG_TRACE\n#   define MP4D_DEBUG_TRACE     0\n#endif\n#if MP4D_DEBUG_TRACE\n#   define MP4D_TRACE(x) printf x\n#else\n#   define MP4D_TRACE(x)\n#endif\n\n// Box type: ATOM box, or 'Object Descriptor' box inside the atom.\ntypedef enum {BOX_ATOM, BOX_OD} mp4d_boxtype_t;\n\n\n/************************************************************************/\n/*      File input (non-portable) stuff                                 */\n/************************************************************************/\n\n/**\n*   Return 64-bit file size in most portable way\n*/\nstatic off_t mp4d_fsize(FILE * f) \n{\n    struct stat st;\n#ifdef _MSC_VER\n    if (fstat(_fileno(f), &st) == 0)\n#else\n    if (fstat(fileno(f), &st) == 0)\n#endif\n    {\n        return st.st_size;\n    }\n    return -1;\n}\n\n/**\n*   Read given number of bytes from the file\n*   Used to read box headers\n*/\nstatic unsigned mp4d_read(FILE * f, int nb, int * eof_flag)\n{\n    uint32_t v = 0; int last_byte;\n    switch (nb)\n    {\n    case 4: v = (v << 8) | fgetc(f);\n    case 3: v = (v << 8) | fgetc(f);\n    case 2: v = (v << 8) | fgetc(f);\n    default:\n    case 1: v = (v << 8) | (last_byte = fgetc(f));\n    }\n    if (last_byte == EOF)\n    {\n        *eof_flag = 1;\n    }\n    return v;\n}\n\n/**\n*   Read given number of bytes, but no more than *payload_bytes specifies...\n*   Used to read box payload\n*/\nstatic uint32_t mp4d_read_payload(FILE * f, unsigned nb, mp4d_size_t * payload_bytes, int * eof_flag)\n{\n    if (*payload_bytes < nb)\n    {\n        *eof_flag = 1;\n        nb = (int)*payload_bytes;\n    }\n    *payload_bytes -= nb;\n\n    return mp4d_read(f, nb, eof_flag);\n}\n\n/**\n*   Skips given number of bytes.\n*/\nstatic void mp4d_skip_bytes(FILE * f, mp4d_size_t skip, int * eof_flag)\n{\n    while (skip > 0)\n    {\n        long lpos = (long)(skip < (mp4d_size_t)LONG_MAX ? skip : LONG_MAX);\n        if (fseek(f, lpos, SEEK_CUR))\n        {\n            *eof_flag = 1;\n            return;\n        }\n        skip -= lpos;\n    }\n}\n\n\n#define READ(n) mp4d_read_payload(f, n, &payload_bytes, &eof_flag)\n#define SKIP(n) {mp4d_size_t t = payload_bytes < (n) ? payload_bytes : (n); mp4d_skip_bytes(f, t, &eof_flag); payload_bytes -= t;}\n#define MP4D_MALLOC(p, size) p = malloc(size); if (!(p)) {MP4D_ERROR(\"out of memory\");}\n#define MP4D_REALLOC(p, size) {void * r = realloc(p, size); if (!(r)) {MP4D_ERROR(\"out of memory\");} else p = r;};\n\n/*\n*   On error: release resources, rewind the file.\n*/\n#define MP4D_RETURN_ERROR(mess) {       \\\n    MP4D_TRACE((\"\\nMP4 ERROR: \" mess)); \\\n    fseek(f, 0, SEEK_SET);              \\\n    MP4D__close(mp4);                   \\\n    return 0;                           \\\n}\n\n/*\n*   Any errors, occurred on top-level hierarchy is passed to exit check: 'if (!mp4->track_count) ... '\n*/\n#define MP4D_ERROR(mess)            \\\n    if (!depth)                     \\\n        break;                      \\\n    else                            \\\n        MP4D_RETURN_ERROR(mess);\n\n\n\n/************************************************************************/\n/*      Exported API functions                                          */\n/************************************************************************/\n\n/**\n*   Parse given file as MP4 file.  Allocate and store data indexes.\n*/\nint MP4D__open(MP4D_demux_t * mp4, FILE * f)\n{\n    int depth = 0;              // box stack size\n\n    // box stack\n    struct\n    {\n        // remaining bytes for box in the stack\n        mp4d_size_t bytes;\n\n        // kind of box children's: OD chunks handled in the same manner as name chunks\n        mp4d_boxtype_t format;\n\n    } stack[MP4D_MAX_CHUNKS_DEPTH];\n\n    off_t file_size = mp4d_fsize(f);\n    int eof_flag = 0;\n    unsigned i;\n    MP4D_track_t * tr = NULL;\n    int read_hdlr = 0;\n\n#if MP4D_DEBUG_TRACE\n    // path of current element: List0/List1/... etc\n    uint32_t box_path[MP4D_MAX_CHUNKS_DEPTH];\n#endif\n\n    if (!f || !mp4)\n    {\n        MP4D_TRACE((\"\\nERROR: invlaid arguments!\"));\n        return 0;\n    }\n\n    if (fseek(f, 0, SEEK_SET))  // some platforms missing rewind()\n    {\n        return 0;\n    }\n\n    memset(mp4, 0, sizeof(MP4D_demux_t));\n\n    stack[0].format = BOX_ATOM;   // start with atom box\n    stack[0].bytes = 0;           // never accessed\n\n    do\n    {\n        // List of boxes, derived from 'FullBox'\n        //                ~~~~~~~~~~~~~~~~~~~~~\n        // need read version field and check version for these boxes\n        static const struct\n        {\n            uint32_t name;\n            unsigned max_version;\n            unsigned use_track_flag;\n        } g_fullbox[] =\n        {\n            {BOX_mdhd, 1, 1},\n            {BOX_mvhd, 1, 0},\n            {BOX_hdlr, 0, 0},\n            {BOX_meta, 0, 0},\n            {BOX_stts, 0, 0},\n            {BOX_ctts, 0, 0},\n            {BOX_stz2, 0, 1},\n            {BOX_stsz, 0, 1},\n            {BOX_stsc, 0, 1},\n            {BOX_stco, 0, 1},\n            {BOX_co64, 0, 1},\n            {BOX_stsd, 0, 0},\n            {BOX_esds, 0, 1}    // esds does not use track, but switches to OD mode. Check here, to avoid OD check\n        };\n\n        // List of boxes, which contains other boxes ('envelopes')\n        // Parser will descend down for boxes in this list, otherwise parsing will proceed to \n        // the next sibling box\n        // OD boxes handled in the same way as atom boxes...\n        static const struct\n        {\n            uint32_t name;\n            mp4d_boxtype_t type;\n        } g_envelope_box[] =\n        {\n            {BOX_esds, BOX_OD},     // TODO: BOX_esds can be used for both audio and video, but this code supports audio only!\n            {OD_ESD,   BOX_OD},\n            {OD_DCD,   BOX_OD},\n            {OD_DSI,   BOX_OD},\n            {BOX_trak, BOX_ATOM},\n            {BOX_moov, BOX_ATOM},\n            {BOX_mdia, BOX_ATOM},\n            {BOX_tref, BOX_ATOM},\n            {BOX_minf, BOX_ATOM},\n            {BOX_dinf, BOX_ATOM},\n            {BOX_stbl, BOX_ATOM},\n            {BOX_stsd, BOX_ATOM},\n            {BOX_mp4a, BOX_ATOM},\n            {BOX_mp4s, BOX_ATOM},\n            {BOX_mp4v, BOX_ATOM},\n            {BOX_avc1, BOX_ATOM},\n            {BOX_udta, BOX_ATOM},\n            {BOX_meta, BOX_ATOM},\n            {BOX_ilst, BOX_ATOM}\n        };\n\n        uint32_t FullAtomVersionAndFlags = 0;\n        mp4d_size_t payload_bytes;\n        mp4d_size_t box_bytes;\n        uint32_t box_name;\n        unsigned char ** ptag = NULL;\n        int read_bytes = 0;\n\n        // Read header box type and it's length\n        if (stack[depth].format == BOX_ATOM)\n        {\n            box_bytes = mp4d_read(f, 4, &eof_flag);\n            if (eof_flag)\n            {\n                break;  // normal exit\n            }\n\n            if (box_bytes >= 2 && box_bytes < 8)\n            {\n                MP4D_ERROR(\"invalid box size (broken file?)\");\n            }\n\n            box_name  = mp4d_read(f, 4, &eof_flag);\n            read_bytes = 8;\n\n            // Decode box size\n            if (box_bytes == 0 ||                         // standard indication of 'till eof' size\n                box_bytes == (mp4d_size_t)0xFFFFFFFFU       // some files uses non-standard 'till eof' signaling\n                )\n            {\n                box_bytes = ~(mp4d_size_t)0;\n            }\n\n            payload_bytes = box_bytes - 8;\n\n            if (box_bytes == 1)           // 64-bit sizes\n            {\n                box_bytes = mp4d_read(f, 4, &eof_flag);\n                box_bytes <<= 32;\n                box_bytes |= mp4d_read(f, 4, &eof_flag);\n                if (box_bytes < 16)\n                {\n                    MP4D_ERROR(\"invalid box size (broken file?)\");\n                }\n                payload_bytes = box_bytes - 16;\n            }\n\n            // Read and check box version for some boxes\n            for (i = 0; i < sizeof(g_fullbox)/sizeof(g_fullbox[0]); i++)\n            {\n                if (box_name == g_fullbox[i].name)\n                {\n                    FullAtomVersionAndFlags = READ(4);\n                    read_bytes += 4;\n\n                    if ((FullAtomVersionAndFlags >> 24) > g_fullbox[i].max_version)\n                    {\n                        MP4D_ERROR(\"unsupported box version!\");\n                    }\n                    if (g_fullbox[i].use_track_flag && !tr)\n                    {\n                        MP4D_ERROR(\"broken file structure!\");\n                    }\n                }\n            }\n        }\n        else // stack[depth].format == BOX_OD\n        {\n            int val;\n            box_name = OD_BASE + mp4d_read(f, 1, &eof_flag);     // 1-byte box type\n            read_bytes += 1;\n            if (eof_flag)\n            {\n                break;\n            }\n\n            payload_bytes = 0;\n            box_bytes = 1;\n            do\n            {\n                val = mp4d_read(f, 1, &eof_flag);\n                read_bytes += 1;\n                if (eof_flag)\n                {\n                    MP4D_ERROR(\"premature EOF!\");\n                }\n                payload_bytes = (payload_bytes << 7) | (val & 0x7F);\n                box_bytes++;\n            } while (val & 0x80);\n            box_bytes += payload_bytes;\n        }\n\n#if MP4D_DEBUG_TRACE\n        box_path[depth] = (box_name >> 24) | (box_name << 24) | ((box_name >> 8) & 0x0000FF00) | ((box_name << 8) & 0x00FF0000);\n        MP4D_TRACE((\"%2d  %8d %.*s  (%d bytes remains for sibilings) \\n\", depth, (int)box_bytes, depth*4, (char*)box_path, (int)stack[depth].bytes));\n#endif\n\n        // Check that box size <= parent size\n        if (depth)\n        {\n            // Skip box with bad size\n            assert(box_bytes > 0);\n            if (box_bytes > stack[depth].bytes)\n            {\n                MP4D_TRACE((\"Wrong %c%c%c%c box size: broken file?\\n\", (box_name >> 24)&255, (box_name >> 16)&255, (box_name >> 8)&255, box_name&255));\n                box_bytes = stack[depth].bytes;\n                box_name = 0;\n                payload_bytes = box_bytes - read_bytes;\n            }\n            stack[depth].bytes -= box_bytes;\n        }\n\n        // Read box header\n        switch(box_name)\n        {\n        case BOX_stz2:  //ISO/IEC 14496-1 Page 38. Section 8.17.2 - Sample Size Box.\n        case BOX_stsz:\n            {\n                int carry_size = 0;\n                uint32_t sample_size = READ(4);\n                tr->sample_count = READ(4);\n                MP4D_MALLOC(tr->entry_size, tr->sample_count*4);\n                for (i = 0; i < tr->sample_count; i++)\n                {\n                    if (box_name == BOX_stsz)\n                    {\n                       tr->entry_size[i] = (sample_size?sample_size:READ(4));\n                    }\n                    else\n                    {\n                        switch (sample_size & 0xFF)\n                        {\n                        case 16:\n                            tr->entry_size[i] = READ(2);\n                            break;\n                        case  8:\n                            tr->entry_size[i] = READ(1);\n                            break;\n                        case  4:\n                            if (i&1)\n                            {\n                                tr->entry_size[i] = carry_size & 15;\n                            }\n                            else\n                            {\n                                carry_size = READ(1);\n                                tr->entry_size[i] = (carry_size >> 4);\n                            }\n                            break;\n                        }\n                    }\n                }\n            }\n            break;\n\n        case BOX_stsc:  //ISO/IEC 14496-12 Page 38. Section 8.18 - Sample To Chunk Box.\n            tr->sample_to_chunk_count = READ(4);\n            MP4D_MALLOC(tr->sample_to_chunk, tr->sample_to_chunk_count*sizeof(tr->sample_to_chunk[0]));\n            for (i = 0; i < tr->sample_to_chunk_count; i++)\n            {\n                tr->sample_to_chunk[i].first_chunk = READ(4);\n                tr->sample_to_chunk[i].samples_per_chunk = READ(4);\n                SKIP(4);    // sample_description_index\n            }\n            break;\n\n        case BOX_stts:\n            {\n                unsigned count = READ(4);\n                unsigned j, k = 0, ts = 0, ts_count = count;\n                MP4D_MALLOC(tr->timestamp, ts_count*4);\n                MP4D_MALLOC(tr->duration, ts_count*4);\n\n                for (i = 0; i < count; i++)\n                {\n                    unsigned sc = READ(4);\n                    int d =  READ(4);\n                    MP4D_TRACE((\"sample %8d count %8d duration %8d\\n\",i,sc,d));\n                    if (k + sc > ts_count)\n                    {\n                        ts_count = k + sc;\n                        MP4D_REALLOC(tr->timestamp, ts_count * sizeof(unsigned));\n                        MP4D_REALLOC(tr->duration, ts_count * sizeof(unsigned));\n                    }\n                    for (j = 0; j < sc; j++)\n                    {\n                        tr->duration[k] = d;\n                        tr->timestamp[k++] = ts;\n                        ts += d;\n                    }\n                }\n            }\n            break;\n\n        case BOX_ctts:\n            {\n                unsigned count = READ(4);\n                for (i = 0; i < count; i++)\n                {\n                    int sc = READ(4);\n                    int d =  READ(4);\n                    (void)sc;\n                    (void)d;\n                    MP4D_TRACE((\"sample %8d count %8d decoding to composition offset %8d\\n\",i,sc,d));\n                }\n            }\n            break;\n\n        case BOX_stco:  //ISO/IEC 14496-12 Page 39. Section 8.19 - Chunk Offset Box.\n        case BOX_co64:\n            tr->chunk_count = READ(4);\n            MP4D_MALLOC(tr->chunk_offset, tr->chunk_count*sizeof(mp4d_size_t));\n            for (i = 0; i < tr->chunk_count; i++)\n            {\n                tr->chunk_offset[i] = READ(4);\n                if (box_name == BOX_co64)\n                {\n                    // 64-bit chunk_offset \n                    tr->chunk_offset[i] <<= 32;\n                    tr->chunk_offset[i] |= READ(4);\n                }\n            }\n            break;\n\n        case BOX_mvhd:\n            SKIP(((FullAtomVersionAndFlags >> 24) == 1) ? 8+8 : 4+4);\n            mp4->timescale = READ(4);\n            mp4->duration_hi = ((FullAtomVersionAndFlags >> 24) == 1) ? READ(4) : 0;\n            mp4->duration_lo = READ(4);\n            SKIP(4+2+2+4*2+4*9+4*6+4);\n            break;\n\n        case BOX_mdhd:\n            SKIP(((FullAtomVersionAndFlags >> 24) == 1) ? 8+8 : 4+4);\n            tr->timescale = READ(4);\n            tr->duration_hi = ((FullAtomVersionAndFlags >> 24) == 1) ? READ(4) : 0;\n            tr->duration_lo = READ(4);\n\n            {\n                int ISO_639_2_T = READ(2);\n                tr->language[2] = (ISO_639_2_T & 31) + 0x60;ISO_639_2_T >>= 5;\n                tr->language[1] = (ISO_639_2_T & 31) + 0x60;ISO_639_2_T >>= 5;\n                tr->language[0] = (ISO_639_2_T & 31) + 0x60;\n            }\n            // the rest of this box is skipped by default ...\n            break;\n\n        case BOX_mdia:\n            read_hdlr = 1;\n            break;\n\n        case BOX_minf:\n            read_hdlr = 0;\n            break;\n\n        case BOX_hdlr:\n            if (tr && read_hdlr) // When this box is within 'meta' box, the track may not be avaialable\n            {\n                SKIP(4);            // pre_defined\n                tr->handler_type = READ(4);\n            }\n            // typically hdlr box does not contain any useful info.\n            // the rest of this box is skipped by default ...\n            break;\n\n        case BOX_btrt:\n            if (!tr)\n            {\n                MP4D_ERROR(\"broken file structure!\");\n            }\n\n            SKIP(4+4);\n            tr->avg_bitrate_bps = READ(4);\n            break;\n\n            // Set pointer to tag to be read...\n        case BOX_calb: ptag = &mp4->tag.album; break;\n        case BOX_cART: ptag = &mp4->tag.artist; break;\n        case BOX_cnam: ptag = &mp4->tag.title; break;\n        case BOX_cday: ptag = &mp4->tag.year; break;\n        case BOX_ccmt: ptag = &mp4->tag.comment; break;\n        case BOX_cgen: ptag = &mp4->tag.genre; break;\n\n        case BOX_stsd:\n            SKIP(4); // entry_count, BOX_mp4a & BOX_mp4v boxes follows immediately\n            break;\n\n        case BOX_mp4s:  // private stream\n            if (!tr)\n            {\n                MP4D_ERROR(\"broken file structure!\");\n            }\n            SKIP(6*1+2/*Base SampleEntry*/);\n            break;\n\n        case BOX_mp4a:\n            if (!tr)\n            {\n                MP4D_ERROR(\"broken file structure!\");\n            }\n            SKIP(6*1+2/*Base SampleEntry*/  + 4*2);\n            tr->SampleDescription.audio.channelcount = READ(2);\n            SKIP(2/*samplesize*/ + 2 + 2);\n            tr->SampleDescription.audio.samplerate_hz = READ(4) >> 16;\n            break;\n\n        // Hap subtypes\n        case BOX_Hap1:\n        case BOX_Hap5:\n        case BOX_HapY:\n        case BOX_HapM:\n        case BOX_HapA:\n\n        // vvvvvvvvvvvvv AVC support vvvvvvvvvvvvv\n        case BOX_avc1:  // AVCSampleEntry extends VisualSampleEntry \n//         case BOX_avc2:   - no test\n//         case BOX_svc1:   - no test\n        case BOX_mp4v:\n            if (!tr)\n            {\n                MP4D_ERROR(\"broken file structure!\");\n            }\n            SKIP(6*1 + 2/*Base SampleEntry*/ + 2 + 2 + 4*3);\n            tr->SampleDescription.video.width = READ(2);\n            tr->SampleDescription.video.height = READ(2);\n            // frame_count is always 1\n            // compressorname is rarely set..\n            SKIP(4 + 4 + 4 + 2/*frame_count*/ + 32/*compressorname*/ + 2 + 2);\n            // ^^^ end of VisualSampleEntry \n            // now follows for BOX_avc1:\n            //      BOX_avcC\n            //      BOX_btrt (optional)\n            //      BOX_m4ds (optional)\n            // for BOX_mp4v:\n            //      BOX_esds        \n            break;\n        \n        case BOX_avcC:  // AVCDecoderConfigurationRecord()\n            // hack: AAC-specific DSI field reused (for it have same purpose as sps/pps)\n            // TODO: check this hack if BOX_esds co-exist with BOX_avcC \n            tr->object_type_indication = MP4_OBJECT_TYPE_AVC;\n            tr->dsi = malloc((size_t)box_bytes);\n            tr->dsi_bytes = (unsigned)box_bytes;\n            {\n                int spspps;\n                unsigned char * p = tr->dsi;\n                unsigned int configurationVersion = READ(1);\n                unsigned int AVCProfileIndication = READ(1);\n                unsigned int profile_compatibility = READ(1);\n                unsigned int AVCLevelIndication = READ(1);\n                //bit(6) reserved = 111111b;\n                unsigned int lengthSizeMinusOne = READ(1) & 3;\n                \n                (void)configurationVersion;\n                (void)AVCProfileIndication;\n                (void)profile_compatibility;\n                (void)AVCLevelIndication;\n                (void)lengthSizeMinusOne;\n                for (spspps = 0; spspps < 2; spspps++)\n                {\n                    unsigned int numOfSequenceParameterSets= READ(1);\n                    if (!spspps)\n                    {\n                         numOfSequenceParameterSets &= 31;  // clears 3 msb for SPS\n                    }\n                    *p++ = numOfSequenceParameterSets;\n                    for (i=0; i< numOfSequenceParameterSets; i++) {\n                        unsigned k, sequenceParameterSetLength  = READ(2);\n                        *p++ = sequenceParameterSetLength >> 8;\n                        *p++ = sequenceParameterSetLength ;\n                        for (k = 0; k < sequenceParameterSetLength ; k++)\n                        {\n                            *p++ = READ(1);\n                        }\n                    }\n                }\n            }\n            break;\n        // ^^^^^^^^^^^^^ AVC support ^^^^^^^^^^^^^\n\n        case OD_ESD:\n            {\n                unsigned flags = READ(3);   // ES_ID(2) + flags(1)\n\n                if (flags & 0x80)       // steamdependflag\n                {\n                    SKIP(2);            // dependsOnESID\n                }\n                if (flags & 0x40)       // urlflag\n                {\n                    unsigned bytecount = READ(1);\n                    SKIP(bytecount);    // skip URL\n                }\n                if (flags & 0x20)       // ocrflag (was reserved in MPEG-4 v.1)\n                {\n                    SKIP(2);            // OCRESID\n                }\n                break;\n            }\n\n        case OD_DCD:        //ISO/IEC 14496-1 Page 28. Section 8.6.5 - DecoderConfigDescriptor.\n            assert(tr);     // ensured by g_fullbox[] check\n            tr->object_type_indication = READ(1);\n            tr->stream_type = READ(1) >> 2;\n            SKIP(3/*bufferSizeDB*/ + 4/*maxBitrate*/);\n            tr->avg_bitrate_bps = READ(4);\n            break;\n\n        case OD_DSI:        //ISO/IEC 14496-1 Page 28. Section 8.6.5 - DecoderConfigDescriptor.\n            assert(tr);     // ensured by g_fullbox[] check\n            if (!tr->dsi && payload_bytes)\n            {\n                MP4D_MALLOC(tr->dsi, (int)payload_bytes);\n                for (i = 0; i < payload_bytes; i++)\n                {\n                    tr->dsi[i] = mp4d_read(f, 1, &eof_flag);    // These bytes available due to check above\n                }\n                tr->dsi_bytes = i;\n                payload_bytes -= i;\n                break;\n            }\n\n        default:\n            MP4D_TRACE((\"[%c%c%c%c]  %d\\n\", box_name>>24, box_name>>16, box_name>>8, box_name, (int)payload_bytes));\n        }\n\n        // Read tag is tag pointer is set\n        if (ptag && !*ptag && payload_bytes > 16)\n        {\n            SKIP(4+4+4+4);\n            MP4D_MALLOC(*ptag, (unsigned)payload_bytes + 1);\n            for (i = 0; payload_bytes != 0; i++)\n            {\n                (*ptag)[i] = READ(1);\n            }\n            (*ptag)[i] = 0; // zero-terminated string\n        }\n\n        if (box_name == BOX_trak)\n        {\n            // New track found: allocate memory using realloc()\n            // Typically there are 1 audio track for AAC audio file,\n            // 4 tracks for movie file,\n            // 3-5 tracks for scalable audio (CELP+AAC)\n            // and up to 50 tracks for BSAC scalable audio\n            MP4D_REALLOC(mp4->track, (mp4->track_count + 1)*sizeof(MP4D_track_t));\n            tr = mp4->track + mp4->track_count++;\n            memset(tr, 0, sizeof(MP4D_track_t));\n        }\n        else if (box_name == BOX_meta)\n        {\n            tr = NULL;  // Avoid update of 'hdlr' box, which may contains in the 'meta' box\n        }\n\n        // If this box is envelope, save it's size in box stack\n        for (i = 0; i < sizeof(g_envelope_box)/sizeof(g_envelope_box[0]); i++)\n        {\n            if (box_name == g_envelope_box[i].name)\n            {\n                if (++depth >= MP4D_MAX_CHUNKS_DEPTH)\n                {\n                    MP4D_ERROR(\"too deep atoms nesting!\");\n                }\n                stack[depth].bytes = payload_bytes;\n                stack[depth].format = g_envelope_box[i].type;\n                break;\n            }\n        }\n\n        // if box is not envelope, just skip it\n        if (i == sizeof(g_envelope_box)/sizeof(g_envelope_box[0]))\n        {\n            if (payload_bytes > file_size)\n            {\n                eof_flag = 1;\n            }\n            else\n            {\n                SKIP(payload_bytes);\n            }\n        }\n\n        // remove empty boxes from stack\n        // don't touch box with index 0 (which indicates whole file)\n        while (depth > 0 && !stack[depth].bytes)\n        {\n            depth--;\n        }\n\n    } while(!eof_flag);\n\n    if (!mp4->track_count)\n    {\n        MP4D_RETURN_ERROR(\"no tracks found\");\n    }\n    fseek(f, 0, SEEK_SET);\n    return 1;\n}\n\n/**\n*   Find chunk, containing given sample.\n*   Returns chunk number, and first sample in this chunk.\n*/\nstatic int mp4d_sample_to_chunk(MP4D_track_t * tr, unsigned nsample, unsigned * nfirst_sample_in_chunk)\n{\n    unsigned chunk_group = 0, nc;\n    unsigned sum = 0;\n    *nfirst_sample_in_chunk = 0;\n    if (tr->chunk_count <= 1)\n    {\n        return 0;\n    }\n    for (nc = 0; nc < tr->chunk_count; nc++)\n    {\n        if (chunk_group+1 < tr->sample_to_chunk_count     // stuck at last entry till EOF\n            && nc + 1 ==    // Chunks counted starting with '1'\n               tr->sample_to_chunk[chunk_group+1].first_chunk)    // next group?\n        {\n            chunk_group++;\n        }\n\n        sum += tr->sample_to_chunk[chunk_group].samples_per_chunk;\n        if (nsample < sum)\n        {\n            return nc;\n        }\n\n        // TODO: this can be calculated once per file\n        *nfirst_sample_in_chunk = sum;\n    }\n    return -1;\n}\n\n/**\n*   Return position and size for given sample from given track.\n*/\nmp4d_size_t MP4D__frame_offset(const MP4D_demux_t * mp4, unsigned ntrack, unsigned nsample, unsigned * frame_bytes, unsigned * timestamp, unsigned * duration)\n{\n    MP4D_track_t * tr = mp4->track + ntrack;\n    unsigned ns;\n    int nchunk = mp4d_sample_to_chunk(tr, nsample, &ns);\n    mp4d_size_t offset;\n\n    if (nchunk < 0)\n    {\n        *frame_bytes = 0;\n        return 0;\n    }\n\n    offset = tr->chunk_offset[nchunk];\n    for (;ns < nsample; ns++)\n    {\n        offset += tr->entry_size[ns];\n    }\n\n    *frame_bytes = tr->entry_size[ns];\n\n    if (timestamp)\n    {\n        *timestamp = tr->timestamp[ns];\n    }\n    if (duration)\n    {\n        *duration = tr->duration[ns];\n    }\n\n    return offset;\n}\n\n/**\n*   De-allocated memory\n*/\nvoid MP4D__close(MP4D_demux_t * mp4)\n{\n#define FREE(x) if (x) {free(x); x = NULL;}\n    while (mp4->track_count)\n    {\n        MP4D_track_t *tr = mp4->track + --mp4->track_count;\n        FREE(tr->entry_size);\n        FREE(tr->timestamp);\n        FREE(tr->duration);\n        FREE(tr->sample_to_chunk);\n        FREE(tr->chunk_offset);\n        FREE(tr->dsi);\n    }\n    FREE(mp4->track);\n    FREE(mp4->tag.title);\n    FREE(mp4->tag.artist);\n    FREE(mp4->tag.album);\n    FREE(mp4->tag.year);\n    FREE(mp4->tag.comment);\n    FREE(mp4->tag.genre);\n}\n\n/**\n*   skip given number of SPS/PPS in the list.\n*   return number of bytes skipped\n*/\nstatic int mp4d_skip_spspps(const unsigned char * p, int nbytes, int nskip)\n{\n    int i, k = 0;\n    for (i = 0; i < nskip; i++)\n    {\n        unsigned segmbytes;\n        if (k > nbytes - 2)\n        {\n            return -1;\n        }\n        segmbytes = p[k]*256 + p[k+1];\n        k += 2 + segmbytes;\n    }\n    return k;\n}\n\n/**\n*   Read SPS/PPS with given index\n*/\nstatic const unsigned char * MP4D__read_spspps(const MP4D_demux_t * mp4, unsigned int ntrack, int pps_flag, int nsps, int * sps_bytes)\n{\n    int sps_count, skip_bytes;\n    int bytepos = 0;\n    unsigned char * p = mp4->track[ntrack].dsi;\n    if (ntrack >= mp4->track_count)\n    {\n        return NULL;\n    }\n    if (mp4->track[ntrack].object_type_indication != MP4_OBJECT_TYPE_AVC)\n    {\n        return NULL;    // SPS/PPS are specific for AVC format only\n    }\n\n    if (pps_flag)\n    {\n        // Skip all SPS\n        sps_count = p[bytepos++];\n        skip_bytes = mp4d_skip_spspps(p+bytepos, mp4->track[ntrack].dsi_bytes - bytepos, sps_count);\n        if (skip_bytes < 0)\n        {\n            return NULL;\n        }\n        bytepos += skip_bytes;\n    }\n\n    // Skip sps/pps before the given target\n    sps_count = p[bytepos++];\n    if (nsps >= sps_count)\n    {\n        return NULL;\n    }\n    skip_bytes = mp4d_skip_spspps(p+bytepos, mp4->track[ntrack].dsi_bytes - bytepos, nsps);\n    if (skip_bytes < 0)\n    {\n        return NULL;\n    }\n    bytepos += skip_bytes;\n    *sps_bytes = p[bytepos]*256 + p[bytepos+1];\n    return p + bytepos + 2;\n}\n\n/**\n*   Read SPS with given index\n*   Return pointer to internal mp4 memory, it must not be free()-ed\n*/\nconst unsigned char * MP4D__read_sps(const MP4D_demux_t * mp4, unsigned int ntrack, int nsps, int * sps_bytes)\n{\n    return MP4D__read_spspps(mp4, ntrack, 0, nsps, sps_bytes);\n}\n\n/**\n*   Read PPS with given index\n*   Return pointer to internal mp4 memory, it must not be free()-ed\n*/\nconst unsigned char * MP4D__read_pps(const MP4D_demux_t * mp4, unsigned int ntrack, int npps, int * pps_bytes)\n{\n    return MP4D__read_spspps(mp4, ntrack, 1, npps, pps_bytes);\n}\n    \n\n/************************************************************************/\n/*  Purely informational part, may be removed for embedded applications */\n/************************************************************************/\n\n/**\n*   Decodes ISO/IEC 14496 MP4 stream type to ASCII string\n*/\nconst char * MP4D__stream_type_to_ascii(int stream_type)\n{\n    switch (stream_type)\n    {\n    case 0x00: return \"Forbidden\";\n    case 0x01: return \"ObjectDescriptorStream\";\n    case 0x02: return \"ClockReferenceStream\";\n    case 0x03: return \"SceneDescriptionStream\";\n    case 0x04: return \"VisualStream\";\n    case 0x05: return \"AudioStream\";\n    case 0x06: return \"MPEG7Stream\";\n    case 0x07: return \"IPMPStream\";\n    case 0x08: return \"ObjectContentInfoStream\";\n    case 0x09: return \"MPEGJStream\";\n    default:\n        if (stream_type >= 0x20 && stream_type <= 0x3F)\n        {\n            return \"User private\";\n        }\n        else\n        {\n            return \"Reserved for ISO use\";\n        }\n    }\n}\n\n/**\n*   Decodes ISO/IEC 14496 MP4 object type to ASCII string\n*/\nconst char * MP4D__object_type_to_ascii(int object_type_indication)\n{\n    switch (object_type_indication)\n    {\n    case 0x00: return \"Forbidden\";\n    case 0x01: return \"Systems ISO/IEC 14496-1\";\n    case 0x02: return \"Systems ISO/IEC 14496-1\";\n    case 0x20: return \"Visual ISO/IEC 14496-2\";\n    case 0x21: return \"Visual ISO/IEC 14496-10\";\n    case 0x22: return \"Visual ISO/IEC 14496-10 Parameter Sets\";\n    case 0x40: return \"Audio ISO/IEC 14496-3\";\n    case 0x60: return \"Visual ISO/IEC 13818-2 Simple Profile\";\n    case 0x61: return \"Visual ISO/IEC 13818-2 Main Profile\";\n    case 0x62: return \"Visual ISO/IEC 13818-2 SNR Profile\";\n    case 0x63: return \"Visual ISO/IEC 13818-2 Spatial Profile\";\n    case 0x64: return \"Visual ISO/IEC 13818-2 High Profile\";\n    case 0x65: return \"Visual ISO/IEC 13818-2 422 Profile\";\n    case 0x66: return \"Audio ISO/IEC 13818-7 Main Profile\";\n    case 0x67: return \"Audio ISO/IEC 13818-7 LC Profile\";\n    case 0x68: return \"Audio ISO/IEC 13818-7 SSR Profile\";\n    case 0x69: return \"Audio ISO/IEC 13818-3\";\n    case 0x6A: return \"Visual ISO/IEC 11172-2\";\n    case 0x6B: return \"Audio ISO/IEC 11172-3\";\n    case 0x6C: return \"Visual ISO/IEC 10918-1\";\n    case 0xFF: return \"no object type specified\";\n    default:\n        if (object_type_indication >= 0xC0 && object_type_indication <= 0xFE)\n        {\n            return \"User private\";\n        }\n        else\n        {\n            return \"Reserved for ISO use\";\n        }\n    }\n}\n\n\n#ifdef mp4demux_test\n/******************************************************************************\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n!!!!                                                                       !!!!\n!!!!                 !!!!!!!!  !!!!!!!!   !!!!!!!   !!!!!!!!               !!!!\n!!!!                    !!     !!        !!            !!                  !!!!\n!!!!                    !!     !!        !!            !!                  !!!!\n!!!!                    !!     !!!!!!     !!!!!!!      !!                  !!!!\n!!!!                    !!     !!               !!     !!                  !!!!\n!!!!                    !!     !!               !!     !!                  !!!!\n!!!!                    !!     !!!!!!!!   !!!!!!!      !!                  !!!!\n!!!!                                                                       !!!!\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n******************************************************************************/\n\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <assert.h>\n#include <string.h>\n#include <math.h>\n#include <memory.h>\n#include \"mp4demux.h\"\n\n\n/**\n*   Print MP4 information to stdout.\n*/\nstatic void print_mp4_info(const MP4D_demux_t * mp4_demux)\n{\n    unsigned i;\n\n    printf(\"\\nMP4 FILE: %d tracks found. Movie time %.2f sec\\n\", mp4_demux->track_count, (4294967296.0*mp4_demux->duration_hi + mp4_demux->duration_lo) / mp4_demux->timescale);\n    printf(\"\\nNo|type|lng| duration           | bitrate| %-23s| Object type\",\"Stream type\");\n    for (i = 0; i < mp4_demux->track_count; i++)\n    {\n        MP4D_track_t * tr = mp4_demux->track + i;\n\n        printf(\"\\n%2d|%c%c%c%c|%c%c%c|%7.2f s %6d frm| %7d|\", i,\n            (tr->handler_type>>24), (tr->handler_type>>16), (tr->handler_type>>8), (tr->handler_type>>0),\n            tr->language[0],tr->language[1],tr->language[2],\n            (65536.0* 65536.0*tr->duration_hi + tr->duration_lo) / tr->timescale,\n            tr->sample_count,\n            tr->avg_bitrate_bps\n            );\n\n        printf(\" %-23s|\", MP4D__stream_type_to_ascii(tr->stream_type));\n        printf(\" %-23s\", MP4D__object_type_to_ascii(tr->object_type_indication));\n\n        if (tr->handler_type == MP4_HANDLER_TYPE_SOUN)\n        {\n            printf(\"  -  %d ch %d hz\", tr->SampleDescription.audio.channelcount, tr->SampleDescription.audio.samplerate_hz);\n        }\n        else if (tr->handler_type == MP4_HANDLER_TYPE_VIDE)\n        {\n            printf(\"  -  %dx%d\", tr->SampleDescription.video.width, tr->SampleDescription.video.height);\n        }\n    }\n    printf(\"\\n\");\n}\n\n/**\n*   Print MP4 file comment to stdout.\n*/\nstatic void print_comment(const MP4D_demux_t * mp4_demux)\n{\n#define STR_TAG(name) if (mp4_demux->tag.name)  printf(\"%10s = %s\\n\", #name, mp4_demux->tag.name)\n    STR_TAG(title);\n    STR_TAG(artist);\n    STR_TAG(album);\n    STR_TAG(year);\n    STR_TAG(comment);\n    STR_TAG(genre);\n}\n\n/**\n*   Print SPS/PPS/DSI data in hex to stdout.\n*/\nstatic void print_dsi_data(const MP4D_demux_t * mp4_demux)\n{\n    unsigned k, ntrack;\n    for (ntrack = 0; ntrack < mp4_demux->track_count; ntrack++)\n    {\n        MP4D_track_t *tr = mp4_demux->track + ntrack;\n        if (tr->dsi_bytes)\n        {\n            int i, k, sps_bytes, pps_bytes, sps_pps_found = 0;\n            for (i = 0; i < 256; i++)\n            {\n                const unsigned char *sps = MP4D__read_sps(mp4_demux, ntrack, i, &sps_bytes);\n                const unsigned char *pps = MP4D__read_pps(mp4_demux, ntrack, i, &pps_bytes);\n                if (sps && sps_bytes)\n                {\n                    printf(\"%d SPS bytes found for track #%d:\\n\", sps_bytes, ntrack);\n                    for (k = 0; k < sps_bytes; k++)\n                    {\n                        printf(\"%02x \", sps[k]);\n                    }\n                    printf(\"\\n\");\n                    sps_pps_found = 1;\n                }\n                if (pps && pps_bytes)\n                {\n                    printf(\"%d PPS bytes found for track #%d:\\n\", pps_bytes, ntrack);\n                    for (k = 0; k < pps_bytes; k++)\n                    {\n                        printf(\"%02x \", pps[k]);\n                    }\n                    printf(\"\\n\");\n                    sps_pps_found = 1;\n                }\n            }\n\n            if (!sps_pps_found)\n            {\n                printf(\"%d DSI bytes found for track #%d:\\n\", tr->dsi_bytes, ntrack);\n                for (k = 0; k < tr->dsi_bytes; k++)\n                {\n                    printf(\"%02x \", tr->dsi[k]);\n                }\n                printf(\"\\n\");\n            }\n        }\n    }\n}\n\n/**\n*   Save AVC & audio tracks data to files\n*/\nstatic void save_track_data(const MP4D_demux_t * mp4_demux, FILE * mp4_file, unsigned ntrack)\n{\n    unsigned i, frame_bytes, timestamp, duration;\n    unsigned avc_bytes_to_next_nal = 0;\n    MP4D_track_t *tr = mp4_demux->track + ntrack;\n    FILE * track_file;\n    char name[100];\n    const char * ext =  (tr->object_type_indication == MP4_OBJECT_TYPE_AVC) ? \"264\" : \n        (tr->handler_type == MP4_HANDLER_TYPE_SOUN) ? \"audio\" :\n        (tr->handler_type == MP4_HANDLER_TYPE_VIDE) ? \"video\" : \"data\";\n\n    sprintf(name, \"track%d.%s\", ntrack, ext);\n    track_file = fopen(name,\"wb\");\n    for (i = 0; i < tr->sample_count; i++)\n    {\n        unsigned char * frame_mem;\n        mp4d_size_t frame_ofs = MP4D__frame_offset(mp4_demux, ntrack, i, &frame_bytes, &timestamp, &duration);\n\n        // print frame offset\n        //printf(\"%4d %06x %08d %d\\n\", i, (unsigned)ofs, duration, frame_bytes);\n        //printf(\"%4d %06x %08d %d\\n\", i, (unsigned)ofs, timestamp, frame_bytes);\n\n        // save payload\n        frame_mem = malloc(frame_bytes);\n        fseek(mp4_file, (long)frame_ofs, SEEK_SET);\n        fread(frame_mem, 1, frame_bytes, mp4_file);\n\n        if (mp4_demux->track[ntrack].object_type_indication == MP4_OBJECT_TYPE_AVC)\n        {\n            // replace 4-byte length field with start code\n            unsigned startcode = 0x01000000;\n            unsigned k = avc_bytes_to_next_nal;\n            while (k < frame_bytes - 4)\n            {\n                avc_bytes_to_next_nal = 4 + ((frame_mem[k] * 256 + frame_mem[k+1])*256 + frame_mem[k+2])*256 + frame_mem[k+3];\n                *(unsigned *)(frame_mem + k) = startcode;\n                k += avc_bytes_to_next_nal;\n            }\n            avc_bytes_to_next_nal = k - frame_bytes;\n\n            // Write SPS/PPS for 1st frame\n            if (!i)\n            {\n                const void * data;\n                int nps, bytes; \n                for (nps = 0; NULL != (data = MP4D__read_sps(mp4_demux, ntrack, nps, &bytes)); nps++)\n                {\n                    fwrite(&startcode, 1, 4, track_file);\n                    fwrite(data, 1, bytes, track_file);\n                }\n                for (nps = 0; NULL != (data = MP4D__read_pps(mp4_demux, ntrack, nps, &bytes)); nps++)\n                {\n                    fwrite(&startcode, 1, 4, track_file);\n                    fwrite(data, 1, bytes, track_file);\n                }\n            }\n        }\n\n        fwrite(frame_mem, 1, frame_bytes, track_file);\n        free(frame_mem);\n    }\n    fclose(track_file);\n}\n\nint main(int argc, char* argv[])\n{\n    unsigned ntrack = 0;\n    MP4D_demux_t mp4_demux = {0,};\n    char* file_name = (argc>1)?argv[1]:\"default_input.mp4\";\n    FILE * mp4_file = fopen(file_name, \"rb\");\n\n    if (!mp4_file)\n    {\n        printf(\"\\nERROR: can't open file %s for reading\\n\", file_name);\n        return 0;\n    }\n    if (!MP4D__open(&mp4_demux, mp4_file))\n    {\n        printf(\"\\nERROR: can't parse %s \\n\", file_name);\n        return 0;\n    }\n\n    print_mp4_info(&mp4_demux);\n    \n    for (ntrack = 0; ntrack < mp4_demux.track_count; ntrack++)\n    {\n        save_track_data(&mp4_demux, mp4_file, ntrack);\n    }\n\n    print_comment(&mp4_demux);\n    print_dsi_data(&mp4_demux);\n    MP4D__close(&mp4_demux);\n    fclose(mp4_file);\n\n    return 0;\n}\n\n// dmc mp4demux.c -Dmp4demux_test && del *.obj *.map \n#endif  // mp4demux_test\n\n"
  },
  {
    "path": "Plugin/MP4/mp4demux.h",
    "content": "/** 20.09.2009 @file\n*   ISO MP4 file parsing\n*\n*   Portability note: this module uses:\n*   - Dynamic memory allocation (malloc(), realloc() and free()\n*   - Direct file access (fgetc(), fread() & fseek())\n*   - File size (fstat())\n*\n*   This module provide functions to decode mp4 indexes, and retrieve\n*   file position and size for each sample in given track.\n*\n*   Integration scenario example:\n*\n*   // 1. Parse MP4 structure\n*   if (MP4D__open(mp4, file_handle))\n*   {\n*       // 2. Find tracks, supported by the application\n*       for (i = 0; i < mp4->track_count; i++)\n*       {\n*           if (supported(mp4->track[i].object_type_indication))\n*           {\n*               // 3. Initialize decoder from transparent 'Decoder Specific Info' data\n*               init_decoder(mp4->track[i].dsi);\n*\n*               // 4. Read track data for each frame\n*               for (k = 0; k < mp4->track[i].sample_count; k++)\n*               {\n*                   fseek(file_handle, MP4D__frame_offset(mp4, i, k, &frame_size, NULL, NULL), SEEK_SET);\n*                   fread(buf, frame_size, 1, file_handle);\n*                   decode(buf);\n*               }\n*           }\n*       }\n*   }\n*\n*/\n\n#ifndef mp4demux_H_INCLUDED\n#define mp4demux_H_INCLUDED\n\n#include <stdio.h>\n#include \"mp4defs.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif  //__cplusplus\n\n\n/************************************************************************/\n/*                  Portable 64-bit type definition                     */\n/************************************************************************/\n\n#if (defined(__GNUC__) && __GNUC__ >= 4) || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901)\n#   include <stdint.h>  // hope that all GCC compilers support this C99 extension\n    typedef uint64_t mp4d_size_t;\n#else\n#   if defined (_MSC_VER)\n    typedef unsigned __int64    mp4d_size_t;\n#   else\n    typedef unsigned long long  mp4d_size_t;\n#   endif\n    typedef unsigned int        uint32_t;\n#endif\n\n\n\ntypedef struct \n{\n    unsigned         first_chunk;\n    unsigned         samples_per_chunk;\n} MP4D_sample_to_chunk_t;\n\n\ntypedef struct\n{\n    /************************************************************************/\n    /*                 mandatory public data                                */\n    /************************************************************************/\n    // How many 'samples' in the track\n    // The 'sample' is MP4 term, denoting audio or video frame\n    unsigned sample_count;\n\n    // Decoder-specific info (DSI) data\n    unsigned char * dsi;\n\n    // DSI data size\n    unsigned dsi_bytes;\n\n    // MP4 object type code\n    // case 0x00: return \"Forbidden\";\n    // case 0x01: return \"Systems ISO/IEC 14496-1\";\n    // case 0x02: return \"Systems ISO/IEC 14496-1\";\n    // case 0x20: return \"Visual ISO/IEC 14496-2\";\n    // case 0x40: return \"Audio ISO/IEC 14496-3\";\n    // case 0x60: return \"Visual ISO/IEC 13818-2 Simple Profile\";\n    // case 0x61: return \"Visual ISO/IEC 13818-2 Main Profile\";\n    // case 0x62: return \"Visual ISO/IEC 13818-2 SNR Profile\";\n    // case 0x63: return \"Visual ISO/IEC 13818-2 Spatial Profile\";\n    // case 0x64: return \"Visual ISO/IEC 13818-2 High Profile\";\n    // case 0x65: return \"Visual ISO/IEC 13818-2 422 Profile\";\n    // case 0x66: return \"Audio ISO/IEC 13818-7 Main Profile\";\n    // case 0x67: return \"Audio ISO/IEC 13818-7 LC Profile\";\n    // case 0x68: return \"Audio ISO/IEC 13818-7 SSR Profile\";\n    // case 0x69: return \"Audio ISO/IEC 13818-3\";\n    // case 0x6A: return \"Visual ISO/IEC 11172-2\";\n    // case 0x6B: return \"Audio ISO/IEC 11172-3\";\n    // case 0x6C: return \"Visual ISO/IEC 10918-1\";\n    unsigned object_type_indication;\n\n\n    /************************************************************************/\n    /*                 informational public data, not needed for decoding   */\n    /************************************************************************/\n    // handler_type when present in a media box, is an integer containing one of\n    // the following values, or a value from a derived specification:\n    // 'vide' Video track\n    // 'soun' Audio track\n    // 'hint' Hint track\n    unsigned handler_type;\n\n    // Track duration: 64-bit value split into 2 variables\n    unsigned duration_hi;\n    unsigned duration_lo;\n\n    // duration scale: duration = timescale*seconds\n    unsigned timescale;\n\n    // Average bitrate, bits per second\n    unsigned avg_bitrate_bps;\n\n    // Track language: 3-char ISO 639-2T code: \"und\", \"eng\", \"rus\", \"jpn\" etc...\n    unsigned char language[4];\n\n    // MP4 stream type\n    // case 0x00: return \"Forbidden\";\n    // case 0x01: return \"ObjectDescriptorStream\";\n    // case 0x02: return \"ClockReferenceStream\";\n    // case 0x03: return \"SceneDescriptionStream\";\n    // case 0x04: return \"VisualStream\";\n    // case 0x05: return \"AudioStream\";\n    // case 0x06: return \"MPEG7Stream\";\n    // case 0x07: return \"IPMPStream\";\n    // case 0x08: return \"ObjectContentInfoStream\";\n    // case 0x09: return \"MPEGJStream\";\n    unsigned stream_type;\n\n    union\n    {\n        // for handler_type == 'soun' tracks\n        struct\n        {\n            unsigned channelcount;\n            unsigned samplerate_hz;\n        } audio;\n\n        // for handler_type == 'vide' tracks\n        struct\n        {\n            unsigned width;\n            unsigned height;\n        } video;\n    } SampleDescription;\n\n    /************************************************************************/\n    /*                 private data: MP4 indexes                            */\n    /************************************************************************/\n    unsigned *entry_size;   // [sample_count]\n    unsigned *timestamp;    // [sample_count]\n    unsigned *duration;     // [sample_count]\n\n    unsigned sample_to_chunk_count;\n    MP4D_sample_to_chunk_t * sample_to_chunk;    // [sample_to_chunk_count]\n\n    unsigned chunk_count;\n    mp4d_size_t * chunk_offset;  // [chunk_count]\n\n} MP4D_track_t;\n\n\ntypedef struct MP4D_demux_tag\n{\n    /************************************************************************/\n    /*                 mandatory public data                                */\n    /************************************************************************/\n    // number of tracks in the movie\n    unsigned track_count;\n\n    // track data (public/private)\n    MP4D_track_t * track;\n\n    /************************************************************************/\n    /*                 informational public data, not needed for decoding   */\n    /************************************************************************/\n    // Movie duration: 64-bit value split into 2 variables\n    unsigned duration_hi;\n    unsigned duration_lo;\n\n    // duration scale: duration = timescale*seconds\n    unsigned timescale;\n\n    // Metadata tag (optional)\n    // Tags provided 'as-is', without any re-encoding\n    struct\n    {\n        unsigned char *title;\n        unsigned char *artist;\n        unsigned char *album;\n        unsigned char *year;\n        unsigned char *comment;\n        unsigned char *genre;\n    } tag;\n\n} MP4D_demux_t;\n\n\n/**\n*   Parse given file as MP4 file.  Allocate and store data indexes.\n*   return 1 on success, 0 on failure\n*   Given file rewind()'ed on return.\n*   The MP4 indexes may be stored at the end of file, so this\n*   function may parse all file, using fseek().\n*   It is guaranteed that function will read/seek the file sequentially,\n*   and will never jump back.\n*/\nint MP4D__open(MP4D_demux_t * mp4, FILE * f);\n\n\n/**\n*   Return position and size for given sample from given track. The 'sample' is a\n*   MP4 term for 'frame'\n*   \n*   frame_bytes [OUT]   - return coded frame size in bytes\n*   timestamp [OUT]     - return frame timestamp (in mp4->timescale units)\n*   duration [OUT]      - return frame duration (in mp4->timescale units)\n*\n*   function return file offset for the frame\n*/\nmp4d_size_t MP4D__frame_offset(const MP4D_demux_t * mp4, unsigned int ntrack, unsigned int nsample, unsigned int * frame_bytes, unsigned * timestamp, unsigned * duration);\n\n\n/**\n*   De-allocated memory\n*/\nvoid MP4D__close(MP4D_demux_t * mp4);\n\n\n/**\n*   Helper functions to parse mp4.track[ntrack].dsi for H.264 SPS/PPS\n*   Return pointer to internal mp4 memory, it must not be free()-ed\n*   \n*   Example: process all SPS in MP4 file:\n*       while (sps = MP4D__read_sps(mp4, num_of_avc_track, sps_count, &sps_bytes))\n*       {\n*           process(sps, sps_bytes);\n*           sps_count++;\n*       }\n*/\nconst unsigned char * MP4D__read_sps(const MP4D_demux_t * mp4, unsigned int ntrack, int nsps, int * sps_bytes);\nconst unsigned char * MP4D__read_pps(const MP4D_demux_t * mp4, unsigned int ntrack, int npps, int * pps_bytes);\n\n\n\n/**\n*   Decode MP4D_track_t::stream_type to ASCII string\n*/\nconst char * MP4D__stream_type_to_ascii(int stream_type);\n\n\n/**\n*   Decode MP4D_track_t::object_type_indication to ASCII string\n*/\nconst char * MP4D__object_type_to_ascii(int object_type_indication);\n\n\n#ifdef __cplusplus\n}\n#endif //__cplusplus\n\n#endif //mp4demux_H_INCLUDED\n"
  },
  {
    "path": "Plugin/Makefile.linux",
    "content": "PLATFORM = Linux\nARCH = x86_64\nTARGET_TYPE = so\n\nCFLAGS = -fPIC -ffunction-sections -fdata-sections\nCXXFLAGS = -fPIC -ffunction-sections -fdata-sections\nLDFLAGS = -shared -Wl,--gc-sections\n\ninclude Common.mk\n"
  },
  {
    "path": "Plugin/Makefile.macos",
    "content": "PLATFORM = macOS\nTARGET_TYPE = dylib\n\nSDK_MIN_VER = 11.0\nARCH_OPT = -arch $(ARCH) -mmacosx-version-min=$(SDK_MIN_VER)\n\nCFLAGS   += $(ARCH_OPT)\nCXXFLAGS += $(ARCH_OPT)\nLDFLAGS  += $(ARCH_OPT) -dynamiclib\n\ninclude Common.mk\n"
  },
  {
    "path": "Plugin/Makefile.windows",
    "content": "PLATFORM = Windows\nARCH = x86_64\nTARGET_TYPE = dll\n\nTOOLCHAIN = $(ARCH)-w64-mingw32\nCC = $(TOOLCHAIN)-gcc-posix\nCXX = $(TOOLCHAIN)-g++-posix\nSTRIP = $(TOOLCHAIN)-strip\n\nLDFLAGS = -shared\nLIBS = -static -Wl,--subsystem,windows\n\ninclude Common.mk\n"
  },
  {
    "path": "Plugin/Snappy/snappy-c.cc",
    "content": "// Copyright 2011 Martin Gieseking <martin.gieseking@uos.de>.\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are\n// met:\n//\n//     * Redistributions of source code must retain the above copyright\n// notice, this list of conditions and the following disclaimer.\n//     * Redistributions in binary form must reproduce the above\n// copyright notice, this list of conditions and the following disclaimer\n// in the documentation and/or other materials provided with the\n// distribution.\n//     * Neither the name of Google Inc. nor the names of its\n// contributors may be used to endorse or promote products derived from\n// this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n// \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n#include \"snappy.h\"\n#include \"snappy-c.h\"\n\nextern \"C\" {\n\nsnappy_status snappy_compress(const char* input,\n                              size_t input_length,\n                              char* compressed,\n                              size_t *compressed_length) {\n  if (*compressed_length < snappy_max_compressed_length(input_length)) {\n    return SNAPPY_BUFFER_TOO_SMALL;\n  }\n  snappy::RawCompress(input, input_length, compressed, compressed_length);\n  return SNAPPY_OK;\n}\n\nsnappy_status snappy_uncompress(const char* compressed,\n                                size_t compressed_length,\n                                char* uncompressed,\n                                size_t* uncompressed_length) {\n  size_t real_uncompressed_length;\n  if (!snappy::GetUncompressedLength(compressed,\n                                     compressed_length,\n                                     &real_uncompressed_length)) {\n    return SNAPPY_INVALID_INPUT;\n  }\n  if (*uncompressed_length < real_uncompressed_length) {\n    return SNAPPY_BUFFER_TOO_SMALL;\n  }\n  if (!snappy::RawUncompress(compressed, compressed_length, uncompressed)) {\n    return SNAPPY_INVALID_INPUT;\n  }\n  *uncompressed_length = real_uncompressed_length;\n  return SNAPPY_OK;\n}\n\nsize_t snappy_max_compressed_length(size_t source_length) {\n  return snappy::MaxCompressedLength(source_length);\n}\n\nsnappy_status snappy_uncompressed_length(const char *compressed,\n                                         size_t compressed_length,\n                                         size_t *result) {\n  if (snappy::GetUncompressedLength(compressed,\n                                    compressed_length,\n                                    result)) {\n    return SNAPPY_OK;\n  } else {\n    return SNAPPY_INVALID_INPUT;\n  }\n}\n\nsnappy_status snappy_validate_compressed_buffer(const char *compressed,\n                                                size_t compressed_length) {\n  if (snappy::IsValidCompressedBuffer(compressed, compressed_length)) {\n    return SNAPPY_OK;\n  } else {\n    return SNAPPY_INVALID_INPUT;\n  }\n}\n\n}  // extern \"C\"\n"
  },
  {
    "path": "Plugin/Snappy/snappy-c.h",
    "content": "/*\n * Copyright 2011 Martin Gieseking <martin.gieseking@uos.de>.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n *     * Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above\n * copyright notice, this list of conditions and the following disclaimer\n * in the documentation and/or other materials provided with the\n * distribution.\n *     * Neither the name of Google Inc. nor the names of its\n * contributors may be used to endorse or promote products derived from\n * this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * Plain C interface (a wrapper around the C++ implementation).\n */\n\n#ifndef THIRD_PARTY_SNAPPY_OPENSOURCE_SNAPPY_C_H_\n#define THIRD_PARTY_SNAPPY_OPENSOURCE_SNAPPY_C_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <stddef.h>\n\n/*\n * Return values; see the documentation for each function to know\n * what each can return.\n */\ntypedef enum {\n  SNAPPY_OK = 0,\n  SNAPPY_INVALID_INPUT = 1,\n  SNAPPY_BUFFER_TOO_SMALL = 2\n} snappy_status;\n\n/*\n * Takes the data stored in \"input[0..input_length-1]\" and stores\n * it in the array pointed to by \"compressed\".\n *\n * <compressed_length> signals the space available in \"compressed\".\n * If it is not at least equal to \"snappy_max_compressed_length(input_length)\",\n * SNAPPY_BUFFER_TOO_SMALL is returned. After successful compression,\n * <compressed_length> contains the true length of the compressed output,\n * and SNAPPY_OK is returned.\n *\n * Example:\n *   size_t output_length = snappy_max_compressed_length(input_length);\n *   char* output = (char*)malloc(output_length);\n *   if (snappy_compress(input, input_length, output, &output_length)\n *       == SNAPPY_OK) {\n *     ... Process(output, output_length) ...\n *   }\n *   free(output);\n */\nsnappy_status snappy_compress(const char* input,\n                              size_t input_length,\n                              char* compressed,\n                              size_t* compressed_length);\n\n/*\n * Given data in \"compressed[0..compressed_length-1]\" generated by\n * calling the snappy_compress routine, this routine stores\n * the uncompressed data to\n *   uncompressed[0..uncompressed_length-1].\n * Returns failure (a value not equal to SNAPPY_OK) if the message\n * is corrupted and could not be decrypted.\n *\n * <uncompressed_length> signals the space available in \"uncompressed\".\n * If it is not at least equal to the value returned by\n * snappy_uncompressed_length for this stream, SNAPPY_BUFFER_TOO_SMALL\n * is returned. After successful decompression, <uncompressed_length>\n * contains the true length of the decompressed output.\n *\n * Example:\n *   size_t output_length;\n *   if (snappy_uncompressed_length(input, input_length, &output_length)\n *       != SNAPPY_OK) {\n *     ... fail ...\n *   }\n *   char* output = (char*)malloc(output_length);\n *   if (snappy_uncompress(input, input_length, output, &output_length)\n *       == SNAPPY_OK) {\n *     ... Process(output, output_length) ...\n *   }\n *   free(output);\n */\nsnappy_status snappy_uncompress(const char* compressed,\n                                size_t compressed_length,\n                                char* uncompressed,\n                                size_t* uncompressed_length);\n\n/*\n * Returns the maximal size of the compressed representation of\n * input data that is \"source_length\" bytes in length.\n */\nsize_t snappy_max_compressed_length(size_t source_length);\n\n/*\n * REQUIRES: \"compressed[]\" was produced by snappy_compress()\n * Returns SNAPPY_OK and stores the length of the uncompressed data in\n * *result normally. Returns SNAPPY_INVALID_INPUT on parsing error.\n * This operation takes O(1) time.\n */\nsnappy_status snappy_uncompressed_length(const char* compressed,\n                                         size_t compressed_length,\n                                         size_t* result);\n\n/*\n * Check if the contents of \"compressed[]\" can be uncompressed successfully.\n * Does not return the uncompressed data; if so, returns SNAPPY_OK,\n * or if not, returns SNAPPY_INVALID_INPUT.\n * Takes time proportional to compressed_length, but is usually at least a\n * factor of four faster than actual decompression.\n */\nsnappy_status snappy_validate_compressed_buffer(const char* compressed,\n                                                size_t compressed_length);\n\n#ifdef __cplusplus\n}  // extern \"C\"\n#endif\n\n#endif  /* THIRD_PARTY_SNAPPY_OPENSOURCE_SNAPPY_C_H_ */\n"
  },
  {
    "path": "Plugin/Snappy/snappy-internal.h",
    "content": "// Copyright 2008 Google Inc. All Rights Reserved.\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are\n// met:\n//\n//     * Redistributions of source code must retain the above copyright\n// notice, this list of conditions and the following disclaimer.\n//     * Redistributions in binary form must reproduce the above\n// copyright notice, this list of conditions and the following disclaimer\n// in the documentation and/or other materials provided with the\n// distribution.\n//     * Neither the name of Google Inc. nor the names of its\n// contributors may be used to endorse or promote products derived from\n// this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n// \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n//\n// Internals shared between the Snappy implementation and its unittest.\n\n#ifndef THIRD_PARTY_SNAPPY_SNAPPY_INTERNAL_H_\n#define THIRD_PARTY_SNAPPY_SNAPPY_INTERNAL_H_\n\n#include <utility>\n\n#include \"snappy-stubs-internal.h\"\n\n#if SNAPPY_HAVE_SSSE3\n// Please do not replace with <x86intrin.h> or with headers that assume more\n// advanced SSE versions without checking with all the OWNERS.\n#include <emmintrin.h>\n#include <tmmintrin.h>\n#endif\n\n#if SNAPPY_HAVE_NEON\n#include <arm_neon.h>\n#endif\n\n#if SNAPPY_RVV_1 || SNAPPY_RVV_0_7\n#define SNAPPY_HAVE_RVV 1\n#include <riscv_vector.h>\n#else\n#define SNAPPY_HAVE_RVV 0\n#endif\n\n#ifdef SNAPPY_RVV_1\n#define VSETVL_E8M2 __riscv_vsetvl_e8m2\n#define VLE8_V_U8M2 __riscv_vle8_v_u8m2\n#define VSE8_V_U8M2 __riscv_vse8_v_u8m2\n#elif SNAPPY_RVV_0_7\n#define VSETVL_E8M2 vsetvl_e8m2\n#define VLE8_V_U8M2 vle8_v_u8m2\n#define VSE8_V_U8M2 vse8_v_u8m2\n#endif\n\n#if SNAPPY_HAVE_SSSE3 || SNAPPY_HAVE_NEON \n#define SNAPPY_HAVE_VECTOR_BYTE_SHUFFLE 1\n#else\n#define SNAPPY_HAVE_VECTOR_BYTE_SHUFFLE 0\n#endif\n\nnamespace snappy {\nnamespace internal {\n\n#if SNAPPY_HAVE_VECTOR_BYTE_SHUFFLE\n#if SNAPPY_HAVE_SSSE3\nusing V128 = __m128i;\n#elif SNAPPY_HAVE_NEON\nusing V128 = uint8x16_t;\n#endif\n \n// Load 128 bits of integer data. `src` must be 16-byte aligned.\ninline V128 V128_Load(const V128* src);\n\n// Load 128 bits of integer data. `src` does not need to be aligned.\ninline V128 V128_LoadU(const V128* src);\n\n// Store 128 bits of integer data. `dst` does not need to be aligned.\ninline void V128_StoreU(V128* dst, V128 val);\n\n// Shuffle packed 8-bit integers using a shuffle mask.\n// Each packed integer in the shuffle mask must be in [0,16).\ninline V128 V128_Shuffle(V128 input, V128 shuffle_mask);\n\n// Constructs V128 with 16 chars |c|.\ninline V128 V128_DupChar(char c);\n\n#if SNAPPY_HAVE_SSSE3\ninline V128 V128_Load(const V128* src) { return _mm_load_si128(src); }\n\ninline V128 V128_LoadU(const V128* src) { return _mm_loadu_si128(src); }\n\ninline void V128_StoreU(V128* dst, V128 val) { _mm_storeu_si128(dst, val); }\n\ninline V128 V128_Shuffle(V128 input, V128 shuffle_mask) {\n  return _mm_shuffle_epi8(input, shuffle_mask);\n}\n\ninline V128 V128_DupChar(char c) { return _mm_set1_epi8(c); }\n\n#elif SNAPPY_HAVE_NEON\ninline V128 V128_Load(const V128* src) {\n  return vld1q_u8(reinterpret_cast<const uint8_t*>(src));\n}\n\ninline V128 V128_LoadU(const V128* src) {\n  return vld1q_u8(reinterpret_cast<const uint8_t*>(src));\n}\n\ninline void V128_StoreU(V128* dst, V128 val) {\n  vst1q_u8(reinterpret_cast<uint8_t*>(dst), val);\n}\n\ninline V128 V128_Shuffle(V128 input, V128 shuffle_mask) {\n  assert(vminvq_u8(shuffle_mask) >= 0 && vmaxvq_u8(shuffle_mask) <= 15);\n  return vqtbl1q_u8(input, shuffle_mask);\n}\n\ninline V128 V128_DupChar(char c) { return vdupq_n_u8(c); }\n\n\n#endif\n#endif  // SNAPPY_HAVE_VECTOR_BYTE_SHUFFLE\n\n// Working memory performs a single allocation to hold all scratch space\n// required for compression.\nclass WorkingMemory {\n public:\n  explicit WorkingMemory(size_t input_size);\n  ~WorkingMemory();\n\n  // Allocates and clears a hash table using memory in \"*this\",\n  // stores the number of buckets in \"*table_size\" and returns a pointer to\n  // the base of the hash table.\n  uint16_t* GetHashTable(size_t fragment_size, int* table_size) const;\n  char* GetScratchInput() const { return input_; }\n  char* GetScratchOutput() const { return output_; }\n\n private:\n  char* mem_;        // the allocated memory, never nullptr\n  size_t size_;      // the size of the allocated memory, never 0\n  uint16_t* table_;  // the pointer to the hashtable\n  char* input_;      // the pointer to the input scratch buffer\n  char* output_;     // the pointer to the output scratch buffer\n\n  // No copying\n  WorkingMemory(const WorkingMemory&);\n  void operator=(const WorkingMemory&);\n};\n\n// Flat array compression that does not emit the \"uncompressed length\"\n// prefix. Compresses \"input\" string to the \"*op\" buffer.\n//\n// REQUIRES: \"input_length <= kBlockSize\"\n// REQUIRES: \"op\" points to an array of memory that is at least\n// \"MaxCompressedLength(input_length)\" in size.\n// REQUIRES: All elements in \"table[0..table_size-1]\" are initialized to zero.\n// REQUIRES: \"table_size\" is a power of two\n//\n// Returns an \"end\" pointer into \"op\" buffer.\n// \"end - op\" is the compressed size of \"input\".\nchar* CompressFragment(const char* input,\n                       size_t input_length,\n                       char* op,\n                       uint16_t* table,\n                       const int table_size);\n\n// Find the largest n such that\n//\n//   s1[0,n-1] == s2[0,n-1]\n//   and n <= (s2_limit - s2).\n//\n// Return make_pair(n, n < 8).\n// Does not read *s2_limit or beyond.\n// Does not read *(s1 + (s2_limit - s2)) or beyond.\n// Requires that s2_limit >= s2.\n//\n// In addition populate *data with the next 5 bytes from the end of the match.\n// This is only done if 8 bytes are available (s2_limit - s2 >= 8). The point is\n// that on some arch's this can be done faster in this routine than subsequent\n// loading from s2 + n.\n//\n// Separate implementation for 64-bit, little-endian cpus.\n// riscv and little-endian cpu choose this routinue can be done faster too.\n#if !SNAPPY_IS_BIG_ENDIAN && \\\n    (defined(__x86_64__) || defined(_M_X64) || defined(ARCH_PPC) || \\\n     defined(ARCH_ARM) || defined(__riscv))\nstatic inline std::pair<size_t, bool> FindMatchLength(const char* s1,\n                                                      const char* s2,\n                                                      const char* s2_limit,\n                                                      uint64_t* data) {\n  assert(s2_limit >= s2);\n  size_t matched = 0;\n\n  // This block isn't necessary for correctness; we could just start looping\n  // immediately.  As an optimization though, it is useful.  It creates some not\n  // uncommon code paths that determine, without extra effort, whether the match\n  // length is less than 8.  In short, we are hoping to avoid a conditional\n  // branch, and perhaps get better code layout from the C++ compiler.\n  if (SNAPPY_PREDICT_TRUE(s2 <= s2_limit - 16)) {\n    uint64_t a1 = UNALIGNED_LOAD64(s1);\n    uint64_t a2 = UNALIGNED_LOAD64(s2);\n    if (SNAPPY_PREDICT_TRUE(a1 != a2)) {\n      // This code is critical for performance. The reason is that it determines\n      // how much to advance `ip` (s2). This obviously depends on both the loads\n      // from the `candidate` (s1) and `ip`. Furthermore the next `candidate`\n      // depends on the advanced `ip` calculated here through a load, hash and\n      // new candidate hash lookup (a lot of cycles). This makes s1 (ie.\n      // `candidate`) the variable that limits throughput. This is the reason we\n      // go through hoops to have this function update `data` for the next iter.\n      // The straightforward code would use *data, given by\n      //\n      // *data = UNALIGNED_LOAD64(s2 + matched_bytes) (Latency of 5 cycles),\n      //\n      // as input for the hash table lookup to find next candidate. However\n      // this forces the load on the data dependency chain of s1, because\n      // matched_bytes directly depends on s1. However matched_bytes is 0..7, so\n      // we can also calculate *data by\n      //\n      // *data = AlignRight(UNALIGNED_LOAD64(s2), UNALIGNED_LOAD64(s2 + 8),\n      //                    matched_bytes);\n      //\n      // The loads do not depend on s1 anymore and are thus off the bottleneck.\n      // The straightforward implementation on x86_64 would be to use\n      //\n      // shrd rax, rdx, cl  (cl being matched_bytes * 8)\n      //\n      // unfortunately shrd with a variable shift has a 4 cycle latency. So this\n      // only wins 1 cycle. The BMI2 shrx instruction is a 1 cycle variable\n      // shift instruction but can only shift 64 bits. If we focus on just\n      // obtaining the least significant 4 bytes, we can obtain this by\n      //\n      // *data = ConditionalMove(matched_bytes < 4, UNALIGNED_LOAD64(s2),\n      //     UNALIGNED_LOAD64(s2 + 4) >> ((matched_bytes & 3) * 8);\n      //\n      // Writen like above this is not a big win, the conditional move would be\n      // a cmp followed by a cmov (2 cycles) followed by a shift (1 cycle).\n      // However matched_bytes < 4 is equal to\n      // static_cast<uint32_t>(xorval) != 0. Writen that way, the conditional\n      // move (2 cycles) can execute in parallel with FindLSBSetNonZero64\n      // (tzcnt), which takes 3 cycles.\n      uint64_t xorval = a1 ^ a2;\n      int shift = Bits::FindLSBSetNonZero64(xorval);\n      size_t matched_bytes = shift >> 3;\n      uint64_t a3 = UNALIGNED_LOAD64(s2 + 4);\n#ifndef __x86_64__\n      a2 = static_cast<uint32_t>(xorval) == 0 ? a3 : a2;\n#else\n      // Ideally this would just be\n      //\n      // a2 = static_cast<uint32_t>(xorval) == 0 ? a3 : a2;\n      //\n      // However clang correctly infers that the above statement participates on\n      // a critical data dependency chain and thus, unfortunately, refuses to\n      // use a conditional move (it's tuned to cut data dependencies). In this\n      // case there is a longer parallel chain anyway AND this will be fairly\n      // unpredictable.\n      asm(\"testl %k2, %k2\\n\\t\"\n          \"cmovzq %1, %0\\n\\t\"\n          : \"+r\"(a2)\n          : \"r\"(a3), \"r\"(xorval)\n          : \"cc\");\n#endif\n      *data = a2 >> (shift & (3 * 8));\n      return std::pair<size_t, bool>(matched_bytes, true);\n    } else {\n      matched = 8;\n      s2 += 8;\n    }\n  }\n  SNAPPY_PREFETCH(s1 + 64);\n  SNAPPY_PREFETCH(s2 + 64);\n\n  // Find out how long the match is. We loop over the data 64 bits at a\n  // time until we find a 64-bit block that doesn't match; then we find\n  // the first non-matching bit and use that to calculate the total\n  // length of the match.\n  while (SNAPPY_PREDICT_TRUE(s2 <= s2_limit - 16)) {\n    uint64_t a1 = UNALIGNED_LOAD64(s1 + matched);\n    uint64_t a2 = UNALIGNED_LOAD64(s2);\n    if (a1 == a2) {\n      s2 += 8;\n      matched += 8;\n    } else {\n      uint64_t xorval = a1 ^ a2;\n      int shift = Bits::FindLSBSetNonZero64(xorval);\n      size_t matched_bytes = shift >> 3;\n      uint64_t a3 = UNALIGNED_LOAD64(s2 + 4);\n#ifndef __x86_64__\n      a2 = static_cast<uint32_t>(xorval) == 0 ? a3 : a2;\n#else\n      asm(\"testl %k2, %k2\\n\\t\"\n          \"cmovzq %1, %0\\n\\t\"\n          : \"+r\"(a2)\n          : \"r\"(a3), \"r\"(xorval)\n          : \"cc\");\n#endif\n      *data = a2 >> (shift & (3 * 8));\n      matched += matched_bytes;\n      assert(matched >= 8);\n      return std::pair<size_t, bool>(matched, false);\n    }\n  }\n  while (SNAPPY_PREDICT_TRUE(s2 < s2_limit)) {\n    if (s1[matched] == *s2) {\n      ++s2;\n      ++matched;\n    } else {\n      if (s2 <= s2_limit - 8) {\n        *data = UNALIGNED_LOAD64(s2);\n      }\n      return std::pair<size_t, bool>(matched, matched < 8);\n    }\n  }\n  return std::pair<size_t, bool>(matched, matched < 8);\n}\n#else\nstatic inline std::pair<size_t, bool> FindMatchLength(const char* s1,\n                                                      const char* s2,\n                                                      const char* s2_limit,\n                                                      uint64_t* data) {\n  // Implementation based on the x86-64 version, above.\n  assert(s2_limit >= s2);\n  int matched = 0;\n\n  while (s2 <= s2_limit - 4 &&\n         UNALIGNED_LOAD32(s2) == UNALIGNED_LOAD32(s1 + matched)) {\n    s2 += 4;\n    matched += 4;\n  }\n  if (LittleEndian::IsLittleEndian() && s2 <= s2_limit - 4) {\n    uint32_t x = UNALIGNED_LOAD32(s2) ^ UNALIGNED_LOAD32(s1 + matched);\n    int matching_bits = Bits::FindLSBSetNonZero(x);\n    matched += matching_bits >> 3;\n    s2 += matching_bits >> 3;\n  } else {\n    while ((s2 < s2_limit) && (s1[matched] == *s2)) {\n      ++s2;\n      ++matched;\n    }\n  }\n  if (s2 <= s2_limit - 8) *data = LittleEndian::Load64(s2);\n  return std::pair<size_t, bool>(matched, matched < 8);\n}\n#endif\n\nstatic inline size_t FindMatchLengthPlain(const char* s1, const char* s2,\n                                          const char* s2_limit) {\n  // Implementation based on the x86-64 version, above.\n  assert(s2_limit >= s2);\n  int matched = 0;\n\n  while (s2 <= s2_limit - 8 &&\n         UNALIGNED_LOAD64(s2) == UNALIGNED_LOAD64(s1 + matched)) {\n    s2 += 8;\n    matched += 8;\n  }\n  if (LittleEndian::IsLittleEndian() && s2 <= s2_limit - 8) {\n    uint64_t x = UNALIGNED_LOAD64(s2) ^ UNALIGNED_LOAD64(s1 + matched);\n    int matching_bits = Bits::FindLSBSetNonZero64(x);\n    matched += matching_bits >> 3;\n    s2 += matching_bits >> 3;\n  } else {\n    while ((s2 < s2_limit) && (s1[matched] == *s2)) {\n      ++s2;\n      ++matched;\n    }\n  }\n  return matched;\n}\n\n// Lookup tables for decompression code.  Give --snappy_dump_decompression_table\n// to the unit test to recompute char_table.\n\nenum {\n  LITERAL = 0,\n  COPY_1_BYTE_OFFSET = 1,  // 3 bit length + 3 bits of offset in opcode\n  COPY_2_BYTE_OFFSET = 2,\n  COPY_4_BYTE_OFFSET = 3\n};\nstatic const int kMaximumTagLength = 5;  // COPY_4_BYTE_OFFSET plus the actual offset.\n\n// Data stored per entry in lookup table:\n//      Range   Bits-used       Description\n//      ------------------------------------\n//      1..64   0..7            Literal/copy length encoded in opcode byte\n//      0..7    8..10           Copy offset encoded in opcode byte / 256\n//      0..4    11..13          Extra bytes after opcode\n//\n// We use eight bits for the length even though 7 would have sufficed\n// because of efficiency reasons:\n//      (1) Extracting a byte is faster than a bit-field\n//      (2) It properly aligns copy offset so we do not need a <<8\nstatic constexpr uint16_t char_table[256] = {\n    // clang-format off\n  0x0001, 0x0804, 0x1001, 0x2001, 0x0002, 0x0805, 0x1002, 0x2002,\n  0x0003, 0x0806, 0x1003, 0x2003, 0x0004, 0x0807, 0x1004, 0x2004,\n  0x0005, 0x0808, 0x1005, 0x2005, 0x0006, 0x0809, 0x1006, 0x2006,\n  0x0007, 0x080a, 0x1007, 0x2007, 0x0008, 0x080b, 0x1008, 0x2008,\n  0x0009, 0x0904, 0x1009, 0x2009, 0x000a, 0x0905, 0x100a, 0x200a,\n  0x000b, 0x0906, 0x100b, 0x200b, 0x000c, 0x0907, 0x100c, 0x200c,\n  0x000d, 0x0908, 0x100d, 0x200d, 0x000e, 0x0909, 0x100e, 0x200e,\n  0x000f, 0x090a, 0x100f, 0x200f, 0x0010, 0x090b, 0x1010, 0x2010,\n  0x0011, 0x0a04, 0x1011, 0x2011, 0x0012, 0x0a05, 0x1012, 0x2012,\n  0x0013, 0x0a06, 0x1013, 0x2013, 0x0014, 0x0a07, 0x1014, 0x2014,\n  0x0015, 0x0a08, 0x1015, 0x2015, 0x0016, 0x0a09, 0x1016, 0x2016,\n  0x0017, 0x0a0a, 0x1017, 0x2017, 0x0018, 0x0a0b, 0x1018, 0x2018,\n  0x0019, 0x0b04, 0x1019, 0x2019, 0x001a, 0x0b05, 0x101a, 0x201a,\n  0x001b, 0x0b06, 0x101b, 0x201b, 0x001c, 0x0b07, 0x101c, 0x201c,\n  0x001d, 0x0b08, 0x101d, 0x201d, 0x001e, 0x0b09, 0x101e, 0x201e,\n  0x001f, 0x0b0a, 0x101f, 0x201f, 0x0020, 0x0b0b, 0x1020, 0x2020,\n  0x0021, 0x0c04, 0x1021, 0x2021, 0x0022, 0x0c05, 0x1022, 0x2022,\n  0x0023, 0x0c06, 0x1023, 0x2023, 0x0024, 0x0c07, 0x1024, 0x2024,\n  0x0025, 0x0c08, 0x1025, 0x2025, 0x0026, 0x0c09, 0x1026, 0x2026,\n  0x0027, 0x0c0a, 0x1027, 0x2027, 0x0028, 0x0c0b, 0x1028, 0x2028,\n  0x0029, 0x0d04, 0x1029, 0x2029, 0x002a, 0x0d05, 0x102a, 0x202a,\n  0x002b, 0x0d06, 0x102b, 0x202b, 0x002c, 0x0d07, 0x102c, 0x202c,\n  0x002d, 0x0d08, 0x102d, 0x202d, 0x002e, 0x0d09, 0x102e, 0x202e,\n  0x002f, 0x0d0a, 0x102f, 0x202f, 0x0030, 0x0d0b, 0x1030, 0x2030,\n  0x0031, 0x0e04, 0x1031, 0x2031, 0x0032, 0x0e05, 0x1032, 0x2032,\n  0x0033, 0x0e06, 0x1033, 0x2033, 0x0034, 0x0e07, 0x1034, 0x2034,\n  0x0035, 0x0e08, 0x1035, 0x2035, 0x0036, 0x0e09, 0x1036, 0x2036,\n  0x0037, 0x0e0a, 0x1037, 0x2037, 0x0038, 0x0e0b, 0x1038, 0x2038,\n  0x0039, 0x0f04, 0x1039, 0x2039, 0x003a, 0x0f05, 0x103a, 0x203a,\n  0x003b, 0x0f06, 0x103b, 0x203b, 0x003c, 0x0f07, 0x103c, 0x203c,\n  0x0801, 0x0f08, 0x103d, 0x203d, 0x1001, 0x0f09, 0x103e, 0x203e,\n  0x1801, 0x0f0a, 0x103f, 0x203f, 0x2001, 0x0f0b, 0x1040, 0x2040,\n    // clang-format on\n};\n\n}  // end namespace internal\n}  // end namespace snappy\n\n#endif  // THIRD_PARTY_SNAPPY_SNAPPY_INTERNAL_H_\n"
  },
  {
    "path": "Plugin/Snappy/snappy-sinksource.cc",
    "content": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are\n// met:\n//\n//     * Redistributions of source code must retain the above copyright\n// notice, this list of conditions and the following disclaimer.\n//     * Redistributions in binary form must reproduce the above\n// copyright notice, this list of conditions and the following disclaimer\n// in the documentation and/or other materials provided with the\n// distribution.\n//     * Neither the name of Google Inc. nor the names of its\n// contributors may be used to endorse or promote products derived from\n// this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n// \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n#include <stddef.h>\n#include <cstring>\n\n#include \"snappy-sinksource.h\"\n\nnamespace snappy {\n\nSource::~Source() = default;\n\nSink::~Sink() = default;\n\nchar* Sink::GetAppendBuffer(size_t length, char* scratch) {\n  // TODO: Switch to [[maybe_unused]] when we can assume C++17.\n  (void)length;\n\n  return scratch;\n}\n\nchar* Sink::GetAppendBufferVariable(\n      size_t min_size, size_t desired_size_hint, char* scratch,\n      size_t scratch_size, size_t* allocated_size) {\n  // TODO: Switch to [[maybe_unused]] when we can assume C++17.\n  (void)min_size;\n  (void)desired_size_hint;\n\n  *allocated_size = scratch_size;\n  return scratch;\n}\n\nvoid Sink::AppendAndTakeOwnership(\n    char* bytes, size_t n,\n    void (*deleter)(void*, const char*, size_t),\n    void *deleter_arg) {\n  Append(bytes, n);\n  (*deleter)(deleter_arg, bytes, n);\n}\n\nByteArraySource::~ByteArraySource() = default;\n\nsize_t ByteArraySource::Available() const { return left_; }\n\nconst char* ByteArraySource::Peek(size_t* len) {\n  *len = left_;\n  return ptr_;\n}\n\nvoid ByteArraySource::Skip(size_t n) {\n  left_ -= n;\n  ptr_ += n;\n}\n\nUncheckedByteArraySink::~UncheckedByteArraySink() { }\n\nvoid UncheckedByteArraySink::Append(const char* data, size_t n) {\n  // Do no copying if the caller filled in the result of GetAppendBuffer()\n  if (data != dest_) {\n    std::memcpy(dest_, data, n);\n  }\n  dest_ += n;\n}\n\nchar* UncheckedByteArraySink::GetAppendBuffer(size_t len, char* scratch) {\n  // TODO: Switch to [[maybe_unused]] when we can assume C++17.\n  (void)len;\n  (void)scratch;\n\n  return dest_;\n}\n\nvoid UncheckedByteArraySink::AppendAndTakeOwnership(\n    char* bytes, size_t n,\n    void (*deleter)(void*, const char*, size_t),\n    void *deleter_arg) {\n  if (bytes != dest_) {\n    std::memcpy(dest_, bytes, n);\n    (*deleter)(deleter_arg, bytes, n);\n  }\n  dest_ += n;\n}\n\nchar* UncheckedByteArraySink::GetAppendBufferVariable(\n      size_t min_size, size_t desired_size_hint, char* scratch,\n      size_t scratch_size, size_t* allocated_size) {\n  // TODO: Switch to [[maybe_unused]] when we can assume C++17.\n  (void)min_size;\n  (void)scratch;\n  (void)scratch_size;\n\n  *allocated_size = desired_size_hint;\n  return dest_;\n}\n\n}  // namespace snappy\n"
  },
  {
    "path": "Plugin/Snappy/snappy-sinksource.h",
    "content": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are\n// met:\n//\n//     * Redistributions of source code must retain the above copyright\n// notice, this list of conditions and the following disclaimer.\n//     * Redistributions in binary form must reproduce the above\n// copyright notice, this list of conditions and the following disclaimer\n// in the documentation and/or other materials provided with the\n// distribution.\n//     * Neither the name of Google Inc. nor the names of its\n// contributors may be used to endorse or promote products derived from\n// this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n// \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n#ifndef THIRD_PARTY_SNAPPY_SNAPPY_SINKSOURCE_H_\n#define THIRD_PARTY_SNAPPY_SNAPPY_SINKSOURCE_H_\n\n#include <stddef.h>\n\nnamespace snappy {\n\n// A Sink is an interface that consumes a sequence of bytes.\nclass Sink {\n public:\n  Sink() { }\n  virtual ~Sink();\n\n  // Append \"bytes[0,n-1]\" to this.\n  virtual void Append(const char* bytes, size_t n) = 0;\n\n  // Returns a writable buffer of the specified length for appending.\n  // May return a pointer to the caller-owned scratch buffer which\n  // must have at least the indicated length.  The returned buffer is\n  // only valid until the next operation on this Sink.\n  //\n  // After writing at most \"length\" bytes, call Append() with the\n  // pointer returned from this function and the number of bytes\n  // written.  Many Append() implementations will avoid copying\n  // bytes if this function returned an internal buffer.\n  //\n  // If a non-scratch buffer is returned, the caller may only pass a\n  // prefix of it to Append().  That is, it is not correct to pass an\n  // interior pointer of the returned array to Append().\n  //\n  // The default implementation always returns the scratch buffer.\n  virtual char* GetAppendBuffer(size_t length, char* scratch);\n\n  // For higher performance, Sink implementations can provide custom\n  // AppendAndTakeOwnership() and GetAppendBufferVariable() methods.\n  // These methods can reduce the number of copies done during\n  // compression/decompression.\n\n  // Append \"bytes[0,n-1] to the sink. Takes ownership of \"bytes\"\n  // and calls the deleter function as (*deleter)(deleter_arg, bytes, n)\n  // to free the buffer. deleter function must be non NULL.\n  //\n  // The default implementation just calls Append and frees \"bytes\".\n  // Other implementations may avoid a copy while appending the buffer.\n  virtual void AppendAndTakeOwnership(\n      char* bytes, size_t n, void (*deleter)(void*, const char*, size_t),\n      void *deleter_arg);\n\n  // Returns a writable buffer for appending and writes the buffer's capacity to\n  // *allocated_size. Guarantees *allocated_size >= min_size.\n  // May return a pointer to the caller-owned scratch buffer which must have\n  // scratch_size >= min_size.\n  //\n  // The returned buffer is only valid until the next operation\n  // on this ByteSink.\n  //\n  // After writing at most *allocated_size bytes, call Append() with the\n  // pointer returned from this function and the number of bytes written.\n  // Many Append() implementations will avoid copying bytes if this function\n  // returned an internal buffer.\n  //\n  // If the sink implementation allocates or reallocates an internal buffer,\n  // it should use the desired_size_hint if appropriate. If a caller cannot\n  // provide a reasonable guess at the desired capacity, it should set\n  // desired_size_hint = 0.\n  //\n  // If a non-scratch buffer is returned, the caller may only pass\n  // a prefix to it to Append(). That is, it is not correct to pass an\n  // interior pointer to Append().\n  //\n  // The default implementation always returns the scratch buffer.\n  virtual char* GetAppendBufferVariable(\n      size_t min_size, size_t desired_size_hint, char* scratch,\n      size_t scratch_size, size_t* allocated_size);\n\n private:\n  // No copying\n  Sink(const Sink&);\n  void operator=(const Sink&);\n};\n\n// A Source is an interface that yields a sequence of bytes\nclass Source {\n public:\n  Source() { }\n  virtual ~Source();\n\n  // Return the number of bytes left to read from the source\n  virtual size_t Available() const = 0;\n\n  // Peek at the next flat region of the source.  Does not reposition\n  // the source.  The returned region is empty iff Available()==0.\n  //\n  // Returns a pointer to the beginning of the region and store its\n  // length in *len.\n  //\n  // The returned region is valid until the next call to Skip() or\n  // until this object is destroyed, whichever occurs first.\n  //\n  // The returned region may be larger than Available() (for example\n  // if this ByteSource is a view on a substring of a larger source).\n  // The caller is responsible for ensuring that it only reads the\n  // Available() bytes.\n  virtual const char* Peek(size_t* len) = 0;\n\n  // Skip the next n bytes.  Invalidates any buffer returned by\n  // a previous call to Peek().\n  // REQUIRES: Available() >= n\n  virtual void Skip(size_t n) = 0;\n\n private:\n  // No copying\n  Source(const Source&);\n  void operator=(const Source&);\n};\n\n// A Source implementation that yields the contents of a flat array\nclass ByteArraySource : public Source {\n public:\n  ByteArraySource(const char* p, size_t n) : ptr_(p), left_(n) { }\n  ~ByteArraySource() override;\n  size_t Available() const override;\n  const char* Peek(size_t* len) override;\n  void Skip(size_t n) override;\n private:\n  const char* ptr_;\n  size_t left_;\n};\n\n// A Sink implementation that writes to a flat array without any bound checks.\nclass UncheckedByteArraySink : public Sink {\n public:\n  explicit UncheckedByteArraySink(char* dest) : dest_(dest) { }\n  ~UncheckedByteArraySink() override;\n  void Append(const char* data, size_t n) override;\n  char* GetAppendBuffer(size_t len, char* scratch) override;\n  char* GetAppendBufferVariable(\n      size_t min_size, size_t desired_size_hint, char* scratch,\n      size_t scratch_size, size_t* allocated_size) override;\n  void AppendAndTakeOwnership(\n      char* bytes, size_t n, void (*deleter)(void*, const char*, size_t),\n      void *deleter_arg) override;\n\n  // Return the current output pointer so that a caller can see how\n  // many bytes were produced.\n  // Note: this is not a Sink method.\n  char* CurrentDestination() const { return dest_; }\n private:\n  char* dest_;\n};\n\n}  // namespace snappy\n\n#endif  // THIRD_PARTY_SNAPPY_SNAPPY_SINKSOURCE_H_\n"
  },
  {
    "path": "Plugin/Snappy/snappy-stubs-internal.cc",
    "content": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are\n// met:\n//\n//     * Redistributions of source code must retain the above copyright\n// notice, this list of conditions and the following disclaimer.\n//     * Redistributions in binary form must reproduce the above\n// copyright notice, this list of conditions and the following disclaimer\n// in the documentation and/or other materials provided with the\n// distribution.\n//     * Neither the name of Google Inc. nor the names of its\n// contributors may be used to endorse or promote products derived from\n// this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n// \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n#include <algorithm>\n#include <string>\n\n#include \"snappy-stubs-internal.h\"\n\nnamespace snappy {\n\nvoid Varint::Append32(std::string* s, uint32_t value) {\n  char buf[Varint::kMax32];\n  const char* p = Varint::Encode32(buf, value);\n  s->append(buf, p - buf);\n}\n\n}  // namespace snappy\n"
  },
  {
    "path": "Plugin/Snappy/snappy-stubs-internal.h",
    "content": "// Copyright 2011 Google Inc. All Rights Reserved.\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are\n// met:\n//\n//     * Redistributions of source code must retain the above copyright\n// notice, this list of conditions and the following disclaimer.\n//     * Redistributions in binary form must reproduce the above\n// copyright notice, this list of conditions and the following disclaimer\n// in the documentation and/or other materials provided with the\n// distribution.\n//     * Neither the name of Google Inc. nor the names of its\n// contributors may be used to endorse or promote products derived from\n// this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n// \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n//\n// Various stubs for the open-source version of Snappy.\n\n#ifndef THIRD_PARTY_SNAPPY_OPENSOURCE_SNAPPY_STUBS_INTERNAL_H_\n#define THIRD_PARTY_SNAPPY_OPENSOURCE_SNAPPY_STUBS_INTERNAL_H_\n\n#if HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <stdint.h>\n\n#include <cassert>\n#include <cstdlib>\n#include <cstring>\n#include <limits>\n#include <string>\n\n#if HAVE_SYS_MMAN_H\n#include <sys/mman.h>\n#endif\n\n#if HAVE_UNISTD_H\n#include <unistd.h>\n#endif\n\n#if defined(_MSC_VER)\n#include <intrin.h>\n#endif  // defined(_MSC_VER)\n\n#ifndef __has_feature\n#define __has_feature(x) 0\n#endif\n\n#if __has_feature(memory_sanitizer)\n#include <sanitizer/msan_interface.h>\n#define SNAPPY_ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \\\n    __msan_unpoison((address), (size))\n#else\n#define SNAPPY_ANNOTATE_MEMORY_IS_INITIALIZED(address, size) /* empty */\n#endif  // __has_feature(memory_sanitizer)\n\n#include \"snappy-stubs-public.h\"\n\n// Used to enable 64-bit optimized versions of some routines.\n#if defined(__PPC64__) || defined(__powerpc64__)\n#define ARCH_PPC 1\n#elif defined(__aarch64__) || defined(_M_ARM64)\n#define ARCH_ARM 1\n#endif\n\n// Needed by OS X, among others.\n#ifndef MAP_ANONYMOUS\n#define MAP_ANONYMOUS MAP_ANON\n#endif\n\n// The size of an array, if known at compile-time.\n// Will give unexpected results if used on a pointer.\n// We undefine it first, since some compilers already have a definition.\n#ifdef ARRAYSIZE\n#undef ARRAYSIZE\n#endif\n#define ARRAYSIZE(a) int{sizeof(a) / sizeof(*(a))}\n\n// Static prediction hints.\n#if HAVE_BUILTIN_EXPECT\n#define SNAPPY_PREDICT_FALSE(x) (__builtin_expect(x, 0))\n#define SNAPPY_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))\n#else\n#define SNAPPY_PREDICT_FALSE(x) x\n#define SNAPPY_PREDICT_TRUE(x) x\n#endif  // HAVE_BUILTIN_EXPECT\n\n// Inlining hints.\n#if HAVE_ATTRIBUTE_ALWAYS_INLINE\n#define SNAPPY_ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline))\n#else\n#define SNAPPY_ATTRIBUTE_ALWAYS_INLINE\n#endif  // HAVE_ATTRIBUTE_ALWAYS_INLINE\n\n#if HAVE_BUILTIN_PREFETCH\n#define SNAPPY_PREFETCH(ptr) __builtin_prefetch(ptr, 0, 3)\n#else\n#define SNAPPY_PREFETCH(ptr) (void)(ptr)\n#endif\n\n// Stubbed version of ABSL_FLAG.\n//\n// In the open source version, flags can only be changed at compile time.\n#define SNAPPY_FLAG(flag_type, flag_name, default_value, help) \\\n  flag_type FLAGS_ ## flag_name = default_value\n\nnamespace snappy {\n\n// Stubbed version of absl::GetFlag().\ntemplate <typename T>\ninline T GetFlag(T flag) { return flag; }\n\nstatic const uint32_t kuint32max = std::numeric_limits<uint32_t>::max();\nstatic const int64_t kint64max = std::numeric_limits<int64_t>::max();\n\n// Potentially unaligned loads and stores.\n\ninline uint16_t UNALIGNED_LOAD16(const void *p) {\n  // Compiles to a single movzx/ldrh on clang/gcc/msvc.\n  uint16_t v;\n  std::memcpy(&v, p, sizeof(v));\n  return v;\n}\n\ninline uint32_t UNALIGNED_LOAD32(const void *p) {\n  // Compiles to a single mov/ldr on clang/gcc/msvc.\n  uint32_t v;\n  std::memcpy(&v, p, sizeof(v));\n  return v;\n}\n\ninline uint64_t UNALIGNED_LOAD64(const void *p) {\n  // Compiles to a single mov/ldr on clang/gcc/msvc.\n  uint64_t v;\n  std::memcpy(&v, p, sizeof(v));\n  return v;\n}\n\ninline void UNALIGNED_STORE16(void *p, uint16_t v) {\n  // Compiles to a single mov/strh on clang/gcc/msvc.\n  std::memcpy(p, &v, sizeof(v));\n}\n\ninline void UNALIGNED_STORE32(void *p, uint32_t v) {\n  // Compiles to a single mov/str on clang/gcc/msvc.\n  std::memcpy(p, &v, sizeof(v));\n}\n\ninline void UNALIGNED_STORE64(void *p, uint64_t v) {\n  // Compiles to a single mov/str on clang/gcc/msvc.\n  std::memcpy(p, &v, sizeof(v));\n}\n\n// Convert to little-endian storage, opposite of network format.\n// Convert x from host to little endian: x = LittleEndian.FromHost(x);\n// convert x from little endian to host: x = LittleEndian.ToHost(x);\n//\n//  Store values into unaligned memory converting to little endian order:\n//    LittleEndian.Store16(p, x);\n//\n//  Load unaligned values stored in little endian converting to host order:\n//    x = LittleEndian.Load16(p);\nclass LittleEndian {\n public:\n  // Functions to do unaligned loads and stores in little-endian order.\n  static inline uint16_t Load16(const void *ptr) {\n    // Compiles to a single mov/str on recent clang and gcc.\n#if SNAPPY_IS_BIG_ENDIAN\n    const uint8_t* const buffer = reinterpret_cast<const uint8_t*>(ptr);\n    return (static_cast<uint16_t>(buffer[0])) |\n            (static_cast<uint16_t>(buffer[1]) << 8);\n#else\n    // memcpy() turns into a single instruction early in the optimization\n    // pipeline (relatively to a series of byte accesses). So, using memcpy\n    // instead of byte accesses may lead to better decisions in more stages of\n    // the optimization pipeline.\n    uint16_t value;\n    std::memcpy(&value, ptr, 2);\n    return value;\n#endif\n  }\n\n  static inline uint32_t Load32(const void *ptr) {\n    // Compiles to a single mov/str on recent clang and gcc.\n#if SNAPPY_IS_BIG_ENDIAN\n    const uint8_t* const buffer = reinterpret_cast<const uint8_t*>(ptr);\n    return (static_cast<uint32_t>(buffer[0])) |\n            (static_cast<uint32_t>(buffer[1]) << 8) |\n            (static_cast<uint32_t>(buffer[2]) << 16) |\n            (static_cast<uint32_t>(buffer[3]) << 24);\n#else\n    // See Load16() for the rationale of using memcpy().\n    uint32_t value;\n    std::memcpy(&value, ptr, 4);\n    return value;\n#endif\n  }\n\n  static inline uint64_t Load64(const void *ptr) {\n    // Compiles to a single mov/str on recent clang and gcc.\n#if SNAPPY_IS_BIG_ENDIAN\n    const uint8_t* const buffer = reinterpret_cast<const uint8_t*>(ptr);\n    return (static_cast<uint64_t>(buffer[0])) |\n            (static_cast<uint64_t>(buffer[1]) << 8) |\n            (static_cast<uint64_t>(buffer[2]) << 16) |\n            (static_cast<uint64_t>(buffer[3]) << 24) |\n            (static_cast<uint64_t>(buffer[4]) << 32) |\n            (static_cast<uint64_t>(buffer[5]) << 40) |\n            (static_cast<uint64_t>(buffer[6]) << 48) |\n            (static_cast<uint64_t>(buffer[7]) << 56);\n#else\n    // See Load16() for the rationale of using memcpy().\n    uint64_t value;\n    std::memcpy(&value, ptr, 8);\n    return value;\n#endif\n  }\n\n  static inline void Store16(void *dst, uint16_t value) {\n    // Compiles to a single mov/str on recent clang and gcc.\n#if SNAPPY_IS_BIG_ENDIAN\n    uint8_t* const buffer = reinterpret_cast<uint8_t*>(dst);\n    buffer[0] = static_cast<uint8_t>(value);\n    buffer[1] = static_cast<uint8_t>(value >> 8);\n#else\n    // See Load16() for the rationale of using memcpy().\n    std::memcpy(dst, &value, 2);\n#endif\n  }\n\n  static void Store32(void *dst, uint32_t value) {\n    // Compiles to a single mov/str on recent clang and gcc.\n#if SNAPPY_IS_BIG_ENDIAN\n    uint8_t* const buffer = reinterpret_cast<uint8_t*>(dst);\n    buffer[0] = static_cast<uint8_t>(value);\n    buffer[1] = static_cast<uint8_t>(value >> 8);\n    buffer[2] = static_cast<uint8_t>(value >> 16);\n    buffer[3] = static_cast<uint8_t>(value >> 24);\n#else\n    // See Load16() for the rationale of using memcpy().\n    std::memcpy(dst, &value, 4);\n#endif\n  }\n\n  static void Store64(void* dst, uint64_t value) {\n    // Compiles to a single mov/str on recent clang and gcc.\n#if SNAPPY_IS_BIG_ENDIAN\n    uint8_t* const buffer = reinterpret_cast<uint8_t*>(dst);\n    buffer[0] = static_cast<uint8_t>(value);\n    buffer[1] = static_cast<uint8_t>(value >> 8);\n    buffer[2] = static_cast<uint8_t>(value >> 16);\n    buffer[3] = static_cast<uint8_t>(value >> 24);\n    buffer[4] = static_cast<uint8_t>(value >> 32);\n    buffer[5] = static_cast<uint8_t>(value >> 40);\n    buffer[6] = static_cast<uint8_t>(value >> 48);\n    buffer[7] = static_cast<uint8_t>(value >> 56);\n#else\n    // See Load16() for the rationale of using memcpy().\n    std::memcpy(dst, &value, 8);\n#endif\n  }\n\n  static inline constexpr bool IsLittleEndian() {\n#if SNAPPY_IS_BIG_ENDIAN\n    return false;\n#else\n    return true;\n#endif  // SNAPPY_IS_BIG_ENDIAN\n  }\n};\n\n// Some bit-manipulation functions.\nclass Bits {\n public:\n  // Return floor(log2(n)) for positive integer n.\n  static int Log2FloorNonZero(uint32_t n);\n\n  // Return floor(log2(n)) for positive integer n.  Returns -1 iff n == 0.\n  static int Log2Floor(uint32_t n);\n\n  // Return the first set least / most significant bit, 0-indexed.  Returns an\n  // undefined value if n == 0.  FindLSBSetNonZero() is similar to ffs() except\n  // that it's 0-indexed.\n  static int FindLSBSetNonZero(uint32_t n);\n\n  static int FindLSBSetNonZero64(uint64_t n);\n\n private:\n  // No copying\n  Bits(const Bits&);\n  void operator=(const Bits&);\n};\n\n// In RISC-V,  CLZ  is supported by instructions from the ZBB bit-manipulation extension.\n#if HAVE_BUILTIN_CTZ\ninline int Bits::Log2FloorNonZero(uint32_t n) {\n  assert(n != 0);\n  // (31 ^ x) is equivalent to (31 - x) for x in [0, 31]. An easy proof\n  // represents subtraction in base 2 and observes that there's no carry.\n  //\n  // GCC and Clang represent __builtin_clz on x86 as 31 ^ _bit_scan_reverse(x).\n  // Using \"31 ^\" here instead of \"31 -\" allows the optimizer to strip the\n  // function body down to _bit_scan_reverse(x).\n  return 31 ^ __builtin_clz(n);\n}\n\ninline int Bits::Log2Floor(uint32_t n) {\n  return (n == 0) ? -1 : Bits::Log2FloorNonZero(n);\n}\n\ninline int Bits::FindLSBSetNonZero(uint32_t n) {\n  assert(n != 0);\n  return __builtin_ctz(n);\n}\n\n#elif defined(_MSC_VER)\n\ninline int Bits::Log2FloorNonZero(uint32_t n) {\n  assert(n != 0);\n  // NOLINTNEXTLINE(runtime/int): The MSVC intrinsic demands unsigned long.\n  unsigned long where;\n  _BitScanReverse(&where, n);\n  return static_cast<int>(where);\n}\n\ninline int Bits::Log2Floor(uint32_t n) {\n  // NOLINTNEXTLINE(runtime/int): The MSVC intrinsic demands unsigned long.\n  unsigned long where;\n  if (_BitScanReverse(&where, n))\n    return static_cast<int>(where);\n  return -1;\n}\n\ninline int Bits::FindLSBSetNonZero(uint32_t n) {\n  assert(n != 0);\n  // NOLINTNEXTLINE(runtime/int): The MSVC intrinsic demands unsigned long.\n  unsigned long where;\n  if (_BitScanForward(&where, n))\n    return static_cast<int>(where);\n  return 32;\n}\n\n#else  // Portable versions.\n\ninline int Bits::Log2FloorNonZero(uint32_t n) {\n  assert(n != 0);\n\n  int log = 0;\n  uint32_t value = n;\n  for (int i = 4; i >= 0; --i) {\n    int shift = (1 << i);\n    uint32_t x = value >> shift;\n    if (x != 0) {\n      value = x;\n      log += shift;\n    }\n  }\n  assert(value == 1);\n  return log;\n}\n\ninline int Bits::Log2Floor(uint32_t n) {\n  return (n == 0) ? -1 : Bits::Log2FloorNonZero(n);\n}\n\ninline int Bits::FindLSBSetNonZero(uint32_t n) {\n  assert(n != 0);\n\n  int rc = 31;\n  for (int i = 4, shift = 1 << 4; i >= 0; --i) {\n    const uint32_t x = n << shift;\n    if (x != 0) {\n      n = x;\n      rc -= shift;\n    }\n    shift >>= 1;\n  }\n  return rc;\n}\n\n#endif  // End portable versions.\n\n// In RISC-V,  CLZ  is supported by instructions from the ZBB bit-manipulation extension.\n#if HAVE_BUILTIN_CTZ\n\ninline int Bits::FindLSBSetNonZero64(uint64_t n) {\n  assert(n != 0);\n  return __builtin_ctzll(n);\n}\n\n#elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64))\n// _BitScanForward64() is only available on x64 and ARM64.\n\ninline int Bits::FindLSBSetNonZero64(uint64_t n) {\n  assert(n != 0);\n  // NOLINTNEXTLINE(runtime/int): The MSVC intrinsic demands unsigned long.\n  unsigned long where;\n  if (_BitScanForward64(&where, n))\n    return static_cast<int>(where);\n  return 64;\n}\n\n#else  // Portable version.\n\n// FindLSBSetNonZero64() is defined in terms of FindLSBSetNonZero().\ninline int Bits::FindLSBSetNonZero64(uint64_t n) {\n  assert(n != 0);\n\n  const uint32_t bottombits = static_cast<uint32_t>(n);\n  if (bottombits == 0) {\n    // Bottom bits are zero, so scan the top bits.\n    return 32 + FindLSBSetNonZero(static_cast<uint32_t>(n >> 32));\n  } else {\n    return FindLSBSetNonZero(bottombits);\n  }\n}\n\n#endif  // HAVE_BUILTIN_CTZ\n\n// Variable-length integer encoding.\nclass Varint {\n public:\n  // Maximum lengths of varint encoding of uint32_t.\n  static const int kMax32 = 5;\n\n  // Attempts to parse a varint32 from a prefix of the bytes in [ptr,limit-1].\n  // Never reads a character at or beyond limit.  If a valid/terminated varint32\n  // was found in the range, stores it in *OUTPUT and returns a pointer just\n  // past the last byte of the varint32. Else returns NULL.  On success,\n  // \"result <= limit\".\n  static const char* Parse32WithLimit(const char* ptr, const char* limit,\n                                      uint32_t* OUTPUT);\n\n  // REQUIRES   \"ptr\" points to a buffer of length sufficient to hold \"v\".\n  // EFFECTS    Encodes \"v\" into \"ptr\" and returns a pointer to the\n  //            byte just past the last encoded byte.\n  static char* Encode32(char* ptr, uint32_t v);\n\n  // EFFECTS    Appends the varint representation of \"value\" to \"*s\".\n  static void Append32(std::string* s, uint32_t value);\n};\n\ninline const char* Varint::Parse32WithLimit(const char* p,\n                                            const char* l,\n                                            uint32_t* OUTPUT) {\n  const unsigned char* ptr = reinterpret_cast<const unsigned char*>(p);\n  const unsigned char* limit = reinterpret_cast<const unsigned char*>(l);\n  uint32_t b, result;\n  if (ptr >= limit) return NULL;\n  b = *(ptr++); result = b & 127;          if (b < 128) goto done;\n  if (ptr >= limit) return NULL;\n  b = *(ptr++); result |= (b & 127) <<  7; if (b < 128) goto done;\n  if (ptr >= limit) return NULL;\n  b = *(ptr++); result |= (b & 127) << 14; if (b < 128) goto done;\n  if (ptr >= limit) return NULL;\n  b = *(ptr++); result |= (b & 127) << 21; if (b < 128) goto done;\n  if (ptr >= limit) return NULL;\n  b = *(ptr++); result |= (b & 127) << 28; if (b < 16) goto done;\n  return NULL;       // Value is too long to be a varint32\n done:\n  *OUTPUT = result;\n  return reinterpret_cast<const char*>(ptr);\n}\n\ninline char* Varint::Encode32(char* sptr, uint32_t v) {\n  // Operate on characters as unsigneds\n  uint8_t* ptr = reinterpret_cast<uint8_t*>(sptr);\n  static const uint8_t B = 128;\n  if (v < (1 << 7)) {\n    *(ptr++) = static_cast<uint8_t>(v);\n  } else if (v < (1 << 14)) {\n    *(ptr++) = static_cast<uint8_t>(v | B);\n    *(ptr++) = static_cast<uint8_t>(v >> 7);\n  } else if (v < (1 << 21)) {\n    *(ptr++) = static_cast<uint8_t>(v | B);\n    *(ptr++) = static_cast<uint8_t>((v >> 7) | B);\n    *(ptr++) = static_cast<uint8_t>(v >> 14);\n  } else if (v < (1 << 28)) {\n    *(ptr++) = static_cast<uint8_t>(v | B);\n    *(ptr++) = static_cast<uint8_t>((v >> 7) | B);\n    *(ptr++) = static_cast<uint8_t>((v >> 14) | B);\n    *(ptr++) = static_cast<uint8_t>(v >> 21);\n  } else {\n    *(ptr++) = static_cast<uint8_t>(v | B);\n    *(ptr++) = static_cast<uint8_t>((v>>7) | B);\n    *(ptr++) = static_cast<uint8_t>((v>>14) | B);\n    *(ptr++) = static_cast<uint8_t>((v>>21) | B);\n    *(ptr++) = static_cast<uint8_t>(v >> 28);\n  }\n  return reinterpret_cast<char*>(ptr);\n}\n\n// If you know the internal layout of the std::string in use, you can\n// replace this function with one that resizes the string without\n// filling the new space with zeros (if applicable) --\n// it will be non-portable but faster.\ninline void STLStringResizeUninitialized(std::string* s, size_t new_size) {\n  s->resize(new_size);\n}\n\n// Return a mutable char* pointing to a string's internal buffer,\n// which may not be null-terminated. Writing through this pointer will\n// modify the string.\n//\n// string_as_array(&str)[i] is valid for 0 <= i < str.size() until the\n// next call to a string method that invalidates iterators.\n//\n// As of 2006-04, there is no standard-blessed way of getting a\n// mutable reference to a string's internal buffer. However, issue 530\n// (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-defects.html#530)\n// proposes this as the method. It will officially be part of the standard\n// for C++0x. This should already work on all current implementations.\ninline char* string_as_array(std::string* str) {\n  return str->empty() ? NULL : &*str->begin();\n}\n\n}  // namespace snappy\n\n#endif  // THIRD_PARTY_SNAPPY_OPENSOURCE_SNAPPY_STUBS_INTERNAL_H_\n"
  },
  {
    "path": "Plugin/Snappy/snappy-stubs-public.h",
    "content": "// Copyright 2011 Google Inc. All Rights Reserved.\n// Author: sesse@google.com (Steinar H. Gunderson)\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are\n// met:\n//\n//     * Redistributions of source code must retain the above copyright\n// notice, this list of conditions and the following disclaimer.\n//     * Redistributions in binary form must reproduce the above\n// copyright notice, this list of conditions and the following disclaimer\n// in the documentation and/or other materials provided with the\n// distribution.\n//     * Neither the name of Google Inc. nor the names of its\n// contributors may be used to endorse or promote products derived from\n// this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n// \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n//\n// Various type stubs for the open-source version of Snappy.\n//\n// This file cannot include config.h, as it is included from snappy.h,\n// which is a public header. Instead, snappy-stubs-public.h is generated by\n// from snappy-stubs-public.h.in at configure time.\n\n#ifndef THIRD_PARTY_SNAPPY_OPENSOURCE_SNAPPY_STUBS_PUBLIC_H_\n#define THIRD_PARTY_SNAPPY_OPENSOURCE_SNAPPY_STUBS_PUBLIC_H_\n\n#include <cstddef>\n#include <cstdint>\n#include <string>\n\n#if 0  // HAVE_SYS_UIO_H\n#include <sys/uio.h>\n#endif  // HAVE_SYS_UIO_H\n\n#define SNAPPY_MAJOR 1\n#define SNAPPY_MINOR 1\n#define SNAPPY_PATCHLEVEL 7\n#define SNAPPY_VERSION \\\n    ((SNAPPY_MAJOR << 16) | (SNAPPY_MINOR << 8) | SNAPPY_PATCHLEVEL)\n\nnamespace snappy {\n\nusing int8 = std::int8_t;\nusing uint8 = std::uint8_t;\nusing int16 = std::int16_t;\nusing uint16 = std::uint16_t;\nusing int32 = std::int32_t;\nusing uint32 = std::uint32_t;\nusing int64 = std::int64_t;\nusing uint64 = std::uint64_t;\n\nusing string = std::string;\n\n#if 1  // !HAVE_SYS_UIO_H\n// Windows does not have an iovec type, yet the concept is universally useful.\n// It is simple to define it ourselves, so we put it inside our own namespace.\nstruct iovec {\n  void* iov_base;\n  size_t iov_len;\n};\n#endif  // !HAVE_SYS_UIO_H\n\n}  // namespace snappy\n\n#endif  // THIRD_PARTY_SNAPPY_OPENSOURCE_SNAPPY_STUBS_PUBLIC_H_\n"
  },
  {
    "path": "Plugin/Snappy/snappy.cc",
    "content": "// Copyright 2005 Google Inc. All Rights Reserved.\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are\n// met:\n//\n//     * Redistributions of source code must retain the above copyright\n// notice, this list of conditions and the following disclaimer.\n//     * Redistributions in binary form must reproduce the above\n// copyright notice, this list of conditions and the following disclaimer\n// in the documentation and/or other materials provided with the\n// distribution.\n//     * Neither the name of Google Inc. nor the names of its\n// contributors may be used to endorse or promote products derived from\n// this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n// \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n#include \"snappy-internal.h\"\n#include \"snappy-sinksource.h\"\n#include \"snappy.h\"\n#if !defined(SNAPPY_HAVE_BMI2)\n// __BMI2__ is defined by GCC and Clang. Visual Studio doesn't target BMI2\n// specifically, but it does define __AVX2__ when AVX2 support is available.\n// Fortunately, AVX2 was introduced in Haswell, just like BMI2.\n//\n// BMI2 is not defined as a subset of AVX2 (unlike SSSE3 and AVX above). So,\n// GCC and Clang can build code with AVX2 enabled but BMI2 disabled, in which\n// case issuing BMI2 instructions results in a compiler error.\n#if defined(__BMI2__) || (defined(_MSC_VER) && defined(__AVX2__))\n#define SNAPPY_HAVE_BMI2 1\n#else\n#define SNAPPY_HAVE_BMI2 0\n#endif\n#endif  // !defined(SNAPPY_HAVE_BMI2)\n\n#if !defined(SNAPPY_HAVE_X86_CRC32)\n#if defined(__SSE4_2__)\n#define SNAPPY_HAVE_X86_CRC32 1\n#else\n#define SNAPPY_HAVE_X86_CRC32 0\n#endif\n#endif  // !defined(SNAPPY_HAVE_X86_CRC32)\n\n#if !defined(SNAPPY_HAVE_NEON_CRC32)\n#if SNAPPY_HAVE_NEON && defined(__ARM_FEATURE_CRC32)\n#define SNAPPY_HAVE_NEON_CRC32 1\n#else\n#define SNAPPY_HAVE_NEON_CRC32 0\n#endif\n#endif  // !defined(SNAPPY_HAVE_NEON_CRC32)\n\n#if SNAPPY_HAVE_BMI2 || SNAPPY_HAVE_X86_CRC32\n// Please do not replace with <x86intrin.h>. or with headers that assume more\n// advanced SSE versions without checking with all the OWNERS.\n#include <immintrin.h>\n#elif SNAPPY_HAVE_NEON_CRC32\n#include <arm_acle.h>\n#endif\n\n#include <algorithm>\n#include <array>\n#include <cstddef>\n#include <cstdint>\n#include <cstdio>\n#include <cstring>\n#include <functional>\n#include <memory>\n#include <string>\n#include <utility>\n#include <vector>\n\nnamespace snappy {\n\nnamespace {\n\n// The amount of slop bytes writers are using for unconditional copies.\nconstexpr int kSlopBytes = 64;\n\nusing internal::char_table;\nusing internal::COPY_1_BYTE_OFFSET;\nusing internal::COPY_2_BYTE_OFFSET;\nusing internal::COPY_4_BYTE_OFFSET;\nusing internal::kMaximumTagLength;\nusing internal::LITERAL;\n#if SNAPPY_HAVE_VECTOR_BYTE_SHUFFLE\nusing internal::V128;\nusing internal::V128_Load;\nusing internal::V128_LoadU;\nusing internal::V128_Shuffle;\nusing internal::V128_StoreU;\nusing internal::V128_DupChar;\n#endif\n\n// We translate the information encoded in a tag through a lookup table to a\n// format that requires fewer instructions to decode. Effectively we store\n// the length minus the tag part of the offset. The lowest significant byte\n// thus stores the length. While total length - offset is given by\n// entry - ExtractOffset(type). The nice thing is that the subtraction\n// immediately sets the flags for the necessary check that offset >= length.\n// This folds the cmp with sub. We engineer the long literals and copy-4 to\n// always fail this check, so their presence doesn't affect the fast path.\n// To prevent literals from triggering the guard against offset < length (offset\n// does not apply to literals) the table is giving them a spurious offset of\n// 256.\ninline constexpr int16_t MakeEntry(int16_t len, int16_t offset) {\n  return len - (offset << 8);\n}\n\ninline constexpr int16_t LengthMinusOffset(int data, int type) {\n  return type == 3   ? 0xFF                    // copy-4 (or type == 3)\n         : type == 2 ? MakeEntry(data + 1, 0)  // copy-2\n         : type == 1 ? MakeEntry((data & 7) + 4, data >> 3)  // copy-1\n         : data < 60 ? MakeEntry(data + 1, 1)  // note spurious offset.\n                     : 0xFF;                   // long literal\n}\n\ninline constexpr int16_t LengthMinusOffset(uint8_t tag) {\n  return LengthMinusOffset(tag >> 2, tag & 3);\n}\n\ntemplate <size_t... Ints>\nstruct index_sequence {};\n\ntemplate <std::size_t N, size_t... Is>\nstruct make_index_sequence : make_index_sequence<N - 1, N - 1, Is...> {};\n\ntemplate <size_t... Is>\nstruct make_index_sequence<0, Is...> : index_sequence<Is...> {};\n\ntemplate <size_t... seq>\nconstexpr std::array<int16_t, 256> MakeTable(index_sequence<seq...>) {\n  return std::array<int16_t, 256>{LengthMinusOffset(seq)...};\n}\n\nalignas(64) const std::array<int16_t, 256> kLengthMinusOffset =\n    MakeTable(make_index_sequence<256>{});\n\n// Given a table of uint16_t whose size is mask / 2 + 1, return a pointer to the\n// relevant entry, if any, for the given bytes.  Any hash function will do,\n// but a good hash function reduces the number of collisions and thus yields\n// better compression for compressible input.\n//\n// REQUIRES: mask is 2 * (table_size - 1), and table_size is a power of two.\ninline uint16_t* TableEntry(uint16_t* table, uint32_t bytes, uint32_t mask) {\n  // Our choice is quicker-and-dirtier than the typical hash function;\n  // empirically, that seems beneficial.  The upper bits of kMagic * bytes are a\n  // higher-quality hash than the lower bits, so when using kMagic * bytes we\n  // also shift right to get a higher-quality end result.  There's no similar\n  // issue with a CRC because all of the output bits of a CRC are equally good\n  // \"hashes.\" So, a CPU instruction for CRC, if available, tends to be a good\n  // choice.\n#if SNAPPY_HAVE_NEON_CRC32\n  // We use mask as the second arg to the CRC function, as it's about to\n  // be used anyway; it'd be equally correct to use 0 or some constant.\n  // Mathematically, _mm_crc32_u32 (or similar) is a function of the\n  // xor of its arguments.\n  const uint32_t hash = __crc32cw(bytes, mask);\n#elif SNAPPY_HAVE_X86_CRC32\n  const uint32_t hash = _mm_crc32_u32(bytes, mask);\n#else\n  constexpr uint32_t kMagic = 0x1e35a7bd;\n  const uint32_t hash = (kMagic * bytes) >> (31 - kMaxHashTableBits);\n#endif\n  return reinterpret_cast<uint16_t*>(reinterpret_cast<uintptr_t>(table) +\n                                     (hash & mask));\n}\n\ninline uint16_t* TableEntry4ByteMatch(uint16_t* table, uint32_t bytes,\n                                      uint32_t mask) {\n  constexpr uint32_t kMagic = 2654435761U;\n  const uint32_t hash = (kMagic * bytes) >> (32 - kMaxHashTableBits);\n  return reinterpret_cast<uint16_t*>(reinterpret_cast<uintptr_t>(table) +\n                                     (hash & mask));\n}\n\ninline uint16_t* TableEntry8ByteMatch(uint16_t* table, uint64_t bytes,\n                                      uint32_t mask) {\n  constexpr uint64_t kMagic = 58295818150454627ULL;\n  const uint32_t hash = (kMagic * bytes) >> (64 - kMaxHashTableBits);\n  return reinterpret_cast<uint16_t*>(reinterpret_cast<uintptr_t>(table) +\n                                     (hash & mask));\n}\n\n}  // namespace\n\nsize_t MaxCompressedLength(size_t source_bytes) {\n  // Compressed data can be defined as:\n  //    compressed := item* literal*\n  //    item       := literal* copy\n  //\n  // The trailing literal sequence has a space blowup of at most 62/60\n  // since a literal of length 60 needs one tag byte + one extra byte\n  // for length information.\n  //\n  // Item blowup is trickier to measure.  Suppose the \"copy\" op copies\n  // 4 bytes of data.  Because of a special check in the encoding code,\n  // we produce a 4-byte copy only if the offset is < 65536.  Therefore\n  // the copy op takes 3 bytes to encode, and this type of item leads\n  // to at most the 62/60 blowup for representing literals.\n  //\n  // Suppose the \"copy\" op copies 5 bytes of data.  If the offset is big\n  // enough, it will take 5 bytes to encode the copy op.  Therefore the\n  // worst case here is a one-byte literal followed by a five-byte copy.\n  // I.e., 6 bytes of input turn into 7 bytes of \"compressed\" data.\n  //\n  // This last factor dominates the blowup, so the final estimate is:\n  return 32 + source_bytes + source_bytes / 6;\n}\n\nnamespace {\n\nvoid UnalignedCopy64(const void* src, void* dst) {\n  char tmp[8];\n  std::memcpy(tmp, src, 8);\n  std::memcpy(dst, tmp, 8);\n}\n\nvoid UnalignedCopy128(const void* src, void* dst) {\n  // std::memcpy() gets vectorized when the appropriate compiler options are\n  // used. For example, x86 compilers targeting SSE2+ will optimize to an SSE2\n  // load and store.\n  char tmp[16];\n  std::memcpy(tmp, src, 16);\n  std::memcpy(dst, tmp, 16);\n}\n\ntemplate <bool use_16bytes_chunk>\ninline void ConditionalUnalignedCopy128(const char* src, char* dst) {\n  if (use_16bytes_chunk) {\n    UnalignedCopy128(src, dst);\n  } else {\n    UnalignedCopy64(src, dst);\n    UnalignedCopy64(src + 8, dst + 8);\n  }\n}\n\n// Copy [src, src+(op_limit-op)) to [op, (op_limit-op)) a byte at a time. Used\n// for handling COPY operations where the input and output regions may overlap.\n// For example, suppose:\n//    src       == \"ab\"\n//    op        == src + 2\n//    op_limit  == op + 20\n// After IncrementalCopySlow(src, op, op_limit), the result will have eleven\n// copies of \"ab\"\n//    ababababababababababab\n// Note that this does not match the semantics of either std::memcpy() or\n// std::memmove().\ninline char* IncrementalCopySlow(const char* src, char* op,\n                                 char* const op_limit) {\n  // TODO: Remove pragma when LLVM is aware this\n  // function is only called in cold regions and when cold regions don't get\n  // vectorized or unrolled.\n#ifdef __clang__\n#pragma clang loop unroll(disable)\n#endif\n  while (op < op_limit) {\n    *op++ = *src++;\n  }\n  return op_limit;\n}\n\n#if SNAPPY_HAVE_VECTOR_BYTE_SHUFFLE\n\n// Computes the bytes for shuffle control mask (please read comments on\n// 'pattern_generation_masks' as well) for the given index_offset and\n// pattern_size. For example, when the 'offset' is 6, it will generate a\n// repeating pattern of size 6. So, the first 16 byte indexes will correspond to\n// the pattern-bytes {0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3} and the\n// next 16 byte indexes will correspond to the pattern-bytes {4, 5, 0, 1, 2, 3,\n// 4, 5, 0, 1, 2, 3, 4, 5, 0, 1}. These byte index sequences are generated by\n// calling MakePatternMaskBytes(0, 6, index_sequence<16>()) and\n// MakePatternMaskBytes(16, 6, index_sequence<16>()) respectively.\n\n\ntemplate <size_t... indexes>\ninline constexpr std::array<char, sizeof...(indexes)> MakePatternMaskBytes(\n    int index_offset, int pattern_size, index_sequence<indexes...>) {\n  return {static_cast<char>((index_offset + indexes) % pattern_size)...};\n}\n\n// Computes the shuffle control mask bytes array for given pattern-sizes and\n// returns an array.\ntemplate <size_t... pattern_sizes_minus_one>\ninline constexpr std::array<std::array<char, sizeof(V128)>,\n                            sizeof...(pattern_sizes_minus_one)>\nMakePatternMaskBytesTable(int index_offset,\n                          index_sequence<pattern_sizes_minus_one...>) {\n  return {\n      MakePatternMaskBytes(index_offset, pattern_sizes_minus_one + 1,\n                           make_index_sequence</*indexes=*/sizeof(V128)>())...};\n}\n// This is an array of shuffle control masks that can be used as the source\n// operand for PSHUFB to permute the contents of the destination XMM register\n// into a repeating byte pattern.\nalignas(16) constexpr std::array<std::array<char, sizeof(V128)>,\n                                 16> pattern_generation_masks =\n    MakePatternMaskBytesTable(\n        /*index_offset=*/0,\n        /*pattern_sizes_minus_one=*/make_index_sequence<16>());\n\n// Similar to 'pattern_generation_masks', this table is used to \"rotate\" the\n// pattern so that we can copy the *next 16 bytes* consistent with the pattern.\n// Basically, pattern_reshuffle_masks is a continuation of\n// pattern_generation_masks. It follows that, pattern_reshuffle_masks is same as\n// pattern_generation_masks for offsets 1, 2, 4, 8 and 16.\nalignas(16) constexpr std::array<std::array<char, sizeof(V128)>,\n                                 16> pattern_reshuffle_masks =\n    MakePatternMaskBytesTable(\n        /*index_offset=*/16,\n        /*pattern_sizes_minus_one=*/make_index_sequence<16>());\n\nSNAPPY_ATTRIBUTE_ALWAYS_INLINE\nstatic inline V128 LoadPattern(const char* src, const size_t pattern_size) {\n  V128 generation_mask = V128_Load(reinterpret_cast<const V128*>(\n      pattern_generation_masks[pattern_size - 1].data()));\n  // Uninitialized bytes are masked out by the shuffle mask.\n  // TODO: remove annotation and macro defs once MSan is fixed.\n  SNAPPY_ANNOTATE_MEMORY_IS_INITIALIZED(src + pattern_size, 16 - pattern_size);\n  return V128_Shuffle(V128_LoadU(reinterpret_cast<const V128*>(src)),\n                      generation_mask);\n}\nSNAPPY_ATTRIBUTE_ALWAYS_INLINE\nstatic inline std::pair<V128 /* pattern */, V128 /* reshuffle_mask */>\nLoadPatternAndReshuffleMask(const char* src, const size_t pattern_size) {\n  V128 pattern = LoadPattern(src, pattern_size);\n\n  // This mask will generate the next 16 bytes in-place. Doing so enables us to\n  // write data by at most 4 V128_StoreU.\n  //\n  // For example, suppose pattern is:        abcdefabcdefabcd\n  // Shuffling with this mask will generate: efabcdefabcdefab\n  // Shuffling again will generate:          cdefabcdefabcdef\n  V128 reshuffle_mask = V128_Load(reinterpret_cast<const V128*>(\n      pattern_reshuffle_masks[pattern_size - 1].data()));\n  return {pattern, reshuffle_mask};\n}\n#endif  // SNAPPY_HAVE_VECTOR_BYTE_SHUFFLE\n\n// Fallback for when we need to copy while extending the pattern, for example\n// copying 10 bytes from 3 positions back abc -> abcabcabcabca.\n//\n// REQUIRES: [dst - offset, dst + 64) is a valid address range.\nSNAPPY_ATTRIBUTE_ALWAYS_INLINE\nstatic inline bool Copy64BytesWithPatternExtension(char* dst, size_t offset) {\n#if SNAPPY_HAVE_VECTOR_BYTE_SHUFFLE\n  if (SNAPPY_PREDICT_TRUE(offset <= 16)) {\n    switch (offset) {\n      case 0:\n        return false;\n      case 1: {\n        // TODO: Ideally we should memset, move back once the\n        // codegen issues are fixed.\n        V128 pattern = V128_DupChar(dst[-1]);\n        for (int i = 0; i < 4; i++) {\n          V128_StoreU(reinterpret_cast<V128*>(dst + 16 * i), pattern);\n        }\n        return true;\n      }\n      case 2:\n      case 4:\n      case 8:\n      case 16: {\n        V128 pattern = LoadPattern(dst - offset, offset);\n        for (int i = 0; i < 4; i++) {\n          V128_StoreU(reinterpret_cast<V128*>(dst + 16 * i), pattern);\n        }\n        return true;\n      }\n      default: {\n        auto pattern_and_reshuffle_mask =\n            LoadPatternAndReshuffleMask(dst - offset, offset);\n        V128 pattern = pattern_and_reshuffle_mask.first;\n        V128 reshuffle_mask = pattern_and_reshuffle_mask.second;\n        for (int i = 0; i < 4; i++) {\n          V128_StoreU(reinterpret_cast<V128*>(dst + 16 * i), pattern);\n          pattern = V128_Shuffle(pattern, reshuffle_mask);\n        }\n        return true;\n      }\n    }\n  }\n#else\n  if (SNAPPY_PREDICT_TRUE(offset < 16)) {\n    if (SNAPPY_PREDICT_FALSE(offset == 0)) return false;\n    // Extend the pattern to the first 16 bytes.\n    // The simpler formulation of `dst[i - offset]` induces undefined behavior.\n    for (int i = 0; i < 16; i++) dst[i] = (dst - offset)[i];\n    // Find a multiple of pattern >= 16.\n    static std::array<uint8_t, 16> pattern_sizes = []() {\n      std::array<uint8_t, 16> res;\n      for (int i = 1; i < 16; i++) res[i] = (16 / i + 1) * i;\n      return res;\n    }();\n    offset = pattern_sizes[offset];\n    for (int i = 1; i < 4; i++) {\n      std::memcpy(dst + i * 16, dst + i * 16 - offset, 16);\n    }\n    return true;\n  }\n#endif  // SNAPPY_HAVE_VECTOR_BYTE_SHUFFLE\n\n  // Very rare.\n  for (int i = 0; i < 4; i++) {\n    std::memcpy(dst + i * 16, dst + i * 16 - offset, 16);\n  }\n  return true;\n}\n\n// Copy [src, src+(op_limit-op)) to [op, op_limit) but faster than\n// IncrementalCopySlow. buf_limit is the address past the end of the writable\n// region of the buffer.\ninline char* IncrementalCopy(const char* src, char* op, char* const op_limit,\n                             char* const buf_limit) {\n#if SNAPPY_HAVE_VECTOR_BYTE_SHUFFLE\n  constexpr int big_pattern_size_lower_bound = 16;\n#else\n  constexpr int big_pattern_size_lower_bound = 8;\n#endif\n\n  // Terminology:\n  //\n  // slop = buf_limit - op\n  // pat  = op - src\n  // len  = op_limit - op\n  assert(src < op);\n  assert(op < op_limit);\n  assert(op_limit <= buf_limit);\n  // NOTE: The copy tags use 3 or 6 bits to store the copy length, so len <= 64.\n  assert(op_limit - op <= 64);\n  // NOTE: In practice the compressor always emits len >= 4, so it is ok to\n  // assume that to optimize this function, but this is not guaranteed by the\n  // compression format, so we have to also handle len < 4 in case the input\n  // does not satisfy these conditions.\n\n  size_t pattern_size = op - src;\n  // The cases are split into different branches to allow the branch predictor,\n  // FDO, and static prediction hints to work better. For each input we list the\n  // ratio of invocations that match each condition.\n  //\n  // input        slop < 16   pat < 8  len > 16\n  // ------------------------------------------\n  // html|html4|cp   0%         1.01%    27.73%\n  // urls            0%         0.88%    14.79%\n  // jpg             0%        64.29%     7.14%\n  // pdf             0%         2.56%    58.06%\n  // txt[1-4]        0%         0.23%     0.97%\n  // pb              0%         0.96%    13.88%\n  // bin             0.01%     22.27%    41.17%\n  //\n  // It is very rare that we don't have enough slop for doing block copies. It\n  // is also rare that we need to expand a pattern. Small patterns are common\n  // for incompressible formats and for those we are plenty fast already.\n  // Lengths are normally not greater than 16 but they vary depending on the\n  // input. In general if we always predict len <= 16 it would be an ok\n  // prediction.\n  //\n  // In order to be fast we want a pattern >= 16 bytes (or 8 bytes in non-SSE)\n  // and an unrolled loop copying 1x 16 bytes (or 2x 8 bytes in non-SSE) at a\n  // time.\n\n  // Handle the uncommon case where pattern is less than 16 (or 8 in non-SSE)\n  // bytes.\n  if (pattern_size < big_pattern_size_lower_bound) {\n#if SNAPPY_HAVE_VECTOR_BYTE_SHUFFLE\n    // Load the first eight bytes into an 128-bit XMM register, then use PSHUFB\n    // to permute the register's contents in-place into a repeating sequence of\n    // the first \"pattern_size\" bytes.\n    // For example, suppose:\n    //    src       == \"abc\"\n    //    op        == op + 3\n    // After V128_Shuffle(), \"pattern\" will have five copies of \"abc\"\n    // followed by one byte of slop: abcabcabcabcabca.\n    //\n    // The non-SSE fallback implementation suffers from store-forwarding stalls\n    // because its loads and stores partly overlap. By expanding the pattern\n    // in-place, we avoid the penalty.\n\n    // Typically, the op_limit is the gating factor so try to simplify the loop\n    // based on that.\n    if (SNAPPY_PREDICT_TRUE(op_limit <= buf_limit - 15)) {\n      auto pattern_and_reshuffle_mask =\n          LoadPatternAndReshuffleMask(src, pattern_size);\n      V128 pattern = pattern_and_reshuffle_mask.first;\n      V128 reshuffle_mask = pattern_and_reshuffle_mask.second;\n      // There is at least one, and at most four 16-byte blocks. Writing four\n      // conditionals instead of a loop allows FDO to layout the code with\n      // respect to the actual probabilities of each length.\n      // TODO: Replace with loop with trip count hint.\n      V128_StoreU(reinterpret_cast<V128*>(op), pattern);\n\n      if (op + 16 < op_limit) {\n        pattern = V128_Shuffle(pattern, reshuffle_mask);\n        V128_StoreU(reinterpret_cast<V128*>(op + 16), pattern);\n      }\n      if (op + 32 < op_limit) {\n        pattern = V128_Shuffle(pattern, reshuffle_mask);\n        V128_StoreU(reinterpret_cast<V128*>(op + 32), pattern);\n      }\n      if (op + 48 < op_limit) {\n        pattern = V128_Shuffle(pattern, reshuffle_mask);\n        V128_StoreU(reinterpret_cast<V128*>(op + 48), pattern);\n      }\n      return op_limit;\n    }\n    char* const op_end = buf_limit - 15;\n    if (SNAPPY_PREDICT_TRUE(op < op_end)) {\n      auto pattern_and_reshuffle_mask =\n          LoadPatternAndReshuffleMask(src, pattern_size);\n      V128 pattern = pattern_and_reshuffle_mask.first;\n      V128 reshuffle_mask = pattern_and_reshuffle_mask.second;\n      // This code path is relatively cold however so we save code size\n      // by avoiding unrolling and vectorizing.\n      //\n      // TODO: Remove pragma when when cold regions don't get\n      // vectorized or unrolled.\n#ifdef __clang__\n#pragma clang loop unroll(disable)\n#endif\n      do {\n        V128_StoreU(reinterpret_cast<V128*>(op), pattern);\n        pattern = V128_Shuffle(pattern, reshuffle_mask);\n        op += 16;\n      } while (SNAPPY_PREDICT_TRUE(op < op_end));\n    }\n    return IncrementalCopySlow(op - pattern_size, op, op_limit);\n#else   // !SNAPPY_HAVE_VECTOR_BYTE_SHUFFLE\n    // If plenty of buffer space remains, expand the pattern to at least 8\n    // bytes. The way the following loop is written, we need 8 bytes of buffer\n    // space if pattern_size >= 4, 11 bytes if pattern_size is 1 or 3, and 10\n    // bytes if pattern_size is 2.  Precisely encoding that is probably not\n    // worthwhile; instead, invoke the slow path if we cannot write 11 bytes\n    // (because 11 are required in the worst case).\n    if (SNAPPY_PREDICT_TRUE(op <= buf_limit - 11)) {\n      while (pattern_size < 8) {\n        UnalignedCopy64(src, op);\n        op += pattern_size;\n        pattern_size *= 2;\n      }\n      if (SNAPPY_PREDICT_TRUE(op >= op_limit)) return op_limit;\n    } else {\n      return IncrementalCopySlow(src, op, op_limit);\n    }\n#endif  // SNAPPY_HAVE_VECTOR_BYTE_SHUFFLE\n  }\n  assert(pattern_size >= big_pattern_size_lower_bound);\n  constexpr bool use_16bytes_chunk = big_pattern_size_lower_bound == 16;\n\n  // Copy 1x 16 bytes (or 2x 8 bytes in non-SSE) at a time. Because op - src can\n  // be < 16 in non-SSE, a single UnalignedCopy128 might overwrite data in op.\n  // UnalignedCopy64 is safe because expanding the pattern to at least 8 bytes\n  // guarantees that op - src >= 8.\n  //\n  // Typically, the op_limit is the gating factor so try to simplify the loop\n  // based on that.\n  if (SNAPPY_PREDICT_TRUE(op_limit <= buf_limit - 15)) {\n    // There is at least one, and at most four 16-byte blocks. Writing four\n    // conditionals instead of a loop allows FDO to layout the code with respect\n    // to the actual probabilities of each length.\n    // TODO: Replace with loop with trip count hint.\n    ConditionalUnalignedCopy128<use_16bytes_chunk>(src, op);\n    if (op + 16 < op_limit) {\n      ConditionalUnalignedCopy128<use_16bytes_chunk>(src + 16, op + 16);\n    }\n    if (op + 32 < op_limit) {\n      ConditionalUnalignedCopy128<use_16bytes_chunk>(src + 32, op + 32);\n    }\n    if (op + 48 < op_limit) {\n      ConditionalUnalignedCopy128<use_16bytes_chunk>(src + 48, op + 48);\n    }\n    return op_limit;\n  }\n\n  // Fall back to doing as much as we can with the available slop in the\n  // buffer. This code path is relatively cold however so we save code size by\n  // avoiding unrolling and vectorizing.\n  //\n  // TODO: Remove pragma when when cold regions don't get vectorized\n  // or unrolled.\n#ifdef __clang__\n#pragma clang loop unroll(disable)\n#endif\n  for (char* op_end = buf_limit - 16; op < op_end; op += 16, src += 16) {\n    ConditionalUnalignedCopy128<use_16bytes_chunk>(src, op);\n  }\n  if (op >= op_limit) return op_limit;\n\n  // We only take this branch if we didn't have enough slop and we can do a\n  // single 8 byte copy.\n  if (SNAPPY_PREDICT_FALSE(op <= buf_limit - 8)) {\n    UnalignedCopy64(src, op);\n    src += 8;\n    op += 8;\n  }\n  return IncrementalCopySlow(src, op, op_limit);\n}\n\n}  // namespace\n\ntemplate <bool allow_fast_path>\nstatic inline char* EmitLiteral(char* op, const char* literal, int len) {\n  // The vast majority of copies are below 16 bytes, for which a\n  // call to std::memcpy() is overkill. This fast path can sometimes\n  // copy up to 15 bytes too much, but that is okay in the\n  // main loop, since we have a bit to go on for both sides:\n  //\n  //   - The input will always have kInputMarginBytes = 15 extra\n  //     available bytes, as long as we're in the main loop, and\n  //     if not, allow_fast_path = false.\n  //   - The output will always have 32 spare bytes (see\n  //     MaxCompressedLength).\n  assert(len > 0);  // Zero-length literals are disallowed\n  int n = len - 1;\n  if (allow_fast_path && len <= 16) {\n    // Fits in tag byte\n    *op++ = LITERAL | (n << 2);\n\n    UnalignedCopy128(literal, op);\n    return op + len;\n  }\n\n  if (n < 60) {\n    // Fits in tag byte\n    *op++ = LITERAL | (n << 2);\n  } else {\n    int count = (Bits::Log2Floor(n) >> 3) + 1;\n    assert(count >= 1);\n    assert(count <= 4);\n    *op++ = LITERAL | ((59 + count) << 2);\n    // Encode in upcoming bytes.\n    // Write 4 bytes, though we may care about only 1 of them. The output buffer\n    // is guaranteed to have at least 3 more spaces left as 'len >= 61' holds\n    // here and there is a std::memcpy() of size 'len' below.\n    LittleEndian::Store32(op, n);\n    op += count;\n  }\n  // When allow_fast_path is true, we can overwrite up to 16 bytes.\n  if (allow_fast_path) {\n    char* destination = op;\n    const char* source = literal;\n    const char* end = destination + len;\n    do {\n      std::memcpy(destination, source, 16);\n      destination += 16;\n      source += 16;\n    } while (destination < end);\n  } else {\n    std::memcpy(op, literal, len);\n  }\n  return op + len;\n}\n\ntemplate <bool len_less_than_12>\nstatic inline char* EmitCopyAtMost64(char* op, size_t offset, size_t len) {\n  assert(len <= 64);\n  assert(len >= 4);\n  assert(offset < 65536);\n  assert(len_less_than_12 == (len < 12));\n\n  if (len_less_than_12) {\n    uint32_t u = (len << 2) + (offset << 8);\n    uint32_t copy1 = COPY_1_BYTE_OFFSET - (4 << 2) + ((offset >> 3) & 0xe0);\n    uint32_t copy2 = COPY_2_BYTE_OFFSET - (1 << 2);\n    // It turns out that offset < 2048 is a difficult to predict branch.\n    // `perf record` shows this is the highest percentage of branch misses in\n    // benchmarks. This code produces branch free code, the data dependency\n    // chain that bottlenecks the throughput is so long that a few extra\n    // instructions are completely free (IPC << 6 because of data deps).\n    u += offset < 2048 ? copy1 : copy2;\n    LittleEndian::Store32(op, u);\n    op += offset < 2048 ? 2 : 3;\n  } else {\n    // Write 4 bytes, though we only care about 3 of them.  The output buffer\n    // is required to have some slack, so the extra byte won't overrun it.\n    uint32_t u = COPY_2_BYTE_OFFSET + ((len - 1) << 2) + (offset << 8);\n    LittleEndian::Store32(op, u);\n    op += 3;\n  }\n  return op;\n}\n\ntemplate <bool len_less_than_12>\nstatic inline char* EmitCopy(char* op, size_t offset, size_t len) {\n  assert(len_less_than_12 == (len < 12));\n  if (len_less_than_12) {\n    return EmitCopyAtMost64</*len_less_than_12=*/true>(op, offset, len);\n  } else {\n    // A special case for len <= 64 might help, but so far measurements suggest\n    // it's in the noise.\n\n    // Emit 64 byte copies but make sure to keep at least four bytes reserved.\n    while (SNAPPY_PREDICT_FALSE(len >= 68)) {\n      op = EmitCopyAtMost64</*len_less_than_12=*/false>(op, offset, 64);\n      len -= 64;\n    }\n\n    // One or two copies will now finish the job.\n    if (len > 64) {\n      op = EmitCopyAtMost64</*len_less_than_12=*/false>(op, offset, 60);\n      len -= 60;\n    }\n\n    // Emit remainder.\n    if (len < 12) {\n      op = EmitCopyAtMost64</*len_less_than_12=*/true>(op, offset, len);\n    } else {\n      op = EmitCopyAtMost64</*len_less_than_12=*/false>(op, offset, len);\n    }\n    return op;\n  }\n}\n\nbool GetUncompressedLength(const char* start, size_t n, size_t* result) {\n  uint32_t v = 0;\n  const char* limit = start + n;\n  if (Varint::Parse32WithLimit(start, limit, &v) != NULL) {\n    *result = v;\n    return true;\n  } else {\n    return false;\n  }\n}\n\nnamespace {\nuint32_t CalculateTableSize(uint32_t input_size) {\n  static_assert(\n      kMaxHashTableSize >= kMinHashTableSize,\n      \"kMaxHashTableSize should be greater or equal to kMinHashTableSize.\");\n  if (input_size > kMaxHashTableSize) {\n    return kMaxHashTableSize;\n  }\n  if (input_size < kMinHashTableSize) {\n    return kMinHashTableSize;\n  }\n  // This is equivalent to Log2Ceiling(input_size), assuming input_size > 1.\n  // 2 << Log2Floor(x - 1) is equivalent to 1 << (1 + Log2Floor(x - 1)).\n  return 2u << Bits::Log2Floor(input_size - 1);\n}\n}  // namespace\n\nnamespace internal {\nWorkingMemory::WorkingMemory(size_t input_size) {\n  const size_t max_fragment_size = std::min(input_size, kBlockSize);\n  const size_t table_size = CalculateTableSize(max_fragment_size);\n  size_ = table_size * sizeof(*table_) + max_fragment_size +\n          MaxCompressedLength(max_fragment_size);\n  mem_ = std::allocator<char>().allocate(size_);\n  table_ = reinterpret_cast<uint16_t*>(mem_);\n  input_ = mem_ + table_size * sizeof(*table_);\n  output_ = input_ + max_fragment_size;\n}\n\nWorkingMemory::~WorkingMemory() {\n  std::allocator<char>().deallocate(mem_, size_);\n}\n\nuint16_t* WorkingMemory::GetHashTable(size_t fragment_size,\n                                      int* table_size) const {\n  const size_t htsize = CalculateTableSize(fragment_size);\n  memset(table_, 0, htsize * sizeof(*table_));\n  *table_size = htsize;\n  return table_;\n}\n}  // end namespace internal\n\n// Flat array compression that does not emit the \"uncompressed length\"\n// prefix. Compresses \"input\" string to the \"*op\" buffer.\n//\n// REQUIRES: \"input\" is at most \"kBlockSize\" bytes long.\n// REQUIRES: \"op\" points to an array of memory that is at least\n// \"MaxCompressedLength(input.size())\" in size.\n// REQUIRES: All elements in \"table[0..table_size-1]\" are initialized to zero.\n// REQUIRES: \"table_size\" is a power of two\n//\n// Returns an \"end\" pointer into \"op\" buffer.\n// \"end - op\" is the compressed size of \"input\".\nnamespace internal {\nchar* CompressFragment(const char* input, size_t input_size, char* op,\n                       uint16_t* table, const int table_size) {\n  // \"ip\" is the input pointer, and \"op\" is the output pointer.\n  const char* ip = input;\n  assert(input_size <= kBlockSize);\n  assert((table_size & (table_size - 1)) == 0);  // table must be power of two\n  const uint32_t mask = 2 * (table_size - 1);\n  const char* ip_end = input + input_size;\n  const char* base_ip = ip;\n\n  const size_t kInputMarginBytes = 15;\n  if (SNAPPY_PREDICT_TRUE(input_size >= kInputMarginBytes)) {\n    const char* ip_limit = input + input_size - kInputMarginBytes;\n\n    for (uint32_t preload = LittleEndian::Load32(ip + 1);;) {\n      // Bytes in [next_emit, ip) will be emitted as literal bytes.  Or\n      // [next_emit, ip_end) after the main loop.\n      const char* next_emit = ip++;\n      uint64_t data = LittleEndian::Load64(ip);\n      // The body of this loop calls EmitLiteral once and then EmitCopy one or\n      // more times.  (The exception is that when we're close to exhausting\n      // the input we goto emit_remainder.)\n      //\n      // In the first iteration of this loop we're just starting, so\n      // there's nothing to copy, so calling EmitLiteral once is\n      // necessary.  And we only start a new iteration when the\n      // current iteration has determined that a call to EmitLiteral will\n      // precede the next call to EmitCopy (if any).\n      //\n      // Step 1: Scan forward in the input looking for a 4-byte-long match.\n      // If we get close to exhausting the input then goto emit_remainder.\n      //\n      // Heuristic match skipping: If 32 bytes are scanned with no matches\n      // found, start looking only at every other byte. If 32 more bytes are\n      // scanned (or skipped), look at every third byte, etc.. When a match is\n      // found, immediately go back to looking at every byte. This is a small\n      // loss (~5% performance, ~0.1% density) for compressible data due to more\n      // bookkeeping, but for non-compressible data (such as JPEG) it's a huge\n      // win since the compressor quickly \"realizes\" the data is incompressible\n      // and doesn't bother looking for matches everywhere.\n      //\n      // The \"skip\" variable keeps track of how many bytes there are since the\n      // last match; dividing it by 32 (ie. right-shifting by five) gives the\n      // number of bytes to move ahead for each iteration.\n      uint32_t skip = 32;\n\n      const char* candidate;\n      if (ip_limit - ip >= 16) {\n        auto delta = ip - base_ip;\n        for (int j = 0; j < 4; ++j) {\n          for (int k = 0; k < 4; ++k) {\n            int i = 4 * j + k;\n            // These for-loops are meant to be unrolled. So we can freely\n            // special case the first iteration to use the value already\n            // loaded in preload.\n            uint32_t dword = i == 0 ? preload : static_cast<uint32_t>(data);\n            assert(dword == LittleEndian::Load32(ip + i));\n            uint16_t* table_entry = TableEntry(table, dword, mask);\n            candidate = base_ip + *table_entry;\n            assert(candidate >= base_ip);\n            assert(candidate < ip + i);\n            *table_entry = delta + i;\n            if (SNAPPY_PREDICT_FALSE(LittleEndian::Load32(candidate) == dword)) {\n              *op = LITERAL | (i << 2);\n              UnalignedCopy128(next_emit, op + 1);\n              ip += i;\n              op = op + i + 2;\n              goto emit_match;\n            }\n            data >>= 8;\n          }\n          data = LittleEndian::Load64(ip + 4 * j + 4);\n        }\n        ip += 16;\n        skip += 16;\n      }\n      while (true) {\n        assert(static_cast<uint32_t>(data) == LittleEndian::Load32(ip));\n        uint16_t* table_entry = TableEntry(table, data, mask);\n        uint32_t bytes_between_hash_lookups = skip >> 5;\n        skip += bytes_between_hash_lookups;\n        const char* next_ip = ip + bytes_between_hash_lookups;\n        if (SNAPPY_PREDICT_FALSE(next_ip > ip_limit)) {\n          ip = next_emit;\n          goto emit_remainder;\n        }\n        candidate = base_ip + *table_entry;\n        assert(candidate >= base_ip);\n        assert(candidate < ip);\n\n        *table_entry = ip - base_ip;\n        if (SNAPPY_PREDICT_FALSE(static_cast<uint32_t>(data) ==\n                                LittleEndian::Load32(candidate))) {\n          break;\n        }\n        data = LittleEndian::Load32(next_ip);\n        ip = next_ip;\n      }\n\n      // Step 2: A 4-byte match has been found.  We'll later see if more\n      // than 4 bytes match.  But, prior to the match, input\n      // bytes [next_emit, ip) are unmatched.  Emit them as \"literal bytes.\"\n      assert(next_emit + 16 <= ip_end);\n      op = EmitLiteral</*allow_fast_path=*/true>(op, next_emit, ip - next_emit);\n\n      // Step 3: Call EmitCopy, and then see if another EmitCopy could\n      // be our next move.  Repeat until we find no match for the\n      // input immediately after what was consumed by the last EmitCopy call.\n      //\n      // If we exit this loop normally then we need to call EmitLiteral next,\n      // though we don't yet know how big the literal will be.  We handle that\n      // by proceeding to the next iteration of the main loop.  We also can exit\n      // this loop via goto if we get close to exhausting the input.\n    emit_match:\n      do {\n        // We have a 4-byte match at ip, and no need to emit any\n        // \"literal bytes\" prior to ip.\n        const char* base = ip;\n        std::pair<size_t, bool> p =\n            FindMatchLength(candidate + 4, ip + 4, ip_end, &data);\n        size_t matched = 4 + p.first;\n        ip += matched;\n        size_t offset = base - candidate;\n        assert(0 == memcmp(base, candidate, matched));\n        if (p.second) {\n          op = EmitCopy</*len_less_than_12=*/true>(op, offset, matched);\n        } else {\n          op = EmitCopy</*len_less_than_12=*/false>(op, offset, matched);\n        }\n        if (SNAPPY_PREDICT_FALSE(ip >= ip_limit)) {\n          goto emit_remainder;\n        }\n        // Expect 5 bytes to match\n        assert((data & 0xFFFFFFFFFF) ==\n               (LittleEndian::Load64(ip) & 0xFFFFFFFFFF));\n        // We are now looking for a 4-byte match again.  We read\n        // table[Hash(ip, mask)] for that.  To improve compression,\n        // we also update table[Hash(ip - 1, mask)] and table[Hash(ip, mask)].\n        *TableEntry(table, LittleEndian::Load32(ip - 1), mask) =\n            ip - base_ip - 1;\n        uint16_t* table_entry = TableEntry(table, data, mask);\n        candidate = base_ip + *table_entry;\n        *table_entry = ip - base_ip;\n        // Measurements on the benchmarks have shown the following probabilities\n        // for the loop to exit (ie. avg. number of iterations is reciprocal).\n        // BM_Flat/6  txt1    p = 0.3-0.4\n        // BM_Flat/7  txt2    p = 0.35\n        // BM_Flat/8  txt3    p = 0.3-0.4\n        // BM_Flat/9  txt3    p = 0.34-0.4\n        // BM_Flat/10 pb      p = 0.4\n        // BM_Flat/11 gaviota p = 0.1\n        // BM_Flat/12 cp      p = 0.5\n        // BM_Flat/13 c       p = 0.3\n      } while (static_cast<uint32_t>(data) == LittleEndian::Load32(candidate));\n      // Because the least significant 5 bytes matched, we can utilize data\n      // for the next iteration.\n      preload = data >> 8;\n    }\n  }\n\nemit_remainder:\n  // Emit the remaining bytes as a literal\n  if (ip < ip_end) {\n    op = EmitLiteral</*allow_fast_path=*/false>(op, ip, ip_end - ip);\n  }\n\n  return op;\n}\n\nchar* CompressFragmentDoubleHash(const char* input, size_t input_size, char* op,\n                                 uint16_t* table, const int table_size,\n                                 uint16_t* table2, const int table_size2) {\n  (void)table_size2;\n  assert(table_size == table_size2);\n  // \"ip\" is the input pointer, and \"op\" is the output pointer.\n  const char* ip = input;\n  assert(input_size <= kBlockSize);\n  assert((table_size & (table_size - 1)) == 0);  // table must be power of two\n  const uint32_t mask = 2 * (table_size - 1);\n  const char* ip_end = input + input_size;\n  const char* base_ip = ip;\n\n  const size_t kInputMarginBytes = 15;\n  if (SNAPPY_PREDICT_TRUE(input_size >= kInputMarginBytes)) {\n    const char* ip_limit = input + input_size - kInputMarginBytes;\n\n    for (;;) {\n      const char* next_emit = ip++;\n      uint64_t data = LittleEndian::Load64(ip);\n      uint32_t skip = 512;\n\n      const char* candidate;\n      uint32_t candidate_length;\n      while (true) {\n        assert(static_cast<uint32_t>(data) == LittleEndian::Load32(ip));\n        uint16_t* table_entry2 = TableEntry8ByteMatch(table2, data, mask);\n        uint32_t bytes_between_hash_lookups = skip >> 9;\n        skip++;\n        const char* next_ip = ip + bytes_between_hash_lookups;\n        if (SNAPPY_PREDICT_FALSE(next_ip > ip_limit)) {\n          ip = next_emit;\n          goto emit_remainder;\n        }\n        candidate = base_ip + *table_entry2;\n        assert(candidate >= base_ip);\n        assert(candidate < ip);\n\n        *table_entry2 = ip - base_ip;\n        if (SNAPPY_PREDICT_FALSE(static_cast<uint32_t>(data) ==\n                                LittleEndian::Load32(candidate))) {\n          candidate_length =\n              FindMatchLengthPlain(candidate + 4, ip + 4, ip_end) + 4;\n          break;\n        }\n\n        uint16_t* table_entry = TableEntry4ByteMatch(table, data, mask);\n        candidate = base_ip + *table_entry;\n        assert(candidate >= base_ip);\n        assert(candidate < ip);\n\n        *table_entry = ip - base_ip;\n        if (SNAPPY_PREDICT_FALSE(static_cast<uint32_t>(data) ==\n                                LittleEndian::Load32(candidate))) {\n          candidate_length =\n              FindMatchLengthPlain(candidate + 4, ip + 4, ip_end) + 4;\n          table_entry2 =\n              TableEntry8ByteMatch(table2, LittleEndian::Load64(ip + 1), mask);\n          auto candidate2 = base_ip + *table_entry2;\n          size_t candidate_length2 =\n              FindMatchLengthPlain(candidate2, ip + 1, ip_end);\n          if (candidate_length2 > candidate_length) {\n            *table_entry2 = ip - base_ip;\n            candidate = candidate2;\n            candidate_length = candidate_length2;\n            ++ip;\n          }\n          break;\n        }\n        data = LittleEndian::Load64(next_ip);\n        ip = next_ip;\n      }\n      // Backtrack to the point it matches fully.\n      while (ip > next_emit && candidate > base_ip &&\n             *(ip - 1) == *(candidate - 1)) {\n        --ip;\n        --candidate;\n        ++candidate_length;\n      }\n      *TableEntry8ByteMatch(table2, LittleEndian::Load64(ip + 1), mask) =\n          ip - base_ip + 1;\n      *TableEntry8ByteMatch(table2, LittleEndian::Load64(ip + 2), mask) =\n          ip - base_ip + 2;\n      *TableEntry4ByteMatch(table, LittleEndian::Load32(ip + 1), mask) =\n          ip - base_ip + 1;\n      // Step 2: A 4-byte or 8-byte match has been found.\n      // We'll later see if more than 4 bytes match.  But, prior to the match,\n      // input bytes [next_emit, ip) are unmatched.  Emit them as\n      // \"literal bytes.\"\n      assert(next_emit + 16 <= ip_end);\n      if (ip - next_emit > 0) {\n        op = EmitLiteral</*allow_fast_path=*/true>(op, next_emit,\n                                                   ip - next_emit);\n      }\n      // Step 3: Call EmitCopy, and then see if another EmitCopy could\n      // be our next move.  Repeat until we find no match for the\n      // input immediately after what was consumed by the last EmitCopy call.\n      //\n      // If we exit this loop normally then we need to call EmitLiteral next,\n      // though we don't yet know how big the literal will be.  We handle that\n      // by proceeding to the next iteration of the main loop.  We also can exit\n      // this loop via goto if we get close to exhausting the input.\n      do {\n        // We have a 4-byte match at ip, and no need to emit any\n        // \"literal bytes\" prior to ip.\n        const char* base = ip;\n        ip += candidate_length;\n        size_t offset = base - candidate;\n        if (candidate_length < 12) {\n          op =\n              EmitCopy</*len_less_than_12=*/true>(op, offset, candidate_length);\n        } else {\n          op = EmitCopy</*len_less_than_12=*/false>(op, offset,\n                                                    candidate_length);\n        }\n        if (SNAPPY_PREDICT_FALSE(ip >= ip_limit)) {\n          goto emit_remainder;\n        }\n        // We are now looking for a 4-byte match again.  We read\n        // table[Hash(ip, mask)] for that. To improve compression,\n        // we also update several previous table entries.\n        if (ip - base_ip > 7) {\n          *TableEntry8ByteMatch(table2, LittleEndian::Load64(ip - 7), mask) =\n              ip - base_ip - 7;\n          *TableEntry8ByteMatch(table2, LittleEndian::Load64(ip - 4), mask) =\n              ip - base_ip - 4;\n        }\n        *TableEntry8ByteMatch(table2, LittleEndian::Load64(ip - 3), mask) =\n            ip - base_ip - 3;\n        *TableEntry8ByteMatch(table2, LittleEndian::Load64(ip - 2), mask) =\n            ip - base_ip - 2;\n        *TableEntry4ByteMatch(table, LittleEndian::Load32(ip - 2), mask) =\n            ip - base_ip - 2;\n        *TableEntry4ByteMatch(table, LittleEndian::Load32(ip - 1), mask) =\n            ip - base_ip - 1;\n\n        uint16_t* table_entry =\n            TableEntry8ByteMatch(table2, LittleEndian::Load64(ip), mask);\n        candidate = base_ip + *table_entry;\n        *table_entry = ip - base_ip;\n        if (LittleEndian::Load32(ip) == LittleEndian::Load32(candidate)) {\n          candidate_length =\n              FindMatchLengthPlain(candidate + 4, ip + 4, ip_end) + 4;\n          continue;\n        }\n        table_entry =\n            TableEntry4ByteMatch(table, LittleEndian::Load32(ip), mask);\n        candidate = base_ip + *table_entry;\n        *table_entry = ip - base_ip;\n        if (LittleEndian::Load32(ip) == LittleEndian::Load32(candidate)) {\n          candidate_length =\n              FindMatchLengthPlain(candidate + 4, ip + 4, ip_end) + 4;\n          continue;\n        }\n        break;\n      } while (true);\n    }\n  }\n\nemit_remainder:\n  // Emit the remaining bytes as a literal\n  if (ip < ip_end) {\n    op = EmitLiteral</*allow_fast_path=*/false>(op, ip, ip_end - ip);\n  }\n\n  return op;\n}\n}  // end namespace internal\n\nstatic inline void Report(int token, const char *algorithm, size_t\ncompressed_size, size_t uncompressed_size) {\n  // TODO: Switch to [[maybe_unused]] when we can assume C++17.\n  (void)token;\n  (void)algorithm;\n  (void)compressed_size;\n  (void)uncompressed_size;\n}\n\n// Signature of output types needed by decompression code.\n// The decompression code is templatized on a type that obeys this\n// signature so that we do not pay virtual function call overhead in\n// the middle of a tight decompression loop.\n//\n// class DecompressionWriter {\n//  public:\n//   // Called before decompression\n//   void SetExpectedLength(size_t length);\n//\n//   // For performance a writer may choose to donate the cursor variable to the\n//   // decompression function. The decompression will inject it in all its\n//   // function calls to the writer. Keeping the important output cursor as a\n//   // function local stack variable allows the compiler to keep it in\n//   // register, which greatly aids performance by avoiding loads and stores of\n//   // this variable in the fast path loop iterations.\n//   T GetOutputPtr() const;\n//\n//   // At end of decompression the loop donates the ownership of the cursor\n//   // variable back to the writer by calling this function.\n//   void SetOutputPtr(T op);\n//\n//   // Called after decompression\n//   bool CheckLength() const;\n//\n//   // Called repeatedly during decompression\n//   // Each function get a pointer to the op (output pointer), that the writer\n//   // can use and update. Note it's important that these functions get fully\n//   // inlined so that no actual address of the local variable needs to be\n//   // taken.\n//   bool Append(const char* ip, size_t length, T* op);\n//   bool AppendFromSelf(uint32_t offset, size_t length, T* op);\n//\n//   // The rules for how TryFastAppend differs from Append are somewhat\n//   // convoluted:\n//   //\n//   //  - TryFastAppend is allowed to decline (return false) at any\n//   //    time, for any reason -- just \"return false\" would be\n//   //    a perfectly legal implementation of TryFastAppend.\n//   //    The intention is for TryFastAppend to allow a fast path\n//   //    in the common case of a small append.\n//   //  - TryFastAppend is allowed to read up to <available> bytes\n//   //    from the input buffer, whereas Append is allowed to read\n//   //    <length>. However, if it returns true, it must leave\n//   //    at least five (kMaximumTagLength) bytes in the input buffer\n//   //    afterwards, so that there is always enough space to read the\n//   //    next tag without checking for a refill.\n//   //  - TryFastAppend must always return decline (return false)\n//   //    if <length> is 61 or more, as in this case the literal length is not\n//   //    decoded fully. In practice, this should not be a big problem,\n//   //    as it is unlikely that one would implement a fast path accepting\n//   //    this much data.\n//   //\n//   bool TryFastAppend(const char* ip, size_t available, size_t length, T* op);\n// };\n\nstatic inline uint32_t ExtractLowBytes(const uint32_t& v, int n) {\n  assert(n >= 0);\n  assert(n <= 4);\n#if SNAPPY_HAVE_BMI2\n  return _bzhi_u32(v, 8 * n);\n#else\n  // This needs to be wider than uint32_t otherwise `mask << 32` will be\n  // undefined.\n  uint64_t mask = 0xffffffff;\n  return v & ~(mask << (8 * n));\n#endif\n}\n\nstatic inline bool LeftShiftOverflows(uint8_t value, uint32_t shift) {\n  assert(shift < 32);\n  static const uint8_t masks[] = {\n      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  //\n      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  //\n      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  //\n      0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe};\n  return (value & masks[shift]) != 0;\n}\n\ninline bool Copy64BytesWithPatternExtension(ptrdiff_t dst, size_t offset) {\n  // TODO: Switch to [[maybe_unused]] when we can assume C++17.\n  (void)dst;\n  return offset != 0;\n}\n\n// Copies between size bytes and 64 bytes from src to dest.  size cannot exceed\n// 64.  More than size bytes, but never exceeding 64, might be copied if doing\n// so gives better performance.  [src, src + size) must not overlap with\n// [dst, dst + size), but [src, src + 64) may overlap with [dst, dst + 64).\nvoid MemCopy64(char* dst, const void* src, size_t size) {\n  // Always copy this many bytes.  If that's below size then copy the full 64.\n  constexpr int kShortMemCopy = 32;\n  (void)kShortMemCopy;\n  assert(size <= 64);\n  assert(std::less_equal<const void*>()(static_cast<const char*>(src) + size,\n                                        dst) ||\n         std::less_equal<const void*>()(dst + size, src));\n\n  // We know that src and dst are at least size bytes apart. However, because we\n  // might copy more than size bytes the copy still might overlap past size.\n  // E.g. if src and dst appear consecutively in memory (src + size >= dst).\n  // TODO: Investigate wider copies on other platforms.\n#if defined(__x86_64__) && defined(__AVX__)\n  assert(kShortMemCopy <= 32);\n  __m256i data = _mm256_lddqu_si256(static_cast<const __m256i *>(src));\n  _mm256_storeu_si256(reinterpret_cast<__m256i *>(dst), data);\n  // Profiling shows that nearly all copies are short.\n  if (SNAPPY_PREDICT_FALSE(size > kShortMemCopy)) {\n    data = _mm256_lddqu_si256(static_cast<const __m256i *>(src) + 1);\n    _mm256_storeu_si256(reinterpret_cast<__m256i *>(dst) + 1, data);\n  }\n  // RVV acceleration available on RISC-V when compiled with -march=rv64gcv\n#elif defined(__riscv) && SNAPPY_HAVE_RVV\n  // Cast pointers to the type we will operate on.\n  unsigned char* dst_ptr = reinterpret_cast<unsigned char*>(dst);\n  const unsigned char* src_ptr = reinterpret_cast<const unsigned char*>(src);\n  size_t remaining_bytes = size;\n  // Loop as long as there are bytes remaining to be copied.\n  while (remaining_bytes > 0) {\n    // Set vector configuration: e8 (8-bit elements), m2 (LMUL=2).\n    // Use e8m2 configuration to maximize throughput.\n    size_t vl = VSETVL_E8M2(remaining_bytes);\n    // Load data from the current source pointer.\n    vuint8m2_t vec = VLE8_V_U8M2(src_ptr, vl);\n    // Store data to the current destination pointer.\n    VSE8_V_U8M2(dst_ptr, vec, vl);\n    // Update pointers and the remaining count.\n    src_ptr += vl;\n    dst_ptr += vl;\n    remaining_bytes -= vl;\n  }\n\n#else\n  std::memmove(dst, src, kShortMemCopy);\n  // Profiling shows that nearly all copies are short.\n  if (SNAPPY_PREDICT_FALSE(size > kShortMemCopy)) {\n    std::memmove(dst + kShortMemCopy,\n                 static_cast<const uint8_t*>(src) + kShortMemCopy,\n                 64 - kShortMemCopy);\n  }\n#endif\n}\n\nvoid MemCopy64(ptrdiff_t dst, const void* src, size_t size) {\n  // TODO: Switch to [[maybe_unused]] when we can assume C++17.\n  (void)dst;\n  (void)src;\n  (void)size;\n}\n\nvoid ClearDeferred(const void** deferred_src, size_t* deferred_length,\n                   uint8_t* safe_source) {\n  *deferred_src = safe_source;\n  *deferred_length = 0;\n}\n\nvoid DeferMemCopy(const void** deferred_src, size_t* deferred_length,\n                  const void* src, size_t length) {\n  *deferred_src = src;\n  *deferred_length = length;\n}\n\nSNAPPY_ATTRIBUTE_ALWAYS_INLINE\ninline size_t AdvanceToNextTagARMOptimized(const uint8_t** ip_p, size_t* tag) {\n  const uint8_t*& ip = *ip_p;\n  // This section is crucial for the throughput of the decompression loop.\n  // The latency of an iteration is fundamentally constrained by the\n  // following data chain on ip.\n  // ip -> c = Load(ip) -> delta1 = (c & 3)        -> ip += delta1 or delta2\n  //                       delta2 = ((c >> 2) + 1)    ip++\n  // This is different from X86 optimizations because ARM has conditional add\n  // instruction (csinc) and it removes several register moves.\n  const size_t tag_type = *tag & 3;\n  const bool is_literal = (tag_type == 0);\n  if (is_literal) {\n    size_t next_literal_tag = (*tag >> 2) + 1;\n    *tag = ip[next_literal_tag];\n    ip += next_literal_tag + 1;\n  } else {\n    *tag = ip[tag_type];\n    ip += tag_type + 1;\n  }\n  return tag_type;\n}\n\nSNAPPY_ATTRIBUTE_ALWAYS_INLINE\ninline size_t AdvanceToNextTagX86Optimized(const uint8_t** ip_p, size_t* tag) {\n  const uint8_t*& ip = *ip_p;\n  // This section is crucial for the throughput of the decompression loop.\n  // The latency of an iteration is fundamentally constrained by the\n  // following data chain on ip.\n  // ip -> c = Load(ip) -> ip1 = ip + 1 + (c & 3) -> ip = ip1 or ip2\n  //                       ip2 = ip + 2 + (c >> 2)\n  // This amounts to 8 cycles.\n  // 5 (load) + 1 (c & 3) + 1 (lea ip1, [ip + (c & 3) + 1]) + 1 (cmov)\n  size_t literal_len = *tag >> 2;\n  size_t tag_type = *tag;\n  bool is_literal;\n#if defined(__GCC_ASM_FLAG_OUTPUTS__) && defined(__x86_64__)\n  // TODO clang misses the fact that the (c & 3) already correctly\n  // sets the zero flag.\n  asm(\"and $3, %k[tag_type]\\n\\t\"\n      : [tag_type] \"+r\"(tag_type), \"=@ccz\"(is_literal)\n      :: \"cc\");\n#else\n  tag_type &= 3;\n  is_literal = (tag_type == 0);\n#endif\n  // TODO\n  // This is code is subtle. Loading the values first and then cmov has less\n  // latency then cmov ip and then load. However clang would move the loads\n  // in an optimization phase, volatile prevents this transformation.\n  // Note that we have enough slop bytes (64) that the loads are always valid.\n  size_t tag_literal =\n      static_cast<const volatile uint8_t*>(ip)[1 + literal_len];\n  size_t tag_copy = static_cast<const volatile uint8_t*>(ip)[tag_type];\n  *tag = is_literal ? tag_literal : tag_copy;\n  const uint8_t* ip_copy = ip + 1 + tag_type;\n  const uint8_t* ip_literal = ip + 2 + literal_len;\n  ip = is_literal ? ip_literal : ip_copy;\n#if defined(__GNUC__) && defined(__x86_64__)\n  // TODO Clang is \"optimizing\" zero-extension (a totally free\n  // operation) this means that after the cmov of tag, it emits another movzb\n  // tag, byte(tag). It really matters as it's on the core chain. This dummy\n  // asm, persuades clang to do the zero-extension at the load (it's automatic)\n  // removing the expensive movzb.\n  asm(\"\" ::\"r\"(tag_copy));\n#endif\n  return tag_type;\n}\n\n// Extract the offset for copy-1 and copy-2 returns 0 for literals or copy-4.\ninline uint32_t ExtractOffset(uint32_t val, size_t tag_type) {\n  // For x86 non-static storage works better. For ARM static storage is better.\n  // TODO: Once the array is recognized as a register, improve the\n  // readability for x86.\n#if defined(__x86_64__)\n  constexpr uint64_t kExtractMasksCombined = 0x0000FFFF00FF0000ull;\n  uint16_t result;\n  memcpy(&result,\n         reinterpret_cast<const char*>(&kExtractMasksCombined) + 2 * tag_type,\n         sizeof(result));\n  return val & result;\n#elif defined(__aarch64__)\n  constexpr uint64_t kExtractMasksCombined = 0x0000FFFF00FF0000ull;\n  return val & static_cast<uint32_t>(\n      (kExtractMasksCombined >> (tag_type * 16)) & 0xFFFF);\n#else\n  static constexpr uint32_t kExtractMasks[4] = {0, 0xFF, 0xFFFF, 0};\n  return val & kExtractMasks[tag_type];\n#endif\n};\n\n// Core decompression loop, when there is enough data available.\n// Decompresses the input buffer [ip, ip_limit) into the output buffer\n// [op, op_limit_min_slop). Returning when either we are too close to the end\n// of the input buffer, or we exceed op_limit_min_slop or when a exceptional\n// tag is encountered (literal of length > 60) or a copy-4.\n// Returns {ip, op} at the points it stopped decoding.\n// TODO This function probably does not need to be inlined, as it\n// should decode large chunks at a time. This allows runtime dispatch to\n// implementations based on CPU capability (BMI2 / perhaps 32 / 64 byte memcpy).\ntemplate <typename T>\nstd::pair<const uint8_t*, ptrdiff_t> DecompressBranchless(\n    const uint8_t* ip, const uint8_t* ip_limit, ptrdiff_t op, T op_base,\n    ptrdiff_t op_limit_min_slop) {\n  // If deferred_src is invalid point it here.\n  uint8_t safe_source[64];\n  const void* deferred_src;\n  size_t deferred_length;\n  ClearDeferred(&deferred_src, &deferred_length, safe_source);\n\n  // We unroll the inner loop twice so we need twice the spare room.\n  op_limit_min_slop -= kSlopBytes;\n  if (2 * (kSlopBytes + 1) < ip_limit - ip && op < op_limit_min_slop) {\n    const uint8_t* const ip_limit_min_slop = ip_limit - 2 * kSlopBytes - 1;\n    ip++;\n    // ip points just past the tag and we are touching at maximum kSlopBytes\n    // in an iteration.\n    size_t tag = ip[-1];\n#if defined(__clang__) && defined(__aarch64__)\n    // Workaround for https://bugs.llvm.org/show_bug.cgi?id=51317\n    // when loading 1 byte, clang for aarch64 doesn't realize that it(ldrb)\n    // comes with free zero-extension, so clang generates another\n    // 'and xn, xm, 0xff' before it use that as the offset. This 'and' is\n    // redundant and can be removed by adding this dummy asm, which gives\n    // clang a hint that we're doing the zero-extension at the load.\n    asm(\"\" ::\"r\"(tag));\n#endif\n    do {\n      // The throughput is limited by instructions, unrolling the inner loop\n      // twice reduces the amount of instructions checking limits and also\n      // leads to reduced mov's.\n\n      SNAPPY_PREFETCH(ip + 128);\n      for (int i = 0; i < 2; i++) {\n        const uint8_t* old_ip = ip;\n        assert(tag == ip[-1]);\n        // For literals tag_type = 0, hence we will always obtain 0 from\n        // ExtractLowBytes. For literals offset will thus be kLiteralOffset.\n        ptrdiff_t len_minus_offset = kLengthMinusOffset[tag];\n        uint32_t next;\n#if defined(__aarch64__)\n        size_t tag_type = AdvanceToNextTagARMOptimized(&ip, &tag);\n        // We never need more than 16 bits. Doing a Load16 allows the compiler\n        // to elide the masking operation in ExtractOffset.\n        next = LittleEndian::Load16(old_ip);\n#else\n        size_t tag_type = AdvanceToNextTagX86Optimized(&ip, &tag);\n        next = LittleEndian::Load32(old_ip);\n#endif\n        size_t len = len_minus_offset & 0xFF;\n        ptrdiff_t extracted = ExtractOffset(next, tag_type);\n        ptrdiff_t len_min_offset = len_minus_offset - extracted;\n        if (SNAPPY_PREDICT_FALSE(len_minus_offset > extracted)) {\n          if (SNAPPY_PREDICT_FALSE(len & 0x80)) {\n            // Exceptional case (long literal or copy 4).\n            // Actually doing the copy here is negatively impacting the main\n            // loop due to compiler incorrectly allocating a register for\n            // this fallback. Hence we just break.\n          break_loop:\n            ip = old_ip;\n            goto exit;\n          }\n          // Only copy-1 or copy-2 tags can get here.\n          assert(tag_type == 1 || tag_type == 2);\n          std::ptrdiff_t delta = (op + deferred_length) + len_min_offset - len;\n          // Guard against copies before the buffer start.\n          // Execute any deferred MemCopy since we write to dst here.\n          MemCopy64(op_base + op, deferred_src, deferred_length);\n          op += deferred_length;\n          ClearDeferred(&deferred_src, &deferred_length, safe_source);\n          if (SNAPPY_PREDICT_FALSE(delta < 0 ||\n                                  !Copy64BytesWithPatternExtension(\n                                      op_base + op, len - len_min_offset))) {\n            goto break_loop;\n          }\n          // We aren't deferring this copy so add length right away.\n          op += len;\n          continue;\n        }\n        std::ptrdiff_t delta = (op + deferred_length) + len_min_offset - len;\n        if (SNAPPY_PREDICT_FALSE(delta < 0)) {\n          // Due to the spurious offset in literals have this will trigger\n          // at the start of a block when op is still smaller than 256.\n          if (tag_type != 0) goto break_loop;\n          MemCopy64(op_base + op, deferred_src, deferred_length);\n          op += deferred_length;\n          DeferMemCopy(&deferred_src, &deferred_length, old_ip, len);\n          continue;\n        }\n\n        // For copies we need to copy from op_base + delta, for literals\n        // we need to copy from ip instead of from the stream.\n        const void* from =\n            tag_type ? reinterpret_cast<void*>(op_base + delta) : old_ip;\n        MemCopy64(op_base + op, deferred_src, deferred_length);\n        op += deferred_length;\n        DeferMemCopy(&deferred_src, &deferred_length, from, len);\n      }\n    } while (ip < ip_limit_min_slop &&\n             static_cast<ptrdiff_t>(op + deferred_length) < op_limit_min_slop);\n  exit:\n    ip--;\n    assert(ip <= ip_limit);\n  }\n  // If we deferred a copy then we can perform.  If we are up to date then we\n  // might not have enough slop bytes and could run past the end.\n  if (deferred_length) {\n    MemCopy64(op_base + op, deferred_src, deferred_length);\n    op += deferred_length;\n    ClearDeferred(&deferred_src, &deferred_length, safe_source);\n  }\n  return {ip, op};\n}\n\n// Helper class for decompression\nclass SnappyDecompressor {\n private:\n  Source* reader_;        // Underlying source of bytes to decompress\n  const char* ip_;        // Points to next buffered byte\n  const char* ip_limit_;  // Points just past buffered bytes\n  // If ip < ip_limit_min_maxtaglen_ it's safe to read kMaxTagLength from\n  // buffer.\n  const char* ip_limit_min_maxtaglen_;\n  uint64_t peeked_;                  // Bytes peeked from reader (need to skip)\n  bool eof_;                         // Hit end of input without an error?\n  char scratch_[kMaximumTagLength];  // See RefillTag().\n\n  // Ensure that all of the tag metadata for the next tag is available\n  // in [ip_..ip_limit_-1].  Also ensures that [ip,ip+4] is readable even\n  // if (ip_limit_ - ip_ < 5).\n  //\n  // Returns true on success, false on error or end of input.\n  bool RefillTag();\n\n  void ResetLimit(const char* ip) {\n    ip_limit_min_maxtaglen_ =\n        ip_limit_ - std::min<ptrdiff_t>(ip_limit_ - ip, kMaximumTagLength - 1);\n  }\n\n public:\n  explicit SnappyDecompressor(Source* reader)\n      : reader_(reader), ip_(NULL), ip_limit_(NULL), peeked_(0), eof_(false) {}\n\n  ~SnappyDecompressor() {\n    // Advance past any bytes we peeked at from the reader\n    reader_->Skip(peeked_);\n  }\n\n  // Returns true iff we have hit the end of the input without an error.\n  bool eof() const { return eof_; }\n\n  // Read the uncompressed length stored at the start of the compressed data.\n  // On success, stores the length in *result and returns true.\n  // On failure, returns false.\n  bool ReadUncompressedLength(uint32_t* result) {\n    assert(ip_ == NULL);  // Must not have read anything yet\n    // Length is encoded in 1..5 bytes\n    *result = 0;\n    uint32_t shift = 0;\n    while (true) {\n      if (shift >= 32) return false;\n      size_t n;\n      const char* ip = reader_->Peek(&n);\n      if (n == 0) return false;\n      const unsigned char c = *(reinterpret_cast<const unsigned char*>(ip));\n      reader_->Skip(1);\n      uint32_t val = c & 0x7f;\n      if (LeftShiftOverflows(static_cast<uint8_t>(val), shift)) return false;\n      *result |= val << shift;\n      if (c < 128) {\n        break;\n      }\n      shift += 7;\n    }\n    return true;\n  }\n\n  // Process the next item found in the input.\n  // Returns true if successful, false on error or end of input.\n  template <class Writer>\n#if defined(__GNUC__) && defined(__x86_64__)\n  __attribute__((aligned(32)))\n#endif\n  void\n  DecompressAllTags(Writer* writer) {\n    const char* ip = ip_;\n    ResetLimit(ip);\n    auto op = writer->GetOutputPtr();\n    // We could have put this refill fragment only at the beginning of the loop.\n    // However, duplicating it at the end of each branch gives the compiler more\n    // scope to optimize the <ip_limit_ - ip> expression based on the local\n    // context, which overall increases speed.\n#define MAYBE_REFILL()                                      \\\n  if (SNAPPY_PREDICT_FALSE(ip >= ip_limit_min_maxtaglen_)) { \\\n    ip_ = ip;                                               \\\n    if (SNAPPY_PREDICT_FALSE(!RefillTag())) goto exit;       \\\n    ip = ip_;                                               \\\n    ResetLimit(ip);                                         \\\n  }                                                         \\\n  preload = static_cast<uint8_t>(*ip)\n\n    // At the start of the for loop below the least significant byte of preload\n    // contains the tag.\n    uint32_t preload;\n    MAYBE_REFILL();\n    for (;;) {\n      {\n        ptrdiff_t op_limit_min_slop;\n        auto op_base = writer->GetBase(&op_limit_min_slop);\n        if (op_base) {\n          auto res =\n              DecompressBranchless(reinterpret_cast<const uint8_t*>(ip),\n                                   reinterpret_cast<const uint8_t*>(ip_limit_),\n                                   op - op_base, op_base, op_limit_min_slop);\n          ip = reinterpret_cast<const char*>(res.first);\n          op = op_base + res.second;\n          MAYBE_REFILL();\n        }\n      }\n      const uint8_t c = static_cast<uint8_t>(preload);\n      ip++;\n\n      // Ratio of iterations that have LITERAL vs non-LITERAL for different\n      // inputs.\n      //\n      // input          LITERAL  NON_LITERAL\n      // -----------------------------------\n      // html|html4|cp   23%        77%\n      // urls            36%        64%\n      // jpg             47%        53%\n      // pdf             19%        81%\n      // txt[1-4]        25%        75%\n      // pb              24%        76%\n      // bin             24%        76%\n      if (SNAPPY_PREDICT_FALSE((c & 0x3) == LITERAL)) {\n        size_t literal_length = (c >> 2) + 1u;\n        if (writer->TryFastAppend(ip, ip_limit_ - ip, literal_length, &op)) {\n          assert(literal_length < 61);\n          ip += literal_length;\n          // NOTE: There is no MAYBE_REFILL() here, as TryFastAppend()\n          // will not return true unless there's already at least five spare\n          // bytes in addition to the literal.\n          preload = static_cast<uint8_t>(*ip);\n          continue;\n        }\n        if (SNAPPY_PREDICT_FALSE(literal_length >= 61)) {\n          // Long literal.\n          const size_t literal_length_length = literal_length - 60;\n          literal_length =\n              ExtractLowBytes(LittleEndian::Load32(ip), literal_length_length) +\n              1;\n          ip += literal_length_length;\n        }\n\n        size_t avail = ip_limit_ - ip;\n        while (avail < literal_length) {\n          if (!writer->Append(ip, avail, &op)) goto exit;\n          literal_length -= avail;\n          reader_->Skip(peeked_);\n          size_t n;\n          ip = reader_->Peek(&n);\n          avail = n;\n          peeked_ = avail;\n          if (avail == 0) goto exit;\n          ip_limit_ = ip + avail;\n          ResetLimit(ip);\n        }\n        if (!writer->Append(ip, literal_length, &op)) goto exit;\n        ip += literal_length;\n        MAYBE_REFILL();\n      } else {\n        if (SNAPPY_PREDICT_FALSE((c & 3) == COPY_4_BYTE_OFFSET)) {\n          const size_t copy_offset = LittleEndian::Load32(ip);\n          const size_t length = (c >> 2) + 1;\n          ip += 4;\n\n          if (!writer->AppendFromSelf(copy_offset, length, &op)) goto exit;\n        } else {\n          const ptrdiff_t entry = kLengthMinusOffset[c];\n          preload = LittleEndian::Load32(ip);\n          const uint32_t trailer = ExtractLowBytes(preload, c & 3);\n          const uint32_t length = entry & 0xff;\n          assert(length > 0);\n\n          // copy_offset/256 is encoded in bits 8..10.  By just fetching\n          // those bits, we get copy_offset (since the bit-field starts at\n          // bit 8).\n          const uint32_t copy_offset = trailer - entry + length;\n          if (!writer->AppendFromSelf(copy_offset, length, &op)) goto exit;\n\n          ip += (c & 3);\n          // By using the result of the previous load we reduce the critical\n          // dependency chain of ip to 4 cycles.\n          preload >>= (c & 3) * 8;\n          if (ip < ip_limit_min_maxtaglen_) continue;\n        }\n        MAYBE_REFILL();\n      }\n    }\n#undef MAYBE_REFILL\n  exit:\n    writer->SetOutputPtr(op);\n  }\n};\n\nconstexpr uint32_t CalculateNeeded(uint8_t tag) {\n  return ((tag & 3) == 0 && tag >= (60 * 4))\n             ? (tag >> 2) - 58\n             : (0x05030201 >> ((tag * 8) & 31)) & 0xFF;\n}\n\n#if __cplusplus >= 201402L\nconstexpr bool VerifyCalculateNeeded() {\n  for (int i = 0; i < 1; i++) {\n    if (CalculateNeeded(i) != static_cast<uint32_t>((char_table[i] >> 11)) + 1)\n      return false;\n  }\n  return true;\n}\n\n// Make sure CalculateNeeded is correct by verifying it against the established\n// table encoding the number of added bytes needed.\nstatic_assert(VerifyCalculateNeeded(), \"\");\n#endif  // c++14\n\nbool SnappyDecompressor::RefillTag() {\n  const char* ip = ip_;\n  if (ip == ip_limit_) {\n    // Fetch a new fragment from the reader\n    reader_->Skip(peeked_);  // All peeked bytes are used up\n    size_t n;\n    ip = reader_->Peek(&n);\n    peeked_ = n;\n    eof_ = (n == 0);\n    if (eof_) return false;\n    ip_limit_ = ip + n;\n  }\n\n  // Read the tag character\n  assert(ip < ip_limit_);\n  const unsigned char c = *(reinterpret_cast<const unsigned char*>(ip));\n  // At this point make sure that the data for the next tag is consecutive.\n  // For copy 1 this means the next 2 bytes (tag and 1 byte offset)\n  // For copy 2 the next 3 bytes (tag and 2 byte offset)\n  // For copy 4 the next 5 bytes (tag and 4 byte offset)\n  // For all small literals we only need 1 byte buf for literals 60...63 the\n  // length is encoded in 1...4 extra bytes.\n  const uint32_t needed = CalculateNeeded(c);\n  assert(needed <= sizeof(scratch_));\n\n  // Read more bytes from reader if needed\n  uint64_t nbuf = ip_limit_ - ip;\n  if (nbuf < needed) {\n    // Stitch together bytes from ip and reader to form the word\n    // contents.  We store the needed bytes in \"scratch_\".  They\n    // will be consumed immediately by the caller since we do not\n    // read more than we need.\n    std::memmove(scratch_, ip, nbuf);\n    reader_->Skip(peeked_);  // All peeked bytes are used up\n    peeked_ = 0;\n    while (nbuf < needed) {\n      size_t length;\n      const char* src = reader_->Peek(&length);\n      if (length == 0) return false;\n      uint64_t to_add = std::min<uint64_t>(needed - nbuf, length);\n      std::memcpy(scratch_ + nbuf, src, to_add);\n      nbuf += to_add;\n      reader_->Skip(to_add);\n    }\n    assert(nbuf == needed);\n    ip_ = scratch_;\n    ip_limit_ = scratch_ + needed;\n  } else if (nbuf < kMaximumTagLength) {\n    // Have enough bytes, but move into scratch_ so that we do not\n    // read past end of input\n    std::memmove(scratch_, ip, nbuf);\n    reader_->Skip(peeked_);  // All peeked bytes are used up\n    peeked_ = 0;\n    ip_ = scratch_;\n    ip_limit_ = scratch_ + nbuf;\n  } else {\n    // Pass pointer to buffer returned by reader_.\n    ip_ = ip;\n  }\n  return true;\n}\n\ntemplate <typename Writer>\nstatic bool InternalUncompress(Source* r, Writer* writer) {\n  // Read the uncompressed length from the front of the compressed input\n  SnappyDecompressor decompressor(r);\n  uint32_t uncompressed_len = 0;\n  if (!decompressor.ReadUncompressedLength(&uncompressed_len)) return false;\n\n  return InternalUncompressAllTags(&decompressor, writer, r->Available(),\n                                   uncompressed_len);\n}\n\ntemplate <typename Writer>\nstatic bool InternalUncompressAllTags(SnappyDecompressor* decompressor,\n                                      Writer* writer, uint32_t compressed_len,\n                                      uint32_t uncompressed_len) {\n    int token = 0;\n  Report(token, \"snappy_uncompress\", compressed_len, uncompressed_len);\n\n  writer->SetExpectedLength(uncompressed_len);\n\n  // Process the entire input\n  decompressor->DecompressAllTags(writer);\n  writer->Flush();\n  return (decompressor->eof() && writer->CheckLength());\n}\n\nbool GetUncompressedLength(Source* source, uint32_t* result) {\n  SnappyDecompressor decompressor(source);\n  return decompressor.ReadUncompressedLength(result);\n}\n\nsize_t Compress(Source* reader, Sink* writer) {\n  return Compress(reader, writer, CompressionOptions{});\n}\n\nsize_t Compress(Source* reader, Sink* writer, CompressionOptions options) {\n  assert(options.level == 1 || options.level == 2);\n  int token = 0;\n  size_t written = 0;\n  size_t N = reader->Available();\n  assert(N <= 0xFFFFFFFFu);\n  const size_t uncompressed_size = N;\n  char ulength[Varint::kMax32];\n  char* p = Varint::Encode32(ulength, N);\n  writer->Append(ulength, p - ulength);\n  written += (p - ulength);\n\n  internal::WorkingMemory wmem(N);\n\n  while (N > 0) {\n    // Get next block to compress (without copying if possible)\n    size_t fragment_size;\n    const char* fragment = reader->Peek(&fragment_size);\n    assert(fragment_size != 0);  // premature end of input\n    const size_t num_to_read = std::min(N, kBlockSize);\n    size_t bytes_read = fragment_size;\n\n    size_t pending_advance = 0;\n    if (bytes_read >= num_to_read) {\n      // Buffer returned by reader is large enough\n      pending_advance = num_to_read;\n      fragment_size = num_to_read;\n    } else {\n      char* scratch = wmem.GetScratchInput();\n      std::memcpy(scratch, fragment, bytes_read);\n      reader->Skip(bytes_read);\n\n      while (bytes_read < num_to_read) {\n        fragment = reader->Peek(&fragment_size);\n        size_t n = std::min<size_t>(fragment_size, num_to_read - bytes_read);\n        std::memcpy(scratch + bytes_read, fragment, n);\n        bytes_read += n;\n        reader->Skip(n);\n      }\n      assert(bytes_read == num_to_read);\n      fragment = scratch;\n      fragment_size = num_to_read;\n    }\n    assert(fragment_size == num_to_read);\n\n    // Get encoding table for compression\n    int table_size;\n    uint16_t* table = wmem.GetHashTable(num_to_read, &table_size);\n\n    // Compress input_fragment and append to dest\n    int max_output = MaxCompressedLength(num_to_read);\n\n    // Since we encode kBlockSize regions followed by a region\n    // which is <= kBlockSize in length, a previously allocated\n    // scratch_output[] region is big enough for this iteration.\n    // Need a scratch buffer for the output, in case the byte sink doesn't\n    // have room for us directly.\n    char* dest = writer->GetAppendBuffer(max_output, wmem.GetScratchOutput());\n    char* end = nullptr;\n    if (options.level == 1) {\n      end = internal::CompressFragment(fragment, fragment_size, dest, table,\n                                       table_size);\n    } else if (options.level == 2) {\n      end = internal::CompressFragmentDoubleHash(\n          fragment, fragment_size, dest, table, table_size >> 1,\n          table + (table_size >> 1), table_size >> 1);\n    }\n    writer->Append(dest, end - dest);\n    written += (end - dest);\n\n    N -= num_to_read;\n    reader->Skip(pending_advance);\n  }\n\n  Report(token, \"snappy_compress\", written, uncompressed_size);\n  return written;\n}\n\n// -----------------------------------------------------------------------\n// IOVec interfaces\n// -----------------------------------------------------------------------\n\n// A `Source` implementation that yields the contents of an `iovec` array. Note\n// that `total_size` is the total number of bytes to be read from the elements\n// of `iov` (_not_ the total number of elements in `iov`).\nclass SnappyIOVecReader : public Source {\n public:\n  SnappyIOVecReader(const struct iovec* iov, size_t total_size)\n      : curr_iov_(iov),\n        curr_pos_(total_size > 0 ? reinterpret_cast<const char*>(iov->iov_base)\n                                 : nullptr),\n        curr_size_remaining_(total_size > 0 ? iov->iov_len : 0),\n        total_size_remaining_(total_size) {\n    // Skip empty leading `iovec`s.\n    if (total_size > 0 && curr_size_remaining_ == 0) Advance();\n  }\n\n  ~SnappyIOVecReader() override = default;\n\n  size_t Available() const override { return total_size_remaining_; }\n\n  const char* Peek(size_t* len) override {\n    *len = curr_size_remaining_;\n    return curr_pos_;\n  }\n\n  void Skip(size_t n) override {\n    while (n >= curr_size_remaining_ && n > 0) {\n      n -= curr_size_remaining_;\n      Advance();\n    }\n    curr_size_remaining_ -= n;\n    total_size_remaining_ -= n;\n    curr_pos_ += n;\n  }\n\n private:\n  // Advances to the next nonempty `iovec` and updates related variables.\n  void Advance() {\n    do {\n      assert(total_size_remaining_ >= curr_size_remaining_);\n      total_size_remaining_ -= curr_size_remaining_;\n      if (total_size_remaining_ == 0) {\n        curr_pos_ = nullptr;\n        curr_size_remaining_ = 0;\n        return;\n      }\n      ++curr_iov_;\n      curr_pos_ = reinterpret_cast<const char*>(curr_iov_->iov_base);\n      curr_size_remaining_ = curr_iov_->iov_len;\n    } while (curr_size_remaining_ == 0);\n  }\n\n  // The `iovec` currently being read.\n  const struct iovec* curr_iov_;\n  // The location in `curr_iov_` currently being read.\n  const char* curr_pos_;\n  // The amount of unread data in `curr_iov_`.\n  size_t curr_size_remaining_;\n  // The amount of unread data in the entire input array.\n  size_t total_size_remaining_;\n};\n\n// A type that writes to an iovec.\n// Note that this is not a \"ByteSink\", but a type that matches the\n// Writer template argument to SnappyDecompressor::DecompressAllTags().\nclass SnappyIOVecWriter {\n private:\n  // output_iov_end_ is set to iov + count and used to determine when\n  // the end of the iovs is reached.\n  const struct iovec* output_iov_end_;\n\n#if !defined(NDEBUG)\n  const struct iovec* output_iov_;\n#endif  // !defined(NDEBUG)\n\n  // Current iov that is being written into.\n  const struct iovec* curr_iov_;\n\n  // Pointer to current iov's write location.\n  char* curr_iov_output_;\n\n  // Remaining bytes to write into curr_iov_output.\n  size_t curr_iov_remaining_;\n\n  // Total bytes decompressed into output_iov_ so far.\n  size_t total_written_;\n\n  // Maximum number of bytes that will be decompressed into output_iov_.\n  size_t output_limit_;\n\n  static inline char* GetIOVecPointer(const struct iovec* iov, size_t offset) {\n    return reinterpret_cast<char*>(iov->iov_base) + offset;\n  }\n\n public:\n  // Does not take ownership of iov. iov must be valid during the\n  // entire lifetime of the SnappyIOVecWriter.\n  inline SnappyIOVecWriter(const struct iovec* iov, size_t iov_count)\n      : output_iov_end_(iov + iov_count),\n#if !defined(NDEBUG)\n        output_iov_(iov),\n#endif  // !defined(NDEBUG)\n        curr_iov_(iov),\n        curr_iov_output_(iov_count ? reinterpret_cast<char*>(iov->iov_base)\n                                   : nullptr),\n        curr_iov_remaining_(iov_count ? iov->iov_len : 0),\n        total_written_(0),\n        output_limit_(-1) {\n  }\n\n  inline void SetExpectedLength(size_t len) { output_limit_ = len; }\n\n  inline bool CheckLength() const { return total_written_ == output_limit_; }\n\n  inline bool Append(const char* ip, size_t len, char**) {\n    if (total_written_ + len > output_limit_) {\n      return false;\n    }\n\n    return AppendNoCheck(ip, len);\n  }\n\n  char* GetOutputPtr() { return nullptr; }\n  char* GetBase(ptrdiff_t*) { return nullptr; }\n  void SetOutputPtr(char* op) {\n    // TODO: Switch to [[maybe_unused]] when we can assume C++17.\n    (void)op;\n  }\n\n  inline bool AppendNoCheck(const char* ip, size_t len) {\n    while (len > 0) {\n      if (curr_iov_remaining_ == 0) {\n        // This iovec is full. Go to the next one.\n        if (curr_iov_ + 1 >= output_iov_end_) {\n          return false;\n        }\n        ++curr_iov_;\n        curr_iov_output_ = reinterpret_cast<char*>(curr_iov_->iov_base);\n        curr_iov_remaining_ = curr_iov_->iov_len;\n      }\n\n      const size_t to_write = std::min(len, curr_iov_remaining_);\n      std::memcpy(curr_iov_output_, ip, to_write);\n      curr_iov_output_ += to_write;\n      curr_iov_remaining_ -= to_write;\n      total_written_ += to_write;\n      ip += to_write;\n      len -= to_write;\n    }\n\n    return true;\n  }\n\n  inline bool TryFastAppend(const char* ip, size_t available, size_t len,\n                            char**) {\n    const size_t space_left = output_limit_ - total_written_;\n    if (len <= 16 && available >= 16 + kMaximumTagLength && space_left >= 16 &&\n        curr_iov_remaining_ >= 16) {\n      // Fast path, used for the majority (about 95%) of invocations.\n      UnalignedCopy128(ip, curr_iov_output_);\n      curr_iov_output_ += len;\n      curr_iov_remaining_ -= len;\n      total_written_ += len;\n      return true;\n    }\n\n    return false;\n  }\n\n  inline bool AppendFromSelf(size_t offset, size_t len, char**) {\n    // See SnappyArrayWriter::AppendFromSelf for an explanation of\n    // the \"offset - 1u\" trick.\n    if (offset - 1u >= total_written_) {\n      return false;\n    }\n    const size_t space_left = output_limit_ - total_written_;\n    if (len > space_left) {\n      return false;\n    }\n\n    // Locate the iovec from which we need to start the copy.\n    const iovec* from_iov = curr_iov_;\n    size_t from_iov_offset = curr_iov_->iov_len - curr_iov_remaining_;\n    while (offset > 0) {\n      if (from_iov_offset >= offset) {\n        from_iov_offset -= offset;\n        break;\n      }\n\n      offset -= from_iov_offset;\n      --from_iov;\n#if !defined(NDEBUG)\n      assert(from_iov >= output_iov_);\n#endif  // !defined(NDEBUG)\n      from_iov_offset = from_iov->iov_len;\n    }\n\n    // Copy <len> bytes starting from the iovec pointed to by from_iov_index to\n    // the current iovec.\n    while (len > 0) {\n      assert(from_iov <= curr_iov_);\n      if (from_iov != curr_iov_) {\n        const size_t to_copy =\n            std::min(from_iov->iov_len - from_iov_offset, len);\n        AppendNoCheck(GetIOVecPointer(from_iov, from_iov_offset), to_copy);\n        len -= to_copy;\n        if (len > 0) {\n          ++from_iov;\n          from_iov_offset = 0;\n        }\n      } else {\n        size_t to_copy = curr_iov_remaining_;\n        if (to_copy == 0) {\n          // This iovec is full. Go to the next one.\n          if (curr_iov_ + 1 >= output_iov_end_) {\n            return false;\n          }\n          ++curr_iov_;\n          curr_iov_output_ = reinterpret_cast<char*>(curr_iov_->iov_base);\n          curr_iov_remaining_ = curr_iov_->iov_len;\n          continue;\n        }\n        if (to_copy > len) {\n          to_copy = len;\n        }\n        assert(to_copy > 0);\n\n        IncrementalCopy(GetIOVecPointer(from_iov, from_iov_offset),\n                        curr_iov_output_, curr_iov_output_ + to_copy,\n                        curr_iov_output_ + curr_iov_remaining_);\n        curr_iov_output_ += to_copy;\n        curr_iov_remaining_ -= to_copy;\n        from_iov_offset += to_copy;\n        total_written_ += to_copy;\n        len -= to_copy;\n      }\n    }\n\n    return true;\n  }\n\n  inline void Flush() {}\n};\n\nbool RawUncompressToIOVec(const char* compressed, size_t compressed_length,\n                          const struct iovec* iov, size_t iov_cnt) {\n  ByteArraySource reader(compressed, compressed_length);\n  return RawUncompressToIOVec(&reader, iov, iov_cnt);\n}\n\nbool RawUncompressToIOVec(Source* compressed, const struct iovec* iov,\n                          size_t iov_cnt) {\n  SnappyIOVecWriter output(iov, iov_cnt);\n  return InternalUncompress(compressed, &output);\n}\n\n// -----------------------------------------------------------------------\n// Flat array interfaces\n// -----------------------------------------------------------------------\n\n// A type that writes to a flat array.\n// Note that this is not a \"ByteSink\", but a type that matches the\n// Writer template argument to SnappyDecompressor::DecompressAllTags().\nclass SnappyArrayWriter {\n private:\n  char* base_;\n  char* op_;\n  char* op_limit_;\n  // If op < op_limit_min_slop_ then it's safe to unconditionally write\n  // kSlopBytes starting at op.\n  char* op_limit_min_slop_;\n\n public:\n  inline explicit SnappyArrayWriter(char* dst)\n      : base_(dst),\n        op_(dst),\n        op_limit_(dst),\n        op_limit_min_slop_(dst) {}  // Safe default see invariant.\n\n  inline void SetExpectedLength(size_t len) {\n    op_limit_ = op_ + len;\n    // Prevent pointer from being past the buffer.\n    op_limit_min_slop_ = op_limit_ - std::min<size_t>(kSlopBytes - 1, len);\n  }\n\n  inline bool CheckLength() const { return op_ == op_limit_; }\n\n  char* GetOutputPtr() { return op_; }\n  char* GetBase(ptrdiff_t* op_limit_min_slop) {\n    *op_limit_min_slop = op_limit_min_slop_ - base_;\n    return base_;\n  }\n  void SetOutputPtr(char* op) { op_ = op; }\n\n  inline bool Append(const char* ip, size_t len, char** op_p) {\n    char* op = *op_p;\n    const size_t space_left = op_limit_ - op;\n    if (space_left < len) return false;\n    std::memcpy(op, ip, len);\n    *op_p = op + len;\n    return true;\n  }\n\n  inline bool TryFastAppend(const char* ip, size_t available, size_t len,\n                            char** op_p) {\n    char* op = *op_p;\n    const size_t space_left = op_limit_ - op;\n    if (len <= 16 && available >= 16 + kMaximumTagLength && space_left >= 16) {\n      // Fast path, used for the majority (about 95%) of invocations.\n      UnalignedCopy128(ip, op);\n      *op_p = op + len;\n      return true;\n    } else {\n      return false;\n    }\n  }\n\n  SNAPPY_ATTRIBUTE_ALWAYS_INLINE\n  inline bool AppendFromSelf(size_t offset, size_t len, char** op_p) {\n    assert(len > 0);\n    char* const op = *op_p;\n    assert(op >= base_);\n    char* const op_end = op + len;\n\n    // Check if we try to append from before the start of the buffer.\n    if (SNAPPY_PREDICT_FALSE(static_cast<size_t>(op - base_) < offset))\n      return false;\n\n    if (SNAPPY_PREDICT_FALSE((kSlopBytes < 64 && len > kSlopBytes) ||\n                            op >= op_limit_min_slop_ || offset < len)) {\n      if (op_end > op_limit_ || offset == 0) return false;\n      *op_p = IncrementalCopy(op - offset, op, op_end, op_limit_);\n      return true;\n    }\n    std::memmove(op, op - offset, kSlopBytes);\n    *op_p = op_end;\n    return true;\n  }\n  inline size_t Produced() const {\n    assert(op_ >= base_);\n    return op_ - base_;\n  }\n  inline void Flush() {}\n};\n\nbool RawUncompress(const char* compressed, size_t compressed_length,\n                   char* uncompressed) {\n  ByteArraySource reader(compressed, compressed_length);\n  return RawUncompress(&reader, uncompressed);\n}\n\nbool RawUncompress(Source* compressed, char* uncompressed) {\n  SnappyArrayWriter output(uncompressed);\n  return InternalUncompress(compressed, &output);\n}\n\nbool Uncompress(const char* compressed, size_t compressed_length,\n                std::string* uncompressed) {\n  size_t ulength;\n  if (!GetUncompressedLength(compressed, compressed_length, &ulength)) {\n    return false;\n  }\n  // On 32-bit builds: max_size() < kuint32max.  Check for that instead\n  // of crashing (e.g., consider externally specified compressed data).\n  if (ulength > uncompressed->max_size()) {\n    return false;\n  }\n  STLStringResizeUninitialized(uncompressed, ulength);\n  return RawUncompress(compressed, compressed_length,\n                       string_as_array(uncompressed));\n}\n\n// A Writer that drops everything on the floor and just does validation\nclass SnappyDecompressionValidator {\n private:\n  size_t expected_;\n  size_t produced_;\n\n public:\n  inline SnappyDecompressionValidator() : expected_(0), produced_(0) {}\n  inline void SetExpectedLength(size_t len) { expected_ = len; }\n  size_t GetOutputPtr() { return produced_; }\n  size_t GetBase(ptrdiff_t* op_limit_min_slop) {\n    *op_limit_min_slop = std::numeric_limits<ptrdiff_t>::max() - kSlopBytes + 1;\n    return 1;\n  }\n  void SetOutputPtr(size_t op) { produced_ = op; }\n  inline bool CheckLength() const { return expected_ == produced_; }\n  inline bool Append(const char* ip, size_t len, size_t* produced) {\n    // TODO: Switch to [[maybe_unused]] when we can assume C++17.\n    (void)ip;\n\n    *produced += len;\n    return *produced <= expected_;\n  }\n  inline bool TryFastAppend(const char* ip, size_t available, size_t length,\n                            size_t* produced) {\n    // TODO: Switch to [[maybe_unused]] when we can assume C++17.\n    (void)ip;\n    (void)available;\n    (void)length;\n    (void)produced;\n\n    return false;\n  }\n  inline bool AppendFromSelf(size_t offset, size_t len, size_t* produced) {\n    // See SnappyArrayWriter::AppendFromSelf for an explanation of\n    // the \"offset - 1u\" trick.\n    if (*produced <= offset - 1u) return false;\n    *produced += len;\n    return *produced <= expected_;\n  }\n  inline void Flush() {}\n};\n\nbool IsValidCompressedBuffer(const char* compressed, size_t compressed_length) {\n  ByteArraySource reader(compressed, compressed_length);\n  SnappyDecompressionValidator writer;\n  return InternalUncompress(&reader, &writer);\n}\n\nbool IsValidCompressed(Source* compressed) {\n  SnappyDecompressionValidator writer;\n  return InternalUncompress(compressed, &writer);\n}\n\nvoid RawCompress(const char* input, size_t input_length, char* compressed,\n                 size_t* compressed_length) {\n  RawCompress(input, input_length, compressed, compressed_length,\n              CompressionOptions{});\n}\n\nvoid RawCompress(const char* input, size_t input_length, char* compressed,\n                 size_t* compressed_length, CompressionOptions options) {\n  ByteArraySource reader(input, input_length);\n  UncheckedByteArraySink writer(compressed);\n  Compress(&reader, &writer, options);\n\n  // Compute how many bytes were added\n  *compressed_length = (writer.CurrentDestination() - compressed);\n}\n\nvoid RawCompressFromIOVec(const struct iovec* iov, size_t uncompressed_length,\n                          char* compressed, size_t* compressed_length) {\n  RawCompressFromIOVec(iov, uncompressed_length, compressed, compressed_length,\n                       CompressionOptions{});\n}\n\nvoid RawCompressFromIOVec(const struct iovec* iov, size_t uncompressed_length,\n                          char* compressed, size_t* compressed_length,\n                          CompressionOptions options) {\n  SnappyIOVecReader reader(iov, uncompressed_length);\n  UncheckedByteArraySink writer(compressed);\n  Compress(&reader, &writer, options);\n\n  // Compute how many bytes were added.\n  *compressed_length = writer.CurrentDestination() - compressed;\n}\n\nsize_t Compress(const char* input, size_t input_length,\n                std::string* compressed) {\n  return Compress(input, input_length, compressed, CompressionOptions{});\n}\n\nsize_t Compress(const char* input, size_t input_length, std::string* compressed,\n                CompressionOptions options) {\n  // Pre-grow the buffer to the max length of the compressed output\n  STLStringResizeUninitialized(compressed, MaxCompressedLength(input_length));\n\n  size_t compressed_length;\n  RawCompress(input, input_length, string_as_array(compressed),\n              &compressed_length, options);\n  compressed->erase(compressed_length);\n  return compressed_length;\n}\n\nsize_t CompressFromIOVec(const struct iovec* iov, size_t iov_cnt,\n                         std::string* compressed) {\n  return CompressFromIOVec(iov, iov_cnt, compressed, CompressionOptions{});\n}\n\nsize_t CompressFromIOVec(const struct iovec* iov, size_t iov_cnt,\n                         std::string* compressed, CompressionOptions options) {\n  // Compute the number of bytes to be compressed.\n  size_t uncompressed_length = 0;\n  for (size_t i = 0; i < iov_cnt; ++i) {\n    uncompressed_length += iov[i].iov_len;\n  }\n\n  // Pre-grow the buffer to the max length of the compressed output.\n  STLStringResizeUninitialized(compressed, MaxCompressedLength(\n      uncompressed_length));\n\n  size_t compressed_length;\n  RawCompressFromIOVec(iov, uncompressed_length, string_as_array(compressed),\n                       &compressed_length, options);\n  compressed->erase(compressed_length);\n  return compressed_length;\n}\n\n// -----------------------------------------------------------------------\n// Sink interface\n// -----------------------------------------------------------------------\n\n// A type that decompresses into a Sink. The template parameter\n// Allocator must export one method \"char* Allocate(int size);\", which\n// allocates a buffer of \"size\" and appends that to the destination.\ntemplate <typename Allocator>\nclass SnappyScatteredWriter {\n  Allocator allocator_;\n\n  // We need random access into the data generated so far.  Therefore\n  // we keep track of all of the generated data as an array of blocks.\n  // All of the blocks except the last have length kBlockSize.\n  std::vector<char*> blocks_;\n  size_t expected_;\n\n  // Total size of all fully generated blocks so far\n  size_t full_size_;\n\n  // Pointer into current output block\n  char* op_base_;   // Base of output block\n  char* op_ptr_;    // Pointer to next unfilled byte in block\n  char* op_limit_;  // Pointer just past block\n  // If op < op_limit_min_slop_ then it's safe to unconditionally write\n  // kSlopBytes starting at op.\n  char* op_limit_min_slop_;\n\n  inline size_t Size() const { return full_size_ + (op_ptr_ - op_base_); }\n\n  bool SlowAppend(const char* ip, size_t len);\n  bool SlowAppendFromSelf(size_t offset, size_t len);\n\n public:\n  inline explicit SnappyScatteredWriter(const Allocator& allocator)\n      : allocator_(allocator),\n        full_size_(0),\n        op_base_(NULL),\n        op_ptr_(NULL),\n        op_limit_(NULL),\n        op_limit_min_slop_(NULL) {}\n  char* GetOutputPtr() { return op_ptr_; }\n  char* GetBase(ptrdiff_t* op_limit_min_slop) {\n    *op_limit_min_slop = op_limit_min_slop_ - op_base_;\n    return op_base_;\n  }\n  void SetOutputPtr(char* op) { op_ptr_ = op; }\n\n  inline void SetExpectedLength(size_t len) {\n    assert(blocks_.empty());\n    expected_ = len;\n  }\n\n  inline bool CheckLength() const { return Size() == expected_; }\n\n  // Return the number of bytes actually uncompressed so far\n  inline size_t Produced() const { return Size(); }\n\n  inline bool Append(const char* ip, size_t len, char** op_p) {\n    char* op = *op_p;\n    size_t avail = op_limit_ - op;\n    if (len <= avail) {\n      // Fast path\n      std::memcpy(op, ip, len);\n      *op_p = op + len;\n      return true;\n    } else {\n      op_ptr_ = op;\n      bool res = SlowAppend(ip, len);\n      *op_p = op_ptr_;\n      return res;\n    }\n  }\n\n  inline bool TryFastAppend(const char* ip, size_t available, size_t length,\n                            char** op_p) {\n    char* op = *op_p;\n    const int space_left = op_limit_ - op;\n    if (length <= 16 && available >= 16 + kMaximumTagLength &&\n        space_left >= 16) {\n      // Fast path, used for the majority (about 95%) of invocations.\n      UnalignedCopy128(ip, op);\n      *op_p = op + length;\n      return true;\n    } else {\n      return false;\n    }\n  }\n\n  inline bool AppendFromSelf(size_t offset, size_t len, char** op_p) {\n    char* op = *op_p;\n    assert(op >= op_base_);\n    // Check if we try to append from before the start of the buffer.\n    if (SNAPPY_PREDICT_FALSE((kSlopBytes < 64 && len > kSlopBytes) ||\n                            static_cast<size_t>(op - op_base_) < offset ||\n                            op >= op_limit_min_slop_ || offset < len)) {\n      if (offset == 0) return false;\n      if (SNAPPY_PREDICT_FALSE(static_cast<size_t>(op - op_base_) < offset ||\n                              op + len > op_limit_)) {\n        op_ptr_ = op;\n        bool res = SlowAppendFromSelf(offset, len);\n        *op_p = op_ptr_;\n        return res;\n      }\n      *op_p = IncrementalCopy(op - offset, op, op + len, op_limit_);\n      return true;\n    }\n    // Fast path\n    char* const op_end = op + len;\n    std::memmove(op, op - offset, kSlopBytes);\n    *op_p = op_end;\n    return true;\n  }\n\n  // Called at the end of the decompress. We ask the allocator\n  // write all blocks to the sink.\n  inline void Flush() { allocator_.Flush(Produced()); }\n};\n\ntemplate <typename Allocator>\nbool SnappyScatteredWriter<Allocator>::SlowAppend(const char* ip, size_t len) {\n  size_t avail = op_limit_ - op_ptr_;\n  while (len > avail) {\n    // Completely fill this block\n    std::memcpy(op_ptr_, ip, avail);\n    op_ptr_ += avail;\n    assert(op_limit_ - op_ptr_ == 0);\n    full_size_ += (op_ptr_ - op_base_);\n    len -= avail;\n    ip += avail;\n\n    // Bounds check\n    if (full_size_ + len > expected_) return false;\n\n    // Make new block\n    size_t bsize = std::min<size_t>(kBlockSize, expected_ - full_size_);\n    op_base_ = allocator_.Allocate(bsize);\n    op_ptr_ = op_base_;\n    op_limit_ = op_base_ + bsize;\n    op_limit_min_slop_ = op_limit_ - std::min<size_t>(kSlopBytes - 1, bsize);\n\n    blocks_.push_back(op_base_);\n    avail = bsize;\n  }\n\n  std::memcpy(op_ptr_, ip, len);\n  op_ptr_ += len;\n  return true;\n}\n\ntemplate <typename Allocator>\nbool SnappyScatteredWriter<Allocator>::SlowAppendFromSelf(size_t offset,\n                                                         size_t len) {\n  // Overflow check\n  // See SnappyArrayWriter::AppendFromSelf for an explanation of\n  // the \"offset - 1u\" trick.\n  const size_t cur = Size();\n  if (offset - 1u >= cur) return false;\n  if (expected_ - cur < len) return false;\n\n  // Currently we shouldn't ever hit this path because Compress() chops the\n  // input into blocks and does not create cross-block copies. However, it is\n  // nice if we do not rely on that, since we can get better compression if we\n  // allow cross-block copies and thus might want to change the compressor in\n  // the future.\n  // TODO Replace this with a properly optimized path. This is not\n  // triggered right now. But this is so super slow, that it would regress\n  // performance unacceptably if triggered.\n  size_t src = cur - offset;\n  char* op = op_ptr_;\n  while (len-- > 0) {\n    char c = blocks_[src >> kBlockLog][src & (kBlockSize - 1)];\n    if (!Append(&c, 1, &op)) {\n      op_ptr_ = op;\n      return false;\n    }\n    src++;\n  }\n  op_ptr_ = op;\n  return true;\n}\n\nclass SnappySinkAllocator {\n public:\n  explicit SnappySinkAllocator(Sink* dest) : dest_(dest) {}\n\n  char* Allocate(int size) {\n    Datablock block(new char[size], size);\n    blocks_.push_back(block);\n    return block.data;\n  }\n\n  // We flush only at the end, because the writer wants\n  // random access to the blocks and once we hand the\n  // block over to the sink, we can't access it anymore.\n  // Also we don't write more than has been actually written\n  // to the blocks.\n  void Flush(size_t size) {\n    size_t size_written = 0;\n    for (Datablock& block : blocks_) {\n      size_t block_size = std::min<size_t>(block.size, size - size_written);\n      dest_->AppendAndTakeOwnership(block.data, block_size,\n                                    &SnappySinkAllocator::Deleter, NULL);\n      size_written += block_size;\n    }\n    blocks_.clear();\n  }\n\n private:\n  struct Datablock {\n    char* data;\n    size_t size;\n    Datablock(char* p, size_t s) : data(p), size(s) {}\n  };\n\n  static void Deleter(void* arg, const char* bytes, size_t size) {\n    // TODO: Switch to [[maybe_unused]] when we can assume C++17.\n    (void)arg;\n    (void)size;\n\n    delete[] bytes;\n  }\n\n  Sink* dest_;\n  std::vector<Datablock> blocks_;\n\n  // Note: copying this object is allowed\n};\n\nsize_t UncompressAsMuchAsPossible(Source* compressed, Sink* uncompressed) {\n  SnappySinkAllocator allocator(uncompressed);\n  SnappyScatteredWriter<SnappySinkAllocator> writer(allocator);\n  InternalUncompress(compressed, &writer);\n  return writer.Produced();\n}\n\nbool Uncompress(Source* compressed, Sink* uncompressed) {\n  // Read the uncompressed length from the front of the compressed input\n  SnappyDecompressor decompressor(compressed);\n  uint32_t uncompressed_len = 0;\n  if (!decompressor.ReadUncompressedLength(&uncompressed_len)) {\n    return false;\n  }\n\n  char c;\n  size_t allocated_size;\n  char* buf = uncompressed->GetAppendBufferVariable(1, uncompressed_len, &c, 1,\n                                                    &allocated_size);\n\n  const size_t compressed_len = compressed->Available();\n  // If we can get a flat buffer, then use it, otherwise do block by block\n  // uncompression\n  if (allocated_size >= uncompressed_len) {\n    SnappyArrayWriter writer(buf);\n    bool result = InternalUncompressAllTags(&decompressor, &writer,\n                                            compressed_len, uncompressed_len);\n    uncompressed->Append(buf, writer.Produced());\n    return result;\n  } else {\n    SnappySinkAllocator allocator(uncompressed);\n    SnappyScatteredWriter<SnappySinkAllocator> writer(allocator);\n    return InternalUncompressAllTags(&decompressor, &writer, compressed_len,\n                                     uncompressed_len);\n  }\n}\n\n}  // namespace snappy\n"
  },
  {
    "path": "Plugin/Snappy/snappy.h",
    "content": "// Copyright 2005 and onwards Google Inc.\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are\n// met:\n//\n//     * Redistributions of source code must retain the above copyright\n// notice, this list of conditions and the following disclaimer.\n//     * Redistributions in binary form must reproduce the above\n// copyright notice, this list of conditions and the following disclaimer\n// in the documentation and/or other materials provided with the\n// distribution.\n//     * Neither the name of Google Inc. nor the names of its\n// contributors may be used to endorse or promote products derived from\n// this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n// \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n//\n// A light-weight compression algorithm.  It is designed for speed of\n// compression and decompression, rather than for the utmost in space\n// savings.\n//\n// For getting better compression ratios when you are compressing data\n// with long repeated sequences or compressing data that is similar to\n// other data, while still compressing fast, you might look at first\n// using BMDiff and then compressing the output of BMDiff with\n// Snappy.\n\n#ifndef THIRD_PARTY_SNAPPY_SNAPPY_H__\n#define THIRD_PARTY_SNAPPY_SNAPPY_H__\n\n#include <stddef.h>\n#include <stdint.h>\n\n#include <string>\n\n#include \"snappy-stubs-public.h\"\n\nnamespace snappy {\n  class Source;\n  class Sink;\n\n  struct CompressionOptions {\n    // Compression level.\n    // Level 1 is the fastest\n    // Level 2 is a little slower but provides better compression. Level 2 is\n    // **EXPERIMENTAL** for the time being. It might happen that we decide to\n    // fall back to level 1 in the future.\n    // Levels 3+ are currently not supported. We plan to support levels up to\n    // 9 in the future.\n    // If you played with other compression algorithms, level 1 is equivalent to\n    // fast mode (level 1) of LZ4, level 2 is equivalent to LZ4's level 2 mode\n    // and compresses somewhere around zstd:-3 and zstd:-2 but generally with\n    // faster decompression speeds than snappy:1 and zstd:-3.\n    int level = DefaultCompressionLevel();\n\n    constexpr CompressionOptions() = default;\n    constexpr CompressionOptions(int compression_level)\n        : level(compression_level) {}\n    static constexpr int MinCompressionLevel() { return 1; }\n    static constexpr int MaxCompressionLevel() { return 2; }\n    static constexpr int DefaultCompressionLevel() { return 1; }\n  };\n\n  // ------------------------------------------------------------------------\n  // Generic compression/decompression routines.\n  // ------------------------------------------------------------------------\n\n  // Compress the bytes read from \"*reader\" and append to \"*writer\". Return the\n  // number of bytes written.\n  // First version is to preserve ABI.\n  size_t Compress(Source* reader, Sink* writer);\n  size_t Compress(Source* reader, Sink* writer,\n                  CompressionOptions options);\n\n  // Find the uncompressed length of the given stream, as given by the header.\n  // Note that the true length could deviate from this; the stream could e.g.\n  // be truncated.\n  //\n  // Also note that this leaves \"*source\" in a state that is unsuitable for\n  // further operations, such as RawUncompress(). You will need to rewind\n  // or recreate the source yourself before attempting any further calls.\n  bool GetUncompressedLength(Source* source, uint32_t* result);\n\n  // ------------------------------------------------------------------------\n  // Higher-level string based routines (should be sufficient for most users)\n  // ------------------------------------------------------------------------\n\n  // Sets \"*compressed\" to the compressed version of \"input[0..input_length-1]\".\n  // Original contents of *compressed are lost.\n  //\n  // REQUIRES: \"input[]\" is not an alias of \"*compressed\".\n  // First version is to preserve ABI.\n  size_t Compress(const char* input, size_t input_length,\n                  std::string* compressed);\n  size_t Compress(const char* input, size_t input_length,\n                  std::string* compressed, CompressionOptions options);\n\n  // Same as `Compress` above but taking an `iovec` array as input. Note that\n  // this function preprocesses the inputs to compute the sum of\n  // `iov[0..iov_cnt-1].iov_len` before reading. To avoid this, use\n  // `RawCompressFromIOVec` below.\n  // First version is to preserve ABI.\n  size_t CompressFromIOVec(const struct iovec* iov, size_t iov_cnt,\n                           std::string* compressed);\n  size_t CompressFromIOVec(const struct iovec* iov, size_t iov_cnt,\n                           std::string* compressed,\n                           CompressionOptions options);\n\n  // Decompresses \"compressed[0..compressed_length-1]\" to \"*uncompressed\".\n  // Original contents of \"*uncompressed\" are lost.\n  //\n  // REQUIRES: \"compressed[]\" is not an alias of \"*uncompressed\".\n  //\n  // returns false if the message is corrupted and could not be decompressed\n  bool Uncompress(const char* compressed, size_t compressed_length,\n                  std::string* uncompressed);\n\n  // Decompresses \"compressed\" to \"*uncompressed\".\n  //\n  // returns false if the message is corrupted and could not be decompressed\n  bool Uncompress(Source* compressed, Sink* uncompressed);\n\n  // This routine uncompresses as much of the \"compressed\" as possible\n  // into sink.  It returns the number of valid bytes added to sink\n  // (extra invalid bytes may have been added due to errors; the caller\n  // should ignore those). The emitted data typically has length\n  // GetUncompressedLength(), but may be shorter if an error is\n  // encountered.\n  size_t UncompressAsMuchAsPossible(Source* compressed, Sink* uncompressed);\n\n  // ------------------------------------------------------------------------\n  // Lower-level character array based routines.  May be useful for\n  // efficiency reasons in certain circumstances.\n  // ------------------------------------------------------------------------\n\n  // REQUIRES: \"compressed\" must point to an area of memory that is at\n  // least \"MaxCompressedLength(input_length)\" bytes in length.\n  //\n  // Takes the data stored in \"input[0..input_length]\" and stores\n  // it in the array pointed to by \"compressed\".\n  //\n  // \"*compressed_length\" is set to the length of the compressed output.\n  //\n  // Example:\n  //    char* output = new char[snappy::MaxCompressedLength(input_length)];\n  //    size_t output_length;\n  //    RawCompress(input, input_length, output, &output_length);\n  //    ... Process(output, output_length) ...\n  //    delete [] output;\n  void RawCompress(const char* input, size_t input_length, char* compressed,\n                   size_t* compressed_length);\n  void RawCompress(const char* input, size_t input_length, char* compressed,\n                   size_t* compressed_length, CompressionOptions options);\n\n  // Same as `RawCompress` above but taking an `iovec` array as input. Note that\n  // `uncompressed_length` is the total number of bytes to be read from the\n  // elements of `iov` (_not_ the number of elements in `iov`).\n  void RawCompressFromIOVec(const struct iovec* iov, size_t uncompressed_length,\n                            char* compressed, size_t* compressed_length);\n  void RawCompressFromIOVec(const struct iovec* iov, size_t uncompressed_length,\n                            char* compressed, size_t* compressed_length,\n                            CompressionOptions options);\n\n  // Given data in \"compressed[0..compressed_length-1]\" generated by\n  // calling the Snappy::Compress routine, this routine\n  // stores the uncompressed data to\n  //    uncompressed[0..GetUncompressedLength(compressed)-1]\n  // returns false if the message is corrupted and could not be decrypted\n  bool RawUncompress(const char* compressed, size_t compressed_length,\n                     char* uncompressed);\n\n  // Given data from the byte source 'compressed' generated by calling\n  // the Snappy::Compress routine, this routine stores the uncompressed\n  // data to\n  //    uncompressed[0..GetUncompressedLength(compressed,compressed_length)-1]\n  // returns false if the message is corrupted and could not be decrypted\n  bool RawUncompress(Source* compressed, char* uncompressed);\n\n  // Given data in \"compressed[0..compressed_length-1]\" generated by\n  // calling the Snappy::Compress routine, this routine\n  // stores the uncompressed data to the iovec \"iov\". The number of physical\n  // buffers in \"iov\" is given by iov_cnt and their cumulative size\n  // must be at least GetUncompressedLength(compressed). The individual buffers\n  // in \"iov\" must not overlap with each other.\n  //\n  // returns false if the message is corrupted and could not be decrypted\n  bool RawUncompressToIOVec(const char* compressed, size_t compressed_length,\n                            const struct iovec* iov, size_t iov_cnt);\n\n  // Given data from the byte source 'compressed' generated by calling\n  // the Snappy::Compress routine, this routine stores the uncompressed\n  // data to the iovec \"iov\". The number of physical\n  // buffers in \"iov\" is given by iov_cnt and their cumulative size\n  // must be at least GetUncompressedLength(compressed). The individual buffers\n  // in \"iov\" must not overlap with each other.\n  //\n  // returns false if the message is corrupted and could not be decrypted\n  bool RawUncompressToIOVec(Source* compressed, const struct iovec* iov,\n                            size_t iov_cnt);\n\n  // Returns the maximal size of the compressed representation of\n  // input data that is \"source_bytes\" bytes in length;\n  size_t MaxCompressedLength(size_t source_bytes);\n\n  // REQUIRES: \"compressed[]\" was produced by RawCompress() or Compress()\n  // Returns true and stores the length of the uncompressed data in\n  // *result normally.  Returns false on parsing error.\n  // This operation takes O(1) time.\n  bool GetUncompressedLength(const char* compressed, size_t compressed_length,\n                             size_t* result);\n\n  // Returns true iff the contents of \"compressed[]\" can be uncompressed\n  // successfully.  Does not return the uncompressed data.  Takes\n  // time proportional to compressed_length, but is usually at least\n  // a factor of four faster than actual decompression.\n  bool IsValidCompressedBuffer(const char* compressed,\n                               size_t compressed_length);\n\n  // Returns true iff the contents of \"compressed\" can be uncompressed\n  // successfully.  Does not return the uncompressed data.  Takes\n  // time proportional to *compressed length, but is usually at least\n  // a factor of four faster than actual decompression.\n  // On success, consumes all of *compressed.  On failure, consumes an\n  // unspecified prefix of *compressed.\n  bool IsValidCompressed(Source* compressed);\n\n  // The size of a compression block. Note that many parts of the compression\n  // code assumes that kBlockSize <= 65536; in particular, the hash table\n  // can only store 16-bit offsets, and EmitCopy() also assumes the offset\n  // is 65535 bytes or less. Note also that if you change this, it will\n  // affect the framing format (see framing_format.txt).\n  //\n  // Note that there might be older data around that is compressed with larger\n  // block sizes, so the decompression code should not rely on the\n  // non-existence of long backreferences.\n  static constexpr int kBlockLog = 16;\n  static constexpr size_t kBlockSize = 1 << kBlockLog;\n\n  static constexpr int kMinHashTableBits = 8;\n  static constexpr size_t kMinHashTableSize = 1 << kMinHashTableBits;\n\n  static constexpr int kMaxHashTableBits = 15;\n  static constexpr size_t kMaxHashTableSize = 1 << kMaxHashTableBits;\n}  // end namespace snappy\n\n#endif  // THIRD_PARTY_SNAPPY_SNAPPY_H__\n"
  },
  {
    "path": "Plugin/Source/Decoder.h",
    "content": "#pragma once\n\n#include <stdint.h>\n#include <mutex>\n#include <vector>\n#include \"ReadBuffer.h\"\n#include \"hap.h\"\n\nnamespace KlakHap\n{\n    class Decoder\n    {\n    public:\n\n        #pragma region Constructor/destructor\n\n        Decoder(int width, int height, int typeID)\n        {\n            buffer_.resize(width * height * GetBppFromTypeID(typeID) / 8);\n        }\n\n        #pragma endregion\n\n        #pragma region Public accessors\n\n        const void* LockBuffer()\n        {\n            bufferLock_.lock();\n            return buffer_.data();\n        }\n\n        void UnlockBuffer()\n        {\n            bufferLock_.unlock();\n        }\n\n        size_t GetBufferSize() const\n        {\n            return buffer_.size();\n        }\n\n        #pragma endregion\n\n        #pragma region Decoding operations\n\n        void DecodeFrame(const ReadBuffer& input)\n        {\n            std::lock_guard<std::mutex> lock(bufferLock_);\n\n            unsigned int format;\n\n            HapDecode(\n                input.storage.data(),\n                static_cast<unsigned long>(input.storage.size()),\n                0, hap_callback, nullptr,\n                buffer_.data(),\n                static_cast<unsigned long>(buffer_.size()),\n                nullptr, &format\n            );\n        }\n\n        #pragma endregion\n\n    private:\n\n        #pragma region Internal-use members\n\n        std::vector<uint8_t> buffer_;\n        std::mutex bufferLock_;\n\n        static size_t GetBppFromTypeID(int typeID)\n        {\n            switch (typeID & 0xf)\n            {\n            case 0xb: return 4; // DXT1\n            case 0xe: return 8; // DXT5\n            case 0xf: return 8; // DXT5\n            case 0xc: return 8; // BC7\n            case 0x1: return 4; // BC4\n            }\n            return 0;\n        }\n\n        #pragma endregion\n\n        #pragma region HAP callback implementation\n\n        static void hap_callback(\n            HapDecodeWorkFunction work, void* p,\n            unsigned int count, void* info\n        )\n        {\n            // FIXME: This should be threaded.\n            for (auto i = 0u; i < count; i++) work(p, i);\n        }\n\n        #pragma endregion\n    };\n}\n"
  },
  {
    "path": "Plugin/Source/Demuxer.h",
    "content": "#pragma once\n\n#include <stdint.h>\n#include <cstring>\n#include \"mp4demux.h\"\n#include \"ReadBuffer.h\"\n\n#ifdef _WIN32\n#include <windows.h>\n#endif\n\nnamespace KlakHap\n{\n    class Demuxer\n    {\n    public:\n\n        #pragma region Constructor/destructor\n\n        Demuxer(const char* path)\n        {\n            std::memset(&demux_, 0, sizeof(MP4D_demux_t));\n\n        #ifdef _WIN32\n            // Convert UTF-8 to wide character for Windows\n            int wlen = MultiByteToWideChar(CP_UTF8, 0, path, -1, nullptr, 0);\n            if (wlen <= 0) return;\n\n            wchar_t* wpath = new wchar_t[wlen];\n            MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, wlen);\n\n            if (_wfopen_s(&file_, wpath, L\"rb\") != 0) {\n                delete[] wpath;\n                return;\n            }\n            delete[] wpath;\n        #else\n            file_ = fopen(path, \"rb\");\n            if (file_ == nullptr) return;\n        #endif\n\n            if (MP4D__open(&demux_, file_) == 0)\n            {\n                fclose(file_);\n                file_ = nullptr;\n            }\n        }\n\n        ~Demuxer()\n        {\n            MP4D__close(&demux_);\n            if (file_ != nullptr) fclose(file_);\n        }\n\n        #pragma endregion\n\n        #pragma region Public accessors\n\n        bool IsValid() const\n        {\n            return file_ != nullptr;\n        }\n\n        const MP4D_track_t& GetVideoTrack() const\n        {\n            return demux_.track[0];\n        }\n\n        #pragma endregion\n\n        #pragma region Read methods\n\n        uint8_t ReadVideoTypeField()\n        {\n            // Data offset for the first frame\n            unsigned int size;\n            auto offs = MP4D__frame_offset(&demux_, 0, 0, &size, nullptr, nullptr);\n\n            // Read to a temporary buffer.\n            uint8_t temp;\n            fseek(file_, (long)offs + 3, SEEK_SET);\n            fread(&temp, 1, 1, file_);\n\n            return temp;\n        }\n\n        void ReadFrame(int index, ReadBuffer& buffer)\n        {\n            // Frame data offset\n            unsigned int inSize, timestamp, duration;\n            auto inOffs = MP4D__frame_offset(&demux_, 0, index, &inSize, &timestamp, &duration);\n\n            // Frame data read\n        #if defined(_WIN32)\n            _fseeki64(file_, inOffs, SEEK_SET);\n        #else\n            fseek(file_, inOffs, SEEK_SET);\n        #endif\n            buffer.storage.resize(inSize);\n            fread(buffer.storage.data(), inSize, 1, file_);\n        }\n\n        #pragma endregion\n\n    private:\n\n        #pragma region Private members\n\n        FILE* file_ = nullptr;\n        MP4D_demux_t demux_;\n\n        #pragma endregion\n    };\n}\n"
  },
  {
    "path": "Plugin/Source/KlakHap.cpp",
    "content": "#include <unordered_map>\n#include \"Decoder.h\"\n#include \"Demuxer.h\"\n#include \"ReadBuffer.h\"\n#include \"IUnityRenderingExtensions.h\"\n\n#if defined(_WIN32)\n#define WIN32_LEAN_AND_MEAN\n#include <windows.h>\n#endif\n\nusing namespace KlakHap;\n\nnamespace\n{\n    #pragma region ID to decorder instance map\n\n    std::unordered_map<uint32_t, Decoder*> decoderMap_;\n\n    #pragma endregion\n\n    #pragma region Texture update callback implementation\n\n    //\n    // Get a \"fake\" byte-per-pixel value for a given compression format\n    //\n    // This is a workaround for a problem that Unity incorrectly uses a BPP\n    // value to calculate a texture pitch. We have to give a mutiplier for\n    // it instead of an actual BPP value.\n    //\n    uint32_t GetFakeBpp(UnityRenderingExtTextureFormat format)\n    {\n        switch (format)\n        {\n        case kUnityRenderingExtFormatRGBA_DXT1_SRGB:\n        case kUnityRenderingExtFormatRGBA_DXT1_UNorm:\n        case kUnityRenderingExtFormatR_BC4_UNorm:\n        case kUnityRenderingExtFormatR_BC4_SNorm:\n            return 2;\n        case kUnityRenderingExtFormatRGBA_DXT5_SRGB:\n        case kUnityRenderingExtFormatRGBA_DXT5_UNorm:\n        case kUnityRenderingExtFormatRGBA_BC7_SRGB:\n        case kUnityRenderingExtFormatRGBA_BC7_UNorm:\n            return 4;\n        }\n        return 0;\n    }\n\n    // Callback for texture update events\n    void TextureUpdateCallback(int eventID, void* data)\n    {\n        auto event = static_cast<UnityRenderingExtEventType>(eventID);\n\n        if (event == kUnityRenderingExtEventUpdateTextureBeginV2)\n        {\n            // UpdateTextureBegin: Return texture image data.\n            auto params = reinterpret_cast<UnityRenderingExtTextureUpdateParamsV2*>(data);\n            auto it = decoderMap_.find(params->userData);\n            if (it != decoderMap_.end())\n            {\n                params->bpp = GetFakeBpp(params->format);\n                params->texData = const_cast<void*>(it->second->LockBuffer());\n            }\n        }\n        else if (event == kUnityRenderingExtEventUpdateTextureEndV2)\n        {\n            // UpdateTextureEnd:\n            auto params = reinterpret_cast<UnityRenderingExtTextureUpdateParamsV2*>(data);\n            auto it = decoderMap_.find(params->userData);\n            if (it != decoderMap_.end()) it->second->UnlockBuffer();\n        }\n    }\n\n    #pragma endregion\n}\n\n#pragma region Plugin common function\n\n#if defined(_WIN32) && defined(_DEBUG)\n\nextern \"C\" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* interfaces)\n{\n    // Open a new console for debug logging.\n    FILE * pConsole;\n    AllocConsole();\n    freopen_s(&pConsole, \"CONOUT$\", \"wb\", stdout);\n}\n\n#endif\n\nextern \"C\" UnityRenderingEventAndData UNITY_INTERFACE_EXPORT KlakHap_GetTextureUpdateCallback()\n{\n    return TextureUpdateCallback;\n}\n\n#pragma endregion\n\n#pragma region Read buffer functions\n\nextern \"C\" ReadBuffer UNITY_INTERFACE_EXPORT * KlakHap_CreateReadBuffer()\n{\n    return new ReadBuffer;\n}\n\nextern \"C\" void UNITY_INTERFACE_EXPORT KlakHap_DestroyReadBuffer(ReadBuffer* buffer)\n{\n    if (buffer != nullptr) delete buffer;\n}\n\n#pragma endregion\n\n#pragma region Demuxer functions\n\nextern \"C\" Demuxer UNITY_INTERFACE_EXPORT * KlakHap_OpenDemuxer(const char* filepath)\n{\n    return new Demuxer(filepath);\n}\n\nextern \"C\" void UNITY_INTERFACE_EXPORT KlakHap_CloseDemuxer(Demuxer* demuxer)\n{\n    if (demuxer != nullptr) delete demuxer;\n}\n\nextern \"C\" int32_t UNITY_INTERFACE_EXPORT KlakHap_DemuxerIsValid(Demuxer* demuxer)\n{\n    if (demuxer == nullptr) return 0;\n    return demuxer->IsValid() ? 1 : 0;\n}\n\nextern \"C\" int32_t UNITY_INTERFACE_EXPORT KlakHap_CountFrames(Demuxer* demuxer)\n{\n    if (demuxer == nullptr) return 0;\n    return demuxer->GetVideoTrack().sample_count;\n}\n\nextern \"C\" double UNITY_INTERFACE_EXPORT KlakHap_GetDuration(Demuxer* demuxer)\n{\n    if (demuxer == nullptr) return 0;\n    auto track = demuxer->GetVideoTrack();\n    auto dur = static_cast<double>(track.duration_hi);\n    dur = dur * 0x100000000L + track.duration_lo;\n    return dur / track.timescale;\n}\n\nextern \"C\" int32_t UNITY_INTERFACE_EXPORT KlakHap_GetVideoWidth(Demuxer* demuxer)\n{\n    if (demuxer == nullptr) return 0;\n    return demuxer->GetVideoTrack().SampleDescription.video.width;\n}\n\nextern \"C\" int32_t UNITY_INTERFACE_EXPORT KlakHap_GetVideoHeight(Demuxer* demuxer)\n{\n    if (demuxer == nullptr) return 0;\n    return demuxer->GetVideoTrack().SampleDescription.video.height;\n}\n\nextern \"C\" int32_t UNITY_INTERFACE_EXPORT KlakHap_AnalyzeVideoType(Demuxer* demuxer)\n{\n    if (demuxer == nullptr) return 0;\n    return demuxer->ReadVideoTypeField();\n}\n\nextern \"C\" void UNITY_INTERFACE_EXPORT KlakHap_ReadFrame(Demuxer* demuxer, int frameNumber, ReadBuffer* buffer)\n{\n    if (demuxer == nullptr || buffer == nullptr) return;\n    return demuxer->ReadFrame(frameNumber, *buffer);\n}\n\n#pragma endregion\n\n#pragma region Decoder functions\n\nextern \"C\" Decoder UNITY_INTERFACE_EXPORT *KlakHap_CreateDecoder(int width, int height, int typeID)\n{\n    return new Decoder(width, height, typeID);\n}\n\nextern \"C\" void UNITY_INTERFACE_EXPORT KlakHap_DestroyDecoder(Decoder* decoder)\n{\n    delete decoder;\n}\n\nextern \"C\" void UNITY_INTERFACE_EXPORT KlakHap_AssignDecoder(uint32_t id, Decoder* decoder)\n{\n    if (decoder != nullptr)\n        decoderMap_[id] = decoder;\n    else\n        decoderMap_.erase(decoderMap_.find(id));\n}\n\nextern \"C\" void UNITY_INTERFACE_EXPORT KlakHap_DecodeFrame(Decoder* decoder, const ReadBuffer* input)\n{\n    if (decoder == nullptr) return;\n    decoder->DecodeFrame(*input);\n}\n\nextern \"C\" const void UNITY_INTERFACE_EXPORT *KlakHap_LockDecoderBuffer(Decoder* decoder)\n{\n    if (decoder == nullptr) return nullptr;\n    return decoder->LockBuffer();\n}\n\nextern \"C\" void UNITY_INTERFACE_EXPORT KlakHap_UnlockDecoderBuffer(Decoder* decoder)\n{\n    if (decoder == nullptr) return;\n    decoder->UnlockBuffer();\n}\n\nextern \"C\" int32_t UNITY_INTERFACE_EXPORT KlakHap_GetDecoderBufferSize(Decoder* decoder)\n{\n    if (decoder == nullptr) return 0;\n    return static_cast<int32_t>(decoder->GetBufferSize());\n}\n\n#pragma endregion\n"
  },
  {
    "path": "Plugin/Source/ReadBuffer.h",
    "content": "#pragma once\n\n#include <stdint.h>\n#include <vector>\n\nnamespace KlakHap\n{\n    struct ReadBuffer\n    {\n        std::vector<uint8_t> storage;\n    };\n}\n"
  },
  {
    "path": "Plugin/Unity/IUnityGraphics.h",
    "content": "// Unity Native Plugin API copyright © 2015 Unity Technologies ApS\n//\n// Licensed under the Unity Companion License for Unity - dependent projects--see[Unity Companion License](http://www.unity3d.com/legal/licenses/Unity_Companion_License).\n//\n// Unless expressly provided otherwise, the Software under this license is made available strictly on an “AS IS” BASIS WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED.Please review the license for details on these and other terms and conditions.\n\n#pragma once\n#include \"IUnityInterface.h\"\n\n// Has to match the GfxDeviceRenderer enum\ntypedef enum UnityGfxRenderer\n{\n    //kUnityGfxRendererOpenGL            =  0, // Legacy OpenGL, removed\n    //kUnityGfxRendererD3D9              =  1, // Direct3D 9, removed\n    kUnityGfxRendererD3D11             =  2, // Direct3D 11\n    kUnityGfxRendererNull              =  4, // \"null\" device (used in batch mode)\n    //kUnityGfxRendererOpenGLES20        =  8, // OpenGL ES 2.0, removed\n    kUnityGfxRendererOpenGLES30        = 11, // OpenGL ES 3.0\n    //kUnityGfxRendererGXM               = 12, // PlayStation Vita, removed\n    kUnityGfxRendererPS4               = 13, // PlayStation 4\n    kUnityGfxRendererXboxOne           = 14, // Xbox One\n    kUnityGfxRendererMetal             = 16, // iOS Metal\n    kUnityGfxRendererOpenGLCore        = 17, // OpenGL core\n    kUnityGfxRendererD3D12             = 18, // Direct3D 12\n    kUnityGfxRendererVulkan            = 21, // Vulkan\n    kUnityGfxRendererNvn               = 22, // Nintendo Switch NVN API\n    kUnityGfxRendererXboxOneD3D12      = 23,  // MS XboxOne Direct3D 12\n    kUnityGfxRendererGameCoreXboxOne   = 24, // GameCore Xbox One\n    kUnityGfxRendererGameCoreXboxSeries  = 25, // GameCore XboxSeries\n    kUnityGfxRendererPS5               = 26, // PS5\n    kUnityGfxRendererPS5NGGC           = 27, // PS5 NGGC\n\n    kUnityGfxRendererNvn2              = 29  // Switch2\n} UnityGfxRenderer;\n\ntypedef enum UnityGfxDeviceEventType\n{\n    kUnityGfxDeviceEventInitialize     = 0,\n    kUnityGfxDeviceEventShutdown       = 1,\n    kUnityGfxDeviceEventBeforeReset    = 2,\n    kUnityGfxDeviceEventAfterReset     = 3,\n} UnityGfxDeviceEventType;\n\ntypedef void (UNITY_INTERFACE_API * IUnityGraphicsDeviceEventCallback)(UnityGfxDeviceEventType eventType);\n\n// Should only be used on the rendering thread unless noted otherwise.\nUNITY_DECLARE_INTERFACE(IUnityGraphics)\n{\n    UnityGfxRenderer(UNITY_INTERFACE_API * GetRenderer)();  // Thread safe\n\n    // This callback will be called when graphics device is created, destroyed, reset, etc.\n    // It is possible to miss the kUnityGfxDeviceEventInitialize event in case plugin is loaded at a later time,\n    // when the graphics device is already created.\n    void(UNITY_INTERFACE_API * RegisterDeviceEventCallback)(IUnityGraphicsDeviceEventCallback callback);\n    void(UNITY_INTERFACE_API * UnregisterDeviceEventCallback)(IUnityGraphicsDeviceEventCallback callback);\n    int(UNITY_INTERFACE_API * ReserveEventIDRange)(int count);  // reserves 'count' event IDs. Plugins should use the result as a base index when issuing events back and forth to avoid event id clashes.\n};\nUNITY_REGISTER_INTERFACE_GUID(0x7CBA0A9CA4DDB544ULL, 0x8C5AD4926EB17B11ULL, IUnityGraphics)\n\n\n// Certain Unity APIs (GL.IssuePluginEvent, CommandBuffer.IssuePluginEvent) can callback into native plugins.\n// Provide them with an address to a function of this signature.\ntypedef void (UNITY_INTERFACE_API * UnityRenderingEvent)(int eventId);\ntypedef void (UNITY_INTERFACE_API * UnityRenderingEventAndData)(int eventId, void* data);\n"
  },
  {
    "path": "Plugin/Unity/IUnityInterface.h",
    "content": "// Unity Native Plugin API copyright © 2015 Unity Technologies ApS\n//\n// Licensed under the Unity Companion License for Unity - dependent projects--see[Unity Companion License](http://www.unity3d.com/legal/licenses/Unity_Companion_License).\n//\n// Unless expressly provided otherwise, the Software under this license is made available strictly on an “AS IS” BASIS WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED.Please review the license for details on these and other terms and conditions.\n\n#pragma once\n\n// Unity native plugin API\n// Compatible with C99\n\n#if defined(__CYGWIN32__)\n    #define UNITY_INTERFACE_API __stdcall\n    #define UNITY_INTERFACE_EXPORT __declspec(dllexport)\n#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(_WIN64) || defined(WINAPI_FAMILY)\n    #define UNITY_INTERFACE_API __stdcall\n    #define UNITY_INTERFACE_EXPORT __declspec(dllexport)\n#elif defined(__MACH__) || defined(__ANDROID__) || defined(__linux__) || defined(LUMIN)\n    #define UNITY_INTERFACE_API\n    #define UNITY_INTERFACE_EXPORT __attribute__ ((visibility (\"default\")))\n#else\n    #define UNITY_INTERFACE_API\n    #define UNITY_INTERFACE_EXPORT\n#endif\n\n/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// IUnityInterface is a registry of interfaces we choose to expose to plugins.\n//\n// USAGE:\n// ---------\n// To retrieve an interface a user can do the following from a plugin, assuming they have the header file for the interface:\n//\n// IMyInterface * ptr = registry->Get<IMyInterface>();\n/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\n// Unity Interface GUID\n// Ensures global uniqueness.\n//\n// Template specialization is used to produce a means of looking up a GUID from its interface type at compile time.\n// The net result should compile down to passing around the GUID.\n//\n// UNITY_REGISTER_INTERFACE_GUID should be placed in the header file of any interface definition outside of all namespaces.\n// The interface structure and the registration GUID are all that is required to expose the interface to other systems.\nstruct UnityInterfaceGUID\n{\n#ifdef __cplusplus\n    UnityInterfaceGUID(unsigned long long high, unsigned long long low)\n        : m_GUIDHigh(high)\n        , m_GUIDLow(low)\n    {\n    }\n\n    UnityInterfaceGUID(const UnityInterfaceGUID& other)\n    {\n        m_GUIDHigh = other.m_GUIDHigh;\n        m_GUIDLow  = other.m_GUIDLow;\n    }\n\n    UnityInterfaceGUID& operator=(const UnityInterfaceGUID& other)\n    {\n        m_GUIDHigh = other.m_GUIDHigh;\n        m_GUIDLow  = other.m_GUIDLow;\n        return *this;\n    }\n\n    bool Equals(const UnityInterfaceGUID& other)   const { return m_GUIDHigh == other.m_GUIDHigh && m_GUIDLow == other.m_GUIDLow; }\n    bool LessThan(const UnityInterfaceGUID& other) const { return m_GUIDHigh < other.m_GUIDHigh || (m_GUIDHigh == other.m_GUIDHigh && m_GUIDLow < other.m_GUIDLow); }\n#endif\n    unsigned long long m_GUIDHigh;\n    unsigned long long m_GUIDLow;\n};\n#ifdef __cplusplus\ninline bool operator==(const UnityInterfaceGUID& left, const UnityInterfaceGUID& right) { return left.Equals(right); }\ninline bool operator!=(const UnityInterfaceGUID& left, const UnityInterfaceGUID& right) { return !left.Equals(right); }\ninline bool operator<(const UnityInterfaceGUID& left, const UnityInterfaceGUID& right) { return left.LessThan(right); }\ninline bool operator>(const UnityInterfaceGUID& left, const UnityInterfaceGUID& right) { return right.LessThan(left); }\ninline bool operator>=(const UnityInterfaceGUID& left, const UnityInterfaceGUID& right) { return !operator<(left, right); }\ninline bool operator<=(const UnityInterfaceGUID& left, const UnityInterfaceGUID& right) { return !operator>(left, right); }\n#else\ntypedef struct UnityInterfaceGUID UnityInterfaceGUID;\n#endif\n\n\n#ifdef __cplusplus\n    #define UNITY_DECLARE_INTERFACE(NAME) \\\n    struct NAME : IUnityInterface\n\n// Generic version of GetUnityInterfaceGUID to allow us to specialize it\n// per interface below. The generic version has no actual implementation\n// on purpose.\n//\n// If you get errors about return values related to this method then\n// you have forgotten to include UNITY_REGISTER_INTERFACE_GUID with\n// your interface, or it is not visible at some point when you are\n// trying to retrieve or add an interface.\ntemplate<typename TYPE>\ninline const UnityInterfaceGUID GetUnityInterfaceGUID();\n\n// This is the macro you provide in your public interface header\n// outside of a namespace to allow us to map between type and GUID\n// without the user having to worry about it when attempting to\n// add or retrieve and interface from the registry.\n    #define UNITY_REGISTER_INTERFACE_GUID(HASHH, HASHL, TYPE)      \\\n    template<>                                                     \\\n    inline const UnityInterfaceGUID GetUnityInterfaceGUID<TYPE>()  \\\n    {                                                              \\\n        return UnityInterfaceGUID(HASHH,HASHL);                    \\\n    }\n\n// Same as UNITY_REGISTER_INTERFACE_GUID but allows the interface to live in\n// a particular namespace. As long as the namespace is visible at the time you call\n// GetUnityInterfaceGUID< INTERFACETYPE >() or you explicitly qualify it in the template\n// calls this will work fine, only the macro here needs to have the additional parameter\n    #define UNITY_REGISTER_INTERFACE_GUID_IN_NAMESPACE(HASHH, HASHL, TYPE, NAMESPACE) \\\n    const UnityInterfaceGUID TYPE##_GUID(HASHH, HASHL);                               \\\n    template<>                                                                        \\\n    inline const UnityInterfaceGUID GetUnityInterfaceGUID< NAMESPACE :: TYPE >()      \\\n    {                                                                                 \\\n        return UnityInterfaceGUID(HASHH,HASHL);                                       \\\n    }\n\n// These macros allow for C compatibility in user code.\n    #define UNITY_GET_INTERFACE_GUID(TYPE) GetUnityInterfaceGUID< TYPE >()\n\n\n#else\n    #define UNITY_DECLARE_INTERFACE(NAME) \\\n    typedef struct NAME NAME;             \\\n    struct NAME\n\n// NOTE: This has the downside that one some compilers it will not get stripped from all compilation units that\n//       can see a header containing this constant. However, it's only for C compatibility and thus should have\n//       minimal impact.\n    #define UNITY_REGISTER_INTERFACE_GUID(HASHH, HASHL, TYPE) \\\n    const UnityInterfaceGUID TYPE##_GUID = {HASHH, HASHL};\n\n// In general namespaces are going to be a problem for C code any interfaces we expose in a namespace are\n// not going to be usable from C.\n    #define UNITY_REGISTER_INTERFACE_GUID_IN_NAMESPACE(HASHH, HASHL, TYPE, NAMESPACE)\n\n// These macros allow for C compatibility in user code.\n    #define UNITY_GET_INTERFACE_GUID(TYPE) TYPE##_GUID\n#endif\n\n// Using this in user code rather than INTERFACES->Get<TYPE>() will be C compatible for those places in plugins where\n// this may be needed. Unity code itself does not need this.\n#define UNITY_GET_INTERFACE(INTERFACES, TYPE) (TYPE*)INTERFACES->GetInterfaceSplit (UNITY_GET_INTERFACE_GUID(TYPE).m_GUIDHigh, UNITY_GET_INTERFACE_GUID(TYPE).m_GUIDLow);\n\n\n#ifdef __cplusplus\nstruct IUnityInterface\n{\n};\n#else\ntypedef void IUnityInterface;\n#endif\n\n\ntypedef struct IUnityInterfaces\n{\n    // Returns an interface matching the guid.\n    // Returns nullptr if the given interface is unavailable in the active Unity runtime.\n    IUnityInterface* (UNITY_INTERFACE_API * GetInterface)(UnityInterfaceGUID guid);\n\n    // Registers a new interface.\n    void(UNITY_INTERFACE_API * RegisterInterface)(UnityInterfaceGUID guid, IUnityInterface * ptr);\n\n    // Split APIs for C\n    IUnityInterface* (UNITY_INTERFACE_API * GetInterfaceSplit)(unsigned long long guidHigh, unsigned long long guidLow);\n    void(UNITY_INTERFACE_API * RegisterInterfaceSplit)(unsigned long long guidHigh, unsigned long long guidLow, IUnityInterface * ptr);\n\n#ifdef __cplusplus\n    // Helper for GetInterface.\n    template<typename INTERFACE>\n    INTERFACE* Get()\n    {\n        return static_cast<INTERFACE*>(GetInterface(GetUnityInterfaceGUID<INTERFACE>()));\n    }\n\n    // Helper for RegisterInterface.\n    template<typename INTERFACE>\n    void Register(IUnityInterface* ptr)\n    {\n        RegisterInterface(GetUnityInterfaceGUID<INTERFACE>(), ptr);\n    }\n\n#endif\n} IUnityInterfaces;\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n// If exported by a plugin, this function will be called when the plugin is loaded.\nvoid UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* unityInterfaces);\n// If exported by a plugin, this function will be called when the plugin is about to be unloaded.\nvoid UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginUnload();\n\n#ifdef __cplusplus\n}\n#endif\n\nstruct RenderSurfaceBase;\ntypedef struct RenderSurfaceBase* UnityRenderBuffer;\ntypedef unsigned int UnityTextureID;\n"
  },
  {
    "path": "Plugin/Unity/IUnityRenderingExtensions.h",
    "content": "// Unity Native Plugin API copyright © 2015 Unity Technologies ApS\n//\n// Licensed under the Unity Companion License for Unity - dependent projects--see[Unity Companion License](http://www.unity3d.com/legal/licenses/Unity_Companion_License).\n//\n// Unless expressly provided otherwise, the Software under this license is made available strictly on an “AS IS” BASIS WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED.Please review the license for details on these and other terms and conditions.\n\n#pragma once\n\n\n#include \"IUnityGraphics.h\"\n#include <stdbool.h>\n\n/*\n    Low-level Native Plugin Rendering Extensions\n    ============================================\n\n    On top of the Low-level native plugin interface, Unity also supports low level rendering extensions that can receive callbacks when certain events happen.\n    This is mostly used to implement and control low-level rendering in your plugin and enable it to work with Unity’s multithreaded rendering.\n\n    Due to the low-level nature of this extension the plugin might need to be preloaded before the devices get created.\n    Currently the convention is name-based namely the plugin name must be prefixed by “GfxPlugin”. Example: GfxPluginMyFancyNativePlugin.\n\n    <code>\n        // Native plugin code example\n\n        enum PluginCustomCommands\n        {\n            kPluginCustomCommandDownscale = kUnityRenderingExtUserEventsStart,\n            kPluginCustomCommandUpscale,\n\n            // insert your own events here\n\n            kPluginCustomCommandCount\n        };\n\n        static IUnityInterfaces* s_UnityInterfaces = NULL;\n\n        extern \"C\" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API\n        UnityPluginLoad(IUnityInterfaces* unityInterfaces)\n        {\n            // initialization code here...\n        }\n\n        extern \"C\" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API\n        UnityRenderingExtEvent(UnityRenderingExtEventType event, void* data)\n        {\n            switch (event)\n            {\n                case kUnityRenderingExtEventBeforeDrawCall:\n                    // do some stuff\n                    break;\n                case kUnityRenderingExtEventAfterDrawCall:\n                    // undo some stuff\n                    break;\n                case kPluginCustomCommandDownscale:\n                    // downscale some stuff\n                    break;\n                case kPluginCustomCommandUpscale:\n                    // upscale some stuff\n                    break;\n            }\n        }\n    </code>\n*/\n\n\n//     These events will be propagated to all plugins that implement void UnityRenderingExtEvent(UnityRenderingExtEventType event, void* data);\n\ntypedef enum UnityRenderingExtEventType\n{\n    kUnityRenderingExtEventSetStereoTarget,                 // issued during SetStereoTarget and carrying the current 'eye' index as parameter\n    kUnityRenderingExtEventSetStereoEye,                    // issued during stereo rendering at the beginning of each eye's rendering loop. It carries the current 'eye' index as parameter\n    kUnityRenderingExtEventStereoRenderingDone,             // issued after the rendering has finished\n    kUnityRenderingExtEventBeforeDrawCall,                  // issued during BeforeDrawCall and carrying UnityRenderingExtBeforeDrawCallParams as parameter\n    kUnityRenderingExtEventAfterDrawCall,                   // issued during AfterDrawCall. This event doesn't carry any parameters\n    kUnityRenderingExtEventCustomGrab,                      // issued during GrabIntoRenderTexture since we can't simply copy the resources\n                                                            //      when custom rendering is used - we need to let plugin handle this. It carries over\n                                                            //      a UnityRenderingExtCustomBlitParams params = { X, source, dest, 0, 0 } ( X means it's irrelevant )\n    kUnityRenderingExtEventCustomBlit,                      // issued by plugin to insert custom blits. It carries over UnityRenderingExtCustomBlitParams as param.\n    kUnityRenderingExtEventUpdateTextureBegin,                                                  // Deprecated.\n    kUnityRenderingExtEventUpdateTextureEnd,                                                    // Deprecated.\n    kUnityRenderingExtEventUpdateTextureBeginV1 = kUnityRenderingExtEventUpdateTextureBegin,    // Deprecated. Issued to update a texture. It carries over UnityRenderingExtTextureUpdateParamsV1\n    kUnityRenderingExtEventUpdateTextureEndV1 = kUnityRenderingExtEventUpdateTextureEnd,        // Deprecated. Issued to signal the plugin that the texture update has finished. It carries over the same UnityRenderingExtTextureUpdateParamsV1 as kUnityRenderingExtEventUpdateTextureBeginV1\n    kUnityRenderingExtEventUpdateTextureBeginV2,                                                // Issued to update a texture. It carries over UnityRenderingExtTextureUpdateParamsV2\n    kUnityRenderingExtEventUpdateTextureEndV2,                                                  // Issued to signal the plugin that the texture update has finished. It carries over the same UnityRenderingExtTextureUpdateParamsV2 as kUnityRenderingExtEventUpdateTextureBeginV2\n\n    // keep this last\n    kUnityRenderingExtEventCount,\n    kUnityRenderingExtUserEventsStart = kUnityRenderingExtEventCount\n} UnityRenderingExtEventType;\n\n\ntypedef enum UnityRenderingExtCustomBlitCommands\n{\n    kUnityRenderingExtCustomBlitVRFlush,                    // This event is mostly used in multi GPU configurations ( SLI, etc ) in order to allow the plugin to flush all GPU's targets\n\n    // keep this last\n    kUnityRenderingExtCustomBlitCount,\n    kUnityRenderingExtUserCustomBlitStart = kUnityRenderingExtCustomBlitCount\n} UnityRenderingExtCustomBlitCommands;\n\n/*\n    This will be propagated to all plugins implementing UnityRenderingExtQuery.\n*/\ntypedef enum UnityRenderingExtQueryType\n{\n    kUnityRenderingExtQueryOverrideViewport             = 1 << 0,           // The plugin handles setting up the viewport rects. Unity will skip its internal SetViewport calls\n    kUnityRenderingExtQueryOverrideScissor              = 1 << 1,           // The plugin handles setting up the scissor rects. Unity will skip its internal SetScissor calls\n    kUnityRenderingExtQueryOverrideVROcclussionMesh     = 1 << 2,           // The plugin handles its own VR occlusion mesh rendering. Unity will skip rendering its internal VR occlusion mask\n    kUnityRenderingExtQueryOverrideVRSinglePass         = 1 << 3,           // The plugin uses its own single pass stereo technique. Unity will only traverse and render the render node graph once.\n                                                                            //      and it will clear the whole render target not just per-eye on demand.\n    kUnityRenderingExtQueryKeepOriginalDoubleWideWidth_DEPRECATED  = 1 << 4,           // Instructs unity to keep the original double wide width. By default unity will try and have a power-of-two width for mip-mapping requirements.\n    kUnityRenderingExtQueryRequestVRFlushCallback       = 1 << 5,           // Instructs unity to provide callbacks when the VR eye textures need flushing. Useful for multi GPU synchronization.\n    kUnityRenderingExtQueryOverridePresentFrame         = 1 << 6,           // The plugin handles it's own SwapChain Present. Unity will skip its internal Present calls\n} UnityRenderingExtQueryType;\n\n\ntypedef enum UnityRenderingExtTextureFormat\n{\n    kUnityRenderingExtFormatNone = 0, kUnityRenderingExtFormatFirst = kUnityRenderingExtFormatNone,\n\n    // sRGB formats\n    kUnityRenderingExtFormatR8_SRGB,\n    kUnityRenderingExtFormatR8G8_SRGB,\n    kUnityRenderingExtFormatR8G8B8_SRGB,\n    kUnityRenderingExtFormatR8G8B8A8_SRGB,\n\n    // 8 bit integer formats\n    kUnityRenderingExtFormatR8_UNorm,\n    kUnityRenderingExtFormatR8G8_UNorm,\n    kUnityRenderingExtFormatR8G8B8_UNorm,\n    kUnityRenderingExtFormatR8G8B8A8_UNorm,\n    kUnityRenderingExtFormatR8_SNorm,\n    kUnityRenderingExtFormatR8G8_SNorm,\n    kUnityRenderingExtFormatR8G8B8_SNorm,\n    kUnityRenderingExtFormatR8G8B8A8_SNorm,\n    kUnityRenderingExtFormatR8_UInt,\n    kUnityRenderingExtFormatR8G8_UInt,\n    kUnityRenderingExtFormatR8G8B8_UInt,\n    kUnityRenderingExtFormatR8G8B8A8_UInt,\n    kUnityRenderingExtFormatR8_SInt,\n    kUnityRenderingExtFormatR8G8_SInt,\n    kUnityRenderingExtFormatR8G8B8_SInt,\n    kUnityRenderingExtFormatR8G8B8A8_SInt,\n\n    // 16 bit integer formats\n    kUnityRenderingExtFormatR16_UNorm,\n    kUnityRenderingExtFormatR16G16_UNorm,\n    kUnityRenderingExtFormatR16G16B16_UNorm,\n    kUnityRenderingExtFormatR16G16B16A16_UNorm,\n    kUnityRenderingExtFormatR16_SNorm,\n    kUnityRenderingExtFormatR16G16_SNorm,\n    kUnityRenderingExtFormatR16G16B16_SNorm,\n    kUnityRenderingExtFormatR16G16B16A16_SNorm,\n    kUnityRenderingExtFormatR16_UInt,\n    kUnityRenderingExtFormatR16G16_UInt,\n    kUnityRenderingExtFormatR16G16B16_UInt,\n    kUnityRenderingExtFormatR16G16B16A16_UInt,\n    kUnityRenderingExtFormatR16_SInt,\n    kUnityRenderingExtFormatR16G16_SInt,\n    kUnityRenderingExtFormatR16G16B16_SInt,\n    kUnityRenderingExtFormatR16G16B16A16_SInt,\n\n    // 32 bit integer formats\n    kUnityRenderingExtFormatR32_UInt,\n    kUnityRenderingExtFormatR32G32_UInt,\n    kUnityRenderingExtFormatR32G32B32_UInt,\n    kUnityRenderingExtFormatR32G32B32A32_UInt,\n    kUnityRenderingExtFormatR32_SInt,\n    kUnityRenderingExtFormatR32G32_SInt,\n    kUnityRenderingExtFormatR32G32B32_SInt,\n    kUnityRenderingExtFormatR32G32B32A32_SInt,\n\n    // HDR formats\n    kUnityRenderingExtFormatR16_SFloat,\n    kUnityRenderingExtFormatR16G16_SFloat,\n    kUnityRenderingExtFormatR16G16B16_SFloat,\n    kUnityRenderingExtFormatR16G16B16A16_SFloat,\n    kUnityRenderingExtFormatR32_SFloat,\n    kUnityRenderingExtFormatR32G32_SFloat,\n    kUnityRenderingExtFormatR32G32B32_SFloat,\n    kUnityRenderingExtFormatR32G32B32A32_SFloat,\n\n    // Luminance and Alpha format\n    kUnityRenderingExtFormatL8_UNorm,\n    kUnityRenderingExtFormatA8_UNorm,\n    kUnityRenderingExtFormatA16_UNorm,\n\n    // BGR formats\n    kUnityRenderingExtFormatB8G8R8_SRGB,\n    kUnityRenderingExtFormatB8G8R8A8_SRGB,\n    kUnityRenderingExtFormatB8G8R8_UNorm,\n    kUnityRenderingExtFormatB8G8R8A8_UNorm,\n    kUnityRenderingExtFormatB8G8R8_SNorm,\n    kUnityRenderingExtFormatB8G8R8A8_SNorm,\n    kUnityRenderingExtFormatB8G8R8_UInt,\n    kUnityRenderingExtFormatB8G8R8A8_UInt,\n    kUnityRenderingExtFormatB8G8R8_SInt,\n    kUnityRenderingExtFormatB8G8R8A8_SInt,\n\n    // 16 bit packed formats\n    kUnityRenderingExtFormatR4G4B4A4_UNormPack16,\n    kUnityRenderingExtFormatB4G4R4A4_UNormPack16,\n    kUnityRenderingExtFormatR5G6B5_UNormPack16,\n    kUnityRenderingExtFormatB5G6R5_UNormPack16,\n    kUnityRenderingExtFormatR5G5B5A1_UNormPack16,\n    kUnityRenderingExtFormatB5G5R5A1_UNormPack16,\n    kUnityRenderingExtFormatA1R5G5B5_UNormPack16,\n\n    // Packed formats\n    kUnityRenderingExtFormatE5B9G9R9_UFloatPack32,\n    kUnityRenderingExtFormatB10G11R11_UFloatPack32,\n\n    kUnityRenderingExtFormatA2B10G10R10_UNormPack32,\n    kUnityRenderingExtFormatA2B10G10R10_UIntPack32,\n    kUnityRenderingExtFormatA2B10G10R10_SIntPack32,\n    kUnityRenderingExtFormatA2R10G10B10_UNormPack32,\n    kUnityRenderingExtFormatA2R10G10B10_UIntPack32,\n    kUnityRenderingExtFormatA2R10G10B10_SIntPack32,\n    kUnityRenderingExtFormatA2R10G10B10_XRSRGBPack32,\n    kUnityRenderingExtFormatA2R10G10B10_XRUNormPack32,\n    kUnityRenderingExtFormatR10G10B10_XRSRGBPack32,\n    kUnityRenderingExtFormatR10G10B10_XRUNormPack32,\n    kUnityRenderingExtFormatA10R10G10B10_XRSRGBPack32,\n    kUnityRenderingExtFormatA10R10G10B10_XRUNormPack32,\n\n    // ARGB formats... TextureFormat legacy\n    kUnityRenderingExtFormatA8R8G8B8_SRGB,\n    kUnityRenderingExtFormatA8R8G8B8_UNorm,\n    kUnityRenderingExtFormatA32R32G32B32_SFloat,\n\n    // Depth Stencil for formats\n    kUnityRenderingExtFormatD16_UNorm,\n    kUnityRenderingExtFormatD24_UNorm,\n    kUnityRenderingExtFormatD24_UNorm_S8_UInt,\n    kUnityRenderingExtFormatD32_SFloat,\n    kUnityRenderingExtFormatD32_SFloat_S8_UInt,\n    kUnityRenderingExtFormatS8_UInt,\n\n    // Compression formats\n    kUnityRenderingExtFormatRGBA_DXT1_SRGB,\n    kUnityRenderingExtFormatRGBA_DXT1_UNorm,\n    kUnityRenderingExtFormatRGBA_DXT3_SRGB,\n    kUnityRenderingExtFormatRGBA_DXT3_UNorm,\n    kUnityRenderingExtFormatRGBA_DXT5_SRGB,\n    kUnityRenderingExtFormatRGBA_DXT5_UNorm,\n    kUnityRenderingExtFormatR_BC4_UNorm,\n    kUnityRenderingExtFormatR_BC4_SNorm,\n    kUnityRenderingExtFormatRG_BC5_UNorm,\n    kUnityRenderingExtFormatRG_BC5_SNorm,\n    kUnityRenderingExtFormatRGB_BC6H_UFloat,\n    kUnityRenderingExtFormatRGB_BC6H_SFloat,\n    kUnityRenderingExtFormatRGBA_BC7_SRGB,\n    kUnityRenderingExtFormatRGBA_BC7_UNorm,\n\n    kUnityRenderingExtFormatRGB_PVRTC_2Bpp_SRGB,\n    kUnityRenderingExtFormatRGB_PVRTC_2Bpp_UNorm,\n    kUnityRenderingExtFormatRGB_PVRTC_4Bpp_SRGB,\n    kUnityRenderingExtFormatRGB_PVRTC_4Bpp_UNorm,\n    kUnityRenderingExtFormatRGBA_PVRTC_2Bpp_SRGB,\n    kUnityRenderingExtFormatRGBA_PVRTC_2Bpp_UNorm,\n    kUnityRenderingExtFormatRGBA_PVRTC_4Bpp_SRGB,\n    kUnityRenderingExtFormatRGBA_PVRTC_4Bpp_UNorm,\n\n    kUnityRenderingExtFormatRGB_ETC_UNorm,\n    kUnityRenderingExtFormatRGB_ETC2_SRGB,\n    kUnityRenderingExtFormatRGB_ETC2_UNorm,\n    kUnityRenderingExtFormatRGB_A1_ETC2_SRGB,\n    kUnityRenderingExtFormatRGB_A1_ETC2_UNorm,\n    kUnityRenderingExtFormatRGBA_ETC2_SRGB,\n    kUnityRenderingExtFormatRGBA_ETC2_UNorm,\n\n    kUnityRenderingExtFormatR_EAC_UNorm,\n    kUnityRenderingExtFormatR_EAC_SNorm,\n    kUnityRenderingExtFormatRG_EAC_UNorm,\n    kUnityRenderingExtFormatRG_EAC_SNorm,\n\n    kUnityRenderingExtFormatRGBA_ASTC4X4_SRGB,\n    kUnityRenderingExtFormatRGBA_ASTC4X4_UNorm,\n    kUnityRenderingExtFormatRGBA_ASTC5X5_SRGB,\n    kUnityRenderingExtFormatRGBA_ASTC5X5_UNorm,\n    kUnityRenderingExtFormatRGBA_ASTC6X6_SRGB,\n    kUnityRenderingExtFormatRGBA_ASTC6X6_UNorm,\n    kUnityRenderingExtFormatRGBA_ASTC8X8_SRGB,\n    kUnityRenderingExtFormatRGBA_ASTC8X8_UNorm,\n    kUnityRenderingExtFormatRGBA_ASTC10X10_SRGB,\n    kUnityRenderingExtFormatRGBA_ASTC10X10_UNorm,\n    kUnityRenderingExtFormatRGBA_ASTC12X12_SRGB,\n    kUnityRenderingExtFormatRGBA_ASTC12X12_UNorm,\n\n    // Video formats\n    kUnityRenderingExtFormatYUV2,\n\n    // Obsoleted\n    //kUnityRenderingExtFormatDepthAuto_removed_donotuse = 142,\n    //kUnityRenderingExtFormatShadowAuto_removed_donotuse = 143,\n    //kUnityRenderingExtFormatVideoAuto_removed_donotuse = 144,\n\n    // ASTC hdr profile\n    kUnityRenderingExtFormatRGBA_ASTC4X4_UFloat = 145,\n    kUnityRenderingExtFormatRGBA_ASTC5X5_UFloat,\n    kUnityRenderingExtFormatRGBA_ASTC6X6_UFloat,\n    kUnityRenderingExtFormatRGBA_ASTC8X8_UFloat,\n    kUnityRenderingExtFormatRGBA_ASTC10X10_UFloat,\n    kUnityRenderingExtFormatRGBA_ASTC12X12_UFloat,\n\n    kUnityRenderingExtFormatLast = kUnityRenderingExtFormatRGBA_ASTC12X12_UFloat, // Remove?\n} UnityRenderingExtTextureFormat;\n\n\ntypedef struct UnityRenderingExtBeforeDrawCallParams\n{\n    void*   vertexShader;                           // bound vertex shader (platform dependent)\n    void*   fragmentShader;                         // bound fragment shader (platform dependent)\n    void*   geometryShader;                         // bound geometry shader (platform dependent)\n    void*   hullShader;                             // bound hull shader (platform dependent)\n    void*   domainShader;                           // bound domain shader (platform dependent)\n    int     eyeIndex;                               // the index of the current stereo \"eye\" being currently rendered.\n} UnityRenderingExtBeforeDrawCallParams;\n\n\ntypedef struct UnityRenderingExtCustomBlitParams\n{\n    UnityTextureID source;                          // source texture\n    UnityRenderBuffer destination;                  // destination surface\n    unsigned int command;                           // command for the custom blit - could be any UnityRenderingExtCustomBlitCommands command or custom ones.\n    unsigned int commandParam;                      // custom parameters for the command\n    unsigned int commandFlags;                      // custom flags for the command\n} UnityRenderingExtCustomBlitParams;\n\n// Deprecated. Use UnityRenderingExtTextureUpdateParamsV2 and CommandBuffer.IssuePluginCustomTextureUpdateV2 instead.\n// Only supports DX11, GLES, Metal\ntypedef struct UnityRenderingExtTextureUpdateParamsV1\n{\n    void*        texData;                           // source data for the texture update. Must be set by the plugin\n    unsigned int userData;                          // user defined data. Set by the plugin\n\n    unsigned int textureID;                         // texture ID of the texture to be updated.\n    UnityRenderingExtTextureFormat format;          // format of the texture to be updated\n    unsigned int width;                             // width of the texture\n    unsigned int height;                            // height of the texture\n    unsigned int bpp;                               // texture bytes per pixel.\n} UnityRenderingExtTextureUpdateParamsV1;\n\n// Deprecated. Use UnityRenderingExtTextureUpdateParamsV2 and CommandBuffer.IssuePluginCustomTextureUpdateV2 instead.\n// Only supports DX11, GLES, Metal\ntypedef UnityRenderingExtTextureUpdateParamsV1 UnityRenderingExtTextureUpdateParams;\n\n// Type of the \"data\" parameter passed when callbacks registered with CommandBuffer.IssuePluginCustomTextureUpdateV2 are called.\n// Supports DX11, GLES, Metal, and Switch (also possibly PS4, PSVita in the future)\ntypedef struct UnityRenderingExtTextureUpdateParamsV2\n{\n    void*        texData;                           // source data for the texture update. Must be set by the plugin\n    intptr_t     textureID;                         // texture ID of the texture to be updated.\n    unsigned int userData;                          // user defined data. Set by the plugin\n    UnityRenderingExtTextureFormat format;          // format of the texture to be updated\n    unsigned int width;                             // width of the texture\n    unsigned int height;                            // height of the texture\n    unsigned int bpp;                               // texture bytes per pixel.\n} UnityRenderingExtTextureUpdateParamsV2;\n\n\n// Certain Unity APIs (GL.IssuePluginEventAndData, CommandBuffer.IssuePluginEventAndData) can callback into native plugins.\n// Provide them with an address to a function of this signature.\ntypedef void (UNITY_INTERFACE_API * UnityRenderingEventAndData)(int eventId, void* data);\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n// If exported by a plugin, this function will be called for all the events in UnityRenderingExtEventType\nvoid UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityRenderingExtEvent(UnityRenderingExtEventType event, void* data);\n// If exported by a plugin, this function will be called to query the plugin for the queries in UnityRenderingExtQueryType\nbool UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityRenderingExtQuery(UnityRenderingExtQueryType query);\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "Plugin/build.macos.sh",
    "content": "#!/bin/sh\nset -exuo pipefail\n\nRPATH_FLAGS=\"-install_name @rpath/KlakHap.bundle\"\nVER_FLAGS=\"-current_version 1.0.0 -compatibility_version 1.0.0\"\n\nmake ARCH=arm64  SO_ARGS=\"$RPATH_FLAGS $VER_FLAGS\" -f Makefile.macos\nmake ARCH=x86_64 SO_ARGS=\"$RPATH_FLAGS $VER_FLAGS\" -f Makefile.macos\n\nlipo -create -output KlakHap.bundle \\\n  build-macOS-arm64/libKlakHap.dylib \\\n  build-macOS-x86_64/libKlakHap.dylib\n\ncp KlakHap.bundle ../Packages/jp.keijiro.klak.hap/Plugin/MacOS/\n"
  },
  {
    "path": "ProjectSettings/AudioManager.asset",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!11 &1\nAudioManager:\n  m_ObjectHideFlags: 0\n  serializedVersion: 2\n  m_Volume: 1\n  Rolloff Scale: 1\n  Doppler Factor: 1\n  Default Speaker Mode: 2\n  m_SampleRate: 0\n  m_DSPBufferSize: 1024\n  m_VirtualVoiceCount: 512\n  m_RealVoiceCount: 32\n  m_EnableOutputSuspension: 1\n  m_SpatializerPlugin: \n  m_AmbisonicDecoderPlugin: \n  m_DisableAudio: 0\n  m_VirtualizeEffects: 1\n  m_RequestedDSPBufferSize: 0\n  m_AudioFoundation: 0\n  m_OutputChannelLayout: 2\n  m_OutputSamplingRate: 48000\n"
  },
  {
    "path": "ProjectSettings/ClusterInputManager.asset",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!236 &1\nClusterInputManager:\n  m_ObjectHideFlags: 0\n  m_Inputs: []\n"
  },
  {
    "path": "ProjectSettings/DynamicsManager.asset",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!55 &1\nPhysicsManager:\n  m_ObjectHideFlags: 0\n  serializedVersion: 22\n  m_Gravity: {x: 0, y: -9.81, z: 0}\n  m_DefaultMaterial: {fileID: 0}\n  m_BounceThreshold: 2\n  m_DefaultMaxDepenetrationVelocity: 10\n  m_SleepThreshold: 0.005\n  m_DefaultContactOffset: 0.01\n  m_DefaultSolverIterations: 6\n  m_DefaultSolverVelocityIterations: 1\n  m_QueriesHitBackfaces: 0\n  m_QueriesHitTriggers: 1\n  m_EnableAdaptiveForce: 0\n  m_ClothInterCollisionDistance: 0.1\n  m_ClothInterCollisionStiffness: 0.2\n  m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n  m_SimulationMode: 0\n  m_AutoSyncTransforms: 0\n  m_ReuseCollisionCallbacks: 1\n  m_InvokeCollisionCallbacks: 1\n  m_ClothInterCollisionSettingsToggle: 0\n  m_ClothGravity: {x: 0, y: -9.81, z: 0}\n  m_ContactPairsMode: 0\n  m_BroadphaseType: 0\n  m_WorldBounds:\n    m_Center: {x: 0, y: 0, z: 0}\n    m_Extent: {x: 256, y: 256, z: 256}\n  m_WorldSubdivisions: 8\n  m_FrictionType: 0\n  m_EnableEnhancedDeterminism: 0\n  m_ImprovedPatchFriction: 0\n  m_GenerateOnTriggerStayEvents: 1\n  m_SolverType: 0\n  m_DefaultMaxAngularSpeed: 50\n  m_ScratchBufferChunkCount: 4\n  m_CurrentBackendId: 4072204805\n  m_FastMotionThreshold: 3.4028235e+38\n  m_SceneBuffersReleaseInterval: 0\n  m_ReleaseSceneBuffers: 0\n  m_LogVerbosity: 3\n"
  },
  {
    "path": "ProjectSettings/EditorBuildSettings.asset",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!1045 &1\nEditorBuildSettings:\n  m_ObjectHideFlags: 0\n  serializedVersion: 2\n  m_Scenes: []\n  m_configObjects: {}\n  m_UseUCBPForAssetBundles: 0\n"
  },
  {
    "path": "ProjectSettings/EditorSettings.asset",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!159 &1\nEditorSettings:\n  m_ObjectHideFlags: 0\n  serializedVersion: 15\n  m_SerializationMode: 2\n  m_LineEndingsForNewScripts: 1\n  m_DefaultBehaviorMode: 0\n  m_PrefabRegularEnvironment: {fileID: 0}\n  m_PrefabUIEnvironment: {fileID: 0}\n  m_SpritePackerMode: 0\n  m_SpritePackerCacheSize: 10\n  m_SpritePackerPaddingPower: 1\n  m_Bc7TextureCompressor: 0\n  m_EtcTextureCompressorBehavior: 1\n  m_EtcTextureFastCompressor: 1\n  m_EtcTextureNormalCompressor: 2\n  m_EtcTextureBestCompressor: 4\n  m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd;asmdef;asmref;rsp;java;cpp;c;mm;m;h\n  m_ProjectGenerationRootNamespace: \n  m_EnableTextureStreamingInEditMode: 1\n  m_EnableTextureStreamingInPlayMode: 1\n  m_EnableEditorAsyncCPUTextureLoading: 0\n  m_AsyncShaderCompilation: 1\n  m_PrefabModeAllowAutoSave: 1\n  m_EnterPlayModeOptionsEnabled: 1\n  m_EnterPlayModeOptions: 3\n  m_GameObjectNamingDigits: 1\n  m_GameObjectNamingScheme: 0\n  m_AssetNamingUsesSpace: 1\n  m_InspectorUseIMGUIDefaultInspector: 0\n  m_UseLegacyProbeSampleCount: 0\n  m_SerializeInlineMappingsOnOneLine: 1\n  m_DisableCookiesInLightmapper: 0\n  m_ShadowmaskStitching: 1\n  m_AssetPipelineMode: 1\n  m_RefreshImportMode: 0\n  m_CacheServerMode: 0\n  m_CacheServerEndpoint: \n  m_CacheServerNamespacePrefix: default\n  m_CacheServerEnableDownload: 1\n  m_CacheServerEnableUpload: 1\n  m_CacheServerEnableAuth: 0\n  m_CacheServerEnableTls: 0\n  m_CacheServerValidationMode: 2\n  m_CacheServerDownloadBatchSize: 128\n  m_EnableEnlightenBakedGI: 0\n  m_ReferencedClipsExactNaming: 1\n  m_ForceAssetUnloadAndGCOnSceneLoad: 1\n"
  },
  {
    "path": "ProjectSettings/GraphicsSettings.asset",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!30 &1\nGraphicsSettings:\n  m_ObjectHideFlags: 0\n  serializedVersion: 16\n  m_Deferred:\n    m_Mode: 1\n    m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0}\n  m_DeferredReflections:\n    m_Mode: 1\n    m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0}\n  m_ScreenSpaceShadows:\n    m_Mode: 1\n    m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0}\n  m_DepthNormals:\n    m_Mode: 1\n    m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0}\n  m_MotionVectors:\n    m_Mode: 1\n    m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0}\n  m_LightHalo:\n    m_Mode: 1\n    m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0}\n  m_LensFlare:\n    m_Mode: 1\n    m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0}\n  m_VideoShadersIncludeMode: 2\n  m_AlwaysIncludedShaders:\n  - {fileID: 7, guid: 0000000000000000f000000000000000, type: 0}\n  - {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0}\n  - {fileID: 15105, guid: 0000000000000000f000000000000000, type: 0}\n  - {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0}\n  - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0}\n  - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0}\n  - {fileID: 10783, guid: 0000000000000000f000000000000000, type: 0}\n  m_PreloadedShaders: []\n  m_PreloadShadersBatchTimeLimit: -1\n  m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0}\n  m_CustomRenderPipeline: {fileID: 11400000, guid: 0f2789a7f25c049d88040a322e46da7c, type: 2}\n  m_TransparencySortMode: 0\n  m_TransparencySortAxis: {x: 0, y: 0, z: 1}\n  m_DefaultRenderingPath: 1\n  m_DefaultMobileRenderingPath: 1\n  m_TierSettings: []\n  m_LightmapStripping: 0\n  m_FogStripping: 0\n  m_InstancingStripping: 0\n  m_BrgStripping: 0\n  m_LightmapKeepPlain: 1\n  m_LightmapKeepDirCombined: 1\n  m_LightmapKeepDynamicPlain: 1\n  m_LightmapKeepDynamicDirCombined: 1\n  m_LightmapKeepShadowMask: 1\n  m_LightmapKeepSubtractive: 1\n  m_FogKeepLinear: 1\n  m_FogKeepExp: 1\n  m_FogKeepExp2: 1\n  m_AlbedoSwatchInfos: []\n  m_RenderPipelineGlobalSettingsMap:\n    UnityEngine.Rendering.Universal.UniversalRenderPipeline: {fileID: 11400000, guid: a0e1abbc8745e464ab699ff4e71959f6, type: 2}\n  m_ShaderBuildSettings:\n    keywordDeclarationOverrides: []\n  m_LightsUseLinearIntensity: 1\n  m_LightsUseColorTemperature: 1\n  m_LogWhenShaderIsCompiled: 0\n  m_LightProbeOutsideHullStrategy: 1\n  m_CameraRelativeLightCulling: 0\n  m_CameraRelativeShadowCulling: 0\n"
  },
  {
    "path": "ProjectSettings/InputManager.asset",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!13 &1\nInputManager:\n  m_ObjectHideFlags: 0\n  serializedVersion: 2\n  m_Axes:\n  - serializedVersion: 3\n    m_Name: Horizontal\n    descriptiveName: \n    descriptiveNegativeName: \n    negativeButton: left\n    positiveButton: right\n    altNegativeButton: a\n    altPositiveButton: d\n    gravity: 3\n    dead: 0.001\n    sensitivity: 3\n    snap: 1\n    invert: 0\n    type: 0\n    axis: 0\n    joyNum: 0\n  - serializedVersion: 3\n    m_Name: Vertical\n    descriptiveName: \n    descriptiveNegativeName: \n    negativeButton: down\n    positiveButton: up\n    altNegativeButton: s\n    altPositiveButton: w\n    gravity: 3\n    dead: 0.001\n    sensitivity: 3\n    snap: 1\n    invert: 0\n    type: 0\n    axis: 0\n    joyNum: 0\n  - serializedVersion: 3\n    m_Name: Fire1\n    descriptiveName: \n    descriptiveNegativeName: \n    negativeButton: \n    positiveButton: left ctrl\n    altNegativeButton: \n    altPositiveButton: mouse 0\n    gravity: 1000\n    dead: 0.001\n    sensitivity: 1000\n    snap: 0\n    invert: 0\n    type: 0\n    axis: 0\n    joyNum: 0\n  - serializedVersion: 3\n    m_Name: Fire2\n    descriptiveName: \n    descriptiveNegativeName: \n    negativeButton: \n    positiveButton: left alt\n    altNegativeButton: \n    altPositiveButton: mouse 1\n    gravity: 1000\n    dead: 0.001\n    sensitivity: 1000\n    snap: 0\n    invert: 0\n    type: 0\n    axis: 0\n    joyNum: 0\n  - serializedVersion: 3\n    m_Name: Fire3\n    descriptiveName: \n    descriptiveNegativeName: \n    negativeButton: \n    positiveButton: left shift\n    altNegativeButton: \n    altPositiveButton: mouse 2\n    gravity: 1000\n    dead: 0.001\n    sensitivity: 1000\n    snap: 0\n    invert: 0\n    type: 0\n    axis: 0\n    joyNum: 0\n  - serializedVersion: 3\n    m_Name: Jump\n    descriptiveName: \n    descriptiveNegativeName: \n    negativeButton: \n    positiveButton: space\n    altNegativeButton: \n    altPositiveButton: \n    gravity: 1000\n    dead: 0.001\n    sensitivity: 1000\n    snap: 0\n    invert: 0\n    type: 0\n    axis: 0\n    joyNum: 0\n  - serializedVersion: 3\n    m_Name: Mouse X\n    descriptiveName: \n    descriptiveNegativeName: \n    negativeButton: \n    positiveButton: \n    altNegativeButton: \n    altPositiveButton: \n    gravity: 0\n    dead: 0\n    sensitivity: 0.1\n    snap: 0\n    invert: 0\n    type: 1\n    axis: 0\n    joyNum: 0\n  - serializedVersion: 3\n    m_Name: Mouse Y\n    descriptiveName: \n    descriptiveNegativeName: \n    negativeButton: \n    positiveButton: \n    altNegativeButton: \n    altPositiveButton: \n    gravity: 0\n    dead: 0\n    sensitivity: 0.1\n    snap: 0\n    invert: 0\n    type: 1\n    axis: 1\n    joyNum: 0\n  - serializedVersion: 3\n    m_Name: Mouse ScrollWheel\n    descriptiveName: \n    descriptiveNegativeName: \n    negativeButton: \n    positiveButton: \n    altNegativeButton: \n    altPositiveButton: \n    gravity: 0\n    dead: 0\n    sensitivity: 0.1\n    snap: 0\n    invert: 0\n    type: 1\n    axis: 2\n    joyNum: 0\n  - serializedVersion: 3\n    m_Name: Horizontal\n    descriptiveName: \n    descriptiveNegativeName: \n    negativeButton: \n    positiveButton: \n    altNegativeButton: \n    altPositiveButton: \n    gravity: 0\n    dead: 0.19\n    sensitivity: 1\n    snap: 0\n    invert: 0\n    type: 2\n    axis: 0\n    joyNum: 0\n  - serializedVersion: 3\n    m_Name: Vertical\n    descriptiveName: \n    descriptiveNegativeName: \n    negativeButton: \n    positiveButton: \n    altNegativeButton: \n    altPositiveButton: \n    gravity: 0\n    dead: 0.19\n    sensitivity: 1\n    snap: 0\n    invert: 1\n    type: 2\n    axis: 1\n    joyNum: 0\n  - serializedVersion: 3\n    m_Name: Fire1\n    descriptiveName: \n    descriptiveNegativeName: \n    negativeButton: \n    positiveButton: joystick button 0\n    altNegativeButton: \n    altPositiveButton: \n    gravity: 1000\n    dead: 0.001\n    sensitivity: 1000\n    snap: 0\n    invert: 0\n    type: 0\n    axis: 0\n    joyNum: 0\n  - serializedVersion: 3\n    m_Name: Fire2\n    descriptiveName: \n    descriptiveNegativeName: \n    negativeButton: \n    positiveButton: joystick button 1\n    altNegativeButton: \n    altPositiveButton: \n    gravity: 1000\n    dead: 0.001\n    sensitivity: 1000\n    snap: 0\n    invert: 0\n    type: 0\n    axis: 0\n    joyNum: 0\n  - serializedVersion: 3\n    m_Name: Fire3\n    descriptiveName: \n    descriptiveNegativeName: \n    negativeButton: \n    positiveButton: joystick button 2\n    altNegativeButton: \n    altPositiveButton: \n    gravity: 1000\n    dead: 0.001\n    sensitivity: 1000\n    snap: 0\n    invert: 0\n    type: 0\n    axis: 0\n    joyNum: 0\n  - serializedVersion: 3\n    m_Name: Jump\n    descriptiveName: \n    descriptiveNegativeName: \n    negativeButton: \n    positiveButton: joystick button 3\n    altNegativeButton: \n    altPositiveButton: \n    gravity: 1000\n    dead: 0.001\n    sensitivity: 1000\n    snap: 0\n    invert: 0\n    type: 0\n    axis: 0\n    joyNum: 0\n  - serializedVersion: 3\n    m_Name: Submit\n    descriptiveName: \n    descriptiveNegativeName: \n    negativeButton: \n    positiveButton: return\n    altNegativeButton: \n    altPositiveButton: joystick button 0\n    gravity: 1000\n    dead: 0.001\n    sensitivity: 1000\n    snap: 0\n    invert: 0\n    type: 0\n    axis: 0\n    joyNum: 0\n  - serializedVersion: 3\n    m_Name: Submit\n    descriptiveName: \n    descriptiveNegativeName: \n    negativeButton: \n    positiveButton: enter\n    altNegativeButton: \n    altPositiveButton: space\n    gravity: 1000\n    dead: 0.001\n    sensitivity: 1000\n    snap: 0\n    invert: 0\n    type: 0\n    axis: 0\n    joyNum: 0\n  - serializedVersion: 3\n    m_Name: Cancel\n    descriptiveName: \n    descriptiveNegativeName: \n    negativeButton: \n    positiveButton: escape\n    altNegativeButton: \n    altPositiveButton: joystick button 1\n    gravity: 1000\n    dead: 0.001\n    sensitivity: 1000\n    snap: 0\n    invert: 0\n    type: 0\n    axis: 0\n    joyNum: 0\n  m_UsePhysicalKeys: 1\n"
  },
  {
    "path": "ProjectSettings/MemorySettings.asset",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!387306366 &1\nMemorySettings:\n  m_ObjectHideFlags: 0\n  m_EditorMemorySettings:\n    m_MainAllocatorBlockSize: -1\n    m_ThreadAllocatorBlockSize: -1\n    m_MainGfxBlockSize: -1\n    m_ThreadGfxBlockSize: -1\n    m_CacheBlockSize: -1\n    m_TypetreeBlockSize: -1\n    m_ProfilerBlockSize: -1\n    m_ProfilerEditorBlockSize: -1\n    m_BucketAllocatorGranularity: -1\n    m_BucketAllocatorBucketsCount: -1\n    m_BucketAllocatorBlockSize: -1\n    m_BucketAllocatorBlockCount: -1\n    m_ProfilerBucketAllocatorGranularity: -1\n    m_ProfilerBucketAllocatorBucketsCount: -1\n    m_ProfilerBucketAllocatorBlockSize: -1\n    m_ProfilerBucketAllocatorBlockCount: -1\n    m_TempAllocatorSizeMain: -1\n    m_JobTempAllocatorBlockSize: -1\n    m_BackgroundJobTempAllocatorBlockSize: -1\n    m_JobTempAllocatorReducedBlockSize: -1\n    m_TempAllocatorSizeGIBakingWorker: -1\n    m_TempAllocatorSizeNavMeshWorker: -1\n    m_TempAllocatorSizeAudioWorker: -1\n    m_TempAllocatorSizeCloudWorker: -1\n    m_TempAllocatorSizeGfx: -1\n    m_TempAllocatorSizeJobWorker: -1\n    m_TempAllocatorSizeBackgroundWorker: -1\n    m_TempAllocatorSizePreloadManager: -1\n  m_PlatformMemorySettings: {}\n"
  },
  {
    "path": "ProjectSettings/MultiplayerManager.asset",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!655991488 &1\nMultiplayerManager:\n  m_ObjectHideFlags: 0\n  m_EnableMultiplayerRoles: 0\n  m_EnablePlayModeLocalDeployment: 0\n  m_EnablePlayModeRemoteDeployment: 0\n  m_StrippingTypes: {}\n"
  },
  {
    "path": "ProjectSettings/NavMeshAreas.asset",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!126 &1\nNavMeshProjectSettings:\n  m_ObjectHideFlags: 0\n  serializedVersion: 2\n  areas:\n  - name: Walkable\n    cost: 1\n  - name: Not Walkable\n    cost: 1\n  - name: Jump\n    cost: 2\n  - name: \n    cost: 1\n  - name: \n    cost: 1\n  - name: \n    cost: 1\n  - name: \n    cost: 1\n  - name: \n    cost: 1\n  - name: \n    cost: 1\n  - name: \n    cost: 1\n  - name: \n    cost: 1\n  - name: \n    cost: 1\n  - name: \n    cost: 1\n  - name: \n    cost: 1\n  - name: \n    cost: 1\n  - name: \n    cost: 1\n  - name: \n    cost: 1\n  - name: \n    cost: 1\n  - name: \n    cost: 1\n  - name: \n    cost: 1\n  - name: \n    cost: 1\n  - name: \n    cost: 1\n  - name: \n    cost: 1\n  - name: \n    cost: 1\n  - name: \n    cost: 1\n  - name: \n    cost: 1\n  - name: \n    cost: 1\n  - name: \n    cost: 1\n  - name: \n    cost: 1\n  - name: \n    cost: 1\n  - name: \n    cost: 1\n  - name: \n    cost: 1\n  m_LastAgentTypeID: -887442657\n  m_Settings:\n  - serializedVersion: 3\n    agentTypeID: 0\n    agentRadius: 0.5\n    agentHeight: 2\n    agentSlope: 45\n    agentClimb: 0.75\n    ledgeDropHeight: 0\n    maxJumpAcrossDistance: 0\n    minRegionArea: 2\n    manualCellSize: 0\n    cellSize: 0.16666667\n    manualTileSize: 0\n    tileSize: 256\n    buildHeightMesh: 0\n    maxJobWorkers: 0\n    preserveTilesOutsideBounds: 0\n    debug:\n      m_Flags: 0\n  m_SettingNames:\n  - Humanoid\n"
  },
  {
    "path": "ProjectSettings/PackageManagerSettings.asset",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!114 &1\nMonoBehaviour:\n  m_ObjectHideFlags: 53\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 0}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 13964, guid: 0000000000000000e000000000000000, type: 0}\n  m_Name: \n  m_EditorClassIdentifier: UnityEditor.dll::UnityEditor.PackageManager.UI.Internal.PackageManagerProjectSettings\n  m_EnablePreReleasePackages: 1\n  m_AdvancedSettingsExpanded: 1\n  m_ScopedRegistriesSettingsExpanded: 1\n  m_SeeAllPackageVersions: 0\n  m_DismissPreviewPackagesInUse: 0\n  oneTimeWarningShown: 1\n  oneTimePackageErrorsPopUpShown: 0\n  m_Registries:\n  - m_Id: main\n    m_Name: \n    m_Url: https://packages.unity.com\n    m_Scopes: []\n    m_IsDefault: 1\n    m_Capabilities: 7\n    m_ConfigSource: 0\n    m_Compliance:\n      m_Status: 0\n      m_Violations: []\n  - m_Id: scoped:project:Keijiro\n    m_Name: Keijiro\n    m_Url: https://registry.npmjs.com\n    m_Scopes:\n    - jp.keijiro\n    m_IsDefault: 0\n    m_Capabilities: 0\n    m_ConfigSource: 4\n    m_Compliance:\n      m_Status: 0\n      m_Violations: []\n  m_UserSelectedRegistryName: Keijiro\n  m_UserAddingNewScopedRegistry: 0\n  m_RegistryInfoDraft:\n    m_Modified: 0\n    m_ErrorMessage: \n    m_UserModificationsInstanceId: -894\n    m_OriginalInstanceId: -896\n  m_LoadAssets: 0\n"
  },
  {
    "path": "ProjectSettings/Packages/com.unity.dedicated-server/MultiplayerRolesSettings.asset",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!114 &1\nMonoBehaviour:\n  m_ObjectHideFlags: 53\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 0}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 15023, guid: 0000000000000000e000000000000000, type: 0}\n  m_Name: \n  m_EditorClassIdentifier: UnityEditor.MultiplayerModule.dll::UnityEditor.Multiplayer.Internal.MultiplayerRolesSettings\n  m_MultiplayerRoleForClassicProfile:\n    m_Keys: []\n    m_Values: \n"
  },
  {
    "path": "ProjectSettings/Physics2DSettings.asset",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!19 &1\nPhysics2DSettings:\n  m_ObjectHideFlags: 0\n  serializedVersion: 11\n  m_Gravity: {x: 0, y: -9.81}\n  m_DefaultMaterial: {fileID: 0}\n  m_VelocityIterations: 8\n  m_PositionIterations: 3\n  m_BounceThreshold: 1\n  m_MaxLinearCorrection: 0.2\n  m_MaxAngularCorrection: 8\n  m_MaxTranslationSpeed: 100\n  m_MaxRotationSpeed: 360\n  m_BaumgarteScale: 0.2\n  m_BaumgarteTimeOfImpactScale: 0.75\n  m_TimeToSleep: 0.5\n  m_LinearSleepTolerance: 0.01\n  m_AngularSleepTolerance: 2\n  m_DefaultContactOffset: 0.01\n  m_ContactThreshold: 0\n  m_JobOptions:\n    serializedVersion: 2\n    useMultithreading: 0\n    useConsistencySorting: 0\n    m_InterpolationPosesPerJob: 100\n    m_NewContactsPerJob: 30\n    m_CollideContactsPerJob: 100\n    m_ClearFlagsPerJob: 200\n    m_ClearBodyForcesPerJob: 200\n    m_SyncDiscreteFixturesPerJob: 50\n    m_SyncContinuousFixturesPerJob: 50\n    m_FindNearestContactsPerJob: 100\n    m_UpdateTriggerContactsPerJob: 100\n    m_IslandSolverCostThreshold: 100\n    m_IslandSolverBodyCostScale: 1\n    m_IslandSolverContactCostScale: 10\n    m_IslandSolverJointCostScale: 10\n    m_IslandSolverBodiesPerJob: 50\n    m_IslandSolverContactsPerJob: 50\n  m_SimulationMode: 0\n  m_SimulationLayers:\n    serializedVersion: 2\n    m_Bits: 4294967295\n  m_MaxSubStepCount: 4\n  m_MinSubStepFPS: 30\n  m_UseSubStepping: 0\n  m_UseSubStepContacts: 0\n  m_QueriesHitTriggers: 1\n  m_QueriesStartInColliders: 1\n  m_CallbacksOnDisable: 1\n  m_ReuseCollisionCallbacks: 1\n  m_AutoSyncTransforms: 0\n  m_GizmoOptions: 10\n  m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n  m_PhysicsLowLevelSettings: {fileID: 0}\n"
  },
  {
    "path": "ProjectSettings/PresetManager.asset",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!1386491679 &1\nPresetManager:\n  m_ObjectHideFlags: 0\n  serializedVersion: 2\n  m_DefaultPresets: {}\n"
  },
  {
    "path": "ProjectSettings/ProjectSettings.asset",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!129 &1\nPlayerSettings:\n  m_ObjectHideFlags: 0\n  serializedVersion: 28\n  productGUID: 912d5b78b8f784c9187b110aa6c731a2\n  AndroidProfiler: 0\n  AndroidFilterTouchesWhenObscured: 0\n  AndroidEnableSustainedPerformanceMode: 0\n  defaultScreenOrientation: 4\n  targetDevice: 2\n  useOnDemandResources: 0\n  accelerometerFrequency: 60\n  companyName: Keijiro\n  productName: KlakHap\n  defaultCursor: {fileID: 0}\n  cursorHotspot: {x: 0, y: 0}\n  m_SplashScreenBackgroundColor: {r: 0.12156863, g: 0.12156863, b: 0.1254902, a: 1}\n  m_ShowUnitySplashScreen: 0\n  m_ShowUnitySplashLogo: 1\n  m_SplashScreenOverlayOpacity: 1\n  m_SplashScreenAnimation: 1\n  m_SplashScreenLogoStyle: 1\n  m_SplashScreenDrawMode: 0\n  m_SplashScreenBackgroundAnimationZoom: 1\n  m_SplashScreenLogoAnimationZoom: 1\n  m_SplashScreenBackgroundLandscapeAspect: 1\n  m_SplashScreenBackgroundPortraitAspect: 1\n  m_SplashScreenBackgroundLandscapeUvs:\n    serializedVersion: 2\n    x: 0\n    y: 0\n    width: 1\n    height: 1\n  m_SplashScreenBackgroundPortraitUvs:\n    serializedVersion: 2\n    x: 0\n    y: 0\n    width: 1\n    height: 1\n  m_SplashScreenLogos: []\n  m_VirtualRealitySplashScreen: {fileID: 0}\n  m_HolographicTrackingLossScreen: {fileID: 0}\n  defaultScreenWidth: 1920\n  defaultScreenHeight: 1080\n  defaultScreenWidthWeb: 960\n  defaultScreenHeightWeb: 600\n  m_StereoRenderingPath: 0\n  m_ActiveColorSpace: 1\n  unsupportedMSAAFallback: 0\n  m_SpriteBatchMaxVertexCount: 65535\n  m_SpriteBatchVertexThreshold: 300\n  m_MTRendering: 1\n  mipStripping: 0\n  numberOfMipsStripped: 0\n  numberOfMipsStrippedPerMipmapLimitGroup: {}\n  m_StackTraceTypes: 010000000100000001000000010000000100000001000000\n  iosShowActivityIndicatorOnLoading: -1\n  androidShowActivityIndicatorOnLoading: -1\n  iosUseCustomAppBackgroundBehavior: 0\n  allowedAutorotateToPortrait: 1\n  allowedAutorotateToPortraitUpsideDown: 1\n  allowedAutorotateToLandscapeRight: 1\n  allowedAutorotateToLandscapeLeft: 1\n  useOSAutorotation: 1\n  use32BitDisplayBuffer: 1\n  preserveFramebufferAlpha: 0\n  disableDepthAndStencilBuffers: 0\n  androidStartInFullscreen: 1\n  androidRenderOutsideSafeArea: 1\n  androidUseSwappy: 1\n  androidDisplayOptions: 1\n  androidBlitType: 0\n  androidResizeableActivity: 1\n  androidDefaultWindowWidth: 1920\n  androidDefaultWindowHeight: 1080\n  androidMinimumWindowWidth: 400\n  androidMinimumWindowHeight: 300\n  androidFullscreenMode: 1\n  androidAutoRotationBehavior: 1\n  androidPredictiveBackSupport: 1\n  androidApplicationEntry: 2\n  defaultIsNativeResolution: 1\n  macRetinaSupport: 1\n  runInBackground: 1\n  muteOtherAudioSources: 0\n  Prepare IOS For Recording: 0\n  Force IOS Speakers When Recording: 0\n  audioSpatialExperience: 0\n  deferSystemGesturesMode: 0\n  hideHomeButton: 0\n  submitAnalytics: 1\n  usePlayerLog: 1\n  dedicatedServerOptimizations: 1\n  bakeCollisionMeshes: 0\n  forceSingleInstance: 0\n  useFlipModelSwapchain: 1\n  resizableWindow: 0\n  useMacAppStoreValidation: 0\n  macAppStoreCategory: public.app-category.games\n  gpuSkinning: 0\n  meshDeformation: 0\n  xboxPIXTextureCapture: 0\n  xboxEnableAvatar: 0\n  xboxEnableKinect: 0\n  xboxEnableKinectAutoTracking: 0\n  xboxEnableFitness: 0\n  visibleInBackground: 1\n  allowFullscreenSwitch: 1\n  fullscreenMode: 3\n  xboxSpeechDB: 0\n  xboxEnableHeadOrientation: 0\n  xboxEnableGuest: 0\n  xboxEnablePIXSampling: 0\n  metalFramebufferOnly: 0\n  xboxOneResolution: 0\n  xboxOneSResolution: 0\n  xboxOneXResolution: 3\n  xboxOneMonoLoggingLevel: 0\n  xboxOneLoggingLevel: 1\n  xboxOneDisableEsram: 0\n  xboxOneEnableTypeOptimization: 0\n  xboxOnePresentImmediateThreshold: 0\n  switchQueueCommandMemory: 1048576\n  switchQueueControlMemory: 16384\n  switchQueueComputeMemory: 262144\n  switchNVNShaderPoolsGranularity: 33554432\n  switchNVNDefaultPoolsGranularity: 16777216\n  switchNVNOtherPoolsGranularity: 16777216\n  switchGpuScratchPoolGranularity: 2097152\n  switchAllowGpuScratchShrinking: 0\n  switchNVNMaxPublicTextureIDCount: 0\n  switchNVNMaxPublicSamplerIDCount: 0\n  switchMaxWorkerMultiple: 8\n  switchNVNGraphicsFirmwareMemory: 32\n  switchGraphicsJobsSyncAfterKick: 1\n  vulkanNumSwapchainBuffers: 3\n  vulkanEnableSetSRGBWrite: 0\n  vulkanEnablePreTransform: 0\n  vulkanEnableLateAcquireNextImage: 0\n  vulkanEnableCommandBufferRecycling: 1\n  loadStoreDebugModeEnabled: 0\n  visionOSBundleVersion: 1.0\n  tvOSBundleVersion: 1.0\n  bundleVersion: 1.0\n  preloadedAssets: []\n  metroInputSource: 0\n  wsaTransparentSwapchain: 0\n  m_HolographicPauseOnTrackingLoss: 1\n  xboxOneDisableKinectGpuReservation: 1\n  xboxOneEnable7thCore: 1\n  vrSettings:\n    enable360StereoCapture: 0\n  isWsaHolographicRemotingEnabled: 0\n  enableFrameTimingStats: 0\n  enableOpenGLProfilerGPURecorders: 1\n  allowHDRDisplaySupport: 0\n  useHDRDisplay: 0\n  hdrBitDepth: 0\n  m_ColorGamuts: 00000000\n  targetPixelDensity: 30\n  resolutionScalingMode: 0\n  resetResolutionOnWindowResize: 0\n  androidSupportedAspectRatio: 1\n  androidMaxAspectRatio: 2.4\n  androidMinAspectRatio: 1\n  applicationIdentifier:\n    Standalone: com.Keijiro.KlakHap\n  buildNumber:\n    Standalone: 0\n    VisionOS: 0\n    iPhone: 0\n    tvOS: 0\n  overrideDefaultApplicationIdentifier: 0\n  AndroidBundleVersionCode: 1\n  AndroidMinSdkVersion: 25\n  AndroidTargetSdkVersion: 0\n  AndroidPreferredInstallLocation: 1\n  AndroidPreferredDataLocation: 1\n  aotOptions: \n  stripEngineCode: 1\n  iPhoneStrippingLevel: 0\n  iPhoneScriptCallOptimization: 0\n  ForceInternetPermission: 0\n  ForceSDCardPermission: 0\n  CreateWallpaper: 0\n  androidSplitApplicationBinary: 0\n  keepLoadedShadersAlive: 0\n  StripUnusedMeshComponents: 0\n  strictShaderVariantMatching: 0\n  VertexChannelCompressionMask: 4054\n  iPhoneSdkVersion: 988\n  iOSSimulatorArchitecture: 0\n  iOSTargetOSVersionString: 15.0\n  tvOSSdkVersion: 0\n  tvOSSimulatorArchitecture: 0\n  tvOSRequireExtendedGameController: 0\n  tvOSTargetOSVersionString: 15.0\n  VisionOSSdkVersion: 0\n  VisionOSTargetOSVersionString: 1.0\n  uIPrerenderedIcon: 0\n  uIRequiresPersistentWiFi: 0\n  uIRequiresFullScreen: 1\n  uIStatusBarHidden: 1\n  uIExitOnSuspend: 0\n  uIStatusBarStyle: 0\n  appleTVSplashScreen: {fileID: 0}\n  appleTVSplashScreen2x: {fileID: 0}\n  tvOSSmallIconLayers: []\n  tvOSSmallIconLayers2x: []\n  tvOSLargeIconLayers: []\n  tvOSLargeIconLayers2x: []\n  tvOSTopShelfImageLayers: []\n  tvOSTopShelfImageLayers2x: []\n  tvOSTopShelfImageWideLayers: []\n  tvOSTopShelfImageWideLayers2x: []\n  iOSLaunchScreenType: 0\n  iOSLaunchScreenPortrait: {fileID: 0}\n  iOSLaunchScreenLandscape: {fileID: 0}\n  iOSLaunchScreenBackgroundColor:\n    serializedVersion: 2\n    rgba: 0\n  iOSLaunchScreenFillPct: 100\n  iOSLaunchScreenSize: 100\n  iOSLaunchScreeniPadType: 0\n  iOSLaunchScreeniPadImage: {fileID: 0}\n  iOSLaunchScreeniPadBackgroundColor:\n    serializedVersion: 2\n    rgba: 0\n  iOSLaunchScreeniPadFillPct: 100\n  iOSLaunchScreeniPadSize: 100\n  iOSLaunchScreenCustomStoryboardPath: \n  iOSLaunchScreeniPadCustomStoryboardPath: \n  iOSDeviceRequirements: []\n  iOSURLSchemes: []\n  macOSURLSchemes: []\n  iOSBackgroundModes: 0\n  iOSMetalForceHardShadows: 0\n  metalEditorSupport: 1\n  metalAPIValidation: 1\n  metalCompileShaderBinary: 0\n  iOSRenderExtraFrameOnPause: 0\n  iosCopyPluginsCodeInsteadOfSymlink: 0\n  appleDeveloperTeamID: \n  iOSManualSigningProvisioningProfileID: \n  tvOSManualSigningProvisioningProfileID: \n  VisionOSManualSigningProvisioningProfileID: \n  iOSManualSigningProvisioningProfileType: 0\n  tvOSManualSigningProvisioningProfileType: 0\n  VisionOSManualSigningProvisioningProfileType: 0\n  appleEnableAutomaticSigning: 0\n  iOSRequireARKit: 0\n  iOSAutomaticallyDetectAndAddCapabilities: 1\n  appleEnableProMotion: 0\n  shaderPrecisionModel: 0\n  clonedFromGUID: 00000000000000000000000000000000\n  templatePackageId: \n  templateDefaultScene: \n  useCustomMainManifest: 0\n  useCustomLauncherManifest: 0\n  useCustomMainGradleTemplate: 0\n  useCustomLauncherGradleManifest: 0\n  useCustomBaseGradleTemplate: 0\n  useCustomGradlePropertiesTemplate: 0\n  useCustomGradleSettingsTemplate: 0\n  useCustomProguardFile: 0\n  AndroidTargetArchitectures: 2\n  AndroidAllowedArchitectures: -1\n  AndroidSplashScreenScale: 0\n  androidSplashScreen: {fileID: 0}\n  AndroidKeystoreName: \n  AndroidKeyaliasName: \n  AndroidEnableArmv9SecurityFeatures: 0\n  AndroidEnableArm64MTE: 0\n  AndroidBuildApkPerCpuArchitecture: 0\n  AndroidTVCompatibility: 0\n  AndroidIsGame: 1\n  androidAppCategory: 3\n  useAndroidAppCategory: 1\n  androidAppCategoryOther: \n  AndroidEnableTango: 0\n  androidEnableBanner: 1\n  androidUseLowAccuracyLocation: 0\n  androidUseCustomKeystore: 0\n  m_AndroidBanners:\n  - width: 320\n    height: 180\n    banner: {fileID: 0}\n  androidGamepadSupportLevel: 0\n  AndroidMinifyRelease: 0\n  AndroidMinifyDebug: 0\n  AndroidValidateAppBundleSize: 1\n  AndroidAppBundleSizeToValidate: 200\n  AndroidReportGooglePlayAppDependencies: 1\n  androidSymbolsSizeThreshold: 800\n  m_BuildTargetIcons: []\n  m_BuildTargetPlatformIcons:\n  - m_BuildTarget: Android\n    m_Icons:\n    - m_Textures: []\n      m_Width: 432\n      m_Height: 432\n      m_Kind: 2\n      m_SubKind: \n    - m_Textures: []\n      m_Width: 324\n      m_Height: 324\n      m_Kind: 2\n      m_SubKind: \n    - m_Textures: []\n      m_Width: 216\n      m_Height: 216\n      m_Kind: 2\n      m_SubKind: \n    - m_Textures: []\n      m_Width: 162\n      m_Height: 162\n      m_Kind: 2\n      m_SubKind: \n    - m_Textures: []\n      m_Width: 108\n      m_Height: 108\n      m_Kind: 2\n      m_SubKind: \n    - m_Textures: []\n      m_Width: 81\n      m_Height: 81\n      m_Kind: 2\n      m_SubKind: \n    - m_Textures: []\n      m_Width: 192\n      m_Height: 192\n      m_Kind: 1\n      m_SubKind: \n    - m_Textures: []\n      m_Width: 144\n      m_Height: 144\n      m_Kind: 1\n      m_SubKind: \n    - m_Textures: []\n      m_Width: 96\n      m_Height: 96\n      m_Kind: 1\n      m_SubKind: \n    - m_Textures: []\n      m_Width: 72\n      m_Height: 72\n      m_Kind: 1\n      m_SubKind: \n    - m_Textures: []\n      m_Width: 48\n      m_Height: 48\n      m_Kind: 1\n      m_SubKind: \n    - m_Textures: []\n      m_Width: 36\n      m_Height: 36\n      m_Kind: 1\n      m_SubKind: \n    - m_Textures: []\n      m_Width: 192\n      m_Height: 192\n      m_Kind: 0\n      m_SubKind: \n    - m_Textures: []\n      m_Width: 144\n      m_Height: 144\n      m_Kind: 0\n      m_SubKind: \n    - m_Textures: []\n      m_Width: 96\n      m_Height: 96\n      m_Kind: 0\n      m_SubKind: \n    - m_Textures: []\n      m_Width: 72\n      m_Height: 72\n      m_Kind: 0\n      m_SubKind: \n    - m_Textures: []\n      m_Width: 48\n      m_Height: 48\n      m_Kind: 0\n      m_SubKind: \n    - m_Textures: []\n      m_Width: 36\n      m_Height: 36\n      m_Kind: 0\n      m_SubKind: \n  m_BuildTargetBatching: []\n  m_BuildTargetShaderSettings: []\n  m_BuildTargetGraphicsJobs: []\n  m_BuildTargetGraphicsJobMode: []\n  m_BuildTargetGraphicsAPIs: []\n  m_BuildTargetVRSettings: []\n  m_DefaultShaderChunkSizeInMB: 16\n  m_DefaultShaderChunkCount: 0\n  openGLRequireES31: 0\n  openGLRequireES31AEP: 0\n  openGLRequireES32: 0\n  m_TemplateCustomTags: {}\n  mobileMTRendering:\n    Android: 1\n    VisionOS: 1\n    iPhone: 1\n    tvOS: 1\n  m_BuildTargetGroupLightmapEncodingQuality: []\n  m_BuildTargetGroupHDRCubemapEncodingQuality: []\n  m_BuildTargetGroupLightmapSettings: []\n  m_BuildTargetGroupLoadStoreDebugModeSettings: []\n  m_BuildTargetNormalMapEncoding: []\n  m_BuildTargetDefaultTextureCompressionFormat: []\n  playModeTestRunnerEnabled: 0\n  runPlayModeTestAsEditModeTest: 0\n  actionOnDotNetUnhandledException: 1\n  editorGfxJobOverride: 1\n  enableInternalProfiler: 0\n  logObjCUncaughtExceptions: 1\n  enableCrashReportAPI: 0\n  cameraUsageDescription: \n  locationUsageDescription: \n  microphoneUsageDescription: \n  bluetoothUsageDescription: \n  macOSTargetOSVersion: 12.0\n  switchNMETAOverride: \n  switchNetLibKey: \n  switchSocketMemoryPoolSize: 6144\n  switchSocketAllocatorPoolSize: 128\n  switchSocketConcurrencyLimit: 14\n  switchScreenResolutionBehavior: 2\n  switchUseCPUProfiler: 0\n  switchEnableFileSystemTrace: 0\n  switchLTOSetting: 0\n  switchApplicationID: 0x01004b9000490000\n  switchNSODependencies: \n  switchCompilerFlags: \n  switchTitleNames_0: \n  switchTitleNames_1: \n  switchTitleNames_2: \n  switchTitleNames_3: \n  switchTitleNames_4: \n  switchTitleNames_5: \n  switchTitleNames_6: \n  switchTitleNames_7: \n  switchTitleNames_8: \n  switchTitleNames_9: \n  switchTitleNames_10: \n  switchTitleNames_11: \n  switchTitleNames_12: \n  switchTitleNames_13: \n  switchTitleNames_14: \n  switchTitleNames_15: \n  switchPublisherNames_0: \n  switchPublisherNames_1: \n  switchPublisherNames_2: \n  switchPublisherNames_3: \n  switchPublisherNames_4: \n  switchPublisherNames_5: \n  switchPublisherNames_6: \n  switchPublisherNames_7: \n  switchPublisherNames_8: \n  switchPublisherNames_9: \n  switchPublisherNames_10: \n  switchPublisherNames_11: \n  switchPublisherNames_12: \n  switchPublisherNames_13: \n  switchPublisherNames_14: \n  switchPublisherNames_15: \n  switchIcons_0: {fileID: 0}\n  switchIcons_1: {fileID: 0}\n  switchIcons_2: {fileID: 0}\n  switchIcons_3: {fileID: 0}\n  switchIcons_4: {fileID: 0}\n  switchIcons_5: {fileID: 0}\n  switchIcons_6: {fileID: 0}\n  switchIcons_7: {fileID: 0}\n  switchIcons_8: {fileID: 0}\n  switchIcons_9: {fileID: 0}\n  switchIcons_10: {fileID: 0}\n  switchIcons_11: {fileID: 0}\n  switchIcons_12: {fileID: 0}\n  switchIcons_13: {fileID: 0}\n  switchIcons_14: {fileID: 0}\n  switchIcons_15: {fileID: 0}\n  switchSmallIcons_0: {fileID: 0}\n  switchSmallIcons_1: {fileID: 0}\n  switchSmallIcons_2: {fileID: 0}\n  switchSmallIcons_3: {fileID: 0}\n  switchSmallIcons_4: {fileID: 0}\n  switchSmallIcons_5: {fileID: 0}\n  switchSmallIcons_6: {fileID: 0}\n  switchSmallIcons_7: {fileID: 0}\n  switchSmallIcons_8: {fileID: 0}\n  switchSmallIcons_9: {fileID: 0}\n  switchSmallIcons_10: {fileID: 0}\n  switchSmallIcons_11: {fileID: 0}\n  switchSmallIcons_12: {fileID: 0}\n  switchSmallIcons_13: {fileID: 0}\n  switchSmallIcons_14: {fileID: 0}\n  switchSmallIcons_15: {fileID: 0}\n  switchManualHTML: \n  switchAccessibleURLs: \n  switchLegalInformation: \n  switchMainThreadStackSize: 1048576\n  switchPresenceGroupId: \n  switchLogoHandling: 0\n  switchReleaseVersion: 0\n  switchDisplayVersion: 1.0.0\n  switchStartupUserAccount: 0\n  switchSupportedLanguagesMask: 0\n  switchLogoType: 0\n  switchApplicationErrorCodeCategory: \n  switchUserAccountSaveDataSize: 0\n  switchUserAccountSaveDataJournalSize: 0\n  switchApplicationAttribute: 0\n  switchCardSpecSize: -1\n  switchCardSpecClock: -1\n  switchRatingsMask: 0\n  switchRatingsInt_0: 0\n  switchRatingsInt_1: 0\n  switchRatingsInt_2: 0\n  switchRatingsInt_3: 0\n  switchRatingsInt_4: 0\n  switchRatingsInt_5: 0\n  switchRatingsInt_6: 0\n  switchRatingsInt_7: 0\n  switchRatingsInt_8: 0\n  switchRatingsInt_9: 0\n  switchRatingsInt_10: 0\n  switchRatingsInt_11: 0\n  switchRatingsInt_12: 0\n  switchLocalCommunicationIds_0: \n  switchLocalCommunicationIds_1: \n  switchLocalCommunicationIds_2: \n  switchLocalCommunicationIds_3: \n  switchLocalCommunicationIds_4: \n  switchLocalCommunicationIds_5: \n  switchLocalCommunicationIds_6: \n  switchLocalCommunicationIds_7: \n  switchParentalControl: 0\n  switchAllowsScreenshot: 1\n  switchAllowsVideoCapturing: 1\n  switchAllowsRuntimeAddOnContentInstall: 0\n  switchDataLossConfirmation: 0\n  switchUserAccountLockEnabled: 0\n  switchSystemResourceMemory: 16777216\n  switchSupportedNpadStyles: 22\n  switchNativeFsCacheSize: 32\n  switchIsHoldTypeHorizontal: 1\n  switchSupportedNpadCount: 8\n  switchEnableTouchScreen: 1\n  switchSocketConfigEnabled: 0\n  switchTcpInitialSendBufferSize: 32\n  switchTcpInitialReceiveBufferSize: 64\n  switchTcpAutoSendBufferSizeMax: 256\n  switchTcpAutoReceiveBufferSizeMax: 256\n  switchUdpSendBufferSize: 9\n  switchUdpReceiveBufferSize: 42\n  switchSocketBufferEfficiency: 4\n  switchSocketInitializeEnabled: 1\n  switchNetworkInterfaceManagerInitializeEnabled: 1\n  switchDisableHTCSPlayerConnection: 0\n  switchUseNewStyleFilepaths: 1\n  switchUseLegacyFmodPriorities: 0\n  switchUseMicroSleepForYield: 1\n  switchEnableRamDiskSupport: 0\n  switchMicroSleepForYieldTime: 25\n  switchRamDiskSpaceSize: 12\n  switchUpgradedPlayerSettingsToNMETA: 0\n  ps4NPAgeRating: 12\n  ps4NPTitleSecret: \n  ps4NPTrophyPackPath: \n  ps4ParentalLevel: 11\n  ps4ContentID: ED1633-NPXX51362_00-0000000000000000\n  ps4Category: 0\n  ps4MasterVersion: 01.00\n  ps4AppVersion: 01.00\n  ps4AppType: 0\n  ps4ParamSfxPath: \n  ps4VideoOutPixelFormat: 0\n  ps4VideoOutInitialWidth: 1920\n  ps4VideoOutBaseModeInitialWidth: 1920\n  ps4VideoOutReprojectionRate: 60\n  ps4PronunciationXMLPath: \n  ps4PronunciationSIGPath: \n  ps4BackgroundImagePath: \n  ps4StartupImagePath: \n  ps4StartupImagesFolder: \n  ps4IconImagesFolder: \n  ps4SaveDataImagePath: \n  ps4SdkOverride: \n  ps4BGMPath: \n  ps4ShareFilePath: \n  ps4ShareOverlayImagePath: \n  ps4PrivacyGuardImagePath: \n  ps4ExtraSceSysFile: \n  ps4NPtitleDatPath: \n  ps4RemotePlayKeyAssignment: -1\n  ps4RemotePlayKeyMappingDir: \n  ps4PlayTogetherPlayerCount: 0\n  ps4EnterButtonAssignment: 2\n  ps4ApplicationParam1: 0\n  ps4ApplicationParam2: 0\n  ps4ApplicationParam3: 0\n  ps4ApplicationParam4: 0\n  ps4DownloadDataSize: 0\n  ps4GarlicHeapSize: 2048\n  ps4ProGarlicHeapSize: 2560\n  playerPrefsMaxSize: 32768\n  ps4Passcode: jx5SBNX6qZpkMcX5Y7A9NxEsBwNSYYCK\n  ps4pnSessions: 1\n  ps4pnPresence: 1\n  ps4pnFriends: 1\n  ps4pnGameCustomData: 1\n  playerPrefsSupport: 0\n  enableApplicationExit: 0\n  resetTempFolder: 1\n  restrictedAudioUsageRights: 0\n  ps4UseResolutionFallback: 0\n  ps4ReprojectionSupport: 0\n  ps4UseAudio3dBackend: 0\n  ps4UseLowGarlicFragmentationMode: 1\n  ps4SocialScreenEnabled: 0\n  ps4ScriptOptimizationLevel: 2\n  ps4Audio3dVirtualSpeakerCount: 14\n  ps4attribCpuUsage: 0\n  ps4PatchPkgPath: \n  ps4PatchLatestPkgPath: \n  ps4PatchChangeinfoPath: \n  ps4PatchDayOne: 0\n  ps4attribUserManagement: 0\n  ps4attribMoveSupport: 0\n  ps4attrib3DSupport: 0\n  ps4attribShareSupport: 0\n  ps4attribExclusiveVR: 0\n  ps4disableAutoHideSplash: 0\n  ps4videoRecordingFeaturesUsed: 0\n  ps4contentSearchFeaturesUsed: 0\n  ps4CompatibilityPS5: 0\n  ps4AllowPS5Detection: 0\n  ps4GPU800MHz: 1\n  ps4attribEyeToEyeDistanceSettingVR: 0\n  ps4IncludedModules: []\n  ps4attribVROutputEnabled: 0\n  monoEnv: \n  splashScreenBackgroundSourceLandscape: {fileID: 0}\n  splashScreenBackgroundSourcePortrait: {fileID: 0}\n  blurSplashScreenBackground: 1\n  spritePackerPolicy: \n  webGLMemorySize: 32\n  webGLExceptionSupport: 1\n  webGLNameFilesAsHashes: 0\n  webGLShowDiagnostics: 0\n  webGLDataCaching: 1\n  webGLDebugSymbols: 0\n  webGLEmscriptenArgs: \n  webGLModulesDirectory: \n  webGLTemplate: APPLICATION:Default\n  webGLAnalyzeBuildSize: 0\n  webGLUseEmbeddedResources: 0\n  webGLCompressionFormat: 1\n  webGLWasmArithmeticExceptions: 0\n  webGLLinkerTarget: 1\n  webGLThreadsSupport: 0\n  webGLDecompressionFallback: 0\n  webGLInitialMemorySize: 32\n  webGLMaximumMemorySize: 2048\n  webGLMemoryGrowthMode: 2\n  webGLMemoryLinearGrowthStep: 16\n  webGLMemoryGeometricGrowthStep: 0.2\n  webGLMemoryGeometricGrowthCap: 96\n  webGLPowerPreference: 2\n  webGLWebAssemblyTable: 0\n  webGLWebAssemblyBigInt: 0\n  webGLCloseOnQuit: 0\n  webWasm2023: 0\n  webEnableSubmoduleStrippingCompatibility: 0\n  scriptingDefineSymbols: {}\n  additionalCompilerArguments: {}\n  platformArchitecture: {}\n  scriptingBackend: {}\n  il2cppCompilerConfiguration: {}\n  il2cppCodeGeneration: {}\n  il2cppStacktraceInformation: {}\n  managedStrippingLevel: {}\n  incrementalIl2cppBuild: {}\n  suppressCommonWarnings: 0\n  allowUnsafeCode: 0\n  useDeterministicCompilation: 1\n  additionalIl2CppArgs: \n  scriptingRuntimeVersion: 1\n  gcIncremental: 1\n  gcWBarrierValidation: 0\n  apiCompatibilityLevelPerPlatform: {}\n  editorAssembliesCompatibilityLevel: 1\n  m_RenderingPath: 1\n  m_MobileRenderingPath: 1\n  metroPackageName: KlakHap\n  metroPackageVersion: \n  metroCertificatePath: \n  metroCertificatePassword: \n  metroCertificateSubject: \n  metroCertificateIssuer: \n  metroCertificateNotAfter: 0000000000000000\n  metroApplicationDescription: KlakHap\n  wsaImages: {}\n  metroTileShortName: \n  metroTileShowName: 0\n  metroMediumTileShowName: 0\n  metroLargeTileShowName: 0\n  metroWideTileShowName: 0\n  metroSupportStreamingInstall: 0\n  metroLastRequiredScene: 0\n  metroDefaultTileSize: 1\n  metroTileForegroundText: 2\n  metroTileBackgroundColor: {r: 0.13333334, g: 0.17254902, b: 0.21568628, a: 0}\n  metroSplashScreenBackgroundColor: {r: 0.12941177, g: 0.17254902, b: 0.21568628, a: 1}\n  metroSplashScreenUseBackgroundColor: 0\n  syncCapabilities: 0\n  platformCapabilities: {}\n  metroTargetDeviceFamilies: {}\n  metroFTAName: \n  metroFTAFileTypes: []\n  metroProtocolName: \n  vcxProjDefaultLanguage: \n  XboxOneProductId: \n  XboxOneUpdateKey: \n  XboxOneSandboxId: \n  XboxOneContentId: \n  XboxOneTitleId: \n  XboxOneSCId: \n  XboxOneGameOsOverridePath: \n  XboxOnePackagingOverridePath: \n  XboxOneAppManifestOverridePath: \n  XboxOneVersion: 1.0.0.0\n  XboxOnePackageEncryption: 0\n  XboxOnePackageUpdateGranularity: 2\n  XboxOneDescription: \n  XboxOneLanguage:\n  - enus\n  XboxOneCapability: []\n  XboxOneGameRating: {}\n  XboxOneIsContentPackage: 0\n  XboxOneEnhancedXboxCompatibilityMode: 0\n  XboxOneEnableGPUVariability: 1\n  XboxOneSockets: {}\n  XboxOneSplashScreen: {fileID: 0}\n  XboxOneAllowedProductIds: []\n  XboxOnePersistentLocalStorageSize: 0\n  XboxOneXTitleMemory: 8\n  XboxOneOverrideIdentityName: \n  XboxOneOverrideIdentityPublisher: \n  vrEditorSettings: {}\n  cloudServicesEnabled: {}\n  luminIcon:\n    m_Name: \n    m_ModelFolderPath: \n    m_PortalFolderPath: \n  luminCert:\n    m_CertPath: \n    m_SignPackage: 1\n  luminIsChannelApp: 0\n  luminVersion:\n    m_VersionCode: 1\n    m_VersionName: \n  hmiPlayerDataPath: \n  hmiForceSRGBBlit: 0\n  embeddedLinuxEnableGamepadInput: 0\n  hmiCpuConfiguration: \n  hmiLogStartupTiming: 0\n  qnxGraphicConfPath: \n  apiCompatibilityLevel: 6\n  captureStartupLogs: {}\n  activeInputHandler: 1\n  windowsGamepadBackendHint: 0\n  cloudProjectId: \n  framebufferDepthMemorylessMode: 0\n  qualitySettingsNames: []\n  projectName: \n  organizationId: \n  cloudEnabled: 0\n  legacyClampBlendShapeWeights: 0\n  hmiLoadingImage: {fileID: 0}\n  platformRequiresReadableAssets: 0\n  virtualTexturingSupportEnabled: 0\n  insecureHttpOption: 0\n  androidVulkanDenyFilterList: []\n  androidVulkanAllowFilterList: []\n  androidVulkanDeviceFilterListAsset: {fileID: 0}\n  d3d12DeviceFilterListAsset: {fileID: 0}\n  allowedHttpConnections: 3\n"
  },
  {
    "path": "ProjectSettings/ProjectVersion.txt",
    "content": "m_EditorVersion: 6000.3.6f1\nm_EditorVersionWithRevision: 6000.3.6f1 (bbb010bdb8a3)\n"
  },
  {
    "path": "ProjectSettings/QualitySettings.asset",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!47 &1\nQualitySettings:\n  m_ObjectHideFlags: 0\n  serializedVersion: 5\n  m_CurrentQuality: 0\n  m_QualitySettings:\n  - serializedVersion: 5\n    name: High\n    pixelLightCount: 2\n    shadows: 2\n    shadowResolution: 1\n    shadowProjection: 1\n    shadowCascades: 2\n    shadowDistance: 40\n    shadowNearPlaneOffset: 3\n    shadowCascade2Split: 0.33333334\n    shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}\n    shadowmaskMode: 1\n    skinWeights: 2\n    globalTextureMipmapLimit: 0\n    textureMipmapLimitSettings: []\n    anisotropicTextures: 1\n    antiAliasing: 0\n    softParticles: 0\n    softVegetation: 1\n    realtimeReflectionProbes: 1\n    billboardsFaceCameraPosition: 1\n    useLegacyDetailDistribution: 0\n    adaptiveVsync: 0\n    vSyncCount: 1\n    realtimeGICPUUsage: 50\n    adaptiveVsyncExtraA: 0\n    adaptiveVsyncExtraB: 0\n    lodBias: 1\n    meshLodThreshold: 1\n    maximumLODLevel: 0\n    enableLODCrossFade: 1\n    streamingMipmapsActive: 0\n    streamingMipmapsAddAllCameras: 1\n    streamingMipmapsMemoryBudget: 512\n    streamingMipmapsRenderersPerFrame: 512\n    streamingMipmapsMaxLevelReduction: 2\n    streamingMipmapsMaxFileIORequests: 1024\n    particleRaycastBudget: 256\n    asyncUploadTimeSlice: 2\n    asyncUploadBufferSize: 16\n    asyncUploadPersistentBuffer: 1\n    resolutionScalingFixedDPIFactor: 1\n    customRenderPipeline: {fileID: 0}\n    terrainQualityOverrides: 0\n    terrainPixelError: 1\n    terrainDetailDensityScale: 1\n    terrainBasemapDistance: 1000\n    terrainDetailDistance: 80\n    terrainTreeDistance: 5000\n    terrainBillboardStart: 50\n    terrainFadeLength: 5\n    terrainMaxTrees: 50\n    excludedTargetPlatforms: []\n  m_TextureMipmapLimitGroupNames: []\n  m_PerPlatformDefaultQuality:\n    Android: 0\n    EmbeddedLinux: 0\n    GameCoreScarlett: 0\n    GameCoreXboxOne: 0\n    Kepler: 0\n    LinuxHeadlessSimulation: 0\n    Nintendo Switch: 0\n    Nintendo Switch 2: 0\n    PS4: 0\n    PS5: 0\n    QNX: 0\n    Server: 0\n    Standalone: 0\n    VisionOS: 0\n    WebGL: 0\n    Windows Store Apps: 0\n    XboxOne: 0\n    iPhone: 0\n    tvOS: 0\n"
  },
  {
    "path": "ProjectSettings/SceneTemplateSettings.json",
    "content": "{\n    \"templatePinStates\": [],\n    \"dependencyTypeInfos\": [\n        {\n            \"userAdded\": false,\n            \"type\": \"UnityEngine.AnimationClip\",\n            \"defaultInstantiationMode\": 0\n        },\n        {\n            \"userAdded\": false,\n            \"type\": \"UnityEditor.Animations.AnimatorController\",\n            \"defaultInstantiationMode\": 0\n        },\n        {\n            \"userAdded\": false,\n            \"type\": \"UnityEngine.AnimatorOverrideController\",\n            \"defaultInstantiationMode\": 0\n        },\n        {\n            \"userAdded\": false,\n            \"type\": \"UnityEditor.Audio.AudioMixerController\",\n            \"defaultInstantiationMode\": 0\n        },\n        {\n            \"userAdded\": false,\n            \"type\": \"UnityEngine.ComputeShader\",\n            \"defaultInstantiationMode\": 1\n        },\n        {\n            \"userAdded\": false,\n            \"type\": \"UnityEngine.Cubemap\",\n            \"defaultInstantiationMode\": 0\n        },\n        {\n            \"userAdded\": false,\n            \"type\": \"UnityEngine.GameObject\",\n            \"defaultInstantiationMode\": 0\n        },\n        {\n            \"userAdded\": false,\n            \"type\": \"UnityEditor.LightingDataAsset\",\n            \"defaultInstantiationMode\": 0\n        },\n        {\n            \"userAdded\": false,\n            \"type\": \"UnityEngine.LightingSettings\",\n            \"defaultInstantiationMode\": 0\n        },\n        {\n            \"userAdded\": false,\n            \"type\": \"UnityEngine.Material\",\n            \"defaultInstantiationMode\": 0\n        },\n        {\n            \"userAdded\": false,\n            \"type\": \"UnityEditor.MonoScript\",\n            \"defaultInstantiationMode\": 1\n        },\n        {\n            \"userAdded\": false,\n            \"type\": \"UnityEngine.PhysicsMaterial\",\n            \"defaultInstantiationMode\": 0\n        },\n        {\n            \"userAdded\": false,\n            \"type\": \"UnityEngine.PhysicsMaterial2D\",\n            \"defaultInstantiationMode\": 0\n        },\n        {\n            \"userAdded\": false,\n            \"type\": \"UnityEngine.Rendering.PostProcessing.PostProcessProfile\",\n            \"defaultInstantiationMode\": 0\n        },\n        {\n            \"userAdded\": false,\n            \"type\": \"UnityEngine.Rendering.PostProcessing.PostProcessResources\",\n            \"defaultInstantiationMode\": 0\n        },\n        {\n            \"userAdded\": false,\n            \"type\": \"UnityEngine.Rendering.VolumeProfile\",\n            \"defaultInstantiationMode\": 0\n        },\n        {\n            \"userAdded\": false,\n            \"type\": \"UnityEditor.SceneAsset\",\n            \"defaultInstantiationMode\": 1\n        },\n        {\n            \"userAdded\": false,\n            \"type\": \"UnityEngine.Shader\",\n            \"defaultInstantiationMode\": 1\n        },\n        {\n            \"userAdded\": false,\n            \"type\": \"UnityEngine.ShaderVariantCollection\",\n            \"defaultInstantiationMode\": 1\n        },\n        {\n            \"userAdded\": false,\n            \"type\": \"UnityEngine.Texture\",\n            \"defaultInstantiationMode\": 0\n        },\n        {\n            \"userAdded\": false,\n            \"type\": \"UnityEngine.Texture2D\",\n            \"defaultInstantiationMode\": 0\n        },\n        {\n            \"userAdded\": false,\n            \"type\": \"UnityEngine.Timeline.TimelineAsset\",\n            \"defaultInstantiationMode\": 0\n        }\n    ],\n    \"defaultDependencyTypeInfo\": {\n        \"userAdded\": false,\n        \"type\": \"<default_scene_template_dependencies>\",\n        \"defaultInstantiationMode\": 1\n    },\n    \"newSceneOverride\": 0\n}"
  },
  {
    "path": "ProjectSettings/ShaderGraphSettings.asset",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!114 &1\nMonoBehaviour:\n  m_ObjectHideFlags: 53\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 0}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: de02f9e1d18f588468e474319d09a723, type: 3}\n  m_Name: \n  m_EditorClassIdentifier: Unity.ShaderGraph.Editor::UnityEditor.ShaderGraph.ShaderGraphProjectSettings\n  shaderVariantLimit: 2048\n  overrideShaderVariantLimit: 0\n  customInterpolatorErrorThreshold: 32\n  customInterpolatorWarningThreshold: 16\n  customHeatmapValues: {fileID: 0}\n"
  },
  {
    "path": "ProjectSettings/TagManager.asset",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!78 &1\nTagManager:\n  serializedVersion: 3\n  tags: []\n  layers:\n  - Default\n  - TransparentFX\n  - Ignore Raycast\n  - \n  - Water\n  - UI\n  - \n  - \n  - \n  - \n  - \n  - \n  - \n  - \n  - \n  - \n  - \n  - \n  - \n  - \n  - \n  - \n  - \n  - \n  - \n  - \n  - \n  - \n  - \n  - \n  - \n  - \n  m_SortingLayers:\n  - name: Default\n    uniqueID: 0\n    locked: 0\n  m_RenderingLayers:\n  - Default\n"
  },
  {
    "path": "ProjectSettings/TimeManager.asset",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!5 &1\nTimeManager:\n  m_ObjectHideFlags: 0\n  serializedVersion: 2\n  Fixed Timestep:\n    m_Count: 2822399\n    m_Rate:\n      m_Denominator: 1\n      m_Numerator: 141120000\n  Maximum Allowed Timestep: 0.33333334\n  m_TimeScale: 1\n  Maximum Particle Timestep: 0.03\n"
  },
  {
    "path": "ProjectSettings/URPProjectSettings.asset",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!114 &1\nMonoBehaviour:\n  m_ObjectHideFlags: 61\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 0}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: 247994e1f5a72c2419c26a37e9334c01, type: 3}\n  m_Name: \n  m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Editor::UnityEditor.Rendering.Universal.UniversalProjectSettings\n  m_LastMaterialVersion: 10\n  m_ProjectSettingFolderPath: URPDefaultResources\n"
  },
  {
    "path": "ProjectSettings/UnityConnectSettings.asset",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!310 &1\nUnityConnectSettings:\n  m_ObjectHideFlags: 0\n  serializedVersion: 1\n  m_Enabled: 0\n  m_TestMode: 0\n  m_EventOldUrl: https://api.uca.cloud.unity3d.com/v1/events\n  m_EventUrl: https://cdp.cloud.unity3d.com/v1/events\n  m_ConfigUrl: https://config.uca.cloud.unity3d.com\n  m_DashboardUrl: https://dashboard.unity3d.com\n  m_TestInitMode: 0\n  InsightsSettings:\n    m_EngineDiagnosticsEnabled: 0\n    m_Enabled: 0\n  CrashReportingSettings:\n    serializedVersion: 2\n    m_EventUrl: https://perf-events.cloud.unity3d.com\n    m_EnableCloudDiagnosticsReporting: 0\n    m_LogBufferSize: 10\n    m_CaptureEditorExceptions: 1\n  UnityPurchasingSettings:\n    m_Enabled: 0\n    m_TestMode: 0\n  UnityAnalyticsSettings:\n    m_Enabled: 0\n    m_TestMode: 0\n    m_InitializeOnStartup: 1\n    m_PackageRequiringCoreStatsPresent: 0\n  UnityAdsSettings:\n    m_Enabled: 0\n    m_InitializeOnStartup: 1\n    m_TestMode: 0\n    m_IosGameId: \n    m_AndroidGameId: \n    m_GameIds: {}\n    m_GameId: \n  PerformanceReportingSettings:\n    m_Enabled: 0\n"
  },
  {
    "path": "ProjectSettings/VFXManager.asset",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!937362698 &1\nVFXManager:\n  m_ObjectHideFlags: 0\n  m_IndirectShader: {fileID: 0}\n  m_CopyBufferShader: {fileID: 0}\n  m_PrefixSumShader: {fileID: 0}\n  m_SortShader: {fileID: 0}\n  m_StripUpdateShader: {fileID: 0}\n  m_EmptyShader: {fileID: 0}\n  m_RenderPipeSettingsPath: \n  m_FixedTimeStep: 0.016666668\n  m_MaxDeltaTime: 0.05\n  m_MaxScrubTime: 30\n  m_MaxCapacity: 100000000\n  m_CompiledVersion: 0\n  m_RuntimeVersion: 0\n  m_RuntimeResources: {fileID: 0}\n  m_BatchEmptyLifetime: 300\n"
  },
  {
    "path": "ProjectSettings/VersionControlSettings.asset",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!890905787 &1\nVersionControlSettings:\n  m_ObjectHideFlags: 0\n  m_Mode: Visible Meta Files\n  m_TrackPackagesOutsideProject: 0\n"
  },
  {
    "path": "README.md",
    "content": "# KlakHap\n\n![GIF](https://i.imgur.com/exuJAIA.gif)\n\n**KlakHap** is a Unity plugin for playing back video streams encoded with the\n[HAP video codecs].\n\nHAP is a fast and high-quality video codec often used in real-time interactive\napplications. From the HAP Codecs website:\n\n> The HAP codecs are designed to fit the needs of a variety of real-time video\n> workflows where ultra high resolution video is needed such as live event\n> production, set design, 360 video for gaming, projection mapping and creative\n> coding.\n\nKlakHap provides decoded frames as textures that you can use anywhere in\nUnity's rendering pipeline: apply them to a material, present full-screen\nvideo, animate a UI element, and more. Thanks to the efficient design and\nimplementation of the HAP codecs, it can adjust playback time and speed\ndynamically without hiccups.\n\n[HAP video codecs]: https://hap.video/\n\n# System requirements\n\n- Unity 2022.3 or later\n\nCurrently, KlakHap supports only 64-bit desktop platforms (Windows, macOS, and\nLinux).\n\n# Supported formats\n\nKlakHap supports **HAP**, **HAP Alpha**, and **HAP Q**. **HAP Q Alpha** is not\nsupported.\n\nKlakHap only supports the QuickTime File Format as a container, i.e., `.mov`\nfiles.\n\n# How to install\n\nInstall the KlakHap package (`jp.keijiro.klak.hap`) from the \"Keijiro\" scoped\nregistry in Package Manager. Follow [these instructions] to add the registry to\nyour project.\n\n[these instructions]:\n  https://gist.github.com/keijiro/f8c7e8ff29bfe63d86b888901b82644c\n\n# How to specify a video file\n\nThere are two ways to specify a video file in the plugin:\n\n- **Streaming Assets Mode**: Put a video file in the [Streaming Assets]\n  directory and specify its file name.\n- **Local File System Mode**: Put a video file somewhere in local drive and\n  specify its full path.\n\nThe former method is recommended when the video file ships with the\napplication. The latter method is useful when you need to play external\ncontent.\n\n[Streaming Assets]: https://docs.unity3d.com/Manual/StreamingAssets.html\n\n# Hap Player component\n\n![Inspector](https://i.imgur.com/pIACL4W.png)\n\n**File Path** and **Path Mode** specify the source video file. See the previous\nsection for details.\n\n**Time**, **Speed** and **Loop** are used to set the initial playback state.\nYou can also change these values during playback.\n\n**Target Texture** stores decoded frames in a render texture. Note that this\nallocates a small amount of GPU time for data transfer.\n\n**Target Renderer** applies the decoded texture to a specific material\nproperty. Although this is the most performant way to render video frames, it\nrequires a few extra steps to render correctly. Keep the following points in\nmind:\n\n- UV coordinate incompatibility: Decoded textures are upside down due to\n  differences in UV coordinate conventions between Unity and HAP. You can fix\n  this using a vertically inverted texture scale/offset. You can also use the\n  `Klak/Hap` shader for this purpose.\n- Color space conversion for HAP Q: [YCoCg conversion] must be added to a\n  shader when using HAP Q. You can also use the `Klak/HAP Q` shader for this\n  purpose.\n\n[YCoCg conversion]:\n  https://gist.github.com/dlublin/90f879cfe027ebf5792bdadf2c911bb5\n\n# How to control playback\n\n`HapPlayer` provides only a few properties and methods for controlling\nplayback. This is an intentional design choice; I avoid ambiguous methods like\n`Play`, `Stop`, and `Pause`. Use the basic properties and methods instead.\n\n- To jump to a specific point: Assign a time in seconds to `time`.\n- To jump to a specific frame: Calculate the time in seconds using `frameCount`\n  and `streamDuration`, then assign it to `time`.\n- To reverse the playback direction: Assign a negative value to `speed`.\n- To pause: Assign `0` to `speed`.\n- To resume: Assign `1` to `speed`.\n- To stop: Assign `false` to `enabled`.\n- To close the video file: Destroy the `HapPlayer` component.\n- To open another video file: Call `AddComponent<HapPlayer>`, then call `Open`.\n\n# Timeline support\n\n![GIF](https://i.imgur.com/efrvvye.gif)\n\nThe HAP Player component implements the [ITimeControl] interface, which allows\nit to control playback time from a Control Track in a [Timeline]. You can\ncreate a control track by dragging and dropping a HAP Player game object into\nthe Timeline Editor, or manually create a Control Track/Clip and set the\nsource game object.\n\n[ITimeControl]: https://docs.unity3d.com/ScriptReference/Timeline.ITimeControl.html\n[Timeline]: https://docs.unity3d.com/Manual/TimelineSection.html\n\n# Platform differences (internal latency)\n\nOn Windows, KlakHap uses the [Custom Texture Update] feature to hide the\nsynchronization point in the background thread. It guarantees exact-frame\nplayback with minimal load on the main thread.\n\nOn macOS and Linux, the Custom Texture Update feature is unavailable for this\npurpose[^1]. Instead, KlakHap delays synchronization to the next frame to avoid\nmain thread stalls. In other words, it guarantees exact-frame playback but adds\na single-frame latency.\n\nYou can turn off this behavior by adding `HAP_NO_DELAY` to the [Scripting\nDefine Symbols] in the project settings. This stalls the main thread for every\nframe decoding. It significantly slows down the application but is useful when\nexact frame matching is essential (e.g., [volumetric video playback] with\nAlembic animation).\n\n[Custom Texture Update]:\n  https://github.com/keijiro/TextureUpdateExample\n\n[Scripting Define Symbols]:\n  https://docs.unity3d.com/Manual/CustomScriptingSymbols.html\n\n[volumetric video playback]:\n  https://github.com/keijiro/Abcvfx\n\n[^1]: The Custom Texture Update feature is available even on macOS/Linux but\n      doesn't support compressed texture formats, which are essential for HAP\n      decoding.\n"
  }
]