UnityPlugin-AVProVideo icon indicating copy to clipboard operation
UnityPlugin-AVProVideo copied to clipboard

Native support of OVR Overlay

Open lightsailvr opened this issue 6 years ago • 37 comments

Is your feature request related to a problem? Please describe. Oculus SDK has introduced the ability to play video on an Overlay layer, bypassing the eye buffer and displaying the video much sharper and without as much jitter as before. I would like to see AVPro support rendering to this layer as it greatly improves image quality.

Describe the solution you'd like A demo scene showing how to render both a flat video and 360/180 spherical video to the OVR Overlay

Describe alternatives you've considered I have tried to utilize Unity's built in video play to accomplish this, but it's no match feature for feature with AVPro, especially when it comes to streaming.

Additional context Video encoding settings being used: https://creator.oculus.com/blog/encoding-high-resolution-360-and-180-video-for-oculus-go/

More information about OVR Overlay: https://developer.oculus.com/documentation/unity/latest/concepts/unity-ovroverlay/

lightsailvr avatar May 29 '19 22:05 lightsailvr

Hi @lightsailvr, I got this working by taking the texture from AVPro (as soon as it's not null) and assigning it to OVR Overlay: ovrOverlay.textures[0] = mediaPlayer.TextureProducer.GetTexture();

It works great! What would be even better is if we could assign the pointer to the native android texture, but AVPro doesn't seem to expose it 'ovrOverlay.externalSurfaceObject = ???'

andriworld avatar May 30 '19 04:05 andriworld

Interesting! I didn't know you could do that....we'll have to expose the surface pointer so you can try it!

AndrewRH avatar May 31 '19 11:05 AndrewRH

@andriworld Is it one of these you are after?

https://developer.android.com/reference/android/view/Surface

Ste-RH avatar Jul 09 '19 16:07 Ste-RH

@RenderHeadsSte I think in this example you can see how to use the external surface properly, but I am not good at native coding.

https://developer.oculus.com/blog/tech-note-animated-loading-screen/

blanxdev avatar Jul 09 '19 22:07 blanxdev

Yeah, I already looked at that sample. It didn't give me the answer.

Before we can make a call on whether we will expose access, we need to know what object you want.

Ste-RH avatar Jul 10 '19 09:07 Ste-RH

One way is to let the video player write to a surface texture or whatever it is called. In the Oculus video player example they provide a surface to the player.

` exoPlayer = ExoPlayerFactory.newSimpleInstance(new CustomRenderersFactory(context), trackSelector);

            exoPlayer.setVideoSurface( surface );

            // Prepare the player with the source.
            exoPlayer.prepare(videoSource);`

And I think the surface gets created in the OVROverlay.cs component which then is used in a overlay layer. This should be the most efficient approach.

"OVR Overlay – Used as a surface on which ExoPlayer plays the video on Mobile platforms.

Of note is the Android-only Is External Surface check box. When checked, this allows for an Android external surface to be controlled by the Asynchronous TimeWarp (ATW) layer. In this sample, this allows the Android ExoPlayer video player surface to be run as an ATW layer, avoiding redundant texture copies to save memory and cycles."

What @andriworld proposed is a different approach. There he wants to use it as a texture I think and just wants a pointer to the texture data. But not sure if I got it right.

blanxdev avatar Jul 10 '19 09:07 blanxdev

Oki, so 'surface' there is the one I linked to (android.view.Surface).

We will have a chat about this internally and make a decision about exposing it.

Ste-RH avatar Jul 10 '19 10:07 Ste-RH

Looking forward. Hopefully then it is possible to do playback on Go without any framedrops. We are trying to playback 60fps footage, but having frame drops every quarter or half second which disturbs the experience. With Oculus Gallery it plays without these drops.

blanxdev avatar Jul 10 '19 10:07 blanxdev

Roger that. Your use case certainly gives weight exposing it.

Ste-RH avatar Jul 10 '19 10:07 Ste-RH

Let me know if you need somebody to test it. Also I can provide you a video file that produces the frame drops on our side.

blanxdev avatar Jul 10 '19 11:07 blanxdev

Just found out that this also exists for GoogleVR https://docs.unity3d.com/Manual/VRDevices-GoogleVRVideoAsyncReprojection.html

blanxdev avatar Jul 10 '19 18:07 blanxdev

About to finally give this a whirl now that this video player project is due. Been struggling with the Native video player used in the oculus SDK because it doesn’t have any calls or hooks to check to see if the video is playing for example. This makes it impossible to sync our external quad binaural audio. Any update on whether this feature is coming?

lightsailvr avatar Aug 13 '19 04:08 lightsailvr

I am looking forward to this as well. This would (could) be a great feature!

Drugges avatar Aug 30 '19 13:08 Drugges

I was able to successfully render a texture from AVPro to an OVR overlay layer. It is rendering a stereo 4k 360 video using Oculus Integration 1.44 and AVPro 1.10.1. I took some demo code from Oculus's Stereo180Video.unity sample scene to properly set up the Overlay layer.

I feel like the video is much sharper on the OVR overlay layer. However, I am noticing some strange color artifacts. Playback on the OVR Overlay layer is much brighter. In addition there seems to be some compression happening on the colors. I am not a compression expert but there seems to be less colors rendering.

I've only spent a couple hours playing with it so there might be something I am missing or set up incorrectly. I am going to continue working with it to try to get it rendering properly.

But being able to assign it to an external texture in theory would produce even better results. I would certainly use it.

Edit: The color is fixed by switching color space to gamma. It is properly rending in stereo and the video looks very sharp and clean. There is some unexpected behavior though. With the OVR Metrics tool running, the GPU level is at 5 and usage is at about 60% which is quite high. The app also can't keep 60fps, it runs around 45 fps, although I could run it at 60 fps before switching to the OVR overlay. In addition, there is some very real artifacting that makes it currently unusable. It seems like there is some judder especially when the frame rate is low. There is what to me looks like small brief moments of small bits of the screen that distorts and glitches. These glitches are a few ms long so I can barely see them but they are there. I am also using another OVR Overlay layer for buttons as well. Also the app takes about 15 seconds to start up which is extremely long. Ill report back with any updates.

robertncoomber avatar Jan 17 '20 22:01 robertncoomber

The overlay layer is not designed to render 360 content. 180 content works however, 360 content produces a thin black line on the back side of the video and there is no way to get rid of it.

robertncoomber avatar Jan 31 '20 07:01 robertncoomber

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Aug 26 '20 17:08 stale[bot]

This issue has been automatically closed because it has not had recent activity. If you wish to continue this issue, then please create a new issue as we do not monitor closed issues.

stale[bot] avatar Sep 02 '20 18:09 stale[bot]

we need to follow this one: https://developer.oculus.com/documentation/unity/unity-sf-stereo180video/

whatisor avatar Oct 16 '20 07:10 whatisor

With the upcoming AVPro 2.0 and the Ultra option - has this feature been added? The difference in quality is astounding when pushing to the OVR Overlay instead of rendering on a sphere. If so, it would be an easy choice to pay to upgrade to 2.0, but I can't find it mentioned in any of the release notes.

lightsailvr avatar Dec 18 '20 18:12 lightsailvr

This is still on the roadmap, but not as yet included in version 2

Ste-RH avatar Jan 07 '21 20:01 Ste-RH

I was able to successfully render a texture from AVPro to an OVR overlay layer. It is rendering a stereo 4k 360 video using Oculus Integration 1.44 and AVPro 1.10.1. I took some demo code from Oculus's Stereo180Video.unity sample scene to properly set up the Overlay layer.

I feel like the video is much sharper on the OVR overlay layer. However, I am noticing some strange color artifacts. Playback on the OVR Overlay layer is much brighter. In addition there seems to be some compression happening on the colors. I am not a compression expert but there seems to be less colors rendering.

I've only spent a couple hours playing with it so there might be something I am missing or set up incorrectly. I am going to continue working with it to try to get it rendering properly.

But being able to assign it to an external texture in theory would produce even better results. I would certainly use it.

Edit: The color is fixed by switching color space to gamma. It is properly rending in stereo and the video looks very sharp and clean. There is some unexpected behavior though. With the OVR Metrics tool running, the GPU level is at 5 and usage is at about 60% which is quite high. The app also can't keep 60fps, it runs around 45 fps, although I could run it at 60 fps before switching to the OVR overlay. In addition, there is some very real artifacting that makes it currently unusable. It seems like there is some judder especially when the frame rate is low. There is what to me looks like small brief moments of small bits of the screen that distorts and glitches. These glitches are a few ms long so I can barely see them but they are there. I am also using another OVR Overlay layer for buttons as well. Also the app takes about 15 seconds to start up which is extremely long. Ill report back with any updates.

Hi there, could you go into more detail as to how you did this? My app is currently rendering 360 video using a sphere and the AVPro Media Player, but I'm trying to render this video to an OVR Overlay. I added an OVR Overlay component to the sphere, matched its settings with that of the half sphere in the demo scene you mentioned, made a copy of Oculus's MoviePlayerSample script and am building off of that, but so far all I've gotten is a light blue sphere covering up the video. The video is still being rendered to the sphere though. I used andriworld's line of code...

ovrOverlay.textures[0] = mediaPlayer.TextureProducer.GetTexture();

...in order to assign the video texture to the overlay. What else did you have to do to get this to work? Thanks!

evan-spiegel avatar Jul 13 '21 22:07 evan-spiegel

Hi @lightsailvr, I got this working by taking the texture from AVPro (as soon as it's not null) and assigning it to OVR Overlay: ovrOverlay.textures[0] = mediaPlayer.TextureProducer.GetTexture();

It works great! What would be even better is if we could assign the pointer to the native android texture, but AVPro doesn't seem to expose it 'ovrOverlay.externalSurfaceObject = ???'

Hi there, I know this was a while ago but can you maybe give some more details as to how you got this working? I found the place in the code for Oculus's MoviePlayerSample script to put your line of code, and that seems to be working in terms of sending/rendering the video texture from AVPro to the OVR overlay layer (the big sphere that gets spawned when I hit Preview In Editor), but I can't seem to be able to see that sphere in play mode. I can see the sphere I already had, but not the bigger one. Any help you can give is much appreciated, thanks!

evan-spiegel avatar Jul 15 '21 19:07 evan-spiegel

@evan-spiegel Here is the code I am using to copy the texture from the AVPro video player onto the OVR Overlay. Hope this helps.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using RenderHeads.Media.AVProVideo;

public class AVProOVR : MonoBehaviour
{
    [SerializeField]
    OVROverlay overlay;
    [SerializeField]
    MediaPlayer mediaPlayer;
    private Renderer mediaRenderer = null;

    private void Awake()
    {
        mediaRenderer = GetComponent<Renderer>();

        Rect destRect = new Rect(0, 0, 1, 1);
        overlay.currentOverlayShape = OVROverlay.OverlayShape.Equirect;

        Rect sourceLeft = new Rect(0.0f, 0.0f, 1.0f, 0.5f);
        Rect sourceRight = new Rect(0.0f, 0.5f, 1.0f, 0.5f);
        overlay.SetSrcDestRects(sourceLeft, sourceRight, destRect, destRect);

        overlay.enabled = false;

        overlay.enabled = (overlay.currentOverlayShape != OVROverlay.OverlayShape.Equirect || Application.platform == RuntimePlatform.Android);
        
        #if UNITY_EDITOR
        overlay.currentOverlayShape = OVROverlay.OverlayShape.Quad;
        overlay.enabled = true;
        #endif
    }

    private void Update()
    {
        var displayTexture = mediaPlayer.TextureProducer.GetTexture() != null ? mediaPlayer.TextureProducer.GetTexture() : 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;

                print("DisplayTexture Render Texture width: " + displayTexture.width + " height: " + displayTexture.height); 
                
                overlay.textures[0] = displayTexture;

                mediaRenderer.material.mainTexture = displayTexture;
                mediaRenderer.material.SetVector("_SrcRectLeft", overlay.srcRectLeft.ToVector());
                mediaRenderer.material.SetVector("_SrcRectRight", overlay.srcRectRight.ToVector());

                overlay.enabled = true;
            }
        }
        else
        {
            mediaRenderer.material.mainTexture = displayTexture;
            mediaRenderer.material.SetVector("_SrcRectLeft", overlay.srcRectLeft.ToVector());
            mediaRenderer.material.SetVector("_SrcRectRight", overlay.srcRectRight.ToVector());
        }
    }
}

robertncoomber avatar Jul 21 '21 18:07 robertncoomber

@robertncoomber Thanks so much for your response, I'll try that!

evan-spiegel avatar Jul 23 '21 19:07 evan-spiegel

Is there a plan to support OVR Overlay natively? I tried using texture from the player and set it on the Overlay, the texture looks much sharper, but it suffers from the Gamma problem.... I also tried to fix it with a shader that does pow(color, 2.2), it looks ok but in the darker area color becomes pixelated. Please support the OVR Overlay natively!!

LYLeon avatar Sep 06 '21 15:09 LYLeon

@RenderHeadsSte i bought AVPro because you claim that AVPro can play 8K 360 Video e.g.: on Oculus Quest 2 (it work's) but without a nativ support for the OVR Overlay (or a different Solution that creates more sharpness) the visual quality is below average / e.g. below Oculus TV. AVPro is not made for a Pro / HQ use case - can you change that?

OliverRudoll avatar Nov 17 '21 07:11 OliverRudoll

@OliverRudoll AVPro does work well with OVR Overlay. It just doesn't work right out of the box. It's been a while since I've looked at the code but you will need to pass the texture produced from AVPro and pass that along to the OVR Overlay. You can either do this through code or through a render texture.

robertncoomber avatar Nov 18 '21 07:11 robertncoomber

This feels like something we need to test and add to our documentation... or perhaps create a helper component for to improve integration..

AndrewRH avatar Nov 18 '21 18:11 AndrewRH

@robertncoomber do you remember whether you did this using the OES texture? Any information will help us to make this a more solid feature.

AndrewRH avatar Nov 18 '21 18:11 AndrewRH

@robertncoomber thanks for your reply - can you define "does work well" and on what device? i really need this to work properly with mono 360 - 7200x3600 CBR 100mbps on an Android based Oculus Quest 2 (Mobile not over Link) - i'm testing on a Quest 2 using OES and Exoplayer. @AndrewRH a proper working example scene / code would be great. Unfortunately i don't have time for a research project.

OliverRudoll avatar Nov 18 '21 18:11 OliverRudoll