Skip to main content
Up and Coming
May 14, 2015

MovieTexture on Gear VR

Hello guys, I know that MovieTexture don't work to Android and the plugin EasyMovieTexture don't work to Gear VR

On Oculus SDK has a script called MoviePlayerSample.cs, and I'm trying to use it, but I don't know if i'm doing right, because I follow the instructions and when I build the video dont play. I tryied to use the example scene to but it still dont play: Thats what I done:

(Instructions by the developper):

" Place a simple textured quad surface with the correct aspect ratio in your scene.
Add the MoviePlayerSample.cs script to the surface object.

Modify it for the correct media location (currently hardcoded)

Modify it to start when you want, instead of on the very first Update()."

On the third instruction that need to modify the media location I changed the line of the example code to this:

 mediaPlayer.Call("setDataSource", "/Card/oculus/Movies/Trailers/Interstellar.mp4");


And I done the other instructions too I just don't know if the last instruction works and if I done right on the third instruction.

I will send the developper code from sdk with my changes to be easy to understand:

 /************************************************************************************

Filename : MoviePlayerSample.cs
Content : An example of how to use the Moonlight video player
Created : July 12, 2014

Copyright : Copyright 2014 Oculus VR, LLC. All Rights reserved.

Use of this software is subject to the terms of the Oculus LLC license
agreement provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.

************************************************************************************/

using UnityEngine;
using System.Collections; // required for Coroutines
using System.Runtime.InteropServices; // required for DllImport
using System; // requred for IntPtr


/************************************************************************************
Usage:

Place a simple textured quad surface with the correct aspect ratio in your scene.

Add the MoviePlayerSample.cs script to the surface object.

Modify it for the correct media location (currently hardcoded)

Modify it to start when you want, instead of on the very first Update().

Implementation:

In the MoviePlayerSample Awake() call, GetNativeTextureID() is called on
renderer.material.mainTexture.

When the Oculus 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 StartVideoPlayerOnTextureId()
script call, which creates an Android MediaPlayer java object, issues a
native plugin call to tell the native code which texture id to put the video
on and return the Android Surface object to pass to MediaPlayer, then sets
up the media stream and starts it.

Every frame, right after VrApi::WarpSwap() is called by the native plugin,
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.

It is important to note that the texture is actually replaced -- the original
version is gone, and the video will now show up everywhere that texture was
used, not just on sthe GameObject that ran the script.

NOTE: The resolution of the movie texture is hard coded to 960x540 in MediaSurface.cpp.

************************************************************************************/

public class MoviePlayerSample : MonoBehaviour
{
private int nativeTextureID;

bool startedVideo = false;

#if (UNITY_ANDROID && !UNITY_EDITOR)
bool videoPaused = false;
AndroidJavaObject mediaPlayer = null;
#endif

/// <summary>
/// Initialization of the movie surface
/// </summary>
void Awake()
{
Debug.Log("Awake");

if (GetComponent<Renderer>().material == null || GetComponent<Renderer>().material.mainTexture == null)
{
Debug.LogError("Can't GetNativeTextureID() for movie surface");
}

// This aparently has to be done at Awake time, before
// multithreaded rendering starts;
nativeTextureID = GetComponent<Renderer>().material.mainTexture.GetNativeTextureID();
Debug.Log("Movie Texture id: " + nativeTextureID);
}

/// <summary>
/// Auto-starts video playback
/// </summary>
void DelayedStartVideo()
{
if (!startedVideo)
{
startedVideo = true;
#if (UNITY_ANDROID && !UNITY_EDITOR)
// This can only be done once multithreaded rendering is running
mediaPlayer = StartVideoPlayerOnTextureId(nativeTextureID);
#endif
}
}

void Start()
{
#if (UNITY_ANDROID && !UNITY_EDITOR)
// delay one frame because OVRCameraController initializes the render thread in Start()
Invoke("DelayedStartVideo", 0.1f);
#endif
}

/// <summary>
/// Pauses video playback when the app loses or gains focus
/// </summary>
void OnApplicationPause(bool wasPaused)
{
Debug.Log("OnApplicationPause: " + wasPaused);
#if (UNITY_ANDROID && !UNITY_EDITOR)
if (mediaPlayer != null)
{
videoPaused = wasPaused;
mediaPlayer.Call(( videoPaused ) ? "pause" : "start");
}
#endif
}

#if (UNITY_ANDROID && !UNITY_EDITOR)
// 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("OculusPlugin")]
private static extern IntPtr OVR_Media_Surface(int surfaceTexId);
#endif

#if (UNITY_ANDROID && !UNITY_EDITOR)
/// <summary>
/// Set up the video player with the movie surface texture id
/// </summary>
AndroidJavaObject StartVideoPlayerOnTextureId(int textureId)
{
Debug.Log("SetUpVideoPlayer ");

IntPtr androidSurface = OVR_Media_Surface(textureId);
c
AndroidJavaObject mediaPlayer = new AndroidJavaObject("android/media/MediaPlayer");

// Can't use AndroidJavaObject.Call() with a jobject, must use low level interface
//mediaPlayer.Call("setSurface", androidSurface);
IntPtr setSurfaceMethodId = AndroidJNI.GetMethodID(mediaPlayer.GetRawClass(),"setSurface","(Landroid/view/Surface;)V");
jvalue[] parms = new jvalue[1];
parms[0] = new jvalue();
parms[0].l = androidSurface;
AndroidJNI.CallObjectMethod(mediaPlayer.GetRawObject(), setSurfaceMethodId, parms);


mediaPlayer.Call("setDataSource", "/Card/oculus/Movies/Trailers/Interstellar.mp4");
mediaPlayer.Call("prepare");
mediaPlayer.Call("setLooping", true);
mediaPlayer.Call("start");

return mediaPlayer;
}
#endif
}
    This topic has been closed for replies.

    29 replies

    July 9, 2015
    I have seen that issue before but I've worked around it, and currently it's working fine in the latest release. Try the sample from oculus mobile sdk 0.6.0.1.

    I believe that issue may have something to do with unity not getting the correct native textureId to play the video on. It seems like the media player initialization is working fine, it's just unable to swap the video with the correct texture?

    Previously I was only able to recreate that issue when I loaded a scene with a video which uses the movieplayersample script, load another scene, and then load the scene with the video again. I tried calling "release" and/or "reset" on the mediaPlayer object (per the android documentation of media player) prior to recreating it when the scene was loaded for the second time but it didn't seem to make a difference.
    New Participant
    July 15, 2015
    "justinlutz" wrote:

    Previously I was only able to recreate that issue when I loaded a scene with a video which uses the movieplayersample script, load another scene, and then load the scene with the video again. I tried calling "release" and/or "reset" on the mediaPlayer object (per the android documentation of media player) prior to recreating it when the scene was loaded for the second time but it didn't seem to make a difference.


    I use oculus mobile sdk 0.6.0.1 and I'm am having the exact issue you described. How exactly did you solve this?
    July 16, 2015
    In my particular case both scenes were utilizing movieplayersample script to play a video. I was able to "hack" it to work but I'm sure there's a better way...here's what I did...

    1) load first scene and play video automatically
    2) load second scene and play video automatically
    3) return to first scene (need to initialize, start playing the video again and pause after about 1 second). I'm not yet sure exactly why but for some reason doing this allowed android/unity to properly release the videoplayer while loading the other scene (2) async and reinitialize when i then loaded scene (2) again
    July 16, 2015
    I've also had a chance to play around with the new Oculus Utilities 0.1.0 beta (https://developer.oculus.com/downloads/) that was release last week. This integration supports packages like Mobile Movie Texture (https://www.assetstore.unity3d.com/en/#!/content/2449) and do away with the need to use OVR_Media_Surface that movieplayersample from Mobile SDK 0.6.0 relies on. In my opinion this whole solution was stopgap anyway so glad to see Unity and Oculus moving in this direction. This way you're able to preview the video in editor rather than having to test on the device.

    Long story short - if you have the time to test porting your existing project over to the latest and greatest you may be better off in the long run as Unity 5.1.1 is starting to support VR natively.
    New Participant
    July 20, 2015
    Thanks for the tips. I was not aware of the Oculus utilities, but I will definitely be checking it out.

    When you say you paused the video after a second, did you have to set a listener for that, and then use mediaPlayer.call("Pause"); ? I'm curious because other than changing the video source, I haven't had much success editing the movieplayersample.
    July 24, 2015
    Hey everyone, super helpful thread!

    I'm having a similar issue trying to get a movie to play on the GearVR S6 with Oculus Utilities. I just grabbed the script "MoviePlayerSample" and changed the path to point to a video on my S6, but it doesn't seem to play. I wonder if this will work or if I need to import a different Unity package instead of the Oculus Utilities?

    I'm getting the errors:
    "Can't GetNativeTextureID() for movie surface"
    "NullReferenceException: Object reference not set to an instance of an object"

    I think a lot of the movie texture assets store bundles are limited with support of file types like .mp4, so I'd rather try it with just the Oculus script...
    Up and Coming
    July 25, 2015
    Hey everyone,

    Looks like I'm having the same issue that others are having - audio on a movie texture, but no video. I have this working perfectly in a test project that I set up, replicated it in an official project, and now I have no video. Very frustrating, especially when it's something that we need working right away to send to a client. I'm using 5.1.1p4 and SDK 0.6.0. A couple main questions:

    -Is the media player dependent on a certain texture or material being applied to the surface that you want it to play on?

    -What is the specific encoding required to play the video smoothly? I'm using H.264 MP4 files and they play but pause intermittently in the project where they work.

    I have adjusted the MoviePlayerSample.cs script to meet all of the suggestions, with no effect. And on a side note, I discovered that you have to have your resolution on line 148 set as "2048, 1024" to get the video (which is 4k) to stretch correctly on the movie surface. Unity seems to be really inconsistent with this problem, working in some projects and not in others, and the documentation on how to do this is sketchy at best. Once we get this figured out, I'd be happy to do an in-depth video tutorial that walks you through how to get this working. If anyone has any other suggestions, I'm all ears!!!! Thanks for the help!

    Barry Zundel
    Villusion Studios, LLC.
    New Participant
    July 27, 2015
    Hi,
    I'm trying to get movies to work, but no results found.
    I'm using Unity 5.1.2f1, so, the oculus sdk 0.6.0 should be included.

    Here it's what I found out (rectify me if I'm wrong):

    If I create a new example project using the SDK examples, all the included scenes work.

    In the last version of these examples, there's not the movie texture example scenne, so I downloaded the ovr_mobile_sdk_0.6.0.1 and I've included the missing scene (and script in my project).

    I've added some debug outputs to MoviePlayerSample.cs and I found out that it crashes in StartVideoPlayerOnTextureId method. The textureId is correctly calculated (38 looks like a good Android-like id), but it crashes when it tries to execute the following code:

    IntPtr  androidSurface = OVR_Media_Surface( textureId, 2880, 1440 );


    where it fetches the android surface relative to the texture id.

    If you look some lines above, you can see that this method should be included in OculusPlugin dll.

    [DllImport("OculusPlugin")]
    private static extern IntPtr OVR_Media_Surface( int surfaceTexId, int surfaceWidth, int surfaceHeight );


    As I’m using Unity 5.1.2, I’ve not OculusPlugin dll on my pc, so I’ve found in
    C:\Program Files\Unity\Editor\Data\VR\win32 another dll: OVRPlugin.dll.
    I’ve changed my code with
    [DllImport("OVRPlugin")]
    private static extern IntPtr OVR_Media_Surface( int surfaceTexId, int surfaceWidth, int surfaceHeight );


    but nothing happens.

    I’ve opened the dll with a disassembler and I noticed that there’s NOT any function called OVR_Media_Surface!! Very frustrating! :?

    So, if my analysis is correct, for this version of Unity there’s no possibility to get movies to work.

    The only way I see is to roll back to legacy approach, by using oculus external sdk (I already used it in a previous project and it drove me crazy sometimes).

    So, my question is: is there the hope that in next future this feature will be natively inclueded in Unity OVR?
    Or
    Am I wrong? (I’d hope it) Maybe there’s another way to get it work?

    Plz light me up! :)
    Inspiring
    July 27, 2015
    Media Surface functionality is currently removed with First Party support. It will be added as a separate plugin to the First Party Utilities package in the very near future.
    AMD Ryzen 7 1800X | MSI X370 Titanium | G.Skill 16GB DDR4 3200 | EVGA SuperNOVA 1000 | Corsair Hydro H110i Gigabyte RX Vega 64 x2 | Samsung 960 Evo M.2 500GB | Seagate FireCuda SSHD 2TB | Phanteks ENTHOO EVOLV
    Up and Coming
    July 27, 2015
    "cybereality" wrote:
    Media Surface functionality is currently removed with First Party support. It will be added as a separate plugin to the First Party Utilities package in the very near future.


    By "very near" do you mean within days? I know it's a somewhat stupid question, but when you are trying to deliver for clients, it it good to know these things. Thanks.