forked from cgvr/DeltaVR
Remove useless files, add hands
This commit is contained in:
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 436b6a9e384de9446bb85b969e0d6eb9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,264 +0,0 @@
|
||||
/************************************************************************************
|
||||
|
||||
Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
|
||||
|
||||
************************************************************************************/
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.IO;
|
||||
|
||||
public class AndroidVideoEditorUtil
|
||||
{
|
||||
private static readonly string videoPlayerFileName = "Assets/Oculus/SampleFramework/Core/Video/Plugins/Android/java/com/oculus/videoplayer/NativeVideoPlayer.java";
|
||||
private static readonly string disabledPlayerFileName = videoPlayerFileName + ".DISABLED";
|
||||
|
||||
#if !UNITY_2018_2_OR_NEWER
|
||||
private static readonly string gradleSourceSetPath = "$projectDir/../../Assets/Oculus/SampleFramework/Core/Video/Plugins/Android/java";
|
||||
#endif
|
||||
|
||||
private static readonly string audio360PluginPath = "Assets/Oculus/SampleFramework/Core/Video/Plugins/Android/Audio360/audio360.aar";
|
||||
private static readonly string audio360Exo29PluginPath = "Assets/Oculus/SampleFramework/Core/Video/Plugins/Android/Audio360/audio360-exo29.aar";
|
||||
|
||||
private static readonly string androidPluginsFolder = "Assets/Plugins/Android/";
|
||||
private static readonly string gradleTemplatePath = androidPluginsFolder + "mainTemplate.gradle";
|
||||
private static readonly string disabledGradleTemplatePath = gradleTemplatePath + ".DISABLED";
|
||||
private static readonly string internalGradleTemplatePath = Path.Combine(Path.Combine(GetBuildToolsDirectory(BuildTarget.Android), "GradleTemplates"), "mainTemplate.gradle");
|
||||
|
||||
private static string GetBuildToolsDirectory(BuildTarget bt)
|
||||
{
|
||||
return (string)(typeof(BuildPipeline).GetMethod("GetBuildToolsDirectory", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).Invoke(null, new object[] { bt }));
|
||||
}
|
||||
|
||||
[MenuItem("Oculus/Video/Enable Native Android Video Player")]
|
||||
public static void EnableNativeVideoPlayer()
|
||||
{
|
||||
// rename NativeJavaPlayer.java.DISABLED to NativeJavaPlayer.java
|
||||
if (File.Exists(disabledPlayerFileName))
|
||||
{
|
||||
File.Move(disabledPlayerFileName, videoPlayerFileName);
|
||||
File.Move(disabledPlayerFileName + ".meta", videoPlayerFileName + ".meta");
|
||||
}
|
||||
|
||||
AssetDatabase.ImportAsset(videoPlayerFileName);
|
||||
AssetDatabase.DeleteAsset(disabledPlayerFileName);
|
||||
|
||||
// Enable audio plugins
|
||||
PluginImporter audio360 = (PluginImporter)AssetImporter.GetAtPath(audio360PluginPath);
|
||||
PluginImporter audio360exo29 = (PluginImporter)AssetImporter.GetAtPath(audio360Exo29PluginPath);
|
||||
|
||||
if (audio360 != null && audio360exo29 != null)
|
||||
{
|
||||
audio360.SetCompatibleWithPlatform(BuildTarget.Android, true);
|
||||
audio360exo29.SetCompatibleWithPlatform(BuildTarget.Android, true);
|
||||
audio360.SaveAndReimport();
|
||||
audio360exo29.SaveAndReimport();
|
||||
}
|
||||
|
||||
// Enable gradle build with exoplayer
|
||||
EditorUserBuildSettings.androidBuildSystem = AndroidBuildSystem.Gradle;
|
||||
|
||||
// create android plugins directory if it doesn't exist
|
||||
if (!Directory.Exists(androidPluginsFolder))
|
||||
{
|
||||
Directory.CreateDirectory(androidPluginsFolder);
|
||||
}
|
||||
|
||||
if (!File.Exists(gradleTemplatePath))
|
||||
{
|
||||
if (File.Exists(gradleTemplatePath + ".DISABLED"))
|
||||
{
|
||||
File.Move(disabledGradleTemplatePath, gradleTemplatePath);
|
||||
File.Move(disabledGradleTemplatePath + ".meta", gradleTemplatePath+".meta");
|
||||
}
|
||||
else
|
||||
{
|
||||
File.Copy(internalGradleTemplatePath, gradleTemplatePath);
|
||||
}
|
||||
AssetDatabase.ImportAsset(gradleTemplatePath);
|
||||
}
|
||||
|
||||
// parse the gradle file to check the current version:
|
||||
string currentFile = File.ReadAllText(gradleTemplatePath);
|
||||
|
||||
List<string> lines = new List<string>(currentFile.Split('\n'));
|
||||
|
||||
var gradleVersion = new System.Text.RegularExpressions.Regex("com.android.tools.build:gradle:([0-9]+\\.[0-9]+\\.[0-9]+)").Match(currentFile).Groups[1].Value;
|
||||
|
||||
if (gradleVersion == "2.3.0")
|
||||
{
|
||||
// add google() to buildscript/repositories
|
||||
int buildscriptRepositories = GoToSection("buildscript.repositories", lines);
|
||||
|
||||
if (FindInScope("google\\(\\)", buildscriptRepositories + 1, lines) == -1)
|
||||
{
|
||||
lines.Insert(GetScopeEnd(buildscriptRepositories + 1, lines), "\t\tgoogle()");
|
||||
}
|
||||
|
||||
// add google() and jcenter() to allprojects/repositories
|
||||
int allprojectsRepositories = GoToSection("allprojects.repositories", lines);
|
||||
|
||||
if (FindInScope("google\\(\\)", allprojectsRepositories + 1, lines) == -1)
|
||||
{
|
||||
lines.Insert(GetScopeEnd(allprojectsRepositories + 1, lines), "\t\tgoogle()");
|
||||
}
|
||||
if (FindInScope("jcenter\\(\\)", allprojectsRepositories + 1, lines) == -1)
|
||||
{
|
||||
lines.Insert(GetScopeEnd(allprojectsRepositories + 1, lines), "\t\tjcenter()");
|
||||
}
|
||||
}
|
||||
|
||||
// add "compile 'com.google.android.exoplayer:exoplayer:2.9.5'" to dependencies
|
||||
int dependencies = GoToSection("dependencies", lines);
|
||||
if (FindInScope("com\\.google\\.android\\.exoplayer:exoplayer", dependencies + 1, lines) == -1)
|
||||
{
|
||||
lines.Insert(GetScopeEnd(dependencies + 1, lines), "\tcompile 'com.google.android.exoplayer:exoplayer:2.9.5'");
|
||||
}
|
||||
|
||||
int android = GoToSection("android", lines);
|
||||
|
||||
// add compileOptions to add Java 1.8 compatibility
|
||||
if (FindInScope("compileOptions", android + 1, lines) == -1)
|
||||
{
|
||||
int compileOptionsIndex = GetScopeEnd(android + 1, lines);
|
||||
lines.Insert(compileOptionsIndex, "\t}");
|
||||
lines.Insert(compileOptionsIndex, "\t\ttargetCompatibility JavaVersion.VERSION_1_8");
|
||||
lines.Insert(compileOptionsIndex, "\t\tsourceCompatibility JavaVersion.VERSION_1_8");
|
||||
lines.Insert(compileOptionsIndex, "\tcompileOptions {");
|
||||
}
|
||||
|
||||
// add sourceSets if Version < 2018.2
|
||||
#if !UNITY_2018_2_OR_NEWER
|
||||
|
||||
if (FindInScope("sourceSets\\.main\\.java\\.srcDir", android + 1, lines) == -1)
|
||||
{
|
||||
lines.Insert(GetScopeEnd(android + 1, lines), "\tsourceSets.main.java.srcDir \"" + gradleSourceSetPath + "\"");
|
||||
}
|
||||
#endif
|
||||
|
||||
File.WriteAllText(gradleTemplatePath, string.Join("\n", lines.ToArray()));
|
||||
}
|
||||
|
||||
[MenuItem("Oculus/Video/Disable Native Android Video Player")]
|
||||
public static void DisableNativeVideoPlayer()
|
||||
{
|
||||
if (File.Exists(videoPlayerFileName))
|
||||
{
|
||||
File.Move(videoPlayerFileName, disabledPlayerFileName);
|
||||
File.Move(videoPlayerFileName + ".meta", disabledPlayerFileName + ".meta");
|
||||
}
|
||||
|
||||
AssetDatabase.ImportAsset(disabledPlayerFileName);
|
||||
AssetDatabase.DeleteAsset(videoPlayerFileName);
|
||||
|
||||
// Disable audio plugins
|
||||
PluginImporter audio360 = (PluginImporter)AssetImporter.GetAtPath(audio360PluginPath);
|
||||
PluginImporter audio360exo29 = (PluginImporter)AssetImporter.GetAtPath(audio360Exo29PluginPath);
|
||||
|
||||
if (audio360 != null && audio360exo29 != null)
|
||||
{
|
||||
audio360.SetCompatibleWithPlatform(BuildTarget.Android, false);
|
||||
audio360exo29.SetCompatibleWithPlatform(BuildTarget.Android, false);
|
||||
audio360.SaveAndReimport();
|
||||
audio360exo29.SaveAndReimport();
|
||||
}
|
||||
|
||||
// remove exoplayer and sourcesets from gradle file (leave other parts since they are harmless).
|
||||
if (File.Exists(gradleTemplatePath))
|
||||
{
|
||||
// parse the gradle file to check the current version:
|
||||
string currentFile = File.ReadAllText(gradleTemplatePath);
|
||||
|
||||
List<string> lines = new List<string>(currentFile.Split('\n'));
|
||||
|
||||
int dependencies = GoToSection("dependencies", lines);
|
||||
int exoplayer = FindInScope("com\\.google\\.android\\.exoplayer:exoplayer", dependencies + 1, lines);
|
||||
if (exoplayer != -1)
|
||||
{
|
||||
lines.RemoveAt(exoplayer);
|
||||
}
|
||||
|
||||
int android = GoToSection("android", lines);
|
||||
int sourceSets = FindInScope("sourceSets\\.main\\.java\\.srcDir", android + 1, lines);
|
||||
if (sourceSets != -1)
|
||||
{
|
||||
lines.RemoveAt(sourceSets);
|
||||
}
|
||||
|
||||
File.WriteAllText(gradleTemplatePath, string.Join("\n", lines.ToArray()));
|
||||
}
|
||||
}
|
||||
|
||||
private static int GoToSection(string section, List<string> lines)
|
||||
{
|
||||
return GoToSection(section, 0, lines);
|
||||
}
|
||||
|
||||
private static int GoToSection(string section, int start, List<string> lines)
|
||||
{
|
||||
var sections = section.Split('.');
|
||||
|
||||
int p = start - 1;
|
||||
for (int i = 0; i < sections.Length; i++)
|
||||
{
|
||||
p = FindInScope("\\s*" + sections[i] + "\\s*\\{\\s*", p + 1, lines);
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
private static int FindInScope(string search, int start, List<string> lines)
|
||||
{
|
||||
var regex = new System.Text.RegularExpressions.Regex(search);
|
||||
|
||||
int depth = 0;
|
||||
|
||||
for (int i = start; i < lines.Count; i++)
|
||||
{
|
||||
if (depth == 0 && regex.IsMatch(lines[i]))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
|
||||
// count the number of open and close braces. If we leave the current scope, break
|
||||
if (lines[i].Contains("{"))
|
||||
{
|
||||
depth++;
|
||||
}
|
||||
if (lines[i].Contains("}"))
|
||||
{
|
||||
depth--;
|
||||
}
|
||||
if (depth < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static int GetScopeEnd(int start, List<string> lines)
|
||||
{
|
||||
int depth = 0;
|
||||
for (int i = start; i < lines.Count; i++)
|
||||
{
|
||||
// count the number of open and close braces. If we leave the current scope, break
|
||||
if (lines[i].Contains("{"))
|
||||
{
|
||||
depth++;
|
||||
}
|
||||
if (lines[i].Contains("}"))
|
||||
{
|
||||
depth--;
|
||||
}
|
||||
if (depth < 0)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c7d707d7c724f334299af6342653da7c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,32 +0,0 @@
|
||||
/************************************************************************************
|
||||
|
||||
Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
|
||||
|
||||
************************************************************************************/
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor.UI;
|
||||
using UnityEditor;
|
||||
|
||||
[CustomEditor(typeof(MediaPlayerImage), true)]
|
||||
public class MediaPlayerImageEditor : ImageEditor
|
||||
{
|
||||
|
||||
SerializedProperty m_ButtonType;
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
|
||||
m_ButtonType = serializedObject.FindProperty("m_ButtonType");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
base.OnInspectorGUI();
|
||||
|
||||
EditorGUILayout.PropertyField(m_ButtonType);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8782cb0bdeb9f2843bc9d9b19ed4d05a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 49c334cc948b2724ea9662d357cb78ae
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,29 +0,0 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: MovieTexture
|
||||
m_Shader: {fileID: 4800000, guid: 873aaf52f432945df9937ea75a74c0e7, type: 3}
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 2800000, guid: a025c23fceb7d4966b603419f551ce99, type: 3}
|
||||
m_Scale: {x: 0.5, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats: []
|
||||
m_Colors:
|
||||
- _SrcRectLeft: {r: 0, g: 0, b: 1, a: 1}
|
||||
- _SrcRectRight: {r: 0, g: 0, b: 1, a: 1}
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0a1063314b03a02488a3ef840b635489
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 83e0182c75aad7d43b7e8288b169db41
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3a259fc639d42744c9aa779ebf0b97c5
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9796cce996f141b41911e7efe0bad759
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,22 +0,0 @@
|
||||
Facebook 360 Audio Terms
|
||||
These Facebook 360 Audio Terms (“Terms”) govern your use of the Facebook 360 Audio Engine software (including any updates, upgrades and/or new versions thereof that are made available to you) (collectively, the “Software”). By accessing or using the Software, you agree to the Terms.
|
||||
|
||||
Last updated on 11 August 2017
|
||||
|
||||
1. Subject to these Terms, Facebook hereby grants to you a worldwide, non-exclusive, no-charge, non-transferable, non-sublicenseable, royalty-free copyright license to (a) use and reproduce the Software in object code format for inclusion in your applications, content, games, and demos (collectively referred to as “Developer Content”), and (b) distribute the Software solely as incorporated in your Developer Content.
|
||||
2. You agree:
|
||||
a) Not to copy or use the Software for any purpose except as expressly permitted by these Terms;
|
||||
b) Not to modify, disassemble, decompile or otherwise reverse engineer the Software;
|
||||
c) To ensure that your employees, agents and other parties under your control who will use the Software do so in accordance with these Terms and are accordingly notified of the same;
|
||||
d) Not to permit or facilitate the use of the Software in any manner which would constitute a breach of these Terms; and
|
||||
e) Not to place or distribute the Software (except as incorporated in your Developer Content) on any website, File Transfer Protocol server or similar location without the express prior written consent of Facebook.
|
||||
3. You will use reasonable efforts to include in the Developer Content any logo, audio badge and/or other branding for the Software that Facebook may reasonably request, and Facebook hereby grants you a limited, non-exclusive, non-transferable, non-sublicenseable license to use such branding assets solely in the manner Facebook requests.
|
||||
4. Facebook may make changes to these Terms at any time by notifying you in writing (including email) describing the changes made. Any such changes will become effective, and will be deemed accepted by you, thirty (30) days following your receipt of notice (except any changes Facebook notifies you are required by law, which will become effective immediately) (the “Notice Period”). If you do not agree to any or all changes to these Terms, you must cease use of the Software during the Notice Period as to any prospective Developer Content, which will be your sole and exclusive remedy. Any then-existing Developer Content will continue to be governed by the then-prior version of these Terms. You agree that your continued use of the Software after the Notice Period constitutes your agreement to the applicable changes to these Terms.
|
||||
5. Facebook reserves the right to terminate these Terms and all your rights hereunder in the event: (a) you materially breach these Terms and fail to cure such breach within ten (10) business days after notice of breach from Facebook; (b) a claim is threatened or made by a third party that the Developer Content infringes its intellectual property or proprietary rights; (c) the Developer Content violates or infringes applicable law; or (d) Facebook believes in good faith that your use of the Software poses a risk to, or could adversely impact, Facebook’s or its affiliates’ products or business. Termination pursuant to this Section 5 shall be effective: (i) immediately upon notice from Facebook for termination under the foregoing subsections (b) or (c), and (ii) within thirty (30) days’ after notice from Facebook for termination under subsection (d). Termination under subsection (d) shall be effective as to any prospective Developer Content but not as to any then-existing Developer Content, provided, however, that you shall use commercially reasonable efforts to create and distribute new versions of the Developer Content during such thirty (30) day notice period which does not utilize the Software (“New Versions”) and encourage end users to replace the Developer Content with the New Versions.
|
||||
6. You may not assign any rights or obligations under these Terms without the advance written consent of Facebook, which may be withheld in its sole discretion; provided, however, that you may, without such consent, assign these Terms in connection with the transfer or sale of all or substantially all of your business or assets related to these Terms, or in the event of a merger, consolidation, change in control or other similar transaction (a “Change of Control”). In the event of a Change of Control: (a) you will give written notice to Facebook within thirty (30) days after the Change of Control; and (b) Facebook may immediately terminate rights or obligations under these Terms any time between the Change of Control and thirty (30) days after it receives that written notice. Facebook may assign its rights or obligations under these Terms in its sole discretion.
|
||||
7. Your remedies under these Terms shall be limited to the right to collect money damages, if any, and you hereby waive your right to injunctive or other equitable relief.
|
||||
8. Your use of third-party materials included in the Software may be subject to other terms and conditions typically found in separate third-party license agreements or “READ ME” files included with such third-party materials. To the extent such other terms and conditions conflict with these Terms, the former will control with respect to the applicable third-party materials.
|
||||
9. Facebook may include in the Software additional content (e.g., samples) for demonstration, references or other specific purposes. Such content will be clearly marked in the Software and is subject to any included terms and conditions.
|
||||
10. If you are accepting these terms on behalf of a third party, you represent and warrant that you have the authority as agent to such party to use such feature on their behalf and bind such party to these terms.
|
||||
11. You are solely responsible for ensuring that your use of the Software complies with the Facebook Platform Policy located at https://developers.facebook.com/policy/.
|
||||
12. The Software is part of “Facebook” under Facebook’s Statement of Rights and Responsibilities (https://www.facebook.com/legal/terms, the “SRR”), and your use of the Software is deemed part of your use of, and actions on, “Facebook.” In the event of any express conflict between these Terms and the SRR, these Terms will govern solely with respect to your use of the Software and solely to the extent of the conflict. Facebook reserves the right to monitor or audit your compliance with these Terms and to update these Terms from time to time as described above.
|
||||
@@ -1,7 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4d41527e8defd4278aa630380a98e8d5
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,141 +0,0 @@
|
||||
THE FOLLOWING SETS FORTH ATTRIBUTION NOTICES FOR THIRD PARTY SOFTWARE THAT MAY BE CONTAINED IN PORTIONS OF AUDIO360
|
||||
|
||||
-----
|
||||
|
||||
The Audio360 software may use libsamplerate under the BSD open source license, available from http://www.mega-nerd.com/SRC/. libsamplerate contains the following license and notice below:
|
||||
|
||||
Copyright (c) 2012-2016, Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
The Audio360 software may use Wavpack, available from http://www.wavpack.com. Wavpack contains the following license and notice below:
|
||||
|
||||
Copyright (c) 1998 - 2016 David Bryant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of Conifer Software nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
The Audio360 software may use libopus, available from http://opus-codec.org/. libopus contains the following license and notice below:
|
||||
|
||||
Copyright 2001-2011 Xiph.Org, Skype Limited, Octasic,
|
||||
Jean-Marc Valin, Timothy B. Terriberry,
|
||||
CSIRO, Gregory Maxwell, Mark Borgerding,
|
||||
Erik de Castro Lopo
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Opus is subject to the royalty-free patent licenses which are
|
||||
specified at:
|
||||
|
||||
Xiph.Org Foundation:
|
||||
https://datatracker.ietf.org/ipr/1524/
|
||||
|
||||
Microsoft Corporation:
|
||||
https://datatracker.ietf.org/ipr/1914/
|
||||
|
||||
Broadcom Corporation:
|
||||
https://datatracker.ietf.org/ipr/1526/
|
||||
|
||||
|
||||
The Audio360 software may use PortAudio, available from http://www.portaudio.com. PortAudio contains the following license and notice below:
|
||||
|
||||
PortAudio Portable Real-Time Audio Library
|
||||
Latest version at: http://www.portaudio.com
|
||||
Copyright (c) 1999-2008 Phil Burk and Ross Bencina
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files
|
||||
(the "Software"), to deal in the Software without restriction,
|
||||
including without limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
The text above constitutes the entire PortAudio license; however,
|
||||
the PortAudio community also makes the following non-binding requests:
|
||||
|
||||
Any person wishing to distribute modifications to the Software is
|
||||
requested to send the modifications to the original developer so that
|
||||
they can be incorporated into the canonical version. It is also
|
||||
requested that these non-binding requests be included along with the
|
||||
license above.
|
||||
@@ -1,7 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1ed4d8069bb483a4ea222be6e17e75b6
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
@@ -1,87 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6f1932f9a85d347a685f96d6643ac091
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
platformData:
|
||||
- first:
|
||||
'': Any
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
Exclude Android: 1
|
||||
Exclude Editor: 1
|
||||
Exclude Linux: 1
|
||||
Exclude Linux64: 1
|
||||
Exclude LinuxUniversal: 1
|
||||
Exclude OSXUniversal: 1
|
||||
Exclude Win: 1
|
||||
Exclude Win64: 1
|
||||
- first:
|
||||
Android: Android
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: ARMv7
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
DefaultValueInitialized: true
|
||||
OS: AnyOS
|
||||
- first:
|
||||
Facebook: Win
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Facebook: Win64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Linux
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: x86
|
||||
- first:
|
||||
Standalone: Linux64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: x86_64
|
||||
- first:
|
||||
Standalone: OSXUniversal
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Win
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Win64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
@@ -1,87 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0fc24de97752a4f81b61159248da7281
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
platformData:
|
||||
- first:
|
||||
'': Any
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
Exclude Android: 1
|
||||
Exclude Editor: 1
|
||||
Exclude Linux: 1
|
||||
Exclude Linux64: 1
|
||||
Exclude LinuxUniversal: 1
|
||||
Exclude OSXUniversal: 1
|
||||
Exclude Win: 1
|
||||
Exclude Win64: 1
|
||||
- first:
|
||||
Android: Android
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: ARMv7
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
DefaultValueInitialized: true
|
||||
OS: AnyOS
|
||||
- first:
|
||||
Facebook: Win
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Facebook: Win64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Linux
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: x86
|
||||
- first:
|
||||
Standalone: Linux64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: x86_64
|
||||
- first:
|
||||
Standalone: OSXUniversal
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Win
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Win64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,267 +0,0 @@
|
||||
/************************************************************************************
|
||||
|
||||
Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
|
||||
|
||||
************************************************************************************/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public static class NativeVideoPlayer {
|
||||
|
||||
public enum PlabackState {
|
||||
Idle = 1,
|
||||
Preparing = 2,
|
||||
Buffering = 3,
|
||||
Ready = 4,
|
||||
Ended = 5
|
||||
}
|
||||
|
||||
private static System.IntPtr? _Activity;
|
||||
private static System.IntPtr? _VideoPlayerClass;
|
||||
|
||||
private static readonly jvalue[] EmptyParams = new jvalue[0];
|
||||
|
||||
private static System.IntPtr getIsPlayingMethodId;
|
||||
private static System.IntPtr getCurrentPlaybackStateMethodId;
|
||||
private static System.IntPtr getDurationMethodId;
|
||||
private static System.IntPtr getPlaybackPositionMethodId;
|
||||
private static System.IntPtr setPlaybackPositionMethodId;
|
||||
private static jvalue[] setPlaybackPositionParams;
|
||||
private static System.IntPtr playVideoMethodId;
|
||||
private static jvalue[] playVideoParams;
|
||||
private static System.IntPtr stopMethodId;
|
||||
private static System.IntPtr resumeMethodId;
|
||||
private static System.IntPtr pauseMethodId;
|
||||
private static System.IntPtr setPlaybackSpeedMethodId;
|
||||
private static jvalue[] setPlaybackSpeedParams;
|
||||
private static System.IntPtr setLoopingMethodId;
|
||||
private static jvalue[] setLoopingParams;
|
||||
private static System.IntPtr setListenerRotationQuaternionMethodId;
|
||||
private static jvalue[] setListenerRotationQuaternionParams;
|
||||
|
||||
private static System.IntPtr VideoPlayerClass
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_VideoPlayerClass.HasValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
System.IntPtr myVideoPlayerClass = AndroidJNI.FindClass("com/oculus/videoplayer/NativeVideoPlayer");
|
||||
|
||||
if (myVideoPlayerClass != System.IntPtr.Zero)
|
||||
{
|
||||
_VideoPlayerClass = AndroidJNI.NewGlobalRef(myVideoPlayerClass);
|
||||
|
||||
AndroidJNI.DeleteLocalRef(myVideoPlayerClass);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("Failed to find NativeVideoPlayer class");
|
||||
_VideoPlayerClass = System.IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
catch(System.Exception ex)
|
||||
{
|
||||
Debug.LogError("Failed to find NativeVideoPlayer class");
|
||||
Debug.LogException(ex);
|
||||
_VideoPlayerClass = System.IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
return _VideoPlayerClass.GetValueOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
private static System.IntPtr Activity
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_Activity.HasValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
System.IntPtr unityPlayerClass = AndroidJNI.FindClass("com/unity3d/player/UnityPlayer");
|
||||
System.IntPtr currentActivityField = AndroidJNI.GetStaticFieldID(unityPlayerClass, "currentActivity", "Landroid/app/Activity;");
|
||||
System.IntPtr activity = AndroidJNI.GetStaticObjectField(unityPlayerClass, currentActivityField);
|
||||
|
||||
_Activity = AndroidJNI.NewGlobalRef(activity);
|
||||
|
||||
AndroidJNI.DeleteLocalRef(activity);
|
||||
AndroidJNI.DeleteLocalRef(unityPlayerClass);
|
||||
}
|
||||
catch(System.Exception ex)
|
||||
{
|
||||
Debug.LogException(ex);
|
||||
_Activity = System.IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
return _Activity.GetValueOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsAvailable
|
||||
{
|
||||
get
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
return VideoPlayerClass != System.IntPtr.Zero;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsPlaying
|
||||
{
|
||||
get
|
||||
{
|
||||
if (getIsPlayingMethodId == System.IntPtr.Zero)
|
||||
{
|
||||
getIsPlayingMethodId = AndroidJNI.GetStaticMethodID(VideoPlayerClass, "getIsPlaying", "()Z");
|
||||
}
|
||||
|
||||
return AndroidJNI.CallStaticBooleanMethod(VideoPlayerClass, getIsPlayingMethodId, EmptyParams);
|
||||
}
|
||||
}
|
||||
|
||||
public static PlabackState CurrentPlaybackState {
|
||||
get {
|
||||
if (getCurrentPlaybackStateMethodId == System.IntPtr.Zero)
|
||||
{
|
||||
getCurrentPlaybackStateMethodId = AndroidJNI.GetStaticMethodID(VideoPlayerClass, "getCurrentPlaybackState", "()I");
|
||||
}
|
||||
|
||||
return (PlabackState)AndroidJNI.CallStaticIntMethod(VideoPlayerClass, getCurrentPlaybackStateMethodId, EmptyParams);
|
||||
}
|
||||
}
|
||||
|
||||
public static long Duration
|
||||
{
|
||||
get
|
||||
{
|
||||
if (getDurationMethodId == System.IntPtr.Zero)
|
||||
{
|
||||
getDurationMethodId = AndroidJNI.GetStaticMethodID(VideoPlayerClass, "getDuration", "()J");
|
||||
}
|
||||
|
||||
return AndroidJNI.CallStaticLongMethod(VideoPlayerClass, getDurationMethodId, EmptyParams);
|
||||
}
|
||||
}
|
||||
|
||||
public static long PlaybackPosition
|
||||
{
|
||||
get
|
||||
{
|
||||
if (getPlaybackPositionMethodId == System.IntPtr.Zero)
|
||||
{
|
||||
getPlaybackPositionMethodId = AndroidJNI.GetStaticMethodID(VideoPlayerClass, "getPlaybackPosition", "()J");
|
||||
}
|
||||
|
||||
return AndroidJNI.CallStaticLongMethod(VideoPlayerClass, getPlaybackPositionMethodId, EmptyParams);
|
||||
}
|
||||
set
|
||||
{
|
||||
if (setPlaybackPositionMethodId == System.IntPtr.Zero)
|
||||
{
|
||||
setPlaybackPositionMethodId = AndroidJNI.GetStaticMethodID(VideoPlayerClass, "setPlaybackPosition", "(J)V");
|
||||
setPlaybackPositionParams = new jvalue[1];
|
||||
}
|
||||
|
||||
setPlaybackPositionParams[0].j = value;
|
||||
|
||||
AndroidJNI.CallStaticVoidMethod(VideoPlayerClass, setPlaybackPositionMethodId, setPlaybackPositionParams);
|
||||
}
|
||||
}
|
||||
|
||||
public static void PlayVideo(string path, string drmLicenseUrl, System.IntPtr surfaceObj)
|
||||
{
|
||||
if (playVideoMethodId == System.IntPtr.Zero)
|
||||
{
|
||||
playVideoMethodId = AndroidJNI.GetStaticMethodID(VideoPlayerClass, "playVideo", "(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;Landroid/view/Surface;)V");
|
||||
playVideoParams = new jvalue[4];
|
||||
}
|
||||
|
||||
System.IntPtr filePathJString = AndroidJNI.NewStringUTF(path);
|
||||
System.IntPtr drmLicenseUrlJString = AndroidJNI.NewStringUTF(drmLicenseUrl);
|
||||
|
||||
playVideoParams[0].l = Activity;
|
||||
playVideoParams[1].l = filePathJString;
|
||||
playVideoParams[2].l = drmLicenseUrlJString;
|
||||
playVideoParams[3].l = surfaceObj;
|
||||
AndroidJNI.CallStaticVoidMethod(VideoPlayerClass, playVideoMethodId, playVideoParams);
|
||||
|
||||
AndroidJNI.DeleteLocalRef(filePathJString);
|
||||
AndroidJNI.DeleteLocalRef(drmLicenseUrlJString);
|
||||
}
|
||||
|
||||
public static void Stop()
|
||||
{
|
||||
if (stopMethodId == System.IntPtr.Zero)
|
||||
{
|
||||
stopMethodId = AndroidJNI.GetStaticMethodID(VideoPlayerClass, "stop", "()V");
|
||||
}
|
||||
|
||||
AndroidJNI.CallStaticVoidMethod(VideoPlayerClass, stopMethodId, EmptyParams);
|
||||
}
|
||||
|
||||
public static void Play()
|
||||
{
|
||||
if (resumeMethodId == System.IntPtr.Zero)
|
||||
{
|
||||
resumeMethodId = AndroidJNI.GetStaticMethodID(VideoPlayerClass, "resume", "()V");
|
||||
}
|
||||
|
||||
AndroidJNI.CallStaticVoidMethod(VideoPlayerClass, resumeMethodId, EmptyParams);
|
||||
}
|
||||
|
||||
public static void Pause()
|
||||
{
|
||||
if (pauseMethodId == System.IntPtr.Zero)
|
||||
{
|
||||
pauseMethodId = AndroidJNI.GetStaticMethodID(VideoPlayerClass, "pause", "()V");
|
||||
}
|
||||
|
||||
AndroidJNI.CallStaticVoidMethod(VideoPlayerClass, pauseMethodId, EmptyParams);
|
||||
}
|
||||
|
||||
public static void SetPlaybackSpeed(float speed)
|
||||
{
|
||||
if (setPlaybackSpeedMethodId == System.IntPtr.Zero)
|
||||
{
|
||||
setPlaybackSpeedMethodId = AndroidJNI.GetStaticMethodID(VideoPlayerClass, "setPlaybackSpeed", "(F)V");
|
||||
setPlaybackSpeedParams = new jvalue[1];
|
||||
}
|
||||
|
||||
setPlaybackSpeedParams[0].f = speed;
|
||||
AndroidJNI.CallStaticVoidMethod(VideoPlayerClass, setPlaybackSpeedMethodId, setPlaybackSpeedParams);
|
||||
}
|
||||
public static void SetLooping(bool looping)
|
||||
{
|
||||
if (setLoopingMethodId == System.IntPtr.Zero)
|
||||
{
|
||||
setLoopingMethodId = AndroidJNI.GetStaticMethodID(VideoPlayerClass, "setLooping", "(Z)V");
|
||||
setLoopingParams = new jvalue[1];
|
||||
}
|
||||
|
||||
setLoopingParams[0].z = looping;
|
||||
AndroidJNI.CallStaticVoidMethod(VideoPlayerClass, setLoopingMethodId, setLoopingParams);
|
||||
}
|
||||
|
||||
public static void SetListenerRotation(Quaternion rotation)
|
||||
{
|
||||
if (setListenerRotationQuaternionMethodId == System.IntPtr.Zero)
|
||||
{
|
||||
setListenerRotationQuaternionMethodId = AndroidJNI.GetStaticMethodID(VideoPlayerClass, "setListenerRotationQuaternion", "(FFFF)V");
|
||||
setListenerRotationQuaternionParams = new jvalue[4];
|
||||
}
|
||||
|
||||
setListenerRotationQuaternionParams[0].f = rotation.x;
|
||||
setListenerRotationQuaternionParams[1].f = rotation.y;
|
||||
setListenerRotationQuaternionParams[2].f = rotation.z;
|
||||
setListenerRotationQuaternionParams[3].f = rotation.w;
|
||||
AndroidJNI.CallStaticVoidMethod(VideoPlayerClass, setListenerRotationQuaternionMethodId, setListenerRotationQuaternionParams);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5f7cc58b9c592bd48b9b1e3eb4338446
|
||||
timeCreated: 1537389680
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d030c8ccce132694ba66efc312b20050
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0dd29019dbce46e4eb76ff5daf345fbd
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 437e818a5df520a41b592b18a218b93e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ef869dfc5cfdad6458d54363c87e5982
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,560 +0,0 @@
|
||||
/************************************************************************************
|
||||
|
||||
Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
|
||||
|
||||
************************************************************************************/
|
||||
|
||||
package com.oculus.videoplayer;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.storage.OnObbStateChangeListener;
|
||||
import android.os.storage.StorageManager;
|
||||
//import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
import android.view.Surface;
|
||||
|
||||
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.C.ContentType;
|
||||
import com.google.android.exoplayer2.DefaultRenderersFactory;
|
||||
import com.google.android.exoplayer2.ExoPlaybackException;
|
||||
import com.google.android.exoplayer2.ExoPlayer;
|
||||
import com.google.android.exoplayer2.ExoPlayerFactory;
|
||||
import com.google.android.exoplayer2.PlaybackParameters;
|
||||
import com.google.android.exoplayer2.PlaybackPreparer;
|
||||
import com.google.android.exoplayer2.Player;
|
||||
import com.google.android.exoplayer2.Renderer;
|
||||
import com.google.android.exoplayer2.RenderersFactory;
|
||||
import com.google.android.exoplayer2.SimpleExoPlayer;
|
||||
import com.google.android.exoplayer2.Timeline;
|
||||
import com.google.android.exoplayer2.audio.AudioProcessor;
|
||||
import com.google.android.exoplayer2.audio.AudioRendererEventListener;
|
||||
import com.google.android.exoplayer2.audio.AudioSink;
|
||||
import com.google.android.exoplayer2.drm.DefaultDrmSessionManager;
|
||||
import com.google.android.exoplayer2.drm.DrmSessionManager;
|
||||
import com.google.android.exoplayer2.drm.FrameworkMediaCrypto;
|
||||
import com.google.android.exoplayer2.drm.FrameworkMediaDrm;
|
||||
import com.google.android.exoplayer2.drm.HttpMediaDrmCallback;
|
||||
import com.google.android.exoplayer2.drm.UnsupportedDrmException;
|
||||
import com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.DecoderInitializationException;
|
||||
import com.google.android.exoplayer2.mediacodec.MediaCodecSelector;
|
||||
import com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException;
|
||||
import com.google.android.exoplayer2.metadata.MetadataOutput;
|
||||
import com.google.android.exoplayer2.source.BehindLiveWindowException;
|
||||
import com.google.android.exoplayer2.source.ConcatenatingMediaSource;
|
||||
import com.google.android.exoplayer2.source.ExtractorMediaSource;
|
||||
import com.google.android.exoplayer2.source.MediaSource;
|
||||
import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||
import com.google.android.exoplayer2.source.ads.AdsLoader;
|
||||
import com.google.android.exoplayer2.source.ads.AdsMediaSource;
|
||||
import com.google.android.exoplayer2.source.dash.DashChunkSource;
|
||||
import com.google.android.exoplayer2.source.dash.DefaultDashChunkSource;
|
||||
import com.google.android.exoplayer2.source.dash.DashMediaSource;
|
||||
import com.google.android.exoplayer2.source.hls.HlsMediaSource;
|
||||
import com.google.android.exoplayer2.source.smoothstreaming.DefaultSsChunkSource;
|
||||
import com.google.android.exoplayer2.source.smoothstreaming.SsChunkSource;
|
||||
import com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource;
|
||||
import com.google.android.exoplayer2.text.TextOutput;
|
||||
import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection;
|
||||
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
|
||||
import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo;
|
||||
import com.google.android.exoplayer2.trackselection.RandomTrackSelection;
|
||||
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
||||
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
|
||||
import com.google.android.exoplayer2.upstream.BandwidthMeter;
|
||||
import com.google.android.exoplayer2.upstream.DataSource;
|
||||
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
|
||||
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
||||
import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory;
|
||||
import com.google.android.exoplayer2.upstream.FileDataSourceFactory;
|
||||
import com.google.android.exoplayer2.upstream.HttpDataSource;
|
||||
import com.google.android.exoplayer2.upstream.cache.Cache;
|
||||
import com.google.android.exoplayer2.upstream.cache.CacheDataSource;
|
||||
import com.google.android.exoplayer2.upstream.cache.CacheDataSourceFactory;
|
||||
import com.google.android.exoplayer2.upstream.cache.NoOpCacheEvictor;
|
||||
import com.google.android.exoplayer2.upstream.cache.SimpleCache;
|
||||
import com.google.android.exoplayer2.util.ErrorMessageProvider;
|
||||
import com.google.android.exoplayer2.util.EventLogger;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
import com.google.android.exoplayer2.video.MediaCodecVideoRenderer;
|
||||
import com.google.android.exoplayer2.video.VideoListener;
|
||||
import com.google.android.exoplayer2.video.VideoRendererEventListener;
|
||||
import com.twobigears.audio360.AudioEngine;
|
||||
import com.twobigears.audio360.ChannelMap;
|
||||
import com.twobigears.audio360.SpatDecoderQueue;
|
||||
import com.twobigears.audio360.TBQuat;
|
||||
import com.twobigears.audio360exo2.Audio360Sink;
|
||||
import com.twobigears.audio360exo2.OpusRenderer;
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.Math;
|
||||
import java.lang.System;
|
||||
import java.net.CookieHandler;
|
||||
import java.net.CookieManager;
|
||||
import java.net.CookiePolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Created by trevordasch on 9/19/2018.
|
||||
*/
|
||||
|
||||
public class NativeVideoPlayer
|
||||
{
|
||||
private static final String TAG = "NativeVideoPlayer"
|
||||
;
|
||||
static AudioEngine engine;
|
||||
static SpatDecoderQueue spat;
|
||||
static final float SAMPLE_RATE = 48000.f;
|
||||
static final int BUFFER_SIZE = 1024;
|
||||
static final int QUEUE_SIZE_IN_SAMPLES = 40960;
|
||||
|
||||
static SimpleExoPlayer exoPlayer;
|
||||
static AudioSink audio360Sink;
|
||||
static File downloadDirectory;
|
||||
static Cache downloadCache;
|
||||
static FrameworkMediaDrm mediaDrm;
|
||||
|
||||
static Handler handler;
|
||||
|
||||
static volatile boolean isPlaying;
|
||||
static volatile int currentPlaybackState;
|
||||
|
||||
static volatile long duration;
|
||||
|
||||
static volatile long lastPlaybackPosition;
|
||||
static volatile long lastPlaybackUpdateTime;
|
||||
static volatile float lastPlaybackSpeed;
|
||||
|
||||
private static void updatePlaybackState() {
|
||||
duration = exoPlayer.getDuration();
|
||||
lastPlaybackPosition = exoPlayer.getCurrentPosition();
|
||||
lastPlaybackSpeed = isPlaying ? exoPlayer.getPlaybackParameters().speed : 0;
|
||||
lastPlaybackUpdateTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
private static Handler getHandler()
|
||||
{
|
||||
if (handler == null)
|
||||
{
|
||||
handler = new Handler(Looper.getMainLooper());
|
||||
}
|
||||
|
||||
return handler;
|
||||
}
|
||||
|
||||
private static class CustomRenderersFactory extends DefaultRenderersFactory {
|
||||
private Context myContext;
|
||||
private long myAllowedVideoJoiningTimeMs = 5000;
|
||||
public CustomRenderersFactory(Context context) {
|
||||
super(context);
|
||||
this.myContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultRenderersFactory setAllowedVideoJoiningTimeMs(long allowedVideoJoiningTimeMs) {
|
||||
super.setAllowedVideoJoiningTimeMs(allowedVideoJoiningTimeMs);
|
||||
myAllowedVideoJoiningTimeMs = allowedVideoJoiningTimeMs;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Renderer[] createRenderers(
|
||||
Handler eventHandler,
|
||||
VideoRendererEventListener videoRendererEventListener,
|
||||
AudioRendererEventListener audioRendererEventListener,
|
||||
TextOutput textRendererOutput,
|
||||
MetadataOutput metadataRendererOutput,
|
||||
/*@Nullable*/ DrmSessionManager<FrameworkMediaCrypto> drmSessionManager) {
|
||||
|
||||
Renderer[] renderers = super.createRenderers(
|
||||
eventHandler,
|
||||
videoRendererEventListener,
|
||||
audioRendererEventListener,
|
||||
textRendererOutput,
|
||||
metadataRendererOutput,
|
||||
drmSessionManager);
|
||||
|
||||
ArrayList<Renderer> rendererList = new ArrayList<Renderer>(Arrays.asList(renderers));
|
||||
|
||||
// The output latency of the engine can be used to compensate for sync
|
||||
double latency = engine.getOutputLatencyMs();
|
||||
|
||||
// Audio: opus codec with the spatial audio engine
|
||||
// TBE_8_2 implies 10 channels of audio (8 channels of spatial audio, 2 channels of head-locked)
|
||||
audio360Sink = new Audio360Sink(spat, ChannelMap.TBE_8_2, latency);
|
||||
final OpusRenderer audioRenderer = new OpusRenderer(audio360Sink);
|
||||
|
||||
rendererList.add(audioRenderer);
|
||||
|
||||
renderers = rendererList.toArray(renderers);
|
||||
return renderers;
|
||||
}
|
||||
}
|
||||
|
||||
private static File getDownloadDirectory(Context context) {
|
||||
if (downloadDirectory == null) {
|
||||
downloadDirectory = context.getExternalFilesDir(null);
|
||||
if (downloadDirectory == null) {
|
||||
downloadDirectory = context.getFilesDir();
|
||||
}
|
||||
}
|
||||
return downloadDirectory;
|
||||
}
|
||||
|
||||
private static synchronized Cache getDownloadCache(Context context) {
|
||||
if (downloadCache == null) {
|
||||
File downloadContentDirectory = new File(getDownloadDirectory(context), "downloads");
|
||||
downloadCache = new SimpleCache(downloadContentDirectory, new NoOpCacheEvictor());
|
||||
}
|
||||
return downloadCache;
|
||||
}
|
||||
|
||||
private static CacheDataSourceFactory buildReadOnlyCacheDataSource(
|
||||
DefaultDataSourceFactory upstreamFactory, Cache cache) {
|
||||
return new CacheDataSourceFactory(
|
||||
cache,
|
||||
upstreamFactory,
|
||||
new FileDataSourceFactory(),
|
||||
/* cacheWriteDataSinkFactory= */ null,
|
||||
CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR,
|
||||
/* eventListener= */ null);
|
||||
}
|
||||
|
||||
/** Returns a {@link DataSource.Factory}. */
|
||||
public static DataSource.Factory buildDataSourceFactory(Context context) {
|
||||
DefaultDataSourceFactory upstreamFactory =
|
||||
new DefaultDataSourceFactory(context, null, buildHttpDataSourceFactory(context));
|
||||
return buildReadOnlyCacheDataSource(upstreamFactory, getDownloadCache(context));
|
||||
}
|
||||
|
||||
/** Returns a {@link HttpDataSource.Factory}. */
|
||||
public static HttpDataSource.Factory buildHttpDataSourceFactory(Context context) {
|
||||
return new DefaultHttpDataSourceFactory(Util.getUserAgent(context, "NativeVideoPlayer"));
|
||||
}
|
||||
|
||||
private static DefaultDrmSessionManager<FrameworkMediaCrypto> buildDrmSessionManagerV18(Context context,
|
||||
UUID uuid, String licenseUrl, String[] keyRequestPropertiesArray, boolean multiSession)
|
||||
throws UnsupportedDrmException {
|
||||
HttpDataSource.Factory licenseDataSourceFactory = buildHttpDataSourceFactory(context);
|
||||
HttpMediaDrmCallback drmCallback =
|
||||
new HttpMediaDrmCallback(licenseUrl, licenseDataSourceFactory);
|
||||
if (keyRequestPropertiesArray != null) {
|
||||
for (int i = 0; i < keyRequestPropertiesArray.length - 1; i += 2) {
|
||||
drmCallback.setKeyRequestProperty(keyRequestPropertiesArray[i],
|
||||
keyRequestPropertiesArray[i + 1]);
|
||||
}
|
||||
}
|
||||
if (mediaDrm != null)
|
||||
{
|
||||
mediaDrm.release();
|
||||
}
|
||||
mediaDrm = FrameworkMediaDrm.newInstance(uuid);
|
||||
return new DefaultDrmSessionManager<>(uuid, mediaDrm, drmCallback, null, multiSession);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static MediaSource buildMediaSource(Context context, Uri uri, /*@Nullable*/ String overrideExtension, DataSource.Factory dataSourceFactory) {
|
||||
@ContentType int type = Util.inferContentType(uri, overrideExtension);
|
||||
switch (type) {
|
||||
case C.TYPE_DASH:
|
||||
|
||||
return new DashMediaSource.Factory(new DefaultDashChunkSource.Factory(dataSourceFactory), dataSourceFactory)
|
||||
.createMediaSource(uri);
|
||||
case C.TYPE_SS:
|
||||
return new SsMediaSource.Factory(new DefaultSsChunkSource.Factory(dataSourceFactory), dataSourceFactory)
|
||||
.createMediaSource(uri);
|
||||
case C.TYPE_HLS:
|
||||
return new HlsMediaSource.Factory(dataSourceFactory)
|
||||
.createMediaSource(uri);
|
||||
case C.TYPE_OTHER:
|
||||
return new ExtractorMediaSource.Factory(dataSourceFactory).createMediaSource(uri);
|
||||
default: {
|
||||
throw new IllegalStateException("Unsupported type: " + type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void playVideo( final Context context, final String filePath, final String drmLicenseUrl, final Surface surface)
|
||||
{
|
||||
// set up exoplayer on main thread
|
||||
getHandler().post( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
// 1. Create a default TrackSelector
|
||||
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
|
||||
TrackSelection.Factory videoTrackSelectionFactory =
|
||||
new AdaptiveTrackSelection.Factory(bandwidthMeter);
|
||||
DefaultTrackSelector trackSelector =
|
||||
new DefaultTrackSelector(videoTrackSelectionFactory);
|
||||
// Produces DataSource instances through which media data is loaded.
|
||||
DataSource.Factory dataSourceFactory = buildDataSourceFactory(context);
|
||||
|
||||
Uri uri = Uri.parse( filePath );
|
||||
|
||||
if (filePath.startsWith( "jar:file:" )) {
|
||||
if (filePath.contains(".apk")) { // APK
|
||||
uri = new Uri.Builder().scheme( "asset" ).path( filePath.substring( filePath.indexOf( "/assets/" ) + "/assets/".length() ) ).build();
|
||||
}
|
||||
else if (filePath.contains(".obb")) { // OBB
|
||||
String obbPath = filePath.substring(11, filePath.indexOf(".obb") + 4);
|
||||
|
||||
StorageManager sm = (StorageManager)context.getSystemService(Context.STORAGE_SERVICE);
|
||||
if (!sm.isObbMounted(obbPath))
|
||||
{
|
||||
sm.mountObb(obbPath, null, new OnObbStateChangeListener() {
|
||||
@Override
|
||||
public void onObbStateChange(String path, int state) {
|
||||
super.onObbStateChange(path, state);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
uri = new Uri.Builder().scheme( "file" ).path( sm.getMountedObbPath(obbPath) + filePath.substring(filePath.indexOf(".obb") + 5) ).build();
|
||||
}
|
||||
}
|
||||
|
||||
// Set up video source if drmLicenseUrl is set
|
||||
DefaultDrmSessionManager<FrameworkMediaCrypto> drmSessionManager = null;
|
||||
if (drmLicenseUrl != null && drmLicenseUrl.length() > 0) {
|
||||
try {
|
||||
drmSessionManager = buildDrmSessionManagerV18(context,
|
||||
Util.getDrmUuid("widevine"), drmLicenseUrl, null, false);
|
||||
} catch (UnsupportedDrmException e) {
|
||||
Log.e(TAG, "Unsupported DRM!", e);
|
||||
}
|
||||
}
|
||||
|
||||
// This is the MediaSource representing the media to be played.
|
||||
MediaSource videoSource = buildMediaSource(context, uri, null, dataSourceFactory);
|
||||
|
||||
Log.d(TAG, "Requested play of " +filePath + " uri: "+uri.toString());
|
||||
|
||||
// 2. Create the player
|
||||
//--------------------------------------
|
||||
//- Audio Engine
|
||||
if (engine == null)
|
||||
{
|
||||
engine = AudioEngine.create(SAMPLE_RATE, BUFFER_SIZE, QUEUE_SIZE_IN_SAMPLES, context);
|
||||
spat = engine.createSpatDecoderQueue();
|
||||
engine.start();
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
//- ExoPlayer
|
||||
|
||||
// Create our modified ExoPlayer instance
|
||||
if (exoPlayer != null)
|
||||
{
|
||||
exoPlayer.release();
|
||||
}
|
||||
exoPlayer = ExoPlayerFactory.newSimpleInstance(context, new CustomRenderersFactory(context), trackSelector, drmSessionManager);
|
||||
|
||||
|
||||
exoPlayer.addListener(new Player.DefaultEventListener() {
|
||||
|
||||
@Override
|
||||
public void onPlayerStateChanged(boolean playWhenReady, int playbackState)
|
||||
{
|
||||
isPlaying = playWhenReady && (playbackState == Player.STATE_READY || playbackState == Player.STATE_BUFFERING);
|
||||
currentPlaybackState = playbackState;
|
||||
|
||||
updatePlaybackState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlaybackParametersChanged(PlaybackParameters params)
|
||||
{
|
||||
updatePlaybackState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPositionDiscontinuity(int reason)
|
||||
{
|
||||
updatePlaybackState();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
exoPlayer.setVideoSurface( surface );
|
||||
|
||||
// Prepare the player with the source.
|
||||
exoPlayer.prepare(videoSource);
|
||||
|
||||
|
||||
exoPlayer.setPlayWhenReady( true );
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void setLooping(final boolean looping)
|
||||
{
|
||||
getHandler().post( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if ( exoPlayer != null )
|
||||
{
|
||||
if ( looping )
|
||||
{
|
||||
exoPlayer.setRepeatMode( Player.REPEAT_MODE_ONE );
|
||||
}
|
||||
else
|
||||
{
|
||||
exoPlayer.setRepeatMode( Player.REPEAT_MODE_OFF );
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void stop()
|
||||
{
|
||||
getHandler().post( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if ( exoPlayer != null )
|
||||
{
|
||||
exoPlayer.stop();
|
||||
exoPlayer.release();
|
||||
exoPlayer = null;
|
||||
}
|
||||
if ( mediaDrm != null) {
|
||||
mediaDrm.release();
|
||||
mediaDrm = null;
|
||||
}
|
||||
if (engine != null)
|
||||
{
|
||||
engine.destroySpatDecoderQueue(spat);
|
||||
engine.delete();
|
||||
spat = null;
|
||||
engine = null;
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void pause()
|
||||
{
|
||||
getHandler().post( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if ( exoPlayer != null )
|
||||
{
|
||||
exoPlayer.setPlayWhenReady(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void resume()
|
||||
{
|
||||
getHandler().post( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if ( exoPlayer != null )
|
||||
{
|
||||
exoPlayer.setPlayWhenReady(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void setPlaybackSpeed(final float speed)
|
||||
{
|
||||
getHandler().post( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if ( exoPlayer != null )
|
||||
{
|
||||
PlaybackParameters param = new PlaybackParameters(speed);
|
||||
exoPlayer.setPlaybackParameters(param);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public static void setListenerRotationQuaternion(float x, float y, float z, float w)
|
||||
{
|
||||
if (engine != null)
|
||||
{
|
||||
engine.setListenerRotation(new TBQuat(x,y,z,w));
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean getIsPlaying()
|
||||
{
|
||||
return isPlaying;
|
||||
}
|
||||
|
||||
public static int getCurrentPlaybackState()
|
||||
{
|
||||
return currentPlaybackState;
|
||||
}
|
||||
|
||||
public static long getDuration()
|
||||
{
|
||||
return duration;
|
||||
}
|
||||
|
||||
public static long getPlaybackPosition()
|
||||
{
|
||||
return Math.max(0, Math.min(duration, lastPlaybackPosition + (long)((System.currentTimeMillis() - lastPlaybackUpdateTime) * lastPlaybackSpeed)));
|
||||
}
|
||||
|
||||
public static void setPlaybackPosition(final long position)
|
||||
{
|
||||
getHandler().post( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if ( exoPlayer != null )
|
||||
{
|
||||
Timeline timeline = exoPlayer.getCurrentTimeline();
|
||||
if ( timeline != null )
|
||||
{
|
||||
int windowIndex = timeline.getFirstWindowIndex(false);
|
||||
long windowPositionUs = position * 1000L;
|
||||
Timeline.Window tmpWindow = new Timeline.Window();
|
||||
for(int i = timeline.getFirstWindowIndex(false);
|
||||
i < timeline.getLastWindowIndex(false); i++)
|
||||
{
|
||||
timeline.getWindow(i, tmpWindow);
|
||||
|
||||
if (tmpWindow.durationUs > windowPositionUs)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
windowIndex++;
|
||||
windowPositionUs -= tmpWindow.durationUs;
|
||||
}
|
||||
|
||||
exoPlayer.seekTo(windowIndex, windowPositionUs / 1000L);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0d7c62804c0fce54b8d0e82ad854713b
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Android: Android
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c178d2dd5c1974842b2c64b78dfc1693
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,22 +0,0 @@
|
||||
/************************************************************************************
|
||||
|
||||
Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
|
||||
|
||||
************************************************************************************/
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
public class ButtonDownListener : MonoBehaviour, UnityEngine.EventSystems.IPointerDownHandler
|
||||
{
|
||||
public event System.Action onButtonDown;
|
||||
|
||||
public void OnPointerDown(PointerEventData eventData)
|
||||
{
|
||||
if (onButtonDown != null)
|
||||
{
|
||||
onButtonDown.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7185ca706364c3546a56069a45a679f6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,165 +0,0 @@
|
||||
/************************************************************************************
|
||||
|
||||
Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
|
||||
|
||||
************************************************************************************/
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class MediaPlayerImage : Image
|
||||
{
|
||||
public enum ButtonType
|
||||
{
|
||||
Play,
|
||||
Pause,
|
||||
FastForward,
|
||||
Rewind,
|
||||
SkipForward,
|
||||
SkipBack,
|
||||
Stop
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private ButtonType m_ButtonType;
|
||||
public ButtonType buttonType
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_ButtonType;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (m_ButtonType != value)
|
||||
{
|
||||
m_ButtonType = value;
|
||||
SetAllDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPopulateMesh(VertexHelper toFill)
|
||||
{
|
||||
var r = GetPixelAdjustedRect();
|
||||
var v = new Vector4(r.x, r.y, r.x + r.width, r.y + r.height);
|
||||
|
||||
Color32 color32 = color;
|
||||
toFill.Clear();
|
||||
|
||||
switch(m_ButtonType)
|
||||
{
|
||||
case ButtonType.Play:
|
||||
{
|
||||
toFill.AddVert(new Vector3(v.x, v.y), color32, new Vector2(0f, 0f));
|
||||
toFill.AddVert(new Vector3(v.x, v.w), color32, new Vector2(0f, 1f));
|
||||
toFill.AddVert(new Vector3(v.z, Mathf.Lerp(v.y, v.w, 0.5f)), color32, new Vector2(1f, 0.5f));
|
||||
toFill.AddTriangle(0, 1, 2);
|
||||
}
|
||||
break;
|
||||
|
||||
case ButtonType.Pause:
|
||||
{
|
||||
const float PAUSE_BAR_WIDTH = 0.35f;
|
||||
toFill.AddVert(new Vector3(v.x, v.y), color32, new Vector2(0f, 0f));
|
||||
toFill.AddVert(new Vector3(v.x, v.w), color32, new Vector2(0f, 1f));
|
||||
toFill.AddVert(new Vector3(Mathf.Lerp(v.x, v.z, PAUSE_BAR_WIDTH), v.w), color32, new Vector2(PAUSE_BAR_WIDTH, 1f));
|
||||
toFill.AddVert(new Vector3(Mathf.Lerp(v.x, v.z, PAUSE_BAR_WIDTH), v.y), color32, new Vector2(PAUSE_BAR_WIDTH, 0f));
|
||||
|
||||
toFill.AddVert(new Vector3(Mathf.Lerp(v.x, v.z, 1 - PAUSE_BAR_WIDTH), v.y), color32, new Vector2(1 - PAUSE_BAR_WIDTH, 0f));
|
||||
toFill.AddVert(new Vector3(Mathf.Lerp(v.x, v.z, 1 - PAUSE_BAR_WIDTH), v.w), color32, new Vector2(1 - PAUSE_BAR_WIDTH, 1f));
|
||||
toFill.AddVert(new Vector3(v.z, v.w), color32, new Vector2(1f, 1f));
|
||||
toFill.AddVert(new Vector3(v.z, v.y), color32, new Vector2(1f, 0f));
|
||||
|
||||
toFill.AddTriangle(0, 1, 2);
|
||||
toFill.AddTriangle(2, 3, 0);
|
||||
toFill.AddTriangle(4, 5, 6);
|
||||
toFill.AddTriangle(6, 7, 4);
|
||||
}
|
||||
break;
|
||||
case ButtonType.FastForward:
|
||||
{
|
||||
toFill.AddVert(new Vector3(v.x, v.y), color32, new Vector2(0f, 0f));
|
||||
toFill.AddVert(new Vector3(v.x, v.w), color32, new Vector2(0f, 1f));
|
||||
toFill.AddVert(new Vector3(Mathf.Lerp(v.x, v.z, 0.5f), Mathf.Lerp(v.y, v.w, 0.5f)), color32, new Vector2(0.5f, 0.5f));
|
||||
|
||||
toFill.AddVert(new Vector3(Mathf.Lerp(v.x, v.z, 0.5f), v.y), color32, new Vector2(0.5f, 0f));
|
||||
toFill.AddVert(new Vector3(Mathf.Lerp(v.x, v.z, 0.5f), v.w), color32, new Vector2(0.5f, 1f));
|
||||
toFill.AddVert(new Vector3(v.z, Mathf.Lerp(v.y, v.w, 0.5f)), color32, new Vector2(1f, 0.5f));
|
||||
toFill.AddTriangle(0, 1, 2);
|
||||
toFill.AddTriangle(3, 4, 5);
|
||||
}
|
||||
break;
|
||||
case ButtonType.Rewind:
|
||||
{
|
||||
toFill.AddVert(new Vector3(v.x, Mathf.Lerp(v.y, v.w, 0.5f)), color32, new Vector2(0f, 0.5f));
|
||||
toFill.AddVert(new Vector3(Mathf.Lerp(v.x, v.z, 0.5f), v.w), color32, new Vector2(0.5f, 1f));
|
||||
toFill.AddVert(new Vector3(Mathf.Lerp(v.x, v.z, 0.5f), v.y), color32, new Vector2(0.5f, 0f));
|
||||
|
||||
toFill.AddVert(new Vector3(Mathf.Lerp(v.x, v.z, 0.5f), Mathf.Lerp(v.y, v.w, 0.5f)), color32, new Vector2(0.5f, 0.5f));
|
||||
toFill.AddVert(new Vector3(v.z, v.w), color32, new Vector2(1f, 1f));
|
||||
toFill.AddVert(new Vector3(v.z, v.y), color32, new Vector2(1f, 0f));
|
||||
toFill.AddTriangle(0, 1, 2);
|
||||
toFill.AddTriangle(3, 4, 5);
|
||||
}
|
||||
break;
|
||||
case ButtonType.SkipForward:
|
||||
{
|
||||
const float SKIP_FORWARD_BAR_WIDTH = 0.125f;
|
||||
|
||||
toFill.AddVert(new Vector3(v.x, v.y), color32, new Vector2(0f, 0f));
|
||||
toFill.AddVert(new Vector3(v.x, v.w), color32, new Vector2(0f, 1f));
|
||||
toFill.AddVert(new Vector3(Mathf.Lerp(v.x, v.z, 0.5f - SKIP_FORWARD_BAR_WIDTH / 2), Mathf.Lerp(v.y, v.w, 0.5f)), color32, new Vector2(0.5f - SKIP_FORWARD_BAR_WIDTH / 2, 0.5f));
|
||||
|
||||
toFill.AddVert(new Vector3(Mathf.Lerp(v.x, v.z, 0.5f - SKIP_FORWARD_BAR_WIDTH / 2), v.y), color32, new Vector2(0.5f - SKIP_FORWARD_BAR_WIDTH / 2, 0f));
|
||||
toFill.AddVert(new Vector3(Mathf.Lerp(v.x, v.z, 0.5f - SKIP_FORWARD_BAR_WIDTH / 2), v.w), color32, new Vector2(0.5f - SKIP_FORWARD_BAR_WIDTH / 2, 1f));
|
||||
toFill.AddVert(new Vector3(Mathf.Lerp(v.x, v.z, 1 - SKIP_FORWARD_BAR_WIDTH), Mathf.Lerp(v.y, v.w, 0.5f)), color32, new Vector2(1f - SKIP_FORWARD_BAR_WIDTH, 0.5f));
|
||||
|
||||
toFill.AddVert(new Vector3(Mathf.Lerp(v.x, v.z, 1 - SKIP_FORWARD_BAR_WIDTH), v.y), color32, new Vector2(1 - SKIP_FORWARD_BAR_WIDTH, 0f));
|
||||
toFill.AddVert(new Vector3(Mathf.Lerp(v.x, v.z, 1 - SKIP_FORWARD_BAR_WIDTH), v.w), color32, new Vector2(1 - SKIP_FORWARD_BAR_WIDTH, 1f));
|
||||
toFill.AddVert(new Vector3(v.z, v.w), color32, new Vector2(1f, 1f));
|
||||
toFill.AddVert(new Vector3(v.z, v.y), color32, new Vector2(1f, 0f));
|
||||
|
||||
toFill.AddTriangle(0, 1, 2);
|
||||
toFill.AddTriangle(3, 4, 5);
|
||||
toFill.AddTriangle(6, 7, 8);
|
||||
toFill.AddTriangle(8, 9, 6);
|
||||
}
|
||||
break;
|
||||
case ButtonType.SkipBack:
|
||||
{
|
||||
const float SKIP_BACK_BAR_WIDTH = 0.125f;
|
||||
toFill.AddVert(new Vector3(v.x, v.y), color32, new Vector2(0f, 0f));
|
||||
toFill.AddVert(new Vector3(v.x, v.w), color32, new Vector2(0f, 1f));
|
||||
toFill.AddVert(new Vector3(Mathf.Lerp(v.x, v.z, SKIP_BACK_BAR_WIDTH), v.w), color32, new Vector2(SKIP_BACK_BAR_WIDTH, 1f));
|
||||
toFill.AddVert(new Vector3(Mathf.Lerp(v.x, v.z, SKIP_BACK_BAR_WIDTH), v.y), color32, new Vector2(SKIP_BACK_BAR_WIDTH, 0f));
|
||||
|
||||
toFill.AddVert(new Vector3(Mathf.Lerp(v.x, v.z, SKIP_BACK_BAR_WIDTH), Mathf.Lerp(v.y, v.w, 0.5f)), color32, new Vector2(SKIP_BACK_BAR_WIDTH, 0.5f));
|
||||
toFill.AddVert(new Vector3(Mathf.Lerp(v.x, v.z, 0.5f + SKIP_BACK_BAR_WIDTH / 2), v.w), color32, new Vector2(0.5f + SKIP_BACK_BAR_WIDTH / 2, 1f));
|
||||
toFill.AddVert(new Vector3(Mathf.Lerp(v.x, v.z, 0.5f + SKIP_BACK_BAR_WIDTH / 2), v.y), color32, new Vector2(0.5f + SKIP_BACK_BAR_WIDTH / 2, 0f));
|
||||
|
||||
toFill.AddVert(new Vector3(Mathf.Lerp(v.x, v.z, 0.5f + SKIP_BACK_BAR_WIDTH / 2), Mathf.Lerp(v.y, v.w, 0.5f)), color32, new Vector2(0.5f + SKIP_BACK_BAR_WIDTH / 2, 0.5f));
|
||||
toFill.AddVert(new Vector3(v.z, v.w), color32, new Vector2(1f, 1f));
|
||||
toFill.AddVert(new Vector3(v.z, v.y), color32, new Vector2(1f, 0f));
|
||||
|
||||
toFill.AddTriangle(0, 1, 2);
|
||||
toFill.AddTriangle(2, 3, 0);
|
||||
toFill.AddTriangle(4, 5, 6);
|
||||
toFill.AddTriangle(7, 8, 9);
|
||||
}
|
||||
break;
|
||||
case ButtonType.Stop:
|
||||
default: // by default draw a stop symbol (which just so happens to be square)
|
||||
{
|
||||
toFill.AddVert(new Vector3(v.x, v.y), color32, new Vector2(0f, 0f));
|
||||
toFill.AddVert(new Vector3(v.x, v.w), color32, new Vector2(0f, 1f));
|
||||
toFill.AddVert(new Vector3(v.z, v.w), color32, new Vector2(1f, 1f));
|
||||
toFill.AddVert(new Vector3(v.z, v.y), color32, new Vector2(1f, 0f));
|
||||
|
||||
toFill.AddTriangle(0, 1, 2);
|
||||
toFill.AddTriangle(2, 3, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 08eed4f8f3d96954a9333eecf0c95cef
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,358 +0,0 @@
|
||||
/************************************************************************************
|
||||
|
||||
Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
|
||||
|
||||
************************************************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
public class MoviePlayerSample : MonoBehaviour
|
||||
{
|
||||
private bool videoPausedBeforeAppPause = false;
|
||||
|
||||
private UnityEngine.Video.VideoPlayer videoPlayer = null;
|
||||
private OVROverlay overlay = null;
|
||||
private Renderer mediaRenderer = null;
|
||||
|
||||
public bool IsPlaying { get; private set; }
|
||||
public long Duration { get; private set; }
|
||||
public long PlaybackPosition { get; private set; }
|
||||
|
||||
private RenderTexture copyTexture;
|
||||
private Material externalTex2DMaterial;
|
||||
|
||||
public string MovieName;
|
||||
public string DrmLicenseUrl;
|
||||
public bool LoopVideo;
|
||||
public VideoShape Shape;
|
||||
public VideoStereo Stereo;
|
||||
public bool DisplayMono;
|
||||
|
||||
// keep track of last state so we know when to update our display
|
||||
VideoShape _LastShape = (VideoShape)(-1);
|
||||
VideoStereo _LastStereo = (VideoStereo)(-1);
|
||||
bool _LastDisplayMono = false;
|
||||
|
||||
public enum VideoShape
|
||||
{
|
||||
_360,
|
||||
_180,
|
||||
Quad
|
||||
}
|
||||
|
||||
public enum VideoStereo
|
||||
{
|
||||
Mono,
|
||||
TopBottom,
|
||||
LeftRight,
|
||||
BottomTop
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialization of the movie surface
|
||||
/// </summary>
|
||||
void Awake()
|
||||
{
|
||||
Debug.Log("MovieSample Awake");
|
||||
|
||||
mediaRenderer = GetComponent<Renderer>();
|
||||
|
||||
videoPlayer = GetComponent<UnityEngine.Video.VideoPlayer>();
|
||||
if (videoPlayer == null)
|
||||
videoPlayer = gameObject.AddComponent<UnityEngine.Video.VideoPlayer>();
|
||||
videoPlayer.isLooping = LoopVideo;
|
||||
|
||||
overlay = GetComponent<OVROverlay>();
|
||||
if (overlay == null)
|
||||
overlay = gameObject.AddComponent<OVROverlay>();
|
||||
|
||||
// disable it to reset it.
|
||||
overlay.enabled = false;
|
||||
// only can use external surface with native plugin
|
||||
overlay.isExternalSurface = NativeVideoPlayer.IsAvailable;
|
||||
// only mobile has Equirect shape
|
||||
overlay.enabled = (overlay.currentOverlayShape != OVROverlay.OverlayShape.Equirect || Application.platform == RuntimePlatform.Android);
|
||||
|
||||
#if UNITY_EDITOR
|
||||
overlay.currentOverlayShape = OVROverlay.OverlayShape.Quad;
|
||||
overlay.enabled = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
private bool IsLocalVideo(string movieName)
|
||||
{
|
||||
// if the path contains any url scheme, it is not local
|
||||
return !movieName.Contains("://");
|
||||
}
|
||||
|
||||
private void UpdateShapeAndStereo()
|
||||
{
|
||||
if (Shape != _LastShape || Stereo != _LastStereo || DisplayMono != _LastDisplayMono)
|
||||
{
|
||||
Rect destRect = new Rect(0, 0, 1, 1);
|
||||
switch (Shape)
|
||||
{
|
||||
case VideoShape._360:
|
||||
// set shape to Equirect
|
||||
overlay.currentOverlayShape = OVROverlay.OverlayShape.Equirect;
|
||||
break;
|
||||
case VideoShape._180:
|
||||
overlay.currentOverlayShape = OVROverlay.OverlayShape.Equirect;
|
||||
destRect = new Rect(0.25f, 0, 0.5f, 1.0f);
|
||||
break;
|
||||
case VideoShape.Quad:
|
||||
default:
|
||||
overlay.currentOverlayShape = OVROverlay.OverlayShape.Quad;
|
||||
break;
|
||||
}
|
||||
|
||||
overlay.overrideTextureRectMatrix = true;
|
||||
|
||||
Rect sourceLeft = new Rect(0, 0, 1, 1);
|
||||
Rect sourceRight = new Rect(0, 0, 1, 1);
|
||||
switch (Stereo)
|
||||
{
|
||||
case VideoStereo.LeftRight:
|
||||
// set source matrices for left/right
|
||||
sourceLeft = new Rect(0.0f, 0.0f, 0.5f, 1.0f);
|
||||
sourceRight = new Rect(0.5f, 0.0f, 0.5f, 1.0f);
|
||||
break;
|
||||
case VideoStereo.TopBottom:
|
||||
// set source matrices for top/bottom
|
||||
sourceLeft = new Rect(0.0f, 0.5f, 1.0f, 0.5f);
|
||||
sourceRight = new Rect(0.0f, 0.0f, 1.0f, 0.5f);
|
||||
break;
|
||||
case VideoStereo.BottomTop:
|
||||
// set source matrices for top/bottom
|
||||
sourceLeft = new Rect(0.0f, 0.0f, 1.0f, 0.5f);
|
||||
sourceRight = new Rect(0.0f, 0.5f, 1.0f, 0.5f);
|
||||
break;
|
||||
}
|
||||
|
||||
overlay.invertTextureRects = false;
|
||||
overlay.SetSrcDestRects(sourceLeft, DisplayMono ? sourceLeft : sourceRight, destRect, destRect);
|
||||
|
||||
_LastDisplayMono = DisplayMono;
|
||||
_LastStereo = Stereo;
|
||||
_LastShape = Shape;
|
||||
}
|
||||
}
|
||||
|
||||
private System.Collections.IEnumerator Start()
|
||||
{
|
||||
if (mediaRenderer.material == null)
|
||||
{
|
||||
Debug.LogError("No material for movie surface");
|
||||
yield break;
|
||||
}
|
||||
|
||||
// wait 1 second to start (there is a bug in Unity where starting
|
||||
// the video too soon will cause it to fail to load)
|
||||
yield return new WaitForSeconds(1.0f);
|
||||
|
||||
if (!string.IsNullOrEmpty(MovieName))
|
||||
{
|
||||
if (IsLocalVideo(MovieName))
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
// in editor, just pull in the movie file from wherever it lives (to test without putting in streaming assets)
|
||||
var guids = UnityEditor.AssetDatabase.FindAssets(Path.GetFileNameWithoutExtension(MovieName));
|
||||
|
||||
if (guids.Length > 0)
|
||||
{
|
||||
string video = UnityEditor.AssetDatabase.GUIDToAssetPath(guids[0]);
|
||||
Play(video, null);
|
||||
}
|
||||
#else
|
||||
Play(Application.streamingAssetsPath +"/" + MovieName, null);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
Play(MovieName, DrmLicenseUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Play(string moviePath, string drmLicencesUrl)
|
||||
{
|
||||
if (moviePath != string.Empty)
|
||||
{
|
||||
Debug.Log("Playing Video: " + moviePath);
|
||||
if (overlay.isExternalSurface)
|
||||
{
|
||||
OVROverlay.ExternalSurfaceObjectCreated surfaceCreatedCallback = () =>
|
||||
{
|
||||
Debug.Log("Playing ExoPlayer with SurfaceObject");
|
||||
NativeVideoPlayer.PlayVideo(moviePath, drmLicencesUrl, overlay.externalSurfaceObject);
|
||||
NativeVideoPlayer.SetLooping(LoopVideo);
|
||||
};
|
||||
|
||||
if (overlay.externalSurfaceObject == IntPtr.Zero)
|
||||
{
|
||||
overlay.externalSurfaceObjectCreated = surfaceCreatedCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
surfaceCreatedCallback.Invoke();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("Playing Unity VideoPlayer");
|
||||
videoPlayer.url = moviePath;
|
||||
videoPlayer.Prepare();
|
||||
videoPlayer.Play();
|
||||
}
|
||||
|
||||
Debug.Log("MovieSample Start");
|
||||
IsPlaying = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("No media file name provided");
|
||||
}
|
||||
}
|
||||
|
||||
public void Play()
|
||||
{
|
||||
if (overlay.isExternalSurface)
|
||||
{
|
||||
NativeVideoPlayer.Play();
|
||||
}
|
||||
else
|
||||
{
|
||||
videoPlayer.Play();
|
||||
}
|
||||
IsPlaying = true;
|
||||
}
|
||||
|
||||
public void Pause()
|
||||
{
|
||||
if (overlay.isExternalSurface)
|
||||
{
|
||||
NativeVideoPlayer.Pause();
|
||||
}
|
||||
else
|
||||
{
|
||||
videoPlayer.Pause();
|
||||
}
|
||||
IsPlaying = false;
|
||||
}
|
||||
|
||||
public void SeekTo(long position)
|
||||
{
|
||||
long seekPos = Math.Max(0, Math.Min(Duration, position));
|
||||
if (overlay.isExternalSurface)
|
||||
{
|
||||
NativeVideoPlayer.PlaybackPosition = seekPos;
|
||||
}
|
||||
else
|
||||
{
|
||||
videoPlayer.time = seekPos / 1000.0;
|
||||
}
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
UpdateShapeAndStereo();
|
||||
if (!overlay.isExternalSurface)
|
||||
{
|
||||
var displayTexture = videoPlayer.texture != null ? videoPlayer.texture : Texture2D.blackTexture;
|
||||
if (overlay.enabled)
|
||||
{
|
||||
if (overlay.textures[0] != displayTexture)
|
||||
{
|
||||
// OVROverlay won't check if the texture changed, so disable to clear old texture
|
||||
overlay.enabled = false;
|
||||
overlay.textures[0] = displayTexture;
|
||||
overlay.enabled = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mediaRenderer.material.mainTexture = displayTexture;
|
||||
mediaRenderer.material.SetVector("_SrcRectLeft", overlay.srcRectLeft.ToVector());
|
||||
mediaRenderer.material.SetVector("_SrcRectRight", overlay.srcRectRight.ToVector());
|
||||
}
|
||||
IsPlaying = videoPlayer.isPlaying;
|
||||
PlaybackPosition = (long)(videoPlayer.time * 1000L);
|
||||
|
||||
#if UNITY_2019_1_OR_NEWER
|
||||
Duration = (long)(videoPlayer.length * 1000L);
|
||||
#else
|
||||
Duration = videoPlayer.frameRate > 0 ? (long)(videoPlayer.frameCount / videoPlayer.frameRate * 1000L) : 0L;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
NativeVideoPlayer.SetListenerRotation(Camera.main.transform.rotation);
|
||||
IsPlaying = NativeVideoPlayer.IsPlaying;
|
||||
PlaybackPosition = NativeVideoPlayer.PlaybackPosition;
|
||||
Duration = NativeVideoPlayer.Duration;
|
||||
if (IsPlaying && (int)OVRManager.display.displayFrequency != 60)
|
||||
{
|
||||
OVRManager.display.displayFrequency = 60.0f;
|
||||
}
|
||||
else if (!IsPlaying && (int)OVRManager.display.displayFrequency != 72)
|
||||
{
|
||||
OVRManager.display.displayFrequency = 72.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetPlaybackSpeed(float speed)
|
||||
{
|
||||
// clamp at 0
|
||||
speed = Mathf.Max(0, speed);
|
||||
if (overlay.isExternalSurface)
|
||||
{
|
||||
NativeVideoPlayer.SetPlaybackSpeed(speed);
|
||||
}
|
||||
else
|
||||
{
|
||||
videoPlayer.playbackSpeed = speed;
|
||||
}
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
if (overlay.isExternalSurface)
|
||||
{
|
||||
NativeVideoPlayer.Stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
videoPlayer.Stop();
|
||||
}
|
||||
|
||||
IsPlaying = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pauses video playback when the app loses or gains focus
|
||||
/// </summary>
|
||||
void OnApplicationPause(bool appWasPaused)
|
||||
{
|
||||
Debug.Log("OnApplicationPause: " + appWasPaused);
|
||||
if (appWasPaused)
|
||||
{
|
||||
videoPausedBeforeAppPause = !IsPlaying;
|
||||
}
|
||||
|
||||
// Pause/unpause the video only if it had been playing prior to app pause
|
||||
if (!videoPausedBeforeAppPause)
|
||||
{
|
||||
if (appWasPaused)
|
||||
{
|
||||
Pause();
|
||||
}
|
||||
else
|
||||
{
|
||||
Play();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6b666ca80b3aa42efac718fe4903bff5
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -1,238 +0,0 @@
|
||||
/************************************************************************************
|
||||
|
||||
Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
|
||||
|
||||
************************************************************************************/
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class MoviePlayerSampleControls : MonoBehaviour
|
||||
{
|
||||
public MoviePlayerSample Player;
|
||||
|
||||
public UnityEngine.EventSystems.OVRInputModule InputModule;
|
||||
public OVRGazePointer GazePointer;
|
||||
|
||||
public GameObject LeftHand;
|
||||
public GameObject RightHand;
|
||||
|
||||
public Canvas Canvas;
|
||||
public ButtonDownListener PlayPause;
|
||||
public MediaPlayerImage PlayPauseImage;
|
||||
public Slider ProgressBar;
|
||||
public ButtonDownListener FastForward;
|
||||
public MediaPlayerImage FastForwardImage;
|
||||
public ButtonDownListener Rewind;
|
||||
public MediaPlayerImage RewindImage;
|
||||
|
||||
public float TimeoutTime = 10f;
|
||||
|
||||
private bool _isVisible = false;
|
||||
|
||||
private float _lastButtonTime = 0f;
|
||||
|
||||
private bool _didSeek = false;
|
||||
private long _seekPreviousPosition;
|
||||
|
||||
private long _rewindStartPosition;
|
||||
private float _rewindStartTime;
|
||||
|
||||
private enum PlaybackState
|
||||
{
|
||||
Playing,
|
||||
Paused,
|
||||
Rewinding,
|
||||
FastForwarding
|
||||
}
|
||||
|
||||
private PlaybackState _state = PlaybackState.Playing;
|
||||
|
||||
|
||||
void Start()
|
||||
{
|
||||
PlayPause.onButtonDown += OnPlayPauseClicked;
|
||||
FastForward.onButtonDown += OnFastForwardClicked;
|
||||
Rewind.onButtonDown += OnRewindClicked;
|
||||
ProgressBar.onValueChanged.AddListener(OnSeekBarMoved);
|
||||
|
||||
PlayPauseImage.buttonType = MediaPlayerImage.ButtonType.Pause;
|
||||
FastForwardImage.buttonType = MediaPlayerImage.ButtonType.SkipForward;
|
||||
RewindImage.buttonType = MediaPlayerImage.ButtonType.SkipBack;
|
||||
SetVisible(false);
|
||||
}
|
||||
|
||||
void OnPlayPauseClicked()
|
||||
{
|
||||
switch(_state)
|
||||
{
|
||||
case PlaybackState.Paused:
|
||||
Player.Play();
|
||||
PlayPauseImage.buttonType = MediaPlayerImage.ButtonType.Pause;
|
||||
FastForwardImage.buttonType = MediaPlayerImage.ButtonType.FastForward;
|
||||
RewindImage.buttonType = MediaPlayerImage.ButtonType.Rewind;
|
||||
_state = PlaybackState.Playing;
|
||||
break;
|
||||
case PlaybackState.Playing:
|
||||
Player.Pause();
|
||||
PlayPauseImage.buttonType = MediaPlayerImage.ButtonType.Play;
|
||||
FastForwardImage.buttonType = MediaPlayerImage.ButtonType.SkipForward;
|
||||
RewindImage.buttonType = MediaPlayerImage.ButtonType.SkipBack;
|
||||
_state = PlaybackState.Paused;
|
||||
break;
|
||||
case PlaybackState.FastForwarding:
|
||||
Player.SetPlaybackSpeed(1);
|
||||
PlayPauseImage.buttonType = MediaPlayerImage.ButtonType.Pause;
|
||||
_state = PlaybackState.Playing;
|
||||
break;
|
||||
case PlaybackState.Rewinding:
|
||||
Player.Play();
|
||||
_state = PlaybackState.Playing;
|
||||
PlayPauseImage.buttonType = MediaPlayerImage.ButtonType.Pause;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OnFastForwardClicked()
|
||||
{
|
||||
switch(_state)
|
||||
{
|
||||
case PlaybackState.FastForwarding:
|
||||
Player.SetPlaybackSpeed(1);
|
||||
_state = PlaybackState.Playing;
|
||||
PlayPauseImage.buttonType = MediaPlayerImage.ButtonType.Pause;
|
||||
break;
|
||||
case PlaybackState.Rewinding:
|
||||
Player.Play();
|
||||
Player.SetPlaybackSpeed(2);
|
||||
_state = PlaybackState.FastForwarding;
|
||||
break;
|
||||
case PlaybackState.Playing:
|
||||
Player.SetPlaybackSpeed(2);
|
||||
PlayPauseImage.buttonType = MediaPlayerImage.ButtonType.Play;
|
||||
_state = PlaybackState.FastForwarding;
|
||||
break;
|
||||
case PlaybackState.Paused:
|
||||
// skip ahead 15 seconds
|
||||
Seek(Player.PlaybackPosition + 15000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OnRewindClicked()
|
||||
{
|
||||
switch (_state)
|
||||
{
|
||||
case PlaybackState.FastForwarding:
|
||||
case PlaybackState.Playing:
|
||||
Player.SetPlaybackSpeed(1);
|
||||
Player.Pause();
|
||||
// Player's do not support negative speed. Instead, we need to seek step by step
|
||||
_rewindStartPosition = Player.PlaybackPosition;
|
||||
_rewindStartTime = Time.time;
|
||||
PlayPauseImage.buttonType = MediaPlayerImage.ButtonType.Play;
|
||||
_state = PlaybackState.Rewinding;
|
||||
break;
|
||||
case PlaybackState.Rewinding:
|
||||
Player.Play();
|
||||
PlayPauseImage.buttonType = MediaPlayerImage.ButtonType.Pause;
|
||||
_state = PlaybackState.Playing;
|
||||
break;
|
||||
case PlaybackState.Paused:
|
||||
// skip ahead 15 seconds
|
||||
Seek(Player.PlaybackPosition - 15000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OnSeekBarMoved(float value)
|
||||
{
|
||||
long newPos = (long)(value * Player.Duration);
|
||||
|
||||
// only seek if the position changed more than 200ms
|
||||
if (Mathf.Abs(newPos - Player.PlaybackPosition) > 200)
|
||||
{
|
||||
Seek(newPos);
|
||||
}
|
||||
}
|
||||
|
||||
private void Seek(long pos)
|
||||
{
|
||||
_didSeek = true;
|
||||
_seekPreviousPosition = Player.PlaybackPosition;
|
||||
Player.SeekTo(pos);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if(OVRInput.Get(OVRInput.Button.One) || OVRInput.Get(OVRInput.Button.PrimaryIndexTrigger) || OVRInput.Get(OVRInput.Button.SecondaryIndexTrigger))
|
||||
{
|
||||
_lastButtonTime = Time.time;
|
||||
if (!_isVisible)
|
||||
{
|
||||
SetVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (OVRInput.GetActiveController() == OVRInput.Controller.LTouch)
|
||||
{
|
||||
InputModule.rayTransform = LeftHand.transform;
|
||||
GazePointer.rayTransform = LeftHand.transform;
|
||||
}
|
||||
else
|
||||
{
|
||||
InputModule.rayTransform = RightHand.transform;
|
||||
GazePointer.rayTransform = RightHand.transform;
|
||||
}
|
||||
|
||||
// if back is pressed, hide controls immediately
|
||||
if (OVRInput.Get(OVRInput.Button.Back))
|
||||
{
|
||||
if (_isVisible)
|
||||
{
|
||||
SetVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (_state == PlaybackState.Rewinding)
|
||||
{
|
||||
// smoothly update our seekbar
|
||||
ProgressBar.value = Mathf.Clamp01((_rewindStartPosition - 1000L * (Time.time - _rewindStartTime)) / Player.Duration);
|
||||
}
|
||||
|
||||
// if we are playing, hide the controls after 15 seconds
|
||||
if (_isVisible && _state == PlaybackState.Playing && Time.time - _lastButtonTime > TimeoutTime)
|
||||
{
|
||||
SetVisible(false);
|
||||
}
|
||||
|
||||
if (_isVisible)
|
||||
{
|
||||
if (!_didSeek || Mathf.Abs(_seekPreviousPosition - Player.PlaybackPosition) > 50)
|
||||
{
|
||||
_didSeek = false;
|
||||
|
||||
if (Player.Duration > 0)
|
||||
{
|
||||
// update our progress bar
|
||||
ProgressBar.value = (float)(Player.PlaybackPosition / (double)Player.Duration);
|
||||
}
|
||||
else
|
||||
{
|
||||
ProgressBar.value = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetVisible(bool visible)
|
||||
{
|
||||
Canvas.enabled = visible;
|
||||
_isVisible = visible;
|
||||
Player.DisplayMono = visible;
|
||||
LeftHand.SetActive(visible);
|
||||
RightHand.SetActive(visible);
|
||||
Debug.Log("Controls Visible: " + visible);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cad3c6e64a3c5834a95b9586a5947678
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,17 +0,0 @@
|
||||
/************************************************************************************
|
||||
|
||||
Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
|
||||
|
||||
************************************************************************************/
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public static class VectorUtil {
|
||||
|
||||
public static Vector4 ToVector(this Rect rect)
|
||||
{
|
||||
return new Vector4(rect.x, rect.y, rect.width, rect.height);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1eaf72ebb00dbb3429d4b6f661947a04
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ff553a5920330cd4692d8f69f021d55b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,68 +0,0 @@
|
||||
Shader "Unlit/Multiview Stereo"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
_MainTex ("Texture", 2D) = "white" {}
|
||||
_SrcRectLeft("SrcRectLeft", Vector) = (0,0,1,1)
|
||||
_SrcRectRight("SrcRectRight", Vector) = (0,0,1,1)
|
||||
}
|
||||
SubShader
|
||||
{
|
||||
Tags { "RenderType"="Opaque" }
|
||||
LOD 100
|
||||
|
||||
Pass
|
||||
{
|
||||
CGPROGRAM
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
struct appdata
|
||||
{
|
||||
float4 vertex : POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
};
|
||||
|
||||
struct v2f
|
||||
{
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 vertex : SV_POSITION;
|
||||
float2 pos : TEXCOORD1;
|
||||
};
|
||||
|
||||
sampler2D _MainTex;
|
||||
float4 _MainTex_ST;
|
||||
|
||||
float4 _SrcRectLeft;
|
||||
float4 _SrcRectRight;
|
||||
|
||||
v2f vert (appdata v)
|
||||
{
|
||||
v2f o;
|
||||
o.vertex = UnityObjectToClipPos(v.vertex);
|
||||
|
||||
float4 srcRect = lerp(_SrcRectLeft, _SrcRectRight, unity_StereoEyeIndex);
|
||||
|
||||
o.pos = TRANSFORM_TEX(v.uv, _MainTex);
|
||||
o.uv = (o.pos * srcRect.zw) + srcRect.xy;
|
||||
return o;
|
||||
}
|
||||
|
||||
fixed4 frag (v2f i) : SV_Target
|
||||
{
|
||||
if (i.pos.x < 0.0 || i.pos.y < 0.0 || i.pos.x > 1.0 || i.pos.y > 1.0)
|
||||
{
|
||||
return float4(0,0,0,0);
|
||||
}
|
||||
|
||||
// sample the texture
|
||||
fixed4 col = tex2D(_MainTex, i.uv);
|
||||
return col;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
Fallback "Unlit/Texture"
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 873aaf52f432945df9937ea75a74c0e7
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user