Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
package net.gangneux.dev.jrmgxlibview;
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Surface;
import android.view.ViewGroup;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
/**
* Created by jerome on 30/10/2016.
*/
public class JrmgxWebView extends WebView {
private Surface surface = null;
// Inherit
public JrmgxWebView(Context context) {
super(context);
Log.i("JrmgxWebView.java", "Constructor with context");
}
public JrmgxWebView(Context context, AttributeSet attrs) {
super(context, attrs);
Log.i("JrmgxWebView.java", "Constructor with context + attrs");
}
public JrmgxWebView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
Log.i("JrmgxWebView.java", "Constructor with context + attrs + styleAttr");
}
// Custom
public long lastUpdateTime = 0;
public int width = 512;
public int height = 512;
public boolean hasUpdate = false;
public JrmgxWebView(Context context, int width, int height) {
super(context);
this.width = width;
this.height = height;
Log.i("JrmgxWebView.java", "Constructor with context + width + height = " + width + " + " + height);
//setWebChromeClient( new WebChromeClient(){} );
//setWebViewClient( new WebViewClient() );
/*
setWebChromeClient(new WebChromeClient());
getSettings().setJavaScriptEnabled(true);
getSettings().setDomStorageEnabled(true);
setWebViewClient(new WebViewClient() {
public boolean shouldOverrideUrlLoading(WebView view,String url) {
return false;
}
});
*/
setLayoutParams(new ViewGroup.LayoutParams(width, height));
}
void setSurface(Surface surface) {
Log.i("JrmgxWebView.java", "setSurface");
this.surface = surface;
}
@Override
public void loadUrl(String url) {
Log.i("JrmgxWebView.java", "load url " + url);
super.loadUrl(url);
}
@Override
public void loadData(String data, String mimeType, String encoding) {
super.loadData(data, mimeType, encoding);
}
public void loadData(String data) {
Log.i("JrmgxWebView.java", "load data with: " + data);
super.loadData(data, "text/html; charset=utf-8", "UTF-8");
}
@Override
protected void onDraw(Canvas canvas) {
Log.i("JrmgxWebView.java", "onDraw");
/*if (lastUpdateTime == 0) {
lastUpdateTime = System.currentTimeMillis();
}
if (System.currentTimeMillis() - lastUpdateTime < 33) {
return; // Skip frame-rate
}
lastUpdateTime = System.currentTimeMillis();
hasUpdate = true;*/
if (surface != null) {
try {
final Canvas surfaceCanvas = surface.lockCanvas(null);
//surfaceCanvas.save();
//surfaceCanvas.translate(0, 0); // TODO scrolling
super.onDraw(surfaceCanvas);
//surfaceCanvas.restore();
surface.unlockCanvasAndPost(surfaceCanvas);
Log.i("JrmgxWebView.java", "onDraw not null + success");
}
catch (Exception e) {
Log.e("JrmgxWebView.java", "onDraw exception " + e.getMessage());
}
}
//super.onDraw(canvas);
/* GVR (samsung)
Canvas attachedCanvas = mSceneObject.lockCanvas();
// translate canvas to reflect view scrolling
attachedCanvas.scale(attachedCanvas.getWidth() / (float) canvas.getWidth(),
attachedCanvas.getHeight() / (float) canvas.getHeight());
attachedCanvas.translate(-getScrollX(), -getScrollY());
// draw the view to provided canvas
super.draw(attachedCanvas);
*/
}
}
/************************************************************************************
Filename : MediaSurface.cpp
Content : Interface to copy/mip a SurfaceTexture stream onto a normal GL texture
Created : July 14, 2014
Authors : John Carmack
Copyright : Copyright 2014 Oculus VR, LLC. All Rights reserved.
*************************************************************************************/
#include "MediaSurface.h"
#include "Kernel/OVR_LogUtils.h"
#include "GlStateSave.h"
namespace OVR
{
MediaSurface::MediaSurface() :
jni( NULL ),
AndroidSurfaceTexture( NULL ),
SurfaceObject( NULL ),
LastSurfaceTexNanoTimeStamp( 0 ),
TexIdWidth( -1 ),
TexIdHeight( -1 ),
BoundWidth( -1 ),
BoundHeight( -1 ),
TexId( 0 ),
Fbo( 0 ),
ExternalTexture( false )
{
}
void MediaSurface::Init( JNIEnv * jni_ )
{
LOG( "MediaSurface - Init()" );
jni = jni_;
LastSurfaceTexNanoTimeStamp = 0;
TexId = 0;
Fbo = 0;
// Setup a surface for playing movies in Unity
AndroidSurfaceTexture = new SurfaceTexture( jni );
static const char * className = "android/view/Surface";
const jclass surfaceClass = jni->FindClass( className );
if ( surfaceClass == 0 )
{
FAIL( "MediaSurface - FindClass( %s ) failed", className );
}
// find the constructor that takes a surfaceTexture object
const jmethodID constructor = jni->GetMethodID( surfaceClass, "<init>", "(Landroid/graphics/SurfaceTexture;)V" );
if ( constructor == 0 )
{
FAIL( "MediaSurface - GetMethodID( <init> ) failed" );
}
jobject obj = jni->NewObject( surfaceClass, constructor, AndroidSurfaceTexture->GetJavaObject() );
if ( obj == 0 )
{
FAIL( "MediaSurface - NewObject() failed" );
}
SurfaceObject = jni->NewGlobalRef( obj );
if ( SurfaceObject == 0 )
{
FAIL( "MediaSurface - NewGlobalRef() failed" );
}
// Now that we have a globalRef, we can free the localRef
jni->DeleteLocalRef( obj );
// The class is also a localRef that we can delete
jni->DeleteLocalRef( surfaceClass );
}
void MediaSurface::Shutdown()
{
LOG( "MediaSurface - Shutdown()" );
DeleteProgram( CopyMovieProgram );
UnitSquare.Free();
delete AndroidSurfaceTexture;
AndroidSurfaceTexture = NULL;
if ( Fbo != 0 )
{
glDeleteFramebuffers( 1, &Fbo );
Fbo = 0;
}
if ( !ExternalTexture && TexId != 0 )
{
glDeleteTextures( 1, &TexId );
}
if ( jni != NULL )
{
if ( SurfaceObject != NULL )
{
jni->DeleteGlobalRef( SurfaceObject );
SurfaceObject = NULL;
}
}
}
jobject MediaSurface::GetSurfaceObject()
{
if ( SurfaceObject == NULL )
{
LOG( "MediaSurface - SurfaceObject == NULL" );
abort();
}
return SurfaceObject;
}
int MediaSurface::GetNativeTextureId()
{
LOG ("MediaSurface - GetNativeTextureId = %i", TexId);
return TexId;
}
void MediaSurface::SetExternalTexId_DEPRECATED( const int texId_ )
{
LOG ("MediaSurface - SetExternalTexId_DEPRECATED DANGER");
TexId = texId_;
ExternalTexture = true;
}
// TODO: Format, mips, etc
void MediaSurface::SetTextureParms( const int texWidth_, const int texHeight_ )
{
BoundWidth = texWidth_;
BoundHeight = texHeight_;
}
void MediaSurface::Update()
{
LOG ("MediaSurface - Update");
if ( AndroidSurfaceTexture == NULL )
{
LOG( "MediaSurface - AndroidSurfaceTexture == NULL" );
return;
}
if ( ExternalTexture && TexId <= 0 )
{
LOG( "MediaSurface - TexId <= 0" );
return;
}
AndroidSurfaceTexture->Update();
long long currentTimeStamp = AndroidSurfaceTexture->GetNanoTimeStamp();
LOG ("MediaSurface - %d =? %d", currentTimeStamp, LastSurfaceTexNanoTimeStamp);
if ( currentTimeStamp == LastSurfaceTexNanoTimeStamp )
{
LOG( "MediaSurface - No new surface!" );
// HARDCORE return;
return;
}
LastSurfaceTexNanoTimeStamp = AndroidSurfaceTexture->GetNanoTimeStamp();
// don't mess up Unity state
GLStateSave stateSave;
// If we haven't allocated our GL objects yet, do it now.
// This isn't done at Init, because GL may not be current then.
if ( UnitSquare.vertexArrayObject == 0 )
{
LOG( "MediaSurface - Allocating GL objects" );
UnitSquare = BuildTesselatedQuad( 1, 1 );
CopyMovieProgram = BuildProgram(
NULL,
"attribute vec4 Position;\n"
"attribute vec2 TexCoord;\n"
"varying highp vec2 oTexCoord;\n"
"void main()\n"
"{\n"
" gl_Position = Position;\n"
" oTexCoord = TexCoord;\n"
"}\n"
,
"#extension GL_OES_EGL_image_external : enable\n"
"#extension GL_OES_EGL_image_external_essl3 : enable\n"
,
"uniform samplerExternalOES Texture0;\n"
"varying highp vec2 oTexCoord;\n"
"void main()\n"
"{\n"
" gl_FragColor = texture2D( Texture0, oTexCoord );\n"
"}\n"
);
}
// If the SurfaceTexture has changed dimensions, we need to
// reallocate the texture and FBO.
if ( ( !ExternalTexture && ( TexId == 0 ) ) || TexIdWidth != BoundWidth || TexIdHeight != BoundHeight )
{
LOG( "MediaSurface - New surface size: %ix%i", BoundWidth, BoundHeight );
TexIdWidth = BoundWidth;
TexIdHeight = BoundHeight;
if ( Fbo != 0 )
{
glDeleteFramebuffers( 1, &Fbo );
}
if ( !ExternalTexture )
{
if ( TexId != 0 )
{
glDeleteTextures( 1, &TexId );
}
glGenTextures( 1, &TexId );
}
glActiveTexture( GL_TEXTURE1 );
glBindTexture( GL_TEXTURE_2D, TexId );
// TODO: Switch to glTexStorage2D when we're no longer having to support deprecated external image interface.
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, TexIdWidth, TexIdHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glBindTexture( GL_TEXTURE_2D, 0 );
glActiveTexture( GL_TEXTURE0 );
glGenFramebuffers( 1, &Fbo );
glBindFramebuffer( GL_FRAMEBUFFER, Fbo );
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, TexId, 0 );
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
}
if ( Fbo != 0 )
{
LOG ("MediaSurface - Fbo != 0");
glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_EXTERNAL_OES, AndroidSurfaceTexture->GetTextureId() );
glBindFramebuffer( GL_FRAMEBUFFER, Fbo );
glDisable( GL_DEPTH_TEST );
glDisable( GL_SCISSOR_TEST );
glDisable( GL_STENCIL_TEST );
glDisable( GL_CULL_FACE );
glDisable( GL_BLEND );
const GLenum fboAttachments[1] = { GL_COLOR_ATTACHMENT0 };
glInvalidateFramebuffer( GL_FRAMEBUFFER, 1, fboAttachments );
glViewport( 0, 0, TexIdWidth, TexIdHeight );
glUseProgram( CopyMovieProgram.Program );
UnitSquare.Draw();
glUseProgram( 0 );
glBindTexture( GL_TEXTURE_EXTERNAL_OES, 0 );
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
glBindTexture( GL_TEXTURE_2D, TexId );
glGenerateMipmap( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, 0 );
}
}
} // namespace OVR
/************************************************************************************
Filename : MediaSurfacePlugin.cpp
Content :
Created : July 1, 2015
Authors :
Copyright : Copyright 2015 Oculus VR, LLC. All Rights reserved.
*************************************************************************************/
#include <jni.h>
#include "Kernel/OVR_Allocator.h"
#include "Kernel/OVR_Types.h"
#include "Kernel/OVR_System.h"
#include "Android/JniUtils.h"
#include "Kernel/OVR_GlUtils.h"
#include "Kernel/OVR_LogUtils.h"
#include "MediaSurface.h"
#include "GlStateSave.h"
#define OCULUS_EXPORT
using namespace OVR;
static struct InitShutdown
{
InitShutdown()
{
OVR::System::Init( OVR::Log::ConfigureDefaultLog( OVR::LogMask_All ) );
}
~InitShutdown()
{
OVR::System::Destroy();
}
} GlobalInitShutdown;
class MediaSurfacePlugin
{
public:
MediaSurfacePlugin() :
initialized( false ),
eventBase( 0 ),
jniEnv( NULL )
{
}
bool initialized;
int eventBase;
JNIEnv * jniEnv;
// Media surface for video player support in Unity
MediaSurface mediaSurface;
};
MediaSurfacePlugin mediaSurfacePlugin;
extern "C"
{
static JavaVM * UnityJavaVM;
JNIEXPORT jint JNI_OnLoad( JavaVM * vm, void * reserved )
{
LOG( "MediaSurfacePlugin - JNI_OnLoad" );
UnityJavaVM = vm;
return JNI_VERSION_1_6;
}
// Call this as early as possible to load the plugin.
OCULUS_EXPORT void OVR_Media_Surface_Init()
{
LOG( "MediaSurfacePlugin - OVR_Media_Surface_Init()" );
}
OCULUS_EXPORT void OVR_Media_Surface_SetEventBase( int eventBase )
{
//LOG( "OVR_Media_Surface_SetEventBase() = %d", eventBase );
mediaSurfacePlugin.eventBase = eventBase;
}
OCULUS_EXPORT jobject OVR_Media_Surface_GetObject()
{
return mediaSurfacePlugin.mediaSurface.GetSurfaceObject();
}
OCULUS_EXPORT intptr_t OVR_Media_Surface_GetNativeTexture()
{
return mediaSurfacePlugin.mediaSurface.GetNativeTextureId();
}
OCULUS_EXPORT void OVR_Media_Surface_SetTextureId_DEPRECATED( void * texPtr )
{
GLuint texId = (GLuint)(size_t)(texPtr);
LOG( "MediaSurfacePlugin - OVR_Media_Surface_SetTextureId(%i)", texId );
return mediaSurfacePlugin.mediaSurface.SetExternalTexId_DEPRECATED( texId );
}
OCULUS_EXPORT void OVR_Media_Surface_SetTextureParms( int const width, int const height )
{
LOG( "MediaSurfacePlugin - OVR_Media_Surface_SetTextureParms(%i, %i)", width, height );
return mediaSurfacePlugin.mediaSurface.SetTextureParms( width, height );
}
void OVR_InitMediaSurface()
{
if ( mediaSurfacePlugin.initialized )
{
return;
}
LOG( "MediaSurfacePlugin - OVR_InitMediaSurface()" );
#if defined( OVR_HAS_OPENGL_LOADER )
if ( !GLES3::LoadGLFunctions() )
{
FAIL( "MediaSurfacePlugin - Failed to load GLES3 core entry points!" );
}
#endif
// We should have a javaVM from the .so loadupdateTexImage
if ( UnityJavaVM == NULL )
{
FAIL( "MediaSurfacePlugin - JNI_OnLoad() not called yet" );
}
UnityJavaVM->AttachCurrentThread( &mediaSurfacePlugin.jniEnv, 0 );
// Look up extensions
GL_InitExtensions();
mediaSurfacePlugin.initialized = true;
mediaSurfacePlugin.mediaSurface.Init( mediaSurfacePlugin.jniEnv );
}
void OVR_ShutdownMediaSurface()
{
if ( !mediaSurfacePlugin.initialized )
{
return;
}
LOG( "MediaSurfacePlugin - OVR_ShutdownMediaSurface()" );
mediaSurfacePlugin.mediaSurface.Shutdown();
mediaSurfacePlugin.initialized = false;
}
enum MediaSurfaceEventType
{
MS_EVENT_INIT = 0,
MS_EVENT_SHUTDOWN = 1,
MS_EVENT_UPDATE = 2
};
// When Unity's multi-threaded renderer is enabled, the GL context is never current for
// the script execution thread, so the only way for a plugin to execute GL code is to
// have it done through the GL.IssuePluginEvent( int ) call, which calls this function.
OCULUS_EXPORT void UnityRenderEvent( int eventID )
{
const int remappedID = eventID - mediaSurfacePlugin.eventBase;
//LOG( "MediaSurface:: UnityRenderEvent %d %d", eventID, remappedID );
switch( remappedID )
{
case MS_EVENT_INIT:
{
OVR_InitMediaSurface();
break;
}
case MS_EVENT_SHUTDOWN:
{
OVR_ShutdownMediaSurface();
break;
}
case MS_EVENT_UPDATE:
{
// Update the movie surface, if active.
mediaSurfacePlugin.mediaSurface.Update();
break;
}
default:
break;
}
}
} // extern "C"
/************************************************************************************
Filename : SurfaceTexture.cpp
Content : Interface to Android SurfaceTexture objects
Created : September 17, 2013
Authors : John Carmack
Copyright : Copyright 2014 Oculus VR, LLC. All Rights reserved.
*************************************************************************************/
#include "SurfaceTexture.h"
#include <stdlib.h>
#include "Kernel/OVR_GlUtils.h"
#include "Kernel/OVR_LogUtils.h"
namespace OVR {
SurfaceTexture::SurfaceTexture( JNIEnv * jni_ ) :
textureId( 0 ),
javaObject( NULL ),
jni( NULL ),
nanoTimeStamp( 0 ),
updateTexImageMethodId( NULL ),
getTimestampMethodId( NULL ),
setDefaultBufferSizeMethodId( NULL )
{
LOG ("SurfaceTexture - init");
#if defined( OVR_OS_ANDROID )
jni = jni_;
// Gen a gl texture id for the java SurfaceTexture to use.
glGenTextures( 1, &textureId );
glBindTexture( GL_TEXTURE_EXTERNAL_OES, textureId );
glTexParameterf( GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameterf( GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameterf( GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameterf( GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glBindTexture( GL_TEXTURE_EXTERNAL_OES, 0 );
static const char * className = "android/graphics/SurfaceTexture";
const jclass surfaceTextureClass = jni->FindClass(className);
if ( surfaceTextureClass == 0 ) {
FAIL( "SurfaceTexture - FindClass( %s ) failed", className );
}
// find the constructor that takes an int
const jmethodID constructor = jni->GetMethodID( surfaceTextureClass, "<init>", "(I)V" );
if ( constructor == 0 ) {
FAIL( "SurfaceTexture - GetMethodID( <init> ) failed" );
}
jobject obj = jni->NewObject( surfaceTextureClass, constructor, textureId );
if ( obj == 0 ) {
FAIL( "SurfaceTexture - NewObject() failed" );
}
javaObject = jni->NewGlobalRef( obj );
if ( javaObject == 0 ) {
FAIL( "SurfaceTexture - NewGlobalRef() failed" );
}
// Now that we have a globalRef, we can free the localRef
jni->DeleteLocalRef( obj );
updateTexImageMethodId = jni->GetMethodID( surfaceTextureClass, "updateTexImage", "()V" );
if ( !updateTexImageMethodId ) {
FAIL( "SurfaceTexture - couldn't get updateTexImageMethodId" );
}
getTimestampMethodId = jni->GetMethodID( surfaceTextureClass, "getTimestamp", "()J" );
if ( !getTimestampMethodId ) {
FAIL( "SurfaceTexture - couldn't get getTimestampMethodId" );
}
setDefaultBufferSizeMethodId = jni->GetMethodID( surfaceTextureClass, "setDefaultBufferSize", "(II)V" );
if ( !setDefaultBufferSizeMethodId ) {
FAIL( "SurfaceTexture - couldn't get setDefaultBufferSize" );
}
// jclass objects are localRefs that need to be freed
jni->DeleteLocalRef( surfaceTextureClass );
LOG ("SurfaceTexture - init with success");
#endif
LOG ("SurfaceTexture - init has success ^^ ? and textureId = %i", textureId);
}
SurfaceTexture::~SurfaceTexture()
{
#if defined( OVR_OS_ANDROID )
if ( textureId ) {
glDeleteTextures( 1, &textureId );
textureId = 0;
}
if ( javaObject ) {
jni->DeleteGlobalRef( javaObject );
javaObject = 0;
}
#endif
}
void SurfaceTexture::SetDefaultBufferSize( const int width, const int height )
{
#if defined( OVR_OS_ANDROID )
jni->CallVoidMethod( javaObject, setDefaultBufferSizeMethodId, width, height );
#else
OVR_UNUSED( width );
OVR_UNUSED( height );
#endif
}
void SurfaceTexture::Update()
{
#if defined( OVR_OS_ANDROID )
// latch the latest movie frame to the texture
if ( !javaObject ) {
return;
}
jni->CallVoidMethod( javaObject, updateTexImageMethodId );
nanoTimeStamp = jni->CallLongMethod( javaObject, getTimestampMethodId );
LOG ("SurfaceTexture - last nanoTimeStamp is %i", nanoTimeStamp);
#endif
}
unsigned SurfaceTexture::GetTextureId()
{
return textureId;
}
jobject SurfaceTexture::GetJavaObject()
{
return javaObject;
}
long long SurfaceTexture::GetNanoTimeStamp()
{
return nanoTimeStamp;
}
} // namespace OVR
/************************************************************************************
Copyright : Copyright 2014 Oculus VR, LLC. All Rights reserved.
Licensed under the Oculus VR Rift SDK License Version 3.3 (the "License");
you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
http://www.oculus.com/licenses/LICENSE-3.3
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
************************************************************************************/
using UnityEngine;
using System.Collections; // required for Coroutines
using System.Runtime.InteropServices; // required for DllImport
using System; // requred for IntPtr
using System.IO; // required for File
/************************************************************************************
Usage:
Place a simple textured quad surface with the correct aspect ratio in your scene.
Add the WebviewPlayerSample.cs script to the surface object.
Supply the name of the media file to play:
This sample assumes the media file is placed in "Assets/StreamingAssets", ie
"ProjectName/Assets/StreamingAssets/url.mp4".
On Desktop, Unity MovieTexture functionality is used. Note: the media file
is loaded at runtime, and therefore expected to be converted to Ogg Theora
beforehand.
Implementation:
In the WebviewPlayerSample Awake() call, GetNativeTexturePtr() is called on
renderer.material.mainTexture.
When the MediaSurface plugin gets the initialization event on the render thread,
it creates a new Android SurfaceTexture and Surface object in preparation
for receiving media.
When the game wants to start the video playing, it calls the StartWebViewOnTextureId()
script call, which creates an Android webView java object, issues a
native plugin call to tell the native code to set up the target texture to
render the video to and return the Android Surface object to pass to webView,
then sets up the media stream and starts it.
Every frame, the SurfaceTexture object is checked for updates. If there
is one, the target texId is re-created at the correct dimensions and format
if it is the first frame, then the video image is rendered to it and mipmapped.
The following frame, instead of Unity drawing the image that was placed
on the surface in the Unity editor, it will draw the current video frame.
************************************************************************************/
public class WebviewPlayerSampleWeb : MonoBehaviour {
public string url = string.Empty;
public int textureWidth = 512;
public int textureHeight = 512;
#if (UNITY_ANDROID && !UNITY_EDITOR)
// Internals
private bool started = false;
private Renderer currentRenderer = null;
private Texture2D nativeTexture = null;
private IntPtr nativeTexId = IntPtr.Zero;
private AndroidJavaObject webView = null;
private int frameCpt = 0;
private enum MediaSurfaceEventType {
Initialize = 0,
Shutdown = 1,
Update = 2,
Max_EventType
};
/// The start of the numeric range used by event IDs.
/// If multiple native rundering plugins are in use, the Oculus Media Surface plugin's event IDs
/// can be re-mapped to avoid conflicts.
///
/// Set this value so that it is higher than the highest event ID number used by your plugin.
/// Oculus Media Surface plugin event IDs start at eventBase and end at eventBase plus the highest
/// value in MediaSurfaceEventType.
public static int eventBase {
get { return _eventBase; }
set {
_eventBase = value;
OVR_Media_Surface_SetEventBase(_eventBase);
}
}
private static int _eventBase = 0;
private static void IssuePluginEvent(MediaSurfaceEventType eventType) {
GL.IssuePluginEvent((int) eventType + eventBase);
}
// GameObject
void log(string message) {
print("WebviewPlayerSampleWeb: LOG " + message);
}
void error(string message) {
print("WebviewPlayerSampleWeb: ERROR " + message);
}
void Awake() {
log("Awake");
OVR_Media_Surface_Init();
currentRenderer = GetComponent<Renderer>();
if (currentRenderer.material == null) {
error("No material for web surface");
if (currentRenderer.material.mainTexture == null) {
error ("No mainTexture");
}
}
if (url == string.Empty) {
error("No url provided");
}
nativeTexture = Texture2D.CreateExternalTexture(textureWidth, textureHeight, TextureFormat.RGBA32, true, false, IntPtr.Zero);
IssuePluginEvent(MediaSurfaceEventType.Initialize);
}
void Start() {
log("Start");
StartCoroutine(DelayedRetrieveWebPage());
}
void Update() {
log ("Update");
IntPtr currTexId = OVR_Media_Surface_GetNativeTexture();
log ("texId = " + currTexId);
if (currTexId != nativeTexId) {
log ("Update + tex is diff");
nativeTexId = currTexId;
nativeTexture.UpdateExternalTexture(currTexId);
}
IssuePluginEvent(MediaSurfaceEventType.Update);
if (webView != null) {
frameCpt++;
if (frameCpt % 100 == 0) {
webView.Call("loadData", "<h1>HELLO WORLD: " + frameCpt);
webView.Call("postInvalidate");
}
}
}
/// Pauses when the app loses or gains focus
void OnApplicationPause(bool wasPaused) {
log("OnApplicationPause: " + wasPaused);
}
private void OnApplicationQuit() {
log("OnApplicationQuit");
// This will trigger the shutdown on the render thread
IssuePluginEvent(MediaSurfaceEventType.Shutdown);
}
/// Auto-starts loading
IEnumerator DelayedRetrieveWebPage() {
log ("DelayedRetrieveWebPage NOT STARTED");
yield return null; // delay 1 frame to allow MediaSurfaceInit from the render thread.
if (!started) {
log ("DelayedRetrieveWebPage STARTED");
started = true;
webView = StartOnTextureId(textureWidth, textureHeight, url);
webView.Call("loadData", "<h1>HELLO WORLD!");
currentRenderer.material.mainTexture = nativeTexture;
}
}
/// Set up the web view with surface texture id.
AndroidJavaObject StartOnTextureId(int texWidth, int texHeight, string url) {
log("StartOnTextureId");
OVR_Media_Surface_SetTextureParms(textureWidth, textureHeight);
IntPtr androidSurface = OVR_Media_Surface_GetObject();
//AndroidJavaObject webView = new AndroidJavaObject("android/webkit/WebView");
AndroidJavaClass unityJavaClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject unityJavaContext = unityJavaClass.GetStatic<AndroidJavaObject>("currentActivity");
AndroidJavaObject webView = new AndroidJavaObject("net.gangneux.dev.jrmgxlibview.JrmgxWebView", unityJavaContext, texWidth, texHeight);
// Can't use AndroidJavaObject.Call() with a jobject, must use low level interface
//webView.Call("setSurface", androidSurface);
IntPtr setSurfaceMethodId = AndroidJNI.GetMethodID(webView.GetRawClass(), "setSurface", "(Landroid/view/Surface;)V");
jvalue[] parms = new jvalue[1];
parms[0] = new jvalue();
parms[0].l = androidSurface;
AndroidJNI.CallVoidMethod(webView.GetRawObject(), setSurfaceMethodId, parms);
try {
webView.Call("loadUrl", url);
//webView.Call("prepare");
//webView.Call("setLooping", true);
//webView.Call("start");
}
catch (Exception e) {
error("Failed to start webView with message " + e.Message);
}
return webView;
}
[DllImport("OculusMediaSurface")]
private static extern void OVR_Media_Surface_Init();
[DllImport("OculusMediaSurface")]
private static extern void OVR_Media_Surface_SetEventBase(int eventBase);
// This function returns an Android Surface object that is
// bound to a SurfaceTexture object on an independent OpenGL texture id.
// Each frame, before the TimeWarp processing, the SurfaceTexture is checked
// for updates, and if one is present, the contents of the SurfaceTexture
// will be copied over to the provided surfaceTexId and mipmaps will be
// generated so normal Unity rendering can use it.
[DllImport("OculusMediaSurface")]
private static extern IntPtr OVR_Media_Surface_GetObject();
[DllImport("OculusMediaSurface")]
private static extern IntPtr OVR_Media_Surface_GetNativeTexture();
[DllImport("OculusMediaSurface")]
private static extern void OVR_Media_Surface_SetTextureParms(int texWidth, int texHeight);
#endif
}
@L0g1k

This comment has been minimized.

Copy link

L0g1k commented Dec 21, 2016

Hi, I found this gist from your SO question. You stated on your blog that you got this working; would you be willing to share it?

Thanks

@wikieden

This comment has been minimized.

Copy link

wikieden commented Dec 26, 2016

thanks for sharing

@geoabensur

This comment has been minimized.

Copy link

geoabensur commented Mar 17, 2019

Hi, would you be willing to share your fixing again?
Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.